[SCM] gdal branch, master, updated. upstream/1.8.1-93-g6735e3e

Francesco Paolo Lovergine frankie at debian.org
Wed Feb 22 23:37:31 UTC 2012


The following commit has been merged in the master branch:
commit 4ff4e02c2318a9da605e8ffee9f5e3b5e8012e72
Author: Francesco Paolo Lovergine <frankie at debian.org>
Date:   Mon Feb 20 11:05:49 2012 +0100

    Moved to upstream version 1.9.0

diff --git a/COMMITERS b/COMMITERS
index dd739d7..8afc31b 100644
--- a/COMMITERS
+++ b/COMMITERS
@@ -141,11 +141,20 @@ harshgovind   Harsh Govind                 kmlsuperoverlay, sde
 aboudreault   Alan Boudreault
               aboudreault at mapgears.com  mitab, DebianGIS Packaging
               
-rburhum       Ragi Yaser Burhum            OGR: ArcObjects
+rburhum       Ragi Yaser Burhum            OGR: ArcObjects, filegdb
 
 kirk          Kirk McKelvey                mrsid, raster
               kmckelvey at lizardtech.com
 
+antonio       Antonio Valentino            SAR formats
+              antonio.valentino at tiscali.it
+
+pramsey       Paul Ramsey                  OGR: FGDB, PostGIS
+              pramsey at cleverelephant.ca
+
+etourigny     Etienne Tourigny             netcdf, hdf
+              etourigny.dev at gmail dot com
+              (old osgeo id etiennesky)
 
 ===============
 Past developers
diff --git a/Doxyfile b/Doxyfile
index d29c44c..84e3bb3 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -950,6 +950,7 @@ PREDEFINED             = HAVE_DLFCN_H \
                          CPL_C_END \
                          __cplusplus \
                          DOXYGEN_SKIP \
+                         HAVE_CURL \
 			 OGR_ENABLED
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
diff --git a/GDALmake.opt.in b/GDALmake.opt.in
index 322c0a7..52b8a04 100644
--- a/GDALmake.opt.in
+++ b/GDALmake.opt.in
@@ -5,11 +5,7 @@ top_builddir	=	$(GDAL_ROOT)
 # the library can be built by the native build or with the help of libtool
 #
 
-# Solaris users: the LIBTOOL line is expanded to $(SHELL) $(top_builddir)/libtool
-# but the libtool script uses bashism, so you may need to uncomment the following
-# line :
-#SHELL=/usr/bin/bash
-
+SHELL    =   @SHELL@
 HAVE_LIBTOOL	=	@HAVE_LIBTOOL@
 LIBTOOL	=	@LIBTOOL@
 ifeq ($(HAVE_LIBTOOL),yes)
@@ -39,7 +35,7 @@ INSTALL_DIR	= 	$(GDAL_ROOT)/install-sh -d
 LIBS	=	$(SDE_LIB) @LIBS@ $(KAK_LIBS) $(DWG_LIBS) $(CURL_LIB) \
 		$(MRSID_LIBS) $(MRSID_LIDAR_LIBS) $(INGRES_LIB) \
 		$(PCIDSK_LIB) $(RASDAMAN_LIB) $(CHARLS_LIB) \
-		$(OPENCL_LIB)
+		$(OPENCL_LIB) $(JVM_LIB) $(LIBICONV) $(FGDB_LIB)
 
 PYTHON_INCLUDES = @PYTHON_INCLUDES@
 PYTHON_LIBS = @PYTHON_LIBS@
@@ -93,9 +89,9 @@ GDAL_INCLUDE	=	-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore \
 
 # libtool targets and help variables
 LIBGDAL	:=		libgdal.la
-LIBGDAL_CURRENT	:=	16
-LIBGDAL_REVISION	:=	1
-LIBGDAL_AGE	:=	15
+LIBGDAL_CURRENT	:=	17
+LIBGDAL_REVISION	:=	0
+LIBGDAL_AGE	:=	16
 
 # native build targets and variables
 GDAL_VER	=	@GDAL_VER@
@@ -138,6 +134,7 @@ LIBS	   +=	$(MYSQL_LIB)
 #
 # HDF4 Support.
 #
+HAVE_HDF4     = @HAVE_HDF4@
 HDF4_INCLUDE  = @HDF4_INCLUDE@ -I$(GDAL_ROOT)/ogr
 
 #
@@ -147,6 +144,13 @@ HAVE_HDF5     = @HAVE_HDF5@
 HDF5_INCLUDE  = @HDF5_INCLUDE@ 
 
 #
+# NetCDF Support.
+#
+NETCDF_ROOT = @NETCDF_ROOT@
+NETCDF_HAS_NC4 = @NETCDF_HAS_NC4@
+NETCDF_HAS_HDF4 = @NETCDF_HAS_HDF4@
+
+#
 # DODS Include file location
 #
 DODS_INC = @DODS_INC@
@@ -162,6 +166,8 @@ endif
 SQLITE_INC = @SQLITE_INC@
 HAVE_SQLITE = @HAVE_SQLITE@
 HAVE_SPATIALITE = @HAVE_SPATIALITE@
+SPATIALITE_INC = @SPATIALITE_INC@
+SPATIALITE_AMALGAMATION = @SPATIALITE_AMALGAMATION@
 
 #
 # JPEG2000 via Kakadu Support.
@@ -248,6 +254,13 @@ SDE_LIB	= @SDE_LIB@
 SDE_INC = @SDE_INC@
 
 # 
+# FileGDB
+#
+HAVE_FGDB = @FGDB_ENABLED@
+FGDB_LIB = @FGDB_LIB@
+FGDB_INC = @FGDB_INC@
+
+# 
 # ArcObjects
 #
 HAVE_ARCOBJECTS = @ARCOBJECTS_ENABLED@
@@ -280,6 +293,11 @@ PCIDSK_SETTING  =       @PCIDSK_SETTING@
 PCIDSK_LIB	=	@PCIDSK_LIB@
 PCIDSK_INCLUDE	=	@PCIDSK_INCLUDE@
 
+#
+# Iconv
+#
+LIBICONV	=	@LIBICONV@
+
 # 
 # DWGdirect Library
 #
@@ -337,8 +355,10 @@ JPEG_SETTING	=	@JPEG_SETTING@
 JPEG12_ENABLED =	@JPEG12_ENABLED@
 TIFF_SETTING	=	@TIFF_SETTING@
 TIFF_OPTS	=	@TIFF_OPTS@
+RENAME_INTERNAL_LIBTIFF_SYMBOLS = @RENAME_INTERNAL_LIBTIFF_SYMBOLS@
 GEOTIFF_SETTING	=	@GEOTIFF_SETTING@
 GEOTIFF_INCLUDE =	@GEOTIFF_INCLUDE@
+RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS = @RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS@
 GIF_SETTING	=	@GIF_SETTING@
 FITS_SETTING    =       @FITS_SETTING@
 OGDI_SETTING	=	@HAVE_OGDI@
@@ -346,6 +366,7 @@ ODBC_SETTING    =       @ODBC_SETTING@
 # PGeo driver is built-in when ODBC is available
 PGEO_SETTING    =       @ODBC_SETTING@
 MSSQLSPATIAL_SETTING    =       @ODBC_SETTING@
+GEOMEDIA_SETTING    =       @ODBC_SETTING@
 NETCDF_SETTING  =       @NETCDF_SETTING@
 LIBZ_SETTING	=	@LIBZ_SETTING@
 LIBLZMA_SETTING	=	@LIBLZMA_SETTING@
@@ -367,6 +388,13 @@ POPPLER_BASE_STREAM_HAS_TWO_ARGS = @POPPLER_BASE_STREAM_HAS_TWO_ARGS@
 POPPLER_INC = @POPPLER_INC@
 
 #
+# Podofo stuff
+#
+
+HAVE_PODOFO = @HAVE_PODOFO@
+PODOFO_INC = @PODOFO_INC@
+
+#
 # CharLs stuff
 # Uncomment and adapt paths to enable JPEGLS driver
 #
@@ -393,6 +421,23 @@ GDAL_LIBS	=	$(GDAL_LIB)
 endif
 
 #
+# Java stuff
+#
+JAVA_INC  =   @JAVA_INC@
+JVM_LIB  =   @JVM_LIB@
+
+MDB_ENABLED =   @MDB_ENABLED@
+
+HAVE_ARMADILLO = @HAVE_ARMADILLO@
+
+#
+# freexl stuff
+#
+
+HAVE_FREEXL = @HAVE_FREEXL@
+FREEXL_INCLUDE = @FREEXL_INCLUDE@
+
+#
 #	Note these codes have to exactly match the format directory names, 
 #	and their uppercase form should be the format portion of the
 #	format registration entry point.  eg. gdb -> GDALRegister_GDB().
@@ -402,9 +447,10 @@ GDAL_FORMATS = 	gxf gtiff hfa aigrid aaigrid ceos ceos2 iso8211 xpm \
 		nitf bmp pcidsk airsar rs2 ilwis rmf leveller sgi srtmhgt \
 		idrisi gsg ingr ers jaxapalsar dimap gff cosar pds adrg \
 		coasp tsx terragen blx msgn til r northwood saga xyz hf2 \
-		kmlsuperoverlay ozi \
+		kmlsuperoverlay ozi ctg e00grid zmap ngsgeoid \
 		@OPT_GDAL_FORMATS@
 
+
 ifneq ($(LIBZ_SETTING),no)
 GDAL_FORMATS := $(GDAL_FORMATS) rik
 endif
diff --git a/GNUmakefile b/GNUmakefile
index 49a1087..4ba2301 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -74,7 +74,7 @@ else
 swig-target:    swig-modules;
 endif
 
-swig-modules:
+swig-modules:	lib-target
 	(cd swig; $(MAKE) build)
 
 clean:	lclean
@@ -127,6 +127,7 @@ docs:
 	cp doc/grid/*.png html
 	cp frmts/*.html frmts/*/frmt_*.html html
 	cp frmts/wms/frmt_wms_*.xml html
+	cp frmts/wms/frmt_twms_*.xml html
 
 man:
 # Generate man pages
diff --git a/HOWTO-RELEASE b/HOWTO-RELEASE
index 3b439a4..98bf2f2 100644
--- a/HOWTO-RELEASE
+++ b/HOWTO-RELEASE
@@ -37,7 +37,9 @@ Process :
 
 3.1) Update ./swig/python/setup.py version information. 
 
-3.2) Update ./swig/include/perl/gdal_perl.i $VERSION string to current version.
+3.2) Update ./swig/include/perl/gdal_perl.i $VERSION and $GDAL_VERSION
+strings to current version. Kick Perl module maintainer to make a CPAN
+release.
 
 3.3) For major releases update the VERSION macro in nmake.opt (for 1.6, 1.7etc)
 
@@ -82,8 +84,8 @@ Process :
 
  ie. On www.gdal.org:
  % cd /osgeo/gdal
- % ./gdalhtmlupdate.sh
- % zip -r /osgeo/download/gdal/gdal150doc.zip gdal-web/*.* gdal-web/ogr
+ % ./gdal-web-refresh.sh
+ % zip -r gdal180doc.zip gdal-web/*.* gdal-web/ogr gdal-web/java 
 
 11) Create a snapshot of autotest suite:
 
diff --git a/NEWS b/NEWS
index a68ca17..a87b30a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,92 +1,945 @@
-= GDAL/OGR 1.8.1 release notes = 
-
-The 1.8.1 release is a routine bug fix release on the stable GDAL/OGR 1.8
-branch.
-
-== General ==
- * Fix for windows build of cpl_vsil_gzip.cpp (#3908)
- * Fix OGRDataSource.Open() signature so utf8 translation works in C# (#3766).
- * Fix cpl_config.h.vc so it also works with mingw compiler on windows (#3960)
- * Fix GEOS configuration checking affecting GEOS 3.0.4 (#3990)
- * Support optional nmake.local file for local MSVC config (r22529).
-
-== GDAL / Raster ==
-
- * GDALReplicateWord(): fix error with missing one pixel (#4090) 
- * Fix issue with duplicating metadata (#3961)
- * VRT: Fix issues with complex data types (#3977)
- * VRT: Fix issue with nodata values and uninitialized buffers (#4045)
- * VRT/.aux.xml: Fix performance with large color tables (#3961)
- * VRT: Fix for VRTs smaller than the default block size (#4137)
- * IDRISI/RST: Fix seg fault with missing fields in .ref and .rdc (#4100)
- * IDRISI: Fix problem with spherical inverse flattening (#3757)
- * GTIFF: Fix support for external overviews with COPY_SRC_OVERVIEWS (#3938)
- * GTIFF: Correct handling of linear geokeys in feet (#3091)
- * GTIFF: Fix edge anomoly issues with jpeg tiles (#4096)
- * GTIFF: Don't skip driver even if library versions differ (#4101)
- * SAGA: Fix reading/writing .sdat files larger than 2GB. (#4104)
- * PCIDSK: Various fixes particularly for linked files (r21513)
- * PCIDSK: Fixes for georeferencing parsing (#3913)
- * ECW: Added/fixed french ECW coordinate systems (#3868)
- * ECW: Force sign of y pixel size when needed (#393)
- * ECW: Support EPSG:n style coordinate systems (#3955)
- * ECW: Fixes related to geotransform overrides (#4131)
- * ERS: Handle .ers files in case insensitive way (#3974)
- * PNG: Add support for libpng >= 1.5.0 (#3914)
- * JP2KAK: Support reading and writing resolution info (#3847)
- * MRSID: Fix for configuring and building on MacOS X (#3910)
- * HFA (.img): Fix filename computations and updating for renaming files (#3897)
- * HFA (.img): Support reading 2bit compressed .img files (#3956)
- * HFA (.img): Fix for rewriting projection/datum parameters (#3969)
- * NITF: Correct hemisphere setting for ICORDS=U with world file (#3931)
- * NITF: Added NITF_DISABLE_RPF_LOCATION_TABLE_SANITY_TESTS option (#3930)
- * NITF: Make attribute section size hack safer (#4020)
- * EHDR: Improved floating point file detection (#3933)
- * ASRP: Approximated support for Azimuthal Equidistant in poles (#3946)
- * HDF5/BAG: fix handle and memory leaks (#3953)
- * HDF5: Avoid returning NULL from GetProjectionRef() (#4076)
- * HDF5: Improve preservation of floating point precision in metadata (r22531).
- * JPIPKAK: Fix problems with overviews, windowing and errors (#3967)
- * USGSDEM: Fixing locale dependent parsing of numbers (#3886, #3979)
- * RS2: Support subdataset oriented metadata and overviews (#4006)
- * AIGRID: Support uncompressed integer images (ArcGIS 10) (#4035)
- * gdalwarp: Include DstDensity mask in memory calculations (#4042)
- * GeoRaster: Full backport for fixes and features (#4039,#3266,#4071,#4072,#4132)
- * ENVISAT: Fix gcp computations for stripline products (#3160,#3709)
- * ENVISAT: Fix gcp computations for MERIS products (#4086)
- * SAR_CEOS: Fix potential crash with odd filenames. (#4065)
- * SAR_CEOS: Skip datasets with wrong record length. (#4146)
- * ENVI: Support ESRI style coordinate system strings (#3312)
- * JAXAPALSAR: Fix datatype of 1.5 level product (#4136)
- * gdalfillnodata: working file is created as bigtiff if possibly needed (#4088)
-
-== OGR / Vector ==
-
- * LIBKML: Fix build issue against static libkml (#3909)
- * LIBKML: Improve checking to see if files are actually kml (#4003)
- * GML: Fix crash with invalid geometries when axis order is lat/long (#3935) 
- * GML: Support curves in directEdges (#3934)
- * GML: Do not force 3D linestrings for directed edges (#3936)
- * GPX/GeoRSS: Fix expat library order issue on unix (#3948)
- * PG/PGDUMP: Fix handling of NaN in zero width fields (#2112)
- * PGDUMP: Add CREATE_SCHEMA and DROP_TABLE layer options (#4033)
- * PGDUMP: Support wkbNone geometry better, and other subtle bugs (#4040)
- * OGR SQL: Allow double quoting column name in SELECT DISTINCT (#3966)
- * OGR SQL: Fix crashes with some uses of SUBSTR and CAST (#4055)
- * OGR SQL: Fix crash on IS NULL test on floating point fields (#4091)
- * OGR SQL: Fix error with SQL joins (#4112)
- * MSSQL: Fix for IDENTITY INSERT problem (#3992)
- * MSSQL: Fix for schema handling (#3951)
- * MSSQL: Fix for geometry handling with ExecuteSQL() (#4149)
- * OCI: Fix writing of tables with no general attributes (#4063)
- * GeoJSON: Fix assertion on ESRI json (#4056, #4057)
- * GeoJSON: Improve numeric field determination (#4082)
- * SHAPE: Fix decoding of triangle fans in multipatch files (#4081)
- * SHAPE: Fix multipolygon detection issue due to isClockwise failure (#4122)
- * MITAB: Fix handling of filenames with two dots in them. (#4123)
- * MITAB: Fix problems with null datetime values (#4150)
- * ogr2ogr: Improve -overwrite/-append handling (#4012)
- * ogr2ogr: Ensure -where fields are address in SetIgnoredFields (#4015)
+= GDAL/OGR 1.9.0 Release Notes =
+
+== In a nutshell... ==
+
+ * New GDAL drivers: ACE2, CTG, E00GRID, ECRGTOC, GRASSASCIIGrid, GTA, NGSGEOID, SNODAS, WebP, ZMap
+ * New OGR drivers:  ARCGEN, CouchDB, DWG, EDIGEO, FileGDB, Geomedia, GFT, IDRISI, MDB, SEGUKOOA, SEGY, SVG, XLS
+ * Significantly improved drivers: NetCDF
+ * Encoding support for shapefile/dbf (#882)
+ * RFC 35: Delete, reorder and alter field definitions of OGR layers
+ * RFC 37: Add mechanism to provide user data to CPLErrorHandler (#4295)
+ * gdalsrsinfo: new supported utility to report SRS in various form (supercedes testepsg)
+
+== New installed files ==
+
+ * data/nitf_spec.xml and data/nitf_spec.xsd
+
+== Backward compatibility issues ==
+
+ * GTiff: ensure false easting/northing in geotiff geokeys are treated as being in geosys units (#3901)
+ * GRIB: Fix grid vs cell-center convention (#2637)
+ * OGR SQL: with DISTINCT, consider null values are such, and not as empty string (#4353)
+
+== GDAL/OGR 1.9.0 - General Changes ==
+
+Build(Unix):
+ * Add --with-rename-internal-libtiff-symbols and --with-rename-internal-libgeotiff-symbols
+   flags in order to safely link against an external libtiff (3.X) and a GDAL built with
+   internal libtiff (4.0) support (#4144)
+ * Add --with-mdb --with-java,--with-jvm-lib, --with-jvm-lib-add-rpath options
+ * Add --with-podofo, --with-podofo-lib, --with-podofo-extra-lib-for-test options
+ * Add --with-armadillo
+ * Update to libtool 2.4
+ * Fix linking against static libkml (#3909)
+ * Fix Xerces detection by using LIBS instead of LDFLAGS (#4195)
+ * Check for .dylib too, when configuring MrSID SDK paths (#3910)
+ * Fix wrong include order in GNUmakefile of GPX and GeoRSS drivers (#3948)
+ * cpl_strtod.cpp: Enable android support (#3952).
+ * ensure swig-modules depends on lib-target so make -j works with swig bindings
+ * Change how we check for GEOS >= 3.1  (#3990)
+ * Define SDE64 on at least x86_64 platforms (#4051)
+ * Make ./configure --with-rasdaman=yes work (#4349)
+ * MinGW cross compilation: clear GEOS_CFLAGS and XERCES_CFLAGS
+   if headers found in /usr/include, do not use Unix 64 bit IO
+ * MinGW build: define __MSVCRT_VERSION__ to 0x0601 if not already set
+
+Build(Windows):
+ * Move MSVC warning disabling to nmake.opt, add SOFTWARNFLAGS for external code
+ * Use nmake.local (#3959)
+ * cpl_config.h.vc: fix up so it also works with mingw (#3960)
+ * Build testepsg utility by default when OGR is enabled (#2554)
+
+== GDAL 1.9.0 - Overview of Changes ==
+
+Port:
+ * /vsigzip/ : Avoid reading beyond file size in case of uncompressed/stored files in zip (#3908)
+ * /vsicurl/ : Better support for escaped and UTF-8 characters
+ * /vsicurl/ : speed-up with a per-thread Curl connection cache
+ * /vsicurl/ : read https directory listing
+ * /vsicurl/ : look for GDAL_DISABLE_READDIR_ON_OPEN configuration option in
+   Open() and Stat() to avoid trying fetching the directory file list
+ * /vsicurl/ : fix performance problem when parsing large directory listings (#4164)
+ * /vsicurl/ : recognize listing of Apache 1.3
+ * /vsicurl/ : fix ReadDir() after reading a file on the same server
+ * /vsicurl/ : fetch more info (size, date) when listing FTP or HTTP directories and save it in cache; use those info for ReadDir() and Stat()
+ * /vsicurl/: accept 225 as a valid response code for FTP downloads (#4365)
+ * /vsicurl/ : add CPL_VSIL_CURL_ALLOWED_EXTENSIONS configuration option that can be used to restrict files whose existence is going to be tested.
+ * /vsitar/ : Recognize additionnal .tar files with slightly header differences
+ * /vsizip/ : wrap the returned file handle in a BufferedReader
+ * /vsizip/ : fix 1900 year offset for year returned by VSIStatL()
+ * /vsizip and /vsitar: remove leading './' pattern at the beginning of filenames contained in the archive
+ * /vsistdout_redirect/ : New virtual file system driver that has the same
+   behaviour as /vsistdout/ (write-only FS) except it can redirect the output to
+   any VSIVirtualFile instead of only stdout (useful for debugging purposes)
+ * Implement VSI*L read caching - useful for crappy io environments like Amazon
+ * VSI*L: Add Truncate() virtual method and implement it for unix, win32 and /vsimem file systems
+ * VSI*L: Add ReadMultiRange() virtual method to read several ranges of data in single call; add an optimized implementation for /vsicurl/
+ * VSIFEofL(): make it more POSIX compliant.
+ * Fine tune CPLCorrespondingPaths() for different basenames when paths involved.
+ * VSIWin32FilesystemHandler::Open() : implement append mode.  Needed by ISIS2 driver with attached label (#3944)
+ * CPLString: add case insensitive find operator (ifind)
+ * RFC23: Add the iconv() based implementation of the CPLRecode() function (#3950)
+ * Preliminary support for wchar_t with iconv recode (#4135)
+ * Avoid calling setlocale if we are already in the C locale, or GDAL_DISABLE_CPLLOCALEC is TRUE (#3979)
+ * CPLMiniXML: emit warnings when encountering non-conformant XML that is however accepted by the parser
+ * add CPLBase64Encode(); move cpl_base64.h contents to cpl_string.h
+ * Use CRITICAL_SECTION instead of Mutex on win32
+ * CPLHTTPFetch(): Add a CLOSE_PERSISTENT option to close the persistant sessions
+ * CPLHTTPFetch(): Add support for "NEGOTIATE" http auth mechanism
+ * CPLHTTPFetch(): Add a CUSTOMREQUEST option
+ * VSIBufferedReaderHandle: fix Eof()
+ * Add CPLStringList class
+ * Add CPLEmergencyError() - to call when services are too screwed up for normal error services to work (#4175)
+ * CPLEscapeString(,,CPLES_URL) : don't escape dot character; fix escaping of characters whose code >= 128
+
+Core:
+ * Provide for ABI specific plugin subdirectories on all platforms
+ * Force cleanup of datasets when destroying the dataset manager
+ * Add a GDALDataset::CloseDependantDatasets() that can be used by GDALDriverManager::~GDALDriverManager() to safely close remaining opened datasets (#3954)
+ * Add GDALRasterBand::ReportError() and GDALDataset::ReportError() to prepend dataset name (and band) before error message (#4242)
+ * Fix performance problem when serializing huge color tables, metadata, CategoryNames and GCPs to VRT/PAM (#3961)
+ * Be careful about Nan complex values getting histogram, avoid locale issues with statistics metadata
+ * GDALRasterBand::IRasterIO() default implementation : don't try to use full-res band if I/O failed on the appropriate overview band (for WMS errors)
+ * RasterIO: Return earlier when a write error occured while flushing dirty block
+ * GDAL_DISABLE_READDIR_ON_OPEN can be set to EMPTY_DIR to avoid reading the dir, but it set an empty dir to avoid looking for auxiliary files
+ * Use sibling file list to look for .aux.xml, .aux, .ovr, world files, tab files
+ * Add GDALFindAssociatedFile() (#4008)
+ * PAM: Make sure GCPs loaded from a .aux.xml override any existing ones from other sources, like an .aux file
+ * PAM: Add cloning of CategoryNames
+ * PAM : PamFindMatchingHistogram() - fix floating-point comparison
+ * GMLJP2: Use http://www.opengis.net/gml as the schemaLocation
+ * GMLJP2: Support for capturing and writing page resolution in a TIFF compatible way (#3847)
+ * GDALJP2Box::SetType() : remove byte-swapping so that SetType()/GetType() correctly round-trips. Do appropriate changes in JP2KAK and ECW drivers. (#4239)
+ * GDALReplicateWord(): fix off-by-one error initialization (#4090)
+
+Algorithms:
+ * polygonize: Added GDALFPolygonize() as an alternative version of GDALPolygonize() using 32b float buffers instead of int32 ones. (#4005)
+ * gdalwarp: take into account memory needed by DstDensity float mask (#4042)
+ * rasterfill: create working file as a bigtiff if at all needed (#4088)
+ * gdalrasterize: use double instead of float to avoid precision issues (#4292)
+
+Utilities:
+ * gdalsrsinfo: new supported utility to report SRS in various form (supercedes testepsg)
+ * gdalinfo: add '-nofl' option to only display the first file of the file list
+ * gdalinfo: add '-sd num' option to report subdataset with the specified number.
+ * gdalinfo: add '-proj4' option to gdalinfo, to report a PROJ.4 string for the CRS
+ * gdal_translate: propagate INTERLEAVE metadata to intermediate VRT dataset
+ * gdal_translate: force quiet mode when outputing to /vsistdout/
+ * gdalwarp: Disable CENTER_LONG rewrapping for cutline (#3932)
+ * gdalwarp: add -refine_gcps option to discard outliers GCPs before warping (#4143)
+ * gdalwarp: add warning if user specifies several of -order, -tps, -rpc or -geoloc options
+ * gdalwarp: speed-up when using -tps with large number of GCPs
+ * gdalwarp: add support for optional use of libarmadillo to speed-up matrix inversion in -tps mode
+ * gdalwarp: detect situations where the user will override the source file
+ * gdallocationinfo: do not let one off-db pixel cause all the rest to be supressed (#4181)
+ * gdal_rasterize: fix half pixel shift when rasterizing points; make gdal_rasterize utility increase the computed raster extent by a half-pixel for point layers (#3774)
+ * gdal_rasterize: when source datasource has a single layer, use it implicitely if none of -l or -sql is specified
+ * nearblack: add -color option (#4085)
+ * nearblack: improve detection of collar
+ * nearblack: remove useless restrictions on number of bands for -setmask and -setalpha options (#4124)
+ * gcps2vec.py: Fix command line parsing; Add SRS definition to created vector layer; Use Point geometry when dumping pixel/line coordinates.
+ * gdal_merge.py: add support for -separate with multiband inputs (#4059)
+ * gdal_merge.py: add a -a_nodata option (#3981)
+ * gdal_proximity.py: -co option existed, but was unused...
+ * gdal_fillnodata.py: add -co option
+ * Add gdal_ls.py and gdal_cp.py as Python samples
+ * Add new sample utility, gdal_edit.py, to edit in place various information of an existing GDAL dataset (projection, geotransform, nodata, metadata) (#4220)
+ * gdalcopyproj.py: make it copy GCPs too
+ * Add warning if a target filename extension isn't consistant with the output driver
+ * Add --pause for convenient debugging, document it and --locale
+
+Multi-driver topics:
+ * Implement reading XMP metadata from GIF, JPEG, PNG, GTiff, PDF and the 5 JPEG2000 drivers. The XMP metadata is stored as raw XML content in the xml:XMP metadata domain (#4153)
+ * Mark BT, DIPEx, ERS, FAST, GenBIN, GSC, GSBG, GSAG, GS7BG, JDEM, JP2ECW, PNM, RMF, TIL, WCS and WMS drivers as compatible with VSI virtual files
+ * Port DOQ1, DOQ2, ELAS, Idrisi, L1B, NDF, NWT_GRD, NWT_GRC, USGSDEM to VSI virtual file API
+ * PAM-enable BT and BLX drivers
+ * Implement Identify() for AAIGrid, ACE2, DTED, NWT_GRD, NWT_GRC, WMS, WCS, JDEM and BSB drivers
+ * Make GIF, JPEG and PNG drivers return a non NULL dataset when outputing to /vsistdout/
+ * HFA and GTiff: add explicit error message when trying to add external overviews when there are already internal overviews (#4044)
+ * Initialize overview manager to support external overviews for AAIGRID, DIPX, ELAS, GXF, FIT, FITS, GMT, GRIB, GSAG, GSBG, GS7BG, ILWIS, L1B, LCP, Leveller, NWT_GRD, NWT_GRC, RIK, SDTS and SAGA
+
+AAIGrid:
+ * Make opening from /vsicurl/ work even when the server returns an empty file list
+
+ACE2 driver:
+ * New for GDAL/OGR 1.9.0
+ * Read ACE2 DEM
+
+AIG driver:
+ * Support uncompressed integer files, new in ArcGIS 10 it seems (#4035)
+ * Use color table from PAM if no native one (#4021)
+ * Fallback to PAM mechanism for RAT (#4021)
+
+BSB driver:
+ * Parse the GD keyword in BSB_KNP to recognize European 1950 datum (#4247)
+ 
+CEOS2 driver:
+ * avoid potential crash reading past end of string. (#4065)
+
+CTG driver:
+ * New for GDAL/OGR 1.9.0
+ * Read USGS LULC Composite Theme Grid files
+
+DIMAP driver:
+ * Add support for DIMAP2
+ * Check underlying raster for SRS. There are cases where HORIZONTAL_CS_CODE is empty and the underlying raster is georeferenced
+
+E00GRID driver:
+ * New for GDAL/OGR 1.9.0
+ * Read Arc/Info Export E00 GRID
+
+ECRGTOC driver:
+ * New for GDAL/OGR 1.9.0
+ * Read TOC.xml file of ECRG products
+
+ECW driver:
+ * Use a long refresh time for ecwp:// connections to ensure we get full resolution data, make configurable
+ * Re-enable writing non8bit data in jpeg2000
+ * Add implementation of an Async reader (4.x SDK)
+ * Improve to support all /vsi stuff (#2344)
+ * Ensure ECW_ENCODE_ values are applied for direct Create as well as CreateCopy
+ * force adfGeoTransform[5] sign to negative. (#393)
+ * Mark GDAL_DCAP_VIRTUALIO=YES when the driver is configured in read-only mode
+ * Ensure we fallback to native geotransform if no pam override
+ * Try to read projection info embedded in ECW file before reading the worldfile (#4046)
+ * Add support for updating geotransform and projection info of a ECW file (#4220)
+ * Fix ECW_CACHE_MAXMEM that was without effect and ECW_AUTOGEN_J2I that set an unrelated ECW parameter (#4308)
+ * Allow to open a ECW file with invalid EPSG code from SWIG bindings (#4187)
+
+EHdr driver:
+ * Improve floating point detection (#3933)
+ * Recognize MIN_VALUE and MAX_VALUE as found in ETOPO1 header
+ * Try opening the .sch file for GTOPO30 or SRTM30 source file
+ * Ignore bogus .stx file where min == nodata
+
+EIR driver:
+ * Add support for DATA_TYPE keyword
+
+ENVI driver:
+ * Add support for ESRI style coordinate system string (#3312)
+ * Try to guess interleave mode from file extension, if interleave keyword is missing
+ * Refuse to open unsupported types, but attempt to open everything else.
+
+ENVISAT driver:
+ * Correct dfGCPLine values for stripline products (#3160, #3709)
+ * Fix checking of tie points per column for MERIS GCPs (#4086)
+ * Report metadata from the ASAR ADS and GADS in the RECORDS metadata domain (#4105)
+ * Read MERIS metadata (#4105)
+ * Read data from ERS products in ENVISAT format (#4105)
+ * Improved MERIS Level 2 bands datection (#4141 and #4142)
+
+EPSILON driver:
+ * Now require libepsilon 0.9.1 to build (now dual LGPL/GPL) (#4084)
+
+ERS driver:
+ * Use case insensitive find so case does not matter (#3974)
+ * Handle case of 1 m pixel resolution when CellInfo is missing (#4067)
+ * Implement ERSRasterBand::SetNoDataValue() (#4207)
+ * Add support for DATUM, PROJ and UNITS creation option; report the values read from the .ers file in the ERS metadata domain (#4229)
+
+GeoRaster driver:
+ * Set nodata causes invalid XML metadata (#3893)
+ * Fix SetStatistics() failure (#4072)
+ * Fix defaut interleaving (#4071)
+ * modelCoordinateLocation=CENTER default (#3266)
+ * Cache block/level error in update (#4089)
+ * Fix sequence.nextval not supported (Oracle 10g) (#4132)
+ * change BLOCKING option to OPTIMALPADDING
+ * fix 'cannot specify columns on insert create option' (#4206)
+ * Fix ULTCoordinate Rows/Columns swapping (#3718)
+ * Fix loading of small images, FlushCache issue (#4363)
+
+GIF driver:
+ * Make CreateCopy() more friendly with outputing in /vsistdout/
+
+GRIB driver:
+ * Fix grid vs cell-center convention (#2637)
+ * use /vsi for all jpeg2000 files now
+ * Fix to allow GFS data to show up properly (#2550)
+ * Added a ConfigOption in GRIB driver to not normalize units to metric when reading the data
+ * Fixed grib1 & grib2 : pixel size precision introduces error for corner coordinates (#4287)
+
+GTA driver:
+ * New for GDAL/OGR 1.9.0
+ * Read/write support for Generic Tagged Arrays
+
+GTiff driver:
+ * Ensure false easting/northing in geotiff geokeys are treated as being in geosys units.  Add GTIFF_LINEAR_UNITS=BROKEN config option to try and read old broken files, and logic to cover for older libgeotiffs when reading (#3901)
+ * Add support for a special tag to keep track of properly written linear units (#3901)
+ * Implement deferred directory chain scanning to accelerate simple opens
+ * Make GTiff COPY_SRC_OVERVIEWS to deal with unusual source overview sizes (#3905)
+ * Fix bug when using -co COPY_SRC_OVERVIEWS=YES on a multiband source with external overviews (#3938)
+ * Add logic to fill out partial tiles on write in for jpeg images (#4096)
+ * Updated to libtiff 4.0.0 final
+ * Refresh with libgeotiff 1.4.0, to support for GeogTOWGS84GeoKey
+ * Add support for Geocentric SRS
+ * libtiff: Enable DEFER_STRILE_LOAD
+ * Turn warning 'ASCII value for tag xx into more silent CPLDebug message
+ * Overviews: Improve error reporting for >16bit images to JPEG compression
+ * Use CPLAtof() for geotiff and epsg .csv file handling (#3886, #3979)
+ * Lots of Imagine and ESRI PE string citation handling changes from 1.8-esri. Some citation related changes only compiled in if ESRI_SPECIFIC defined.
+ * Give PAM information precidence over metadata from GeoTIFF itself.   Avoid unnecessary (default) writes of scale/offset.  Treat (0,1,0,0,0,-1) as a default geotransform as well as (0,1,0,0,0,1).
+ * Migrate in some ESRI only logic for 1bit color tables, AdjustLinearUnits and default for 1bit data
+ * Add a GTIFF_IGNORE_READ_ERRORS configuration option (#3994)
+ * Lazy loading of RPC/RPB/IMD files (#3996)
+ * Add mutex protection in GTiffOneTimeInit() to avoid occasionnal segfaults
+ * Stop interpreting 4th band as alpha when not defined
+ * Also list nSubType == FILETYPE_PAGE as subdatasets
+ * CreateCopy(): copies category names from the source bands
+ * Add capability of writing TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE
+ * Don't prevent from loading GTiff driver even if libtiff version mismatch detected (#4101)
+ * Use GTIFF_ESRI_CITATION flag to disable writing special meaning ESRI citations
+ * Optimize GTiffRGBABand implementation (#3476)
+ * Add GTIFF_DIRECT_IO config. option that can be set to YES so that IRasterIO() reads directly bytes from the file using ReadMultiRange().
+ * Use VSI_TIFFOpen() in GTIFFBuildOverviews() to make it work on virtual file systems
+ * Treat _UNASSALPHA as alpha
+
+GRASSASCIIGrid driver:
+ * New for GDAL/OGR 1.9.0
+ * Read GRASS ASCII grids (similar to ArcInfo ASCII grids)
+
+GRIB driver:
+ * Check for memory allocation failures
+
+HDF4 driver:
+ * Use larger object name buffer
+ * Handle SWopen failures
+
+HDF5 driver:
+ * Fix HDF5/BAG handle/memory leaks (#3953)
+ * Better error checking
+ * Do not return NULL from getprojectionref() (#4076)
+ * Identify datasets whose header starts with some XML content (#4196)
+ * Fixed HDF5 variable length string attributes reading (#4228)
+
+HFA driver:
+ * Add support for writing RATs (#999)
+ * Add support for reading 2bit compressed .img files (#3956)
+ * Update EPRJ_ list based on input from Erdas, round trip Krovak and Mercator Variant A (#3958)
+ * Major push to move projections from 1.6-esri into trunk in HFA driver (#3958)
+ * Reinitialize RRDNamesList and ExternalRasterDMS (#3897)
+ * Ensure the whole entry is reinitialized when writing proparams and datum (#3969)
+ * Ensure PEString cleared if we aren't writing it (#3969)
+ * Get nodata from an overview if not present on main band.  Set geotransform[1] and [5] to 1.0 if pixelSize.width/height are 0.0.  Improve error checking if MakeData() fails.
+ * atof() changed to CPLAtofM() to avoid locale issues.
+ * Altered Edsc_BinFunction column "Value" to "BinValues" and changed type.
+ * Equirectangular StdParallel1 changed to LatitudeOfOrigin.
+ * Logic to preserve psMapInfo->proName as the PROJCS name for UTM/StatePlane.
+ * Special state plane zone handling.
+ * Special wisconsin handling for some LCC and TM SRSes.
+ * 1-bit null blocks to default to 1 in ESRI_BUILDs
+ * Add support for GDA94 (#4025)
+
+Idrisi driver:
+ * Fix segfaults when fields are missing in .ref or .rdc files (#4100)
+ * Fix problem with inverse flattening when reading a SRS of a sphere (#3757)
+
+INGR driver:
+ * Set NBITS for 1 bit bands
+ 
+ISIS2/ISIS3 driver:
+ * Various improvements to PDS related drivers (#3944)
+
+JaxaPalsar driver:
+ * Fixed datatype of ALOS PALSAR products Level 1.5 (#4136)
+ * Fixed detection of unsupported PALSAR Level 1.0 products (#2234)
+
+JPIPKAK driver:
+ * Add try to in GetNextUpdatedRegion() to protect against kakadu exceptions (#3967)
+ * Fixed a serious bug in the computation of fsiz and region. (#3967)
+
+KMLSUPEROVERLAY driver :
+ * Remove spaces between coordinates in coordinate triplets as mandated by KML 2.2 spec, to restore compatibility with Google Earth 6.1.0.5001 (#4347)
+
+LAN driver:
+ * Preliminary support for writing gis/lan files
+
+MEM driver:
+ * Add support for remembered histograms and PIXELTYPE
+
+MG4Lidar driver:
+ * Clamp nOverviewCount, some LiDAR files end up with -1 overviews
+
+MrSID driver:
+ * Initialize overview manager to enable RFC 15 mask band support (#3968)
+ * Mark GDAL_DCAP_VIRTUALIO=YES when the driver is configured in read-only mode
+ * Handle LTI_COLORSPACE_RGBA
+
+NetCDF driver:
+ * Set cylindrical equal area representation to the proper cf-1.x notation (#3425)
+ * Fix precision issue in geotransform (#4200) and metadata
+ * Add support for netcdf filetypes nc2(64-bit) and nc4 to netCDFDataset (#3890, #2379)
+ * Add function Identify and IdentifyFileType() (#3890, #2379)
+ * Temporarily disabling PAM for netcdf driver (#4244)
+ * Make creation of geographic grid CF compliant (#2129)
+ * Fixes for netcdf metadata export: duplication, Band metadata, int/float/double vs. char* and add_offset/scale_factor (#4211, #4204), double precision ( 4200)
+ * Fix netcdf metadata import (float and double precision) (#4211)
+ * Improve import of CF projection
+ * Add netcdf history metadata (#4297)
+ * CF-1.5 compatible export of projected grids (optional lon/lat export)
+ * Fix LCC-1SP import and export (#3324)
+ * Fix handling of UNITS import and export (#4402 and #3324)
+ * Fix upside-down export and import of grids without projection and geotransform (#2129, #4284)
+ * Support import of polar stereographic variant without standard parallel (#2893)
+ * New driver options
+ * Add simple progress indicator
+ * Add support for netcdf-4, HDF4 and HDF5 (#4294 and #3166)
+ * Add support for deflate compression
+ * Add format support information and CreateOptionList to driver metadata 
+ * Add support for valid_range/valid_min/valid_max
+ * Proper handling of singed/unsigned byte data
+ * Add support for Create() function and significantly refactor code for export (#4221)
+ * Improvements to CF projection support (see wiki:NetCDF_ProjectionTestingStatus)
+
+NGSGEOID driver:
+ * New for GDAL/OGR 1.9.0
+ * Read NOAA NGS Geoid Height Grids
+ 
+NITF driver:
+ * Add a generic way of decoding TREs from a XML description file located in data/nitf_spec.xml
+ * Add a new metadata domain xml:TRE to report as XML content the decoded TREs
+ * Add NITF_OPEN_UNDERLYING_DS configuration option that can be set to FALSE to avoid opening the underlying image with the J2K/JPEG drivers
+ * Support JP2KAK driver for jpeg2000 output, use /vsisubfile/ in all cases
+ * NITFCreate(): deal with cases where image_height = block_height > 8192 or image_width = block_width > 8192 (#3922)
+ * Add IREPBAND and ISUBCAT creation option (#4343)
+ * Make sure scanline access is used only on single block image (#3926)
+ * Add a NITF_DISABLE_RPF_LOCATION_TABLE_SANITY_TESTS configuration option that can be set to TRUE to blindly trust the RPF location table (#3930)
+ * Correctly assign hemisphere for a ICORDS='U' NITF file with accompagnying .nfw and .hdr files (#3931)
+ * Make PAM available at band level for JPEG/JPEG2000 compressed datasets (#3985)
+ * Read IMRFCA TRE for RPC info. Read CSEXRA TRE.
+ * Read CSDIDA and PIAIMC TREs as metadata
+ * Optional support for densifying GCPs and applying RPCs to them
+ * Add GetFileList() that captures associated files with some NITF products.
+ * Added ESRI only ExtractEsriMD() function.  Add raw header capture in NITF_METADATA domain in base64 encoded form.
+ * Fetch NITF_DESDATA in segment data; decode specialized fields of XML_DATA_CONTENT and CSATTA DES
+ * Truncate TRE name to 6 character (#4324)
+ * Take into account the presence of comments when patching COMRAT for JPEG/JPEG2000 NITF (#4371)
+
+NWT_GRD driver:
+  * Fix interpolation of color when the maximum z value is below a threshold of the color scheme (#4395)
+
+OPENJPEG driver:
+ * Optimize decoding of big images made of a single block
+ * Fallback to PAM to get projection and geotransform
+
+PCIDSK driver:
+ * Refresh PCIDSK SDK from upstream
+ * Fix support for band description setting, add BANDDESCn creation option
+ * Implement GetCategoryNames(), and color table from metadata for PCIDSK
+ * Fix exception on files with bitmaps as bands in GetFileList()
+ * Avoid closing and reopening file so we don't fracture the SysBMData with a metadata write
+ * In read-only, if .pix is raster (resp. vector) only, then make sure that OGR (resp. GDAL) cannot open it
+
+PDF driver:
+ * Support linking against podofo library (LGPL) instead of poppler --> however
+   pdftoppm binary from poppler distribution is needed for rasterization
+
+PDS driver:
+ * Add support for MISSING and MISSING_CONSTANT keywords for nodata values (#3939)
+ * Add support for uncompressed images in the UNCOMPRESSED_FILE subdomain (#3943)
+ * Add support for PDS_Sample/LineProjectOffset_Shift/Mult (#3940)
+ * Preliminary qube write support (#3944)
+ * Fix band offset computation in BSQ (#4368)
+
+PNG driver:
+ * Add compatibility with libpng >= 1.5.0 (#3914)
+ * Upgrade internal libpng to 1.2.46
+
+PNM driver:
+ * Make it compatible with VSI virtual files
+
+PostgisRaster driver:
+ * Speed of PostGIS Raster driver improved. (#3228, #3233)
+ 
+Rasterlite driver:
+ * Robustness against buggy databases
+ * Enable QUALITY creation option for WEBP tiles
+
+RS2 driver:
+ * Setup to properly support subdataset oriented metadata and overviews (#4006)
+ * Allow opening subdatasets by passing in the folder (#4387)
+
+SAGA driver:
+ * Fix reading & writing .sdat files bigger than 2GB (#4104)
+ * Use nodata value from source dataset in CreateCopy() (#4152)
+
+SDE driver:
+ * Break assumption that LONG==long (#4051)
+
+SNODAS driver:
+ * New for GDAL/OGR 1.9.0
+ * Read Snow Data Assimilation System datasets
+
+SRP driver:
+ * Set Azimuthal Equidistant projection/geotransform info for ASRP north/south polar zones (#3946)
+ * ASRP/USRP: fix skipping of padding characters on some datasets (#4254)
+
+SRTMHGT driver:
+ * Fix segfault in CreateCopy() if we cannot create the output file
+
+Terralib driver:
+ * Removed driver: was unfinished and is unmaintained (#3288)
+
+TIL driver:
+ * Implement GetFileList() (#4008)
+
+TSX driver:
+ * Add support for selecting a directory
+ * Make Terrasar-X driver also open TanDEM-X data (#4390)
+ * Fix memleaks
+
+USGSDEM driver:
+ * Ensure blocks read in C locale (#3886)
+
+VRT driver:
+ * Implement VRTDataset::IRasterIO() that can delegate to source Dataset::RasterIO() in particular cases
+ * Implement GetMinimum() and GetMaximum()
+ * GetFileList(): for /vsicurl/ ressources, don't actually test their existence as it can be excruciating slow
+ * VRTComplexSource: correctly deal with complex data type (#3977)
+ * Fix 2 segfaults related to using '<VRTDataset', but with invalid XML, as the target filename of VRTDataset::Create()
+ * Fix 'VRTDerivedRasterBand with ComplexSource and nodata value yields potentially uninitialized buffer' (#4045)
+ * VRTDerivedRasterBand: Recognize PixelFunctionType and SourceTransferType options in AddBand() for  (#3925)
+ * Copy GEOLOCATION metadata in CreateCopy().
+ * VRTDerivedRasterBand: register pixel functions in a map for faster access (#3924)
+ * VRT warped dataset: limit block size to dataset dimensions (#4137)
+
+WCS driver:
+ * Add time support (#3449)
+ * Honour dimensionLimit restrictions on WCS request size.
+ * Fetch projection from returned image file chunks if they have them (ie. GeoTIFF).
+ * Honour Resample option for WCS 1.0.
+ * Include service url in GetFileList if ESRI_BUILD defined
+ * Check validity of 'OverviewCount' parameter
+ * Add support for getting the coverage offering details from the xml:CoverageOffering domain
+ * Try to preserve the servers name for a CRS (WCS 1.0.0) (#3449).
+
+WebP driver:
+ * New for GDAL/OGR 1.9.0
+ * Read/write GDAL driver for WebP image format
+
+WMS driver:
+ * Implementation of the OnEarth Tiled WMS minidriver (#3493)
+ * Implementation of a VirtualEarth minidriver
+ * Improve handling of .aux.xml files, ensure colorinterp support works for tiled wms server
+ * Report subdatasets when being provided WMS:http://server.url (classic WMS), WMS:http://server.url?request=GetTileService or a url to a TMS server; recognize datasets specified as a pseudo GetMap request
+ * Add capability to open the URL of a REST definition for a ArcGIS MapServer, like http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer?f=json
+ * Parse WMS-C TileSet info in VendorSpecificCapabilities of GetCapabilities
+ * Implement CreateCopy() when source is a WMS dataset to serialize to disk the definition of a WMS dataset
+ * WMS dataset : report INTERLEAVE=PIXEL
+ * Make autodetection of TMS work with http://maps.qualitystreetmap.org/tilecache
+ * Add capability to set Referer http header
+ * Add a TMS-specific hack for some servers that require tile numbers to have exactly 3 characters (#3997)
+ * Fix to make file:// URL to work
+ * Add hack for OSGEO:41001
+ * Fix GDALWMSRasterBand::IReadBlock() to avoid the ReadBlocks() optimization to become an anti-optimization in some use cases
+ * Add service=WMS parameter if not already provided in <ServerUrl> (#4080)
+ * Add options, ZeroBlockHttpCodes and ZeroBlockOnServerException, to control which http error codes should be considered as meaning blank tile (#4169)
+
+ZMap driver:
+ * New for GDAL/OGR 1.9.0
+ * Read/write GDAL driver for ZMap Plus Grid format
+
+== OGR 1.9.0 - Overview of Changes ==
+
+Core:
+ * RFC35: Add OGRLayer::DeleteField(), ReorderField(), ReorderFields() and AlterFieldDefn()
+ * Avoid OGRLineString::addPoint( OGRPoint * poPoint ) to always force the geometry to be 3D (#3907)
+ * Add a OGREnvelope3D object and getEnvelope( OGREnvelope3D * psEnvelope ) / OGR_G_GetEnvelope3D() method
+ * Add OGR_G_SimplifyPreserveTopology() / OGRGeometry::SimplifyPreserveTopology()
+ * OGR SQL: recognize optional ESCAPE escape_char clause
+ * OGR SQL: allow NULL to be used as a value, so that 'SELECT *, NULL FROM foo works'
+ * OGR SQL: Accept doublequoting of column_name in 'SELECT DISTINCT "column_name" FROM table_name' (#3966)
+ * OGR SQL: OGRGenSQLResultsLayer: if the dialect is explicitely set to OGRSQL, don't propagate the WHERE clause of the SELECT to the source layer, but evaluate it instead at the OGRGenSQLResultsLayer level (#4022)
+ * OGR SQL: Avoid error emission on requests such as 'SELECT MIN(EAS_ID), COUNT(*) FROM POLY'
+ * OGR SQL: Avoid setting width/precision for AVG column
+ * OGR SQL: Add a mechanism to delete a layer (DROP TABLE x)
+ * OGR SQL: fix segfault when evaluating a 'IS NULL' on a float column (#4091)
+ * OGR SQL: add support for new special commands : 'ALTER TABLE layername ADD COLUMN columnname columntype', 'ALTER TABLE layername RENAME COLUMN oldname TO new name', 'ALTER TABLE layername ALTER COLUMN columnname TYPE columntype', 'ALTER TABLE layername DROP COLUMN columnname'
+ * OGR SQL: Add implicit conversion from string to numeric (#4259)
+ * OGR SQL: Correctly parse big SQL statements (#4262)
+ * OGR SQL: fix joining a float column with a string column (#4321)
+ * OGR SQL: with DISTINCT, consider null values are such, and not as empty string (#4353)
+ * OGR SQL: fix offset convertion for SUBSTR() (#4348)
+ * Add OGR_G_GetPoints()
+ * Fix parsing of WKT geometries mixing 2D and 3D parts
+ * OGR_Dr_CopyDataSource() and OGRSFDriver::CopyDataSource() : make sure that the driver is attached to the created datasource (#4350)
+ * OGRFeature::SetFrom() supports more conversions between field types. 
+
+OGRSpatialReference:
+ * Update to EPSG 7.9 database
+ * Add Geocentric SRS Support
+ * Add support for Interrupted Goode Homolosine projection (#4060)
+ * Add SRS vertical unit support
+ * Add SetVertCS(), OSRSetVertCS(), SetCompound(), IsCompound() and target oriented set/get linear units functions
+ * ESRI : Improve spheroid remapping (#3904)
+ * ESRI: Compare whole names in RemapNameBasedOnKeyName() (#3965).
+ * ESRI: addition of ImportFromESRIStatePlaneWKT and ImportfromESRIWisconsinWKT methods
+ * ESRI: importFromESRI() : support POLYCONIC projection from old style files (#3983)
+ * ESRI: importFromESRI() : support LAMBERT_AZIMUTHAL projection from old style files (#4302)
+ * ESRI: fix EPSG:32161 mapping
+ * ESRI: fix Stereo/Oblique_Stereo/Double_Stereo (bugs #1428 and #4267)
+ * ESRI: fix projection parameter mapping for Orthographic projection (#4249)
+ * ESRI: add optional fixing of TOWGS84, DATUM and GEOGCS with GDAL_FIX_ESRI_WKT config. option (#4345 and #4378)
+ * ESRI: fix add Krassowsky/Krasovsky 1940 spheroid mapping
+ * Add EPSG:102113 in the data/esri_extra.wkt file
+ * Add Germany zone 1-5 in range 31491-31495 in the data/esri_extra.wkt file
+ * fix NAD_1983_Oregon_Statewide_Lambert_Feet_Intl code
+ * added/updated coordinates systems provided by IGNF (#3868)
+ * ERM: add support for EPSG:n based coordinate sysetms (#3955)
+ * ImportFromEPSG(): Add default support for various degree units without supporting .csv file.
+ * ImportFromEPSG(): Add support for spherical LAEA (#3828)
+ * ImportFromEPSG(): use CoLatConeAxis parameter to build Krovak azimuth parameter (#4223)
+ * importFromURN(): support compound SRS
+ * importFromURN(): accept 'urn:opengis:crs:' syntax found in some TOP10NL GML files
+ * Add CRS: support and for importing two part ESRI PE SRS with VERTCS
+ * SetFromUserInput() : recognize 'IGNF:xxx'
+ * Ensure that the result of importFromEPSGA() always has keyword ordering fixed up (#4178)
+ * exportToERM() : deal with GDA94 datum and its UTM projections (#4208)
+ * Fix ESRI_DATUM_NAME for D_MOLDREF99 and D_Philippine_Reference_System_1992 (#4378)
+
+Utilities:
+ * ogr2ogr: Make 'ogr2ogr someDirThatDoesNotExist.shp dataSourceWithMultipleLayer' create a directory
+ * ogr2ogr: make -overwrite/-append work with non-spatial tables created by GDAL 1.8.0;
+ * ogr2ogr: take into account fields specified in the -where clause in combinations with -select to create the correct list of fields to pass to SetIgnoredFields() (#4015)
+ * ogr2ogr: fix -zfield option so that the modified geometry properly reports coordinate dimension = 3. Also avoids it to be in the list of ignored field names
+ * ogr2ogr: add -simplify option to simplify geometries
+ * ogr2ogr: add a warning if the target filename has an extension or a prefix that isn't consistant with the default output format (i.e. Shapefile), but which matches another driver. Can be made quiet with -q option
+ * ogrinfo/ogr2ogr: exit when SetAttributeFilter() fails, instead of silently going on (#4261)
+
+Multi driver topics:
+ * RFC35 : implementation in Shapefile, Memory and PG drivers (#2671)
+ * DXF, EDIGEO, KML, LIBKML, Shapefile, SDE, SOSI: Mark as supporting UTF-8
+ * BNA, CSV, GPX, KML, GeoRSS, GML, LIBKML, GeoJSON, PGDump : accept both /dev/stdout and /vsistdout/ as filenames; remove 'stdout' as a valid alias that could be used in some of them (#4225, #4226)
+
+ARCGEN driver:
+ * New for GDAL/OGR 1.9.0
+ * Read-only OGR driver for Arc/Info Generate files
+
+CouchDB driver:
+ * New for GDAL/OGR 1.9.0
+ * Read/write OGR driver for CouchDB / GeoCouch
+
+CSV driver:
+ * Add special recognition and handling for USGS GNIS (Geographic Names Information System) files
+ * Directly recognize the structure of the allCountries file from GeoNames.org
+ * Implement GetFeatureCount() to be a little bit faster
+ * Accept /dev/stdout as a filename for CreateDataSource()
+ * Fix handling of non-numeric values in numeric columns (NULL instead of 0)
+ * Fix handling of column names with numbers
+ * Recognize numeric fieldnames inside quotes
+ * Accept real numbers with ',' as decimal separator when ';' is the field separator (CSV export in French locale)
+
+DXF driver:
+ * Add support for DXF_ENCODING config var and DWGCODEPAGE header field (#4008)
+ * Added DXF_MERGE_BLOCK_GEOMETRIES
+ * Treat ATTDEFs the same as TEXT entities
+ * Implement hatch polyline and elliptical arc support, hatch fill, do not polygonize closed smoothed lines
+ * Add handling of hidden/frozen/off layers.
+
+DWG driver:
+ * New for GDAL/OGR 1.9.0
+ * Read DWG files through the use of Open Design Alliance Teigha Libraries
+
+EDIGEO driver:
+ * New for GDAL/OGR 1.9.0
+ * Read files of French EDIGEO exchange format
+
+FileGDB driver:
+ * New for GDAL/OGR 1.9.0
+ * Read/write support based on FileGDB API SDK
+
+GeoJSON driver:
+ * Support writing 3D lines and polygons
+ * Add a bbox attribute with the geometry bounding box if WRITE_BBOX layer creation option is set (#2392)
+ * Write bbox of FeatureCollection before features when file is seekable
+ * Remove unsetting of FID that caused FID not at the last position of properties to be lost
+ * Properly deal with null field values in reading and writing
+ * Handle OFTIntegerList, OFTRealList and OFTStringList fields
+ * Recognize other arrays as OFTString field
+ * Fix assertion on unhandled ESRI json (#4056)
+ * Fix segfault on feature where 'properties' member exists but isn't an object (#4057)
+ * Better detection of OGR type for numeric JSON fields (#4082)
+ * Add COORDINATE_PRECISION layer creation option to specify the maximum number of figures after decimal point in coordinates; set to 15 by default with smart truncation of trailing zeros (like done for WKT)
+ * Add OGR_G_ExportToJsonEx() to accept a list of options
+ * Add ability to detect geojson files without an extension (#4314)
+
+Geomedia driver:
+ * New for GDAL/OGR 1.9.0
+ * Read-only driver to read Geomedia .MDB databases
+
+GeoRSS driver:
+ * Parse RSS documents without <channel> element
+ 
+GFT driver:
+ * New for GDAL/OGR 1.9.0
+ * Read/write driver for Google Fusion Tables
+
+GML driver:
+ * Major performance improvement when reading large multi-layer GML files. See usage of new GML_READ_MODE configuration option
+ * Support gml:xlink resolving for huge GML files through GML_SKIP_RESOLVE_ELEMS=HUGE (requires SQLite)
+ * Add GML_GFS_TEMPLATE config option to specify a template .gfs file that can be used for several GML files with similar structure (#4380)
+ * Be able to build the driver with support of both Expat and Xerces libraries and add ability of select one at runtime. For UTF-8 documents, we select Expat if it is available, because it is faster than Xerces
+ * Expose fid or gml_id as feature fields if autodetected. This behaviour can be altered by the GML_EXPOSE_FID / GML_EXPOSE_GML_ID configuration option.
+ * Improve handling of .gml and .xsd produced by FME (in particular for CanVec GML)
+ * Be able to open .gz file directly (like OS Mastermap ones), and read/write the .gfs file next to the .gz file
+ * Fix segfault when encountering an invalid (or unhandled by OGR) geometry and when the axis order is lat/long (#3935)
+ * GML3: use a new method to interpret Face objects (which requires GEOS support);
+         old method available if GML_FACE_HOLE_NEGATIVE config. option set to YES (#3937)
+ * GML3: support Curve as a valid child for curveProperty inside directEdge parsing (#3934)
+ * GML3: don't force the linestring to be 3D when inverting its orientation during parsing of directedEdge (#3936)
+ * GML3: accept <pointProperty> element in <gml:LineString> or <gml:LineStringSegment>
+ * OGR_G_CreateFromGML(): accept <gml:coordinates> with coordinate tuples separated by comma and coordinate components separated by space
+ * Recognized schemas with <complexType> inside <element>, such as the one returned by http://deegree3-demo.deegree.org:80/deegree-utah-demo/services
+ * Write the Z component of bounding box for 25D geometries
+ * Force layer geometry type to 3D when there's only a .xsd file and we detect a hint that the bounding box is 3D
+ * Handle layers of type wkbNone appropriately (#4154)
+ * Change format of (GML 2.1.1) FID generated from Fxxx to layer_name.xxx (where xxx is the OGR FID) to ensure uniqueness (#4250)
+ * Accept 'GML3Deegree' as a valid value for the dataset creation option FORMAT, to produce a .XSD that should be better handled by Deegree3 (#4252), and 'GML3.2' to produce GML file and schema that validate against GML 3.2.1 schema.
+ * Don't try to parse successfully a feature type in the .xsd if there are elements we don't know how to parse. Better to rely on the .gfs mechanism (#4328)
+ * Fix bug in OGRAtof() that caused wrong parsing of coordinates in GML files written in scientific notation (#4399)
+
+GMT driver:
+ * Fix GetExtent() result that swallowed the first char of the minx bound (#4260)
+
+IDRISI driver:
+ * New for GDAL/OGR 1.9.0
+ * Read Idrisi .VCT vector files
+
+ILI1 driver:
+ * Fix for missing geometry in ILI1
+
+LIBKML driver:
+ * Set the OGRStylePen unit type to pixel when reading <LineStyle>
+ * Avoid ingesting zip files that are not valid kmz (#4003)
+ * Do not use displayname to set the field name
+ * Recognize <Data> elements of <ExtendedData> in case <ExtendedData> doesn't use a <SchemaData>
+ * Fix mapping of the type attribute of <SimpleType> elements inside <Schema> to OGR field type (#4171)
+ * Parse correctly kml docs containing only one placemark
+ * Properly set the feature style string from a placemarks style
+ * Improve OGRStyleLabel <-> KmlLabelStyle mapping
+ * Combine styles from the style table and features styles when LIBKML_RESOLVE_STYLE=YES (#4231)
+ * Check that string values put in fields are valid UTF-8 (#4300)
+
+MDB driver:
+ * New for GDAL/OGR 1.9.0
+ * Read-only driver to read PGeo and Geomedia .MDB databases
+ * Relies on using the Java Jackcess library (LGPL) through JNI.
+
+MITAB driver:
+ * Add support for reading google mercator from mapinfo (#4115)
+ * Fixed problem of the null datetime values (#4150)
+ * Fix problem with tab delimiter used in MIF files (#4257)
+
+MSSQLSpatial driver:
+ * Removing 'Initial Catalog' which is not supported in the ODBC SQL driver connection strings.
+ * Allow to specify 'Driver' in MSSQL connection strings (#4393)
+ * Fix for the IDENTITY INSERT problem with MSSQL Spatial (#3992)
+ * Add more verbose warnings to the geometry validator
+ * Fix for the schema handling problem with MSSQL Spatial (#3951)
+ * Fix for the corrupt geometry report when using the ogr2ogr -sql option (#4149)
+
+MySQL driver:
+ * Recognize columns with types POINT, LINESTRING, etc. as geometry columns
+
+NAS driver:
+ * Add support for treating wfs:Delete as a special Delete feature with typeName and FeatureId properties
+ * Handle empty files gracefully (#3809)
+ * Preliminary support for SRS in NAS files, including 3GKn SRS
+ * Implement special treatement for <lage> to be zero passed and string (NAS #9)
+ * Add special handling of punktkennung (NAS #12)
+ * Add special handling for artDerFlurstuecksgrenze (#4255)
+ * Add support for wfsext:Replace operations (PostNAS #11)
+ * Correct NASHandler::dataHandler() to avoid trimming non-leading white space
+
+NTF driver:
+ * Create and manage height field as floating point since some DTM products have floating point elevations.
+
+OCI driver:
+ * Added TRUNCATE layer creation option (#4000)
+ * Clear errors after speculative dimension calls (#4001)
+ * Fix multithreading related problems (#4039)
+ * Ensure that AllocAndBindForWrite does not mess up if there are no general attributes (#4063)
+ * Implement DeleteLayer(int) method
+ * Ensure extents updated by SyncToDisk(), and that new features are merged into existing extents (#4079)
+
+OGDI driver:
+ * Fix GetFeature() that did not like switching between layers
+   
+PG driver:
+ * Write geometries as EWKB by default to avoid precision loss (#4138)
+ * Return the table columns in the order they are in the database (#4194)
+ * Add a NONE_AS_UNKNOWN layer creation option that can be set to TRUE to force layers with geom type = wkbNone to be created as if it was wkbUnknown (PostGIS GEOMETRY type) to be able to revert to behaviour prior to GDAL 1.8.0 (#4012)
+ * Add EXTRACT_SCHEMA_FROM_LAYER_NAME layer creation option that can be set to OFF to disable analysis of layer name as schema_name.table_name
+ * Add FID layer creation option to specify the name of the FID column
+ * ogr2ogr: make sure that for a PG datasource, -nln public.XXX can also be used with -append
+ * Fix CreateFeatureViaInsert() to emit 'INSERT INTO xx DEFAULT VALUES'
+ * Fix handling of Nan with fields with non-zero width (#2112)
+ * Use wrapper for PQexec() to use PQexecParams() instead in most cases
+ * Add proper escaping of table and column names
+ * OGR SQL: add proper column name escaping and quoting for PostgreSQL datasources
+ * Launder single quote character in table name
+ * Better reporting of error in case of failed ExecuteSQL()
+ * Create field of type OFTString and width > 0, as VARCHAR(width) (#4202)
+ * Add more compat with Postgis 2.0SVN (geometry_columns- #4217, unknown SRID handling)
+ * Better behaviour, in particular in error reporting, of ExecuteSQL() when passed with non-select statements, or with select statements that have side-effects such as AddGeometryColumn()
+
+PGDump driver:
+ * fix handling of Nan with fields with non-zero width (#2112)
+ * Add CREATE_SCHEMA and DROP_TABLE layer creation option (#4033)
+ * Fix crash when inserting a feature with a geometry in a layer with a geom type of wkbNone;
+ * PG and PGDump: fix insertion of features with first field being a 0-charachter string in a non-spatial table and without FID in COPY mode (#4040)
+ * Add NONE_AS_UNKNOWN, FID, EXTRACT_SCHEMA_FROM_LAYER_NAME layer creation options
+ * Better escaping of column and table names
+ * Create field of type OFTString and width > 0, as VARCHAR(width) (#4202)
+ 
+PGeo driver:
+ * Move CreateFromShapeBin() method to an upper level
+ * Only try to open .mdb files that have the GDB_GeomColumns string
+ * Decode Z coordinate for a POINTZM shape
+ * Aad support for decoding multipoint/multipointz geometries
+ * Fix setting of the layer geometry type
+ * Add support for zlib compressed streams
+ * Implement MultiPatch decoding
+
+SDE driver:
+ * Add support for decoding NSTRING fields (#4053)
+ * Add support in CreateLayer() to clean up partially registered tables that aren't full spatial layers
+ * Add logic to force envelope for geographic coordsys objects (#4054)
+ * Add USE_STRING layer creation and configuration options information
+ * Set SE_MULTIPART_TYPE_MASK for multipolygon layers (#4061).
+ * Change how offset and precision are set for geographic coordinate systems to more closely match SDE
+
+SEGUKOOA driver:
+ * New for GDAL/OGR 1.9.0
+ * Read files in SEG-P1 and UKOOA P1/90 formats
+ 
+SEGY driver:
+ * New for GDAL/OGR 1.9.0
+ * Read files in SEG-Y format
+ 
+Shapefile driver:
+ * Encoding support for shapefile/dbf (#882)
+ * Allow managing datasources with several hundreds of layers (#4306)
+ * Lazy loading of SRS and lazy initialization of attribute index support
+ * Use VSI*L API to access .qix spatial index files
+ * Add special SQL command 'RECOMPUTE EXTENT ON layer_name' to force recomputation of the layer extent (#4027)
+ * Faster implementation of GetFeatureCount() in some circumstances.
+ * Fix crash in CreateField() if there is no DBF file
+ * Fix add field record flushing fix (#4073)
+ * Fix decoding of triangle fan in a multipatch made of several parts (#4081)
+ * Refuse to open a .shp in update mode if the matching .dbf exists but cannot be opened in update mode too (#4095)
+ * Recognize blank values for Date fields as null values (#4265)
+ * Recognize 'NULL' as a valid value for SHPT creation option as documented
+ * Check that we are not trying to add too many fields.
+ * Support reading measure values as Z coordinate.
+
+SQLite/Spatialite driver:
+ * Spatialite: major write support improvements (creation/update of Spatialite DB now limited to GDAL builds with libspatialite linking)
+ * Spatialite: add support for 3D geometries (#4092)
+ * Spatialite: speed-up spatial filter on table layers by using spatial index table (#4212)
+ * Spatialite: add support for reading Spatialite views registered in the views_geometry_columns
+ * Spatialite: better support for building against amalgamated or not
+ * Spatialite: when it exists, use srs_wkt column in spatial_ref_sys when retrieving/inserting SRS
+ * Spatialite: add COMPRESS_GEOM=YES layer creation option to generate Spatialite compressed geometries
+ * Spatialite: add support for VirtualXLS layers.
+ * Spatialite: imported VirtualShape support, in particular it is now possible to open on-the-fly a shapefile as a VirtualShape with 'VirtualShape:shapefile.shp' syntax as a datasource
+ * Implement RFC35 (DeleteField, AlterFieldDefn, ReorderFields)
+ * Implement DeleteDataSource()
+ * Implement DeleteFeature()
+ * Implement SetFeature() by using UPDATE instead of DELETE / INSERT
+ * Add capability to use VSI Virtual File API when needed (if SQLite >= 3.6.0)
+ * Make CreateDataSource(':memory:') work
+ * Enforce opening update/read-only mode to allow/forbid create/delete layers, create/update features (#4215)
+ * Launder single quote character in table name; properly escape table name if no laundering (#1834)
+ * Use ALTER TABLE ADD COLUMN by default to create a new field; older method can still be used by defining the OGR_SQLITE_USE_ADD_COLUMN config option to FALSE in order to provide read-compat by sqlite 3.1.3 or earlier
+ * Fix bug in CreateField() : if there was already one record, the content of the table was not preserved, but filled with the column names, and not their values
+ * Map 'DECIMAL' columns to OGR real type (#4346)
+ * Add OGR_SQLITE_CACHE configuration option for performance enhancements
+ * Try to reuse INSERT statement to speed up bulk loading.
+
+SVG driver:
+ * New for GDAL/OGR 1.9.0
+ * Read only driver for Cloudmade Vector Stream files
+
+S57 driver:
+ * Add support for Dutch inland ENCs (#3881)
+ * Allow up to 65536 attributes, use GUInt16 for iAttr (#3881)
+ * Be cautious of case where end piont of a line segment has an invalid RCID
+ * Correct handling of update that need to existing SG2D into an existing feature without it (#4332)
+
+VRT driver:
+ * Do not try to read too big files
+ * Lazy initialization of OGRVRTLayer
+ * Don't set feature field when source feature field is unset
+
+WFS driver:
+ * Add preliminary support for WFS 2.0.0, but for now don't request it by default.
+ * Increase performance of layer definition building by issuing a DescribeFeatureType request for several layers at the same time
+ * Better server error reporting
+ * Use the layer bounding box for EPSG:4326 layers (restricted to GEOSERVER for now) (#4041)
+ * Add capability of opening a on-disk Capabilities document
+ * Add special (hidden) layer 'WFSLayerMetadata' to store layer metadata
+ * Add special (hidden) layer 'WFSGetCapabilities' to get the raw XML result of the GetCapabilities request
+ * CreateFeature()/SetFeature(): use GML3 geometries in WFS 1.1.0 (make TinyOWS happy when it validates against the schema)
+ * Make spatial filtering work with strict Deegree 3 servers
+ * Fix reading when layer names only differ by their prefix
+
+XLS driver:
+ * New for GDAL/OGR 1.9.0
+ * Read only driver for MS XLS files and relies on FreeXL library.
+
+XPlane driver:
+ * Port to VSI*L API
+
+XYZ driver:
+ * Ignore comment lines at the beginning of files
+
+== SWIG Language Bindings ==
+
+General :
+ * RFC 30: Correct the signature of Datasource.CreateDataSource() and DeleteDataSource(),  gdal.Unlink() to accept UTF-8 filenames (#3766)
+ * Add Band.GetCategoryNames() and Band.SetCategoryNames()
+ * Add Geometry.GetPoints() (only for Python and Java) (#4016)
+ * Add Geometry.GetEnvelope3D()
+ * Add Geometry.SimplifyPreserveTopology()
+ * Extend SWIG Geometry.ExportToJson() to accept a list of options (#4108)
+ * Add (OGR)DataSource.SyncToDisk()
+ * Add SpatialReference.SetVertCS(), IsSameVertCS(), IsVertical(), SetCompount(), IsCompound()
+ * Add SpatialReference.SetIGH() (#4060)
+ * RFC 35: Add OGRLayer.DeleteField(), ReorderField(), ReorderFields(), AlterFieldDefn()
+ * Add gdal.VSIFTruncateL()
+
+CSharp bindings:
+ * Implement the typemap for utf8_path in C# (#3766)
+ * Correcting the signature of OGRDataSource.Open to make the utf8 typemap to work (#3766)
+
+Java bindings:
+ * Turn the gdalJNI, gdalconstJNI and osrJNI into package private classes
+ * Make Layer.GetExtent() return null when OGR_L_GetExtent() fails.
+
+Perl bindings:
+ * The "Points" method of Geometry was not accepting its own output in the case of a single point. It accepted only a point as a list. Now it accepts a point both as a list containing one point (a ref to a point as a list) and a point as a list.
+ * Fixed UTF-8 support in decoding names (datasource, layer, field etc.).
+ * Assume all GDAL strings are UTF-8, handle all changes in typemaps.
+ * Additions to Perl bindings due to new developments etc: Layer capabilities, GeometryType  method for Layer, improved create, new Export and Set methods for SpatialReference.
+ * Detect context in a typemap which returns a array, this now returns a list in list context; the change affects at least GetExtent and GetEnvelope methods, which retain backward compatibility though new and/or changed methods: FeatureDefn::Name, FeatureDefn::GeometryIgnored, FeatureDefn::StyleIgnored, Feature::ReferenceGeometry, Feature::SetFrom, FieldDefn::Ignored, Geometry::AsJSON
+ * Perl typemaps: more correct manipulation of the stack, more cases where a list is returned in a list context, better handling of callback_data @Band::COLORINTERPRETATIONS, Band methods Unit, ScaleAndOffset, GetBandNumber, RasterAttributeTable method LinearBinning
+ * Typemaps for VSIF{Write|Read}L, tests and docs for some VSI* functions.
+ * Perl bindings: better by name / by index logics, some checks for silent failures, return schema as a hash if wanted, support ->{field} syntax for features, return list attributes as lists or listrefs as wished so that ->{field} works for lists too (API change)
+
+Python bindings:
+ * Improvements for ogr.Feature field get/set
+ * Add hack to bring Python 3.2 compatibility
+ * First argument of VSIFWriteL() should accept buffers for Python3 compat
+ * Fix reference leak in 'typemap(in) char **dict'
+ * Add gdal.VSIStatL()
+ * swig/python/setup.py : fix for virtualenv setups (#4285)
+ * Layer.GetExtent() : add optional parameter can_return_null that can be set to allow returning None when OGR_L_GetExtent() fails
+ * Make gdal.VSIFSeekL(), gdal.VSIFTellL() and gdal.VSIFTruncateL() use GIntBig instead of long for compat with 32bit platforms
+ * Add script to build the python extensions with Python 2.7 and a mingw32 cross-compiler under Linux/Unix
+
+Ruby bindings:
+ * Build SWIG Ruby Bindings against modern Ruby versions (1.8.7 and 1.9.2) (#3999)
 
 = GDAL/OGR 1.8.0 release notes =
 
@@ -420,6 +1273,8 @@ JP2KAK driver:
  * Major restructuring, all reading now goes through DirectRasterIO (#3295)
  * Introduce YCC optimization
  * Ensure we fetch <= 8 bit images with their true precision (#3540)
+ * Make JP2KAK_RESILIENT also turn off persist, and force sequential access (#4336)
+ * Fix reading overviews via direct case (#4340)
 
 JP2OpenJPEG:
  * New for GDAL/OGR 1.8.0
diff --git a/PROVENANCE.TXT b/PROVENANCE.TXT
index b4169d9..056bd03 100644
--- a/PROVENANCE.TXT
+++ b/PROVENANCE.TXT
@@ -47,7 +47,7 @@ Historical and Current:
  kruland - Kevin Ruland
  vgough - Valient Gough - 1999 - configure stuff. 
  silke - Silke Reimer (Intevation)
- ilucena - Ivan Lucena (Idrisi)
+ ilucena - Ivan Lucena (Oracle)
  shalasz - Steve Halasz (Debian)
  srioux - Sylvain Rioux (Softmap)
  ldjohn - Lowell D. Johnson - 2001 - rawdataset.cpp - one commit
diff --git a/VERSION b/VERSION
index a8fdfda..f8e233b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.8.1
+1.9.0
diff --git a/aclocal.m4 b/aclocal.m4
index 998b76f..4ea4f44 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -19,6 +19,10 @@ m4_include([m4/ax_lib_sqlite3.m4])
 m4_include([m4/ax_lib_xerces.m4])
 m4_include([m4/ax_oracle_oci.m4])
 m4_include([m4/geos.m4])
+m4_include([m4/iconv.m4])
+m4_include([m4/lib-ld.m4])
+m4_include([m4/lib-link.m4])
+m4_include([m4/lib-prefix.m4])
 m4_include([m4/libtool.m4])
 m4_include([m4/ltoptions.m4])
 m4_include([m4/ltsugar.m4])
diff --git a/alg/GNUmakefile b/alg/GNUmakefile
index e012a01..3ca8aa3 100644
--- a/alg/GNUmakefile
+++ b/alg/GNUmakefile
@@ -6,13 +6,19 @@ OBJ	=	gdalmediancut.o gdaldither.o gdal_crs.o gdaltransformer.o \
 		gdalwarpoperation.o gdalchecksum.o gdal_rpc.o gdal_tps.o \
 		thinplatespline.o llrasterize.o gdalrasterize.o gdalgeoloc.o \
 		gdalgrid.o gdalcutline.o gdalproximity.o rasterfill.o \
-		gdalrasterpolygonenumerator.o gdalsievefilter.o \
-		gdalwarpkernel_opencl.o polygonize.o contour.o
+		gdalrasterpolygonenumerator.o \
+		gdalsievefilter.o gdalwarpkernel_opencl.o polygonize.o \
+		gdalrasterfpolygonenumerator.o fpolygonize.o \
+		contour.o
 
 ifeq ($(HAVE_GEOS),yes)
 CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
 endif
 
+ifeq ($(HAVE_ARMADILLO),yes)
+CPPFLAGS 	:=	-DHAVE_ARMADILLO $(CPPFLAGS)
+endif
+
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(OPENCL_FLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
diff --git a/alg/fpolygonize.cpp b/alg/fpolygonize.cpp
new file mode 100644
index 0000000..5883fa8
--- /dev/null
+++ b/alg/fpolygonize.cpp
@@ -0,0 +1,820 @@
+/******************************************************************************
+ * $Id: fpolygonize.cpp 22501 2011-06-04 21:28:47Z rouault $
+ * 
+ * Project:  GDAL
+ * Purpose:  Version of Raster to Polygon Converter using float buffers.
+ * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com. Most of the code
+ * taken from GDALPolygonize.cpp, by Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Jorge Arevalo
+ * Copyright (c) 2008, Frank Warmerdam
+ *
+ * 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_alg_priv.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include <vector>
+
+CPL_CVSID("$Id: fpolygonize.cpp 22501 2011-06-04 21:28:47Z rouault $");
+
+#define GP_NODATA_MARKER -51502112
+
+#ifdef OGR_ENABLED
+
+/******************************************************************************/
+/*                          GDALFloatEquals()                                 */
+/* Code from:                                                                 */
+/* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm  */
+/******************************************************************************/
+GBool GDALFloatEquals(float A, float B)
+{
+    /**
+     * This function will allow maxUlps-1 floats between A and B.
+     */
+    int maxUlps = MAX_ULPS;
+    int aInt, bInt;
+
+    /**
+     * Make sure maxUlps is non-negative and small enough that the default NAN
+     * won't compare as equal to anything.
+     */
+    CPLAssert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
+
+    /**
+     * This assignation could violate strict aliasing. It causes a warning with
+     * gcc -O2. Use of memcpy preferred. Credits for Even Rouault. Further info
+     * at http://trac.osgeo.org/gdal/ticket/4005#comment:6
+     */
+    //int aInt = *(int*)&A;
+    memcpy(&aInt, &A, 4);
+
+    /**
+     * Make aInt lexicographically ordered as a twos-complement int
+     */
+    if (aInt < 0)
+        aInt = 0x80000000 - aInt;
+    /**
+     * Make bInt lexicographically ordered as a twos-complement int
+     */
+    //int bInt = *(int*)&B;
+    memcpy(&bInt, &B, 4);
+    
+    if (bInt < 0)
+        bInt = 0x80000000 - bInt;
+    int intDiff = abs(aInt - bInt);
+    if (intDiff <= maxUlps)
+        return true;
+    return false;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                               RPolygonF                              */
+/*									*/
+/*      This is a helper class to hold polygons while they are being    */
+/*      formed in memory, and to provide services to coalesce a much    */
+/*      of edge sections into complete rings.                           */
+/* ==================================================================== */
+/************************************************************************/
+
+class RPolygonF {
+public:
+    RPolygonF( float fValue ) { fPolyValue = fValue; nLastLineUpdated = -1; }
+
+    float            fPolyValue;
+    int              nLastLineUpdated;
+
+    std::vector< std::vector<int> > aanXY;
+
+    void             AddSegment( int x1, int y1, int x2, int y2 );
+    void             Dump();
+    void             Coalesce();
+    void             Merge( int iBaseString, int iSrcString, int iDirection );
+};
+
+/************************************************************************/
+/*                                Dump()                                */
+/************************************************************************/
+void RPolygonF::Dump()
+{
+    size_t iString;
+
+    printf( "RPolygonF: Value=%f, LastLineUpdated=%d\n",
+            fPolyValue, nLastLineUpdated );
+    
+    for( iString = 0; iString < aanXY.size(); iString++ )
+    {
+        std::vector<int> &anString = aanXY[iString];
+        size_t iVert;
+     
+        printf( "  String %d:\n", (int) iString );
+        for( iVert = 0; iVert < anString.size(); iVert += 2 )
+        {
+            printf( "    (%d,%d)\n", anString[iVert], anString[iVert+1] );
+        }
+    }
+}
+
+/************************************************************************/
+/*                              Coalesce()                              */
+/************************************************************************/
+
+void RPolygonF::Coalesce()
+
+{
+    size_t iBaseString;
+
+/* -------------------------------------------------------------------- */
+/*      Iterate over loops starting from the first, trying to merge     */
+/*      other segments into them.                                       */
+/* -------------------------------------------------------------------- */
+    for( iBaseString = 0; iBaseString < aanXY.size(); iBaseString++ )
+    {
+        std::vector<int> &anBase = aanXY[iBaseString];
+        int bMergeHappened = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Keep trying to merge the following strings into our target      */
+/*      "base" string till we have tried them all once without any      */
+/*      mergers.                                                        */
+/* -------------------------------------------------------------------- */
+        while( bMergeHappened )
+        {
+            size_t iString;
+
+            bMergeHappened = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Loop over the following strings, trying to find one we can      */
+/*      merge onto the end of our base string.                          */
+/* -------------------------------------------------------------------- */
+            for( iString = iBaseString+1; 
+                 iString < aanXY.size(); 
+                 iString++ )
+            {
+                std::vector<int> &anString = aanXY[iString];
+
+                if( anBase[anBase.size()-2] == anString[0]
+                    && anBase[anBase.size()-1] == anString[1] )
+                {
+                    Merge( iBaseString, iString, 1 );
+                    bMergeHappened = TRUE;
+                }
+                else if( anBase[anBase.size()-2] == anString[anString.size()-2]
+                         && anBase[anBase.size()-1] == anString[anString.size()-1] )
+                {
+                    Merge( iBaseString, iString, -1 );
+                    bMergeHappened = TRUE;
+                }
+            }
+        }
+
+        /* At this point our loop *should* be closed! */
+
+        CPLAssert( anBase[0] == anBase[anBase.size()-2]
+                   && anBase[1] == anBase[anBase.size()-1] );
+    }
+
+}
+
+/************************************************************************/
+/*                               Merge()                                */
+/************************************************************************/
+
+void RPolygonF::Merge( int iBaseString, int iSrcString, int iDirection )
+
+{
+    std::vector<int> &anBase = aanXY[iBaseString];
+    std::vector<int> &anString = aanXY[iSrcString];
+    int iStart, iEnd, i;
+
+    if( iDirection == 1 )
+    {
+        iStart = 1;
+        iEnd = anString.size() / 2; 
+    }
+    else
+    {
+        iStart = anString.size() / 2 - 2;
+        iEnd = -1; 
+    }
+    
+    for( i = iStart; i != iEnd; i += iDirection )
+    {
+        anBase.push_back( anString[i*2+0] );
+        anBase.push_back( anString[i*2+1] );
+    }
+    
+    if( iSrcString < ((int) aanXY.size())-1 )
+        aanXY[iSrcString] = aanXY[aanXY.size()-1];
+
+    size_t nSize = aanXY.size(); 
+    aanXY.resize(nSize-1);
+}
+
+/************************************************************************/
+/*                             AddSegment()                             */
+/************************************************************************/
+
+void RPolygonF::AddSegment( int x1, int y1, int x2, int y2 )
+
+{
+    nLastLineUpdated = MAX(y1, y2);
+
+/* -------------------------------------------------------------------- */
+/*      Is there an existing string ending with this?                   */
+/* -------------------------------------------------------------------- */
+    size_t iString;
+
+    for( iString = 0; iString < aanXY.size(); iString++ )
+    {
+        std::vector<int> &anString = aanXY[iString];
+        size_t nSSize = anString.size();
+        
+        if( anString[nSSize-2] == x1 
+            && anString[nSSize-1] == y1 )
+        {
+            int nTemp;
+
+            nTemp = x2;
+            x2 = x1;
+            x1 = nTemp;
+
+            nTemp = y2;
+            y2 = y1;
+            y1 = nTemp;
+        }
+
+        if( anString[nSSize-2] == x2 
+            && anString[nSSize-1] == y2 )
+        {
+            // We are going to add a segment, but should we just extend 
+            // an existing segment already going in the right direction?
+
+            int nLastLen = MAX(ABS(anString[nSSize-4]-anString[nSSize-2]),
+                               ABS(anString[nSSize-3]-anString[nSSize-1]));
+            
+            if( nSSize >= 4 
+                && (anString[nSSize-4] - anString[nSSize-2]
+                    == (anString[nSSize-2] - x1)*nLastLen)
+                && (anString[nSSize-3] - anString[nSSize-1]
+                    == (anString[nSSize-1] - y1)*nLastLen) )
+            {
+                anString.pop_back();
+                anString.pop_back();
+            }
+
+            anString.push_back( x1 );
+            anString.push_back( y1 );
+            return;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a new string.                                            */
+/* -------------------------------------------------------------------- */
+    size_t nSize = aanXY.size();
+    aanXY.resize(nSize + 1);
+    std::vector<int> &anString = aanXY[nSize];
+
+    anString.push_back( x1 );
+    anString.push_back( y1 );
+    anString.push_back( x2 );
+    anString.push_back( y2 );
+
+    return;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*     End of RPolygonF                                                  */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                              AddEdges()                              */
+/*                                                                      */
+/*      Examine one pixel and compare to its neighbour above            */
+/*      (previous) and right.  If they are different polygon ids        */
+/*      then add the pixel edge to this polygon and the one on the      */
+/*      other side of the edge.                                         */
+/************************************************************************/
+
+static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId, 
+                      GInt32 *panPolyIdMap, float *pafPolyValue,
+                      RPolygonF **papoPoly, int iX, int iY )
+
+{
+    int nThisId = panThisLineId[iX];
+    int nRightId = panThisLineId[iX+1];
+    int nPreviousId = panLastLineId[iX];
+    int iXReal = iX - 1;
+
+    if( nThisId != -1 )
+        nThisId = panPolyIdMap[nThisId];
+    if( nRightId != -1 )
+        nRightId = panPolyIdMap[nRightId];
+    if( nPreviousId != -1 )
+        nPreviousId = panPolyIdMap[nPreviousId];
+
+    if( nThisId != nPreviousId )
+    {
+        if( nThisId != -1 )
+        {
+            if( papoPoly[nThisId] == NULL )
+                papoPoly[nThisId] = new RPolygonF( pafPolyValue[nThisId] );
+
+            papoPoly[nThisId]->AddSegment( iXReal, iY, iXReal+1, iY );
+        }
+        if( nPreviousId != -1 )
+        {
+            if( papoPoly[nPreviousId] == NULL )
+                papoPoly[nPreviousId] = new RPolygonF(pafPolyValue[nPreviousId]);
+
+            papoPoly[nPreviousId]->AddSegment( iXReal, iY, iXReal+1, iY );
+        }
+    }
+
+    if( nThisId != nRightId )
+    {
+        if( nThisId != -1 )
+        {
+            if( papoPoly[nThisId] == NULL )
+                papoPoly[nThisId] = new RPolygonF(pafPolyValue[nThisId]);
+
+            papoPoly[nThisId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
+        }
+
+        if( nRightId != -1 )
+        {
+            if( papoPoly[nRightId] == NULL )
+                papoPoly[nRightId] = new RPolygonF(pafPolyValue[nRightId]);
+
+            papoPoly[nRightId]->AddSegment( iXReal+1, iY, iXReal+1, iY+1 );
+        }
+    }
+}
+
+/************************************************************************/
+/*                         EmitPolygonToLayer()                         */
+/************************************************************************/
+
+static CPLErr
+EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
+                    RPolygonF *poRPoly, double *padfGeoTransform )
+
+{
+    OGRFeatureH hFeat;
+    OGRGeometryH hPolygon;
+
+/* -------------------------------------------------------------------- */
+/*      Turn bits of lines into coherent rings.                         */
+/* -------------------------------------------------------------------- */
+    poRPoly->Coalesce();
+
+/* -------------------------------------------------------------------- */
+/*      Create the polygon geometry.                                    */
+/* -------------------------------------------------------------------- */
+    size_t iString;
+
+    hPolygon = OGR_G_CreateGeometry( wkbPolygon );
+    
+    for( iString = 0; iString < poRPoly->aanXY.size(); iString++ )
+    {
+        std::vector<int> &anString = poRPoly->aanXY[iString];
+        OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
+
+        int iVert;
+
+        // we go last to first to ensure the linestring is allocated to 
+        // the proper size on the first try.
+        for( iVert = anString.size()/2 - 1; iVert >= 0; iVert-- )
+        {
+            double dfX, dfY;
+            int    nPixelX, nPixelY;
+            
+            nPixelX = anString[iVert*2];
+            nPixelY = anString[iVert*2+1];
+
+            dfX = padfGeoTransform[0] 
+                + nPixelX * padfGeoTransform[1]
+                + nPixelY * padfGeoTransform[2];
+            dfY = padfGeoTransform[3] 
+                + nPixelX * padfGeoTransform[4]
+                + nPixelY * padfGeoTransform[5];
+
+            OGR_G_SetPoint_2D( hRing, iVert, dfX, dfY );
+        }
+
+        OGR_G_AddGeometryDirectly( hPolygon, hRing );
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Create the feature object.                                      */
+/* -------------------------------------------------------------------- */
+    hFeat = OGR_F_Create( OGR_L_GetLayerDefn( hOutLayer ) );
+
+    OGR_F_SetGeometryDirectly( hFeat, hPolygon );
+
+    if( iPixValField >= 0 )
+        OGR_F_SetFieldDouble( hFeat, iPixValField, (double)poRPoly->fPolyValue );
+
+/* -------------------------------------------------------------------- */
+/*      Write the to the layer.                                         */
+/* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
+
+    if( OGR_L_CreateFeature( hOutLayer, hFeat ) != OGRERR_NONE )
+        eErr = CE_Failure;
+
+    OGR_F_Destroy( hFeat );
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          GPMaskImageData()                           */
+/*                                                                      */
+/*      Mask out image pixels to a special nodata value if the mask     */
+/*      band is zero.                                                   */
+/************************************************************************/
+
+static CPLErr 
+GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXSize, 
+                 float *pafImageLine )
+
+{
+    CPLErr eErr;
+
+    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
+                         pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
+    if( eErr == CE_None )
+    {
+        int i;
+        for( i = 0; i < nXSize; i++ )
+        {
+            if( pabyMaskLine[i] == 0 )
+                pafImageLine[i] = GP_NODATA_MARKER;
+        }
+    }
+
+    return eErr;
+}
+#endif // OGR_ENABLED
+
+/************************************************************************/
+/*                           GDALFPolygonize()                           */
+/************************************************************************/
+
+/**
+ * Create polygon coverage from raster data.
+ *
+ * This function creates vector polygons for all connected regions of pixels in
+ * the raster sharing a common pixel value.  Optionally each polygon may be
+ * labelled with the pixel value in an attribute.  Optionally a mask band
+ * can be provided to determine which pixels are eligible for processing.
+ *
+ * The source pixel band values are read into a 32bit float buffer. If you want
+ * to use a (probably faster) version using signed 32bit integer buffer, see
+ * GDALPolygonize() at polygonize.cpp.
+ *
+ * Polygon features will be created on the output layer, with polygon 
+ * geometries representing the polygons.  The polygon geometries will be
+ * in the georeferenced coordinate system of the image (based on the
+ * geotransform of the source dataset).  It is acceptable for the output
+ * layer to already have features.  Note that GDALFPolygonize() does not
+ * set the coordinate system on the output layer.  Application code should
+ * do this when the layer is created, presumably matching the raster 
+ * coordinate system. 
+ *
+ * The algorithm used attempts to minimize memory use so that very large
+ * rasters can be processed.  However, if the raster has many polygons 
+ * or very large/complex polygons, the memory use for holding polygon 
+ * enumerations and active polygon geometries may grow to be quite large. 
+ *
+ * The algorithm will generally produce very dense polygon geometries, with
+ * edges that follow exactly on pixel boundaries for all non-interior pixels.
+ * For non-thematic raster data (such as satellite images) the result will
+ * essentially be one small polygon per pixel, and memory and output layer
+ * sizes will be substantial.  The algorithm is primarily intended for 
+ * relatively simple thematic imagery, masks, and classification results. 
+ * 
+ * @param hSrcBand the source raster band to be processed.
+ * @param hMaskBand an optional mask band.  All pixels in the mask band with a 
+ * value other than zero will be considered suitable for collection as 
+ * polygons.  
+ * @param hOutLayer the vector feature layer to which the polygons should
+ * be written. 
+ * @param iPixValField the attribute field index indicating the feature
+ * attribute into which the pixel value of the polygon should be written.
+ * @param papszOptions a name/value list of additional options
+ * <dl>
+ * <dt>"8CONNECTED":</dt> May be set to "8" to use 8 connectedness.
+ * Otherwise 4 connectedness will be applied to the algorithm
+ * </dl>
+ * @param pfnProgress callback for reporting algorithm progress matching the
+ * GDALProgressFunc() semantics.  May be NULL.
+ * @param pProgressArg callback argument passed to pfnProgress.
+ * 
+ * @return CE_None on success or CE_Failure on a failure.
+ *
+ * @since GDAL 1.9.0
+ */
+
+CPLErr CPL_STDCALL
+GDALFPolygonize( GDALRasterBandH hSrcBand,
+                GDALRasterBandH hMaskBand,
+                OGRLayerH hOutLayer, int iPixValField, 
+                char **papszOptions,
+                GDALProgressFunc pfnProgress, 
+                void * pProgressArg )
+
+{
+#ifndef OGR_ENABLED
+    CPLError(CE_Failure, CPLE_NotSupported, "GDALFPolygonize() unimplemented in a non OGR build");
+    return CE_Failure;
+#else
+    VALIDATE_POINTER1( hSrcBand, "GDALFPolygonize", CE_Failure );
+    VALIDATE_POINTER1( hOutLayer, "GDALFPolygonize", CE_Failure );
+
+    if( pfnProgress == NULL )
+        pfnProgress = GDALDummyProgress;
+
+    int nConnectedness = CSLFetchNameValue( papszOptions, "8CONNECTED" ) ? 8 : 4;
+
+/* -------------------------------------------------------------------- */
+/*      Confirm our output layer will support feature creation.         */
+/* -------------------------------------------------------------------- */
+    if( !OGR_L_TestCapability( hOutLayer, OLCSequentialWrite ) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Output feature layer does not appear to support creation\n"
+                  "of features in GDALFPolygonize()." );
+        return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Allocate working buffers.                                       */
+/* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
+    int nXSize = GDALGetRasterBandXSize( hSrcBand );
+    int nYSize = GDALGetRasterBandYSize( hSrcBand );
+    float *pafLastLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
+    float *pafThisLineVal = (float *) VSIMalloc2(sizeof(float),nXSize + 2);
+    GInt32 *panLastLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
+    GInt32 *panThisLineId =  (GInt32 *) VSIMalloc2(sizeof(GInt32),nXSize + 2);
+    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSIMalloc(nXSize) : NULL;
+    if (pafLastLineVal == NULL || pafThisLineVal == NULL ||
+        panLastLineId == NULL || panThisLineId == NULL ||
+        (hMaskBand != NULL && pabyMaskLine == NULL))
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Could not allocate enough memory for temporary buffers");
+        CPLFree( panThisLineId );
+        CPLFree( panLastLineId );
+        CPLFree( pafThisLineVal );
+        CPLFree( pafLastLineVal );
+        CPLFree( pabyMaskLine );
+        return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get the geotransform, if there is one, so we can convert the    */
+/*      vectors into georeferenced coordinates.                         */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
+    double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
+
+    if( hSrcDS )
+        GDALGetGeoTransform( hSrcDS, adfGeoTransform );
+
+/* -------------------------------------------------------------------- */
+/*      The first pass over the raster is only used to build up the     */
+/*      polygon id map so we will know in advance what polygons are     */
+/*      what on the second pass.                                        */
+/* -------------------------------------------------------------------- */
+    int iY;
+    GDALRasterFPolygonEnumerator oFirstEnum(nConnectedness);
+
+    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
+    {
+        eErr = GDALRasterIO( 
+            hSrcBand,
+            GF_Read, 0, iY, nXSize, 1, 
+            pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );
+        
+        if( eErr == CE_None && hMaskBand != NULL )
+            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
+                    pafThisLineVal );
+
+        if( iY == 0 )
+            oFirstEnum.ProcessLine( 
+                NULL, pafThisLineVal, NULL, panThisLineId, nXSize );
+        else
+            oFirstEnum.ProcessLine(
+                pafLastLineVal, pafThisLineVal,
+                panLastLineId,  panThisLineId, 
+                nXSize );
+
+        // swap lines
+        float * pafTmp = pafLastLineVal;
+        pafLastLineVal = pafThisLineVal;
+        pafThisLineVal = pafTmp;
+
+        GInt32 * panTmp = panThisLineId;
+        panThisLineId = panLastLineId;
+        panLastLineId = panTmp;
+
+/* -------------------------------------------------------------------- */
+/*      Report progress, and support interrupts.                        */
+/* -------------------------------------------------------------------- */
+        if( eErr == CE_None 
+            && !pfnProgress( 0.10 * ((iY+1) / (double) nYSize), 
+                             "", pProgressArg ) )
+        {
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            eErr = CE_Failure;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Make a pass through the maps, ensuring every polygon id         */
+/*      points to the final id it should use, not an intermediate       */
+/*      value.                                                          */
+/* -------------------------------------------------------------------- */
+    oFirstEnum.CompleteMerges();
+
+/* -------------------------------------------------------------------- */
+/*      Initialize ids to -1 to serve as a nodata value for the         */
+/*      previous line, and past the beginning and end of the            */
+/*      scanlines.                                                      */
+/* -------------------------------------------------------------------- */
+    int iX;
+
+    panThisLineId[0] = -1;
+    panThisLineId[nXSize+1] = -1;
+
+    for( iX = 0; iX < nXSize+2; iX++ )
+        panLastLineId[iX] = -1;
+
+/* -------------------------------------------------------------------- */
+/*      We will use a new enumerator for the second pass primariliy     */
+/*      so we can preserve the first pass map.                          */
+/* -------------------------------------------------------------------- */
+    GDALRasterFPolygonEnumerator oSecondEnum(nConnectedness);
+    RPolygonF **papoPoly = (RPolygonF **)
+        CPLCalloc(sizeof(RPolygonF*),oFirstEnum.nNextPolygonId);
+
+/* ==================================================================== */
+/*      Second pass during which we will actually collect polygon       */
+/*      edges as geometries.                                            */
+/* ==================================================================== */
+    for( iY = 0; eErr == CE_None && iY < nYSize+1; iY++ )
+    {
+/* -------------------------------------------------------------------- */
+/*      Read the image data.                                            */
+/* -------------------------------------------------------------------- */
+        if( iY < nYSize )
+        {
+            eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iY, nXSize, 1, 
+                                 pafThisLineVal, nXSize, 1, GDT_Float32, 0, 0 );
+
+            if( eErr == CE_None && hMaskBand != NULL )
+                eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
+                        pafThisLineVal );
+        }
+
+        if( eErr != CE_None )
+            continue;
+
+/* -------------------------------------------------------------------- */
+/*      Determine what polygon the various pixels belong to (redoing    */
+/*      the same thing done in the first pass above).                   */
+/* -------------------------------------------------------------------- */
+        if( iY == nYSize )
+        {
+            for( iX = 0; iX < nXSize+2; iX++ )
+                panThisLineId[iX] = -1;
+        }
+        else if( iY == 0 )
+            oSecondEnum.ProcessLine( 
+                NULL, pafThisLineVal, NULL, panThisLineId+1, nXSize );
+        else
+            oSecondEnum.ProcessLine(
+                pafLastLineVal, pafThisLineVal,
+                panLastLineId+1,  panThisLineId+1, 
+                nXSize );
+
+/* -------------------------------------------------------------------- */
+/*      Add polygon edges to our polygon list for the pixel             */
+/*      boundaries within and above this line.                          */
+/* -------------------------------------------------------------------- */
+        for( iX = 0; iX < nXSize+1; iX++ )
+        {
+            AddEdges( panThisLineId, panLastLineId, 
+                      oFirstEnum.panPolyIdMap, oFirstEnum.pafPolyValue,
+                      papoPoly, iX, iY );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Periodically we scan out polygons and write out those that      */
+/*      haven't been added to on the last line as we can be sure        */
+/*      they are complete.                                              */
+/* -------------------------------------------------------------------- */
+        if( iY % 8 == 7 )
+        {
+            for( iX = 0; 
+                 eErr == CE_None && iX < oSecondEnum.nNextPolygonId; 
+                 iX++ )
+            {
+                if( papoPoly[iX] && papoPoly[iX]->nLastLineUpdated < iY-1 )
+                {
+                    if( hMaskBand == NULL
+                        || !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
+                    {
+                        eErr = 
+                            EmitPolygonToLayer( hOutLayer, iPixValField, 
+                                                papoPoly[iX], adfGeoTransform );
+                    }
+                    delete papoPoly[iX];
+                    papoPoly[iX] = NULL;
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Swap pixel value, and polygon id lines to be ready for the      */
+/*      next line.                                                      */
+/* -------------------------------------------------------------------- */
+        float *pafTmp = pafLastLineVal;
+        pafLastLineVal = pafThisLineVal;
+        pafThisLineVal = pafTmp;
+
+        GInt32 *panTmp = panThisLineId;
+        panThisLineId = panLastLineId;
+        panLastLineId = panTmp;
+
+/* -------------------------------------------------------------------- */
+/*      Report progress, and support interrupts.                        */
+/* -------------------------------------------------------------------- */
+        if( eErr == CE_None 
+            && !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize), 
+                             "", pProgressArg ) )
+        {
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            eErr = CE_Failure;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Make a cleanup pass for all unflushed polygons.                 */
+/* -------------------------------------------------------------------- */
+    for( iX = 0; eErr == CE_None && iX < oSecondEnum.nNextPolygonId; iX++ )
+    {
+        if( papoPoly[iX] )
+        {
+            if( hMaskBand == NULL
+                || !GDALFloatEquals(papoPoly[iX]->fPolyValue, GP_NODATA_MARKER) )
+            {
+                eErr = 
+                    EmitPolygonToLayer( hOutLayer, iPixValField, 
+                                        papoPoly[iX], adfGeoTransform );
+            }
+            delete papoPoly[iX];
+            papoPoly[iX] = NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    CPLFree( panThisLineId );
+    CPLFree( panLastLineId );
+    CPLFree( pafThisLineVal );
+    CPLFree( pafLastLineVal );
+    CPLFree( pabyMaskLine );
+    CPLFree( papoPoly );
+
+    return eErr;
+#endif // OGR_ENABLED
+}
+
diff --git a/alg/gdal_alg.h b/alg/gdal_alg.h
index 5a3742c..8dd323d 100644
--- a/alg/gdal_alg.h
+++ b/alg/gdal_alg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg.h 18227 2009-12-09 13:08:16Z chaitanya $
+ * $Id: gdal_alg.h 22655 2011-07-06 18:29:28Z rouault $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes, and definitions for various GDAL based algorithms.
@@ -90,6 +90,14 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
                 void * pProgressArg );
 
 CPLErr CPL_DLL CPL_STDCALL
+GDALFPolygonize( GDALRasterBandH hSrcBand,
+                GDALRasterBandH hMaskBand,
+                OGRLayerH hOutLayer, int iPixValField,
+                char **papszOptions,
+                GDALProgressFunc pfnProgress,
+                void * pProgressArg );
+
+CPLErr CPL_DLL CPL_STDCALL
 GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
                  GDALRasterBandH hDstBand,
                  int nSizeThreshold, int nConnectedness,
@@ -157,6 +165,12 @@ int CPL_DLL GDALReprojectionTransform(
 void CPL_DLL *
 GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
                           int nReqOrder, int bReversed );
+			  
+/* GCP based transformer with refinement of the GCPs ... forward is to georef coordinates */
+void CPL_DLL *
+GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+                                int nReqOrder, int bReversed, double tolerance, int minimumGcps);
+			  
 void CPL_DLL GDALDestroyGCPTransformer( void *pTransformArg );
 int CPL_DLL GDALGCPTransform( 
     void *pTransformArg, int bDstToSrc, int nPointCount,
diff --git a/alg/gdal_alg_priv.h b/alg/gdal_alg_priv.h
index b2430f0..d45374a 100644
--- a/alg/gdal_alg_priv.h
+++ b/alg/gdal_alg_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg_priv.h 20078 2010-07-16 21:21:29Z rouault $
+ * $Id: gdal_alg_priv.h 22502 2011-06-04 21:33:58Z rouault $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes and definitions for various GDAL based algorithms:
@@ -117,6 +117,42 @@ public:
     void     Clear();
 };
 
+#ifdef OGR_ENABLED
+/************************************************************************/
+/*                          Polygon Enumerator                          */
+/*                                                                      */
+/*              Buffers has float values instead og GInt32              */
+/************************************************************************/
+class GDALRasterFPolygonEnumerator
+
+{
+private:
+    void     MergePolygon( int nSrcId, int nDstId );
+    int      NewPolygon( float fValue );
+
+public:  // these are intended to be readonly.
+
+    GInt32   *panPolyIdMap;
+    float    *pafPolyValue;
+
+    int      nNextPolygonId;
+    int      nPolyAlloc;
+
+    int      nConnectedness;
+
+public:
+             GDALRasterFPolygonEnumerator( int nConnectedness=4 );
+            ~GDALRasterFPolygonEnumerator();
+
+    void     ProcessLine( float *pafLastLineVal, float *pafThisLineVal,
+                          GInt32 *panLastLineId,  GInt32 *panThisLineId,
+                          int nXSize );
+
+    void     CompleteMerges();
+
+    void     Clear();
+};
+#endif
 
 typedef void* (*GDALTransformDeserializeFunc)( CPLXMLNode *psTree );
 
@@ -125,4 +161,18 @@ void* GDALRegisterTransformDeserializer(const char* pszTransformName,
                                        GDALTransformDeserializeFunc pfnDeserializeFunc);
 void GDALUnregisterTransformDeserializer(void* pData);
 
+/************************************************************************/
+/*      Float comparison function.                                      */
+/************************************************************************/
+
+/**
+ * Units in the Last Place. This specifies how big an error we are willing to
+ * accept in terms of the value of the least significant digit of the floating
+ * point number’s representation. MAX_ULPS can also be interpreted in terms of
+ * how many representable floats we are willing to accept between A and B. 
+ */
+#define MAX_ULPS 10
+
+GBool GDALFloatEquals(float A, float B);
+
 #endif /* ndef GDAL_ALG_PRIV_H_INCLUDED */
diff --git a/alg/gdal_crs.c b/alg/gdal_crs.c
index 3fb9a34..7c7faf6 100644
--- a/alg/gdal_crs.c
+++ b/alg/gdal_crs.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_crs.c 16614 2009-03-17 23:46:39Z rouault $
+ * $Id: gdal_crs.c 22670 2011-07-08 17:15:19Z rouault $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implemention of the GDALTransformer wrapper around CRS.C functions
@@ -26,7 +26,9 @@
       Added printout of trnfile. Triggered by BDEBUG.
     Last Update:  1/27/92 Brian J. Buckley
       Fixed bug so that only the active control points were used.
-
+    Last Update:  6/29/2011 C. F. Stallmann & R. van den Dool (South African National Space Agency)
+      GCP refinement added
+      
 
     Copyright (c) 1992, Michigan State University
    
@@ -55,7 +57,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdal_crs.c 16614 2009-03-17 23:46:39Z rouault $");
+CPL_CVSID("$Id: gdal_crs.c 22670 2011-07-08 17:15:19Z rouault $");
 
 #define MAXORDER 3
 
@@ -69,26 +71,6 @@ struct Control_Points
     int *status;
 };
 
-CPL_C_START
-CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg );
-void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
-CPL_C_END
-
-/* crs.c */
-static int CRS_georef(double, double, double *, double *, 
-                              double [], double [], int);
-static int CRS_compute_georef_equations(struct Control_Points *,
-    double [], double [], double [], double [], int);
-
-
-static char *CRS_error_message[] = {
-    "Failed to compute GCP transform: Not enough points available",
-    "Failed to compute GCP transform: Transform is not solvable",
-    "Failed to compute GCP transform: Not enough memory"
-    "Failed to compute GCP transform: Parameter error",
-    "Failed to compute GCP transform: Internal error"
-};
-
 typedef struct
 {
     GDALTransformerInfo sTI;
@@ -104,9 +86,32 @@ typedef struct
 
     int       nGCPCount;
     GDAL_GCP *pasGCPList;
+    int    bRefine;
+    int    nMinimumGcps;
+    double dfTolerance;
     
 } GCPTransformInfo;
 
+CPL_C_START
+CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg );
+void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
+CPL_C_END
+
+/* crs.c */
+static int CRS_georef(double, double, double *, double *, 
+                              double [], double [], int);
+static int CRS_compute_georef_equations(struct Control_Points *,
+    double [], double [], double [], double [], int);
+static int remove_outliers(GCPTransformInfo *);
+
+static char *CRS_error_message[] = {
+    "Failed to compute GCP transform: Not enough points available",
+    "Failed to compute GCP transform: Transform is not solvable",
+    "Failed to compute GCP transform: Not enough memory",
+    "Failed to compute GCP transform: Parameter error",
+    "Failed to compute GCP transform: Internal error"
+};
+
 
 /************************************************************************/
 /*                      GDALCreateGCPTransformer()                      */
@@ -139,8 +144,8 @@ typedef struct
  * @return the transform argument or NULL if creation fails. 
  */
 
-void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
-                                int nReqOrder, int bReversed )
+void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList, 
+                                int nReqOrder, int bReversed, int bRefine, double dfTolerance, int nMinimumGcps)
 
 {
     GCPTransformInfo *psInfo;
@@ -162,6 +167,9 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     psInfo = (GCPTransformInfo *) CPLCalloc(sizeof(GCPTransformInfo),1);
     psInfo->bReversed = bReversed;
     psInfo->nOrder = nReqOrder;
+    psInfo->bRefine = bRefine;
+    psInfo->dfTolerance = dfTolerance;
+    psInfo->nMinimumGcps = nMinimumGcps;
 
     psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
     psInfo->nGCPCount = nGCPCount;
@@ -171,45 +179,51 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     psInfo->sTI.pfnTransform = GDALGCPTransform;
     psInfo->sTI.pfnCleanup = GDALDestroyGCPTransformer;
     psInfo->sTI.pfnSerialize = GDALSerializeGCPTransformer;
-
+    
 /* -------------------------------------------------------------------- */
-/*      Allocate and initialize the working points list.                */
+/*      Compute the forward and reverse polynomials.                    */
 /* -------------------------------------------------------------------- */
-    padfGeoX = (double *) CPLCalloc(sizeof(double),nGCPCount);
-    padfGeoY = (double *) CPLCalloc(sizeof(double),nGCPCount);
-    padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
-    padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
-    panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
-    
-    for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
+
+    if(bRefine)
     {
-        panStatus[iGCP] = 1;
-        padfGeoX[iGCP] = pasGCPList[iGCP].dfGCPX;
-        padfGeoY[iGCP] = pasGCPList[iGCP].dfGCPY;
-        padfRasterX[iGCP] = pasGCPList[iGCP].dfGCPPixel;
-        padfRasterY[iGCP] = pasGCPList[iGCP].dfGCPLine;
+        nCRSresult = remove_outliers(psInfo);
     }
-
-    sPoints.count = nGCPCount;
-    sPoints.e1 = padfRasterX;
-    sPoints.n1 = padfRasterY;
-    sPoints.e2 = padfGeoX;
-    sPoints.n2 = padfGeoY;
-    sPoints.status = panStatus;
+    else
+    {
+        /* -------------------------------------------------------------------- */
+        /*      Allocate and initialize the working points list.                */
+        /* -------------------------------------------------------------------- */
+        padfGeoX = (double *) CPLCalloc(sizeof(double),nGCPCount);
+        padfGeoY = (double *) CPLCalloc(sizeof(double),nGCPCount);
+        padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
+        padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
+        panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
     
-/* -------------------------------------------------------------------- */
-/*      Compute the forward and reverse polynomials.                    */
-/* -------------------------------------------------------------------- */
-    nCRSresult = CRS_compute_georef_equations( &sPoints,
-                                      psInfo->adfToGeoX, psInfo->adfToGeoY,
-                                      psInfo->adfFromGeoX, psInfo->adfFromGeoY,
-                                      nReqOrder );
+        for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
+        {
+            panStatus[iGCP] = 1;
+            padfGeoX[iGCP] = pasGCPList[iGCP].dfGCPX;
+            padfGeoY[iGCP] = pasGCPList[iGCP].dfGCPY;
+            padfRasterX[iGCP] = pasGCPList[iGCP].dfGCPPixel;
+            padfRasterY[iGCP] = pasGCPList[iGCP].dfGCPLine;
+        }
 
-    CPLFree( padfGeoX );
-    CPLFree( padfGeoY );
-    CPLFree( padfRasterX );
-    CPLFree( padfRasterY );
-    CPLFree( panStatus );
+        sPoints.count = nGCPCount;
+        sPoints.e1 = padfRasterX;
+        sPoints.n1 = padfRasterY;
+        sPoints.e2 = padfGeoX;
+        sPoints.n2 = padfGeoY;
+        sPoints.status = panStatus;
+        nCRSresult = CRS_compute_georef_equations( &sPoints,
+                                                psInfo->adfToGeoX, psInfo->adfToGeoY,
+                                                psInfo->adfFromGeoX, psInfo->adfFromGeoY,
+                                                nReqOrder );
+        CPLFree( padfGeoX );
+        CPLFree( padfGeoY );
+        CPLFree( padfRasterX );
+        CPLFree( padfRasterY );
+        CPLFree( panStatus );
+    }
 
     if (nCRSresult != 1)
     {
@@ -223,6 +237,26 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     }
 }
 
+void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+                                int nReqOrder, int bReversed )
+
+{
+    return GDALCreateGCPTransformerEx(nGCPCount, pasGCPList, nReqOrder, bReversed, FALSE, -1, -1);
+}
+
+void *GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
+                                int nReqOrder, int bReversed, double dfTolerance, int nMinimumGcps)
+
+{
+    //If no minimumGcp parameter was passed, we  use the default value according to the model
+    if(nMinimumGcps == -1)
+    {
+        nMinimumGcps = ((nReqOrder+1) * (nReqOrder+2)) / 2 + 1;
+    }
+    return GDALCreateGCPTransformerEx(nGCPCount, pasGCPList, nReqOrder, bReversed, TRUE, dfTolerance, nMinimumGcps);
+}
+
+
 /************************************************************************/
 /*                     GDALDestroyGCPTransformer()                      */
 /************************************************************************/
@@ -337,6 +371,21 @@ CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
     CPLCreateXMLElementAndValue( 
         psTree, "Reversed", 
         CPLSPrintf( "%d", psInfo->bReversed ) );
+
+    if( psInfo->bRefine )
+    {
+        CPLCreateXMLElementAndValue(
+            psTree, "Refine",
+            CPLSPrintf( "%d", psInfo->bRefine ) );
+
+        CPLCreateXMLElementAndValue(
+            psTree, "MinimumGcps",
+            CPLSPrintf( "%d", psInfo->nMinimumGcps ) );
+
+        CPLCreateXMLElementAndValue(
+            psTree, "Tolerance",
+            CPLSPrintf( "%f", psInfo->dfTolerance ) );
+    }
                                  
 /* -------------------------------------------------------------------- */
 /*	Attach GCP List. 						*/
@@ -347,6 +396,11 @@ CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
         CPLXMLNode *psGCPList = CPLCreateXMLNode( psTree, CXT_Element, 
                                                   "GCPList" );
 
+	if(psInfo->bRefine)
+	{
+	  remove_outliers(psInfo);
+	}
+	
         for( iGCP = 0; iGCP < psInfo->nGCPCount; iGCP++ )
         {
             CPLXMLNode *psXMLGCP;
@@ -392,6 +446,9 @@ void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree )
     void *pResult;
     int nReqOrder;
     int bReversed;
+    int bRefine;
+    int nMinimumGcps;
+    double dfTolerance;
 
     /* -------------------------------------------------------------------- */
     /*      Check for GCPs.                                                 */
@@ -442,12 +499,23 @@ void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
     nReqOrder = atoi(CPLGetXMLValue(psTree,"Order","3"));
     bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
+    bRefine = atoi(CPLGetXMLValue(psTree,"Refine","0"));
+    nMinimumGcps = atoi(CPLGetXMLValue(psTree,"MinimumGcps","6"));
+    dfTolerance = atof(CPLGetXMLValue(psTree,"Tolerance","1.0"));
 
 /* -------------------------------------------------------------------- */
 /*      Generate transformation.                                        */
 /* -------------------------------------------------------------------- */
-    pResult = GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, 
+    if(bRefine)
+    {
+        pResult = GDALCreateGCPRefineTransformer( nGCPCount, pasGCPList, nReqOrder, 
+                                        bReversed, dfTolerance, nMinimumGcps );
+    }
+    else
+    {
+        pResult = GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, 
                                         bReversed );
+    }
     
 /* -------------------------------------------------------------------- */
 /*      Cleanup GCP copy.                                               */
@@ -914,3 +982,181 @@ static int solvemat (struct MATRIX *m,
 
     return(MSUCCESS);
 }
+
+/***************************************************************************/
+/*
+  DETECTS THE WORST OUTLIER IN THE GCP LIST AND RETURNS THE INDEX OF THE
+  OUTLIER.
+  
+  THE WORST OUTLIER IS CALCULATED BASED ON THE CONTROL POINTS, COEFFICIENTS
+  AND THE ALLOWED TOLERANCE:
+  
+  sampleAdj = a0 + a1*sample + a2*line + a3*line*sample
+  lineAdj = b0 + b1*sample + b2*line + b3*line*sample
+  
+  WHERE sampleAdj AND lineAdj ARE CORRELATED GCPS
+  
+  [residualSample] = [A1][sampleCoefficients] - [b1]
+  [residualLine] = [A2][lineCoefficients] - [b2]
+  
+  sampleResidual^2 = sum( [residualSample]^2 )
+  lineResidual^2 = sum( [lineSample]^2 )
+  
+  residuals(i) = squareRoot( residualSample(i)^2 + residualLine(i)^2 )
+  
+  THE GCP WITH THE GREATEST DISTANCE residual(i) GREATER THAN THE TOLERANCE WILL
+  CONSIDERED THE WORST OUTLIER.
+  
+  IF NO OUTLIER CAN BE FOUND, -1 WILL BE RETURNED.
+*/
+/***************************************************************************/
+static int worst_outlier(struct Control_Points *cp, double E[], double N[], double dfTolerance)
+{
+    double *padfResiduals;
+    int nI, nIndex;
+    double dfDifference, dfSampleResidual, dfLineResidual, dfSampleRes, dfLineRes, dfCurrentDifference;
+    double dfE1, dfN1, dfE2, dfN2, dfEn;
+  
+    padfResiduals = (double *) CPLCalloc(sizeof(double),cp->count);
+    dfSampleResidual = 0.0;
+    dfLineResidual = 0.0;
+  
+    for(nI = 0; nI < cp->count; nI++)
+    {
+        dfE1 = cp->e1[nI];
+        dfN1 = cp->n1[nI];
+        dfE2 = dfE1 * dfE1;
+        dfN2 = dfN1 * dfN1;
+        dfEn = dfE1 * dfN1;
+
+        dfSampleRes = E[0] + E[1] * dfE1 + E[2] * dfN1 + E[3] * dfE2 + E[4] * dfEn + E[5] * dfN2 - cp->e2[nI];
+        dfLineRes = N[0] + N[1] * dfE1 + N[2] * dfN1 + N[3] * dfE2 + N[4] * dfEn + N[5] * dfN2 - cp->n2[nI];
+    
+        dfSampleResidual += dfSampleRes*dfSampleRes;
+        dfLineResidual += dfLineRes*dfLineRes;
+    
+        padfResiduals[nI] = sqrt(dfSampleRes*dfSampleRes + dfLineRes*dfLineRes);
+    }
+  
+    nIndex = -1;
+    dfDifference = -1.0;
+    for(nI = 0; nI < cp->count; nI++)
+    {
+        dfCurrentDifference = padfResiduals[nI];
+        if(fabs(dfCurrentDifference) < 1.19209290E-07F /*FLT_EPSILON*/)
+        {
+            dfCurrentDifference = 0.0;
+        }
+        if(dfCurrentDifference > dfDifference && dfCurrentDifference >= dfTolerance)
+        {
+            dfDifference = dfCurrentDifference;
+            nIndex = nI;
+        }
+    }
+    CPLFree( padfResiduals );
+    return nIndex;
+}
+
+/***************************************************************************/
+/*
+  REMOVES THE WORST OUTLIERS ITERATIVELY UNTIL THE MINIMUM NUMBER OF GCPS
+  ARE REACHED OR NO OUTLIERS CAN BE DETECTED.
+  
+  1. WE CALCULATE THE COEFFICIENTS FOR ALL THE GCPS.
+  2. THE GCP LIST WILL BE SCANED TO DETERMINE THE WORST OUTLIER USING
+     THE CALCULATED COEFFICIENTS.
+  3. THE WORST OUTLIER WILL BE REMOVED FROM THE GCP LIST.
+  4. THE COEFFICIENTS WILL BE RECALCULATED WITHOUT THE WORST OUTLIER.
+  5. STEP 1 TO 4 ARE EXECUTED UNTIL THE MINIMUM NUMBER OF GCPS WERE REACHED
+     OR IF NO GCP IS CONSIDERED AN OUTLIER WITH THE PASSED TOLERANCE.
+*/
+/***************************************************************************/
+static int remove_outliers( GCPTransformInfo *psInfo )
+{
+    double *padfGeoX, *padfGeoY, *padfRasterX, *padfRasterY;
+    int *panStatus;
+    int nI, nCRSresult, nGCPCount, nMinimumGcps, nReqOrder;
+    double dfTolerance;
+    struct Control_Points sPoints;
+    
+    nGCPCount = psInfo->nGCPCount;
+    nMinimumGcps = psInfo->nMinimumGcps;
+    nReqOrder = psInfo->nOrder;
+    dfTolerance = psInfo->dfTolerance;
+    
+    padfGeoX = (double *) CPLCalloc(sizeof(double),nGCPCount);
+    padfGeoY = (double *) CPLCalloc(sizeof(double),nGCPCount);
+    padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
+    padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
+    panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
+    
+    for( nI = 0; nI < nGCPCount; nI++ )
+    {
+        panStatus[nI] = 1;
+        padfGeoX[nI] = psInfo->pasGCPList[nI].dfGCPX;
+        padfGeoY[nI] = psInfo->pasGCPList[nI].dfGCPY;
+        padfRasterX[nI] = psInfo->pasGCPList[nI].dfGCPPixel;
+        padfRasterY[nI] = psInfo->pasGCPList[nI].dfGCPLine;
+    }
+
+    sPoints.count = nGCPCount;
+    sPoints.e1 = padfRasterX;
+    sPoints.n1 = padfRasterY;
+    sPoints.e2 = padfGeoX;
+    sPoints.n2 = padfGeoY;
+    sPoints.status = panStatus;
+  
+    nCRSresult = CRS_compute_georef_equations( &sPoints,
+                                      psInfo->adfToGeoX, psInfo->adfToGeoY,
+                                      psInfo->adfFromGeoX, psInfo->adfFromGeoY,
+                                      nReqOrder );
+
+    while(sPoints.count > nMinimumGcps)
+    {
+        int nIndex;
+
+        nIndex = worst_outlier(&sPoints, psInfo->adfFromGeoX, psInfo->adfFromGeoY, dfTolerance);
+
+        //If no outliers were detected, stop the GCP elimination
+        if(nIndex == -1)
+        {
+            break;
+        }
+
+        CPLFree(psInfo->pasGCPList[nIndex].pszId);
+        CPLFree(psInfo->pasGCPList[nIndex].pszInfo);
+
+        for( nI = nIndex; nI < sPoints.count - 1; nI++ )
+        {
+            sPoints.e1[nI] = sPoints.e1[nI + 1];
+            sPoints.n1[nI] = sPoints.n1[nI + 1];
+            sPoints.e2[nI] = sPoints.e2[nI + 1];
+            sPoints.n2[nI] = sPoints.n2[nI + 1];
+            psInfo->pasGCPList[nI].pszId = psInfo->pasGCPList[nI + 1].pszId;
+            psInfo->pasGCPList[nI].pszInfo = psInfo->pasGCPList[nI + 1].pszInfo;
+        }
+
+        sPoints.count = sPoints.count - 1;
+
+        nCRSresult = CRS_compute_georef_equations( &sPoints,
+                                      psInfo->adfToGeoX, psInfo->adfToGeoY,
+                                      psInfo->adfFromGeoX, psInfo->adfFromGeoY,
+                                      nReqOrder );
+    }
+
+    for( nI = 0; nI < sPoints.count; nI++ )
+    {
+        psInfo->pasGCPList[nI].dfGCPX = sPoints.e2[nI];
+        psInfo->pasGCPList[nI].dfGCPY = sPoints.n2[nI];
+        psInfo->pasGCPList[nI].dfGCPPixel = sPoints.e1[nI];
+        psInfo->pasGCPList[nI].dfGCPLine = sPoints.n1[nI];
+    }
+    psInfo->nGCPCount = sPoints.count;
+    
+    CPLFree( sPoints.e1 );
+    CPLFree( sPoints.n1 );
+    CPLFree( sPoints.e2 );
+    CPLFree( sPoints.n2 );
+    CPLFree( sPoints.status );
+    return nCRSresult;
+}
diff --git a/alg/gdal_nrgcrs.c b/alg/gdal_nrgcrs.c
index e27051d..c5c759e 100644
--- a/alg/gdal_nrgcrs.c
+++ b/alg/gdal_nrgcrs.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_nrgcrs.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gdal_nrgcrs.c 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implemention of the GDALTransformer wrapper around CRS.C functions
@@ -77,6 +77,7 @@ typedef struct
  * @param nGCPCount the number of GCPs in pasGCPList.
  * @param pasGCPList an array of GCPs to be used as input.
  * @param nReqOrder the requested polynomial order.  It should be 1, 2 or 3.
+ * @param bReversed set it to TRUE to compute the reversed transformation.
  * 
  * @return the transform argument or NULL if creation fails. 
  */
diff --git a/alg/gdal_rpc.cpp b/alg/gdal_rpc.cpp
index b5efa97..2f10160 100644
--- a/alg/gdal_rpc.cpp
+++ b/alg/gdal_rpc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rpc.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: gdal_rpc.cpp 22903 2011-08-07 22:20:48Z rouault $
  *
  * Project:  Image Warper
  * Purpose:  Implements a rational polynomail (RPC) based transformer. 
@@ -32,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: gdal_rpc.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: gdal_rpc.cpp 22903 2011-08-07 22:20:48Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg );
@@ -856,7 +856,8 @@ void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree )
 
     psMetadata = CPLGetXMLNode( psTree, "Metadata" );
 
-    if( psMetadata->eType != CXT_Element
+    if( psMetadata == NULL
+        || psMetadata->eType != CXT_Element
         || !EQUAL(psMetadata->pszValue,"Metadata") )
         return NULL;
     
diff --git a/alg/gdal_tps.cpp b/alg/gdal_tps.cpp
index b12da62..4327335 100644
--- a/alg/gdal_tps.cpp
+++ b/alg/gdal_tps.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_tps.cpp 16861 2009-04-26 19:22:29Z rouault $
+ * $Id: gdal_tps.cpp 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Thin Plate Spline transformer (GDAL wrapper portion)
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdal_tps.cpp 16861 2009-04-26 19:22:29Z rouault $");
+CPL_CVSID("$Id: gdal_tps.cpp 23156 2011-10-01 15:34:16Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg );
@@ -81,7 +81,7 @@ typedef struct
  *
  * @param nGCPCount the number of GCPs in pasGCPList.
  * @param pasGCPList an array of GCPs to be used as input.
- * @Param bReversed 
+ * @param bReversed set it to TRUE to compute the reversed transformation.
  * 
  * @return the transform argument or NULL if creation fails. 
  */
diff --git a/alg/gdalcutline.cpp b/alg/gdalcutline.cpp
index 40d59c9..4c12762 100644
--- a/alg/gdalcutline.cpp
+++ b/alg/gdalcutline.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalcutline.cpp 17041 2009-05-17 22:35:15Z warmerdam $
+ * $Id: gdalcutline.cpp 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implement cutline/blend mask generator.
@@ -34,7 +34,7 @@
 #include "ogr_geometry.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalcutline.cpp 17041 2009-05-17 22:35:15Z warmerdam $");
+CPL_CVSID("$Id: gdalcutline.cpp 23033 2011-09-03 18:46:11Z rouault $");
 
 /************************************************************************/
 /*                         BlendMaskGenerator()                         */
@@ -174,7 +174,7 @@ BlendMaskGenerator( int nXOff, int nYOff, int nXSize, int nYSize,
                 dfRatio = 0.5 + (dfDist / dfBlendDist) * 0.5;
             }                
 
-            pafValidityMask[iX + iY * nXSize] *= dfRatio;
+            pafValidityMask[iX + iY * nXSize] *= (float)dfRatio;
         }
     }
 
diff --git a/alg/gdalgrid.cpp b/alg/gdalgrid.cpp
index bc01d07..5832929 100644
--- a/alg/gdalgrid.cpp
+++ b/alg/gdalgrid.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: gdalgrid.cpp 22889 2011-08-07 13:07:14Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -30,11 +30,21 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 #include "gdalgrid.h"
+#include <float.h>
+#include <limits.h>
 
-CPL_CVSID("$Id: gdalgrid.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: gdalgrid.cpp 22889 2011-08-07 13:07:14Z rouault $");
 
 #define TO_RADIANS (3.14159265358979323846 / 180.0)
 
+#ifndef DBL_MAX
+# ifdef __DBL_MAX__
+#  define DBL_MAX __DBL_MAX__
+# else
+#  define DBL_MAX 1.7976931348623157E+308
+# endif /* __DBL_MAX__ */
+#endif /* DBL_MAX */
+
 /************************************************************************/
 /*                   GDALGridInverseDistanceToAPower()                  */
 /************************************************************************/
@@ -409,8 +419,7 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
         ((GDALGridNearestNeighborOptions *)poOptions)->dfNoDataValue;
     // Nearest distance will be initialized with the distance to the first
     // point in array.
-    double      dfNearestR = (padfX[0] - dfXPoint) * (padfX[0] - dfXPoint)
-        + (padfY[0] - dfYPoint) * (padfY[0] - dfYPoint);
+    double      dfNearestR = DBL_MAX;
     GUInt32 i = 0;
 
     while ( i < nPoints )
@@ -1131,7 +1140,7 @@ GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
 /**
  * Create regular grid from the scattered data.
  *
- * This fucntion takes the arrays of X and Y coordinates and corresponding Z
+ * This function takes the arrays of X and Y coordinates and corresponding Z
  * values as input and computes regular grid (or call it a raster) from these
  * scattered data. You should supply geometry and extent of the output grid
  * and allocate array sufficient to hold such a grid.
@@ -1296,6 +1305,11 @@ CPLErr ParseAlgorithmAndOptions( const char *pszAlgoritm,
                                  GDALGridAlgorithm *peAlgorithm,
                                  void **ppOptions )
 {
+    CPLAssert( pszAlgoritm );
+    CPLAssert( peAlgorithm );
+    CPLAssert( ppOptions );
+
+    *ppOptions = NULL;
 
     char **papszParms = CSLTokenizeString2( pszAlgoritm, ":", FALSE );
 
diff --git a/alg/gdalrasterfpolygonenumerator.cpp b/alg/gdalrasterfpolygonenumerator.cpp
new file mode 100644
index 0000000..3b2325f
--- /dev/null
+++ b/alg/gdalrasterfpolygonenumerator.cpp
@@ -0,0 +1,227 @@
+/******************************************************************************
+ * $Id: gdalrasterfpolygonenumerator.cpp 22502 2011-06-04 21:33:58Z rouault $
+ *
+ * Project:  GDAL
+ * Purpose:  Version of Raster Polygon Enumerator using float buffers.
+ * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com. Most of the code
+ * taken from GDALRasterFPolygonEnumerator, by Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Jorge Arevalo
+ * Copyright (c) 2008, Frank Warmerdam
+ *
+ * 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_alg_priv.h"
+#include "cpl_conv.h"
+#include <vector>
+
+CPL_CVSID("$Id: gdalrasterfpolygonenumerator.cpp 22502 2011-06-04 21:33:58Z rouault $");
+
+#ifdef OGR_ENABLED
+/************************************************************************/
+/*                    GDALRasterFPolygonEnumerator()                     */
+/************************************************************************/
+
+GDALRasterFPolygonEnumerator::GDALRasterFPolygonEnumerator(
+    int nConnectedness )
+
+{
+    panPolyIdMap = NULL;
+    pafPolyValue = NULL;
+    nNextPolygonId = 0;
+    nPolyAlloc = 0;
+    this->nConnectedness = nConnectedness;
+    CPLAssert( nConnectedness == 4 || nConnectedness == 8 );
+}
+
+/************************************************************************/
+/*                    ~GDALRasterFPolygonEnumerator()                    */
+/************************************************************************/
+
+GDALRasterFPolygonEnumerator::~GDALRasterFPolygonEnumerator()
+
+{
+    Clear();
+}
+
+/************************************************************************/
+/*                               Clear()                                */
+/************************************************************************/
+
+void GDALRasterFPolygonEnumerator::Clear()
+
+{
+    CPLFree( panPolyIdMap );
+    CPLFree( pafPolyValue );
+    
+    panPolyIdMap = NULL;
+    pafPolyValue = NULL;
+    
+    nNextPolygonId = 0;
+    nPolyAlloc = 0;
+}
+
+/************************************************************************/
+/*                            MergePolygon()                            */
+/*                                                                      */
+/*      Update the polygon map to indicate the merger of two polygons.  */
+/************************************************************************/
+
+void GDALRasterFPolygonEnumerator::MergePolygon( int nSrcId, int nDstId )
+
+{
+    while( panPolyIdMap[nDstId] != nDstId )
+        nDstId = panPolyIdMap[nDstId];
+
+    while( panPolyIdMap[nSrcId] != nSrcId )
+        nSrcId = panPolyIdMap[nSrcId];
+
+    if( nSrcId == nDstId )
+        return;
+
+    panPolyIdMap[nSrcId] = nDstId;
+}
+
+/************************************************************************/
+/*                             NewPolygon()                             */
+/*                                                                      */
+/*      Allocate a new polygon id, and reallocate the polygon maps      */
+/*      if needed.                                                      */
+/************************************************************************/
+
+int GDALRasterFPolygonEnumerator::NewPolygon( float fValue )
+
+{
+    int nPolyId = nNextPolygonId;
+
+    if( nNextPolygonId >= nPolyAlloc )
+    {
+        nPolyAlloc = nPolyAlloc * 2 + 20;
+        panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*4);
+        pafPolyValue = (float *) CPLRealloc(pafPolyValue,nPolyAlloc*4);
+    }
+
+    nNextPolygonId++;
+
+    panPolyIdMap[nPolyId] = nPolyId;
+    pafPolyValue[nPolyId] = fValue;
+
+    return nPolyId;
+}
+
+/************************************************************************/
+/*                           CompleteMerges()                           */
+/*                                                                      */
+/*      Make a pass through the maps, ensuring every polygon id         */
+/*      points to the final id it should use, not an intermediate       */
+/*      value.                                                          */
+/************************************************************************/
+
+void GDALRasterFPolygonEnumerator::CompleteMerges()
+
+{
+    int iPoly;
+    int nFinalPolyCount = 0;
+
+    for( iPoly = 0; iPoly < nNextPolygonId; iPoly++ )
+    {
+        while( panPolyIdMap[iPoly] 
+               != panPolyIdMap[panPolyIdMap[iPoly]] )
+            panPolyIdMap[iPoly] = panPolyIdMap[panPolyIdMap[iPoly]];
+
+        if( panPolyIdMap[iPoly] == iPoly )
+            nFinalPolyCount++;
+    }
+
+    CPLDebug( "GDALRasterFPolygonEnumerator",
+              "Counted %d polygon fragments forming %d final polygons.", 
+              nNextPolygonId, nFinalPolyCount );
+}
+
+/************************************************************************/
+/*                            ProcessLine()                             */
+/*                                                                      */
+/*      Assign ids to polygons, one line at a time.                     */
+/************************************************************************/
+
+void GDALRasterFPolygonEnumerator::ProcessLine(
+    float *pafLastLineVal, float *pafThisLineVal,
+    GInt32 *panLastLineId,  GInt32 *panThisLineId,
+    int nXSize )
+
+{
+    int i;
+
+/* -------------------------------------------------------------------- */
+/*      Special case for the first line.                                */
+/* -------------------------------------------------------------------- */
+    if( pafLastLineVal == NULL )
+    {
+        for( i=0; i < nXSize; i++ )
+        {
+            if( i == 0 || !GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
+            {
+                panThisLineId[i] = NewPolygon( pafThisLineVal[i] );
+            }
+            else
+                panThisLineId[i] = panThisLineId[i-1];
+        }        
+        
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process each pixel comparing to the previous pixel, and to      */
+/*      the last line.                                                  */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < nXSize; i++ )
+    {
+        if( i > 0 && GDALFloatEquals(pafThisLineVal[i], pafThisLineVal[i-1]) )
+        {
+            panThisLineId[i] = panThisLineId[i-1];        
+
+            if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i])
+                && (panPolyIdMap[panLastLineId[i]]
+                    != panPolyIdMap[panThisLineId[i]]) )
+            {
+                MergePolygon( panLastLineId[i], panThisLineId[i] );
+            }
+        }
+        else if( GDALFloatEquals(pafLastLineVal[i], pafThisLineVal[i]) )
+        {
+            panThisLineId[i] = panLastLineId[i];
+        }
+        else if( i > 0 && nConnectedness == 8 
+                 && GDALFloatEquals(pafLastLineVal[i-1], pafThisLineVal[i]) )
+        {
+            panThisLineId[i] = panLastLineId[i-1];
+        }
+        else if( i < nXSize-1 && nConnectedness == 8 
+                 && GDALFloatEquals(pafLastLineVal[i+1], pafThisLineVal[i]) )
+        {
+            panThisLineId[i] = panLastLineId[i+1];
+        }
+        else
+            panThisLineId[i] = 
+                NewPolygon( pafThisLineVal[i] );
+    }
+}
+#endif
diff --git a/alg/gdalrasterize.cpp b/alg/gdalrasterize.cpp
index 54a47c6..65e2b6f 100644
--- a/alg/gdalrasterize.cpp
+++ b/alg/gdalrasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterize.cpp 21236 2010-12-11 17:28:32Z rouault $
+ * $Id: gdalrasterize.cpp 23250 2011-10-18 19:05:02Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Vector rasterization.
@@ -81,25 +81,27 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
             memset( pabyInsert, nBurnValue, nXEnd - nXStart + 1 );
         }
     }
-    else
+    else if( psInfo->eType == GDT_Float64 )
     {
         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
             int	nPixels = nXEnd - nXStart + 1;
-            float   *pafInsert;
-            float   fBurnValue = (float)
+            double   *padfInsert;
+            double   dfBurnValue = 
                 ( psInfo->padfBurnValue[iBand] +
                   ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                              0 : dfVariant ) );
             
-            pafInsert = ((float *) psInfo->pabyChunkBuf) 
+            padfInsert = ((double *) psInfo->pabyChunkBuf)
                 + iBand * psInfo->nXSize * psInfo->nYSize
                 + nY * psInfo->nXSize + nXStart;
 
             while( nPixels-- > 0 )
-                *(pafInsert++) = fBurnValue;
+                *(padfInsert++) = dfBurnValue;
         }
     }
+    else
+        CPLAssert(0);
 }
 
 /************************************************************************/
@@ -128,19 +130,21 @@ void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
                              0 : dfVariant ) );
         }
     }
-    else
+    else if( psInfo->eType == GDT_Float64 )
     {
         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
-            float   *pfInsert = ((float *) psInfo->pabyChunkBuf) 
+            double   *pdfInsert = ((double *) psInfo->pabyChunkBuf)
                                 + iBand * psInfo->nXSize * psInfo->nYSize
                                 + nY * psInfo->nXSize + nX;
 
-            *pfInsert = (float)( psInfo->padfBurnValue[iBand] +
+            *pdfInsert = ( psInfo->padfBurnValue[iBand] +
                          ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                             0 : dfVariant ) );
         }
     }
+    else
+        CPLAssert(0);
 }
 
 /************************************************************************/
@@ -450,7 +454,7 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
  * @param pfnTransformer transformation to apply to geometries to put into 
  * pixel/line coordinates on raster.  If NULL a geotransform based one will
  * be created internally.
- * @param pTransformerArg callback data for transformer.
+ * @param pTransformArg callback data for transformer.
  * @param padfGeomBurnValue the array of values to burn into the raster.  
  * There should be nBandCount values for each geometry. 
  * @param papszOptions special options controlling rasterization
@@ -540,7 +544,7 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
     if( poBand->GetRasterDataType() == GDT_Byte )
         eType = GDT_Byte;
     else
-        eType = GDT_Float32;
+        eType = GDT_Float64;
 
     nScanlineBytes = nBandCount * poDS->GetRasterXSize()
         * (GDALGetDataTypeSize(eType)/8);
@@ -649,10 +653,10 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
  * @param pfnTransformer transformation to apply to geometries to put into 
  * pixel/line coordinates on raster.  If NULL a geotransform based one will
  * be created internally.
- * @param pTransformerArg callback data for transformer.
+ * @param pTransformArg callback data for transformer.
  * @param padfLayerBurnValues the array of values to burn into the raster.  
  * There should be nBandCount values for each layer. 
- * @param papszOption special options controlling rasterization:
+ * @param papszOptions special options controlling rasterization:
  * <dl>
  * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
  * used for a burn in value. The value will be burned into all output
@@ -735,7 +739,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
     if( poBand->GetRasterDataType() == GDT_Byte )
         eType = GDT_Byte;
     else
-        eType = GDT_Float32;
+        eType = GDT_Float64;
 
     nScanlineBytes = nBandCount * poDS->GetRasterXSize()
         * (GDALGetDataTypeSize(eType)/8);
@@ -1021,11 +1025,11 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  * pixel/line coordinates on raster.  If NULL a geotransform based one will
  * be created internally.
  *
- * @param pTransformerArg callback data for transformer.
+ * @param pTransformArg callback data for transformer.
  *
  * @param dfBurnValue the value to burn into the raster.  
  *
- * @param papszOption special options controlling rasterization:
+ * @param papszOptions special options controlling rasterization:
  * <dl>
  * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
  * used for a burn in value. The value will be burned into all output
diff --git a/alg/gdalsievefilter.cpp b/alg/gdalsievefilter.cpp
index 08da349..c8ea707 100644
--- a/alg/gdalsievefilter.cpp
+++ b/alg/gdalsievefilter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalsievefilter.cpp 21213 2010-12-08 16:43:11Z warmerdam $
+ * $Id: gdalsievefilter.cpp 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdalsievefilter.cpp 21213 2010-12-08 16:43:11Z warmerdam $");
+CPL_CVSID("$Id: gdalsievefilter.cpp 23156 2011-10-01 15:34:16Z rouault $");
 
 #define GP_NODATA_MARKER -51502112
 #define MY_MAX_INT 2147483647
@@ -169,7 +169,7 @@ static inline void CompareNeighbour( int nPolyId1, int nPolyId2,
  * @param nConnectedness either 4 indicating that diagonal pixels are not
  * considered directly adjacent for polygon membership purposes or 8
  * indicating they are. 
- * @param papszOption algorithm options in name=value list form.  None currently
+ * @param papszOptions algorithm options in name=value list form.  None currently
  * supported.
  * @param pfnProgress callback for reporting algorithm progress matching the
  * GDALProgressFunc() semantics.  May be NULL.
diff --git a/alg/gdaltransformer.cpp b/alg/gdaltransformer.cpp
index bede63a..4335e2d 100644
--- a/alg/gdaltransformer.cpp
+++ b/alg/gdaltransformer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaltransformer.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: gdaltransformer.cpp 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implementation of one or more GDALTrasformerFunc types, including
@@ -37,7 +37,7 @@
 #include "cpl_list.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdaltransformer.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: gdaltransformer.cpp 23156 2011-10-01 15:34:16Z rouault $");
 CPL_C_START
 void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree );
@@ -51,6 +51,8 @@ static void *GDALDeserializeReprojectionTransformer( CPLXMLNode *psTree );
 static CPLXMLNode *GDALSerializeGenImgProjTransformer( void *pTransformArg );
 static void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree );
 
+static void GDALRefreshGenImgProjTransformer(void* hTransformArg);
+
 /************************************************************************/
 /*                          GDALTransformFunc                           */
 /*                                                                      */
@@ -348,6 +350,12 @@ GDALSuggestedWarpOutput2( GDALDatasetH hSrcDS,
     int    nInXSize = GDALGetRasterXSize( hSrcDS );
     int    nInYSize = GDALGetRasterYSize( hSrcDS );
 
+    if (pfnTransformer == GDALGenImgProjTransform)
+    {
+        /* In case CHECK_WITH_INVERT_PROJ has been modified */
+        GDALRefreshGenImgProjTransformer(pTransformArg);
+    }
+
 #define N_PIXELSTEP 50
     int nSteps = (int) (double(MIN(nInYSize, nInXSize)) / N_PIXELSTEP + .5);
     if (nSteps < 20)
@@ -1000,6 +1008,8 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
  * <li> SRC_SRS: WKT SRS to be used as an override for hSrcDS.
  * <li> DST_SRS: WKT SRS to be used as an override for hDstDS.
  * <li> GCPS_OK: If false, GCPs will not be used, default is TRUE. 
+ * <li> REFINE_MINIMUM_GCPS: The minimum amount of GCPs that should be available after the refinement.
+ * <li> REFINE_TOLERANCE: The tolernace that specifies when a GCP will be eliminated.
  * <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.
@@ -1008,10 +1018,14 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
  * considered on the source 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 
+ * CENTER_LONG value on the coordinate system to rewrap things around the
+ * center of the image.  
  * </ul>
  * 
  * @param hSrcDS source dataset, or NULL.
- * @param hDstDS destination dataset (or NULL). 
+ * @param hDstDS destination dataset (or NULL).
+ * @param papszOptions NULL-terminated list of string options (or NULL).
  * 
  * @return handle suitable for use GDALGenImgProjTransform(), and to be
  * deallocated with GDALDestroyGenImgProjTransformer() or NULL on failure.
@@ -1027,7 +1041,8 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     GDALRPCInfo sRPCInfo;
     const char *pszMethod = CSLFetchNameValue( papszOptions, "METHOD" );
     const char *pszValue;
-    int nOrder = 0, bGCPUseOK = TRUE;
+    int nOrder = 0, bGCPUseOK = TRUE, nMinimumGcps = -1, bRefine = FALSE;
+    double dfTolerance = 0.0;
     const char *pszSrcWKT = CSLFetchNameValue( papszOptions, "SRC_SRS" );
     const char *pszDstWKT = CSLFetchNameValue( papszOptions, "DST_SRS" );
 
@@ -1039,6 +1054,20 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     if( pszValue )
         bGCPUseOK = CSLTestBoolean(pszValue);
 
+    pszValue = CSLFetchNameValue( papszOptions, "REFINE_MINIMUM_GCPS" );
+    if( pszValue )
+    {
+        if( atoi(pszValue) != -1)
+            nMinimumGcps = atoi(pszValue);
+    }
+
+    pszValue = CSLFetchNameValue( papszOptions, "REFINE_TOLERANCE" );
+    if( pszValue )
+    {
+        dfTolerance = atof(pszValue);
+        bRefine = TRUE;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
@@ -1086,10 +1115,20 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
              && (pszMethod == NULL || EQUAL(pszMethod,"GCP_POLYNOMIAL") )
              && GDALGetGCPCount( hSrcDS ) > 0 && nOrder >= 0 )
     {
-        psInfo->pSrcGCPTransformArg = 
-            GDALCreateGCPTransformer( GDALGetGCPCount( hSrcDS ),
-                                      GDALGetGCPs( hSrcDS ), nOrder, 
-                                      FALSE );
+        if(bRefine)
+        {
+                psInfo->pSrcGCPTransformArg = 
+                    GDALCreateGCPRefineTransformer( GDALGetGCPCount( hSrcDS ),
+                                                    GDALGetGCPs( hSrcDS ), nOrder, 
+                                                    FALSE, dfTolerance, nMinimumGcps );
+        }
+        else
+        {
+            psInfo->pSrcGCPTransformArg = 
+                GDALCreateGCPTransformer( GDALGetGCPCount( hSrcDS ),
+                                          GDALGetGCPs( hSrcDS ), nOrder, 
+                                          FALSE );
+        }
 
         if( psInfo->pSrcGCPTransformArg == NULL )
         {
@@ -1183,7 +1222,8 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         && !EQUAL(pszSrcWKT,pszDstWKT) )
     {
         CPLString osSrcWKT = pszSrcWKT;
-        if (hSrcDS)
+        if (hSrcDS 
+            && CSLFetchBoolean( papszOptions, "INSERT_CENTER_LONG", TRUE ) )
             osSrcWKT = InsertCenterLong( hSrcDS, osSrcWKT );
         
         psInfo->pReprojectArg = 
@@ -1216,6 +1256,24 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 }
 
 /************************************************************************/
+/*                  GDALRefreshGenImgProjTransformer()                  */
+/************************************************************************/
+
+void GDALRefreshGenImgProjTransformer(void* hTransformArg)
+{
+    GDALGenImgProjTransformInfo *psInfo =
+        static_cast<GDALGenImgProjTransformInfo *>( hTransformArg );
+
+    if (psInfo->pReprojectArg)
+    {
+        CPLXMLNode* psXML = GDALSerializeReprojectionTransformer(psInfo->pReprojectArg);
+        GDALDestroyReprojectionTransformer(psInfo->pReprojectArg);
+        psInfo->pReprojectArg = GDALDeserializeReprojectionTransformer(psXML);
+        CPLDestroyXMLNode(psXML);
+    }
+}
+
+/************************************************************************/
 /*                  GDALCreateGenImgProjTransformer3()                  */
 /************************************************************************/
 
@@ -1247,8 +1305,10 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
  * GDALGCPTransform().  This stage is skipped if hDstDS is NULL when the
  * transformation is created. 
  *
- * @param hSrcDS source dataset, or NULL.
- * @param hDstDS destination dataset (or NULL). 
+ * @param pszSrcWKT source WKT (or NULL).
+ * @param padfSrcGeoTransform source geotransform (or NULL).
+ * @param pszDstWKT destination WKT (or NULL).
+ * @param padfDstGeoTransform destination geotransform (or NULL).
  * 
  * @return handle suitable for use GDALGenImgProjTransform(), and to be
  * deallocated with GDALDestroyGenImgProjTransformer() or NULL on failure.
@@ -1987,19 +2047,19 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
  * GDALCreateReprojectionTransformer().
  */
 
-void GDALDestroyReprojectionTransformer( void *pTransformAlg )
+void GDALDestroyReprojectionTransformer( void *pTransformArg )
 
 {
-    VALIDATE_POINTER0( pTransformAlg, "GDALDestroyReprojectionTransformer" );
+    VALIDATE_POINTER0( pTransformArg, "GDALDestroyReprojectionTransformer" );
 
     GDALReprojectionTransformInfo *psInfo = 
-        (GDALReprojectionTransformInfo *) pTransformAlg;		
+        (GDALReprojectionTransformInfo *) pTransformArg;		
 
     if( psInfo->poForwardTransform )
         delete psInfo->poForwardTransform;
 
     if( psInfo->poReverseTransform )
-    delete psInfo->poReverseTransform;
+        delete psInfo->poReverseTransform;
 
     CPLFree( psInfo );
 }
diff --git a/alg/gdalwarper.cpp b/alg/gdalwarper.cpp
index cc106ed..1dfa0f4 100644
--- a/alg/gdalwarper.cpp
+++ b/alg/gdalwarper.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarper.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: gdalwarper.cpp 22888 2011-08-07 13:06:36Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of high level convenience APIs for warper.
@@ -33,7 +33,7 @@
 #include "ogr_api.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalwarper.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: gdalwarper.cpp 22888 2011-08-07 13:06:36Z rouault $");
 
 /************************************************************************/
 /*                         GDALReprojectImage()                         */
@@ -429,7 +429,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
           {
               float fVal = pafData[iOffset];
-              if( (bIsNoDataNan && CPLIsNan(fVal)) || EQUAL_TO_NODATA(fVal, fNoData) )
+              if( (bIsNoDataNan && CPLIsNan(fVal)) || (!bIsNoDataNan && ARE_REAL_EQUAL(fVal, fNoData)) )
               {
                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
               }
@@ -451,7 +451,7 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
           {
               double dfVal = padfData[iOffset];
-              if( (bIsNoDataNan && CPLIsNan(dfVal)) || EQUAL_TO_NODATA(dfVal, dfNoData) )
+              if( (bIsNoDataNan && CPLIsNan(dfVal)) || (!bIsNoDataNan && ARE_REAL_EQUAL(dfVal, dfNoData)) )
               {
                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
               }
@@ -478,9 +478,9 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
               for( iPixel = 0; iPixel < nXSize; iPixel++ )
               {
                   if( ((bIsNoDataRealNan && CPLIsNan(padfWrk[iPixel*2])) ||
-                        EQUAL_TO_NODATA(padfWrk[iPixel*2], padfNoData[0]))
+                       (!bIsNoDataRealNan && ARE_REAL_EQUAL(padfWrk[iPixel*2], padfNoData[0])))
                       && ((bIsNoDataImagNan && CPLIsNan(padfWrk[iPixel*2+1])) ||
-                        EQUAL_TO_NODATA(padfWrk[iPixel*2+1], padfNoData[1])) )
+                          (!bIsNoDataImagNan && ARE_REAL_EQUAL(padfWrk[iPixel*2+1], padfNoData[1]))) )
                   {
                       int iOffset = iPixel + iLine * nXSize;
                       
@@ -884,12 +884,14 @@ void CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions *psOptions )
 
 
 #define COPY_MEM(target,type,count)					\
-   if( (psSrcOptions->target) != NULL && (count) != 0 ) 		\
+   do { if( (psSrcOptions->target) != NULL && (count) != 0 ) 		\
    { 									\
-       (psDstOptions->target) = (type *) CPLMalloc(sizeof(type)*count); \
+       (psDstOptions->target) = (type *) CPLMalloc(sizeof(type)*(count)); \
        memcpy( (psDstOptions->target), (psSrcOptions->target),		\
- 	       sizeof(type) * count ); 	        			\
-   }
+ 	       sizeof(type) * (count) ); 	        			\
+   } \
+   else \
+       (psDstOptions->target) = NULL; } while(0)
 
 /************************************************************************/
 /*                        GDALCloneWarpOptions()                        */
@@ -915,6 +917,7 @@ GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
     COPY_MEM( padfDstNoDataImag, double, psSrcOptions->nBandCount );
     COPY_MEM( papfnSrcPerBandValidityMaskFunc, GDALMaskFunc, 
               psSrcOptions->nBandCount );
+    psDstOptions->papSrcPerBandValidityMaskFuncArg = NULL;
 
     if( psSrcOptions->hCutline != NULL )
         psDstOptions->hCutline = 
diff --git a/alg/gdalwarpkernel.cpp b/alg/gdalwarpkernel.cpp
index 3c468fe..abf0562 100644
--- a/alg/gdalwarpkernel.cpp
+++ b/alg/gdalwarpkernel.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel.cpp 21221 2010-12-08 20:18:37Z rouault $
+ * $Id: gdalwarpkernel.cpp 22887 2011-08-07 13:01:45Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel class.  Implements the actual
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "gdalwarpkernel_opencl.h"
 
-CPL_CVSID("$Id: gdalwarpkernel.cpp 21221 2010-12-08 20:18:37Z rouault $");
+CPL_CVSID("$Id: gdalwarpkernel.cpp 22887 2011-08-07 13:01:45Z rouault $");
 
 static const int anGWKFilterRadius[] =
 {
@@ -2651,6 +2651,35 @@ free_warper:
 }
 #endif /* defined(HAVE_OPENCL) */
 
+
+#define COMPUTE_iSrcOffset(_pabSuccess, _iDstX, _padfX, _padfY, _poWK, _nSrcXSize, _nSrcYSize) \
+            if( !_pabSuccess[_iDstX] ) \
+                continue; \
+\
+/* -------------------------------------------------------------------- */ \
+/*      Figure out what pixel we want in our source raster, and skip    */ \
+/*      further processing if it is well off the source image.          */ \
+/* -------------------------------------------------------------------- */ \
+            /* We test against the value before casting to avoid the */ \
+            /* problem of asymmetric truncation effects around zero.  That is */ \
+            /* -0.5 will be 0 when cast to an int. */ \
+            if( _padfX[_iDstX] < _poWK->nSrcXOff \
+                || _padfY[_iDstX] < _poWK->nSrcYOff ) \
+                continue; \
+\
+            int iSrcX, iSrcY, iSrcOffset;\
+\
+            iSrcX = ((int) (_padfX[_iDstX] + 1e-10)) - _poWK->nSrcXOff;\
+            iSrcY = ((int) (_padfY[_iDstX] + 1e-10)) - _poWK->nSrcYOff;\
+\
+            /* If operating outside natural projection area, padfX/Y can be */ \
+            /* a very huge positive number, that becomes -2147483648 in the */ \
+            /* int trucation. So it is necessary to test now for non negativeness. */ \
+            if( iSrcX < 0 || iSrcX >= _nSrcXSize || iSrcY < 0 || iSrcY >= _nSrcYSize )\
+                continue;\
+\
+            iSrcOffset = iSrcX + iSrcY * _nSrcXSize;
+
 /************************************************************************/
 /*                           GWKGeneralCase()                           */
 /*                                                                      */
@@ -2730,32 +2759,7 @@ static CPLErr GWKGeneralCase( GDALWarpKernel *poWK )
         {
             int iDstOffset;
 
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Do not try to apply transparent/invalid source pixels to the    */
@@ -2959,29 +2963,7 @@ static CPLErr GWKNearestNoMasksByte( GDALWarpKernel *poWK )
             if( !pabSuccess[iDstX] )
                 continue;
 
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -3091,32 +3073,7 @@ static CPLErr GWKBilinearNoMasksByte( GDALWarpKernel *poWK )
 /* ==================================================================== */
         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -3228,32 +3185,7 @@ static CPLErr GWKCubicNoMasksByte( GDALWarpKernel *poWK )
 /* ==================================================================== */
         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -3368,32 +3300,7 @@ static CPLErr GWKCubicSplineNoMasksByte( GDALWarpKernel *poWK )
 /* ==================================================================== */
         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -3509,32 +3416,7 @@ static CPLErr GWKNearestByte( GDALWarpKernel *poWK )
         {
             int iDstOffset;
 
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Do not try to apply invalid source pixels to the dest.          */
@@ -3701,32 +3583,7 @@ static CPLErr GWKNearestNoMasksShort( GDALWarpKernel *poWK )
         {
             int iDstOffset;
 
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -3835,32 +3692,7 @@ static CPLErr GWKBilinearNoMasksShort( GDALWarpKernel *poWK )
 /* ==================================================================== */
         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -3974,32 +3806,7 @@ static CPLErr GWKCubicNoMasksShort( GDALWarpKernel *poWK )
 /* ==================================================================== */
         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -4117,32 +3924,7 @@ static CPLErr GWKCubicSplineNoMasksShort( GDALWarpKernel *poWK )
 /* ==================================================================== */
         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -4260,32 +4042,7 @@ static CPLErr GWKNearestShort( GDALWarpKernel *poWK )
         {
             int iDstOffset;
 
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Don't generate output pixels for which the source valid         */
@@ -4451,32 +4208,7 @@ static CPLErr GWKNearestNoMasksFloat( GDALWarpKernel *poWK )
         {
             int iDstOffset;
 
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -4587,32 +4319,7 @@ static CPLErr GWKNearestFloat( GDALWarpKernel *poWK )
         {
             int iDstOffset;
 
-            if( !pabSuccess[iDstX] )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out what pixel we want in our source raster, and skip    */
-/*      further processing if it is well off the source image.          */
-/* -------------------------------------------------------------------- */
-            // We test against the value before casting to avoid the
-            // problem of asymmetric truncation effects around zero.  That is
-            // -0.5 will be 0 when cast to an int. 
-            if( padfX[iDstX] < poWK->nSrcXOff 
-                || padfY[iDstX] < poWK->nSrcYOff )
-                continue;
-
-            int iSrcX, iSrcY, iSrcOffset;
-
-            iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
-            iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
-
-            // If operating outside natural projection area, padfX/Y can be
-            // a very huge positive number, that becomes -2147483648 in the
-            // int trucation. So it is necessary to test now for non negativeness.
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
-                continue;
-
-            iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+            COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Do not try to apply invalid source pixels to the dest.          */
diff --git a/alg/gdalwarpoperation.cpp b/alg/gdalwarpoperation.cpp
index dfdfb67..07d41e0 100644
--- a/alg/gdalwarpoperation.cpp
+++ b/alg/gdalwarpoperation.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpoperation.cpp 22162 2011-04-14 20:22:35Z rouault $
+ * $Id: gdalwarpoperation.cpp 22888 2011-08-07 13:06:36Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpOperation class.
@@ -32,7 +32,7 @@
 #include "cpl_multiproc.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: gdalwarpoperation.cpp 22162 2011-04-14 20:22:35Z rouault $");
+CPL_CVSID("$Id: gdalwarpoperation.cpp 22888 2011-08-07 13:06:36Z rouault $");
 
 /* Defined in gdalwarpkernel.cpp */
 int GWKGetFilterRadius(GDALResampleAlg eResampleAlg);
@@ -1203,6 +1203,8 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Integer overflow : nDstXSize=%d, nDstYSize=%d",
                   nDstXSize, nDstYSize);
+        if( hIOMutex != NULL )
+            CPLReleaseMutex( hIOMutex );
         return CE_Failure;
     }
 
@@ -1212,6 +1214,8 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
         CPLError( CE_Failure, CPLE_OutOfMemory,
                   "Out of memory allocating %d byte destination buffer.",
                   nBandSize * psOptions->nBandCount );
+        if( hIOMutex != NULL )
+            CPLReleaseMutex( hIOMutex );
         return CE_Failure;
     }
 
@@ -1257,11 +1261,12 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                 memset( pBandData, 
                         MAX(0,MIN(255,(int)adfInitRealImag[0])), 
                         nBandSize);
-            else if( adfInitRealImag[0] == 0.0 && adfInitRealImag[1] == 0 )
+            else if( !CPLIsNan(adfInitRealImag[0]) && adfInitRealImag[0] == 0.0 &&
+                     !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
             {
                 memset( pBandData, 0, nBandSize );
             }
-            else if( adfInitRealImag[1] == 0.0 )
+            else if( !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
             {
                 GDALCopyWords( &adfInitRealImag, GDT_Float64, 0, 
                                pBandData,psOptions->eWorkingDataType,nWordSize,
@@ -1295,6 +1300,8 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
         if( eErr != CE_None )
         {
             CPLFree( pDstBuffer );
+            if( hIOMutex != NULL )
+                CPLReleaseMutex( hIOMutex );
             return eErr;
         }
 
diff --git a/alg/llrasterize.cpp b/alg/llrasterize.cpp
index 50e1953..be341d0 100644
--- a/alg/llrasterize.cpp
+++ b/alg/llrasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: llrasterize.cpp 18340 2009-12-19 04:41:45Z chaitanya $
+ * $Id: llrasterize.cpp 22998 2011-08-28 12:23:29Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Vector polygon rasterization code.
@@ -195,43 +195,43 @@ No known bug
                 dx2 = padfX[ind1];
                 dx1 = padfX[ind2];
             } else /* if (fabs(dy1-dy2)< 1.e-6) */
-	    {
+            {
                 
                 /*AE: DO NOT skip bottom horizontal segments 
-		  -Fill them separately- 
-		  They are not taken into account twice.*/
-		if (padfX[ind1] > padfX[ind2])
-		{
-		    horizontal_x1 = (int) floor(padfX[ind2]+0.5);
-		    horizontal_x2 = (int) floor(padfX[ind1]+0.5);
+                  -Fill them separately- 
+                  They are not taken into account twice.*/
+                if (padfX[ind1] > padfX[ind2])
+                {
+                    horizontal_x1 = (int) floor(padfX[ind2]+0.5);
+                    horizontal_x2 = (int) floor(padfX[ind1]+0.5);
 		
                     if  ( (horizontal_x1 >  maxx) ||  (horizontal_x2 <= minx) )
                         continue;
 
-		    /*fill the horizontal segment (separately from the rest)*/
-		    pfnScanlineFunc( pCBData, y, horizontal_x1, horizontal_x2 - 1, (dfVariant == NULL)?0:dfVariant[0] );
-		    continue;
-		}
-		else /*skip top horizontal segments (they are already filled in the regular loop)*/
-		    continue;
+                    /*fill the horizontal segment (separately from the rest)*/
+                    pfnScanlineFunc( pCBData, y, horizontal_x1, horizontal_x2 - 1, (dfVariant == NULL)?0:dfVariant[0] );
+                    continue;
+                }
+                else /*skip top horizontal segments (they are already filled in the regular loop)*/
+                    continue;
 
-	    }
+            }
 
             if(( dy < dy2 ) && (dy >= dy1))
             {
                 
                 intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
 
-		polyInts[ints++] = (int) floor(intersect+0.5);
-	    }
-	}
+                polyInts[ints++] = (int) floor(intersect+0.5);
+            }
+        }
 
         /* 
          * It would be more efficient to do this inline, to avoid 
          * a function call for each comparison.
-	 * NOTE - mloskot: make llCompareInt a functor and use std
-	 * algorithm and it will be optimized and expanded
-	 * automatically in compile-time, with modularity preserved.
+         * NOTE - mloskot: make llCompareInt a functor and use std
+         * algorithm and it will be optimized and expanded
+         * automatically in compile-time, with modularity preserved.
          */
         qsort(polyInts, ints, sizeof(int), llCompareInt);
 
@@ -261,8 +261,8 @@ void GDALdllImagePoint( int nRasterXSize, int nRasterYSize,
  
     for ( i = 0; i < nPartCount; i++ )
     {
-        int nX = (int)floor( padfX[i] + 0.5 );
-        int nY = (int)floor( padfY[i] + 0.5 );
+        int nX = (int)floor( padfX[i] );
+        int nY = (int)floor( padfY[i] );
         double dfVariant = 0;
         if( padfVariant != NULL )
             dfVariant = padfVariant[i];
@@ -292,11 +292,11 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
 
         for ( j = 1; j < panPartSize[i]; j++ )
         {
-            int iX = (int)floor( padfX[n + j - 1] + 0.5 );
-            int iY = (int)floor( padfY[n + j - 1] + 0.5 );
+            int iX = (int)floor( padfX[n + j - 1] );
+            int iY = (int)floor( padfY[n + j - 1] );
 
-            const int iX1 = (int)floor( padfX[n + j] + 0.5 );
-            const int iY1 = (int)floor( padfY[n + j] + 0.5 );
+            const int iX1 = (int)floor( padfX[n + j] );
+            const int iY1 = (int)floor( padfY[n + j] );
 
             double dfVariant = 0, dfVariant1 = 0;
             if( padfVariant != NULL && 
@@ -320,7 +320,9 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                 const int nXError = nDeltaY << 1;
                 const int nYError = nXError - (nDeltaX << 1);
                 int nError = nXError - nDeltaX;
-                double dfDeltaVariant = (dfVariant1 - dfVariant) /
+                /* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
+                /* it is == 0, dfDeltaVariant is not really used, so any value is OK */
+                double dfDeltaVariant = (nDeltaX == 0) ? 0 : (dfVariant1 - dfVariant) /
                                                            (double)nDeltaX;
 
                 while ( nDeltaX-- >= 0 )
@@ -345,7 +347,9 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                 const int nXError = nDeltaX << 1;
                 const int nYError = nXError - (nDeltaY << 1);
                 int nError = nXError - nDeltaY;
-                double dfDeltaVariant = (dfVariant1 - dfVariant) /
+                /* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
+                /* it is == 0, dfDeltaVariant is not really used, so any value is OK */
+                double dfDeltaVariant = (nDeltaY == 0) ? 0 : (dfVariant1 - dfVariant) /
                                                            (double)nDeltaY;
 
                 while ( nDeltaY-- >= 0 )
diff --git a/alg/makefile.vc b/alg/makefile.vc
index dd70449..80a4778 100644
--- a/alg/makefile.vc
+++ b/alg/makefile.vc
@@ -19,7 +19,7 @@ OBJ =	gdaldither.obj gdalmediancut.obj gdal_crs.obj gdaltransformer.obj \
 	gdalwarpoperation.obj gdalchecksum.obj gdal_rpc.obj gdalgeoloc.obj \
 	gdalgrid.obj gdalcutline.obj gdalproximity.obj rasterfill.obj \
 	gdalsievefilter.obj gdalrasterpolygonenumerator.obj polygonize.obj \
-	contour.obj
+	gdalrasterfpolygonenumerator.obj fpolygonize.obj contour.obj
 
 default:	$(OBJ) 
 
diff --git a/alg/polygonize.cpp b/alg/polygonize.cpp
index b70fe10..336295f 100644
--- a/alg/polygonize.cpp
+++ b/alg/polygonize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: polygonize.cpp 21236 2010-12-11 17:28:32Z rouault $
+ * $Id: polygonize.cpp 22501 2011-06-04 21:28:47Z rouault $
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: polygonize.cpp 21236 2010-12-11 17:28:32Z rouault $");
+CPL_CVSID("$Id: polygonize.cpp 22501 2011-06-04 21:28:47Z rouault $");
 
 #define GP_NODATA_MARKER -51502112
 
@@ -446,7 +446,8 @@ GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXS
  *
  * Note that currently the source pixel band values are read into a
  * signed 32bit integer buffer (Int32), so floating point or complex 
- * bands will be implicitly truncated before processing.  
+ * bands will be implicitly truncated before processing. If you want to use a
+ * version using 32bit float buffers, see GDALFPolygonize() at fpolygonize.cpp.
  *
  * Polygon features will be created on the output layer, with polygon 
  * geometries representing the polygons.  The polygon geometries will be
diff --git a/alg/rasterfill.cpp b/alg/rasterfill.cpp
index 45957e9..a115cc4 100644
--- a/alg/rasterfill.cpp
+++ b/alg/rasterfill.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterfill.cpp 22396 2011-05-17 21:27:47Z warmerdam $
+ * $Id: rasterfill.cpp 22395 2011-05-17 21:27:03Z warmerdam $
  *
  * Project:  GDAL
  * Purpose:  Interpolate in nodata areas.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: rasterfill.cpp 22396 2011-05-17 21:27:47Z warmerdam $");
+CPL_CVSID("$Id: rasterfill.cpp 22395 2011-05-17 21:27:03Z warmerdam $");
 
 /************************************************************************/
 /*                           GDALFilterLine()                           */
diff --git a/alg/thinplatespline.cpp b/alg/thinplatespline.cpp
index 6e59e7e..f8a9f44 100644
--- a/alg/thinplatespline.cpp
+++ b/alg/thinplatespline.cpp
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: thinplatespline.cpp 15547 2008-10-17 17:45:03Z rouault $
+ * $Id: thinplatespline.cpp 22879 2011-08-07 01:00:45Z rouault $
  *
  * Project:  GDAL Warp API
  * Purpose:  Implemenentation of 2D Thin Plate Spline transformer. 
  * Author:   VIZRT Development Team.
  *
- * This code was provided by Gilad Ronnen (gro at visrt dot com) with 
+ * This code was provided by Gilad Ronnen (gro at visrt dot com) with
  * permission to reuse under the following license.
  * 
  ******************************************************************************
@@ -30,6 +30,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifdef HAVE_ARMADILLO
+/* Include before #define A(r,c) because armadillo uses A in its include files */
+#include "armadillo"
+#endif
+
 #include "thinplatespline.h"
 
 #ifdef HAVE_FLOAT_H
@@ -56,7 +61,7 @@ VizGeorefSpline2D* viz_llz2xy;
 
 #define VIZ_GEOREF_SPLINE_DEBUG 0
 
-int matrixInvert( int N, double input[], double output[] );
+static int matrixInvert( int N, double input[], double output[] );
 
 void VizGeorefSpline2D::grow_points()
 
@@ -434,7 +439,32 @@ double VizGeorefSpline2D::base_func( const double x1, const double y1,
 	return dist * log( dist );	
 }
 
-int matrixInvert( int N, double input[], double output[] )
+#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
+
+static int matrixInvert( int N, double input[], double output[] )
 {
     // Receives an array of dimension NxN as input.  This is passed as a one-
     // dimensional array of N-squared size.  It produces the inverse of the
@@ -530,14 +560,16 @@ int matrixInvert( int N, double input[], double output[] )
             temp[ k*2*N + col ] /= ftemp;
         }
 		
+        int i2 = k*2*N ;
         for ( row=0; row<N; row++ )
         {
             if ( row != k )
             {
-                ftemp = temp[ row*2*N + k ];
+                int i1 = row*2*N;
+                ftemp = temp[ i1 + k ];
                 for ( col=k; col<2*N; col++ ) 
                 {
-                    temp[ row*2*N + col ] -= ftemp * temp[ k*2*N + col ];
+                    temp[ i1 + col ] -= ftemp * temp[ i2 + col ];
                 }
             }
         }
@@ -568,3 +600,4 @@ int matrixInvert( int N, double input[], double output[] )
     delete [] temp;       // free memory
     return true;
 }
+#endif
diff --git a/apps/GNUmakefile b/apps/GNUmakefile
index 9947d51..17f4db4 100644
--- a/apps/GNUmakefile
+++ b/apps/GNUmakefile
@@ -10,7 +10,7 @@ DEP_LIBS	=	$(EXE_DEP_LIBS) $(XTRAOBJ)
 BIN_LIST	=	gdalinfo$(EXE) gdal_translate$(EXE) gdaladdo$(EXE) \
 			gdalwarp$(EXE) nearblack$(EXE) gdalmanage$(EXE) \
 			gdalenhance$(EXE) gdaltransform$(EXE) gdaldem$(EXE) \
-			gdallocationinfo$(EXE)
+			gdallocationinfo$(EXE) gdalsrsinfo$(EXE) 
 
 ifeq ($(OGR_ENABLED),yes)
 BIN_LIST += 	gdal_contour$(EXE) \
@@ -40,26 +40,26 @@ lib-depend:
 gdalinfo$(EXE):	gdalinfo.$(OBJ_EXT)  $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdal_translate$(EXE):	gdal_translate.$(OBJ_EXT)  $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdal_translate$(EXE):	gdal_translate.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdaladdo$(EXE):	gdaladdo.$(OBJ_EXT)  $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdalwarp$(EXE): gdalwarp.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdalwarp$(EXE): gdalwarp.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdal_contour$(EXE):	gdal_contour.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-nearblack$(EXE):	nearblack.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+nearblack$(EXE):	nearblack.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdalmanage$(EXE):	gdalmanage.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdal_rasterize$(EXE):	gdal_rasterize.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdal_rasterize$(EXE):	gdal_rasterize.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdaltindex$(EXE):	gdaltindex.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
@@ -73,14 +73,14 @@ multireadtest$(EXE):	multireadtest.$(OBJ_EXT) $(DEP_LIBS)
 dumpoverviews$(EXE):	dumpoverviews.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdalenhance$(EXE):	gdalenhance.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdalenhance$(EXE):	gdalenhance.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
-gdaldem$(EXE): gdaldem.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
-	
-gdal_grid$(EXE):	gdal_grid.$(OBJ_EXT) $(DEP_LIBS)
-	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+gdaldem$(EXE): gdaldem.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+
+gdal_grid$(EXE):	gdal_grid.$(OBJ_EXT) commonutils.$(OBJ_EXT) $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< commonutils.$(OBJ_EXT) $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
 gdalwarpsimple$(EXE): gdalwarpsimple.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
@@ -91,6 +91,9 @@ gdaltransform$(EXE): gdaltransform.$(OBJ_EXT) $(DEP_LIBS)
 gdallocationinfo$(EXE): gdallocationinfo.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
+gdalsrsinfo$(EXE):	gdalsrsinfo.$(OBJ_EXT)  $(DEP_LIBS)
+	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
+
 gdalflattenmask$(EXE): gdalflattenmask.$(OBJ_EXT) $(DEP_LIBS)
 	$(LD) $(LNK_FLAGS) $< $(XTRAOBJ) $(CONFIG_LIBS) -o $@
 
diff --git a/apps/commonutils.cpp b/apps/commonutils.cpp
new file mode 100755
index 0000000..f698744
--- /dev/null
+++ b/apps/commonutils.cpp
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * $Id: commonutils.cpp 22643 2011-07-04 18:20:29Z 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
+ *
+ * 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 "commonutils.h"
+#include "cpl_string.h"
+#include "gdal.h"
+
+CPL_CVSID("$Id: commonutils.cpp 22643 2011-07-04 18:20:29Z rouault $");
+
+/* -------------------------------------------------------------------- */
+/*                      CheckExtensionConsistency()                     */
+/*                                                                      */
+/*      Check that the target file extension is consistant with the     */
+/*      requested driver. Actually, we only warn in cases where the     */
+/*      inconsistency is blatant (use of an extension declared by one   */
+/*      or several drivers, and not by the selected one)                */
+/* -------------------------------------------------------------------- */
+
+void CheckExtensionConsistency(const char* pszDestFilename,
+                               const char* pszDriverName)
+{
+
+    char* pszDestExtension = CPLStrdup(CPLGetExtension(pszDestFilename));
+    if (pszDestExtension[0] != '\0')
+    {
+        int nDriverCount = GDALGetDriverCount();
+        CPLString osConflictingDriverList;
+        for(int i=0;i<nDriverCount;i++)
+        {
+            GDALDriverH hDriver = GDALGetDriver(i);
+            const char* pszDriverExtension = 
+                GDALGetMetadataItem( hDriver, GDAL_DMD_EXTENSION, NULL );   
+            if (pszDriverExtension && EQUAL(pszDestExtension, pszDriverExtension))
+            {
+                if (GDALGetDriverByName(pszDriverName) != hDriver)
+                {
+                    if (osConflictingDriverList.size())
+                        osConflictingDriverList += ", ";
+                    osConflictingDriverList += GDALGetDriverShortName(hDriver);
+                }
+                else
+                {
+                    /* If the request driver allows the used extension, then */
+                    /* just stop iterating now */
+                    osConflictingDriverList = "";
+                    break;
+                }
+            }
+        }
+        if (osConflictingDriverList.size())
+        {
+            fprintf(stderr,
+                    "Warning: The target file has a '%s' extension, which is normally used by the %s driver%s,\n"
+                    "but the requested output driver is %s. Is it really what you want ?\n",
+                    pszDestExtension,
+                    osConflictingDriverList.c_str(),
+                    strchr(osConflictingDriverList.c_str(), ',') ? "s" : "",
+                    pszDriverName);
+        }
+    }
+
+    CPLFree(pszDestExtension);
+}
diff --git a/apps/commonutils.h b/apps/commonutils.h
new file mode 100644
index 0000000..733a8e0
--- /dev/null
+++ b/apps/commonutils.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * $Id: commonutils.h 22643 2011-07-04 18:20:29Z 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
+ *
+ * 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 _COMMONUTILS_H_
+#define _COMMONUTILS_H_
+
+void CheckExtensionConsistency(const char* pszDestFilename,
+                               const char* pszDriverName);
+
+#endif
diff --git a/apps/dumpoverviews.cpp b/apps/dumpoverviews.cpp
index 7201fc3..7669005 100644
--- a/apps/dumpoverviews.cpp
+++ b/apps/dumpoverviews.cpp
@@ -1,5 +1,5 @@
 /* ****************************************************************************
- * $Id: dumpoverviews.cpp 20991 2010-10-27 20:13:47Z rouault $
+ * $Id: dumpoverviews.cpp 23484 2011-12-07 03:34:10Z warmerdam $
  *
  * Project:  GDAL Utilities
  * Purpose:  Dump overviews to external files.
@@ -32,12 +32,22 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dumpoverviews.cpp 20991 2010-10-27 20:13:47Z rouault $");
+CPL_CVSID("$Id: dumpoverviews.cpp 23484 2011-12-07 03:34:10Z warmerdam $");
 
 static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hBand,
                       const char *pszName );
 
 /************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+static void Usage() 
+
+{
+    printf( "Usage: dumpoverviews [-masks] <filename> [overview]*\n" );
+    exit( 1 );
+}
+
+/************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
@@ -75,16 +85,12 @@ int main( int argc, char ** argv )
         }
         else
         {
-            printf( "Usage: dumpoverviews [-masks] <filename> [overview]*\n" );
-            exit( 1 );
+            Usage();
         }
     }
 
     if( pszSrcFilename == NULL )
-    {
-        printf( "Usage: dumpoverviews <filename> [overview]*\n" );
-        exit( 1 );
-    }
+        Usage();
 
 /* -------------------------------------------------------------------- */
 /*      Open the input file.                                            */
diff --git a/apps/gdal_grid.cpp b/apps/gdal_grid.cpp
index 1191d13..31f5182 100644
--- a/apps/gdal_grid.cpp
+++ b/apps/gdal_grid.cpp
@@ -1,5 +1,5 @@
 /* ****************************************************************************
- * $Id: gdal_grid.cpp 21149 2010-11-19 10:08:55Z dron $
+ * $Id: gdal_grid.cpp 22783 2011-07-23 19:28:16Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL scattered data gridding (interpolation) tool
@@ -38,8 +38,9 @@
 #include "ogr_api.h"
 #include "ogrsf_frmts.h"
 #include "gdalgrid.h"
+#include "commonutils.h"
 
-CPL_CVSID("$Id: gdal_grid.cpp 21149 2010-11-19 10:08:55Z dron $");
+CPL_CVSID("$Id: gdal_grid.cpp 22783 2011-07-23 19:28:16Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -512,6 +513,7 @@ 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;
@@ -559,6 +561,7 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i],"-of") && i < argc-1 )
         {
             pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
         }
 
         else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
@@ -880,6 +883,9 @@ int main( int argc, char ** argv )
     if ( nYSize == 0 )
         nYSize = 256;
 
+    if (!bQuiet && !bFormatExplicitelySet)
+        CheckExtensionConsistency(pszDest, pszFormat);
+
     hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
                          eOutputType, papszCreateOptions );
     if ( hDstDS == NULL )
diff --git a/apps/gdal_rasterize.cpp b/apps/gdal_rasterize.cpp
index 62adbff..64909c7 100644
--- a/apps/gdal_rasterize.cpp
+++ b/apps/gdal_rasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rasterize.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: gdal_rasterize.cpp 23285 2011-10-27 21:39:19Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Rasterize OGR shapes into a GDAL raster.
@@ -33,9 +33,10 @@
 #include "ogr_api.h"
 #include "ogr_srs_api.h"
 #include "cpl_string.h"
+#include "commonutils.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdal_rasterize.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: gdal_rasterize.cpp 23285 2011-10-27 21:39:19Z rouault $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
@@ -280,7 +281,7 @@ static void ProcessLayer(
 /* -------------------------------------------------------------------- */
 /*      If we are in inverse mode, we add one extra ring around the     */
 /*      whole dataset to invert the concept of insideness and then      */
-/*      merge everything into one geomtry collection.                   */
+/*      merge everything into one geometry collection.                  */
 /* -------------------------------------------------------------------- */
     if( bInverse )
     {
@@ -333,12 +334,24 @@ GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
         {
             OGREnvelope sLayerEnvelop;
 
-            if (OGR_L_GetExtent(hLayer, &sLayerEnvelop, FALSE) != OGRERR_NONE)
+            if (OGR_L_GetExtent(hLayer, &sLayerEnvelop, TRUE) != OGRERR_NONE)
             {
                 fprintf(stderr, "Cannot get layer extent\n");
                 exit(2);
             }
 
+            /* When rasterizing point layers and that the bounds have */
+            /* not been explicitely set, voluntary increase the extent by */
+            /* a half-pixel size to avoid missing points on the border */
+            if (wkbFlatten(OGR_L_GetGeomType(hLayer)) == wkbPoint &&
+                !bTargetAlignedPixels && dfXRes != 0 && dfYRes != 0)
+            {
+                sLayerEnvelop.MinX -= dfXRes / 2;
+                sLayerEnvelop.MaxX += dfXRes / 2;
+                sLayerEnvelop.MinY -= dfYRes / 2;
+                sLayerEnvelop.MaxY += dfYRes / 2;
+            }
+
             if (bFirstLayer)
             {
                 sEnvelop.MinX = sLayerEnvelop.MinX;
@@ -371,7 +384,6 @@ GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
         }
     }
 
-    double adfProjection[6];
     if (dfXRes == 0 && dfYRes == 0)
     {
         dfXRes = (sEnvelop.MaxX - sEnvelop.MinX) / nXSize;
@@ -385,6 +397,7 @@ GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
         sEnvelop.MaxY = ceil(sEnvelop.MaxY / dfYRes) * dfYRes;
     }
 
+    double adfProjection[6];
     adfProjection[0] = sEnvelop.MinX;
     adfProjection[1] = dfXRes;
     adfProjection[2] = 0;
@@ -466,6 +479,7 @@ int main( int argc, char ** argv )
     double dfXRes = 0, dfYRes = 0;
     int bCreateOutput = FALSE;
     const char* pszFormat = "GTiff";
+    int bFormatExplicitelySet = FALSE;
     char **papszCreateOptions = NULL;
     GDALDriverH hDriver = NULL;
     GDALDataType eOutputType = GDT_Float64;
@@ -593,6 +607,7 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i],"-of") && i < argc-1 )
         {
             pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
             bCreateOutput = TRUE;
         }
         else if( EQUAL(argv[i],"-init") && i < argc - 1 )
@@ -730,12 +745,6 @@ int main( int argc, char ** argv )
         fprintf( stderr, "Missing source or destination.\n\n" );
         Usage();
     }
-    
-    if( pszSQL == NULL && papszLayers == NULL )
-    {
-        fprintf( stderr, "At least one of -l or -sql required.\n\n" );
-        Usage();
-    }
 
     if( adfBurnValues.size() == 0 && pszBurnAttribute == NULL && !b3D )
     {
@@ -800,6 +809,19 @@ int main( int argc, char ** argv )
         exit( 1 );
     }
 
+    if( pszSQL == NULL && papszLayers == NULL )
+    {
+        if( OGR_DS_GetLayerCount(hSrcDS) == 1 )
+        {
+            papszLayers = CSLAddString(NULL, OGR_L_GetName(OGR_DS_GetLayer(hSrcDS, 0)));
+        }
+        else
+        {
+            fprintf( stderr, "At least one of -l or -sql required.\n\n" );
+            Usage();
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Open target raster file.  Eventually we will add optional       */
 /*      creation.                                                       */
@@ -836,6 +858,9 @@ int main( int argc, char ** argv )
             printf( "\n" );
             exit( 1 );
         }
+
+        if (!bQuiet && !bFormatExplicitelySet)
+            CheckExtensionConsistency(pszDstFilename, pszFormat);
     }
     else
     {
diff --git a/apps/gdal_translate.cpp b/apps/gdal_translate.cpp
index bcae998..d5ee838 100644
--- a/apps/gdal_translate.cpp
+++ b/apps/gdal_translate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_translate.cpp 21386 2011-01-03 20:17:11Z rouault $
+ * $Id: gdal_translate.cpp 22783 2011-07-23 19:28:16Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Image Translator Program
@@ -33,8 +33,9 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 #include "vrt/vrtdataset.h"
+#include "commonutils.h"
 
-CPL_CVSID("$Id: gdal_translate.cpp 21386 2011-01-03 20:17:11Z rouault $");
+CPL_CVSID("$Id: gdal_translate.cpp 22783 2011-07-23 19:28:16Z rouault $");
 
 static int ArgIsNumeric( const char * );
 static void AttachMetadata( GDALDatasetH, char ** );
@@ -99,6 +100,7 @@ static int ProxyMain( int argc, char ** argv )
     int			i;
     int			nRasterXSize, nRasterYSize;
     const char		*pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
+    int bFormatExplicitelySet = FALSE;
     GDALDriverH		hDriver;
     int			*panBandList = NULL; /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */
     int         nBandCount = 0, bDefBands = TRUE;
@@ -177,7 +179,10 @@ static int ProxyMain( int argc, char ** argv )
             return 0;
         }
         else if( EQUAL(argv[i],"-of") && i < argc-1 )
+        {
             pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
+        }
 
         else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
         {
@@ -491,6 +496,15 @@ static int ProxyMain( int argc, char ** argv )
         exit( 1 );
     }
 
+    if( strcmp(pszDest, "/vsistdout/") == 0)
+    {
+        bQuiet = TRUE;
+        pfnProgress = GDALDummyProgress;
+    }
+
+    if (!bQuiet && !bFormatExplicitelySet)
+        CheckExtensionConsistency(pszDest, pszFormat);
+
 /* -------------------------------------------------------------------- */
 /*      Attempt to open source file.                                    */
 /* -------------------------------------------------------------------- */
@@ -869,9 +883,32 @@ static int ProxyMain( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Transfer generally applicable metadata.                         */
 /* -------------------------------------------------------------------- */
-    poVDS->SetMetadata( ((GDALDataset*)hDataset)->GetMetadata() );
+    char** papszMetadata = CSLDuplicate(((GDALDataset*)hDataset)->GetMetadata());
+    if ( bScale || bUnscale || eOutputType != GDT_Unknown )
+    {
+        /* Remove TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE */
+        /* if the data range may change because of options */
+        char** papszIter = papszMetadata;
+        while(papszIter && *papszIter)
+        {
+            if (EQUALN(*papszIter, "TIFFTAG_MINSAMPLEVALUE=", 23) ||
+                EQUALN(*papszIter, "TIFFTAG_MAXSAMPLEVALUE=", 23))
+            {
+                CPLFree(*papszIter);
+                memmove(papszIter, papszIter+1, sizeof(char*) * (CSLCount(papszIter+1)+1));
+            }
+            else
+                papszIter++;
+        }
+    }
+    poVDS->SetMetadata( papszMetadata );
+    CSLDestroy( papszMetadata );
     AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
 
+    const char* pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
+    if (pszInterleave)
+        poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
+
 /* -------------------------------------------------------------------- */
 /*      Transfer metadata that remains valid if the spatial             */
 /*      arrangement of the data is unaltered.                           */
diff --git a/apps/gdal_utilities.dox b/apps/gdal_utilities.dox
index 7c52f80..728ed33 100644
--- a/apps/gdal_utilities.dox
+++ b/apps/gdal_utilities.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_utilities.dox 21386 2011-01-03 20:17:11Z rouault $ */
+/* $Id: gdal_utilities.dox 23393 2011-11-19 19:06:04Z etourigny $ */
 #endif /* DOXYGEN_SKIP */
 
 /*! 
@@ -30,6 +30,7 @@ The following utility programs are distributed with GDAL.
 <li> \ref gdal_sieve - Raster Sieve filter.
 <li> \ref gdal_fillnodata - Interpolate in nodata regions.
 <li> \ref gdallocationinfo - Query raster at a location.
+<li> \ref gdalsrsinfo - Report a given SRS in different formats.  (GDAL >= 1.9.0)
 <li> \ref gdal-config - Get options required to build software using GDAL.
 </ul>
 
@@ -154,7 +155,7 @@ be influenced by other configuration options.
 Control what debugging messages are emitted.  A value of <i>ON</i> will
 enable all debug messages.  A value of <i>OFF</i> will disable all debug
 messages.  Another value will select only debug messages containing that
-string in the debug prefix code. 
+string in the debug prefix code.  
 </dd>
 
 <dt> <b>--help-general</b></dt><dd>
@@ -166,7 +167,7 @@ and exit.
 
 \htmlonly
 <p>
-$Id: gdal_utilities.dox 21386 2011-01-03 20:17:11Z rouault $
+$Id: gdal_utilities.dox 23393 2011-11-19 19:06:04Z etourigny $
 </p>
 \endhtmlonly
 */
@@ -176,14 +177,15 @@ $Id: gdal_utilities.dox 21386 2011-01-03 20:17:11Z rouault $
 
 lists information about a raster dataset
 
-\section synopsis SYNOPSIS
+\section gdalinfo_synopsis SYNOPSIS
 
 \verbatim
 gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
-         [-noct] [-checksum] [-mdd domain]* datasetname
+         [-noct] [-nofl] [-checksum] [-proj4] [-mdd domain]*
+	 [-sd subdataset] datasetname
 \endverbatim
 
-\section description DESCRIPTION
+\section gdalinfo_description DESCRIPTION
 
 The gdalinfo program lists various information about a GDAL supported
 raster dataset. 
@@ -194,12 +196,19 @@ band in the dataset.</dd>
 <dt> <b>-hist</b></dt><dd> Report histogram information for all bands.</dd>
 <dt> <b>-nogcp</b></dt><dd> Suppress ground control points list printing. It may be
 useful for datasets with huge amount of GCPs, such as L1B AVHRR or HDF4 MODIS
-which contain thousands of the ones.</dd>
+which contain thousands of them.</dd>
 <dt> <b>-nomd</b></dt><dd> Suppress metadata printing. Some datasets may contain a lot
 of metadata strings.</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>-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
+dataset contains several subdatasets read and display a subdataset with
+specified number (starting from 1). This is an alternative of giving the full
+subdataset name.</dd>
+<dt> <b>-proj4</b></dt><dd> (GDAL >= 1.9.0) Report a PROJ.4 string corresponding to the file's coordinate system.</dd>
 </dl>
 
 The gdalinfo will report all of the following (if known):
@@ -226,7 +235,7 @@ the full geotransform (but not GCPs).
 <li> Band pseudo-color tables. 
 </ul>
 
-\section example EXAMPLE
+\section gdalinfo_example EXAMPLE
 
 \verbatim
 gdalinfo ~/openev/utm.tif 
@@ -258,7 +267,7 @@ Band 1 Block=512x16 Type=Byte, ColorInterp=Gray
 \endverbatim
 
 \if man
-\section author AUTHORS
+\section gdalinfo_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -268,7 +277,7 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 converts raster data between different formats
 
-\section tsynopsis SYNOPSIS
+\section gdal_translate_synopsis SYNOPSIS
 
 \verbatim
 gdal_translate [--help-general]
@@ -285,7 +294,7 @@ gdal_translate [--help-general]
        src_dataset dst_dataset
 \endverbatim
 
-\section tdescription DESCRIPTION
+\section gdal_translate_description DESCRIPTION
 
 The gdal_translate utility can be used to convert raster data between 
 different formats, potentially performing some operations like subsettings, 
@@ -362,7 +371,7 @@ 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>
 </dl>
 
-\section texample EXAMPLE
+\section gdal_translate_example EXAMPLE
 
 \verbatim
 gdal_translate -of GTiff -co "TILED=YES" utm.tif utm_tiled.tif
@@ -379,7 +388,7 @@ gdal_translate withmask.tif rgba.tif -b 1 -b 2 -b 3 -b mask
 \endverbatim
 
 \if man
-\section tauthor AUTHORS
+\section gdal_translate_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -389,14 +398,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 builds or rebuilds overview images
 
-\section asynopsis SYNOPSIS
+\section gdaladdo_synopsis SYNOPSIS
 
 \verbatim
 gdaladdo [-r {nearest,average,gauss,cubic,average_mp,average_magphase,mode}]
          [-ro] [-clean] [--help-general] filename levels
 \endverbatim
 
-\section adescription DESCRIPTION
+\section gdaladdo_description DESCRIPTION
 
 The gdaladdo utility can be used to build or rebuild overview images for
 most supported file formats with one over several downsampling algorithms. 
@@ -443,7 +452,7 @@ format.  To trigger this use the USE_RRD=YES configuration option.  This will
 place the overviews in an associated .aux file suitable for direct use with 
 Imagine or ArcGIS as well as GDAL applications.  (eg --config USE_RRD YES)
 
-\section externalgtiffoverviews External overviews in GeoTIFF format
+\section gdaladdo_externalgtiffoverviews External overviews in GeoTIFF format
 
 External overviews created in TIFF format may be compressed using the COMPRESS_OVERVIEW 
 configuration option.  All compression methods, supported by the GeoTIFF 
@@ -476,7 +485,7 @@ documented in the GeoTIFF driver documentation.
 
 See the documentation of the GeoTIFF driver for further explanations on all those options.
 
-\section aexample EXAMPLE
+\section gdaladdo_example EXAMPLE
 
 \htmlonly
 Example:
@@ -510,7 +519,7 @@ gdaladdo --config USE_RRD YES airphoto.jpg 3 9 27 81
 \endverbatim
 
 \if man
-\section aauthor AUTHORS
+\section gdaladdo_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -520,13 +529,13 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 builds a shapefile as a raster tileindex
 
-\section isynopsis SYNOPSIS
+\section gdaltindex_synopsis SYNOPSIS
 
 \verbatim
 gdaltindex [-tileindex field_name] [-write_absolute_path] [-skip_different_projection] index_file [gdal_file]*
 \endverbatim
 
-\section idescription DESCRIPTION
+\section gdaltindex_description DESCRIPTION
 
 This program builds a shapefile with a record for each input raster file, 
 an attribute containing the filename, and a polygon geometry outlining the
@@ -545,7 +554,7 @@ as files already inserted in the tileindex will be inserted.
 coordinate system as the rasters.
 </ul>
 
-\section iexample EXAMPLE
+\section gdaltindex_example EXAMPLE
 
 \htmlonly
 Example:
@@ -556,7 +565,7 @@ gdaltindex doq_index.shp doq/*.tif
 \endverbatim
 
 \if man
-\section wauthor AUTHOR
+\section gdaltindex_author AUTHOR
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
@@ -780,7 +789,7 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 burns vector geometries into a raster
 
-\section zsynopsis SYNOPSIS
+\section gdal_rasterize_synopsis SYNOPSIS
 
 \verbatim
 Usage: gdal_rasterize [-b band]* [-i] [-at]
@@ -794,7 +803,7 @@ Usage: gdal_rasterize [-b band]* [-i] [-at]
        <src_datasource> <dst_filename>
 \endverbatim
 
-\section zdescription DESCRIPTION
+\section gdal_rasterize_description DESCRIPTION
 
 This program burns vector geometries (points, lines and polygons) into the 
 raster band(s) of a raster image.  Vectors are read from OGR supported vector 
@@ -901,7 +910,7 @@ Before GDAL 1.8.0, gdal_rasterize could not create new output files.</dd>
 
 </dl>
 
-\section zexample EXAMPLE
+\section gdal_rasterize_example EXAMPLE
 
 The following would burn all polygons from mask.shp into the RGB TIFF
 file work.tif with the color red (RGB = 255,0,0).  
@@ -918,7 +927,7 @@ gdal_rasterize -a ROOF_H -where 'class="A"' -l footprints footprints.shp city_de
 \endverbatim
 
 \if man
-\section zauthor AUTHORS
+\section gdal_rasterize_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
@@ -928,13 +937,13 @@ Frank Warmerdam <warmerdam at pobox.com>
 
 Convert a 24bit RGB image to 8bit paletted
 
-\section rsynopsis SYNOPSIS
+\section rgb2pct_synopsis SYNOPSIS
 
 \verbatim
 rgb2pct.py [-n colors | -pct palette_file] [-of format] source_file dest_file
 \endverbatim
 
-\section rdescription DESCRIPTION
+\section rgb2pct_description DESCRIPTION
 
 This utility will compute an optimal pseudo-color table for a given RGB image
 using a median cut algorithm on a downsampled RGB histogram.   Then it 
@@ -960,7 +969,7 @@ created.</dd>
 NOTE: rgb2pct.py is a Python script, and will only work if GDAL was built
 with Python support.  
 
-\section example EXAMPLE
+\section rgb2pct_example EXAMPLE
 
 If it is desired to hand create the palette, likely the simpliest text format
 is the GDAL VRT format.  In the following example a VRT was created in a 
@@ -984,7 +993,7 @@ text editor with a small 4 color palette with the RGBA colors 238/238/238/255,
 \endverbatim
 
 \if man
-\section iauthor AUTHOR
+\section rgb2pct_author AUTHOR
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
@@ -994,7 +1003,7 @@ Frank Warmerdam <warmerdam at pobox.com>
 
 Convert an 8bit paletted image to 24bit RGB
 
-\section psynopsis SYNOPSIS
+\section pct2rgb_synopsis SYNOPSIS
 
 \htmlonly
 Usage: 
@@ -1004,7 +1013,7 @@ Usage:
 pct2rgb.py [-of format] [-b band] [-rgba] source_file dest_file
 \endverbatim
 
-\section pdescription DESCRIPTION
+\section pct2rgb_description DESCRIPTION
 
 This utility will convert a pseudocolor band on the input file into an output
 RGB file of the desired format. 
@@ -1025,7 +1034,7 @@ with Python support.
 The new '-expand rgb|rgba' option of gdal_translate obsoletes that utility.
 
 \if man
-\section pauthor AUTHORS
+\section pct2rgb_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -1035,7 +1044,7 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 	
 transforms coordinates 
 
-\section fsynopsis SYNOPSIS
+\section gdaltransform_synopsis SYNOPSIS
 
 \verbatim
 gdaltransform [--help-general]
@@ -1045,7 +1054,7 @@ gdaltransform [--help-general]
     [srcfile [dstfile]]
 \endverbatim
 
-\section fdescription DESCRIPTION
+\section gdaltransform_description DESCRIPTION
 
 The gdaltransform utility reprojects a list of coordinates into any supported
 projection,including  GCP-based transformations.
@@ -1089,7 +1098,7 @@ If an input image file is provided, input is in pixel/line coordinates on that
 image.  If an output file is provided, output is in pixel/line coordinates
 on that image.  
 
-\section fexample Reprojection Example
+\section gdaltransform_example Reprojection Example
 
 Simple reprojection from one projected coordinate system to another:
 
@@ -1105,7 +1114,7 @@ Produces the following output in meters in the "Belge 1972 / Belgian Lambert
 244510.77404604 166154.532871342 -1046.79270555763
 \endverbatim
 
-\section gexample Image RPC Example
+\section gdaltransform_example Image RPC Example
 
 The following command requests an RPC based transformation using the RPC
 model associated with the named file.  Because the -i (inverse) flag is
@@ -1123,7 +1132,7 @@ Produces this output measured in pixels and lines on the image:
 \endverbatim
 
 \if man
-\section fauthor AUTHORS
+\section gdaltransform_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Jan Hartmann <j.l.h.hartmann at uva.nl>
 \endif
 */
@@ -1132,17 +1141,17 @@ Frank Warmerdam <warmerdam at pobox.com>, Jan Hartmann <j.l.h.hartmann at uva.nl>
 
 convert nearly black/white borders to black
 
-\section msynopsis SYNOPSIS
+\section nearblack_synopsis SYNOPSIS
 
 \verbatim
-nearblack [-of format] [-white] [-near dist] [-nb non_black_pixels]
+nearblack [-of format] [-white | [-color c1,c2,c3...cn]*] [-near dist] [-nb non_black_pixels]
           [-setalpha] [-setmask] [-o outfile] [-q]  [-co "NAME=VALUE"]* infile
 \endverbatim
 
-\section mdescription DESCRIPTION
+\section nearblack_description DESCRIPTION
 
-This utility will scan an image and try to set all pixels that are nearly
-black (or nearly white) around the collar to exactly black (or white).  This
+This utility will scan an image and try to set all pixels that are nearly or exactly
+black, white or one or more custom colors around the collar to black or white.  This
 is often used to "fix up" lossy compressed airphotos so that color pixels
 can be treated as transparent when mosaicing. 
 
@@ -1158,8 +1167,12 @@ specific documentation for legal creation options for each format. Only valid wh
 <dt> <b>-white</b>:</dt><dd> 
 Search for nearly white (255) pixels instead of nearly black pixels.
 </dd>
+<dt> <b>-color</b> <i>c1,c2,c3...cn</i>:</dt><dd> (GDAL >= 1.9.0)
+Search for pixels near the specified color. May be specified multiple times.
+When -color is specified, the pixels that are considered as the collar are set to 0.
+</dd>
 <dt> <b>-near</b> <i>dist</i>:</dt><dd> 
-Select how far from black (or white) the pixel values can be and still considered near black (white).  Defaults to 15. 
+Select how far from black, white or custom colors the pixel values can be and still considered near black, white or custom color.  Defaults to 15. 
 </dd>
 <dt> <b>-nb</b> <i>non_black_pixels</i>:</dt><dd> 
 number of non-black pixels that can be encountered before the giving up search inwards. Defaults to 2. 
@@ -1184,10 +1197,10 @@ Byte bands.
 </dl>
 
 The algorithm processes the image one scanline at a time.  A scan "in" is done 
-from either end setting pixels to black (white) until at least 
+from either end setting pixels to black or white until at least 
 "non_black_pixels" pixels that are more than "dist" gray levels away from 
-black (white) have been encountered at which point the scan stops.  The nearly
-black (white) pixels are set to black (white). The algorithm also scans from
+black, white or custom colors have been encountered at which point the scan stops.  The nearly
+black, white or custom color pixels are set to black or white. The algorithm also scans from
 top to bottom and from bottom to top to identify indentations in the top or bottom.
 
 The processing is all done in 8bit (Bytes).
@@ -1196,7 +1209,7 @@ If the output file is omitted, the processed results will be written back
 to the input file - which must support update. 
 
 \if man
-\section mauthor AUTHORS
+\section nearblack_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
@@ -1206,7 +1219,7 @@ Frank Warmerdam <warmerdam at pobox.com>
 
 mosaics a set of images
 
-\section gsynopsis SYNOPSIS
+\section gdal_merge_synopsis SYNOPSIS
 
 \verbatim
 gdal_merge.py [-o out_filename] [-of out_format] [-co NAME=VALUE]*
@@ -1215,7 +1228,7 @@ gdal_merge.py [-o out_filename] [-of out_format] [-co NAME=VALUE]*
               [-ot datatype] [-createonly] input_files
 \endverbatim
 
-\section gdescription DESCRIPTION
+\section gdal_merge_description DESCRIPTION
 
 This utility will automatically mosaic a set of images.  All the images must
 be in the same coordinate system and have a matching number of bands, but 
@@ -1258,6 +1271,8 @@ color table.
 <dt> <b>-n</b> <i>nodata_value</i>:</dt><dd> 
 Ignore pixels from files being merged in with this pixel value. 
 </dd>
+<dt> <b>-a_nodata</b> <i>output_nodata_value</i>:</dt><dd>
+(GDAL >= 1.9.0) Assign a specified nodata value to output bands.</dd>
 <dt> <b>-init</b> <i>"value(s)"</i>:</dt><dd> 
 Pre-initialize the output image bands with these values.  However, it is not
 marked as the nodata value in the output file.  If only one value is given, the
@@ -1272,7 +1287,7 @@ image data is copied into it.
 NOTE: gdal_merge.py is a Python script, and will only work if GDAL was built
 with Python support.
 
-\section example EXAMPLE
+\section gdal_merge_example EXAMPLE
 
 Create an image with the pixels in all bands initialized to 255.
 
@@ -1288,7 +1303,7 @@ will be initialized to 0 and the third band will be initalized to 255.
 \endverbatim
 
 \if man
-\section gauthor AUTHORS
+\section gdal_merge_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -1323,22 +1338,52 @@ World files and embedded georeference is used during tile generation, but you
 can publish a picture without proper georeference too. 
 
 <dl>
-<dt> <b>-title</b> <i>"Title"</i>:</dt>
-  <dd>Title used for generated metadata, web viewers and KML files.</dd>
-<dt> <b>-publishurl</b> <i>http://yourserver/dir/</i>:</dt>
-  <dd>Address of a directory into which you are going to upload the result. It should end with slash.</dd>
-<dt> <b>-nogooglemaps</b>:</dt>
-  <dd>Do not generate Google Maps based html page.</dd>
-<dt> <b>-noopenlayers</b>:</dt>
-  <dd>Do not generate OpenLayers based html page.</dd>
-<dt> <b>-nokml</b>:</dt>
-  <dd>Do not generate KML files for Google Earth.</dd>
-<dt> <b>-googlemapskey</b> <i>KEY</i>:</dt>
-  <dd>Key for your domain generated on Google Maps API web page (http://www.google.com/apis/maps/signup.html).</dd>
-<dt> <b>-forcekml</b></dt>
-  <dd>Force generating of KML files. Input file must use EPSG:4326 coordinates!</dd>
-<dt> <b>-v</b></dt>
-  <dd> Generate verbose output of tile generation.</dd>
+<dt> <b>-p</b> <i>PROFILE</i>, --profile=<i>PROFILE</i>:</dt>
+  <dd>Tile cutting profile (mercator,geodetic,raster) - default 'mercator' (Google Maps compatible).</dd>
+<dt> <b>-r</b> <i>RESAMPLING</i>, --resampling=<i>RESAMPLING</i>:</dt>
+  <dd>Resampling method (average,near,bilinear,cubic,cubicspline,lanczos,antialias) - default 'average'.</dd>
+<dt> <b>-s</b> <i>SRS</i>, --s_srs=<i>SRS</i>:</dt>
+  <dd>The spatial reference system used for the source input data.</dd>
+<dt> <b>-z</b> <i>ZOOM</i>, --zoom=<i>ZOOM</i>:</dt>
+  <dd>Zoom levels to render (format:'2-5' or '10').</dd>
+<dt> <b>-e</b>, --resume:</dt>
+  <dd>Resume mode. Generate only missing files.</dd>
+<dt> <b>-a</b> <i>NODATA</i>, --srcnodata=<i>NODATA</i>:</dt>
+  <dd>NODATA transparency value to assign to the input data.</dd>
+<dt> <b>-v, --verbose</b></dt>
+  <dd>Generate verbose output of tile generation.</dd>
+<dt> <b>-h, --help</b></dt>
+  <dd>Show help message and exit.</dd>
+<dt> <b>--version</b></dt>
+  <dd>Show program's version number and exit.</dd>
+</dl>
+
+<b>KML (Google Earth) options:</b>
+
+Options for generated Google Earth SuperOverlay metadata
+<dl>
+<dt> <b>-k, --force-kml</b></dt>
+  <dd>Generate KML for Google Earth - default for 'geodetic' profile and 'raster' in EPSG:4326. For a dataset with different projection use with caution!</dd>
+<dt> <b>-n, --no-kml</b>:</dt>
+  <dd>Avoid automatic generation of KML files for EPSG:4326.</dd>
+<dt> <b>-u</b> <i>URL</i>, --url=<i>URL</i>:</dt>
+  <dd>URL address where the generated tiles are going to be published.</dd>
+</dl>
+
+<b>Web viewer options:</b>
+
+Options for generated HTML viewers a la Google Maps
+<dl>
+<dt> <b>-w</b> <i>WEBVIEWER</i>, --webviewer=<i>WEBVIEWER</i>:</dt>
+  <dd>Web viewer to generate (all,google,openlayers,none) - default 'all'.</dd>
+<dt> <b>-t</b> <i>TITLE</i>, --title=<i>TITLE</i>:</dt>
+  <dd>Title of the map.</dd>
+<dt> <b>-c</b> <i>COPYRIGHT</i>, --copyright=<i>COPYRIGHT</i>:</dt>
+  <dd>Copyright for the map.</dd>
+<dt> <b>-g</b> <i>GOOGLEKEY</i>, --googlekey=<i>GOOGLEKEY</i>:</dt>
+  <dd>Google Maps API key from http://code.google.com/apis/maps/signup.html.</dd>
+<dt> <b>-y</b> <i>YAHOOKEY</i>, --yahookey=<i>YAHOOKEY</i>:</dt>
+  <dd>Yahoo Application ID from http://developer.yahoo.com/wsregapp/.</dd>
 </dl>
 
 
@@ -1355,7 +1400,7 @@ Klokan Petr Pridal <klokan at klokan.cz> as a Google SoC 2007 Project.
 
 determines various information about a GDAL installation
 
-\section csynopsis SYNOPSIS
+\section gdal_config_synopsis SYNOPSIS
 
 \verbatim
 gdal-config [OPTIONS]
@@ -1368,7 +1413,7 @@ Options:
         [--formats]
 \endverbatim
 
-\section cdescription DESCRIPTION
+\section gdal_config_description DESCRIPTION
 
 This utility script (available on Unix systems) can be used to determine
 various information about a GDAL installation.  It is normally just used
@@ -1975,7 +2020,7 @@ The following specifics options are available :
 <dt> <b>-nearest_color_entry</b> :</dt><dd></dd>use the RGBA quadruplet corresponding to the closest entry in the color configuration file.</dd>
 </dl>
 
-The color-relief mode is the only mode that supports VRT as output format. In that case, it will translate the color configuration file into appropriate <LUT> elements. Note that elevations specified as percentage will be translated as absolute values, which must be taken into account when the statistics of the source raster differ from the one that was used when building the VRT.
+The color-relief mode is the only mode that supports VRT as output format. In that case, it will translate the color configuration file into appropriate LUT elements. Note that elevations specified as percentage will be translated as absolute values, which must be taken into account when the statistics of the source raster differ from the one that was used when building the VRT.
 
 The text-based color configuration file generally contains 4 columns per line : the elevation value and the
 corresponding Red, Green, Blue component (between 0 and 255).
@@ -2051,3 +2096,156 @@ http://grass.osgeo.org/grass64/manuals/html64_user/r.shaded.relief.html
 http://grass.osgeo.org/grass64/manuals/html64_user/r.colors.html
 
 */
+
+
+*******************************************************************************
+/*! \page gdalsrsinfo gdalsrsinfo
+	
+lists info about a given SRS in number of formats (WKT, PROJ.4, etc.)
+
+\section gdalsrsinfo_synopsis SYNOPSIS
+
+\verbatim
+Usage: gdalsrsinfo [options] srs_def
+
+srs_def may be the filename of a dataset supported by GDAL/OGR from which to extract SRS information
+OR any of the usual GDAL/OGR forms (complete WKT, PROJ.4, EPSG:n or a file containing the SRS)
+
+Options: 
+   [--help-general] [-h]  Show help and exit
+   [-p]                   Pretty-print where applicable (e.g. WKT)
+   [-V]                   Validate SRS
+   [-o out_type]          Output type { default, all, wkt_all, proj4,
+                                        wkt, wkt_simple, wkt_noct, wkt_esri,
+                                        mapinfo, xml }
+
+\endverbatim
+
+\section gdalsrsinfo_description DESCRIPTION
+
+The gdalsrsinfo utility reports information about a given SRS from one of the following:
+
+- The filename of a dataset supported by GDAL/OGR which contains SRS information
+- Any of the usual GDAL/OGR forms (complete WKT, PROJ.4, EPSG:n or a file containing the SRS)
+
+Output types:
+
+- <b>default</b>   proj4 and wkt (default option)
+- <b>all</b>   all options available
+- <b>wkt_all</b>   all wkt options available
+- <b>proj4</b>   PROJ.4 string
+- <b>wkt</b>   OGC WKT format (full)
+- <b>wkt_simple</b>   OGC WKT (simplified)
+- <b>wkt_noct</b>   OGC WKT (without OGC CT params)
+- <b>wkt_esri</b>   ESRI WKT format
+- <b>mapinfo</b>   Mapinfo style CoordSys format
+- <b>xml</b>   XML format (GML based)
+
+\n
+\section gdal_grid_example EXAMPLE
+
+\verbatim
+$  gdalsrsinfo   "EPSG:4326"
+
+PROJ.4 : '+proj=longlat +datum=WGS84 +no_defs '
+
+OGC WKT :
+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"]]
+
+\endverbatim
+
+\n
+\verbatim
+$ gdalsrsinfo -o proj4 osr/data/lcc_esri.prj
+'+proj=lcc +lat_1=34.33333333333334 +lat_2=36.16666666666666 +lat_0=33.75 +lon_0=-79 +x_0=609601.22 +y_0=0 +datum=NAD83 +units=m +no_defs '
+\endverbatim
+
+\n
+\verbatim
+$ gdalsrsinfo -o proj4 landsat.tif
+PROJ.4 : '+proj=utm +zone=19 +south +datum=WGS84 +units=m +no_defs '
+\endverbatim
+
+\n
+\verbatim
+$ gdalsrsinfo  -o wkt -p  "EPSG:32722"
+
+PROJCS["WGS 84 / UTM zone 22S",
+    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"]],
+    PROJECTION["Transverse_Mercator"],
+    PARAMETER["latitude_of_origin",0],
+    PARAMETER["central_meridian",-51],
+    PARAMETER["scale_factor",0.9996],
+    PARAMETER["false_easting",500000],
+    PARAMETER["false_northing",10000000],
+    UNIT["metre",1,
+        AUTHORITY["EPSG","9001"]],
+    AXIS["Easting",EAST],
+    AXIS["Northing",NORTH],
+    AUTHORITY["EPSG","32722"]]
+\endverbatim
+
+\n
+\verbatim
+$ gdalsrsinfo  -o wkt_all  "EPSG:4618"
+
+OGC WKT :
+GEOGCS["SAD69",
+    DATUM["South_American_Datum_1969",
+        SPHEROID["GRS 1967 Modified",6378160,298.25,
+            AUTHORITY["EPSG","7050"]],
+        TOWGS84[-57,1,-41,0,0,0,0],
+        AUTHORITY["EPSG","6618"]],
+    PRIMEM["Greenwich",0,
+        AUTHORITY["EPSG","8901"]],
+    UNIT["degree",0.0174532925199433,
+        AUTHORITY["EPSG","9122"]],
+    AUTHORITY["EPSG","4618"]]
+
+OGC WKT (simple) :
+GEOGCS["SAD69",
+    DATUM["South_American_Datum_1969",
+        SPHEROID["GRS 1967 Modified",6378160,298.25],
+        TOWGS84[-57,1,-41,0,0,0,0]],
+    PRIMEM["Greenwich",0],
+    UNIT["degree",0.0174532925199433]]
+
+OGC WKT (no CT) :
+GEOGCS["SAD69",
+    DATUM["South_American_Datum_1969",
+        SPHEROID["GRS 1967 Modified",6378160,298.25]],
+    PRIMEM["Greenwich",0],
+    UNIT["degree",0.0174532925199433]]
+
+ESRI WKT :
+GEOGCS["SAD69",
+    DATUM["D_South_American_1969",
+        SPHEROID["GRS_1967_Truncated",6378160,298.25]],
+    PRIMEM["Greenwich",0],
+    UNIT["Degree",0.017453292519943295]]
+\endverbatim
+
+
+\if man
+\section gdalsrsinfo_author AUTHORS
+Frank Warmerdam <warmerdam at pobox.com>, Etienne Tourigny <etourigny.dev-at-gmail-dot-com>
+\endif
+*/
diff --git a/apps/gdaldem.cpp b/apps/gdaldem.cpp
index 4ded6d9..437dceb 100644
--- a/apps/gdaldem.cpp
+++ b/apps/gdaldem.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldem.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: gdaldem.cpp 22857 2011-08-02 18:17:45Z rouault $
  *
  * Project:  GDAL DEM Utilities
  * Purpose:  
@@ -89,14 +89,15 @@
 #include "cpl_string.h"
 #include "gdal.h"
 #include "gdal_priv.h"
+#include "commonutils.h"
 
-CPL_CVSID("$Id: gdaldem.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: gdaldem.cpp 22857 2011-08-02 18:17:45Z rouault $");
 
 #ifndef M_PI
 # define M_PI  3.1415926535897932384626433832795
 #endif
 
-#define INTERPOL(a,b) ((bSrcHasNoData && (EQUAL_TO_NODATA(a, fSrcNoDataValue) || EQUAL_TO_NODATA(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
+#define INTERPOL(a,b) ((bSrcHasNoData && (ARE_REAL_EQUAL(a, fSrcNoDataValue) || ARE_REAL_EQUAL(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -162,7 +163,7 @@ static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
                         void* pData,
                         int bComputeAtEdges)
 {
-    if (bSrcHasNoData && EQUAL_TO_NODATA(afWin[4], fSrcNoDataValue))
+    if (bSrcHasNoData && ARE_REAL_EQUAL(afWin[4], fSrcNoDataValue))
     {
         return fDstNoDataValue;
     }
@@ -171,7 +172,7 @@ static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
         int k;
         for(k=0;k<9;k++)
         {
-            if (EQUAL_TO_NODATA(afWin[k], fSrcNoDataValue))
+            if (ARE_REAL_EQUAL(afWin[k], fSrcNoDataValue))
             {
                 if (bComputeAtEdges)
                     afWin[k] = afWin[4];
@@ -2119,7 +2120,7 @@ typedef enum
 int main( int argc, char ** argv )
 
 {
-    Algorithm eUtilityMode;
+    Algorithm eUtilityMode = HILL_SHADE;
     double z = 1.0;
     double scale = 1.0;
     double az = 315.0;
@@ -2138,6 +2139,7 @@ int main( int argc, char ** argv )
     const char *pszDstFilename = NULL;
     const char *pszColorFilename = NULL;
     const char *pszFormat = "GTiff";
+    int bFormatExplicitelySet = FALSE;
     char **papszCreateOptions = NULL;
     
     GDALDatasetH hSrcDataset = NULL;
@@ -2153,6 +2155,8 @@ int main( int argc, char ** argv )
     
     int bComputeAtEdges = FALSE;
     int bZevenbergenThorne = FALSE;
+
+    int bQuiet = FALSE;
     
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(argv[0]))
@@ -2294,6 +2298,7 @@ int main( int argc, char ** argv )
         else if ( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
         {
             pfnProgress = GDALDummyProgress;
+            bQuiet = TRUE;
         }
         else if( EQUAL(argv[i],"-co") && i < argc-1 )
         {
@@ -2302,6 +2307,7 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i],"-of") && i < argc-1 )
         {
             pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
         }
         else if( argv[i][0] == '-' )
         {
@@ -2397,6 +2403,9 @@ int main( int argc, char ** argv )
         exit( 1 );
     }
 
+    if (!bQuiet && !bFormatExplicitelySet)
+        CheckExtensionConsistency(pszDstFilename, pszFormat);
+
     double dfDstNoDataValue = 0;
     int bDstHasNoData = FALSE;
     void* pData = NULL;
diff --git a/apps/gdalenhance.cpp b/apps/gdalenhance.cpp
index a6dbc34..7e4f25b 100644
--- a/apps/gdalenhance.cpp
+++ b/apps/gdalenhance.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalenhance.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: gdalenhance.cpp 22783 2011-07-23 19:28:16Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline application to do image enhancement. 
@@ -32,8 +32,9 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 #include "vrt/vrtdataset.h"
+#include "commonutils.h"
 
-CPL_CVSID("$Id: gdalenhance.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: gdalenhance.cpp 22783 2011-07-23 19:28:16Z rouault $");
 
 static int
 ComputeEqualizationLUTs( GDALDatasetH hDataset,  int nLUTBins,
@@ -87,6 +88,7 @@ int main( int argc, char ** argv )
     GDALDatasetH	hDataset, hOutDS;
     int			i;
     const char		*pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
+    int bFormatExplicitelySet = FALSE;
     GDALDriverH		hDriver;
     GDALDataType	eOutputType = GDT_Unknown;
     char                **papszCreateOptions = NULL;
@@ -99,6 +101,7 @@ int main( int argc, char ** argv )
     int               **papanLUTs = NULL;
     int                 iBand;
     const char         *pszConfigFile = NULL;
+    int                 bQuiet = FALSE;
 
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(argv[0]))
@@ -124,7 +127,10 @@ int main( int argc, char ** argv )
             return 0;
         }
         else if( EQUAL(argv[i],"-of") && i < argc-1 )
+        {
             pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
+        }
 
         else if( EQUAL(argv[i],"-ot") && i < argc-1 )
         {
@@ -184,6 +190,7 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i],"-quiet") )
         {
             pfnProgress = GDALDummyProgress;
+            bQuiet = TRUE;
         }
 
         else if( argv[i][0] == '-' )
@@ -257,6 +264,9 @@ int main( int argc, char ** argv )
         Usage();
     }
 
+    if (!bQuiet && pszDest != NULL && !bFormatExplicitelySet)
+        CheckExtensionConsistency(pszDest, pszFormat);
+
 /* -------------------------------------------------------------------- */
 /*      If histogram equalization is requested, do it now.              */
 /* -------------------------------------------------------------------- */
@@ -609,9 +619,9 @@ static CPLErr EnhancerCallback( void *hCBData,
         iBin = MAX(0,MIN(psEInfo->nLUTBins-1,iBin));
 
         if( psEInfo->panLUT )
-            pabyOutImage[iPixel] = psEInfo->panLUT[iBin];
+            pabyOutImage[iPixel] = (GByte) psEInfo->panLUT[iBin];
         else
-            pabyOutImage[iPixel] = iBin;
+            pabyOutImage[iPixel] = (GByte) iBin;
     }
 
     CPLFree( pafSrcImage );
diff --git a/apps/gdalinfo.c b/apps/gdalinfo.c
index 7111c48..ce8633e 100644
--- a/apps/gdalinfo.c
+++ b/apps/gdalinfo.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalinfo.c 19692 2010-05-13 17:16:55Z rouault $
+ * $Id: gdalinfo.c 23245 2011-10-17 06:55:42Z etourigny $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline application to list info about a file.
@@ -34,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalinfo.c 19692 2010-05-13 17:16:55Z rouault $");
+CPL_CVSID("$Id: gdalinfo.c 23245 2011-10-17 06:55:42Z etourigny $");
 
 static int 
 GDALInfoReportCorner( GDALDatasetH hDataset, 
@@ -50,7 +50,8 @@ void Usage()
 
 {
     printf( "Usage: gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n"
-            "                [-norat] [-noct] [-checksum] [-mdd domain]* datasetname\n" );
+            "                [-norat] [-noct] [-nofl] [-checksum] [-proj4] [-mdd domain]*\n"
+            "                [-sd subdataset] datasetname\n" );
     exit( 1 );
 }
 
@@ -58,7 +59,7 @@ void Usage()
 /*                                main()                                */
 /************************************************************************/
 
-int main( int argc, char ** argv )
+int main( int argc, char ** argv ) 
 
 {
     GDALDatasetH	hDataset;
@@ -72,10 +73,13 @@ int main( int argc, char ** argv )
     int                 bStats = FALSE, bApproxStats = TRUE, iMDD;
     int                 bShowColorTable = TRUE, bComputeChecksum = FALSE;
     int                 bReportHistograms = FALSE;
+    int                 bReportProj4 = FALSE;
+    int                 nSubdataset = -1;
     const char          *pszFilename = NULL;
     char              **papszExtraMDDomains = NULL, **papszFileList;
     const char  *pszProjection = NULL;
     OGRCoordinateTransformationH hTransform = NULL;
+    int             bShowFileList = TRUE;
 
     /* Check that we are running against at least GDAL 1.5 */
     /* Note to developers : if we use newer API, please change the requirement */
@@ -121,6 +125,8 @@ int main( int argc, char ** argv )
             bComputeMinMax = TRUE;
         else if( EQUAL(argv[i], "-hist") )
             bReportHistograms = TRUE;
+        else if( EQUAL(argv[i], "-proj4") )
+            bReportProj4 = TRUE;
         else if( EQUAL(argv[i], "-stats") )
         {
             bStats = TRUE;
@@ -146,6 +152,10 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i], "-mdd") && i < argc-1 )
             papszExtraMDDomains = CSLAddString( papszExtraMDDomains,
                                                 argv[++i] );
+        else if( EQUAL(argv[i], "-nofl") )
+            bShowFileList = FALSE;
+        else if( EQUAL(argv[i], "-sd") && i < argc-1 )
+            nSubdataset = atoi(argv[++i]);
         else if( argv[i][0] == '-' )
             Usage();
         else if( pszFilename == NULL )
@@ -181,6 +191,38 @@ int main( int argc, char ** argv )
     }
     
 /* -------------------------------------------------------------------- */
+/*      Read specified subdataset if requested.                         */
+/* -------------------------------------------------------------------- */
+    if ( nSubdataset > 0 )
+    {
+        char **papszSubdatasets = GDALGetMetadata( hDataset, "SUBDATASETS" );
+        int nSubdatasets = CSLCount( papszSubdatasets );
+
+        if ( nSubdatasets > 0 && nSubdataset <= nSubdatasets )
+        {
+            char szKeyName[1024];
+            char *pszSubdatasetName;
+
+            snprintf( szKeyName, sizeof(szKeyName),
+                      "SUBDATASET_%d_NAME", nSubdataset );
+            szKeyName[sizeof(szKeyName) - 1] = '\0';
+            pszSubdatasetName =
+                CPLStrdup( CSLFetchNameValue( papszSubdatasets, szKeyName ) );
+            GDALClose( hDataset );
+            hDataset = GDALOpen( pszSubdatasetName, GA_ReadOnly );
+            CPLFree( pszSubdatasetName );
+        }
+        else
+        {
+            fprintf( stderr,
+                     "gdalinfo warning: subdataset %d of %d requested. "
+                     "Reading the main dataset.\n",
+                     nSubdataset, nSubdatasets );
+
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Report general info.                                            */
 /* -------------------------------------------------------------------- */
     hDriver = GDALGetDatasetDriver( hDataset );
@@ -196,8 +238,11 @@ int main( int argc, char ** argv )
     else
     {
         printf( "Files: %s\n", papszFileList[0] );
-        for( i = 1; papszFileList[i] != NULL; i++ )
-            printf( "       %s\n", papszFileList[i] );
+        if( bShowFileList )
+        {
+            for( i = 1; papszFileList[i] != NULL; i++ )
+                printf( "       %s\n", papszFileList[i] );
+        }
     }
     CSLDestroy( papszFileList );
 
@@ -228,6 +273,14 @@ int main( int argc, char ** argv )
             printf( "Coordinate System is `%s'\n",
                     GDALGetProjectionRef( hDataset ) );
 
+        if ( bReportProj4 ) 
+        {
+            char *pszProj4 = NULL;
+            OSRExportToProj4( hSRS, &pszProj4 );
+            printf("PROJ.4 string is:\n\'%s\'\n",pszProj4);
+            CPLFree( pszProj4 ); 
+        }
+
         OSRDestroySpatialReference( hSRS );
     }
 
@@ -319,7 +372,10 @@ int main( int argc, char ** argv )
             printf( "Metadata (%s):\n", papszExtraMDDomains[iMDD]);
             for( i = 0; papszMetadata[i] != NULL; i++ )
             {
-                printf( "  %s\n", papszMetadata[i] );
+                if (EQUALN(papszExtraMDDomains[iMDD], "xml:", 4))
+                    printf( "%s\n", papszMetadata[i] );
+                else
+                    printf( "  %s\n", papszMetadata[i] );
             }
         }
     }
diff --git a/apps/gdallocationinfo.cpp b/apps/gdallocationinfo.cpp
index 28e85cb..099cc98 100644
--- a/apps/gdallocationinfo.cpp
+++ b/apps/gdallocationinfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdallocationinfo.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: gdallocationinfo.cpp 23155 2011-10-01 15:03:13Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Commandline raster query tool.
@@ -33,14 +33,14 @@
 #include "cpl_minixml.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdallocationinfo.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: gdallocationinfo.cpp 23155 2011-10-01 15:03:13Z rouault $");
 
 /******************************************************************************/
 /*! \page gdallocationinfo gdallocationinfo
 
 raster query tool
 
-\section wsynopsis SYNOPSIS
+\section gdallocationinfo_synopsis SYNOPSIS
 
 \htmlonly
 Usage: 
@@ -52,7 +52,7 @@ Usage: gdallocationinfo [--help-general] [-xml] [-lifonly] [-valonly]
                         srcfile [x y]
 \endverbatim
 
-\section wdescription DESCRIPTION
+\section gdallocationinfo_description DESCRIPTION
 
 <p>
 The gdallocationinfo utility provide a mechanism to query information about
@@ -124,7 +124,7 @@ It is anticipated that additional reporting capabilities will be added to
 gdallocationinfo in the future. 
 
 <p>
-\section wexample EXAMPLE
+\section gdallocationinfo_example EXAMPLE
 
 Simple example reporting on pixel (256,256) on the file utm.tif.
 
@@ -151,7 +151,7 @@ $ gdallocationinfo -xml -wgs84 utm.vrt -117.5 33.75
 \endverbatim
 
 \if man
-\section wauthor AUTHORS
+\section gdallocationinfo_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
@@ -384,7 +384,9 @@ int main( int argc, char ** argv )
             printf( "Report:\n" );
             printf( "  Location: (%dP,%dL)\n", iPixel, iLine );
         }
-    
+
+        int bPixelReport = TRUE;
+
         if( iPixel < 0 || iLine < 0 
             || iPixel >= GDALGetRasterXSize( hSrcDS )
             || iLine  >= GDALGetRasterYSize( hSrcDS ) )
@@ -395,13 +397,13 @@ int main( int argc, char ** argv )
                 printf("\n");
             else if( !bQuiet )
                 printf( "\nLocation is off this file! No further details to report.\n");
-            anBandList.clear();
+            bPixelReport = FALSE;
         }
         
     /* -------------------------------------------------------------------- */
     /*      Process each band.                                              */
     /* -------------------------------------------------------------------- */
-        for( i = 0; i < (int) anBandList.size(); i++ )
+        for( i = 0; bPixelReport && i < (int) anBandList.size(); i++ )
         {
             GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, anBandList[i] );
             if (hBand == NULL)
diff --git a/apps/gdalsrsinfo.cpp b/apps/gdalsrsinfo.cpp
new file mode 100644
index 0000000..00b602d
--- /dev/null
+++ b/apps/gdalsrsinfo.cpp
@@ -0,0 +1,638 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Commandline application to list info about a given CRS.
+ *           Outputs a number of formats (WKT, PROJ.4, etc.).
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *           Etienne Tourigny, etourigny.dev-at-gmail-dot-com       
+ *
+ * ****************************************************************************
+ * Copyright (c) 1998, Frank Warmerdam
+ *
+ * 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_priv.h"
+#include "cpl_string.h"
+#include "ogr_spatialref.h"
+#include "ogr_api.h"
+#include "ogrsf_frmts.h"
+
+CPL_CVSID("$Id$");
+
+int FindSRS( const char *pszInput, OGRSpatialReference &oSRS, int bDebug );
+CPLErr PrintSRS( const OGRSpatialReference &oSRS, 
+                 const char * pszOutputType, 
+                 int bPretty, int bPrintSep );
+void PrintSRSOutputTypes( const OGRSpatialReference &oSRS, 
+                          const char ** papszOutputTypes );
+int FindEPSG( const OGRSpatialReference &oSRS );
+int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget );
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+void Usage()
+
+{
+    printf( "\nUsage: gdalsrsinfo [options] srs_def\n"
+            "\n"
+            "srs_def may be the filename of a dataset supported by GDAL/OGR "
+            "from which to extract SRS information\n"
+            "OR any of the usual GDAL/OGR forms "
+            "(complete WKT, PROJ.4, EPSG:n or a file containing the SRS)\n"
+            "\n"          
+            "Options: \n"
+            "   [--help-general] [-h]  Show help and exit\n"
+            "   [-p]                   Pretty-print where applicable (e.g. WKT)\n"
+            "   [-V]                   Validate SRS\n"
+            "   [-e]                   Search for EPSG number corresponding to SRS (experimental)\n"
+            "   [-o out_type]          Output type { default, all, wkt_all,\n"
+            "                                        proj4, epsg,\n"
+            "                                        wkt, wkt_simple, wkt_noct, wkt_esri,\n"
+            "                                        mapinfo, xml }\n\n" ); 
+    exit( 1 );
+}
+
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int argc, char ** argv ) 
+
+{
+    int            i;
+    int            bGotSRS = FALSE;
+    int            bPretty = FALSE;
+    int            bValidate = FALSE;
+    int            bDebug = FALSE;
+    int            bFindEPSG = FALSE;
+    int            nEPSGCode = -1;
+    const char     *pszInput = NULL;
+    const char     *pszOutputType = "default";
+    OGRSpatialReference  oSRS;
+
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    /* Must process GDAL_SKIP before GDALAllRegister(), but we can't call */
+    /* GDALGeneralCmdLineProcessor before it needs the drivers to be registered */
+    /* for the --format or --formats options */
+    for( i = 1; i < argc; i++ )
+    {
+        if( EQUAL(argv[i],"--config") && i + 2 < argc && EQUAL(argv[i + 1], "GDAL_SKIP") )
+        {
+            CPLSetConfigOption( argv[i+1], argv[i+2] );
+
+            i += 2;
+        }
+    }
+
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    for( i = 1; i < argc; i++ )
+    {
+        CPLDebug( "gdalsrsinfo", "got arg #%d : [%s]", i, argv[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], "-h") )
+            Usage();
+        else if( EQUAL(argv[i], "-e") )
+            bFindEPSG = TRUE;
+        else if( EQUAL(argv[i], "-o") && i < argc - 1)
+            pszOutputType = argv[++i];
+        else if( EQUAL(argv[i], "-p") )
+            bPretty = TRUE;
+        else if( EQUAL(argv[i], "-V") )
+            bValidate = TRUE;
+        else if( argv[i][0] == '-' )
+        {
+            CSLDestroy( argv );
+            Usage();
+        }
+        else  
+            pszInput = argv[i];
+    }
+
+    if ( pszInput == NULL ) {
+        CSLDestroy( argv );
+        Usage();
+    }
+
+    /* Register drivers */
+    GDALAllRegister();
+    OGRRegisterAll();
+
+    /* Search for SRS */
+    bGotSRS = FindSRS( pszInput, oSRS, bDebug );
+
+    CPLDebug( "gdalsrsinfo", 
+              "bGotSRS: %d bValidate: %d pszOutputType: %s bPretty: %d",
+              bGotSRS, bValidate, pszOutputType, bPretty  );
+      
+
+    /* Make sure we got a SRS */
+    if ( ! bGotSRS ) {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ERROR - failed to load SRS definition from %s",
+                  pszInput );
+    }
+
+    else {
+
+        /* Find EPSG code - experimental */
+        if ( EQUAL(pszOutputType,"epsg") )
+            bFindEPSG = TRUE;
+        if ( bFindEPSG ) {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "EPSG detection is experimental and requires new data files (see bug #4345)" );
+            nEPSGCode = FindEPSG( oSRS );
+            /* If found, replace oSRS based on EPSG code */
+            if(nEPSGCode != -1) {
+                CPLDebug( "gdalsrsinfo", 
+                          "Found EPSG code %d", nEPSGCode );
+                OGRSpatialReference oSRS2;
+                if ( oSRS2.importFromEPSG( nEPSGCode ) == OGRERR_NONE )
+                    oSRS = oSRS2;
+            }
+        }
+        /* Validate - not well tested!*/
+        if ( bValidate ) {
+            OGRErr eErr = oSRS.Validate( );
+            if ( eErr != OGRERR_NONE ) {
+                printf( "\nValidate Fails" );
+                if ( eErr == OGRERR_CORRUPT_DATA )
+                    printf( " - SRS is not well formed");
+                else if ( eErr == OGRERR_UNSUPPORTED_SRS )
+                    printf(" - contains non-standard PROJECTION[] values");
+                printf("\n");
+            }
+            else
+                printf( "\nValidate Succeeds\n" );
+        }
+        
+        /* Output */
+        if ( EQUAL("default", pszOutputType ) ) {
+            /* does this work in MSVC? */
+            const char* papszOutputTypes[] = 
+                { "proj4", "wkt", NULL };      
+            if ( bFindEPSG ) 
+                printf("\nEPSG:%d\n",nEPSGCode);
+            PrintSRSOutputTypes( oSRS, papszOutputTypes );
+        }
+        else if ( EQUAL("all", pszOutputType ) ) {
+            if ( bFindEPSG ) 
+                printf("\nEPSG:%d\n\n",nEPSGCode);
+            const char* papszOutputTypes[] = 
+                {"proj4","wkt","wkt_simple","wkt_noct","wkt_esri","mapinfo","xml",NULL};
+            PrintSRSOutputTypes( oSRS, papszOutputTypes );
+        }
+        else if ( EQUAL("wkt_all", pszOutputType ) ) {
+            const char* papszOutputTypes[] = 
+                { "wkt", "wkt_simple", "wkt_noct", "wkt_esri", NULL };
+            PrintSRSOutputTypes( oSRS, papszOutputTypes );
+        }
+        else {
+            if ( bPretty )
+                printf( "\n" );
+            if ( EQUAL(pszOutputType,"epsg") )
+                printf("EPSG:%d\n",nEPSGCode);
+            else
+                PrintSRS( oSRS, pszOutputType, bPretty, FALSE );
+            if ( bPretty )
+                printf( "\n" );        
+        }
+
+    }
+
+    /* cleanup anything left */
+    GDALDestroyDriverManager();
+    OGRCleanupAll();
+    CSLDestroy( argv );
+
+    return 0;
+}
+
+/************************************************************************/
+/*                      FindSRS()                                       */
+/*                                                                      */
+/*      Search for SRS from pszInput, update oSRS.                      */
+/************************************************************************/
+int FindSRS( const char *pszInput, OGRSpatialReference &oSRS, int bDebug )
+
+{
+    int            bGotSRS = FALSE;
+    VSILFILE      *fp = NULL;
+    GDALDataset	  *poGDALDS = NULL; 
+    OGRDataSource *poOGRDS = NULL;
+    OGRLayer      *poLayer = NULL;
+    char           *pszProjection = NULL;
+    CPLErrorHandler oErrorHandler = NULL;
+    int bIsFile = FALSE;
+    OGRErr eErr = CE_None;
+      
+    /* temporarily supress error messages we may get from xOpen() */
+    if ( ! bDebug )
+        oErrorHandler = CPLSetErrorHandler ( CPLQuietErrorHandler );
+
+    /* If argument is a file, try to open it with GDAL and OGROpen() */
+    fp = VSIFOpenL( pszInput, "r" );
+    if ( fp )  {
+        
+        bIsFile = TRUE;
+        VSIFCloseL( fp );
+        
+        /* try to open with GDAL */
+        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 ) {
+                CPLDebug( "gdalsrsinfo", "got SRS from GDAL" );
+                bGotSRS = TRUE;
+            }
+            GDALClose( (GDALDatasetH) poGDALDS );
+        }
+        if ( ! bGotSRS ) 
+            CPLDebug( "gdalsrsinfo", "did not open with GDAL" );
+        
+        /* if unsuccessful, try to open with OGR */
+        if ( ! bGotSRS ) {
+            CPLDebug( "gdalsrsinfo", "trying to open with OGR" );
+            poOGRDS = OGRSFDriverRegistrar::Open( pszInput, FALSE, NULL );
+            if( poOGRDS != NULL ) {
+                poLayer = poOGRDS->GetLayer( 0 );
+                if ( poLayer != NULL ) {
+                    OGRSpatialReference *poSRS = poLayer->GetSpatialRef( );
+                    if ( poSRS != NULL ) {
+                        CPLDebug( "gdalsrsinfo", "got SRS from OGR" );
+                        bGotSRS = TRUE;
+                        OGRSpatialReference* poSRSClone = poSRS->Clone();
+                        oSRS = *poSRSClone;
+                        OGRSpatialReference::DestroySpatialReference( poSRSClone );
+                    }
+                }
+                OGRDataSource::DestroyDataSource( poOGRDS );
+                poOGRDS = NULL;
+            } 
+            if ( ! bGotSRS ) 
+                CPLDebug( "gdalsrsinfo", "did not open with OGR" );
+         }
+        
+    }
+ 
+    /* Try ESRI file */
+    if ( ! bGotSRS && (strstr(pszInput,".prj") != NULL) ) {
+        CPLDebug( "gdalsrsinfo", 
+                  "trying to get SRS from ESRI .prj file [%s]", pszInput );
+
+        char **pszTemp;
+        if ( strstr(pszInput,"ESRI::") != NULL )
+            pszTemp = CSLLoad( pszInput+6 );
+        else 
+            pszTemp = CSLLoad( pszInput );
+
+        if( pszTemp ) {
+            eErr = oSRS.importFromESRI( pszTemp );
+            CSLDestroy( pszTemp );
+        }
+        else 
+            eErr = OGRERR_UNSUPPORTED_SRS;
+
+        if( eErr != OGRERR_NONE ) {
+            CPLDebug( "gdalsrsinfo", "did not get SRS from ESRI .prj file" );
+        }
+        else {
+            CPLDebug( "gdalsrsinfo", "got SRS from ESRI .prj file" );
+            bGotSRS = TRUE;
+        }
+    }
+
+    /* Last resort, try OSRSetFromUserInput() */
+    if ( ! bGotSRS ) {
+        CPLDebug( "gdalsrsinfo", 
+                  "trying to get SRS from user input [%s]", pszInput );
+
+        eErr = oSRS.SetFromUserInput( pszInput );
+ 
+       if(  eErr != OGRERR_NONE ) {
+            CPLDebug( "gdalsrsinfo", "did not get SRS from user input" );
+        }
+        else {
+            CPLDebug( "gdalsrsinfo", "got SRS from user input" );
+            bGotSRS = TRUE;
+        }
+    }
+    
+  /* restore error messages */
+    if ( ! bDebug )
+        CPLSetErrorHandler ( oErrorHandler );	
+
+
+    return bGotSRS;
+}
+
+
+/************************************************************************/
+/*                      PrintSRS()                                      */
+/*                                                                      */
+/*      Print spatial reference in specified format.                    */
+/************************************************************************/
+CPLErr PrintSRS( const OGRSpatialReference &oSRS, 
+                 const char * pszOutputType, 
+                 int bPretty, int bPrintSep )
+
+{
+    if ( ! pszOutputType || EQUAL(pszOutputType,""))
+        return CE_None;
+
+    CPLDebug( "gdalsrsinfo", "PrintSRS( oSRS, %s, %d, %d )\n",
+              pszOutputType, bPretty, bPrintSep );
+    
+    char *pszOutput = NULL;
+
+    if ( EQUAL("proj4", pszOutputType ) ) {
+        if ( bPrintSep ) printf( "PROJ.4 : ");
+        oSRS.exportToProj4( &pszOutput );
+        printf( "\'%s\'\n", pszOutput );
+    }
+
+    else if ( EQUAL("wkt", pszOutputType ) ) {
+        if ( bPrintSep ) printf("OGC WKT :\n");
+        if ( bPretty ) 
+            oSRS.exportToPrettyWkt( &pszOutput, FALSE );
+        else
+            oSRS.exportToWkt( &pszOutput );
+        printf("%s\n",pszOutput);
+    }
+        
+    else if (  EQUAL("wkt_simple", pszOutputType ) ) {
+        if ( bPrintSep ) printf("OGC WKT (simple) :\n");
+        oSRS.exportToPrettyWkt( &pszOutput, TRUE );
+        printf("%s\n",pszOutput);
+    }
+        
+    else if ( EQUAL("wkt_noct", pszOutputType ) ) {
+        if (  bPrintSep ) printf("OGC WKT (no CT) :\n");
+        OGRSpatialReference *poSRS = oSRS.Clone();
+        poSRS->StripCTParms( );
+        if ( bPretty ) 
+            poSRS->exportToPrettyWkt( &pszOutput, FALSE );
+        else
+            poSRS->exportToWkt( &pszOutput );
+        OGRSpatialReference::DestroySpatialReference( poSRS );
+        printf("%s\n",pszOutput);
+    }
+        
+    else if ( EQUAL("wkt_esri", pszOutputType ) ) {
+        if ( bPrintSep ) printf("ESRI WKT :\n");
+        OGRSpatialReference *poSRS = oSRS.Clone();
+        poSRS->morphToESRI( );
+        if ( bPretty ) 
+            poSRS->exportToPrettyWkt( &pszOutput, FALSE );
+        else
+            poSRS->exportToWkt( &pszOutput );
+        OGRSpatialReference::DestroySpatialReference( poSRS );
+        printf("%s\n",pszOutput);
+    }
+        
+    else if ( EQUAL("mapinfo", pszOutputType ) ) {
+        if ( bPrintSep ) printf("MAPINFO : ");
+        oSRS.exportToMICoordSys( &pszOutput );
+        printf("\'%s\'\n",pszOutput);
+    }
+        
+    else if ( EQUAL("xml", pszOutputType ) ) {
+        if ( bPrintSep ) printf("XML :\n");
+        oSRS.exportToXML( &pszOutput, NULL );
+        printf("%s\n",pszOutput);
+    }
+
+    else {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ERROR - %s output not supported",
+                  pszOutputType );
+        return CE_Failure;
+    }
+
+    CPLFree( pszOutput );
+    
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      PrintSRSOutputTypes()                           */
+/*                                                                      */
+/*      Print spatial reference in specified formats.                   */
+/************************************************************************/
+void PrintSRSOutputTypes( const OGRSpatialReference &oSRS, 
+                          const char ** papszOutputTypes )
+    
+{
+    int nOutputTypes = CSLCount((char**)papszOutputTypes);
+    printf( "\n" );
+    for ( int i=0; i<nOutputTypes; i++ ) {
+        PrintSRS( oSRS, papszOutputTypes[i], TRUE, TRUE );
+        printf( "\n" );        
+    }
+}
+
+/************************************************************************/
+/*                      SearchCSVForWKT()                               */
+/*                                                                      */
+/*      Search CSV file for target WKT, return EPSG code (or -1).       */
+/*      For saving space, the file can be compressed (gz)               */
+/*      If CSV file is absent are absent the function silently exits    */
+/************************************************************************/
+int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget )
+{
+    const char *pszFilename = NULL;
+    const char *pszWKT = NULL;
+    char szTemp[1024];
+    int nPos = 0;
+    const char *pszTemp = NULL;
+
+    VSILFILE *fp = NULL;
+    OGRSpatialReference oSRS;
+    int nCode = 0;
+    int nFound = -1;
+
+    CPLDebug( "gdalsrsinfo", 
+              "SearchCSVForWKT()\nfile=%s\nWKT=%s\n",
+              pszFileCSV, pszTarget);
+
+/* -------------------------------------------------------------------- */
+/*      Find and open file.                                             */
+/* -------------------------------------------------------------------- */
+    // pszFilename = pszFileCSV;
+    pszFilename = CPLFindFile( "gdal", pszFileCSV );
+    if( pszFilename == NULL )
+    {
+        CPLDebug( "gdalsrsinfo", "could not find support file %s",
+                   pszFileCSV );
+        // return OGRERR_UNSUPPORTED_SRS;
+        return -1;
+    }
+
+    /* support gzipped file */
+    if ( strstr( pszFileCSV,".gz") != NULL )
+        sprintf( szTemp, "/vsigzip/%s", pszFilename);
+    else
+        sprintf( szTemp, "%s", pszFilename);
+
+    CPLDebug( "gdalsrsinfo", "SearchCSVForWKT() using file %s",
+              szTemp );
+
+    fp = VSIFOpenL( szTemp, "r" );
+    if( fp == NULL ) 
+    {
+        CPLDebug( "gdalsrsinfo", "could not open support file %s",
+                  pszFilename );
+
+        // return OGRERR_UNSUPPORTED_SRS;
+        return -1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process lines.                                                  */
+/* -------------------------------------------------------------------- */
+    const char *pszLine;
+
+    while( (pszLine = CPLReadLine2L(fp,-1,NULL)) != NULL )
+
+    {
+        // CPLDebug( "gdalsrsinfo", "read line %s", pszLine );
+
+        if( pszLine[0] == '#' )
+            continue;
+            /* do nothing */;
+
+        // else if( EQUALN(pszLine,"include ",8) )
+        // {
+        //     eErr = importFromDict( pszLine + 8, pszCode );
+        //     if( eErr != OGRERR_UNSUPPORTED_SRS )
+        //         break;
+        // }
+
+        // else if( strstr(pszLine,",") == NULL )
+        //     /* do nothing */;
+
+        pszTemp = strstr(pszLine,",");
+        if (pszTemp)
+        {
+            nPos = pszTemp - pszLine;
+
+            if ( nPos == 0 )
+                continue;
+            
+            strncpy( szTemp, pszLine, nPos );
+            szTemp[nPos] = '\0';
+            nCode = atoi(szTemp);
+
+            pszWKT = (char *) pszLine + nPos +1;
+
+            // CPLDebug( "gdalsrsinfo", 
+            //           "code=%d\nWKT=\n[%s]\ntarget=\n[%s]\n",
+            //           nCode,pszWKT, pszTarget );
+
+            if ( EQUAL(pszTarget,pszWKT) )
+            {
+                nFound = nCode;
+                CPLDebug( "gdalsrsinfo", "found EPSG:%d\n"
+                          "current=%s\ntarget= %s\n",
+                          nCode, pszWKT, pszTarget );
+                break;
+            }
+        }
+    }
+    
+    VSIFCloseL( fp );
+
+    return nFound;
+
+}
+
+/* TODO 
+   - search for well-known values (AutoIdentifyEPSG()) 
+
+   - should we search .override.csv files?
+
+   - fix precision differences (namely in degree: 17 vs 15) so we can use epsg_ogc_simple
+target:
+ orig: GEOGCS["SAD69",DATUM["D_South_American_1969",SPHEROID["GRS_1967_Modified",6378160,298.25]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
+ ESRI: GEOGCS["SAD69",DATUM["D_South_American_1969",SPHEROID["GRS_1967_Truncated",6378160,298.25]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
+ OGC:  GEOGCS["SAD69",DATUM["South_American_Datum_1969",SPHEROID["GRS_1967_Modified",6378160,298.25]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
+database:
+ ESRI: GEOGCS["SAD69",DATUM["D_South_American_1969",SPHEROID["GRS_1967_Truncated",6378160,298.25]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
+ OGC:  GEOGCS["SAD69",DATUM["South_American_Datum_1969",SPHEROID["GRS 1967 Modified",6378160,298.25]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]
+*/
+
+/************************************************************************/
+/*                      FindEPSG()                                      */
+/*                                                                      */
+/*      Return EPSG code corresponding to spatial reference (or -1)     */
+/************************************************************************/
+int FindEPSG( const OGRSpatialReference &oSRS )
+{
+    char *pszWKT = NULL;
+    char *pszESRI = NULL;
+    int nFound = -1;
+    OGRSpatialReference *poSRS = NULL;
+ 
+    poSRS = oSRS.Clone();
+    poSRS->StripCTParms();
+    poSRS->exportToWkt( &pszWKT );
+    OGRSpatialReference::DestroySpatialReference( poSRS );
+
+    poSRS = oSRS.Clone();
+    poSRS->morphToESRI( );
+    poSRS->exportToWkt( &pszESRI );
+    OGRSpatialReference::DestroySpatialReference( poSRS );
+
+    CPLDebug( "gdalsrsinfo", "FindEPSG()\nWKT (OGC)= %s\nWKT (ESRI)=%s",
+              pszWKT,pszESRI );
+
+    /* search for EPSG code in epsg_*.wkt.gz files */
+    /* using ESRI WKT for now, as it seems to work best */
+    nFound = SearchCSVForWKT( "epsg_esri.wkt.gz", pszESRI );
+    if ( nFound == -1 )
+        nFound = SearchCSVForWKT( "epsg_ogc_simple.wkt.gz", pszESRI );
+    if ( nFound == -1 )
+        nFound = SearchCSVForWKT( "epsg_ogc.wkt.gz", pszESRI );
+
+    
+    CPLFree( pszWKT );
+    CPLFree( pszESRI );    
+    
+    return nFound;
+}
diff --git a/apps/gdaltorture.cpp b/apps/gdaltorture.cpp
index c48f872..a00079c 100644
--- a/apps/gdaltorture.cpp
+++ b/apps/gdaltorture.cpp
@@ -48,7 +48,7 @@ static void Usage()
 /*                              TortureDS()                             */
 /************************************************************************/
 
-static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations)
+static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations, int nRecurse)
 {
     int             nBlockXSize, nBlockYSize;
     int             nRasterXSize, nRasterYSize;
@@ -60,6 +60,9 @@ static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations)
     float           afSampleBuf;
     GDALRasterBandH hMaskBand;
 
+    if (nRecurse > 5)
+        return;
+
     GDALGetRasterDataType(hBand);
     GDALGetBlockSize(hBand, &nBlockXSize, &nBlockYSize);
     //GDALRasterAdviseRead
@@ -82,7 +85,7 @@ static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations)
     {
         GDALRasterBandH hOverviewBand = GDALGetOverview(hBand, iOverview);
         if (hOverviewBand)
-            TortureBand(hOverviewBand, FALSE);
+            TortureBand(hOverviewBand, FALSE, nRecurse + 1);
     }
 
     GDALGetRasterNoDataValue(hBand, &bHasNoData);
@@ -113,7 +116,7 @@ static void TortureBand(GDALRasterBandH hBand, int bReadWriteOperations)
     //GDALAddDerivedBandPixelFunc
     hMaskBand = GDALGetMaskBand(hBand);
     if (hMaskBand != hBand)
-        TortureBand(hMaskBand, FALSE);
+        TortureBand(hMaskBand, FALSE, nRecurse + 1);
     GDALGetMaskFlags(hBand);
     //GDALCreateMaskBand
     
@@ -176,7 +179,7 @@ static void TortureDS(const char *pszTarget, int bReadWriteOperations)
         if (hBand == NULL)
             continue;
 
-        TortureBand(hBand, bReadWriteOperations);
+        TortureBand(hBand, bReadWriteOperations, 0);
     }
 
     GDALClose(hDS);
diff --git a/apps/gdalwarp.cpp b/apps/gdalwarp.cpp
index c087133..f32c1b0 100644
--- a/apps/gdalwarp.cpp
+++ b/apps/gdalwarp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarp.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: gdalwarp.cpp 23364 2011-11-11 13:48:37Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Test program for high performance warper API.
@@ -32,8 +32,9 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 #include "ogr_api.h"
+#include "commonutils.h"
 
-CPL_CVSID("$Id: gdalwarp.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: gdalwarp.cpp 23364 2011-11-11 13:48:37Z rouault $");
 
 static void
 LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
@@ -46,7 +47,9 @@ TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
 static GDALDatasetH 
 GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename, 
                       const char *pszFormat, char **papszTO,
-                      char ***ppapszCreateOptions, GDALDataType eDT );
+                      char ***ppapszCreateOptions, GDALDataType eDT,
+                      void ** phTransformArg,
+                      GDALDatasetH* phSrcDS );
 
 static double	       dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
 static double	       dfXRes=0.0, dfYRes=0.0;
@@ -61,7 +64,7 @@ static int             bVRT = FALSE;
 
 image reprojection and warping utility
 
-\section wsynopsis SYNOPSIS
+\section gdalwarp_synopsis SYNOPSIS
 
 \htmlonly
 Usage: 
@@ -70,7 +73,8 @@ Usage:
 \verbatim
 gdalwarp [--help-general] [--formats]
     [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"]
-    [-order n] [-tps] [-rpc] [-geoloc] [-et err_threshold]
+    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]
+    [-refine_gcps tolerance [minimum_gcps]]
     [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]
     [-wo "NAME=VALUE"] [-ot Byte/Int16/...] [-wt Byte/Int16]
     [-srcnodata "value [value...]"] [-dstnodata "value [value...]"] -dstalpha
@@ -81,7 +85,7 @@ gdalwarp [--help-general] [--formats]
     srcfile* dstfile
 \endverbatim
 
-\section wdescription DESCRIPTION
+\section gdalwarp_description DESCRIPTION
 
 <p>
 The gdalwarp utility is an image mosaicing, reprojection and warping
@@ -112,6 +116,12 @@ available GCPs.</dd>
 <dt> <b>-geoloc</b>:</dt><dd>Force use of Geolocation Arrays.</dd>
 <dt> <b>-et</b> <em>err_threshold</em>:</dt><dd> error threshold for
 transformation approximation (in pixel units - defaults to 0.125).</dd>
+<dt> <b>-refine_gcps</b> <em>tolerance minimum_gcps</em>:</dt><dd>  (GDAL >= 1.9.0) refines the GCPs by automatically eliminating outliers.
+Outliers will be eliminated until minimum_gcps are left or when no outliers can be detected.
+The tolerance is passed to adjust when a GCP will be eliminated.
+Not that GCP refinement only works with polynomial interpolation.
+The tolerance is in pixel units if no projection is available, otherwise it is in SRS units.
+If minimum_gcps is not provided, the minimum GCPs according to the polynomial model is used.</dd>
 <dt> <b>-te</b> <em>xmin ymin xmax ymax</em>:</dt><dd> set georeferenced
 extents of output file to be created (in target SRS).</dd>
 <dt> <b>-tr</b> <em>xres yres</em>:</dt><dd> set output file resolution (in
@@ -169,7 +179,7 @@ cutline datasource.</dd>
 <dt> <b>-cwhere</b> <em>expression</em>:</dt><dd>Restrict desired cutline features based on attribute query.</dd>
 <dt> <b>-csql</b> <em>query</em>:</dt><dd>Select cutline features using an SQL query instead of from a layer with -cl.</dd>
 <dt> <b>-cblend</b> <em>distance</em>:</dt><dd>Set a blend distance to use to blend over cutlines (in pixels).</dd>
-<dt> <b>-crop_to_cutline</b>:</dt><dd>Crop the extent of the target dataset to the extent of the cutline.</dd>
+<dt> <b>-crop_to_cutline</b>:</dt><dd>(GDAL >= 1.8.0) Crop the extent of the target dataset to the extent of the cutline.</dd>
 <dt> <b>-overwrite</b>:</dt><dd>(GDAL >= 1.8.0) Overwrite the target dataset if it already exists.</dd>
 
 <dt> <em>srcfile</em>:</dt><dd> The source file name(s). </dd>
@@ -178,15 +188,18 @@ cutline datasource.</dd>
 
 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.
+be modified to accomodate new data, so you may have to remove it in that case, or
+use the -overwrite option.
 
-Polygon cutlines may be used to restrict the the area of the destination file 
+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.
+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.
 
 <p>
-\section wexample EXAMPLE
+\section gdalwarp_example EXAMPLE
 
 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
@@ -205,7 +218,7 @@ gdalwarp HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-20020
 \endverbatim
 
 \if man
-\section wauthor AUTHORS
+\section gdalwarp_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -220,13 +233,14 @@ static void Usage()
     printf( 
         "Usage: gdalwarp [--help-general] [--formats]\n"
         "    [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"]\n"
-        "    [-order n] [-tps] [-rpc] [-geoloc] [-et err_threshold]\n"
+        "    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]\n"
+        "    [-refine_gcps tolerance [minimum_gcps]]\n"
         "    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n"
         "    [-wo \"NAME=VALUE\"] [-ot Byte/Int16/...] [-wt Byte/Int16]\n"
         "    [-srcnodata \"value [value...]\"] [-dstnodata \"value [value...]\"] -dstalpha\n" 
         "    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]\n"
         "    [-cutline datasource] [-cl layer] [-cwhere expression]\n"
-        "    [-csql statement] [-cblend dist_in_pixels]\n"
+        "    [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]\n"
         "    [-of format] [-co \"NAME=VALUE\"]* [-overwrite]\n"
         "    srcfile* dstfile\n"
         "\n"
@@ -272,6 +286,7 @@ int main( int argc, char ** argv )
 {
     GDALDatasetH	hDstDS;
     const char         *pszFormat = "GTiff";
+    int bFormatExplicitelySet = FALSE;
     char              **papszSrcFiles = NULL;
     char               *pszDstFilename = NULL;
     int                 bCreateOutput = FALSE, i;
@@ -330,6 +345,18 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     for( i = 1; i < argc; i++ )
     {
+        if( EQUAL(argv[i],"-tps") || EQUAL(argv[i],"-rpc") || EQUAL(argv[i],"-geoloc")  )
+        {
+            const char* pszMethod = CSLFetchNameValue(papszTO, "METHOD");
+            if (pszMethod)
+                fprintf(stderr, "Warning: only one METHOD can be used. Method %s is already defined.\n",
+                        pszMethod);
+            const char* pszMAX_GCP_ORDER = CSLFetchNameValue(papszTO, "MAX_GCP_ORDER");
+            if (pszMAX_GCP_ORDER)
+                fprintf(stderr, "Warning: only one METHOD can be used. -order %s option was specified, so it is likely that GCP_POLYNOMIAL was implied.\n",
+                        pszMAX_GCP_ORDER);
+        }
+
         if( EQUAL(argv[i], "--utility_version") )
         {
             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
@@ -364,6 +391,7 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i],"-of") && i < argc-1 )
         {
             pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
             bCreateOutput = TRUE;
             if( EQUAL(pszFormat,"VRT") )
                 bVRT = TRUE;
@@ -382,8 +410,29 @@ int main( int argc, char ** argv )
         }
         else if( EQUAL(argv[i],"-order") && i < argc-1 )
         {
+            const char* pszMethod = CSLFetchNameValue(papszTO, "METHOD");
+            if (pszMethod)
+                fprintf(stderr, "Warning: only one METHOD can be used. Method %s is already defined\n",
+                        pszMethod);
             papszTO = CSLSetNameValue( papszTO, "MAX_GCP_ORDER", argv[++i] );
         }
+        else if( EQUAL(argv[i],"-refine_gcps") && i < argc-1 )
+        {
+            papszTO = CSLSetNameValue( papszTO, "REFINE_TOLERANCE", argv[++i] );
+            if(atof(argv[i]) < 0)
+            {
+                printf( "The tolerance for -refine_gcps may not be negative\n");
+                Usage();
+            }
+            if (i < argc-1 && atoi(argv[i+1]) >= 0 && isdigit(argv[i+1][0]))
+            {
+                papszTO = CSLSetNameValue( papszTO, "REFINE_MINIMUM_GCPS", argv[++i] );
+            }
+            else
+            {
+                papszTO = CSLSetNameValue( papszTO, "REFINE_MINIMUM_GCPS", "-1" );
+            }
+        }
         else if( EQUAL(argv[i],"-tps") )
         {
             papszTO = CSLSetNameValue( papszTO, "METHOD", "GCP_TPS" );
@@ -601,6 +650,17 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Does the output dataset already exist?                          */
 /* -------------------------------------------------------------------- */
+
+    /* FIXME ? source filename=target filename and -overwrite is definitely */
+    /* an error. But I can't imagine of a valid case (without -overwrite), */
+    /* where it would make sense. In doubt, let's keep that dubious possibility... */
+    if ( CSLCount(papszSrcFiles) == 1 &&
+         strcmp(papszSrcFiles[0], pszDstFilename) == 0 && bOverwrite)
+    {
+        fprintf(stderr, "Source and destination datasets must be different.\n");
+        exit( 1 );
+    }
+
     CPLPushErrorHandler( CPLQuietErrorHandler );
     hDstDS = GDALOpen( pszDstFilename, GA_Update );
     CPLPopErrorHandler();
@@ -743,11 +803,18 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     int   bInitDestSetForFirst = FALSE;
 
+    void* hUniqueTransformArg = NULL;
+    GDALDatasetH hUniqueSrcDS = NULL;
+
     if( hDstDS == NULL )
     {
+        if (!bQuiet && !bFormatExplicitelySet)
+            CheckExtensionConsistency(pszDstFilename, pszFormat);
+
         hDstDS = GDALWarpCreateOutput( papszSrcFiles, pszDstFilename,pszFormat,
                                        papszTO, &papszCreateOptions, 
-                                       eOutputType );
+                                       eOutputType, &hUniqueTransformArg,
+                                       &hUniqueSrcDS);
         bCreateOutput = TRUE;
 
         if( CSLFetchNameValue( papszWarpOptions, "INIT_DEST" ) == NULL 
@@ -767,7 +834,7 @@ int main( int argc, char ** argv )
         CSLDestroy( papszCreateOptions );
         papszCreateOptions = NULL;
     }
-
+ 
     if( hDstDS == NULL )
         exit( 1 );
 
@@ -783,7 +850,10 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Open this file.                                                 */
 /* -------------------------------------------------------------------- */
-        hSrcDS = GDALOpen( papszSrcFiles[iSrc], GA_ReadOnly );
+        if (hUniqueSrcDS)
+            hSrcDS = hUniqueSrcDS;
+        else
+            hSrcDS = GDALOpen( papszSrcFiles[iSrc], GA_ReadOnly );
     
         if( hSrcDS == NULL )
             exit( 2 );
@@ -792,7 +862,7 @@ int main( int argc, char ** argv )
 /*      Check that there's at least one raster band                     */
 /* -------------------------------------------------------------------- */
         if ( GDALGetRasterCount(hSrcDS) == 0 )
-        {
+        {     
             fprintf(stderr, "Input file %s has no raster bands.\n", papszSrcFiles[iSrc] );
             exit( 1 );
         }
@@ -804,7 +874,7 @@ int main( int argc, char ** argv )
 /*      Warns if the file has a color table and something more          */
 /*      complicated than nearest neighbour resampling is asked          */
 /* -------------------------------------------------------------------- */
-
+ 
         if ( eResampleAlg != GRA_NearestNeighbour &&
              GDALGetRasterColorTable(GDALGetRasterBand(hSrcDS, 1)) != NULL)
         {
@@ -833,8 +903,11 @@ int main( int argc, char ** argv )
 /*      Create a transformation object from the source to               */
 /*      destination coordinate system.                                  */
 /* -------------------------------------------------------------------- */
-        hTransformArg = hGenImgProjArg = 
-            GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszTO );
+        if (hUniqueTransformArg)
+            hTransformArg = hGenImgProjArg = hUniqueTransformArg;
+        else
+            hTransformArg = hGenImgProjArg =
+                GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszTO );
         
         if( hTransformArg == NULL )
             exit( 1 );
@@ -1208,12 +1281,18 @@ int main( int argc, char ** argv )
 /*                                                                      */
 /*      Create the output file based on various commandline options,    */
 /*      and the input file.                                             */
+/*      If there's just one source file, then *phTransformArg and       */
+/*      *phSrcDS will be set, in order them to be reused by main        */
+/*      function. This saves dataset re-opening, and above all transform*/
+/*      recomputation, which can be expensive in the -tps case          */
 /************************************************************************/
 
 static GDALDatasetH 
 GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename, 
                       const char *pszFormat, char **papszTO, 
-                      char ***ppapszCreateOptions, GDALDataType eDT )
+                      char ***ppapszCreateOptions, GDALDataType eDT,
+                      void ** phTransformArg,
+                      GDALDatasetH* phSrcDS)
 
 
 {
@@ -1225,6 +1304,9 @@ GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename,
     double dfWrkResX=0, dfWrkResY=0;
     int nDstBandCount = 0;
 
+    *phTransformArg = NULL;
+    *phSrcDS = NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Find the output driver.                                         */
 /* -------------------------------------------------------------------- */
@@ -1348,6 +1430,8 @@ GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename,
             GDALClose( hSrcDS );
             return NULL;
         }
+        
+        GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg;
 
 /* -------------------------------------------------------------------- */
 /*      Get approximate output definition.                              */
@@ -1357,7 +1441,7 @@ GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename,
         int    nThisPixels, nThisLines;
 
         if( GDALSuggestedWarpOutput2( hSrcDS, 
-                                      GDALGenImgProjTransform, hTransformArg, 
+                                      psInfo->pfnTransform, hTransformArg, 
                                       adfThisGeoTransform, 
                                       &nThisPixels, &nThisLines, 
                                       adfExtent, 0 ) != CE_None )
@@ -1391,10 +1475,10 @@ GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename,
                     double y = expected_y;
                     double z = 0;
                     /* Target SRS coordinates to source image pixel coordinates */
-                    if (!GDALGenImgProjTransform(hTransformArg, TRUE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
+                    if (!psInfo->pfnTransform(hTransformArg, TRUE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
                         bSuccess = FALSE;
                     /* Source image pixel coordinates to target SRS coordinates */
-                    if (!GDALGenImgProjTransform(hTransformArg, FALSE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
+                    if (!psInfo->pfnTransform(hTransformArg, FALSE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
                         bSuccess = FALSE;
                     if (fabs(x - expected_x) > (MaxX - MinX) / nThisPixels ||
                         fabs(y - expected_y) > (MaxY - MinY) / nThisLines)
@@ -1409,12 +1493,9 @@ GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename,
             {
                 CPLSetConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" );
                 CPLDebug("WARP", "Recompute out extent with CHECK_WITH_INVERT_PROJ=TRUE");
-                GDALDestroyGenImgProjTransformer(hTransformArg);
-                hTransformArg = 
-                    GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
-                    
+
                 if( GDALSuggestedWarpOutput2( hSrcDS, 
-                                      GDALGenImgProjTransform, hTransformArg, 
+                                      psInfo->pfnTransform, hTransformArg, 
                                       adfThisGeoTransform, 
                                       &nThisPixels, &nThisLines, 
                                       adfExtent, 0 ) != CE_None )
@@ -1448,10 +1529,17 @@ GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename,
             dfWrkResX = MIN(dfWrkResX,adfThisGeoTransform[1]);
             dfWrkResY = MIN(dfWrkResY,ABS(adfThisGeoTransform[5]));
         }
-        
-        GDALDestroyGenImgProjTransformer( hTransformArg );
 
-        GDALClose( hSrcDS );
+        if (iSrc == 0 && papszSrcFiles[1] == NULL)
+        {
+            *phTransformArg = hTransformArg;
+            *phSrcDS = hSrcDS;
+        }
+        else
+        {
+            GDALDestroyGenImgProjTransformer( hTransformArg );
+            GDALClose( hSrcDS );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1624,6 +1712,9 @@ GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename,
     GDALSetProjection( hDstDS, pszThisTargetSRS );
     GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
 
+    if (*phTransformArg != NULL)
+        GDALSetGenImgProjTransformerDstGeoTransform( *phTransformArg, adfDstGeoTransform);
+
 /* -------------------------------------------------------------------- */
 /*      Try to set color interpretation of output file alpha band.      */
 /*      TODO: We should likely try to copy the other bands too.         */
@@ -1873,6 +1964,13 @@ TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
     }
 
 /* -------------------------------------------------------------------- */
+/*      It may be unwise to let the mask geometry be re-wrapped by      */
+/*      the CENTER_LONG machinery as this can easily screw up world     */
+/*      spanning masks and invert the mask topology.                    */
+/* -------------------------------------------------------------------- */
+    papszTO = CSLSetNameValue( papszTO, "INSERT_CENTER_LONG", "FALSE" );
+
+/* -------------------------------------------------------------------- */
 /*      Transform the geometry to pixel/line coordinates.               */
 /* -------------------------------------------------------------------- */
     CutlineTransformer oTransformer;
diff --git a/apps/makefile.vc b/apps/makefile.vc
index 0bbcbf2..c5fd1eb 100644
--- a/apps/makefile.vc
+++ b/apps/makefile.vc
@@ -12,12 +12,12 @@ XTRAFLAGS =	-I..\frmts -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts
 !IFDEF INCLUDE_OGR_FRMTS
 OGR_PROGRAMS =	gdal_contour.exe gdaltindex.exe gdal_rasterize.exe \
 		gdal_grid.exe ogrinfo.exe ogr2ogr.exe ogrtindex.exe \
-		gdalbuildvrt.exe
+		gdalbuildvrt.exe testepsg.exe
 !ENDIF
 
 default:	gdal_translate.exe gdalinfo.exe gdaladdo.exe gdalwarp.exe \
 		nearblack.exe gdalmanage.exe gdalenhance.exe gdaltransform.exe\
-		gdaldem.exe gdallocationinfo.exe $(OGR_PROGRAMS)
+		gdaldem.exe gdallocationinfo.exe gdalsrsinfo.exe $(OGR_PROGRAMS)
 
 all:	default multireadtest.exe \
 			dumpoverviews.exe gdalwarpsimple.exe gdalflattenmask.exe \
@@ -28,8 +28,8 @@ gdalinfo.exe:	gdalinfo.c $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdal_translate.exe:	gdal_translate.cpp $(GDALLIB) $(XTRAOBJ)
-	$(CC) $(CFLAGS) $(XTRAFLAGS) gdal_translate.cpp $(XTRAOBJ) $(LIBS) \
+gdal_translate.exe:	gdal_translate.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ)
+	$(CC) $(CFLAGS) $(XTRAFLAGS) gdal_translate.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
@@ -53,8 +53,13 @@ gdallocationinfo.exe:	gdallocationinfo.cpp $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdalwarp.exe:	gdalwarp.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(CFLAGS) $(XTRAFLAGS) gdalwarp.cpp $(XTRAOBJ) $(LIBS) \
+gdalsrsinfo.exe:	gdalsrsinfo.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) gdalsrsinfo.cpp $(XTRAOBJ) $(LIBS) \
+		/link $(LINKER_FLAGS)
+	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
+	
+gdalwarp.exe:	gdalwarp.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) gdalwarp.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
@@ -63,23 +68,23 @@ gdal_contour.exe:	gdal_contour.cpp $(GDALLIB) $(XTRAOBJ)
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-nearblack.exe:	nearblack.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(CFLAGS) $(XTRAFLAGS) nearblack.cpp $(XTRAOBJ) $(LIBS) \
+nearblack.exe:	nearblack.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) nearblack.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdalenhance.exe:	gdalenhance.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(CFLAGS) $(XTRAFLAGS) gdalenhance.cpp $(XTRAOBJ) $(LIBS) \
+gdalenhance.exe:	gdalenhance.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) gdalenhance.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdaldem.exe:	gdaldem.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(CFLAGS) $(XTRAFLAGS) gdaldem.cpp $(XTRAOBJ) $(LIBS) \
+gdaldem.exe:	gdaldem.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) gdaldem.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdal_grid.exe:	gdal_grid.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(CFLAGS) $(XTRAFLAGS) gdal_grid.cpp $(XTRAOBJ) $(LIBS) \
+gdal_grid.exe:	gdal_grid.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) gdal_grid.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
@@ -93,8 +98,8 @@ gdaltindex.exe:	gdaltindex.c $(GDALLIB) $(XTRAOBJ)
 		$(XTRAOBJ) $(LIBS) /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 	
-gdal_rasterize.exe:	gdal_rasterize.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(CFLAGS) $(XTRAFLAGS) gdal_rasterize.cpp $(XTRAOBJ) $(LIBS) \
+gdal_rasterize.exe:	gdal_rasterize.cpp commonutils.cpp $(GDALLIB) $(XTRAOBJ) 
+	$(CC) $(CFLAGS) $(XTRAFLAGS) gdal_rasterize.cpp commonutils.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
diff --git a/apps/nearblack.cpp b/apps/nearblack.cpp
index 6dc9563..0a73283 100644
--- a/apps/nearblack.cpp
+++ b/apps/nearblack.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nearblack.cpp 21156 2010-11-22 16:46:20Z winkey $
+ * $Id: nearblack.cpp 22783 2011-07-23 19:28:16Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Convert nearly black or nearly white border to exact black/white.
@@ -30,14 +30,41 @@
 #include "gdal.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include <vector>
+#include "commonutils.h"
 
-CPL_CVSID("$Id: nearblack.cpp 21156 2010-11-22 16:46:20Z winkey $");
+CPL_CVSID("$Id: nearblack.cpp 22783 2011-07-23 19:28:16Z rouault $");
 
-static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart, int iEnd, int nSrcBands, int nDstBands,
-                         int nNearDist, int nMaxNonBlack, int bNearWhite,
-                         int *panLastLineCounts, 
-                         int bDoHorizontalCheck, 
-                         int bDoVerticalCheck );
+typedef std::vector<int> Color;
+typedef std::vector< Color > Colors;
+
+static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
+                         int iEnd, int nSrcBands, int nDstBands, int nNearDist,
+                         int nMaxNonBlack, int bNearWhite, Colors *poColors,
+                         int *panLastLineCounts, int bDoHorizontalCheck,
+                         int bDoVerticalCheck, int bBottomUp);
+
+/************************************************************************/
+/*                            IsInt()                                   */
+/************************************************************************/
+
+int IsInt( const char *pszArg )
+{
+    if( pszArg[0] == '-' )
+        pszArg++;
+
+    if( *pszArg == '\0' )
+        return FALSE;
+
+    while( *pszArg != '\0' )
+    {
+        if( *pszArg < '0' || *pszArg > '9' )
+            return FALSE;
+        pszArg++;
+    }
+
+    return TRUE;
+}
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -45,7 +72,7 @@ static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart, int iEnd,
 
 void Usage()
 {
-    printf( "nearblack [-of format] [-white] [-near dist] [-nb non_black_pixels]\n"
+    printf( "nearblack [-of format] [-white | [-color c1,c2,c3...cn]*] [-near dist] [-nb non_black_pixels]\n"
             "          [-setalpha] [-setmask] [-o outfile] [-q] [-co \"NAME=VALUE\"]* infile\n" );
     exit( 1 );
 }
@@ -87,8 +114,11 @@ int main( int argc, char ** argv )
     int bSetAlpha = FALSE;
     int bSetMask = FALSE;
     const char* pszDriverName = "HFA";
+    int bFormatExplicitelySet = FALSE;
     char** papszCreationOptions = NULL;
     int bQuiet = FALSE;
+
+    Colors oColors;
     
     for( i = 1; i < argc; i++ )
     {
@@ -101,9 +131,60 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i], "-o") && i < argc-1 )
             pszOutFile = argv[++i];
         else if( EQUAL(argv[i], "-of") && i < argc-1 )
+        {
             pszDriverName = argv[++i];
-        else if( EQUAL(argv[i], "-white") )
+            bFormatExplicitelySet = TRUE;
+        }
+        else if( EQUAL(argv[i], "-white") ) {
             bNearWhite = TRUE;
+        }
+
+        /***** -color c1,c2,c3...cn *****/
+        
+        else if( EQUAL(argv[i], "-color") && i < argc-1 ) {
+            Color oColor;
+            
+            /***** tokenize the arg on , *****/
+            
+            char **papszTokens;
+            papszTokens = CSLTokenizeString2( argv[++i], ",", 0 );
+
+            /***** loop over the tokens *****/
+            
+            int iToken;
+            for( iToken = 0; papszTokens && papszTokens[iToken]; iToken++ )
+            {
+
+                /***** ensure the token is an int and add it to the color *****/
+                
+                if ( IsInt( papszTokens[iToken] ) )
+                    oColor.push_back( atoi( papszTokens[iToken] ) );
+                else {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Colors must be valid integers." );
+                    CSLDestroy( papszTokens );
+                    exit(1);
+                }
+            }
+            
+            CSLDestroy( papszTokens );
+
+            /***** check if the number of bands is consistant *****/
+
+            if ( oColors.size() > 0 &&
+                 oColors.front().size() != oColor.size() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "ERROR: all -color args must have the same number of values.\n" );
+                exit(1);
+            }
+
+            /***** add the color to the colors *****/
+            
+            oColors.push_back( oColor );
+            
+        }
+        
         else if( EQUAL(argv[i], "-nb") && i < argc-1 )
             nMaxNonBlack = atoi(argv[++i]);
         else if( EQUAL(argv[i], "-near") && i < argc-1 )
@@ -164,35 +245,24 @@ int main( int argc, char ** argv )
         if (hDriver == NULL)
             exit(1);
 
+        if (!bQuiet && !bFormatExplicitelySet)
+            CheckExtensionConsistency(pszOutFile, pszDriverName);
+
         if (bSetAlpha)
         {
-            if (nBands == 3)
-                nDstBands ++;
-            else if (nBands == 4)
+            /***** fixme there should be a way to preserve alpha band data not in the collar *****/
+            if (nBands == 4)
                 nBands --;
             else
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Number of bands of file = %d. Expected 3 or 4.",
-                         nBands);
-                exit(1);
-            }
+                nDstBands ++;
         }
 
         if (bSetMask)
         {
-            if (nBands == 3){
-            }
-            else if (nBands == 4)
+            if (nBands == 4)
                 nDstBands = nBands = 3;
-            else
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Number of bands of file = %d. Expected 3 or 4.",
-                         nBands);
-                exit(1);
-            }
         }
+
         hOutDS = GDALCreate( hDriver, pszOutFile, 
                              nXSize, nYSize, nDstBands, GDT_Byte, 
                              papszCreationOptions );
@@ -211,11 +281,12 @@ int main( int argc, char ** argv )
     {
         if (bSetAlpha)
         {
-            if (nBands != 4)
+            if (nBands != 4 &&
+                (nBands < 2 ||
+                 GDALGetRasterColorInterpretation(GDALGetRasterBand(hOutDS, nBands)) != GCI_AlphaBand))
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                        "Number of bands of output file = %d. Expected 4.",
-                        nBands);
+                        "Last band is not an alpha band.");
                 exit(1);
             }
 
@@ -226,17 +297,43 @@ int main( int argc, char ** argv )
         {
             if (nBands == 4)
                 nDstBands = nBands = 3;
+        }
+    }
 
-            if (nBands != 3)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Number of bands of output file = %d. Expected 3.",
-                        nBands);
-                exit(1);
-            }
+    /***** set a color if there are no colors set? *****/
+
+    if ( oColors.size() == 0) {
+        Color oColor;
+
+        /***** loop over the bands to get the right number of values *****/
+
+        int iBand;
+        for (iBand = 0; iBand < nBands ; iBand++) {
+
+            /***** black or white? *****/
+
+            if (bNearWhite) 
+                oColor.push_back(255);
+            else
+                oColor.push_back(0);
         }
+
+        /***** add the color to the colors *****/
+
+        oColors.push_back(oColor);
+            
     }
 
+    /***** does the number of bands match the number of color values? *****/
+
+    if ( (int)oColors.front().size() != nBands ) {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "-color args must have the same number of values as the non alpha input band count.\n" );
+        exit(1); 
+    }
+
+    /***** check the input and output datasets are the same size *****/
+    
     if (GDALGetRasterXSize(hOutDS) != nXSize ||
         GDALGetRasterYSize(hOutDS) != nYSize)
     {
@@ -275,7 +372,7 @@ int main( int argc, char ** argv )
 
             if ( CE_None != GDALCreateDatasetMaskBand(hOutDS, GMF_PER_DATASET) ) {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                         "CE_Warning Failed to create mask band on output DS");
+                         "Failed to create mask band on output DS");
                 bSetMask = FALSE;
             }
         }
@@ -333,10 +430,20 @@ int main( int argc, char ** argv )
             }
         }
         
-        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands, nNearDist, nMaxNonBlack,
-                     bNearWhite, panLastLineCounts, TRUE, TRUE );
-        ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands, nNearDist, nMaxNonBlack,
-                     bNearWhite, NULL, TRUE, FALSE );
+        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE, // bDoHorizontalCheck
+                     TRUE, // bDoVerticalCheck
+                     FALSE // bBottomUp
+                    );
+        ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE,  // bDoHorizontalCheck
+                     FALSE, // bDoVerticalCheck
+                     FALSE  // bBottomUp
+                    );
         
         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
                                     pabyLine, nXSize, 1, GDT_Byte, 
@@ -365,7 +472,7 @@ int main( int argc, char ** argv )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Now process from the bottom back up, doing only the vertical pass.*/
+/*      Now process from the bottom back up                            .*/
 /* -------------------------------------------------------------------- */
     memset( panLastLineCounts, 0, sizeof(int) * nXSize);
     
@@ -393,8 +500,20 @@ int main( int argc, char ** argv )
         }
 
         
-        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands, nNearDist, nMaxNonBlack,
-                     bNearWhite, panLastLineCounts, FALSE, TRUE );
+        ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE, // bDoHorizontalCheck
+                     TRUE, // bDoVerticalCheck
+                     TRUE  // bBottomUp
+                   );
+        ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
+                     nNearDist, nMaxNonBlack, bNearWhite, &oColors,
+                     panLastLineCounts,
+                     TRUE,  // bDoHorizontalCheck
+                     FALSE, // bDoVerticalCheck
+                     TRUE   // bBottomUp
+                    );
         
         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
                                     pabyLine, nXSize, 1, GDT_Byte, 
@@ -444,74 +563,83 @@ int main( int argc, char ** argv )
 /*      Process a single scanline of image data.                        */
 /************************************************************************/
 
-static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart, int iEnd, int nSrcBands,
-                         int nDstBands,
-                         int nNearDist, int nMaxNonBlack, int bNearWhite,
-                         int *panLastLineCounts, 
-                         int bDoHorizontalCheck, 
-                         int bDoVerticalCheck )
-
+static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
+                        int iEnd, int nSrcBands, int nDstBands, int nNearDist,
+                        int nMaxNonBlack, int bNearWhite, Colors *poColors,
+                        int *panLastLineCounts, int bDoHorizontalCheck,
+                        int bDoVerticalCheck, int bBottomUp )
 {
     int iDir, i;
+    GByte nReplacevalue = 0;
+    if( bNearWhite )
+        nReplacevalue = 255;
 
-/* -------------------------------------------------------------------- */
-/*      Vertical checking.                                              */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      Vertical checking.                                              */
+    /* -------------------------------------------------------------------- */
+    
     if( bDoVerticalCheck )
     {
         int nXSize = MAX(iStart+1,iEnd+1);
 
         for( i = 0; i < nXSize; i++ )
         {
-            int iBand;
-            int bIsNonBlack = FALSE;
 
             // are we already terminated for this column?
+
             if( panLastLineCounts[i] > nMaxNonBlack )
                 continue;
 
-            for( iBand = 0; iBand < nSrcBands; iBand++ )
-            {
+            /***** is the pixel valid data? ****/
 
-                if( bNearWhite )
-                {
-                    if( (255 - pabyLine[i * nDstBands + iBand]) > nNearDist )
-                    {
-                        bIsNonBlack = TRUE;
-                        break;
-                    }
-                }
-                else
+            int bIsNonBlack = FALSE;
+
+            /***** loop over the colors *****/
+
+            int iColor;
+            for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
+
+                Color oColor = (*poColors)[iColor];
+
+                bIsNonBlack = FALSE;
+
+                /***** loop over the bands *****/
+
+                int iBand;
+                for( iBand = 0; iBand < nSrcBands; iBand++ )
                 {
-                    if( pabyLine[i * nDstBands + iBand] > nNearDist )
+                    int nPix = pabyLine[i * nDstBands + iBand];
+
+                    if( oColor[iBand] - nPix > nNearDist ||
+                       nPix > nNearDist + oColor[iBand] )
                     {
                         bIsNonBlack = TRUE;
                         break;
                     }
                 }
+                
+                if (bIsNonBlack == FALSE)
+                    break;          
             }
 
-            if( bIsNonBlack )
-            {
+            if (bIsNonBlack) {
                 panLastLineCounts[i]++;
 
                 if( panLastLineCounts[i] > nMaxNonBlack )
                     continue; 
             }
-            else
-                panLastLineCounts[i] = 0;
+            //else
+            //  panLastLineCounts[i] = 0; // not sure this even makes sense 
 
+            /***** replace the pixel values *****/
+
+            int iBand;
             for( iBand = 0; iBand < nSrcBands; iBand++ )
-            {
-                if( bNearWhite )
-                    pabyLine[i * nDstBands + iBand] = 255;
-                else
-                    pabyLine[i * nDstBands + iBand] = 0;
-            }
+                pabyLine[i * nDstBands + iBand] = nReplacevalue;
 
             /***** alpha *****/
-            
-            if( nSrcBands != nDstBands )
+
+            if( nDstBands > nSrcBands )
                 pabyLine[i * nDstBands + nDstBands - 1] = 0;
 
             /***** mask *****/
@@ -521,72 +649,106 @@ static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart, int iEnd,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Horizontal Checking.                                            */
-/* -------------------------------------------------------------------- */
+    /* -------------------------------------------------------------------- */
+    /*      Horizontal Checking.                                            */
+    /* -------------------------------------------------------------------- */
+    
     if( bDoHorizontalCheck )
     {
         int nNonBlackPixels = 0;
 
+        /***** on a bottom up pass assume nMaxNonBlack is 0 *****/ 
+
+        if (bBottomUp)
+            nMaxNonBlack = 0;
+
         if( iStart < iEnd )
             iDir = 1;
         else
             iDir = -1;
+        int bDoTest = TRUE;
 
         for( i = iStart; i != iEnd; i += iDir )
         {
-            int iBand;
-            int bIsNonBlack = FALSE;
 
-            for( iBand = 0; iBand < nSrcBands; iBand++ )
-            {
-                if( bNearWhite )
-                {
-                    if( (255 - pabyLine[i * nDstBands + iBand]) > nNearDist )
+            /***** not seen any valid data? *****/
+
+            if ( bDoTest ) {
+
+                /***** is the pixel valid data? ****/
+
+                int bIsNonBlack = FALSE;
+
+                /***** loop over the colors *****/
+
+                int iColor;
+                for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
+
+                    Color oColor = (*poColors)[iColor];
+
+                    bIsNonBlack = FALSE;
+
+                    /***** loop over the bands *****/
+
+                    int iBand;
+                    for( iBand = 0; iBand < nSrcBands; iBand++ )
                     {
-                        bIsNonBlack = TRUE;
-                        break;
+                        int nPix = pabyLine[i * nDstBands + iBand];
+
+                        if( oColor[iBand] - nPix > nNearDist ||
+                           nPix > nNearDist + oColor[iBand] )
+                        {
+                            bIsNonBlack = TRUE;
+                            break;
+                        }
                     }
+                    
+                    if (bIsNonBlack == FALSE)
+                        break;          
                 }
-                else
-                {
-                    if( pabyLine[i * nDstBands + iBand] > nNearDist )
-                    {
-                        bIsNonBlack = TRUE;
-                        break;
-                    }
+
+                if (bIsNonBlack) {
+
+                    /***** use nNonBlackPixels in grey areas  *****/
+                    /***** from the verical pass's grey areas ****/
+
+                    if( panLastLineCounts[i] <= nMaxNonBlack )
+                        nNonBlackPixels = panLastLineCounts[i];
+                    else 
+                        nNonBlackPixels++;
                 }
-            }
 
-            if( bIsNonBlack )
-            {
-                nNonBlackPixels++;
+                if( nNonBlackPixels > nMaxNonBlack ) {
+                    bDoTest = FALSE;
+                    continue;
+                }
 
-                if( nNonBlackPixels > nMaxNonBlack )
-                    return;
-            }
-            else
-                nNonBlackPixels = 0;
+                /***** replace the pixel values *****/
 
-            for( iBand = 0; iBand < nSrcBands; iBand++ )
-            {
-                if( bNearWhite )
-                    pabyLine[i * nDstBands + iBand] = 255;
-                else
-                    pabyLine[i * nDstBands + iBand] = 0;
-            }
+                int iBand;
+                for( iBand = 0; iBand < nSrcBands; iBand++ )
+                    pabyLine[i * nDstBands + iBand] = nReplacevalue;
 
-            /***** alpha *****/
-            
-            if( nSrcBands != nDstBands )
-                pabyLine[i * nDstBands + nDstBands - 1] = 0;
+                /***** alpha *****/
 
-            /***** mask *****/
+                if( nDstBands > nSrcBands )
+                    pabyLine[i * nDstBands + nDstBands - 1] = 0;
 
-            if (pabyMask != NULL)
-                pabyMask[i] = 0;
-            
+                /***** mask *****/
+
+                if (pabyMask != NULL)
+                    pabyMask[i] = 0;
+            }
+
+            /***** seen valid data but test if the *****/
+            /***** vertical pass saw any non valid data *****/
+
+            else if( panLastLineCounts[i] == 0 ) {
+                bDoTest = TRUE;
+                nNonBlackPixels = 0;
+            }        
         }
     }
 
 }
+
diff --git a/apps/ogr2ogr.cpp b/apps/ogr2ogr.cpp
index d013f15..54f0a7f 100644
--- a/apps/ogr2ogr.cpp
+++ b/apps/ogr2ogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2ogr.cpp 22027 2011-03-25 19:28:44Z rouault $
+ * $Id: ogr2ogr.cpp 23530 2011-12-11 17:13:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for translating between formats.
@@ -34,7 +34,7 @@
 #include "ogr_api.h"
 #include "gdal.h"
 
-CPL_CVSID("$Id: ogr2ogr.cpp 22027 2011-03-25 19:28:44Z rouault $");
+CPL_CVSID("$Id: ogr2ogr.cpp 23530 2011-12-11 17:13:55Z rouault $");
 
 static int bSkipFailures = FALSE;
 static int nGroupTransactions = 200;
@@ -43,6 +43,13 @@ static int nFIDToFetch = OGRNullFID;
 
 static void Usage(int bShort = TRUE);
 
+typedef enum
+{
+    NONE,
+    SEGMENTIZE,
+    SIMPLIFY_PRESERVE_TOPOLOGY,
+} GeomOperation;
+
 static int TranslateLayer( OGRDataSource *poSrcDS, 
                            OGRLayer * poSrcLayer,
                            OGRDataSource *poDstDS,
@@ -55,7 +62,8 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
                            char **papszSelFields,
                            int bAppend, int eGType,
                            int bOverwrite,
-                           double dfMaxSegmentLength,
+                           GeomOperation eGeomOp,
+                           double dfGeomOpParam,
                            char** papszFieldTypesToString,
                            long nCountLayerFeatures,
                            int bWrapDateline,
@@ -68,6 +76,83 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
                            void *pProgressArg);
 
 
+/* -------------------------------------------------------------------- */
+/*                  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" },
+                                               { 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);
+}
+
 /************************************************************************/
 /*                            IsNumber()                               */
 /************************************************************************/
@@ -199,9 +284,9 @@ class OGRSplitListFieldLayer : public OGRLayer
     virtual void                 ResetReading() { poSrcLayer->ResetReading(); }
     virtual int                  TestCapability(const char*) { return FALSE; }
 
-    virtual int                  GetFeatureCount()
+    virtual int                  GetFeatureCount( int bForce = TRUE )
     {
-        return poSrcLayer->GetFeatureCount();
+        return poSrcLayer->GetFeatureCount(bForce);
     }
 
     virtual OGRSpatialReference *GetSpatialRef()
@@ -526,6 +611,8 @@ OGRFeatureDefn* OGRSplitListFieldLayer::GetLayerDefn()
 int main( int nArgc, char ** papszArgv )
 
 {
+    int          bQuiet = FALSE;
+    int          bFormatExplicitelySet = FALSE;
     const char  *pszFormat = "ESRI Shapefile";
     const char  *pszDataSource = NULL;
     const char  *pszDestDataSource = NULL;
@@ -546,7 +633,8 @@ int main( int nArgc, char ** papszArgv )
     const char  *pszSQLStatement = NULL;
     const char  *pszDialect = NULL;
     int         eGType = -2;
-    double       dfMaxSegmentLength = 0;
+    GeomOperation eGeomOp = NONE;
+    double       dfGeomOpParam = 0;
     char        **papszFieldTypesToString = NULL;
     int          bDisplayProgress = FALSE;
     GDALProgressFunc pfnProgress = NULL;
@@ -596,8 +684,14 @@ int main( int nArgc, char ** papszArgv )
         {
             Usage(FALSE);
         }
+
+        else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") )
+        {
+            bQuiet = TRUE;
+        }
         else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
         {
+            bFormatExplicitelySet = TRUE;
             pszFormat = papszArgv[++iArg];
         }
         else if( EQUAL(papszArgv[iArg],"-dsco") && iArg < nArgc-1 )
@@ -730,7 +824,13 @@ int main( int nArgc, char ** papszArgv )
         }
         else if( EQUAL(papszArgv[iArg],"-segmentize") && iArg < nArgc-1 )
         {
-            dfMaxSegmentLength = atof(papszArgv[++iArg]);
+            eGeomOp = SEGMENTIZE;
+            dfGeomOpParam = atof(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-simplify") && iArg < nArgc-1 )
+        {
+            eGeomOp = SIMPLIFY_PRESERVE_TOPOLOGY;
+            dfGeomOpParam = atof(papszArgv[++iArg]);
         }
         else if( EQUAL(papszArgv[iArg],"-fieldTypeToString") && iArg < nArgc-1 )
         {
@@ -962,7 +1062,7 @@ int main( int nArgc, char ** papszArgv )
             Usage();
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Open data source.                                               */
 /* -------------------------------------------------------------------- */
@@ -994,10 +1094,43 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     OGRDataSource       *poODS = NULL;
     OGRSFDriver          *poDriver = NULL;
+    int                  bCloseODS = TRUE;
 
     if( bUpdate )
     {
-        poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE, &poDriver );
+        /* Special case for FileGDB that doesn't like updating if the same */
+        /* GDB is opened twice. It stalls at datasource closing. So use just */
+        /* one single connection. This could also TRUE for other drivers. */
+        if (EQUAL(poDS->GetDriver()->GetName(), "FileGDB") &&
+            strcmp(pszDestDataSource, pszDataSource) == 0)
+        {
+            poODS = poDS;
+            poDriver = poODS->GetDriver();
+            bCloseODS = FALSE;
+            if (bOverwrite || bAppend)
+            {
+                /* Various tests to avoid overwriting the source layer(s) */
+                /* or to avoid appending a layer to itself */
+                int bError = FALSE;
+                if (pszNewLayerName == NULL)
+                    bError = TRUE;
+                else if (CSLCount(papszLayers) == 1)
+                    bError = strcmp(pszNewLayerName, papszLayers[0]) == 0;
+                else if (pszSQLStatement == NULL)
+                    bError = TRUE;
+                if (bError)
+                {
+                    fprintf( stderr,
+                             "ERROR: -nln name must be specified combined with "
+                             "a single source layer name,\nor a -sql statement, and "
+                             "name must be different from an existing layer.\n");
+                    exit(1);
+                }
+            }
+        }
+        else
+            poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE, &poDriver );
+
         if( poODS == NULL )
         {
             if (bOverwrite || bAppend)
@@ -1035,19 +1168,13 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     if( !bUpdate )
     {
+        if (!bQuiet && !bFormatExplicitelySet)
+            CheckDestDataSourceNameConsistency(pszDestDataSource, pszFormat);
+
         OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
         int                  iDriver;
 
-        for( iDriver = 0;
-             iDriver < poR->GetDriverCount() && poDriver == NULL;
-             iDriver++ )
-        {
-            if( EQUAL(poR->GetDriver(iDriver)->GetName(),pszFormat) )
-            {
-                poDriver = poR->GetDriver(iDriver);
-            }
-        }
-
+        poDriver = poR->GetDriverByName(pszFormat);
         if( poDriver == NULL )
         {
             fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
@@ -1068,6 +1195,33 @@ int main( int nArgc, char ** papszArgv )
         }
 
 /* -------------------------------------------------------------------- */
+/*      Special case to improve user experience when translating        */
+/*      a datasource with multiple layers into a shapefile. If the      */
+/*      user gives a target datasource with .shp and it does not exist, */
+/*      the shapefile driver will try to create a file, but this is not */
+/*      appropriate because here we have several layers, so create      */
+/*      a directory instead.                                            */
+/* -------------------------------------------------------------------- */
+        VSIStatBufL  sStat;
+        if (EQUAL(poDriver->GetName(), "ESRI Shapefile") &&
+            pszSQLStatement == NULL &&
+            (CSLCount(papszLayers) > 1 ||
+             (CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)) &&
+            pszNewLayerName == NULL &&
+            EQUAL(CPLGetExtension(pszDestDataSource), "SHP") &&
+            VSIStatL(pszDestDataSource, &sStat) != 0)
+        {
+            if (VSIMkdir(pszDestDataSource, 0755) != 0)
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to create directory %s\n"
+                      "for shapefile datastore.\n",
+                      pszDestDataSource );
+                exit(1);
+            }
+        }
+
+/* -------------------------------------------------------------------- */
 /*      Create the output data source.                                  */
 /* -------------------------------------------------------------------- */
         poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
@@ -1167,7 +1321,7 @@ int main( int nArgc, char ** papszArgv )
             if( !TranslateLayer( poDS, poPassedLayer, poODS, papszLCO, 
                                  pszNewLayerName, bTransform, poOutputSRS, bNullifyOutputSRS,
                                  poSourceSRS, papszSelFields, bAppend, eGType,
-                                 bOverwrite, dfMaxSegmentLength, papszFieldTypesToString,
+                                 bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
                                  nCountLayerFeatures, bWrapDateline, poClipSrc, poClipDst,
                                  bExplodeCollections, pszZField, pszWHERE, pfnProgress, pProgressArg))
             {
@@ -1268,7 +1422,14 @@ int main( int nArgc, char ** papszArgv )
                 continue;
 
             if( pszWHERE != NULL )
-                poLayer->SetAttributeFilter( pszWHERE );
+            {
+                if( poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
+                {
+                    fprintf( stderr, "FAILURE: SetAttributeFilter(%s) failed.\n", pszWHERE );
+                    if (!bSkipFailures)
+                        exit( 1 );
+                }
+            }
 
             if( poSpatialFilter != NULL )
                 poLayer->SetSpatialFilter( poSpatialFilter );
@@ -1348,7 +1509,7 @@ int main( int nArgc, char ** papszArgv )
             if( !TranslateLayer( poDS, poPassedLayer, poODS, papszLCO, 
                                 pszNewLayerName, bTransform, poOutputSRS, bNullifyOutputSRS,
                                 poSourceSRS, papszSelFields, bAppend, eGType,
-                                bOverwrite, dfMaxSegmentLength, papszFieldTypesToString,
+                                bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
                                 panLayerCountFeatures[iLayer], bWrapDateline, poClipSrc, poClipDst,
                                 bExplodeCollections, pszZField, pszWHERE, pfnProgress, pProgressArg)
                 && !bSkipFailures )
@@ -1382,7 +1543,8 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     OGRSpatialReference::DestroySpatialReference(poOutputSRS);
     OGRSpatialReference::DestroySpatialReference(poSourceSRS);
-    OGRDataSource::DestroyDataSource(poODS);
+    if (bCloseODS)
+        OGRDataSource::DestroyDataSource(poODS);
     OGRDataSource::DestroyDataSource(poDS);
     OGRGeometryFactory::destroyGeometry(poSpatialFilter);
     OGRGeometryFactory::destroyGeometry(poClipSrc);
@@ -1434,7 +1596,8 @@ static void Usage(int bShort)
             "               [-clipdstsql sql_statement] [-clipdstlayer layer]\n"
             "               [-clipdstwhere expression]\n"
             "               [-wrapdateline]\n"
-            "               [-segmentize max_dist] [-fieldTypeToString All|(type1[,type2]*)]\n"
+            "               [[-simplify tolerance] | [-segmentize max_dist]]\n"
+            "               [-fieldTypeToString All|(type1[,type2]*)]\n"
             "               [-splitlistfields] [-maxsubfields val]\n"
             "               [-explodecollections] [-zfield field_name]\n");
 
@@ -1469,6 +1632,7 @@ static void Usage(int bShort)
             " -skipfailures: skip features or layers that fail to convert\n"
             " -gt n: group n features per transaction (default 200)\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"
             "                       Used to create intermediate points\n"
             " -dsco NAME=VALUE: Dataset creation option (format specific)\n"
@@ -1560,7 +1724,8 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
                            OGRSpatialReference *poSourceSRS,
                            char **papszSelFields,
                            int bAppend, int eGType, int bOverwrite,
-                           double dfMaxSegmentLength,
+                           GeomOperation eGeomOp,
+                           double dfGeomOpParam,
                            char** papszFieldTypesToString,
                            long nCountLayerFeatures,
                            int bWrapDateline,
@@ -1663,30 +1828,32 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Find the layer.                                                 */
 /* -------------------------------------------------------------------- */
-    int iLayer = -1;
-    poDstLayer = NULL;
 
     /* 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);
-    poDstDS->GetLayerByName(pszNewLayerName);
+    poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
     CPLPopErrorHandler();
     CPLErrorReset();
 
-    for( iLayer = 0; iLayer < poDstDS->GetLayerCount(); iLayer++ )
+    int iLayer = -1;
+    if (poDstLayer != NULL)
     {
-        OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
-
-        if( poLayer != NULL 
-            && EQUAL(poLayer->GetName(),pszNewLayerName) )
+        int nLayerCount = poDstDS->GetLayerCount();
+        for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
         {
-            poDstLayer = poLayer;
-            break;
+            OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
+            if (poLayer == poDstLayer)
+                break;
         }
+
+        if (iLayer == nLayerCount)
+            /* shouldn't happen with an ideal driver */
+            poDstLayer = NULL;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      If the user requested overwrite, and we have the layer in       */
 /*      question we need to delete it now so it will get recreated      */
@@ -1733,7 +1900,8 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
                     eGType = wkbUnknown | n25DBit;
                 }
             }
-            else if ( pszZField )
+
+            if ( pszZField )
                 eGType |= wkb25DBit;
         }
 
@@ -1903,6 +2071,7 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
                     }
                 }
                 bFieldRequested |= CSLFindString(papszWHEREUsedFields, pszFieldName) >= 0;
+                bFieldRequested |= (pszZField != NULL && strcmp(pszFieldName, pszZField) == 0);
 
                 /* If source field not requested, add it to ignored files list */
                 if (!bFieldRequested)
@@ -1988,7 +2157,8 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
 /* -------------------------------------------------------------------- */
     OGRFeature  *poFeature;
     int         nFeaturesInTransaction = 0;
-    long        nCount = 0;
+    GIntBig      nCount = 0; /* written + failed */
+    GIntBig      nFeaturesWritten = 0;
 
     int iSrcZField = -1;
     if (pszZField != NULL)
@@ -2086,10 +2256,31 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
                 }
 
                 if (iSrcZField != -1)
+                {
                     SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
+                    /* This will correct the coordinate dimension to 3 */
+                    OGRGeometry* poDupGeometry = poDstGeometry->clone();
+                    poDstFeature->SetGeometryDirectly(poDupGeometry);
+                    poDstGeometry = poDupGeometry;
+                }
 
-                if (dfMaxSegmentLength > 0)
-                    poDstGeometry->segmentize(dfMaxSegmentLength);
+                if (eGeomOp == SEGMENTIZE)
+                {
+                    if (dfGeomOpParam > 0)
+                        poDstGeometry->segmentize(dfGeomOpParam);
+                }
+                else if (eGeomOp == SIMPLIFY_PRESERVE_TOPOLOGY)
+                {
+                    if (dfGeomOpParam > 0)
+                    {
+                        OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(dfGeomOpParam);
+                        if (poNewGeom)
+                        {
+                            poDstFeature->SetGeometryDirectly(poNewGeom);
+                            poDstGeometry = poNewGeom;
+                        }
+                    }
+                }
 
                 if (poClipSrc)
                 {
@@ -2166,8 +2357,11 @@ static int TranslateLayer( OGRDataSource *poSrcDS,
             }
 
             CPLErrorReset();
-            if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE
-                && !bSkipFailures )
+            if( poDstLayer->CreateFeature( poDstFeature ) == OGRERR_NONE )
+            {
+                nFeaturesWritten ++;
+            }
+            else if( !bSkipFailures )
             {
                 if( nGroupTransactions )
                     poDstLayer->RollbackTransaction();
@@ -2194,6 +2388,9 @@ end_loop:
     if( nGroupTransactions )
         poDstLayer->CommitTransaction();
 
+    CPLDebug("OGR2OGR", CPL_FRMT_GIB " features written in layer '%s'",
+             nFeaturesWritten, pszNewLayerName);
+
 /* -------------------------------------------------------------------- */
 /*      Cleaning                                                        */
 /* -------------------------------------------------------------------- */
diff --git a/apps/ogr_utilities.dox b/apps/ogr_utilities.dox
index b952d2a..9db4cd6 100644
--- a/apps/ogr_utilities.dox
+++ b/apps/ogr_utilities.dox
@@ -15,9 +15,7 @@ toolkit:
 
 lists information about an OGR supported data source
 
-\if man
-\section synopsis SYNOPSIS
-\endif
+\section ogrinfo_synopsis SYNOPSIS
 
 \htmlonly
 Usage:
@@ -32,9 +30,7 @@ ogrinfo [--help-general] [-ro] [-q] [-where restricted_where]
 
 \endverbatim
 
-\if man
-\section description DESCRIPTION
-\endif
+\section ogrinfo_description DESCRIPTION
 
 The ogrinfo program lists various information about an OGR supported data
 source to stdout (the terminal). 
@@ -83,9 +79,7 @@ If no query parameters are provided, all features are reported.
 
 Geometries are reported in OGC WKT format.
 
-\if man
-\section example EXAMPLE
-\endif
+\section ogrinfo_example EXAMPLE
 
 Example reporting all layers in an NTF file:
 \verbatim
@@ -156,7 +150,7 @@ OGRFeature(BL2000_LINK):2
 \endverbatim
 
 \if man
-\section author AUTHORS
+\section ogrinfo_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -165,9 +159,7 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 converts simple features data between file formats
 
-\if man
-\section synopsis SYNOPSIS
-\endif
+\section ogr2ogr_synopsis SYNOPSIS
 
 \htmlonly
 Usage:
@@ -193,15 +185,14 @@ Advanced options :
                [-clipdstsql sql_statement] [-clipdstlayer layer]
                [-clipdstwhere expression]
                [-wrapdateline]
-               [-segmentize max_dist] [-fieldTypeToString All|(type1[,type2]*)]
+               [[-simplify tolerance] | [-segmentize max_dist]]
+               [-fieldTypeToString All|(type1[,type2]*)]
                [-splitlistfields] [-maxsubfields val]
                [-explodecollections] [-zfield field_name]
 
 \endverbatim
 
-\if man
-\section description DESCRIPTION
-\endif
+\section ogr2ogr_description DESCRIPTION
 
 This program can be used to convert simple features data between file formats
 performing various operations during the process such as spatial or attribute
@@ -245,6 +236,7 @@ Add "25D" to the name to get 2.5D versions.</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>
+<dt> <b>-preserve_fid</b>:</dt><dd>Use the FID of the source features instead of letting the output driver to automatically assign a new one.</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
@@ -258,7 +250,8 @@ 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)</dd>
+<dt> <b>-gt</b> <em>n</em>:</dt><dd> group <em>n</em> features per transaction (default 200). 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
 box (expressed in source SRS), WKT geometry (POLYGON or MULTIPOLYGON), from a
@@ -276,8 +269,10 @@ you will generally want to use it in combination of the -clipdstlayer, -clipdstw
 <dt> <b>-clipdstlayer</b> <em>layername</em>:</dt><dd>Select the named layer from the destination clip datasource.</dd>
 <dt> <b>-clipdstwhere</b> <em>expression</em>:</dt><dd>Restrict desired geometries based on attribute query.</dd>
 <dt> <b>-wrapdateline</b>:</dt><dd> (starting with GDAL 1.7.0) split geometries crossing the dateline meridian (long. = +/- 180deg)</dd>
+<dt> <b>-simplify</b><em> tolerance</em>:</dt><dd> (starting with GDAL 1.9.0) distance tolerance for simplification.
+This method will preserve topology, in particular for polygon geometries.</dd>
 <dt> <b>-segmentize</b><em> max_dist</em>:</dt><dd> (starting with GDAL 1.6.0) maximum distance between 2 nodes.
-Used to create intermediate pointsspatial query extents</dd>
+Used to create intermediate points</dd>
 <dt> <b>-fieldTypeToString</b><em> type1, ...</em>:</dt><dd> (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 <b>All</b> can be used to convert all fields to strings.
@@ -288,9 +283,23 @@ This is an alternate way to using the CAST operator of OGR SQL, that may avoid t
 <dt> <b>-zfield</b> <em>field_name</em>:</dt><dd>(starting with GDAL 1.8.0) Uses the specified field to fill the Z coordinate of geometries</dd>
 </dl>
 
-\if man
-\section example EXAMPLE
-\endif
+\section ogr2ogr_performance PERFORMANCE HINTS
+
+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
+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.
+
+For PostgreSQL, the PG_USE_COPY config option can be set to YES for significantly insertion
+performance boot. See the PG driver documentation page.
+
+More generally, consult the documentation page of the input and output drivers for performance hints.
+
+\section ogr2ogr_example EXAMPLE
 
 Example appending to an existing layer (both flags need to be used):
 
@@ -307,7 +316,7 @@ Example reprojecting from ETRS_1989_LAEA_52N_10E to EPSG:4326 and clipping to a
 More examples are given in the individual format pages.
 
 \if man
-\section author AUTHOR
+\section ogr2ogr_author AUTHOR
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
@@ -316,9 +325,7 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 creates a tileindex
 
-\if man
-\section synopsis SYNOPSIS
-\endif
+\section ogrtindex_synopsis SYNOPSIS
 
 \htmlonly
 Usage:
@@ -330,9 +337,7 @@ ogrtindex [-lnum n]... [-lname name]... [-f output_format]
                  output_dataset src_dataset...
 \endverbatim
 
-\if man
-\section description DESCRIPTION
-\endif
+\section ogrtindex_description DESCRIPTION
 
 The ogrtindex program can be used to create a tileindex - a file containing
 a list of the identities of a bunch of other files along with there spatial
@@ -365,9 +370,7 @@ It is a flaw of the current ogrtindex program that no attempt is made to
 copy the coordinate system definition from the source datasets to the tile
 index (as is expected by MapServer when PROJECTION AUTO is in use).   
 
-\if man
-\section example EXAMPLE
-\endif
+\section ogrtindex_example EXAMPLE
 
 This example would create a shapefile (tindex.shp) containing a tile index
 of the BL2000_LINK layers in all the NTF files in the wrk directory:
@@ -376,7 +379,7 @@ of the BL2000_LINK layers in all the NTF files in the wrk directory:
 \endverbatim
 
 \if man
-\section author AUTHORS
+\section ogrtindex_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 \endif
diff --git a/apps/ogrinfo.cpp b/apps/ogrinfo.cpp
index 241fbd9..4a1029a 100644
--- a/apps/ogrinfo.cpp
+++ b/apps/ogrinfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrinfo.cpp 20589 2010-09-12 16:47:56Z rouault $
+ * $Id: ogrinfo.cpp 23119 2011-09-24 16:15:21Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing OGR driver data.
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrinfo.cpp 20589 2010-09-12 16:47:56Z rouault $");
+CPL_CVSID("$Id: ogrinfo.cpp 23119 2011-09-24 16:15:21Z rouault $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
@@ -238,7 +238,13 @@ int main( int nArgc, char ** papszArgv )
         if( poResultSet != NULL )
         {
             if( pszWHERE != NULL )
-                poResultSet->SetAttributeFilter( pszWHERE );
+            {
+                if (poResultSet->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
+                {
+                    printf( "FAILURE: SetAttributeFilter(%s) failed.\n", pszWHERE );
+                    exit(1);
+                }
+            }
 
             ReportOnLayer( poResultSet, NULL, NULL );
             poDS->ReleaseResultSet( poResultSet );
@@ -357,7 +363,13 @@ static void ReportOnLayer( OGRLayer * poLayer, const char *pszWHERE,
 /*      Set filters if provided.                                        */
 /* -------------------------------------------------------------------- */
     if( pszWHERE != NULL )
-        poLayer->SetAttributeFilter( pszWHERE );
+    {
+        if (poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
+        {
+            printf( "FAILURE: SetAttributeFilter(%s) failed.\n", pszWHERE );
+            exit(1);
+        }
+    }
 
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( poSpatialFilter );
diff --git a/apps/test_ogrsf.cpp b/apps/test_ogrsf.cpp
index 7ce39a5..f14b169 100644
--- a/apps/test_ogrsf.cpp
+++ b/apps/test_ogrsf.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: test_ogrsf.cpp 21462 2011-01-11 22:29:39Z rouault $
+ * $Id: test_ogrsf.cpp 23602 2011-12-19 21:35:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Formal test harnass for OGRLayer implementations.
@@ -32,13 +32,14 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: test_ogrsf.cpp 21462 2011-01-11 22:29:39Z rouault $");
+CPL_CVSID("$Id: test_ogrsf.cpp 23602 2011-12-19 21:35:25Z rouault $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
 
 static void Usage();
 static int TestOGRLayer( OGRDataSource * poDS, OGRLayer * poLayer, int bIsSQLLayer );
+static int TestInterleavedReading( const char* pszDataSource, char** papszLayers );
 
 /************************************************************************/
 /*                                main()                                */
@@ -193,6 +194,13 @@ int main( int nArgc, char ** papszArgv )
                     poLayer->GetName() );
             bRet &= TestOGRLayer( poDS, poLayer, FALSE );
         }
+
+        if (poDS->GetLayerCount() >= 2)
+        {
+            OGRDataSource::DestroyDataSource(poDS);
+            poDS = NULL;
+            bRet &= TestInterleavedReading( pszDataSource, NULL );
+        }
     }
     else
     {
@@ -217,6 +225,13 @@ int main( int nArgc, char ** papszArgv )
             
             papszLayerIter ++;
         }
+
+        if (CSLCount(papszLayers) >= 2)
+        {
+            OGRDataSource::DestroyDataSource(poDS);
+            poDS = NULL;
+            bRet &= TestInterleavedReading( pszDataSource, papszLayers );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -330,12 +345,53 @@ static int TestOGRLayerFeatureCount( OGRDataSource* poDS, OGRLayer *poLayer, int
     if (!bIsSQLLayer)
     {
         CPLString osSQL;
-        osSQL.Printf("SELECT COUNT(*) FROM \"%s\"", poLayer->GetName());
+        const char* pszLayerName = poLayer->GetName();
+        int i;
+        char ch;
+        for(i=0;(ch = pszLayerName[i]) != 0;i++)
+        {
+            if (ch >= '0' && ch <= '9')
+            {
+                if (i == 0)
+                    break;
+            }
+            else if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')))
+                break;
+        }
+        /* Only quote if needed. Quoting conventions depend on the driver... */
+        if (ch == 0)
+            osSQL.Printf("SELECT COUNT(*) FROM %s", pszLayerName);
+        else
+        {
+            if (EQUAL(poDS->GetDriver()->GetName(), "MYSQL"))
+                osSQL.Printf("SELECT COUNT(*) FROM `%s`", pszLayerName);
+            else if (EQUAL(poDS->GetDriver()->GetName(), "PostgreSQL") &&
+                     strchr(pszLayerName, '.'))
+            {
+                char** papszTokens = CSLTokenizeStringComplex(pszLayerName, ".", 0, 0);
+                if (CSLCount(papszTokens) == 2)
+                {
+                    osSQL.Printf("SELECT COUNT(*) FROM \"%s\".\"%s\"", papszTokens[0], papszTokens[1]);
+                }
+                else
+                    osSQL.Printf("SELECT COUNT(*) FROM \"%s\"", pszLayerName);
+                CSLDestroy(papszTokens);
+            }
+            else if (EQUAL(poDS->GetDriver()->GetName(), "SQLAnywhere"))
+                osSQL.Printf("SELECT COUNT(*) FROM %s", pszLayerName);
+            else
+                osSQL.Printf("SELECT COUNT(*) FROM \"%s\"", pszLayerName);
+        }
         OGRLayer* poSQLLyr = poDS->ExecuteSQL(osSQL.c_str(), NULL, NULL);
         if (poSQLLyr)
         {
             OGRFeature* poFeatCount = poSQLLyr->GetNextFeature();
-            if (nClaimedFC != poFeatCount->GetFieldAsInteger(0))
+            if (poFeatCount == NULL)
+            {
+                bRet = FALSE;
+                printf( "ERROR: '%s' failed.\n", osSQL.c_str() );
+            }
+            else if (nClaimedFC != poFeatCount->GetFieldAsInteger(0))
             {
                 bRet = FALSE;
                 printf( "ERROR: Claimed feature count %d doesn't match '%s' one, %d.\n",
@@ -366,7 +422,7 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
 
 {
     int bRet = TRUE;
-    OGRFeature  *papoFeatures[5], *poFeature;
+    OGRFeature  *papoFeatures[5], *poFeature = NULL;
     int         iFeature;
 
     poLayer->SetSpatialFilter( NULL );
@@ -388,14 +444,32 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
     
     for( iFeature = 0; iFeature < 5; iFeature++ )
     {
+        papoFeatures[iFeature] = NULL;
+    }
+    for( iFeature = 0; iFeature < 5; iFeature++ )
+    {
         papoFeatures[iFeature] = poLayer->GetNextFeature();
-        CPLAssert( papoFeatures[iFeature] != NULL );
+        if( papoFeatures[iFeature] == NULL )
+        {
+            if( bVerbose )
+                printf( "INFO: Only %d features on layer,"
+                        "skipping random read test.\n",
+                        iFeature );
+            goto end;
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Test feature 2.                                                 */
 /* -------------------------------------------------------------------- */
     poFeature = poLayer->GetFeature( papoFeatures[1]->GetFID() );
+    if (poFeature == NULL)
+    {
+        printf( "ERROR: Cannot fetch feature %ld.\n",
+                 papoFeatures[1]->GetFID() );
+        goto end;
+    }
+
     if( !poFeature->Equal( papoFeatures[1] ) )
     {
         bRet = FALSE;
@@ -403,6 +477,8 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
                 "       have returned a different feature than sequential\n"
                 "       reading indicates should have happened.\n",
                 papoFeatures[1]->GetFID() );
+        poFeature->DumpReadable(stdout);
+        papoFeatures[1]->DumpReadable(stdout);
 
         goto end;
     }
@@ -452,6 +528,8 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
     OGRFeature  *papoFeatures[5], *poFeature = NULL;
     int         iFeature;
 
+    memset(papoFeatures, 0, sizeof(papoFeatures));
+
     poLayer->SetSpatialFilter( NULL );
     
     if( poLayer->GetFeatureCount() < 5 )
@@ -472,7 +550,12 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
     for( iFeature = 0; iFeature < 5; iFeature++ )
     {
         papoFeatures[iFeature] = poLayer->GetNextFeature();
-        CPLAssert( papoFeatures[iFeature] != NULL );
+        if( papoFeatures[iFeature] == NULL )
+        {
+            bRet = FALSE;
+            printf( "ERROR: Cannot get feature %d.\n", iFeature );
+            goto end;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -581,8 +664,10 @@ static int TestOGRLayerRandomWrite( OGRLayer *poLayer )
     int         iFeature;
     long        nFID2, nFID5;
 
+    memset(papoFeatures, 0, sizeof(papoFeatures));
+
     poLayer->SetSpatialFilter( NULL );
-    
+
     if( poLayer->GetFeatureCount() < 5 )
     {
         if( bVerbose )
@@ -609,7 +694,12 @@ static int TestOGRLayerRandomWrite( OGRLayer *poLayer )
     for( iFeature = 0; iFeature < 5; iFeature++ )
     {
         papoFeatures[iFeature] = poLayer->GetNextFeature();
-        CPLAssert( papoFeatures[iFeature] != NULL );
+        if( papoFeatures[iFeature] == NULL )
+        {
+            bRet = FALSE;
+            printf( "ERROR: Cannot get feature %d.\n", iFeature );
+            goto end;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -641,6 +731,12 @@ static int TestOGRLayerRandomWrite( OGRLayer *poLayer )
 /*      Now re-read feature 2 to verify the effect stuck.               */
 /* -------------------------------------------------------------------- */
     poFeature = poLayer->GetFeature( nFID5 );
+    if(poFeature == NULL)
+    {
+        bRet = FALSE;
+        printf( "ERROR: Attempt to GetFeature( nFID5 ) failed.\n" );
+        goto end;
+    }
     if( !poFeature->Equal(papoFeatures[1]) )
     {
         bRet = FALSE;
@@ -832,7 +928,7 @@ static int TestSpatialFilter( OGRLayer *poLayer )
 /*      filter that doesn't include this feature, and test again.       */
 /************************************************************************/
 
-static int TestAttributeFilter( OGRLayer *poLayer )
+static int TestAttributeFilter( OGRDataSource* poDS, OGRLayer *poLayer )
 
 {
     int bRet = TRUE;
@@ -881,7 +977,21 @@ static int TestAttributeFilter( OGRLayer *poLayer )
 /*      Construct inclusive filter.                                     */
 /* -------------------------------------------------------------------- */
 
-    osAttributeFilter = pszFieldName;
+    if (EQUAL(poDS->GetDriver()->GetName(), "PostgreSQL") &&
+        (strchr(pszFieldName, '_') || strchr(pszFieldName, ' ')))
+    {
+        osAttributeFilter = "\"";
+        osAttributeFilter += pszFieldName;
+        osAttributeFilter += "\"";
+    }
+    else if (strchr(pszFieldName, ' ') || pszFieldName[0] == '_')
+    {
+        osAttributeFilter = "'";
+        osAttributeFilter += pszFieldName;
+        osAttributeFilter += "'";
+    }
+    else
+        osAttributeFilter = pszFieldName;
     osAttributeFilter += " = ";
     if (eType == OFTString)
         osAttributeFilter += "'";
@@ -925,8 +1035,22 @@ static int TestAttributeFilter( OGRLayer *poLayer )
 /* -------------------------------------------------------------------- */
 /*      Construct exclusive filter.                                     */
 /* -------------------------------------------------------------------- */
-    osAttributeFilter = pszFieldName;
-    osAttributeFilter += " != ";
+    if (EQUAL(poDS->GetDriver()->GetName(), "PostgreSQL") &&
+        (strchr(pszFieldName, '_') || strchr(pszFieldName, ' ')))
+    {
+        osAttributeFilter = "\"";
+        osAttributeFilter += pszFieldName;
+        osAttributeFilter += "\"";
+    }
+    else if (strchr(pszFieldName, ' ') || pszFieldName[0] == '_')
+    {
+        osAttributeFilter = "'";
+        osAttributeFilter += pszFieldName;
+        osAttributeFilter += "'";
+    }
+    else
+        osAttributeFilter = pszFieldName;
+    osAttributeFilter += " <> ";
     if (eType == OFTString)
         osAttributeFilter += "'";
     osAttributeFilter += osValue;
@@ -989,6 +1113,300 @@ static int TestAttributeFilter( OGRLayer *poLayer )
 }
 
 /************************************************************************/
+/*                         TestOGRLayerUTF8()                           */
+/************************************************************************/
+
+static int TestOGRLayerUTF8 ( OGRLayer *poLayer )
+{
+    int bRet = TRUE;
+
+    poLayer->SetSpatialFilter( NULL );
+    poLayer->SetAttributeFilter( NULL );
+    poLayer->ResetReading();
+
+    int bIsAdvertizedAsUTF8 = poLayer->TestCapability( OLCStringsAsUTF8 );
+    int nFields = poLayer->GetLayerDefn()->GetFieldCount();
+    int bFoundString = FALSE;
+    int bFoundNonASCII = FALSE;
+    int bFoundUTF8 = FALSE;
+    int bCanAdvertizeUTF8 = TRUE;
+
+    OGRFeature* poFeature = NULL;
+    while( bRet && (poFeature = poLayer->GetNextFeature()) != NULL )
+    {
+        for(int i = 0; i<nFields; i++)
+        {
+            if (!poFeature->IsFieldSet(i))
+                continue;
+            if (poFeature->GetFieldDefnRef(i)->GetType() == OFTString)
+            {
+                const char* pszVal = poFeature->GetFieldAsString(i);
+                if (pszVal[0] != 0)
+                {
+                    bFoundString = TRUE;
+                    const GByte* pszIter = (const GByte*) pszVal;
+                    int bIsASCII = TRUE;
+                    while(*pszIter)
+                    {
+                        if (*pszIter >= 128)
+                        {
+                            bFoundNonASCII = TRUE;
+                            bIsASCII = FALSE;
+                            break;
+                        }
+                        pszIter ++;
+                    }
+                    int bIsUTF8 = CPLIsUTF8(pszVal, -1);
+                    if (bIsUTF8 && !bIsASCII)
+                        bFoundUTF8 = TRUE;
+                    if (bIsAdvertizedAsUTF8)
+                    {
+                        if (!bIsUTF8)
+                        {
+                            printf( "ERROR: Found non-UTF8 content at field %d of feature %ld, but layer is advertized as UTF-8.\n",
+                                    i, poFeature->GetFID() );
+                            bRet = FALSE;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        if (!bIsUTF8)
+                            bCanAdvertizeUTF8 = FALSE;
+                    }
+                }
+            }
+        }
+        OGRFeature::DestroyFeature(poFeature);
+    }
+
+    if (!bFoundString)
+    {
+    }
+    else if (bCanAdvertizeUTF8)
+    {
+        if (bIsAdvertizedAsUTF8)
+        {
+            if (bFoundUTF8)
+            {
+                printf( "INFO: Layer has UTF-8 content and is consistently declared as having UTF-8 content.\n" );
+            }
+            else if (!bFoundNonASCII)
+            {
+                printf( "INFO: Layer has ASCII only content and is consistently declared as having UTF-8 content.\n" );
+            }
+        }
+        else
+        {
+            if (bFoundUTF8)
+            {
+                printf( "INFO: Layer could perhaps be advertized as UTF-8 compatible (and it has non-ASCII UTF-8 content).\n" );
+            }
+            else if (!bFoundNonASCII)
+            {
+                printf( "INFO: Layer could perhaps be advertized as UTF-8 compatible (it has only ASCII content).\n" );
+            }
+        }
+    }
+    else
+    {
+        printf( "INFO: Layer has non UTF-8 content (and is consistently declared as not being UTF-8 compatible).\n" );
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                         TestGetExtent()                              */
+/************************************************************************/
+
+static int TestGetExtent ( OGRLayer *poLayer )
+{
+    int bRet = TRUE;
+
+    poLayer->SetSpatialFilter( NULL );
+    poLayer->SetAttributeFilter( NULL );
+    poLayer->ResetReading();
+
+    OGREnvelope sExtent;
+    OGREnvelope sExtentSlow;
+
+    OGRErr eErr = poLayer->GetExtent(&sExtent, TRUE);
+    OGRErr eErr2 = poLayer->OGRLayer::GetExtent(&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");
+        }
+        else
+        {
+            bRet = FALSE;
+            printf("ERROR: GetExtent() failed but OGRLayer::GetExtent() succeeded.\n");
+        }
+    }
+    else if (eErr == OGRERR_NONE)
+    {
+        if (fabs(sExtentSlow.MinX - sExtent.MinX) < 1e-10 &&
+            fabs(sExtentSlow.MinY - sExtent.MinY) < 1e-10 &&
+            fabs(sExtentSlow.MaxX - sExtent.MaxX) < 1e-10 &&
+            fabs(sExtentSlow.MaxY - sExtent.MaxY) < 1e-10)
+        {
+            printf("INFO: GetExtent() test passed.\n");
+        }
+        else
+        {
+            if (sExtentSlow.Contains(sExtent))
+            {
+                printf("INFO: sExtentSlow.Contains(sExtent)\n");
+            }
+            else if (sExtent.Contains(sExtentSlow))
+            {
+                printf("INFO: sExtent.Contains(sExtentSlow)\n");
+            }
+            else
+            {
+                printf("INFO: unknown relationship between sExtent and sExentSlow.\n");
+            }
+            printf("INFO: sExtentSlow.MinX = %.15f\n", sExtentSlow.MinX);
+            printf("INFO: sExtentSlow.MinY = %.15f\n", sExtentSlow.MinY);
+            printf("INFO: sExtentSlow.MaxX = %.15f\n", sExtentSlow.MaxX);
+            printf("INFO: sExtentSlow.MaxY = %.15f\n", sExtentSlow.MaxY);
+            printf("INFO: sExtent.MinX = %.15f\n", sExtent.MinX);
+            printf("INFO: sExtent.MinY = %.15f\n", sExtent.MinY);
+            printf("INFO: sExtent.MaxX = %.15f\n", sExtent.MaxX);
+            printf("INFO: sExtent.MaxY = %.15f\n", sExtent.MaxY);
+        }
+    }
+
+    return bRet;
+}
+
+/*************************************************************************/
+/*             TestOGRLayerDeleteAndCreateFeature()                      */
+/*                                                                       */
+/*      Test delete feature by trying to delete the last feature and     */
+/*      recreate it.                                                     */
+/*************************************************************************/
+
+static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
+
+{
+    int bRet = TRUE;
+    OGRFeature  * poFeature = NULL;
+    OGRFeature  * poFeatureTest = NULL;
+    long        nFID;
+
+    poLayer->SetSpatialFilter( NULL );
+    
+    if( !poLayer->TestCapability( OLCRandomRead ) )
+    {
+        if( bVerbose )
+            printf( "INFO: Skipping delete feature test since this layer "
+                    "doesn't support random read.\n" );
+        return bRet;
+    }
+
+    if( poLayer->GetFeatureCount() == 0 )
+    {
+        if( bVerbose )
+            printf( "INFO: No feature available on layer '%s',"
+                    "skipping delete/create feature test.\n",
+                    poLayer->GetName() );
+        
+        return bRet;
+    }
+/* -------------------------------------------------------------------- */
+/*      Fetch the last feature                                          */
+/* -------------------------------------------------------------------- */
+    poLayer->ResetReading();
+
+    poLayer->SetNextByIndex(poLayer->GetFeatureCount() - 1);
+    poFeature = poLayer->GetNextFeature();
+    if (poFeature == NULL)
+    {
+        bRet = FALSE;
+        printf( "ERROR: Could not get last feature of layer.\n" );
+        goto end;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get the feature ID of the last feature                          */
+/* -------------------------------------------------------------------- */
+    nFID = poFeature->GetFID();
+
+/* -------------------------------------------------------------------- */
+/*      Delete the feature.                                             */
+/* -------------------------------------------------------------------- */
+    if( poLayer->DeleteFeature( nFID ) != OGRERR_NONE )
+    {
+        bRet = FALSE;
+        printf( "ERROR: Attempt to DeleteFeature() failed.\n" );
+        goto end;
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Now re-read the feature to verify the delete effect worked.     */
+/* -------------------------------------------------------------------- */
+    CPLPushErrorHandler(CPLQuietErrorHandler); /* silent legitimate error message */
+    poFeatureTest = poLayer->GetFeature( nFID );
+    CPLPopErrorHandler();
+    if( poFeatureTest != NULL)
+    {
+        bRet = FALSE;
+        printf( "ERROR: The feature was not deleted.\n" );
+    }
+    else
+    {
+        printf( "INFO: Delete Feature test passed.\n" );
+    }
+    OGRFeature::DestroyFeature(poFeatureTest);
+
+/* -------------------------------------------------------------------- */
+/*      Re-insert the features to restore to original state             */
+/* -------------------------------------------------------------------- */
+    if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
+    {
+        bRet = FALSE;
+        printf( "ERROR: Attempt to restore feature failed.\n" );
+    }
+
+    if( poFeature->GetFID() != nFID )
+    {
+        /* 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" );
+        nFID = poFeature->GetFID();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Now re-read the feature to verify the create effect worked.     */
+/* -------------------------------------------------------------------- */
+    poFeatureTest = poLayer->GetFeature( nFID );
+    if( poFeatureTest == NULL)
+    {
+        bRet = FALSE;
+        printf( "ERROR: The feature was not created.\n" );
+    }
+    else
+    {
+        printf( "INFO: Create Feature test passed.\n" );
+    }
+    OGRFeature::DestroyFeature(poFeatureTest);
+    
+end:
+/* -------------------------------------------------------------------- */
+/*      Cleanup.                                                        */
+/* -------------------------------------------------------------------- */
+
+    OGRFeature::DestroyFeature(poFeature);
+
+    return bRet;
+}
+
+/************************************************************************/
 /*                            TestOGRLayer()                            */
 /************************************************************************/
 
@@ -1020,7 +1438,12 @@ static int TestOGRLayer( OGRDataSource* poDS, OGRLayer * poLayer, int bIsSQLLaye
 /* -------------------------------------------------------------------- */
 /*      Test attribute filtering                                        */
 /* -------------------------------------------------------------------- */
-    bRet &= TestAttributeFilter( poLayer );
+    bRet &= TestAttributeFilter( poDS, poLayer );
+
+/* -------------------------------------------------------------------- */
+/*      Test GetExtent()                                                */
+/* -------------------------------------------------------------------- */
+    bRet &= TestGetExtent( poLayer );
 
 /* -------------------------------------------------------------------- */
 /*      Test random reading.                                            */
@@ -1039,6 +1462,14 @@ static int TestOGRLayer( OGRDataSource* poDS, OGRLayer * poLayer, int bIsSQLLaye
     }
     
 /* -------------------------------------------------------------------- */
+/*      Test delete feature.                                            */
+/* -------------------------------------------------------------------- */
+    if( poLayer->TestCapability( OLCDeleteFeature ) )
+    {
+        bRet &= TestOGRLayerDeleteAndCreateFeature( poLayer );
+    }
+    
+/* -------------------------------------------------------------------- */
 /*      Test random writing.                                            */
 /* -------------------------------------------------------------------- */
     if( poLayer->TestCapability( OLCRandomWrite ) )
@@ -1046,5 +1477,135 @@ static int TestOGRLayer( OGRDataSource* poDS, OGRLayer * poLayer, int bIsSQLLaye
         bRet &= TestOGRLayerRandomWrite( poLayer );
     }
 
+    bRet &= TestOGRLayerUTF8( poLayer );
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                        TestInterleavedReading()                      */
+/************************************************************************/
+
+static int TestInterleavedReading( const char* pszDataSource, char** papszLayers )
+{
+    int bRet = TRUE;
+    OGRDataSource* poDS = NULL;
+    OGRDataSource* poDS2 = NULL;
+    OGRLayer* poLayer1 = NULL;
+    OGRLayer* poLayer2 = NULL;
+    OGRFeature* poFeature11_Ref = NULL;
+    OGRFeature* poFeature12_Ref = NULL;
+    OGRFeature* poFeature21_Ref = NULL;
+    OGRFeature* poFeature22_Ref = NULL;
+    OGRFeature* poFeature11 = NULL;
+    OGRFeature* poFeature12 = NULL;
+    OGRFeature* poFeature21 = NULL;
+    OGRFeature* poFeature22 = NULL;
+
+    /* Check that we have 2 layers with at least 2 features */
+    poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, NULL );
+    if (poDS == NULL)
+    {
+        printf( "INFO: Skipping TestInterleavedReading(). Cannot reopen datasource\n" );
+        goto bye;
+    }
+
+    poLayer1 = papszLayers ? poDS->GetLayerByName(papszLayers[0]) : poDS->GetLayer(0);
+    poLayer2 = papszLayers ? poDS->GetLayerByName(papszLayers[1]) : poDS->GetLayer(1);
+    if (poLayer1 == NULL || poLayer2 == NULL ||
+        poLayer1->GetFeatureCount() < 2 || poLayer2->GetFeatureCount() < 2)
+    {
+        printf( "INFO: Skipping TestInterleavedReading(). Test conditions are not met\n" );
+        goto bye;
+    }
+
+    /* Test normal reading */
+    OGRDataSource::DestroyDataSource(poDS);
+    poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, NULL );
+    poDS2 = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, NULL );
+    if (poDS == NULL || poDS2 == NULL)
+    {
+        printf( "INFO: Skipping TestInterleavedReading(). Cannot reopen datasource\n" );
+        goto bye;
+    }
+
+    poLayer1 = papszLayers ? poDS->GetLayerByName(papszLayers[0]) : poDS->GetLayer(0);
+    poLayer2 = papszLayers ? poDS->GetLayerByName(papszLayers[1]) : poDS->GetLayer(1);
+    if (poLayer1 == NULL || poLayer2 == NULL)
+    {
+        printf( "ERROR: Skipping TestInterleavedReading(). Test conditions are not met\n" );
+        bRet = FALSE;
+        goto bye;
+    }
+
+    poFeature11_Ref = poLayer1->GetNextFeature();
+    poFeature12_Ref = poLayer1->GetNextFeature();
+    poFeature21_Ref = poLayer2->GetNextFeature();
+    poFeature22_Ref = poLayer2->GetNextFeature();
+    if (poFeature11_Ref == NULL || poFeature12_Ref == NULL || poFeature21_Ref == NULL || poFeature22_Ref == NULL)
+    {
+        printf( "ERROR: TestInterleavedReading() failed: poFeature11_Ref=%p, poFeature12_Ref=%p, poFeature21_Ref=%p, poFeature22_Ref=%p\n",
+                poFeature11_Ref, poFeature12_Ref, poFeature21_Ref, poFeature22_Ref);
+        bRet = FALSE;
+        goto bye;
+    }
+
+    /* Test interleaved reading */
+    poLayer1 = papszLayers ? poDS2->GetLayerByName(papszLayers[0]) : poDS2->GetLayer(0);
+    poLayer2 = papszLayers ? poDS2->GetLayerByName(papszLayers[1]) : poDS2->GetLayer(1);
+    if (poLayer1 == NULL || poLayer2 == NULL)
+    {
+        printf( "ERROR: Skipping TestInterleavedReading(). Test conditions are not met\n" );
+        bRet = FALSE;
+        goto bye;
+    }
+
+    poFeature11 = poLayer1->GetNextFeature();
+    poFeature21 = poLayer2->GetNextFeature();
+    poFeature12 = poLayer1->GetNextFeature();
+    poFeature22 = poLayer2->GetNextFeature();
+
+    if (poFeature11 == NULL || poFeature21 == NULL || poFeature12 == NULL || poFeature22 == NULL)
+    {
+        printf( "ERROR: TestInterleavedReading() failed: poFeature11=%p, poFeature21=%p, poFeature12=%p, poFeature22=%p\n",
+                poFeature11, poFeature21, poFeature12, poFeature22);
+        bRet = FALSE;
+        goto bye;
+    }
+
+    if (poFeature12->Equal(poFeature11))
+    {
+        printf( "WARN: TestInterleavedReading() failed: poFeature12 == poFeature11. "
+                "The datasource resets the layer reading when interleaved layer reading pattern is detected. Acceptable but could be improved\n" );
+        goto bye;
+    }
+
+    /* We cannot directly compare the feature as they don't share */
+    /* the same (pointer) layer definition, so just compare FIDs */
+    if (poFeature12_Ref->GetFID() != poFeature12->GetFID())
+    {
+        printf( "ERROR: TestInterleavedReading() failed: poFeature12_Ref != poFeature12\n" );
+        poFeature12_Ref->DumpReadable(stdout, NULL);
+        poFeature12->DumpReadable(stdout, NULL);
+        bRet = FALSE;
+        goto bye;
+    }
+
+    if( bVerbose )
+    {
+        printf("INFO: TestInterleavedReading() successfull.\n");
+    }
+
+bye:
+    OGRFeature::DestroyFeature(poFeature11_Ref);
+    OGRFeature::DestroyFeature(poFeature12_Ref);
+    OGRFeature::DestroyFeature(poFeature21_Ref);
+    OGRFeature::DestroyFeature(poFeature22_Ref);
+    OGRFeature::DestroyFeature(poFeature11);
+    OGRFeature::DestroyFeature(poFeature21);
+    OGRFeature::DestroyFeature(poFeature12);
+    OGRFeature::DestroyFeature(poFeature22);
+    OGRDataSource::DestroyDataSource(poDS);
+    OGRDataSource::DestroyDataSource(poDS2);
     return bRet;
 }
diff --git a/configure b/configure
index a948a3d..997bbbf 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.67.
+# Generated by GNU Autoconf 2.68.
 #
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -89,6 +89,7 @@ fi
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -171,6 +172,14 @@ test x\$exitcode = x0 || exit 1"
   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'\" &&
   test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
 test \$(( 1 + 1 )) = 2 || exit 1"
   if (eval "$as_required") 2>/dev/null; then :
   as_have_required=yes
@@ -214,11 +223,18 @@ IFS=$as_save_IFS
   # 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
-	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+	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+"$@"}
 fi
 
     if test x$as_have_required = xno; then :
@@ -525,155 +541,8 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 # Sed expression to map a string onto a valid variable name.
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
-
-
-# Check that we are running under the correct shell.
 SHELL=${CONFIG_SHELL-/bin/sh}
 
-case X$lt_ECHO in
-X*--fallback-echo)
-  # Remove one level of quotation (which was required for Make).
-  ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','`
-  ;;
-esac
-
-ECHO=${lt_ECHO-echo}
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
-  # Yippee, $ECHO works!
-  :
-else
-  # Restart under the correct shell.
-  exec $SHELL "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<_LT_EOF
-$*
-_LT_EOF
-  exit 0
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-if test -z "$lt_ECHO"; then
-  if test "X${echo_test_string+set}" != Xset; then
-    # find a string as large as possible, as long as the shell can cope with it
-    for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
-      # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-      if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
-	 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
-      then
-        break
-      fi
-    done
-  fi
-
-  if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
-     echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
-     test "X$echo_testing_string" = "X$echo_test_string"; then
-    :
-  else
-    # The Solaris, AIX, and Digital Unix default echo programs unquote
-    # backslashes.  This makes it impossible to quote backslashes using
-    #   echo "$something" | sed 's/\\/\\\\/g'
-    #
-    # So, first we look for a working echo in the user's PATH.
-
-    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-    for dir in $PATH /usr/ucb; do
-      IFS="$lt_save_ifs"
-      if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
-         test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
-         echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
-         test "X$echo_testing_string" = "X$echo_test_string"; then
-        ECHO="$dir/echo"
-        break
-      fi
-    done
-    IFS="$lt_save_ifs"
-
-    if test "X$ECHO" = Xecho; then
-      # We didn't find a better echo, so look for alternatives.
-      if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
-         echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
-         test "X$echo_testing_string" = "X$echo_test_string"; then
-        # This shell has a builtin print -r that does the trick.
-        ECHO='print -r'
-      elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
-	   test "X$CONFIG_SHELL" != X/bin/ksh; then
-        # If we have ksh, try running configure again with it.
-        ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
-        export ORIGINAL_CONFIG_SHELL
-        CONFIG_SHELL=/bin/ksh
-        export CONFIG_SHELL
-        exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
-      else
-        # Try using printf.
-        ECHO='printf %s\n'
-        if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
-	   echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
-	   test "X$echo_testing_string" = "X$echo_test_string"; then
-	  # Cool, printf works
-	  :
-        elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
-	     test "X$echo_testing_string" = 'X\t' &&
-	     echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
-	     test "X$echo_testing_string" = "X$echo_test_string"; then
-	  CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
-	  export CONFIG_SHELL
-	  SHELL="$CONFIG_SHELL"
-	  export SHELL
-	  ECHO="$CONFIG_SHELL $0 --fallback-echo"
-        elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
-	     test "X$echo_testing_string" = 'X\t' &&
-	     echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
-	     test "X$echo_testing_string" = "X$echo_test_string"; then
-	  ECHO="$CONFIG_SHELL $0 --fallback-echo"
-        else
-	  # maybe with a smaller string...
-	  prev=:
-
-	  for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
-	    if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
-	    then
-	      break
-	    fi
-	    prev="$cmd"
-	  done
-
-	  if test "$prev" != 'sed 50q "$0"'; then
-	    echo_test_string=`eval $prev`
-	    export echo_test_string
-	    exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
-	  else
-	    # Oops.  We lost completely, so just stick with echo.
-	    ECHO=echo
-	  fi
-        fi
-      fi
-    fi
-  fi
-fi
-
-# Copy echo and quote the copy suitably for passing to libtool from
-# the Makefile, instead of quoting the original, which is used later.
-lt_ECHO=$ECHO
-if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
-   lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
-fi
-
-
-
 
 test -n "$DJDIR" || exec 7<&0 </dev/null
 exec 6>&1
@@ -742,9 +611,14 @@ ac_includes_default="\
 
 ac_subst_vars='LTLIBOBJS
 LIBOBJS
+HAVE_ARMADILLO
 RASDAMAN_LIB
 RASDAMAN_INC
 RASDAMAN_ENABLED
+JVM_LIB
+MDB_ENABLED
+JAVA_INC
+JAVA_HOME
 BINDINGS
 PY_HAVE_SETUPTOOLS
 pymoddir
@@ -761,11 +635,15 @@ GDAL_VERSION_MINOR
 GDAL_VERSION_MAJOR
 PROJ_INCLUDE
 PROJ_STATIC
+PODOFO_INC
+HAVE_PODOFO
 POPPLER_INC
 POPPLER_BASE_STREAM_HAS_TWO_ARGS
 POPPLER_HAS_OPTCONTENT
 HAVE_POPPLER
 PAM_SETTING
+FREEXL_INCLUDE
+HAVE_FREEXL
 OPENCL_LIB
 OPENCL_FLAGS
 GEOS_CONFIG
@@ -787,6 +665,8 @@ SQLITE_INC
 SQLITE3_LDFLAGS
 SQLITE3_CFLAGS
 SQLITE3_VERSION
+SPATIALITE_AMALGAMATION
+SPATIALITE_INC
 HAVE_SPATIALITE
 CURL_LIB
 CURL_INC
@@ -832,9 +712,16 @@ MRSID_FLAGS
 MRSID_INCLUDE
 KAKDIR
 ECW_SETTING
+FGDB_INC
+FGDB_LIB
+FGDB_ENABLED
 HAVE_OPENJPEG
 JASPER_FLAGS
 HAVE_JASPER
+NETCDF_HAS_HDF4
+NETCDF_HAS_NC4
+NETCDF_ROOT
+NETCDF_SETTING
 HDF5_INCLUDE
 HAVE_HDF5
 HDF4_INCLUDE
@@ -852,8 +739,8 @@ TIFF_SETTING
 PCIDSK_INCLUDE
 PCIDSK_LIB
 PCIDSK_SETTING
+GTA_SETTING
 PNG_SETTING
-NETCDF_SETTING
 PCRASTER_SETTING
 FITS_SETTING
 HAVE_GRASS
@@ -865,7 +752,11 @@ PG_INC
 HAVE_PG
 PG_CONFIG
 LIBLZMA_SETTING
+LTLIBICONV
+LIBICONV
 LIBZ_SETTING
+RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
+RENAME_INTERNAL_LIBTIFF_SYMBOLS
 HAVE_HIDE_INTERNAL_SYMBOLS
 HAVE_GCC_ATOMIC_BUILTINS
 HAVE_LIBTOOL
@@ -878,9 +769,11 @@ OTOOL
 LIPO
 NMEDIT
 DSYMUTIL
-lt_ECHO
+MANIFEST_TOOL
+AWK
 RANLIB
 STRIP
+ac_ct_AR
 AR
 LN_S
 NM
@@ -961,23 +854,28 @@ enable_static
 with_pic
 enable_fast_install
 with_gnu_ld
+with_sysroot
 enable_libtool_lock
 with_libtool
 with_ld_shared
 with_unix_stdio_64
 enable_debug
-with_with_hide_internal_symbols
+with_hide_internal_symbols
+with_rename_internal_libtiff_symbols
+with_rename_internal_libgeotiff_symbols
 with_local
 with_threads
 with_libz
+enable_rpath
+with_libiconv_prefix
 with_liblzma
 with_pg
 with_grass
 with_libgrass
 with_cfitsio
 with_pcraster
-with_netcdf
 with_png
+with_gta
 with_pcidsk
 with_libtiff
 with_geotiff
@@ -988,8 +886,10 @@ with_ogdi
 with_fme
 with_hdf4
 with_hdf5
+with_netcdf
 with_jasper
 with_openjpeg
+with_fgdb
 with_ecw
 with_kakadu
 with_mrsid
@@ -1024,12 +924,17 @@ with_sde
 with_sde_version
 with_vfk
 with_epsilon
+with_webp
 with_geos
 with_opencl
 with_opencl_include
 with_opencl_lib
+with_freexl
 with_pam
 with_poppler
+with_podofo
+with_podofo_lib
+with_podofo_extra_lib_for_test
 with_static_proj4
 with_gdal_ver
 with_
@@ -1038,7 +943,12 @@ with_php
 with_ruby
 with_python
 with_pymoddir
+with_java
+with_mdb
+with_jvm_lib
+with_jvm_lib_add_rpath
 with_rasdaman
+with_armadillo
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1457,7 +1367,7 @@ Try \`$0 --help' for more information"
     $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
     expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
       $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
     ;;
 
   esac
@@ -1672,6 +1582,7 @@ Optional Features:
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
   --enable-debug          enable debugging (disabled by default)
+  --disable-rpath         do not hardcode runtime library paths
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1679,13 +1590,20 @@ Optional Packages:
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-sysroot=DIR Search for dependent libraries within DIR
+                        (or the compiler's sysroot if not specified).
   --without-libtool     Don't use libtool to build the library
   --without-ld-shared   Disable shared library support
   --with-unix-stdio-64=ARG Utilize 64 stdio api (yes/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)
   --with-local=dir      Include /usr/local or other local tree for INCLUDE/LIBS
   --with-threads=ARG    Include thread safe support (ARG=yes(default), no or linkopt)
   --with-libz=ARG       Include libz support (ARG=internal or libz directory)
+  --with-gnu-ld           assume the C compiler uses GNU ld default=no
+  --with-libiconv-prefix[=DIR]  search for libiconv in DIR/include and DIR/lib
+  --without-libiconv-prefix     don't search for libiconv in includedir and libdir
   --with-liblzma=ARG       Include liblzma support (ARG=yes/no)
   --with-pg=ARG           Include PostgreSQL GDAL/OGR Support (ARG=path to
                           pg_config)
@@ -1693,8 +1611,8 @@ Optional Packages:
   --with-libgrass=ARG   Include GRASS support based on libgrass (GRASS 5.0+)
   --with-cfitsio=ARG    Include FITS support (ARG=no or libcfitsio path)
   --with-pcraster=ARG   Include PCRaster (libcsf) support (ARG=internal, no or path)
-  --with-netcdf=ARG     Include netCDF support (ARG=no or netCDF tree prefix)
   --with-png=ARG        Include PNG support (ARG=internal, no or path)
+  --with-gta=ARG        Include GTA support (ARG=no or libgta tree prefix)
   --with-pcidsk=ARG     Path to external PCIDSK SDK, or internal (default), or old
   --with-libtiff=ARG    Libtiff library to use (ARG=internal, yes or path)
   --with-geotiff=ARG    Libgeotiff library to use (ARG=internal, yes or path)
@@ -1705,8 +1623,10 @@ Optional Packages:
   --with-fme=ARG        Include FMEObjects support (ARG=FME_HOME path)
   --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)
   --with-jasper=ARG     Include JPEG-2000 support via JasPer library (ARG=path)
   --with-openjpeg=ARG     Include JPEG-2000 support via OpenJPEG v2 library (ARG=path)
+  --with-fgdb=ARG        Include ESRI File Geodatabase support (ARG=FGDP API Path, yes or no)
   --with-ecw=ARG        Include ECW support (ARG=ECW SDK Path, yes or no)
   --with-kakadu=ARG     Include Kakadu/JPEG2000 support
   --with-mrsid=ARG      Include MrSID support (ARG=path to MrSID DSDK or no)
@@ -1749,13 +1669,18 @@ Optional Packages:
   --with-sde-version=VERSION NUMBER  Set ESRI SDE version number (Default is 80).
   --without-vfk         Disable VFK support
   --with-epsilon=ARG    Include EPSILON support (ARG=no, yes or libepsilon install root path)
+  --with-webp=ARG    Include WEBP support (ARG=no, yes or libwebp install root path)
   --with-geos=ARG         Include GEOS support (ARG=yes, no or geos-config
                           path)
   --with-opencl=ARG       Include OpenCL (GPU) support
   --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)
   --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)
+  --with-podofo-lib=ARG   podofo Link Flags (ie. -L/xxx -lpodofo ...). Mainly for static libpodofo
+  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (ie. -ljpeg ...). Mainly for static libpodofo
   --with-static-proj4=ARG Compile with PROJ.4 statically (ARG=no or path)
   --with-gdal-ver=ARG   Override GDAL version
   --with-macosx-framework         Build and install GDAL as a Mac OS X Framework
@@ -1764,7 +1689,12 @@ Optional Packages:
   --with-ruby           Enable Ruby bindings
   --with-python       Enable python bindings
   --with-pymoddir=ARG   Override Old-gen Python package install dir
+  --with-java       Include Java support (ARG=yes, no or JDK home path)  [default=no]
+  --with-mdb       Include MDB driver
+  --with-jvm-lib=ARG        ARG points to Java libjvm path
+  --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)
   --with-rasdaman=DIR        Include rasdaman support (DIR is rasdaman's install dir).
+  --with-armadillo=ARG       Include Armadillo support for faster TPS transform computation (ARG=yes/no) [default=no]
 
 Some influential environment variables:
   CC          C compiler command
@@ -1846,7 +1776,7 @@ test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
 configure
-generated by GNU Autoconf 2.67
+generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
@@ -1892,7 +1822,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
 	ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_compile
@@ -1930,7 +1860,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
 	ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_compile
@@ -1976,7 +1906,7 @@ fi
   # interfere with the next link command; also delete a directory that is
   # left behind by Apple's compiler.  We do this before executing the actions.
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_link
@@ -1990,7 +1920,7 @@ ac_fn_c_check_header_compile ()
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2008,7 +1938,7 @@ fi
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_compile
 
@@ -2044,7 +1974,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
     ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_cpp
@@ -2086,7 +2016,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
        ac_retval=$ac_status
 fi
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_run
@@ -2099,7 +2029,7 @@ ac_fn_c_check_func ()
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2154,7 +2084,7 @@ fi
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_func
 
@@ -2190,7 +2120,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
     ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_cpp
@@ -2236,7 +2166,7 @@ fi
   # interfere with the next link command; also delete a directory that is
   # left behind by Apple's compiler.  We do this before executing the actions.
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_link
@@ -2249,10 +2179,10 @@ fi
 ac_fn_c_check_header_mongrel ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if eval "test \"\${$3+set}\"" = set; then :
+  if eval \${$3+:} false; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 fi
 eval ac_res=\$$3
@@ -2315,7 +2245,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
 esac
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   eval "$3=\$ac_header_compiler"
@@ -2324,7 +2254,7 @@ eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_mongrel
 
@@ -2501,7 +2431,7 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
 rm -f conftest.val
 
   fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_compute_int
@@ -2515,7 +2445,7 @@ ac_fn_c_check_type ()
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   eval "$3=no"
@@ -2556,7 +2486,7 @@ fi
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_type
 
@@ -2571,7 +2501,7 @@ ac_fn_c_check_decl ()
   as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
 $as_echo_n "checking whether $as_decl_name is declared... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -2602,7 +2532,7 @@ fi
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_decl
 cat >config.log <<_ACEOF
@@ -2610,7 +2540,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.67.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
 
@@ -2942,7 +2872,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
-ac_config_headers="$ac_config_headers port/cpl_config.h:port/cpl_config.h.in:port/cpl_config_extras.h"
+ac_config_headers="$ac_config_headers port/cpl_config.h:port/cpl_config.h.in"
+
 
 
 
@@ -2982,7 +2913,7 @@ $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
 $as_echo_n "checking build system type... " >&6; }
-if test "${ac_cv_build+set}" = set; then :
+if ${ac_cv_build+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_build_alias=$build_alias
@@ -3016,7 +2947,7 @@ case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
 $as_echo_n "checking host system type... " >&6; }
-if test "${ac_cv_host+set}" = set; then :
+if ${ac_cv_host+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test "x$host_alias" = x; then
@@ -3058,7 +2989,7 @@ if test -n "$ac_tool_prefix"; then
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -3098,7 +3029,7 @@ if test -z "$ac_cv_prog_CC"; then
 set dummy gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -3151,7 +3082,7 @@ if test -z "$CC"; then
 set dummy ${ac_tool_prefix}cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -3191,7 +3122,7 @@ if test -z "$CC"; then
 set dummy cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -3250,7 +3181,7 @@ if test -z "$CC"; then
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -3294,7 +3225,7 @@ do
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -3577,7 +3508,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
 ac_clean_files=$ac_clean_files_save
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
 $as_echo_n "checking for suffix of object files... " >&6; }
-if test "${ac_cv_objext+set}" = set; then :
+if ${ac_cv_objext+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3628,7 +3559,7 @@ OBJEXT=$ac_cv_objext
 ac_objext=$OBJEXT
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+if ${ac_cv_c_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3665,7 +3596,7 @@ ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
 $as_echo_n "checking whether $CC accepts -g... " >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then :
+if ${ac_cv_prog_cc_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_c_werror_flag=$ac_c_werror_flag
@@ -3743,7 +3674,7 @@ else
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then :
+if ${ac_cv_prog_cc_c89+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
@@ -3841,7 +3772,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking C_WFLAGS for maximum warnings" >&5
 $as_echo_n "checking C_WFLAGS for maximum warnings... " >&6; }
-if test "${ac_cv_cflags_warn_all+set}" = set; then :
+if ${ac_cv_cflags_warn_all+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_cflags_warn_all="no, unknown"
@@ -3919,7 +3850,7 @@ if test -z "$CXX"; then
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CXX+set}" = set; then :
+if ${ac_cv_prog_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CXX"; then
@@ -3963,7 +3894,7 @@ do
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CXX"; then
@@ -4041,7 +3972,7 @@ done
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4078,7 +4009,7 @@ ac_test_CXXFLAGS=${CXXFLAGS+set}
 ac_save_CXXFLAGS=$CXXFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
 $as_echo_n "checking whether $CXX accepts -g... " >&6; }
-if test "${ac_cv_prog_cxx_g+set}" = set; then :
+if ${ac_cv_prog_cxx_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_cxx_werror_flag=$ac_cxx_werror_flag
@@ -4163,7 +4094,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking CXX_WFLAGS for maximum warnings" >&5
 $as_echo_n "checking CXX_WFLAGS for maximum warnings... " >&6; }
-if test "${ac_cv_cxxflags_warn_all+set}" = set; then :
+if ${ac_cv_cxxflags_warn_all+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_cxxflags_warn_all="no, unknown"
@@ -4240,7 +4171,7 @@ if test -n "$ac_tool_prefix"; then
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -4280,7 +4211,7 @@ if test -z "$ac_cv_prog_CC"; then
 set dummy gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -4333,7 +4264,7 @@ if test -z "$CC"; then
 set dummy ${ac_tool_prefix}cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -4373,7 +4304,7 @@ if test -z "$CC"; then
 set dummy cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -4432,7 +4363,7 @@ if test -z "$CC"; then
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -4476,7 +4407,7 @@ do
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -4560,7 +4491,7 @@ done
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+if ${ac_cv_c_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4597,7 +4528,7 @@ ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
 $as_echo_n "checking whether $CC accepts -g... " >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then :
+if ${ac_cv_prog_cc_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_c_werror_flag=$ac_c_werror_flag
@@ -4675,7 +4606,7 @@ else
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then :
+if ${ac_cv_prog_cc_c89+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
@@ -4786,7 +4717,7 @@ if test -z "$CXX"; then
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CXX+set}" = set; then :
+if ${ac_cv_prog_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CXX"; then
@@ -4830,7 +4761,7 @@ do
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CXX"; then
@@ -4908,7 +4839,7 @@ done
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4945,7 +4876,7 @@ ac_test_CXXFLAGS=${CXXFLAGS+set}
 ac_save_CXXFLAGS=$CXXFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
 $as_echo_n "checking whether $CXX accepts -g... " >&6; }
-if test "${ac_cv_prog_cxx_g+set}" = set; then :
+if ${ac_cv_prog_cxx_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_cxx_werror_flag=$ac_cxx_werror_flag
@@ -5030,13 +4961,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 enable_win32_dll=yes
 
 case $host in
-*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
   if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
 set dummy ${ac_tool_prefix}as; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_AS+set}" = set; then :
+if ${ac_cv_prog_AS+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$AS"; then
@@ -5076,7 +5007,7 @@ if test -z "$ac_cv_prog_AS"; then
 set dummy as; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_AS+set}" = set; then :
+if ${ac_cv_prog_ac_ct_AS+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_AS"; then
@@ -5128,7 +5059,7 @@ fi
 set dummy ${ac_tool_prefix}dlltool; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_DLLTOOL+set}" = set; then :
+if ${ac_cv_prog_DLLTOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$DLLTOOL"; then
@@ -5168,7 +5099,7 @@ if test -z "$ac_cv_prog_DLLTOOL"; then
 set dummy dlltool; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then :
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_DLLTOOL"; then
@@ -5220,7 +5151,7 @@ fi
 set dummy ${ac_tool_prefix}objdump; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
+if ${ac_cv_prog_OBJDUMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$OBJDUMP"; then
@@ -5260,7 +5191,7 @@ if test -z "$ac_cv_prog_OBJDUMP"; then
 set dummy objdump; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_OBJDUMP"; then
@@ -5338,8 +5269,8 @@ esac
 
 
 
-macro_version='2.2.6'
-macro_revision='1.3012'
+macro_version='2.4'
+macro_revision='1.3293'
 
 
 
@@ -5355,9 +5286,78 @@ macro_revision='1.3012'
 
 ltmain="$ac_aux_dir/ltmain.sh"
 
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case "$ECHO" in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
 $as_echo_n "checking for a sed that does not truncate output... " >&6; }
-if test "${ac_cv_path_SED+set}" = set; then :
+if ${ac_cv_path_SED+:} false; then :
   $as_echo_n "(cached) " >&6
 else
             ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
@@ -5439,7 +5439,7 @@ Xsed="$SED -e 1s/^X//"
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
 $as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then :
+if ${ac_cv_path_GREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -z "$GREP"; then
@@ -5502,7 +5502,7 @@ $as_echo "$ac_cv_path_GREP" >&6; }
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
 $as_echo_n "checking for egrep... " >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then :
+if ${ac_cv_path_EGREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
@@ -5569,7 +5569,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; }
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
 $as_echo_n "checking for fgrep... " >&6; }
-if test "${ac_cv_path_FGREP+set}" = set; then :
+if ${ac_cv_path_FGREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
@@ -5700,7 +5700,7 @@ else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
 $as_echo_n "checking for non-GNU ld... " >&6; }
 fi
-if test "${lt_cv_path_LD+set}" = set; then :
+if ${lt_cv_path_LD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -z "$LD"; then
@@ -5740,7 +5740,7 @@ fi
 test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
-if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+if ${lt_cv_prog_gnu_ld+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   # I'd rather use --version here, but apparently some GNU lds only accept -v.
@@ -5767,7 +5767,7 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
-if test "${lt_cv_path_NM+set}" = set; then :
+if ${lt_cv_path_NM+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$NM"; then
@@ -5820,14 +5820,17 @@ if test "$lt_cv_path_NM" != "no"; then
   NM="$lt_cv_path_NM"
 else
   # Didn't find any BSD compatible name lister, look for dumpbin.
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
+if ${ac_cv_prog_DUMPBIN+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$DUMPBIN"; then
@@ -5865,13 +5868,13 @@ fi
 fi
 if test -z "$DUMPBIN"; then
   ac_ct_DUMPBIN=$DUMPBIN
-  for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+  for ac_prog in dumpbin "link -dump"
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then :
+if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_DUMPBIN"; then
@@ -5920,6 +5923,15 @@ esac
   fi
 fi
 
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
 
   if test "$DUMPBIN" != ":"; then
     NM="$DUMPBIN"
@@ -5934,18 +5946,18 @@ test -z "$NM" && NM=nm
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
 $as_echo_n "checking the name lister ($NM) interface... " >&6; }
-if test "${lt_cv_nm_interface+set}" = set; then :
+if ${lt_cv_nm_interface+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:5942: $ac_compile\"" >&5)
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5945: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:5948: output\"" >&5)
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
   cat conftest.out >&5
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -5969,7 +5981,7 @@ fi
 # find the maximum length of command line arguments
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
 $as_echo_n "checking the maximum length of command line arguments... " >&6; }
-if test "${lt_cv_sys_max_cmd_len+set}" = set; then :
+if ${lt_cv_sys_max_cmd_len+:} false; then :
   $as_echo_n "(cached) " >&6
 else
     i=0
@@ -6002,6 +6014,11 @@ else
     lt_cv_sys_max_cmd_len=8192;
     ;;
 
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
   amigaos*)
     # On AmigaOS with pdksh, this test takes hours, literally.
     # So we just punt and use a minimum line length of 8192.
@@ -6066,8 +6083,8 @@ else
       # If test is not a shell built-in, we'll probably end up computing a
       # maximum length that is only half of the actual maximum length, but
       # we can't tell.
-      while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
-	         = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+      while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
 	      test $i != 17 # 1/2 MB should be enough
       do
         i=`expr $i + 1`
@@ -6109,8 +6126,8 @@ $as_echo_n "checking whether the shell understands some XSI constructs... " >&6;
 # Try some XSI features
 xsi_shell=no
 ( _lt_dummy="a/b/c"
-  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
-      = c,a/b,, \
+  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,b/c, \
     && eval 'test $(( 1 + 1 )) -eq 2 \
     && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
   && xsi_shell=yes
@@ -6159,9 +6176,83 @@ esac
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+$as_echo_n "checking how to convert $build file names to $host format... " >&6; }
+if ${lt_cv_to_host_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+$as_echo "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
+if ${lt_cv_to_tool_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+$as_echo "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
 $as_echo_n "checking for $LD option to reload object files... " >&6; }
-if test "${lt_cv_ld_reload_flag+set}" = set; then :
+if ${lt_cv_ld_reload_flag+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_ld_reload_flag='-r'
@@ -6175,6 +6266,11 @@ case $reload_flag in
 esac
 reload_cmds='$LD$reload_flag -o $output$reload_objs'
 case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test "$GCC" != yes; then
+      reload_cmds=false
+    fi
+    ;;
   darwin*)
     if test "$GCC" = yes; then
       reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
@@ -6197,7 +6293,7 @@ if test -n "$ac_tool_prefix"; then
 set dummy ${ac_tool_prefix}objdump; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
+if ${ac_cv_prog_OBJDUMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$OBJDUMP"; then
@@ -6237,7 +6333,7 @@ if test -z "$ac_cv_prog_OBJDUMP"; then
 set dummy objdump; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_OBJDUMP"; then
@@ -6293,7 +6389,7 @@ test -z "$OBJDUMP" && OBJDUMP=objdump
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
 $as_echo_n "checking how to recognize dependent libraries... " >&6; }
-if test "${lt_cv_deplibs_check_method+set}" = set; then :
+if ${lt_cv_deplibs_check_method+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_file_magic_cmd='$MAGIC_CMD'
@@ -6335,16 +6431,18 @@ mingw* | pw32*)
   # Base MSYS/MinGW do not provide the 'file' command needed by
   # func_win32_libid shell function, so use a weaker test based on 'objdump',
   # unless we find 'file', for example because we are cross-compiling.
-  if ( file / ) >/dev/null 2>&1; then
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
     lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
     lt_cv_file_magic_cmd='func_win32_libid'
   else
-    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
     lt_cv_file_magic_cmd='$OBJDUMP -f'
   fi
   ;;
 
-cegcc)
+cegcc*)
   # use the weaker test based on 'objdump'. See mingw*.
   lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
   lt_cv_file_magic_cmd='$OBJDUMP -f'
@@ -6374,6 +6472,10 @@ gnu*)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
 hpux10.20* | hpux11*)
   lt_cv_file_magic_cmd=/usr/bin/file
   case $host_cpu in
@@ -6382,11 +6484,11 @@ hpux10.20* | hpux11*)
     lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
     ;;
   hppa*64*)
-    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
     lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
     ;;
   *)
-    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
     lt_cv_file_magic_test_file=/usr/lib/libc.sl
     ;;
   esac
@@ -6408,11 +6510,11 @@ irix5* | irix6* | nonstopux*)
   ;;
 
 # This must be Linux ELF.
-linux* | k*bsd*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
   else
@@ -6489,6 +6591,21 @@ esac
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
 $as_echo "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
 file_magic_cmd=$lt_cv_file_magic_cmd
 deplibs_check_method=$lt_cv_deplibs_check_method
 test -z "$deplibs_check_method" && deplibs_check_method=unknown
@@ -6504,16 +6621,26 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown
 
 
 
+
+
+
+
+
+
+
+
+
+
 if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ar; ac_word=$2
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_AR+set}" = set; then :
+if ${ac_cv_prog_DLLTOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$AR"; then
-  ac_cv_prog_AR="$AR" # Let the user override the test.
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -6522,7 +6649,7 @@ do
   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
-    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    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
   fi
@@ -6532,10 +6659,10 @@ IFS=$as_save_IFS
 
 fi
 fi
-AR=$ac_cv_prog_AR
-if test -n "$AR"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -6543,17 +6670,17 @@ fi
 
 
 fi
-if test -z "$ac_cv_prog_AR"; then
-  ac_ct_AR=$AR
-  # Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$ac_ct_AR"; then
-  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+  if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -6562,7 +6689,7 @@ do
   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
-    ac_cv_prog_ac_ct_AR="ar"
+    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
   fi
@@ -6572,17 +6699,17 @@ IFS=$as_save_IFS
 
 fi
 fi
-ac_ct_AR=$ac_cv_prog_ac_ct_AR
-if test -n "$ac_ct_AR"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
-$as_echo "$ac_ct_AR" >&6; }
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
-  if test "x$ac_ct_AR" = x; then
-    AR="false"
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
   else
     case $cross_compiling:$ac_tool_warned in
 yes:)
@@ -6590,18 +6717,51 @@ yes:)
 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
 ac_tool_warned=yes ;;
 esac
-    AR=$ac_ct_AR
+    DLLTOOL=$ac_ct_DLLTOOL
   fi
 else
-  AR="$ac_cv_prog_AR"
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
 fi
 
-test -z "$AR" && AR=ar
-test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
 
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+$as_echo_n "checking how to associate runtime and link libraries... " >&6; }
+if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
 
 
 
@@ -6610,15 +6770,17 @@ test -z "$AR_FLAGS" && AR_FLAGS=cru
 
 
 if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
+  for ac_prog in ar
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_STRIP+set}" = set; then :
+if ${ac_cv_prog_AR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$STRIP"; then
-  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -6627,7 +6789,7 @@ do
   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
-    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    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
   fi
@@ -6637,24 +6799,193 @@ IFS=$as_save_IFS
 
 fi
 fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
-$as_echo "$STRIP" >&6; }
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
 
+    test -n "$AR" && break
+  done
 fi
-if test -z "$ac_cv_prog_STRIP"; then
-  ac_ct_STRIP=$STRIP
+if test -z "$AR"; then
+  ac_ct_AR=$AR
+  for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+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
+    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
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_AR" && break
+done
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+fi
+
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+$as_echo_n "checking for archiver @FILE support... " >&6; }
+if ${lt_cv_ar_at_file+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ar_at_file=no
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+      if test "$ac_status" -eq 0; then
+	# Ensure the archiver fails upon bogus file names.
+	rm -f conftest.$ac_objext libconftest.a
+	{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	if test "$ac_status" -ne 0; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+$as_echo "$lt_cv_ar_at_file" >&6; }
+
+if test "x$lt_cv_ar_at_file" = xno; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+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
+    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
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
   # Extract the first word of "strip", so it can be a program name with args.
 set dummy strip; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_STRIP"; then
@@ -6713,7 +7044,7 @@ if test -n "$ac_tool_prefix"; then
 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_RANLIB+set}" = set; then :
+if ${ac_cv_prog_RANLIB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$RANLIB"; then
@@ -6753,7 +7084,7 @@ if test -z "$ac_cv_prog_RANLIB"; then
 set dummy ranlib; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_RANLIB"; then
@@ -6824,6 +7155,20 @@ if test -n "$RANLIB"; then
   old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
 fi
 
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
 
 
 
@@ -6837,7 +7182,47 @@ fi
 
 
 
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+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
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
 
+  test -n "$AWK" && break
+done
 
 
 
@@ -6870,7 +7255,7 @@ compiler=$CC
 # Check for command to grab the raw symbol name followed by C symbol from nm.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
-if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then :
+if ${lt_cv_sys_global_symbol_pipe+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
@@ -6931,8 +7316,8 @@ esac
 lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
 
 # Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
 
 # Handle CRLF in mingw tool chain
 opt_cr=
@@ -6968,6 +7353,7 @@ for ac_symprfx in "" "_"; do
   else
     lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
   fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
 
   # Check to see that the pipe works correctly.
   pipe_works=no
@@ -6993,8 +7379,8 @@ _LT_EOF
   test $ac_status = 0; }; then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5
-  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; } && test -s "$nlist"; then
@@ -7009,6 +7395,18 @@ _LT_EOF
       if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
 	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
 	  cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -7020,7 +7418,7 @@ _LT_EOF
 	  cat <<_LT_EOF >> conftest.$ac_ext
 
 /* The mapping between symbol names and symbols.  */
-const struct {
+LT_DLSYM_CONST struct {
   const char *name;
   void       *address;
 }
@@ -7046,8 +7444,8 @@ static const void *lt_preloaded_setup() {
 _LT_EOF
 	  # Now try linking the two files.
 	  mv conftest.$ac_objext conftstm.$ac_objext
-	  lt_save_LIBS="$LIBS"
-	  lt_save_CFLAGS="$CFLAGS"
+	  lt_globsym_save_LIBS=$LIBS
+	  lt_globsym_save_CFLAGS=$CFLAGS
 	  LIBS="conftstm.$ac_objext"
 	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
 	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
@@ -7057,8 +7455,8 @@ _LT_EOF
   test $ac_status = 0; } && test -s conftest${ac_exeext}; then
 	    pipe_works=yes
 	  fi
-	  LIBS="$lt_save_LIBS"
-	  CFLAGS="$lt_save_CFLAGS"
+	  LIBS=$lt_globsym_save_LIBS
+	  CFLAGS=$lt_globsym_save_CFLAGS
 	else
 	  echo "cannot find nm_test_func in $nlist" >&5
 	fi
@@ -7095,6 +7493,18 @@ else
 $as_echo "ok" >&6; }
 fi
 
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+
+
+
+
+
 
 
 
@@ -7116,6 +7526,43 @@ fi
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+$as_echo_n "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+  withval=$with_sysroot;
+else
+  with_sysroot=no
+fi
+
+
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+   if test "$GCC" = yes; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5
+$as_echo "${with_sysroot}" >&6; }
+   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+   ;;
+esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+$as_echo "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
 # Check whether --enable-libtool-lock was given.
 if test "${enable_libtool_lock+set}" = set; then :
   enableval=$enable_libtool_lock;
@@ -7147,7 +7594,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 7150 "configure"' > conftest.$ac_ext
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7241,7 +7688,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   CFLAGS="$CFLAGS -belf"
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
 $as_echo_n "checking whether the C compiler needs -belf... " >&6; }
-if test "${lt_cv_cc_needs_belf+set}" = set; then :
+if ${lt_cv_cc_needs_belf+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_ext=c
@@ -7309,19 +7756,16 @@ esac
 
 need_locks="$enable_libtool_lock"
 
-
-  case $host_os in
-    rhapsody* | darwin*)
-    if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
-set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_DSYMUTIL+set}" = set; then :
+if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$DSYMUTIL"; then
-  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+  if test -n "$MANIFEST_TOOL"; then
+  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -7330,7 +7774,7 @@ do
   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
-    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    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
   fi
@@ -7340,10 +7784,10 @@ IFS=$as_save_IFS
 
 fi
 fi
-DSYMUTIL=$ac_cv_prog_DSYMUTIL
-if test -n "$DSYMUTIL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
-$as_echo "$DSYMUTIL" >&6; }
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+$as_echo "$MANIFEST_TOOL" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -7351,17 +7795,17 @@ fi
 
 
 fi
-if test -z "$ac_cv_prog_DSYMUTIL"; then
-  ac_ct_DSYMUTIL=$DSYMUTIL
-  # Extract the first word of "dsymutil", so it can be a program name with args.
-set dummy dsymutil; ac_word=$2
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+  # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then :
+if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$ac_ct_DSYMUTIL"; then
-  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+  if test -n "$ac_ct_MANIFEST_TOOL"; then
+  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -7370,7 +7814,7 @@ do
   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
-    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    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
   fi
@@ -7380,17 +7824,17 @@ IFS=$as_save_IFS
 
 fi
 fi
-ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
-if test -n "$ac_ct_DSYMUTIL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
-$as_echo "$ac_ct_DSYMUTIL" >&6; }
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+$as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
-  if test "x$ac_ct_DSYMUTIL" = x; then
-    DSYMUTIL=":"
+  if test "x$ac_ct_MANIFEST_TOOL" = x; then
+    MANIFEST_TOOL=":"
   else
     case $cross_compiling:$ac_tool_warned in
 yes:)
@@ -7398,23 +7842,143 @@ yes:)
 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
 ac_tool_warned=yes ;;
 esac
-    DSYMUTIL=$ac_ct_DSYMUTIL
+    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
   fi
 else
-  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if ${lt_cv_path_mainfest_tool+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&5
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+$as_echo "$lt_cv_path_mainfest_tool" >&6; }
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+  MANIFEST_TOOL=:
 fi
 
+
+
+
+
+
+  case $host_os in
+    rhapsody* | darwin*)
     if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
-set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_NMEDIT+set}" = set; then :
+if ${ac_cv_prog_DSYMUTIL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$NMEDIT"; then
-  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
-else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+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
+    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
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+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
+    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
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
@@ -7449,7 +8013,7 @@ if test -z "$ac_cv_prog_NMEDIT"; then
 set dummy nmedit; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then :
+if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_NMEDIT"; then
@@ -7501,7 +8065,7 @@ fi
 set dummy ${ac_tool_prefix}lipo; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_LIPO+set}" = set; then :
+if ${ac_cv_prog_LIPO+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$LIPO"; then
@@ -7541,7 +8105,7 @@ if test -z "$ac_cv_prog_LIPO"; then
 set dummy lipo; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then :
+if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_LIPO"; then
@@ -7593,7 +8157,7 @@ fi
 set dummy ${ac_tool_prefix}otool; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OTOOL+set}" = set; then :
+if ${ac_cv_prog_OTOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$OTOOL"; then
@@ -7633,7 +8197,7 @@ if test -z "$ac_cv_prog_OTOOL"; then
 set dummy otool; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then :
+if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_OTOOL"; then
@@ -7685,7 +8249,7 @@ fi
 set dummy ${ac_tool_prefix}otool64; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_OTOOL64+set}" = set; then :
+if ${ac_cv_prog_OTOOL64+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$OTOOL64"; then
@@ -7725,7 +8289,7 @@ if test -z "$ac_cv_prog_OTOOL64"; then
 set dummy otool64; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then :
+if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_OTOOL64"; then
@@ -7800,7 +8364,7 @@ fi
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
 $as_echo_n "checking for -single_module linker flag... " >&6; }
-if test "${lt_cv_apple_cc_single_mod+set}" = set; then :
+if ${lt_cv_apple_cc_single_mod+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_apple_cc_single_mod=no
@@ -7829,7 +8393,7 @@ fi
 $as_echo "$lt_cv_apple_cc_single_mod" >&6; }
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
-if test "${lt_cv_ld_exported_symbols_list+set}" = set; then :
+if ${lt_cv_ld_exported_symbols_list+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_ld_exported_symbols_list=no
@@ -7859,6 +8423,38 @@ rm -f core conftest.err conftest.$ac_objext \
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if ${lt_cv_ld_force_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cru libconftest.a conftest.o" >&5
+      $AR cru libconftest.a conftest.o 2>&5
+      echo "$RANLIB libconftest.a" >&5
+      $RANLIB libconftest.a 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
     case $host_os in
     rhapsody* | darwin1.[012])
       _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
@@ -7886,7 +8482,7 @@ $as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
     else
       _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
     fi
-    if test "$DSYMUTIL" != ":"; then
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
       _lt_dsymutil='~$DSYMUTIL $lib || :'
     else
       _lt_dsymutil=
@@ -7906,7 +8502,7 @@ if test -n "$CPP" && test -d "$CPP"; then
   CPP=
 fi
 if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then :
+  if ${ac_cv_prog_CPP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
       # Double quotes because CPP needs to be expanded
@@ -8034,7 +8630,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
 $as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then :
+if ${ac_cv_header_stdc+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -8165,7 +8761,7 @@ for ac_header in dlfcn.h
 do :
   ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
 "
-if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_DLFCN_H 1
 _ACEOF
@@ -8176,410 +8772,23 @@ done
 
 
 
-ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-if test -z "$CXX"; then
-  if test -n "$CCC"; then
-    CXX=$CCC
-  else
-    if test -n "$ac_tool_prefix"; then
-  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CXX+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CXX"; then
-  ac_cv_prog_CXX="$CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-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
-    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
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-CXX=$ac_cv_prog_CXX
-if test -n "$CXX"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
-$as_echo "$CXX" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
+func_stripname_cnf ()
+{
+  case ${2} in
+  .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+  *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+} # func_stripname_cnf
 
 
-    test -n "$CXX" && break
-  done
-fi
-if test -z "$CXX"; then
-  ac_ct_CXX=$CXX
-  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_CXX"; then
-  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-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
-    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
-  fi
-done
-  done
-IFS=$as_save_IFS
 
-fi
-fi
-ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
-if test -n "$ac_ct_CXX"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
-$as_echo "$ac_ct_CXX" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
 
 
-  test -n "$ac_ct_CXX" && break
-done
+# Set options
 
-  if test "x$ac_ct_CXX" = x; then
-    CXX="g++"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    CXX=$ac_ct_CXX
-  fi
-fi
 
-  fi
-fi
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
-  { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    sed '10a\
-... rest of stderr output deleted ...
-         10q' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-  fi
-  rm -f conftest.er1 conftest.err
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-done
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
-$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  ac_compiler_gnu=yes
-else
-  ac_compiler_gnu=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
-$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
-  GXX=yes
-else
-  GXX=
-fi
-ac_test_CXXFLAGS=${CXXFLAGS+set}
-ac_save_CXXFLAGS=$CXXFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
-$as_echo_n "checking whether $CXX accepts -g... " >&6; }
-if test "${ac_cv_prog_cxx_g+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
-   ac_cxx_werror_flag=yes
-   ac_cv_prog_cxx_g=no
-   CXXFLAGS="-g"
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  ac_cv_prog_cxx_g=yes
-else
-  CXXFLAGS=""
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-
-else
-  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
-	 CXXFLAGS="-g"
-	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  ac_cv_prog_cxx_g=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
-$as_echo "$ac_cv_prog_cxx_g" >&6; }
-if test "$ac_test_CXXFLAGS" = set; then
-  CXXFLAGS=$ac_save_CXXFLAGS
-elif test $ac_cv_prog_cxx_g = yes; then
-  if test "$GXX" = yes; then
-    CXXFLAGS="-g -O2"
-  else
-    CXXFLAGS="-g"
-  fi
-else
-  if test "$GXX" = yes; then
-    CXXFLAGS="-O2"
-  else
-    CXXFLAGS=
-  fi
-fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
-    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
-    (test "X$CXX" != "Xg++"))) ; then
-  ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
-$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
-if test -z "$CXXCPP"; then
-  if test "${ac_cv_prog_CXXCPP+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-      # Double quotes because CXXCPP needs to be expanded
-    for CXXCPP in "$CXX -E" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_cxx_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-		     Syntax error
-_ACEOF
-if ac_fn_cxx_try_cpp "$LINENO"; then :
-
-else
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_cxx_try_cpp "$LINENO"; then :
-  # Broken: success on invalid input.
-continue
-else
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-  break
-fi
-
-    done
-    ac_cv_prog_CXXCPP=$CXXCPP
-
-fi
-  CXXCPP=$ac_cv_prog_CXXCPP
-else
-  ac_cv_prog_CXXCPP=$CXXCPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
-$as_echo "$CXXCPP" >&6; }
-ac_preproc_ok=false
-for ac_cxx_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-		     Syntax error
-_ACEOF
-if ac_fn_cxx_try_cpp "$LINENO"; then :
-
-else
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_cxx_try_cpp "$LINENO"; then :
-  # Broken: success on invalid input.
-continue
-else
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
-  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-_lt_caught_CXX_error=yes; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-else
-  _lt_caught_CXX_error=yes
-fi
-
-
-
-
-# Set options
-
-
-
-        enable_dlopen=no
+        enable_dlopen=no
 
 
 
@@ -8725,6 +8934,7 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool'
 
 
 
+
 test -z "$LN_S" && LN_S="ln -s"
 
 
@@ -8746,7 +8956,7 @@ fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
 $as_echo_n "checking for objdir... " >&6; }
-if test "${lt_cv_objdir+set}" = set; then :
+if ${lt_cv_objdir+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   rm -f .libs 2>/dev/null
@@ -8774,19 +8984,6 @@ _ACEOF
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
 case $host_os in
 aix3*)
   # AIX sometimes has problems with the GCC collect2 program.  For some
@@ -8799,23 +8996,6 @@ aix3*)
   ;;
 esac
 
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\(["`\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to delay expansion of an escaped single quote.
-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
 # Global variables:
 ofile=libtool
 can_build_shared=yes
@@ -8844,7 +9024,7 @@ for cc_temp in $compiler""; do
     *) break;;
   esac
 done
-cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
 
 
 # Only perform the check for file, if the check method requires it
@@ -8854,7 +9034,7 @@ file_magic*)
   if test "$file_magic_cmd" = '$MAGIC_CMD'; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
-if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $MAGIC_CMD in
@@ -8920,7 +9100,7 @@ if test -z "$lt_cv_path_MAGIC_CMD"; then
   if test -n "$ac_tool_prefix"; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
 $as_echo_n "checking for file... " >&6; }
-if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $MAGIC_CMD in
@@ -9053,11 +9233,16 @@ if test -n "$compiler"; then
 lt_prog_compiler_no_builtin_flag=
 
 if test "$GCC" = yes; then
-  lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
-if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
+if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_rtti_exceptions=no
@@ -9073,15 +9258,15 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9076: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:9080: \$? = $ac_status" >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_rtti_exceptions=yes
@@ -9110,8 +9295,6 @@ fi
 lt_prog_compiler_pic=
 lt_prog_compiler_static=
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
-$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 
   if test "$GCC" = yes; then
     lt_prog_compiler_wl='-Wl,'
@@ -9159,6 +9342,12 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
       lt_prog_compiler_pic='-fno-common'
       ;;
 
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
     hpux*)
       # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
       # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
@@ -9201,6 +9390,13 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
       lt_prog_compiler_pic='-fPIC'
       ;;
     esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      lt_prog_compiler_pic='-Xcompiler -fPIC'
+      ;;
+    esac
   else
     # PORTME Check for flag to pass linker flags through the system compiler.
     case $host_os in
@@ -9242,7 +9438,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
       lt_prog_compiler_static='-non_shared'
       ;;
 
-    linux* | k*bsd*-gnu)
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
       case $cc_basename in
       # old Intel for x86_64 which still supported -KPIC.
       ecc*)
@@ -9263,7 +9459,13 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 	lt_prog_compiler_pic='--shared'
 	lt_prog_compiler_static='--static'
 	;;
-      pgcc* | pgf77* | pgf90* | pgf95*)
+      nagfor*)
+	# NAG Fortran compiler
+	lt_prog_compiler_wl='-Wl,-Wl,,'
+	lt_prog_compiler_pic='-PIC'
+	lt_prog_compiler_static='-Bstatic'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
         # Portland Group compilers (*not* the Pentium gcc compiler,
 	# which looks to be a dead project)
 	lt_prog_compiler_wl='-Wl,'
@@ -9275,25 +9477,25 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
         # All Alpha code is PIC.
         lt_prog_compiler_static='-non_shared'
         ;;
-      xl*)
-	# IBM XL C 8.0/Fortran 10.1 on PPC
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
 	lt_prog_compiler_wl='-Wl,'
 	lt_prog_compiler_pic='-qpic'
 	lt_prog_compiler_static='-qstaticlink'
 	;;
       *)
 	case `$CC -V 2>&1 | sed 5q` in
-	*Sun\ C*)
-	  # Sun C 5.9
+	*Sun\ F* | *Sun*Fortran*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
 	  lt_prog_compiler_pic='-KPIC'
 	  lt_prog_compiler_static='-Bstatic'
-	  lt_prog_compiler_wl='-Wl,'
+	  lt_prog_compiler_wl=''
 	  ;;
-	*Sun\ F*)
-	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	*Sun\ C*)
+	  # Sun C 5.9
 	  lt_prog_compiler_pic='-KPIC'
 	  lt_prog_compiler_static='-Bstatic'
-	  lt_prog_compiler_wl=''
+	  lt_prog_compiler_wl='-Wl,'
 	  ;;
 	esac
 	;;
@@ -9325,7 +9527,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
       lt_prog_compiler_pic='-KPIC'
       lt_prog_compiler_static='-Bstatic'
       case $cc_basename in
-      f77* | f90* | f95*)
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
 	lt_prog_compiler_wl='-Qoption ld ';;
       *)
 	lt_prog_compiler_wl='-Wl,';;
@@ -9382,13 +9584,17 @@ case $host_os in
     lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
     ;;
 esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
-$as_echo "$lt_prog_compiler_pic" >&6; }
-
-
-
-
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+$as_echo "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
 
 #
 # Check to make sure the PIC flag actually works.
@@ -9396,7 +9602,7 @@ $as_echo "$lt_prog_compiler_pic" >&6; }
 if test -n "$lt_prog_compiler_pic"; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
-if test "${lt_cv_prog_compiler_pic_works+set}" = set; then :
+if ${lt_cv_prog_compiler_pic_works+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_pic_works=no
@@ -9412,15 +9618,15 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9415: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:9419: \$? = $ac_status" >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_pic_works=yes
@@ -9449,13 +9655,18 @@ fi
 
 
 
+
+
+
+
+
 #
 # Check to make sure the static flag actually works.
 #
 wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
-if test "${lt_cv_prog_compiler_static_works+set}" = set; then :
+if ${lt_cv_prog_compiler_static_works+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_static_works=no
@@ -9468,7 +9679,7 @@ else
      if test -s conftest.err; then
        # Append any errors to the config.log.
        cat conftest.err 1>&5
-       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
        if diff conftest.exp conftest.er2 >/dev/null; then
          lt_cv_prog_compiler_static_works=yes
@@ -9498,7 +9709,7 @@ fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+if ${lt_cv_prog_compiler_c_o+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_c_o=no
@@ -9517,16 +9728,16 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9520: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:9524: \$? = $ac_status" >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o=yes
@@ -9553,7 +9764,7 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; }
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+if ${lt_cv_prog_compiler_c_o+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_c_o=no
@@ -9572,16 +9783,16 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9575: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:9579: \$? = $ac_status" >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o=yes
@@ -9691,13 +9902,36 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
   openbsd*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu)
-    link_all_deplibs=no
-    ;;
   esac
 
   ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
   if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
     # If archive_cmds runs LD, not CC, wlarc should be empty
     wlarc='${wl}'
 
@@ -9715,6 +9949,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
     fi
     supports_anon_versioning=no
     case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
       *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
       *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
       *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
@@ -9730,11 +9965,12 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
 	ld_shlibs=no
 	cat <<_LT_EOF 1>&2
 
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** Warning: the GNU linker, at least up to release 2.19, is reported
 *** to be unable to reliably create shared libraries on AIX.
 *** Therefore, libtool is disabling shared libraries support.  If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
 
 _LT_EOF
       fi
@@ -9770,10 +10006,12 @@ _LT_EOF
       # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
       # as there is no search path for DLLs.
       hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='${wl}--export-all-symbols'
       allow_undefined_flag=unsupported
       always_export_symbols=no
       enable_shared_with_static_runtimes=yes
-      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
 
       if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
         archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
@@ -9791,6 +10029,11 @@ _LT_EOF
       fi
       ;;
 
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
     interix[3-9]*)
       hardcode_direct=no
       hardcode_shlibpath_var=no
@@ -9806,7 +10049,7 @@ _LT_EOF
       archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
       ;;
 
-    gnu* | linux* | tpf* | k*bsd*-gnu)
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
       tmp_diet=no
       if test "$host_os" = linux-dietlibc; then
 	case $cc_basename in
@@ -9816,15 +10059,16 @@ _LT_EOF
       if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
 	 && test "$tmp_diet" = no
       then
-	tmp_addflag=
+	tmp_addflag=' $pic_flag'
 	tmp_sharedflag='-shared'
 	case $cc_basename,$host_cpu in
         pgcc*)				# Portland Group C compiler
-	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	  tmp_addflag=' $pic_flag'
 	  ;;
-	pgf77* | pgf90* | pgf95*)	# Portland Group f77 and f90 compilers
-	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	  tmp_addflag=' $pic_flag -Mnomain' ;;
 	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
 	  tmp_addflag=' -i_dynamic' ;;
@@ -9835,13 +10079,17 @@ _LT_EOF
 	lf95*)				# Lahey Fortran 8.1
 	  whole_archive_flag_spec=
 	  tmp_sharedflag='--shared' ;;
-	xl[cC]*)			# IBM XL C 8.0 on PPC (deal with xlf below)
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
 	  tmp_sharedflag='-qmkshrobj'
 	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  ;;
 	esac
 	case `$CC -V 2>&1 | sed 5q` in
 	*Sun\ C*)			# Sun C 5.9
-	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	  compiler_needs_object=yes
 	  tmp_sharedflag='-G' ;;
 	*Sun\ F*)			# Sun Fortran 8.3
@@ -9857,17 +10105,17 @@ _LT_EOF
         fi
 
 	case $cc_basename in
-	xlf*)
+	xlf* | bgf* | bgxlf* | mpixlf*)
 	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
 	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
 	  hardcode_libdir_flag_spec=
 	  hardcode_libdir_flag_spec_ld='-rpath $libdir'
-	  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
 	  if test "x$supports_anon_versioning" = xyes; then
 	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
 	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
 	      echo "local: *; };" >> $output_objdir/$libname.ver~
-	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	      $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
 	  fi
 	  ;;
 	esac
@@ -9876,13 +10124,13 @@ _LT_EOF
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
 	wlarc=
       else
-	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
       fi
       ;;
 
@@ -9900,8 +10148,8 @@ _LT_EOF
 
 _LT_EOF
       elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
       else
 	ld_shlibs=no
       fi
@@ -9947,8 +10195,8 @@ _LT_EOF
 
     *)
       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
       else
 	ld_shlibs=no
       fi
@@ -9988,8 +10236,10 @@ _LT_EOF
       else
 	# If we're using GNU nm, then we don't want the "-C" option.
 	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
 	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
-	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
 	else
 	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
 	fi
@@ -10051,7 +10301,6 @@ _LT_EOF
 	if test "$aix_use_runtimelinking" = yes; then
 	  shared_flag="$shared_flag "'${wl}-G'
 	fi
-	link_all_deplibs=no
       else
 	# not using gcc
 	if test "$host_cpu" = ia64; then
@@ -10077,7 +10326,13 @@ _LT_EOF
 	allow_undefined_flag='-berok'
         # Determine the default libpath from the value encoded in an
         # empty executable.
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+        if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -10090,25 +10345,32 @@ main ()
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
 
-lt_aix_libpath_sed='
-    /Import File Strings/,/^$/ {
-	/^0/ {
-	    s/^0  *\(.*\)$/\1/
-	    p
-	}
-    }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
-  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
 
         hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
-        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
       else
 	if test "$host_cpu" = ia64; then
 	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
@@ -10117,7 +10379,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	else
 	 # Determine the default libpath from the value encoded in an
 	 # empty executable.
-	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+	 if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -10130,30 +10398,42 @@ main ()
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
 
-lt_aix_libpath_sed='
-    /Import File Strings/,/^$/ {
-	/^0/ {
-	    s/^0  *\(.*\)$/\1/
-	    p
-	}
-    }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
-  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
 
 	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
 	  # Warning - without using the other run time loading flags,
 	  # -berok will link without error, but may produce a broken library.
 	  no_undefined_flag=' ${wl}-bernotok'
 	  allow_undefined_flag=' ${wl}-berok'
-	  # Exported symbols can be pulled into shared objects from archives
-	  whole_archive_flag_spec='$convenience'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec='$convenience'
+	  fi
 	  archive_cmds_need_lc=yes
 	  # This is similar to how AIX traditionally builds its shared libraries.
 	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
@@ -10185,20 +10465,63 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       # Microsoft Visual C++.
       # hardcode_libdir_flag_spec is actually meaningless, as there is
       # no search path for DLLs.
-      hardcode_libdir_flag_spec=' '
-      allow_undefined_flag=unsupported
-      # Tell ltmain to make .lib files, not .a files.
-      libext=lib
-      # Tell ltmain to make .dll files, not .so files.
-      shrext_cmds=".dll"
-      # FIXME: Setting linknames here is a bad hack.
-      archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
-      # The linker will automatically build a .lib file if we build a DLL.
-      old_archive_from_new_cmds='true'
-      # FIXME: Should let the user specify the lib program.
-      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
-      fix_srcfile_path='`cygpath -w "$srcfile"`'
-      enable_shared_with_static_runtimes=yes
+      case $cc_basename in
+      cl*)
+	# Native MSVC
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	always_export_symbols=yes
+	file_list_spec='@'
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=".dll"
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+	  else
+	    sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+	  fi~
+	  $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+	  linknames='
+	# The linker will not automatically build a static lib if we build a DLL.
+	# _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+	enable_shared_with_static_runtimes=yes
+	export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+	# Don't use ranlib
+	old_postinstall_cmds='chmod 644 $oldlib'
+	postlink_cmds='lt_outputfile="@OUTPUT@"~
+	  lt_tool_outputfile="@TOOL_OUTPUT@"~
+	  case $lt_outputfile in
+	    *.exe|*.EXE) ;;
+	    *)
+	      lt_outputfile="$lt_outputfile.exe"
+	      lt_tool_outputfile="$lt_tool_outputfile.exe"
+	      ;;
+	  esac~
+	  if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+	    $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+	    $RM "$lt_outputfile.manifest";
+	  fi'
+	;;
+      *)
+	# Assume MSVC wrapper
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=".dll"
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+	# The linker will automatically build a .lib file if we build a DLL.
+	old_archive_from_new_cmds='true'
+	# FIXME: Should let the user specify the lib program.
+	old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+	enable_shared_with_static_runtimes=yes
+	;;
+      esac
       ;;
 
     darwin* | rhapsody*)
@@ -10208,7 +10531,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
   hardcode_direct=no
   hardcode_automatic=yes
   hardcode_shlibpath_var=unsupported
-  whole_archive_flag_spec=''
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    whole_archive_flag_spec=''
+  fi
   link_all_deplibs=yes
   allow_undefined_flag="$_lt_dar_allow_undefined"
   case $cc_basename in
@@ -10216,7 +10543,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
      *) _lt_dar_can_shared=$GCC ;;
   esac
   if test "$_lt_dar_can_shared" = "yes"; then
-    output_verbose_link_cmd=echo
+    output_verbose_link_cmd=func_echo_all
     archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
     module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
     archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
@@ -10259,7 +10586,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
     freebsd* | dragonfly*)
-      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
       hardcode_libdir_flag_spec='-R$libdir'
       hardcode_direct=yes
       hardcode_shlibpath_var=no
@@ -10267,7 +10594,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
     hpux9*)
       if test "$GCC" = yes; then
-	archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
       else
 	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
       fi
@@ -10282,8 +10609,8 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       ;;
 
     hpux10*)
-      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
-	archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
       else
 	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
       fi
@@ -10301,16 +10628,16 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       ;;
 
     hpux11*)
-      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
 	case $host_cpu in
 	hppa*64*)
 	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
-	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	*)
-	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	esac
       else
@@ -10322,7 +10649,46 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	*)
-	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if ${lt_cv_prog_compiler__b+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
 	  ;;
 	esac
       fi
@@ -10350,26 +10716,39 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
     irix5* | irix6* | nonstopux*)
       if test "$GCC" = yes; then
-	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 	# Try to use the -exported_symbol ld option, if it does not
 	# work, assume that -exports_file does not work either and
 	# implicitly export all symbols.
-        save_LDFLAGS="$LDFLAGS"
-        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+	# This should be the same for all languages, so no per-tag cache variable.
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if ${lt_cv_irix_exported_symbol+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  save_LDFLAGS="$LDFLAGS"
+	   LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-int foo(void) {}
+int foo (void) { return 0; }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
-
+  lt_cv_irix_exported_symbol=yes
+else
+  lt_cv_irix_exported_symbol=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-        LDFLAGS="$save_LDFLAGS"
+           LDFLAGS="$save_LDFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+$as_echo "$lt_cv_irix_exported_symbol" >&6; }
+	if test "$lt_cv_irix_exported_symbol" = yes; then
+          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+	fi
       else
-	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
-	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
       fi
       archive_cmds_need_lc='no'
       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
@@ -10378,7 +10757,7 @@ rm -f core conftest.err conftest.$ac_objext \
       link_all_deplibs=yes
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
@@ -10431,17 +10810,17 @@ rm -f core conftest.err conftest.$ac_objext \
       hardcode_libdir_flag_spec='-L$libdir'
       hardcode_minus_L=yes
       allow_undefined_flag=unsupported
-      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
       old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
       ;;
 
     osf3*)
       if test "$GCC" = yes; then
 	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
       else
 	allow_undefined_flag=' -expect_unresolved \*'
-	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
       fi
       archive_cmds_need_lc='no'
       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
@@ -10451,13 +10830,13 @@ rm -f core conftest.err conftest.$ac_objext \
     osf4* | osf5*)	# as osf3* with the addition of -msym flag
       if test "$GCC" = yes; then
 	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
       else
 	allow_undefined_flag=' -expect_unresolved \*'
-	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
-	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
 
 	# Both c and cxx compiler support -rpath directly
 	hardcode_libdir_flag_spec='-rpath $libdir'
@@ -10470,9 +10849,9 @@ rm -f core conftest.err conftest.$ac_objext \
       no_undefined_flag=' -z defs'
       if test "$GCC" = yes; then
 	wlarc='${wl}'
-	archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
 	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
       else
 	case `$CC -V 2>&1` in
 	*"Compilers 5.0"*)
@@ -10660,44 +11039,50 @@ x|xyes)
       # to ld, don't add -lc before -lgcc.
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
-      $RM conftest*
-      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+if ${lt_cv_archive_cmds_need_lc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
 
-      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; } 2>conftest.err; then
-        soname=conftest
-        lib=conftest
-        libobjs=conftest.$ac_objext
-        deplibs=
-        wl=$lt_prog_compiler_wl
-	pic_flag=$lt_prog_compiler_pic
-        compiler_flags=-v
-        linker_flags=-v
-        verstring=
-        output_objdir=.
-        libname=conftest
-        lt_save_allow_undefined_flag=$allow_undefined_flag
-        allow_undefined_flag=
-        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl
+	  pic_flag=$lt_prog_compiler_pic
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag
+	  allow_undefined_flag=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
   (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }
-        then
-	  archive_cmds_need_lc=no
-        else
-	  archive_cmds_need_lc=yes
-        fi
-        allow_undefined_flag=$lt_save_allow_undefined_flag
-      else
-        cat conftest.err 1>&5
-      fi
-      $RM conftest*
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5
-$as_echo "$archive_cmds_need_lc" >&6; }
+	  then
+	    lt_cv_archive_cmds_need_lc=no
+	  else
+	    lt_cv_archive_cmds_need_lc=yes
+	  fi
+	  allow_undefined_flag=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
       ;;
     esac
   fi
@@ -10868,16 +11253,23 @@ if test "$GCC" = yes; then
     darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
     *) lt_awk_arg="/^libraries:/" ;;
   esac
-  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
-  if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
     # if the path contains ";" then we assume it to be the separator
     # otherwise default to the standard path separator (i.e. ":") - it is
     # assumed that no part of a normal pathname contains ";" but that should
     # okay in the real world where ";" in dirpaths is itself problematic.
-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
-  else
-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
-  fi
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
   # Ok, now we have the path, separated by spaces, we can step through it
   # and add multilib dir if necessary.
   lt_tmp_lt_search_path_spec=
@@ -10890,7 +11282,7 @@ if test "$GCC" = yes; then
 	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
     fi
   done
-  lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
 BEGIN {RS=" "; FS="/|\n";} {
   lt_foo="";
   lt_count=0;
@@ -10910,7 +11302,13 @@ BEGIN {RS=" "; FS="/|\n";} {
   if (lt_foo != "") { lt_freq[lt_foo]++; }
   if (lt_freq[lt_foo] == 1) { print lt_foo; }
 }'`
-  sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
 else
   sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
 fi
@@ -10998,7 +11396,7 @@ amigaos*)
   m68k)
     library_names_spec='$libname.ixlibrary $libname.a'
     # Create ${libname}_ixlibrary.a entries in /sys/libs.
-    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
     ;;
   esac
   ;;
@@ -11029,8 +11427,9 @@ cygwin* | mingw* | pw32* | cegcc*)
   need_version=no
   need_lib_prefix=no
 
-  case $GCC,$host_os in
-  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
     library_names_spec='$libname.dll.a'
     # DLL is installed to $(libdir)/../bin by postinstall_cmds
     postinstall_cmds='base_file=`basename \${file}`~
@@ -11051,36 +11450,83 @@ cygwin* | mingw* | pw32* | cegcc*)
     cygwin*)
       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
       soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
       ;;
     mingw* | cegcc*)
       # MinGW DLLs use traditional 'lib' prefix
       soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
-      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
-        # It is most probably a Windows format PATH printed by
-        # mingw gcc, but we are running on Cygwin. Gcc prints its search
-        # path with ; separators, and with drive letters. We can handle the
-        # drive letters (cygwin fileutils understands them), so leave them,
-        # especially as we might pass files found there to a mingw objdump,
-        # which wouldn't understand a cygwinified path. Ahh.
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
-      else
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
-      fi
       ;;
     pw32*)
       # pw32 DLLs use 'pw' prefix rather than 'lib'
       library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
       ;;
     esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
     ;;
 
   *)
+    # Assume MSVC wrapper
     library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
     ;;
   esac
-  dynamic_linker='Win32 ld.exe'
   # FIXME: first we should search . and the directory the executable is in
   shlibpath_var=PATH
   ;;
@@ -11167,6 +11613,19 @@ gnu*)
   hardcode_into_libs=yes
   ;;
 
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
 hpux9* | hpux10* | hpux11*)
   # Give a soname corresponding to the major version so that dld.sl refuses to
   # link against other versions.
@@ -11209,8 +11668,10 @@ hpux9* | hpux10* | hpux11*)
     soname_spec='${libname}${release}${shared_ext}$major'
     ;;
   esac
-  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
   postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
   ;;
 
 interix[3-9]*)
@@ -11268,7 +11729,7 @@ linux*oldld* | linux*aout* | linux*coff*)
   ;;
 
 # This must be Linux ELF.
-linux* | k*bsd*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
   version_type=linux
   need_lib_prefix=no
   need_version=no
@@ -11277,12 +11738,17 @@ linux* | k*bsd*-gnu)
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
   shlibpath_var=LD_LIBRARY_PATH
   shlibpath_overrides_runpath=no
+
   # Some binutils ld are patched to set DT_RUNPATH
-  save_LDFLAGS=$LDFLAGS
-  save_libdir=$libdir
-  eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
-       LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -11295,13 +11761,17 @@ main ()
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
   if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
-  shlibpath_overrides_runpath=yes
+  lt_cv_shlibpath_overrides_runpath=yes
 fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-  LDFLAGS=$save_LDFLAGS
-  libdir=$save_libdir
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
 
   # This implies no fast_install, which is unacceptable.
   # Some rework will be needed to allow for fast_install
@@ -11310,7 +11780,7 @@ rm -f core conftest.err conftest.$ac_objext \
 
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
     sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
@@ -11323,18 +11793,6 @@ rm -f core conftest.err conftest.$ac_objext \
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -11625,6 +12083,11 @@ fi
 
 
 
+
+
+
+
+
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
 $as_echo_n "checking how to hardcode library paths into programs... " >&6; }
 hardcode_action=
@@ -11697,7 +12160,7 @@ else
   # if libdl is installed we need to link against it
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
 $as_echo_n "checking for dlopen in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+if ${ac_cv_lib_dl_dlopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -11731,7 +12194,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
 $as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
   lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
 else
 
@@ -11745,12 +12208,12 @@ fi
 
   *)
     ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
-if test "x$ac_cv_func_shl_load" = x""yes; then :
+if test "x$ac_cv_func_shl_load" = xyes; then :
   lt_cv_dlopen="shl_load"
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
 $as_echo_n "checking for shl_load in -ldld... " >&6; }
-if test "${ac_cv_lib_dld_shl_load+set}" = set; then :
+if ${ac_cv_lib_dld_shl_load+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -11784,16 +12247,16 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
 $as_echo "$ac_cv_lib_dld_shl_load" >&6; }
-if test "x$ac_cv_lib_dld_shl_load" = x""yes; then :
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
   lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
 else
   ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
-if test "x$ac_cv_func_dlopen" = x""yes; then :
+if test "x$ac_cv_func_dlopen" = xyes; then :
   lt_cv_dlopen="dlopen"
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
 $as_echo_n "checking for dlopen in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+if ${ac_cv_lib_dl_dlopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -11827,12 +12290,12 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
 $as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
   lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
 $as_echo_n "checking for dlopen in -lsvld... " >&6; }
-if test "${ac_cv_lib_svld_dlopen+set}" = set; then :
+if ${ac_cv_lib_svld_dlopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -11866,12 +12329,12 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
 $as_echo "$ac_cv_lib_svld_dlopen" >&6; }
-if test "x$ac_cv_lib_svld_dlopen" = x""yes; then :
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
   lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
 $as_echo_n "checking for dld_link in -ldld... " >&6; }
-if test "${ac_cv_lib_dld_dld_link+set}" = set; then :
+if ${ac_cv_lib_dld_dld_link+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -11905,7 +12368,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
 $as_echo "$ac_cv_lib_dld_dld_link" >&6; }
-if test "x$ac_cv_lib_dld_dld_link" = x""yes; then :
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
   lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
 fi
 
@@ -11946,7 +12409,7 @@ fi
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
 $as_echo_n "checking whether a program can dlopen itself... " >&6; }
-if test "${lt_cv_dlopen_self+set}" = set; then :
+if ${lt_cv_dlopen_self+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   	  if test "$cross_compiling" = yes; then :
@@ -11955,7 +12418,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11958 "configure"
+#line $LINENO "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11996,7 +12459,13 @@ else
 #  endif
 #endif
 
-void fnord() { int i=42;}
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
 int main ()
 {
   void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
@@ -12005,7 +12474,11 @@ int main ()
   if (self)
     {
       if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
-      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
       /* dlclose (self); */
     }
   else
@@ -12042,7 +12515,7 @@ $as_echo "$lt_cv_dlopen_self" >&6; }
       wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
-if test "${lt_cv_dlopen_self_static+set}" = set; then :
+if ${lt_cv_dlopen_self_static+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   	  if test "$cross_compiling" = yes; then :
@@ -12051,7 +12524,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12054 "configure"
+#line $LINENO "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12092,7 +12565,13 @@ else
 #  endif
 #endif
 
-void fnord() { int i=42;}
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
 int main ()
 {
   void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
@@ -12101,7 +12580,11 @@ int main ()
   if (self)
     {
       if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
-      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
       /* dlclose (self); */
     }
   else
@@ -12258,23 +12741,162 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 CC="$lt_save_CC"
 
-
-ac_ext=cpp
+      if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
-archive_cmds_need_lc_CXX=no
-allow_undefined_flag_CXX=
-always_export_symbols_CXX=no
-archive_expsym_cmds_CXX=
-compiler_needs_object_CXX=no
-export_dynamic_flag_spec_CXX=
-hardcode_direct_CXX=no
-hardcode_direct_absolute_CXX=no
-hardcode_libdir_flag_spec_CXX=
-hardcode_libdir_flag_spec_ld_CXX=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if ${ac_cv_prog_CXXCPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+else
+  _lt_caught_CXX_error=yes
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+compiler_needs_object_CXX=no
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_direct_absolute_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
 hardcode_libdir_separator_CXX=
 hardcode_minus_L_CXX=no
 hardcode_shlibpath_var_CXX=unsupported
@@ -12284,6 +12906,8 @@ module_cmds_CXX=
 module_expsym_cmds_CXX=
 link_all_deplibs_CXX=unknown
 old_archive_cmds_CXX=$old_archive_cmds
+reload_flag_CXX=$reload_flag
+reload_cmds_CXX=$reload_cmds
 no_undefined_flag_CXX=
 whole_archive_flag_spec_CXX=
 enable_shared_with_static_runtimes_CXX=no
@@ -12339,6 +12963,7 @@ $RM -r conftest*
 
   # Allow CC to be a program name with arguments.
   lt_save_CC=$CC
+  lt_save_CFLAGS=$CFLAGS
   lt_save_LD=$LD
   lt_save_GCC=$GCC
   GCC=$GXX
@@ -12356,6 +12981,7 @@ $RM -r conftest*
   fi
   test -z "${LDCXX+set}" || LD=$LDCXX
   CC=${CXX-"c++"}
+  CFLAGS=$CXXFLAGS
   compiler=$CC
   compiler_CXX=$CC
   for cc_temp in $compiler""; do
@@ -12366,7 +12992,7 @@ $RM -r conftest*
     *) break;;
   esac
 done
-cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
 
 
   if test -n "$compiler"; then
@@ -12429,7 +13055,7 @@ else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
 $as_echo_n "checking for non-GNU ld... " >&6; }
 fi
-if test "${lt_cv_path_LD+set}" = set; then :
+if ${lt_cv_path_LD+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -z "$LD"; then
@@ -12469,7 +13095,7 @@ fi
 test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
-if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+if ${lt_cv_prog_gnu_ld+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   # I'd rather use --version here, but apparently some GNU lds only accept -v.
@@ -12495,8 +13121,8 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
       # Check if GNU C++ uses GNU ld as the underlying linker, since the
       # archiving commands below assume that GNU ld is being used.
       if test "$with_gnu_ld" = yes; then
-        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
-        archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+        archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
 
         hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
         export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
@@ -12528,7 +13154,7 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
       # Commands to make compiler produce verbose output that lists
       # what "hidden" libraries, object files and flags are used when
       # linking a shared library.
-      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 
     else
       GXX=no
@@ -12638,7 +13264,13 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
           allow_undefined_flag_CXX='-berok'
           # Determine the default libpath from the value encoded in an empty
           # executable.
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+          if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath__CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -12651,26 +13283,33 @@ main ()
 _ACEOF
 if ac_fn_cxx_try_link "$LINENO"; then :
 
-lt_aix_libpath_sed='
-    /Import File Strings/,/^$/ {
-	/^0/ {
-	    s/^0  *\(.*\)$/\1/
-	    p
-	}
-    }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
-  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath__CXX
+fi
 
           hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
 
-          archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+          archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
         else
           if test "$host_cpu" = ia64; then
 	    hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
@@ -12679,7 +13318,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
           else
 	    # Determine the default libpath from the value encoded in an
 	    # empty executable.
-	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+	    if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath__CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -12692,30 +13337,42 @@ main ()
 _ACEOF
 if ac_fn_cxx_try_link "$LINENO"; then :
 
-lt_aix_libpath_sed='
-    /Import File Strings/,/^$/ {
-	/^0/ {
-	    s/^0  *\(.*\)$/\1/
-	    p
-	}
-    }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
-  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+  if test -z "$lt_cv_aix_libpath__CXX"; then
+    lt_cv_aix_libpath__CXX="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath__CXX
+fi
 
 	    hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
 	    # Warning - without using the other run time loading flags,
 	    # -berok will link without error, but may produce a broken library.
 	    no_undefined_flag_CXX=' ${wl}-bernotok'
 	    allow_undefined_flag_CXX=' ${wl}-berok'
-	    # Exported symbols can be pulled into shared objects from archives
-	    whole_archive_flag_spec_CXX='$convenience'
+	    if test "$with_gnu_ld" = yes; then
+	      # We only use this code for GNU lds that support --whole-archive.
+	      whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    else
+	      # Exported symbols can be pulled into shared objects from archives
+	      whole_archive_flag_spec_CXX='$convenience'
+	    fi
 	    archive_cmds_need_lc_CXX=yes
 	    # This is similar to how AIX traditionally builds its shared
 	    # libraries.
@@ -12745,28 +13402,75 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
         ;;
 
       cygwin* | mingw* | pw32* | cegcc*)
-        # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
-        # as there is no search path for DLLs.
-        hardcode_libdir_flag_spec_CXX='-L$libdir'
-        allow_undefined_flag_CXX=unsupported
-        always_export_symbols_CXX=no
-        enable_shared_with_static_runtimes_CXX=yes
-
-        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
-          archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-          # If the export-symbols file already is a .def file (1st line
-          # is EXPORTS), use it as is; otherwise, prepend...
-          archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
-	    cp $export_symbols $output_objdir/$soname.def;
-          else
-	    echo EXPORTS > $output_objdir/$soname.def;
-	    cat $export_symbols >> $output_objdir/$soname.def;
-          fi~
-          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-        else
-          ld_shlibs_CXX=no
-        fi
-        ;;
+	case $GXX,$cc_basename in
+	,cl* | no,cl*)
+	  # Native MSVC
+	  # hardcode_libdir_flag_spec is actually meaningless, as there is
+	  # no search path for DLLs.
+	  hardcode_libdir_flag_spec_CXX=' '
+	  allow_undefined_flag_CXX=unsupported
+	  always_export_symbols_CXX=yes
+	  file_list_spec_CXX='@'
+	  # Tell ltmain to make .lib files, not .a files.
+	  libext=lib
+	  # Tell ltmain to make .dll files, not .so files.
+	  shrext_cmds=".dll"
+	  # FIXME: Setting linknames here is a bad hack.
+	  archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+	  archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	      $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+	    else
+	      $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+	    fi~
+	    $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+	    linknames='
+	  # The linker will not automatically build a static lib if we build a DLL.
+	  # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true'
+	  enable_shared_with_static_runtimes_CXX=yes
+	  # Don't use ranlib
+	  old_postinstall_cmds_CXX='chmod 644 $oldlib'
+	  postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~
+	    lt_tool_outputfile="@TOOL_OUTPUT@"~
+	    case $lt_outputfile in
+	      *.exe|*.EXE) ;;
+	      *)
+		lt_outputfile="$lt_outputfile.exe"
+		lt_tool_outputfile="$lt_tool_outputfile.exe"
+		;;
+	    esac~
+	    func_to_tool_file "$lt_outputfile"~
+	    if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+	      $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+	      $RM "$lt_outputfile.manifest";
+	    fi'
+	  ;;
+	*)
+	  # g++
+	  # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+	  # as there is no search path for DLLs.
+	  hardcode_libdir_flag_spec_CXX='-L$libdir'
+	  export_dynamic_flag_spec_CXX='${wl}--export-all-symbols'
+	  allow_undefined_flag_CXX=unsupported
+	  always_export_symbols_CXX=no
+	  enable_shared_with_static_runtimes_CXX=yes
+
+	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+	    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	    # If the export-symbols file already is a .def file (1st line
+	    # is EXPORTS), use it as is; otherwise, prepend...
+	    archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	      cp $export_symbols $output_objdir/$soname.def;
+	    else
+	      echo EXPORTS > $output_objdir/$soname.def;
+	      cat $export_symbols >> $output_objdir/$soname.def;
+	    fi~
+	    $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	  else
+	    ld_shlibs_CXX=no
+	  fi
+	  ;;
+	esac
+	;;
       darwin* | rhapsody*)
 
 
@@ -12774,7 +13478,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
   hardcode_direct_CXX=no
   hardcode_automatic_CXX=yes
   hardcode_shlibpath_var_CXX=unsupported
-  whole_archive_flag_spec_CXX=''
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    whole_archive_flag_spec_CXX=''
+  fi
   link_all_deplibs_CXX=yes
   allow_undefined_flag_CXX="$_lt_dar_allow_undefined"
   case $cc_basename in
@@ -12782,7 +13490,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
      *) _lt_dar_can_shared=$GCC ;;
   esac
   if test "$_lt_dar_can_shared" = "yes"; then
-    output_verbose_link_cmd=echo
+    output_verbose_link_cmd=func_echo_all
     archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
     module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
     archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
@@ -12835,6 +13543,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       gnu*)
         ;;
 
+      haiku*)
+        archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        link_all_deplibs_CXX=yes
+        ;;
+
       hpux9*)
         hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
         hardcode_libdir_separator_CXX=:
@@ -12859,11 +13572,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
             # explicitly linking system object files so we need to strip them
             # from the output so that they don't get included in the library
             # dependencies.
-            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
             ;;
           *)
             if test "$GXX" = yes; then
-              archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+              archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
             else
               # FIXME: insert proper C++ library support
               ld_shlibs_CXX=no
@@ -12924,7 +13637,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
 	    ;;
           *)
 	    if test "$GXX" = yes; then
@@ -12934,10 +13647,10 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	            ;;
 	          ia64*)
-	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	            ;;
 	          *)
-	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	            ;;
 	        esac
 	      fi
@@ -12967,7 +13680,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
         case $cc_basename in
           CC*)
 	    # SGI C++
-	    archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	    archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 
 	    # Archives containing C++ object files must be created using
 	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
@@ -12978,9 +13691,9 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
           *)
 	    if test "$GXX" = yes; then
 	      if test "$with_gnu_ld" = no; then
-	        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 	      else
-	        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
 	      fi
 	    fi
 	    link_all_deplibs_CXX=yes
@@ -12991,7 +13704,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
         inherit_rpath_CXX=yes
         ;;
 
-      linux* | k*bsd*-gnu)
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
         case $cc_basename in
           KCC*)
 	    # Kuck and Associates, Inc. (KAI) C++ Compiler
@@ -13009,7 +13722,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
 
 	    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
 	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
@@ -13046,26 +13759,26 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
           pgCC* | pgcpp*)
             # Portland Group C++ compiler
 	    case `$CC -V` in
-	    *pgCC\ [1-5]* | *pgcpp\ [1-5]*)
+	    *pgCC\ [1-5].* | *pgcpp\ [1-5].*)
 	      prelink_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
-		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+		compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
 	      old_archive_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
-		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
 		$RANLIB $oldlib'
 	      archive_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
-		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
 	      archive_expsym_cmds_CXX='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
-		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 	      ;;
-	    *) # Version 6 will use weak symbols
+	    *) # Version 6 and above use weak symbols
 	      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
 	      archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 	      ;;
@@ -13073,7 +13786,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
 	    hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
 	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
-	    whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	    whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
             ;;
 	  cxx*)
 	    # Compaq C++
@@ -13092,9 +13805,9 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
 	    ;;
-	  xl*)
+	  xl* | mpixl* | bgxl*)
 	    # IBM XL 8.0 on PPC, with GNU ld
 	    hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
 	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
@@ -13114,13 +13827,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	      archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	      archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
 	      hardcode_libdir_flag_spec_CXX='-R$libdir'
-	      whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	      whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	      compiler_needs_object_CXX=yes
 
 	      # Not sure whether something based on
 	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
 	      # would be better.
-	      output_verbose_link_cmd='echo'
+	      output_verbose_link_cmd='func_echo_all'
 
 	      # Archives containing C++ object files must be created using
 	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
@@ -13189,7 +13902,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    export_dynamic_flag_spec_CXX='${wl}-E'
 	    whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
 	  fi
-	  output_verbose_link_cmd=echo
+	  output_verbose_link_cmd=func_echo_all
 	else
 	  ld_shlibs_CXX=no
 	fi
@@ -13224,15 +13937,15 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    case $host in
 	      osf3*)
 	        allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
-	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 	        hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
 		;;
 	      *)
 	        allow_undefined_flag_CXX=' -expect_unresolved \*'
-	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 	        archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
 	          echo "-hidden">> $lib.exp~
-	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
 	          $RM $lib.exp'
 	        hardcode_libdir_flag_spec_CXX='-rpath $libdir'
 		;;
@@ -13248,17 +13961,17 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
 	    ;;
 	  *)
 	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
 	      allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
 	      case $host in
 	        osf3*)
-	          archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	          archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 		  ;;
 	        *)
-	          archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	          archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 		  ;;
 	      esac
 
@@ -13268,7 +13981,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	      # Commands to make compiler produce verbose output that lists
 	      # what "hidden" libraries, object files and flags are used when
 	      # linking a shared library.
-	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 
 	    else
 	      # FIXME: insert proper C++ library support
@@ -13304,7 +14017,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
       solaris*)
         case $cc_basename in
-          CC*)
+          CC* | sunCC*)
 	    # Sun C++ 4.2, 5.x and Centerline C++
             archive_cmds_need_lc_CXX=yes
 	    no_undefined_flag_CXX=' -zdefs'
@@ -13325,7 +14038,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    esac
 	    link_all_deplibs_CXX=yes
 
-	    output_verbose_link_cmd='echo'
+	    output_verbose_link_cmd='func_echo_all'
 
 	    # Archives containing C++ object files must be created using
 	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
@@ -13345,14 +14058,14 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
 	      no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
 	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
-	        archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
 	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+		  $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
 
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
 	        # linking a shared library.
-	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 	      else
 	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
 	        # platform.
@@ -13363,7 +14076,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
 	        # linking a shared library.
-	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 	      fi
 
 	      hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
@@ -13417,6 +14130,10 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
           CC*)
 	    archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
 	    archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~
+	      '"$old_archive_cmds_CXX"
+	    reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~
+	      '"$reload_cmds_CXX"
 	    ;;
 	  *)
 	    archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
@@ -13478,6 +14195,13 @@ private:
 };
 _LT_EOF
 
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+esac
+
 if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -13491,7 +14215,7 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   pre_test_object_deps_done=no
 
   for p in `eval "$output_verbose_link_cmd"`; do
-    case $p in
+    case ${prev}${p} in
 
     -L* | -R* | -l*)
        # Some compilers place space between "-{L,R}" and the path.
@@ -13500,13 +14224,22 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
           test $p = "-R"; then
 	 prev=$p
 	 continue
-       else
-	 prev=
        fi
 
+       # Expand the sysroot to ease extracting the directories later.
+       if test -z "$prev"; then
+         case $p in
+         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+         esac
+       fi
+       case $p in
+       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+       esac
        if test "$pre_test_object_deps_done" = no; then
-	 case $p in
-	 -L* | -R*)
+	 case ${prev} in
+	 -L | -R)
 	   # Internal compiler library paths should come after those
 	   # provided the user.  The postdeps already come after the
 	   # user supplied libs so there is no need to process them.
@@ -13526,8 +14259,10 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
 	   postdeps_CXX="${postdeps_CXX} ${prev}${p}"
 	 fi
        fi
+       prev=
        ;;
 
+    *.lto.$objext) ;; # Ignore GCC LTO objects
     *.$objext)
        # This assumes that the test object file only shows up
        # once in the compiler output.
@@ -13563,6 +14298,7 @@ else
 fi
 
 $RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
 
 # PORTME: override above test on systems where it is broken
 case $host_os in
@@ -13598,7 +14334,7 @@ linux*)
 
 solaris*)
   case $cc_basename in
-  CC*)
+  CC* | sunCC*)
     # The more standards-conforming stlport4 library is
     # incompatible with the Cstd library. Avoid specifying
     # it if it's in CXXFLAGS. Ignore libCrun as
@@ -13663,8 +14399,6 @@ fi
 lt_prog_compiler_pic_CXX=
 lt_prog_compiler_static_CXX=
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
-$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 
   # C++ specific cases for pic, static, wl, etc.
   if test "$GXX" = yes; then
@@ -13714,6 +14448,11 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
       # DJGPP does not support shared libraries at all
       lt_prog_compiler_pic_CXX=
       ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static_CXX=
+      ;;
     interix[3-9]*)
       # Interix 3.x gcc -fpic/-fPIC options generate broken code.
       # Instead, we relocate shared libraries at runtime.
@@ -13763,6 +14502,11 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 	  ;;
 	esac
 	;;
+      mingw* | cygwin* | os2* | pw32* | cegcc*)
+	# This hack is so that the source file can tell whether it is being
+	# built for inclusion in a dll (and should export symbols for example).
+	lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+	;;
       dgux*)
 	case $cc_basename in
 	  ec++*)
@@ -13819,7 +14563,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 	    ;;
 	esac
 	;;
-      linux* | k*bsd*-gnu)
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
 	case $cc_basename in
 	  KCC*)
 	    # KAI C++ Compiler
@@ -13852,8 +14596,8 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 	    lt_prog_compiler_pic_CXX=
 	    lt_prog_compiler_static_CXX='-non_shared'
 	    ;;
-	  xlc* | xlC*)
-	    # IBM XL 8.0 on PPC
+	  xlc* | xlC* | bgxl[cC]* | mpixl[cC]*)
+	    # IBM XL 8.0, 9.0 on PPC and BlueGene
 	    lt_prog_compiler_wl_CXX='-Wl,'
 	    lt_prog_compiler_pic_CXX='-qpic'
 	    lt_prog_compiler_static_CXX='-qstaticlink'
@@ -13883,7 +14627,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 	    ;;
 	esac
 	;;
-      netbsd* | netbsdelf*-gnu)
+      netbsd*)
 	;;
       *qnx* | *nto*)
         # QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -13915,7 +14659,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
 	;;
       solaris*)
 	case $cc_basename in
-	  CC*)
+	  CC* | sunCC*)
 	    # Sun C++ 4.2, 5.x and Centerline C++
 	    lt_prog_compiler_pic_CXX='-KPIC'
 	    lt_prog_compiler_static_CXX='-Bstatic'
@@ -13980,10 +14724,17 @@ case $host_os in
     lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
     ;;
 esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5
-$as_echo "$lt_prog_compiler_pic_CXX" >&6; }
-
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; }
+lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX
 
 #
 # Check to make sure the PIC flag actually works.
@@ -13991,7 +14742,7 @@ $as_echo "$lt_prog_compiler_pic_CXX" >&6; }
 if test -n "$lt_prog_compiler_pic_CXX"; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
-if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then :
+if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_pic_works_CXX=no
@@ -14007,15 +14758,15 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14010: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14014: \$? = $ac_status" >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_pic_works_CXX=yes
@@ -14041,13 +14792,15 @@ fi
 
 
 
+
+
 #
 # Check to make sure the static flag actually works.
 #
 wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
-if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then :
+if ${lt_cv_prog_compiler_static_works_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_static_works_CXX=no
@@ -14060,7 +14813,7 @@ else
      if test -s conftest.err; then
        # Append any errors to the config.log.
        cat conftest.err 1>&5
-       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
        if diff conftest.exp conftest.er2 >/dev/null; then
          lt_cv_prog_compiler_static_works_CXX=yes
@@ -14087,7 +14840,7 @@ fi
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then :
+if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_c_o_CXX=no
@@ -14106,16 +14859,16 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14109: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14113: \$? = $ac_status" >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o_CXX=yes
@@ -14139,7 +14892,7 @@ $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then :
+if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   lt_cv_prog_compiler_c_o_CXX=no
@@ -14158,16 +14911,16 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14161: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14165: \$? = $ac_status" >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        lt_cv_prog_compiler_c_o_CXX=yes
@@ -14218,30 +14971,35 @@ fi
 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
 
   export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
   case $host_os in
   aix[4-9]*)
     # If we're using GNU nm, then we don't want the "-C" option.
     # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    # Also, AIX nm treats weak defined symbols like other global defined
+    # symbols, whereas GNU nm marks them as "W".
     if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
-      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
     else
       export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
     fi
     ;;
   pw32*)
     export_symbols_cmds_CXX="$ltdll_cmds"
-  ;;
+    ;;
   cygwin* | mingw* | cegcc*)
-    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
-  ;;
-  linux* | k*bsd*-gnu)
-    link_all_deplibs_CXX=no
-  ;;
+    case $cc_basename in
+    cl*) ;;
+    *)
+      export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+      ;;
+    esac
+    ;;
   *)
     export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
-  ;;
+    ;;
   esac
-  exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
 $as_echo "$ld_shlibs_CXX" >&6; }
@@ -14273,44 +15031,50 @@ x|xyes)
       # to ld, don't add -lc before -lgcc.
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
-      $RM conftest*
-      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
 
-      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; } 2>conftest.err; then
-        soname=conftest
-        lib=conftest
-        libobjs=conftest.$ac_objext
-        deplibs=
-        wl=$lt_prog_compiler_wl_CXX
-	pic_flag=$lt_prog_compiler_pic_CXX
-        compiler_flags=-v
-        linker_flags=-v
-        verstring=
-        output_objdir=.
-        libname=conftest
-        lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
-        allow_undefined_flag_CXX=
-        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl_CXX
+	  pic_flag=$lt_prog_compiler_pic_CXX
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+	  allow_undefined_flag_CXX=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
   (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }
-        then
-	  archive_cmds_need_lc_CXX=no
-        else
-	  archive_cmds_need_lc_CXX=yes
-        fi
-        allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
-      else
-        cat conftest.err 1>&5
-      fi
-      $RM conftest*
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_CXX" >&5
-$as_echo "$archive_cmds_need_lc_CXX" >&6; }
+	  then
+	    lt_cv_archive_cmds_need_lc_CXX=no
+	  else
+	    lt_cv_archive_cmds_need_lc_CXX=yes
+	  fi
+	  allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
+      archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
       ;;
     esac
   fi
@@ -14467,7 +15231,7 @@ amigaos*)
   m68k)
     library_names_spec='$libname.ixlibrary $libname.a'
     # Create ${libname}_ixlibrary.a entries in /sys/libs.
-    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
     ;;
   esac
   ;;
@@ -14498,8 +15262,9 @@ cygwin* | mingw* | pw32* | cegcc*)
   need_version=no
   need_lib_prefix=no
 
-  case $GCC,$host_os in
-  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
     library_names_spec='$libname.dll.a'
     # DLL is installed to $(libdir)/../bin by postinstall_cmds
     postinstall_cmds='base_file=`basename \${file}`~
@@ -14520,38 +15285,84 @@ cygwin* | mingw* | pw32* | cegcc*)
     cygwin*)
       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
       soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+
       ;;
     mingw* | cegcc*)
       # MinGW DLLs use traditional 'lib' prefix
       soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
-      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
-        # It is most probably a Windows format PATH printed by
-        # mingw gcc, but we are running on Cygwin. Gcc prints its search
-        # path with ; separators, and with drive letters. We can handle the
-        # drive letters (cygwin fileutils understands them), so leave them,
-        # especially as we might pass files found there to a mingw objdump,
-        # which wouldn't understand a cygwinified path. Ahh.
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
-      else
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
-      fi
       ;;
     pw32*)
       # pw32 DLLs use 'pw' prefix rather than 'lib'
       library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
       ;;
     esac
+    dynamic_linker='Win32 ld.exe'
     ;;
 
-  *)
-    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
-    ;;
-  esac
-  dynamic_linker='Win32 ld.exe'
-  # FIXME: first we should search . and the directory the executable is in
-  shlibpath_var=PATH
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
   ;;
 
 darwin* | rhapsody*)
@@ -14635,6 +15446,19 @@ gnu*)
   hardcode_into_libs=yes
   ;;
 
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
 hpux9* | hpux10* | hpux11*)
   # Give a soname corresponding to the major version so that dld.sl refuses to
   # link against other versions.
@@ -14677,8 +15501,10 @@ hpux9* | hpux10* | hpux11*)
     soname_spec='${libname}${release}${shared_ext}$major'
     ;;
   esac
-  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
   postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
   ;;
 
 interix[3-9]*)
@@ -14736,7 +15562,7 @@ linux*oldld* | linux*aout* | linux*coff*)
   ;;
 
 # This must be Linux ELF.
-linux* | k*bsd*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
   version_type=linux
   need_lib_prefix=no
   need_version=no
@@ -14745,12 +15571,17 @@ linux* | k*bsd*-gnu)
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
   shlibpath_var=LD_LIBRARY_PATH
   shlibpath_overrides_runpath=no
+
   # Some binutils ld are patched to set DT_RUNPATH
-  save_LDFLAGS=$LDFLAGS
-  save_libdir=$libdir
-  eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
-       LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -14763,13 +15594,17 @@ main ()
 _ACEOF
 if ac_fn_cxx_try_link "$LINENO"; then :
   if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
-  shlibpath_overrides_runpath=yes
+  lt_cv_shlibpath_overrides_runpath=yes
 fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-  LDFLAGS=$save_LDFLAGS
-  libdir=$save_libdir
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
 
   # This implies no fast_install, which is unacceptable.
   # Some rework will be needed to allow for fast_install
@@ -14778,7 +15613,7 @@ rm -f core conftest.err conftest.$ac_objext \
 
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
     sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
@@ -14791,18 +15626,6 @@ rm -f core conftest.err conftest.$ac_objext \
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -15042,6 +15865,8 @@ fi
 
 
 
+
+
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
 $as_echo_n "checking how to hardcode library paths into programs... " >&6; }
 hardcode_action_CXX=
@@ -15089,6 +15914,7 @@ fi
   fi # test -n "$compiler"
 
   CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
   LDCXX=$LD
   LD=$lt_save_LD
   GCC=$lt_save_GCC
@@ -15139,7 +15965,7 @@ if test -n "$ac_tool_prefix"; then
 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_RANLIB+set}" = set; then :
+if ${ac_cv_prog_RANLIB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$RANLIB"; then
@@ -15179,7 +16005,7 @@ if test -z "$ac_cv_prog_RANLIB"; then
 set dummy ranlib; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_RANLIB"; then
@@ -15231,7 +16057,8 @@ fi
 	if test -z "`${CC-cc} $CFLAGS -fPIC -c conftest.c 2>&1`"; then
 	  CFLAGS="$CFLAGS -fPIC"
 	fi
-	if test -z "`${CXX-g++} $CXXFLAGS -fPIC -c conftest.c 2>&1`"; then
+	echo 'void f(){}' > conftest.cpp
+	if test -z "`${CXX-g++} $CXXFLAGS -fPIC -c conftest.cpp 2>&1`"; then
 	  CXXFLAGS="$CXXFLAGS -fPIC"
 	fi
 	rm -f conftest*
@@ -15385,7 +16212,7 @@ HAVE_LIBTOOL=$with_libtool
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
 $as_echo_n "checking for dlopen in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+if ${ac_cv_lib_dl_dlopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -15419,7 +16246,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
 $as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBDL 1
 _ACEOF
@@ -15431,7 +16258,7 @@ fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanosleep in -lrt" >&5
 $as_echo_n "checking for nanosleep in -lrt... " >&6; }
-if test "${ac_cv_lib_rt_nanosleep+set}" = set; then :
+if ${ac_cv_lib_rt_nanosleep+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -15465,7 +16292,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_nanosleep" >&5
 $as_echo "$ac_cv_lib_rt_nanosleep" >&6; }
-if test "x$ac_cv_lib_rt_nanosleep" = x""yes; then :
+if test "x$ac_cv_lib_rt_nanosleep" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBRT 1
 _ACEOF
@@ -15481,7 +16308,7 @@ case "${host_os}" in
     *)
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
 $as_echo_n "checking for sin in -lm... " >&6; }
-if test "${ac_cv_lib_m_sin+set}" = set; then :
+if ${ac_cv_lib_m_sin+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -15515,7 +16342,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5
 $as_echo "$ac_cv_lib_m_sin" >&6; }
-if test "x$ac_cv_lib_m_sin" = x""yes; then :
+if test "x$ac_cv_lib_m_sin" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBM 1
 _ACEOF
@@ -15529,7 +16356,7 @@ esac
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
 $as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then :
+if ${ac_cv_header_stdc+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -15655,7 +16482,7 @@ done
 
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
 $as_echo_n "checking whether byte ordering is bigendian... " >&6; }
-if test "${ac_cv_c_bigendian+set}" = set; then :
+if ${ac_cv_c_bigendian+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_c_bigendian=unknown
@@ -15906,6 +16733,22 @@ fi
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64bit file io" >&5
 $as_echo_n "checking for 64bit file io... " >&6; }
 
+    case "${host_os}" in
+    *mingw*)
+        with_unix_stdio_64=no
+
+cat >>confdefs.h <<_ACEOF
+#define VSI_STAT64 _stat64
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VSI_STAT64_T __stat64
+_ACEOF
+
+        ;;
+  esac
+
   if test x"$with_unix_stdio_64" = x"yes" ; then
     VSI_FTELL64=ftell64
     VSI_FSEEK64=fseek64
@@ -15978,19 +16821,26 @@ $as_echo "#define VSI_NEED_LARGEFILE64_SOURCE 1" >>confdefs.h
 $as_echo "yes" >&6; }
 
     ac_fn_c_check_func "$LINENO" "stat64" "ac_cv_func_stat64"
-if test "x$ac_cv_func_stat64" = x""yes; then :
+if test "x$ac_cv_func_stat64" = xyes; then :
   VSI_STAT64=stat64 VSI_STAT64_T=stat64
 else
   VSI_STAT64=stat VSI_STAT64_T=stat
 fi
 
     ac_fn_c_check_func "$LINENO" "fopen64" "ac_cv_func_fopen64"
-if test "x$ac_cv_func_fopen64" = x""yes; then :
+if test "x$ac_cv_func_fopen64" = xyes; then :
   VSI_FOPEN64=fopen64
 else
   VSI_FOPEN64=fopen
 fi
 
+    ac_fn_c_check_func "$LINENO" "ftruncate64" "ac_cv_func_ftruncate64"
+if test "x$ac_cv_func_ftruncate64" = xyes; then :
+  VSI_FTRUNCATE64=ftruncate64
+else
+  VSI_FTRUNCATE64=ftruncate
+fi
+
 
 
 $as_echo "#define UNIX_STDIO_64 1" >>confdefs.h
@@ -15999,7 +16849,7 @@ $as_echo "#define UNIX_STDIO_64 1" >>confdefs.h
 $as_echo "#define VSI_LARGE_API_SUPPORTED 1" >>confdefs.h
 
 
-    export VSI_FTELL64 VSI_FSEEK64 VSI_STAT64 VSI_STAT64_T VSI_OPEN64
+    export VSI_FTELL64 VSI_FSEEK64 VSI_STAT64 VSI_STAT64_T VSI_OPEN64 VSI_FTRUNCATE64
 
 cat >>confdefs.h <<_ACEOF
 #define VSI_FTELL64 $VSI_FTELL64
@@ -16025,6 +16875,11 @@ cat >>confdefs.h <<_ACEOF
 #define VSI_FOPEN64 $VSI_FOPEN64
 _ACEOF
 
+
+cat >>confdefs.h <<_ACEOF
+#define VSI_FTRUNCATE64 $VSI_FTRUNCATE64
+_ACEOF
+
   else
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -16038,7 +16893,7 @@ $as_echo "no" >&6; }
 # This bug is HP SR number 8606223364.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
 $as_echo_n "checking size of int... " >&6; }
-if test "${ac_cv_sizeof_int+set}" = set; then :
+if ${ac_cv_sizeof_int+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int"        "$ac_includes_default"; then :
@@ -16071,7 +16926,7 @@ _ACEOF
 # This bug is HP SR number 8606223364.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5
 $as_echo_n "checking size of unsigned long... " >&6; }
-if test "${ac_cv_sizeof_unsigned_long+set}" = set; then :
+if ${ac_cv_sizeof_unsigned_long+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long"        "$ac_includes_default"; then :
@@ -16104,7 +16959,7 @@ _ACEOF
 # This bug is HP SR number 8606223364.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void*" >&5
 $as_echo_n "checking size of void*... " >&6; }
-if test "${ac_cv_sizeof_voidp+set}" = set; then :
+if ${ac_cv_sizeof_voidp+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void*))" "ac_cv_sizeof_voidp"        "$ac_includes_default"; then :
@@ -16137,7 +16992,7 @@ ac_fn_c_check_type "$LINENO" "int8" "ac_cv_type_int8" "
 #endif
 
 "
-if test "x$ac_cv_type_int8" = x""yes; then :
+if test "x$ac_cv_type_int8" = xyes; then :
 
 cat >>confdefs.h <<_ACEOF
 #define HAVE_INT8 1
@@ -16151,7 +17006,7 @@ ac_fn_c_check_type "$LINENO" "int16" "ac_cv_type_int16" "
 #endif
 
 "
-if test "x$ac_cv_type_int16" = x""yes; then :
+if test "x$ac_cv_type_int16" = xyes; then :
 
 cat >>confdefs.h <<_ACEOF
 #define HAVE_INT16 1
@@ -16165,7 +17020,7 @@ ac_fn_c_check_type "$LINENO" "int32" "ac_cv_type_int32" "
 #endif
 
 "
-if test "x$ac_cv_type_int32" = x""yes; then :
+if test "x$ac_cv_type_int32" = xyes; then :
 
 cat >>confdefs.h <<_ACEOF
 #define HAVE_INT32 1
@@ -16205,13 +17060,13 @@ _ACEOF
 for ac_func in vprintf
 do :
   ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf"
-if test "x$ac_cv_func_vprintf" = x""yes; then :
+if test "x$ac_cv_func_vprintf" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_VPRINTF 1
 _ACEOF
 
 ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
-if test "x$ac_cv_func__doprnt" = x""yes; then :
+if test "x$ac_cv_func__doprnt" = xyes; then :
 
 $as_echo "#define HAVE_DOPRNT 1" >>confdefs.h
 
@@ -16236,7 +17091,7 @@ done
 for ac_func in atoll
 do :
   ac_fn_c_check_func "$LINENO" "atoll" "ac_cv_func_atoll"
-if test "x$ac_cv_func_atoll" = x""yes; then :
+if test "x$ac_cv_func_atoll" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_ATOLL 1
 _ACEOF
@@ -16247,7 +17102,7 @@ done
 for ac_func in strtof
 do :
   ac_fn_c_check_func "$LINENO" "strtof" "ac_cv_func_strtof"
-if test "x$ac_cv_func_strtof" = x""yes; then :
+if test "x$ac_cv_func_strtof" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_STRTOF 1
 _ACEOF
@@ -16258,7 +17113,7 @@ done
 for ac_func in getcwd
 do :
   ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd"
-if test "x$ac_cv_func_getcwd" = x""yes; then :
+if test "x$ac_cv_func_getcwd" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_GETCWD 1
 _ACEOF
@@ -16268,7 +17123,7 @@ done
 
 
 ac_fn_c_check_decl "$LINENO" "strtof" "ac_cv_have_decl_strtof" "$ac_includes_default"
-if test "x$ac_cv_have_decl_strtof" = x""yes; then :
+if test "x$ac_cv_have_decl_strtof" = xyes; then :
   ac_have_decl=1
 else
   ac_have_decl=0
@@ -16282,7 +17137,7 @@ _ACEOF
 for ac_func in readlink
 do :
   ac_fn_c_check_func "$LINENO" "readlink" "ac_cv_func_readlink"
-if test "x$ac_cv_func_readlink" = x""yes; then :
+if test "x$ac_cv_func_readlink" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_READLINK 1
 _ACEOF
@@ -16300,7 +17155,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gmtime_r" >&5
 $as_echo_n "checking for gmtime_r... " >&6; }
-if test "${ac_cv_func_gmtime_r+set}" = set; then :
+if ${ac_cv_func_gmtime_r+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -16336,7 +17191,7 @@ if test $ac_cv_func_gmtime_r = yes; then :
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for localtime_r" >&5
 $as_echo_n "checking for localtime_r... " >&6; }
-if test "${ac_cv_func_localtime_r+set}" = set; then :
+if ${ac_cv_func_localtime_r+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -16378,7 +17233,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 ac_fn_c_check_func "$LINENO" "setlocale" "ac_cv_func_setlocale"
-if test "x$ac_cv_func_setlocale" = x""yes; then :
+if test "x$ac_cv_func_setlocale" = xyes; then :
 
 fi
 
@@ -16448,9 +17303,9 @@ HAVE_GCC_ATOMIC_BUILTINS=$HAVE_GCC_ATOMIC_BUILTINS
 
 
 
-# Check whether --with-with_hide_internal_symbols was given.
-if test "${with_with_hide_internal_symbols+set}" = set; then :
-  withval=$with_with_hide_internal_symbols;
+# Check whether --with-hide_internal_symbols was given.
+if test "${with_hide_internal_symbols+set}" = set; then :
+  withval=$with_hide_internal_symbols;
 fi
 
 
@@ -16498,6 +17353,33 @@ HAVE_HIDE_INTERNAL_SYMBOLS=$HAVE_HIDE_INTERNAL_SYMBOLS
 
 
 
+
+# Check whether --with-rename_internal_libtiff_symbols was given.
+if test "${with_rename_internal_libtiff_symbols+set}" = set; then :
+  withval=$with_rename_internal_libtiff_symbols;
+fi
+
+if test "$with_rename_internal_libtiff_symbols" = ""; then
+    with_rename_internal_libtiff_symbols=no
+fi
+RENAME_INTERNAL_LIBTIFF_SYMBOLS=$with_rename_internal_libtiff_symbols
+
+
+
+
+# Check whether --with-rename_internal_libgeotiff_symbols was given.
+if test "${with_rename_internal_libgeotiff_symbols+set}" = set; then :
+  withval=$with_rename_internal_libgeotiff_symbols;
+fi
+
+if test "$with_rename_internal_libgeotiff_symbols" = ""; then
+    with_rename_internal_libgeotiff_symbols=no
+fi
+RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS=$with_rename_internal_libgeotiff_symbols
+
+
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for local include/lib path" >&5
 $as_echo_n "checking for local include/lib path... " >&6; }
 
@@ -16542,7 +17424,7 @@ if test "$with_threads" = "yes" -o "$with_threads" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
 $as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then :
+if ${ac_cv_lib_pthread_pthread_create+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -16576,7 +17458,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = x""yes; then :
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
   THREAD_FLAG=CPL_MULTIPROC_PTHREAD
 fi
 
@@ -16665,7 +17547,7 @@ if test "$with_libz" = "external" -o "$with_libz" = "" -o "$with_libz" = "yes" ;
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflateInit_ in -lz" >&5
 $as_echo_n "checking for deflateInit_ in -lz... " >&6; }
-if test "${ac_cv_lib_z_deflateInit_+set}" = set; then :
+if ${ac_cv_lib_z_deflateInit_+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -16699,7 +17581,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflateInit_" >&5
 $as_echo "$ac_cv_lib_z_deflateInit_" >&6; }
-if test "x$ac_cv_lib_z_deflateInit_" = x""yes; then :
+if test "x$ac_cv_lib_z_deflateInit_" = xyes; then :
   LIBZ_SETTING=external
 else
   LIBZ_SETTING=internal
@@ -16709,7 +17591,7 @@ fi
   if test "$LIBZ_SETTING" = "external" ; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5
 $as_echo_n "checking for inflateCopy in -lz... " >&6; }
-if test "${ac_cv_lib_z_inflateCopy+set}" = set; then :
+if ${ac_cv_lib_z_inflateCopy+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -16743,7 +17625,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateCopy" >&5
 $as_echo "$ac_cv_lib_z_inflateCopy" >&6; }
-if test "x$ac_cv_lib_z_inflateCopy" = x""yes; then :
+if test "x$ac_cv_lib_z_inflateCopy" = xyes; then :
   LIBZ_SETTING=external
 else
   LIBZ_SETTING=internal
@@ -16767,7 +17649,50 @@ elif test "$with_libz" != "no" -a "$with_libz" != "internal" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflateInit_ in -lz" >&5
 $as_echo_n "checking for deflateInit_ in -lz... " >&6; }
-if test "${ac_cv_lib_z_deflateInit_+set}" = set; then :
+if ${ac_cv_lib_z_deflateInit_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz -L$with_libz -L$with_libz/lib -lz $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 deflateInit_ ();
+int
+main ()
+{
+return deflateInit_ ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_z_deflateInit_=yes
+else
+  ac_cv_lib_z_deflateInit_=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_z_deflateInit_" >&5
+$as_echo "$ac_cv_lib_z_deflateInit_" >&6; }
+if test "x$ac_cv_lib_z_deflateInit_" = xyes; then :
+  LIBZ_SETTING=external
+else
+  LIBZ_SETTING=internal
+fi
+
+  if test "$LIBZ_SETTING" = "external" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5
+$as_echo_n "checking for inflateCopy in -lz... " >&6; }
+if ${ac_cv_lib_z_inflateCopy+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -16775,112 +17700,1017 @@ LIBS="-lz -L$with_libz -L$with_libz/lib -lz $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 deflateInit_ ();
+/* 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 inflateCopy ();
+int
+main ()
+{
+return inflateCopy ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_z_inflateCopy=yes
+else
+  ac_cv_lib_z_inflateCopy=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_z_inflateCopy" >&5
+$as_echo "$ac_cv_lib_z_inflateCopy" >&6; }
+if test "x$ac_cv_lib_z_inflateCopy" = xyes; then :
+  LIBZ_SETTING=external
+else
+  LIBZ_SETTING=internal
+fi
+
+     if test "$LIBZ_SETTING" = "external" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using libz library from $with_libz" >&5
+$as_echo "using libz library from $with_libz" >&6; }
+    else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using internal libz code as inflateCopy from $with_libz is missing" >&5
+$as_echo "using internal libz code as inflateCopy from $with_libz is missing" >&6; }
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: using internal libz code as deflateInit_ from $with_libz is missing" >&5
+$as_echo "using internal libz code as deflateInit_ from $with_libz is missing" >&6; }
+  fi
+
+fi
+
+if test "$LIBZ_SETTING" = "external" ; then
+  LIBS="-lz $LIBS"
+  if test "$with_libz" != "" -a "$with_libz" != "yes" -a "$with_libz" != "external" ; then
+    EXTRA_INCLUDES="-I$with_libz -I$with_libz/include $EXTRA_INCLUDES"
+  fi
+elif test "$with_libz" = "no" ; then
+  LIBZ_SETTING=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using libz at all." >&5
+$as_echo "not using libz at all." >&6; }
+else
+  LIBZ_SETTING=internal
+  OPT_GDAL_FORMATS="zlib $OPT_GDAL_FORMATS"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: using internal libz code." >&5
+$as_echo "using internal libz code." >&6; }
+fi
+
+LIBZ_SETTING=$LIBZ_SETTING
+
+
+
+      if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5
+$as_echo_n "checking for ld used by GCC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${acl_cv_path_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      acl_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break ;;
+      *)
+	test "$with_gnu_ld" != yes && break ;;
+      esac
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${acl_cv_prog_gnu_ld+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  acl_cv_prog_gnu_ld=yes ;;
+*)
+  acl_cv_prog_gnu_ld=no ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_prog_gnu_ld" >&5
+$as_echo "$acl_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$acl_cv_prog_gnu_ld
+
+
+
+
+                                                { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5
+$as_echo_n "checking for shared library run path origin... " >&6; }
+if ${acl_cv_rpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5
+$as_echo "$acl_cv_rpath" >&6; }
+  wl="$acl_cv_wl"
+  acl_libext="$acl_cv_libext"
+  acl_shlibext="$acl_cv_shlibext"
+  acl_libname_spec="$acl_cv_libname_spec"
+  acl_library_names_spec="$acl_cv_library_names_spec"
+  acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  acl_hardcode_direct="$acl_cv_hardcode_direct"
+  acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+    # Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then :
+  enableval=$enable_rpath; :
+else
+  enable_rpath=yes
+fi
+
+
+
+                  acl_libdirstem=lib
+  searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+  if test -n "$searchpath"; then
+    acl_save_IFS="${IFS= 	}"; IFS=":"
+    for searchdir in $searchpath; do
+      if test -d "$searchdir"; then
+        case "$searchdir" in
+          */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+          *) searchdir=`cd "$searchdir" && pwd`
+             case "$searchdir" in
+               */lib64 ) acl_libdirstem=lib64 ;;
+             esac ;;
+        esac
+      fi
+    done
+    IFS="$acl_save_IFS"
+  fi
+
+
+
+
+
+
+
+
+
+    use_additional=yes
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then :
+  withval=$with_libiconv_prefix;
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/$acl_libdirstem"
+      fi
+    fi
+
+fi
+
+      LIBICONV=
+  LTLIBICONV=
+  INCICONV=
+  LIBICONV_PREFIX=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='iconv '
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+                        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value"
+          else
+                                    :
+          fi
+        else
+                              found_dir=
+          found_la=
+          found_so=
+          found_a=
+          eval libname=\"$acl_libname_spec\"    # typically: libname=lib$name
+          if test -n "$acl_shlibext"; then
+            shrext=".$acl_shlibext"             # typically: shrext=.so
+          else
+            shrext=
+          fi
+          if test $use_additional = yes; then
+            dir="$additional_libdir"
+                                    if test -n "$acl_shlibext"; then
+              if test -f "$dir/$libname$shrext"; then
+                found_dir="$dir"
+                found_so="$dir/$libname$shrext"
+              else
+                if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                  ver=`(cd "$dir" && \
+                        for f in "$libname$shrext".*; do echo "$f"; done \
+                        | sed -e "s,^$libname$shrext\\\\.,," \
+                        | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                        | sed 1q ) 2>/dev/null`
+                  if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                    found_dir="$dir"
+                    found_so="$dir/$libname$shrext.$ver"
+                  fi
+                else
+                  eval library_names=\"$acl_library_names_spec\"
+                  for f in $library_names; do
+                    if test -f "$dir/$f"; then
+                      found_dir="$dir"
+                      found_so="$dir/$f"
+                      break
+                    fi
+                  done
+                fi
+              fi
+            fi
+                        if test "X$found_dir" = "X"; then
+              if test -f "$dir/$libname.$acl_libext"; then
+                found_dir="$dir"
+                found_a="$dir/$libname.$acl_libext"
+              fi
+            fi
+            if test "X$found_dir" != "X"; then
+              if test -f "$dir/$libname.la"; then
+                found_la="$dir/$libname.la"
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                                    if test -n "$acl_shlibext"; then
+                    if test -f "$dir/$libname$shrext"; then
+                      found_dir="$dir"
+                      found_so="$dir/$libname$shrext"
+                    else
+                      if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                        ver=`(cd "$dir" && \
+                              for f in "$libname$shrext".*; do echo "$f"; done \
+                              | sed -e "s,^$libname$shrext\\\\.,," \
+                              | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                              | sed 1q ) 2>/dev/null`
+                        if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                          found_dir="$dir"
+                          found_so="$dir/$libname$shrext.$ver"
+                        fi
+                      else
+                        eval library_names=\"$acl_library_names_spec\"
+                        for f in $library_names; do
+                          if test -f "$dir/$f"; then
+                            found_dir="$dir"
+                            found_so="$dir/$f"
+                            break
+                          fi
+                        done
+                      fi
+                    fi
+                  fi
+                                    if test "X$found_dir" = "X"; then
+                    if test -f "$dir/$libname.$acl_libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/$libname.$acl_libext"
+                    fi
+                  fi
+                  if test "X$found_dir" != "X"; then
+                    if test -f "$dir/$libname.la"; then
+                      found_la="$dir/$libname.la"
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+                        LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+                                                        if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
+                                LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+              else
+                                                                                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                                if test "$acl_hardcode_direct" = yes; then
+                                                      LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                else
+                  if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+                                                            LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                                                            haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                                                                                haveit=
+                    for x in $LDFLAGS $LIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir"
+                    fi
+                    if test "$acl_hardcode_minus_L" != no; then
+                                                                                        LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a"
+              else
+                                                LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name"
+              fi
+            fi
+                        additional_includedir=
+            case "$found_dir" in
+              */$acl_libdirstem | */$acl_libdirstem/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+                LIBICONV_PREFIX="$basedir"
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+                                                                                                                if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INCICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                                            INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+                        if test -n "$found_la"; then
+                                                        save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+                            for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                                                                                                                                                                if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBICONV; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -R*)
+                    dir=`echo "X$dep" | sed -e 's/^X-R//'`
+                    if test "$enable_rpath" != no; then
+                                                                  haveit=
+                      for x in $rpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        rpathdirs="$rpathdirs $dir"
+                      fi
+                                                                  haveit=
+                      for x in $ltrpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        ltrpathdirs="$ltrpathdirs $dir"
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                                        names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                                                                                names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                                        LIBICONV="${LIBICONV}${LIBICONV:+ }$dep"
+                    LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+            LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$acl_hardcode_libdir_separator"; then
+                        alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+      done
+            acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$acl_hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+    else
+            for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$acl_hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir"
+    done
+  fi
+
+
+
+
+
+
+
+          am_save_CPPFLAGS="$CPPFLAGS"
+
+  for element in $INCICONV; do
+    haveit=
+    for x in $CPPFLAGS; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+    fi
+  done
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5
+$as_echo_n "checking for iconv... " >&6; }
+if ${am_cv_func_iconv+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <iconv.h>
+
 int
 main ()
 {
-return deflateInit_ ();
+iconv_t cd = iconv_open("","");
+           iconv(cd,NULL,NULL,NULL,NULL);
+           iconv_close(cd);
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_z_deflateInit_=yes
-else
-  ac_cv_lib_z_deflateInit_=no
+  am_cv_func_iconv=yes
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <iconv.h>
+
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+             iconv(cd,NULL,NULL,NULL,NULL);
+             iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  am_cv_lib_iconv=yes
+        am_cv_func_iconv=yes
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflateInit_" >&5
-$as_echo "$ac_cv_lib_z_deflateInit_" >&6; }
-if test "x$ac_cv_lib_z_deflateInit_" = x""yes; then :
-  LIBZ_SETTING=external
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+      LIBS="$am_save_LIBS"
+    fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5
+$as_echo "$am_cv_func_iconv" >&6; }
+  if test "$am_cv_func_iconv" = yes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5
+$as_echo_n "checking for working iconv... " >&6; }
+if ${am_cv_func_iconv_works+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  LIBZ_SETTING=internal
+
+                  am_save_LIBS="$LIBS"
+      if test $am_cv_lib_iconv = yes; then
+        LIBS="$LIBS $LIBICONV"
+      fi
+      if test "$cross_compiling" = yes; then :
+
+         case "$host_os" in
+           aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+           *)            am_cv_func_iconv_works="guessing yes" ;;
+         esac
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <iconv.h>
+#include <string.h>
+int main ()
+{
+  int result = 0;
+  /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+     returns.  */
+  {
+    iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+    if (cd_utf8_to_88591 != (iconv_t)(-1))
+      {
+        static const char input[] = "\342\202\254"; /* EURO SIGN */
+        char buf[10];
+        const char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_utf8_to_88591,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 1;
+        iconv_close (cd_utf8_to_88591);
+      }
+  }
+  /* Test against Solaris 10 bug: Failures are not distinguishable from
+     successful returns.  */
+  {
+    iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
+    if (cd_ascii_to_88591 != (iconv_t)(-1))
+      {
+        static const char input[] = "\263";
+        char buf[10];
+        const char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_ascii_to_88591,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 2;
+        iconv_close (cd_ascii_to_88591);
+      }
+  }
+  /* Test against AIX 6.1..7.1 bug: Buffer overrun.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static const char input[] = "\304";
+        static char buf[2] = { (char)0xDE, (char)0xAD };
+        const char *inptr = input;
+        size_t inbytesleft = 1;
+        char *outptr = buf;
+        size_t outbytesleft = 1;
+        size_t res = iconv (cd_88591_to_utf8,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
+          result |= 4;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#if 0 /* This bug could be worked around by the caller.  */
+  /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+        char buf[50];
+        const char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_88591_to_utf8,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if ((int)res > 0)
+          result |= 8;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#endif
+  /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+     provided.  */
+  if (/* Try standardized names.  */
+      iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+      /* Try IRIX, OSF/1 names.  */
+      && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+      /* Try AIX names.  */
+      && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+      /* Try HP-UX names.  */
+      && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+    result |= 16;
+  return result;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  am_cv_func_iconv_works=yes
+else
+  am_cv_func_iconv_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
 fi
 
-  if test "$LIBZ_SETTING" = "external" ; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5
-$as_echo_n "checking for inflateCopy in -lz... " >&6; }
-if test "${ac_cv_lib_z_inflateCopy+set}" = set; then :
+      LIBS="$am_save_LIBS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5
+$as_echo "$am_cv_func_iconv_works" >&6; }
+    case "$am_cv_func_iconv_works" in
+      *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+      *)   am_func_iconv=yes ;;
+    esac
+  else
+    am_func_iconv=no am_cv_lib_iconv=no
+  fi
+  if test "$am_func_iconv" = yes; then
+
+$as_echo "#define HAVE_ICONV 1" >>confdefs.h
+
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5
+$as_echo_n "checking how to link with libiconv... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5
+$as_echo "$LIBICONV" >&6; }
+  else
+            CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+
+
+
+  if test "$am_cv_func_iconv" = yes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5
+$as_echo_n "checking for iconv declaration... " >&6; }
+    if ${am_cv_proto_iconv+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz -L$with_libz -L$with_libz/lib -lz $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+
+      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.  */
+#include <stdlib.h>
+#include <iconv.h>
+extern
 #ifdef __cplusplus
-extern "C"
+"C"
 #endif
-char inflateCopy ();
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+
 int
 main ()
 {
-return inflateCopy ();
+
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_z_inflateCopy=yes
+if ac_fn_c_try_compile "$LINENO"; then :
+  am_cv_proto_iconv_arg1=""
 else
-  ac_cv_lib_z_inflateCopy=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+  am_cv_proto_iconv_arg1="const"
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateCopy" >&5
-$as_echo "$ac_cv_lib_z_inflateCopy" >&6; }
-if test "x$ac_cv_lib_z_inflateCopy" = x""yes; then :
-  LIBZ_SETTING=external
-else
-  LIBZ_SETTING=internal
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"
 fi
 
-     if test "$LIBZ_SETTING" = "external" ; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using libz library from $with_libz" >&5
-$as_echo "using libz library from $with_libz" >&6; }
+    am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result:
+         $am_cv_proto_iconv" >&5
+$as_echo "
+         $am_cv_proto_iconv" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $am_cv_proto_iconv_arg1
+_ACEOF
+
+
+  fi
+
+
+if test "$am_func_iconv" = "yes"; then
+    rm -f testiconv.*
+    echo '#include <iconv.h>' > testiconv.cpp
+    echo 'int main(int argc, char** argv) { iconv_t cd; return iconv (cd, (const char **) 0, 0, 0, 0); } ' >> testiconv.cpp
+    if test -z "`${CXX} testiconv.cpp -c 2>&1`" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using ICONV_CPP_CONST=\"const\"" >&5
+$as_echo "using ICONV_CPP_CONST=\"const\"" >&6; }
+        ICONV_CPP_CONST="const"
     else
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using internal libz code as inflateCopy from $with_libz is missing" >&5
-$as_echo "using internal libz code as inflateCopy from $with_libz is missing" >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: using ICONV_CPP_CONST=\"\"" >&5
+$as_echo "using ICONV_CPP_CONST=\"\"" >&6; }
+        ICONV_CPP_CONST=""
     fi
-  else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: using internal libz code as deflateInit_ from $with_libz is missing" >&5
-$as_echo "using internal libz code as deflateInit_ from $with_libz is missing" >&6; }
-  fi
+    rm -f testiconv.*
 
-fi
 
-if test "$LIBZ_SETTING" = "external" ; then
-  LIBS="-lz $LIBS"
-  if test "$with_libz" != "" -a "$with_libz" != "yes" -a "$with_libz" != "external" ; then
-    EXTRA_INCLUDES="-I$with_libz -I$with_libz/include $EXTRA_INCLUDES"
-  fi
-elif test "$with_libz" = "no" ; then
-  LIBZ_SETTING=no
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: not using libz at all." >&5
-$as_echo "not using libz at all." >&6; }
-else
-  LIBZ_SETTING=internal
-  OPT_GDAL_FORMATS="zlib $OPT_GDAL_FORMATS"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: using internal libz code." >&5
-$as_echo "using internal libz code." >&6; }
-fi
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CPP_CONST $ICONV_CPP_CONST
+_ACEOF
 
-LIBZ_SETTING=$LIBZ_SETTING
+fi
 
 
 
@@ -16894,7 +18724,7 @@ fi
 if test "$with_liblzma" = "yes" ; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_code in -llzma" >&5
 $as_echo_n "checking for lzma_code in -llzma... " >&6; }
-if test "${ac_cv_lib_lzma_lzma_code+set}" = set; then :
+if ${ac_cv_lib_lzma_lzma_code+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -16928,7 +18758,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_code" >&5
 $as_echo "$ac_cv_lib_lzma_lzma_code" >&6; }
-if test "x$ac_cv_lib_lzma_lzma_code" = x""yes; then :
+if test "x$ac_cv_lib_lzma_lzma_code" = xyes; then :
   LIBLZMA_SETTING=yes
 else
   LIBLZMA_SETTING=no
@@ -16960,7 +18790,7 @@ if test "x$with_pg" = "xyes" -o "x$with_pg" = "x" ; then
 set dummy pg_config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_PG_CONFIG+set}" = set; then :
+if ${ac_cv_path_PG_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $PG_CONFIG in
@@ -17031,7 +18861,7 @@ $as_echo "yes" >&6; }
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQconnectdb in -lpq" >&5
 $as_echo_n "checking for PQconnectdb in -lpq... " >&6; }
-if test "${ac_cv_lib_pq_PQconnectdb+set}" = set; then :
+if ${ac_cv_lib_pq_PQconnectdb+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17065,7 +18895,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQconnectdb" >&5
 $as_echo "$ac_cv_lib_pq_PQconnectdb" >&6; }
-if test "x$ac_cv_lib_pq_PQconnectdb" = x""yes; then :
+if test "x$ac_cv_lib_pq_PQconnectdb" = xyes; then :
   HAVE_PG=yes
 else
   HAVE_PG=no
@@ -17080,7 +18910,7 @@ fi
     saved_LIBS="$LIBS"
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQputCopyData in -lpq" >&5
 $as_echo_n "checking for PQputCopyData in -lpq... " >&6; }
-if test "${ac_cv_lib_pq_PQputCopyData+set}" = set; then :
+if ${ac_cv_lib_pq_PQputCopyData+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17114,7 +18944,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQputCopyData" >&5
 $as_echo "$ac_cv_lib_pq_PQputCopyData" >&6; }
-if test "x$ac_cv_lib_pq_PQputCopyData" = x""yes; then :
+if test "x$ac_cv_lib_pq_PQputCopyData" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBPQ 1
 _ACEOF
@@ -17133,7 +18963,7 @@ fi
     saved_LIBS="$LIBS"
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQescapeStringConn in -lpq" >&5
 $as_echo_n "checking for PQescapeStringConn in -lpq... " >&6; }
-if test "${ac_cv_lib_pq_PQescapeStringConn+set}" = set; then :
+if ${ac_cv_lib_pq_PQescapeStringConn+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17167,7 +18997,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQescapeStringConn" >&5
 $as_echo "$ac_cv_lib_pq_PQescapeStringConn" >&6; }
-if test "x$ac_cv_lib_pq_PQescapeStringConn" = x""yes; then :
+if test "x$ac_cv_lib_pq_PQescapeStringConn" = xyes; then :
   DEFINE_PG_HAS_PQESCAPESTRINGCONN=-DPG_HAS_PQESCAPESTRINGCONN
 fi
 
@@ -17219,7 +19049,7 @@ 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_n "checking for G_asprintf in -lgrass_gis... " >&6; }
-if test "${ac_cv_lib_grass_gis_G_asprintf+set}" = set; then :
+if ${ac_cv_lib_grass_gis_G_asprintf+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17253,7 +19083,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_grass_gis_G_asprintf" >&5
 $as_echo "$ac_cv_lib_grass_gis_G_asprintf" >&6; }
-if test "x$ac_cv_lib_grass_gis_G_asprintf" = x""yes; then :
+if test "x$ac_cv_lib_grass_gis_G_asprintf" = xyes; then :
   GRASS_SETTING=grass57+
 else
   GRASS_SETTING=no
@@ -17280,7 +19110,7 @@ elif test "$with_libgrass" = "yes" -o "$with_libgrass" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_gisinit_2 in -lgrass5" >&5
 $as_echo_n "checking for G_gisinit_2 in -lgrass5... " >&6; }
-if test "${ac_cv_lib_grass5_G_gisinit_2+set}" = set; then :
+if ${ac_cv_lib_grass5_G_gisinit_2+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17314,7 +19144,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_grass5_G_gisinit_2" >&5
 $as_echo "$ac_cv_lib_grass5_G_gisinit_2" >&6; }
-if test "x$ac_cv_lib_grass5_G_gisinit_2" = x""yes; then :
+if test "x$ac_cv_lib_grass5_G_gisinit_2" = xyes; then :
   GRASS_SETTING=libgrass
 else
   GRASS_SETTING=no
@@ -17329,7 +19159,7 @@ else
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_gisinit_2 in -lgrass5" >&5
 $as_echo_n "checking for G_gisinit_2 in -lgrass5... " >&6; }
-if test "${ac_cv_lib_grass5_G_gisinit_2+set}" = set; then :
+if ${ac_cv_lib_grass5_G_gisinit_2+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17363,7 +19193,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_grass5_G_gisinit_2" >&5
 $as_echo "$ac_cv_lib_grass5_G_gisinit_2" >&6; }
-if test "x$ac_cv_lib_grass5_G_gisinit_2" = x""yes; then :
+if test "x$ac_cv_lib_grass5_G_gisinit_2" = xyes; then :
   GRASS_SETTING=libgrass
 else
   GRASS_SETTING=no
@@ -17408,7 +19238,7 @@ elif test "$with_cfitsio" = "yes" -o "$with_cfitsio" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ffopen in -lcfitsio" >&5
 $as_echo_n "checking for ffopen in -lcfitsio... " >&6; }
-if test "${ac_cv_lib_cfitsio_ffopen+set}" = set; then :
+if ${ac_cv_lib_cfitsio_ffopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17442,7 +19272,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cfitsio_ffopen" >&5
 $as_echo "$ac_cv_lib_cfitsio_ffopen" >&6; }
-if test "x$ac_cv_lib_cfitsio_ffopen" = x""yes; then :
+if test "x$ac_cv_lib_cfitsio_ffopen" = xyes; then :
   FITS_SETTING=external
 else
   FITS_SETTING=no
@@ -17494,7 +19324,7 @@ elif test "$with_pcraster" = "yes" -o "$with_pcraster" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mopen in -lcsf" >&5
 $as_echo_n "checking for Mopen in -lcsf... " >&6; }
-if test "${ac_cv_lib_csf_Mopen+set}" = set; then :
+if ${ac_cv_lib_csf_Mopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17512,160 +19342,73 @@ char Mopen ();
 int
 main ()
 {
-return Mopen ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_csf_Mopen=yes
-else
-  ac_cv_lib_csf_Mopen=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_csf_Mopen" >&5
-$as_echo "$ac_cv_lib_csf_Mopen" >&6; }
-if test "x$ac_cv_lib_csf_Mopen" = x""yes; then :
-  PCRASTER_SETTING=external
-else
-  PCRASTER_SETTING=internal
-fi
-
-  for ac_header in csf.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "csf.h" "ac_cv_header_csf_h" "$ac_includes_default"
-if test "x$ac_cv_header_csf_h" = x""yes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_CSF_H 1
-_ACEOF
-
-fi
-
-done
-
-
-  if test "$PCRASTER_SETTING" = "external" -a "$ac_cv_header_csf_h" = "no" ; then
-    PCRASTER_SETTING=internal
-  fi
-
-  if test "$PCRASTER_SETTING" = "external" ; then
-    LIBS="-lcsf $LIBS"
-    echo "using pre-installed libcsf."
-  else
-    echo "using internal csf code."
-  fi
-
-elif test "$with_pcraster" = "internal" ; then
-
-  PCRASTER_SETTING=internal
-
-  echo "using internal csf code."
-
-else
-
-  PCRASTER_SETTING=external
-  LIBS="-L$with_pcraster/lib -lcsf $LIBS"
-  EXTRA_INCLUDES="-I$with_pcraster/include $EXTRA_INCLUDES"
-
-  echo "using libcsf from $with_pcraster."
-
-fi
-
-PCRASTER_SETTING=$PCRASTER_SETTING
-
-
-if test "$PCRASTER_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="pcraster $OPT_GDAL_FORMATS"
-fi
-
-
-
-# Check whether --with-netcdf was given.
-if test "${with_netcdf+set}" = set; then :
-  withval=$with_netcdf;
-fi
-
-
-if test "$with_netcdf" = "no" ; then
-
-  NETCDF_SETTING=no
-
-  echo "netCDF support disabled."
-
-elif test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nc_open in -lnetcdf" >&5
-$as_echo_n "checking for nc_open in -lnetcdf... " >&6; }
-if test "${ac_cv_lib_netcdf_nc_open+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnetcdf  $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 nc_open ();
-int
-main ()
-{
-return nc_open ();
+return Mopen ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_netcdf_nc_open=yes
+  ac_cv_lib_csf_Mopen=yes
 else
-  ac_cv_lib_netcdf_nc_open=no
+  ac_cv_lib_csf_Mopen=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_netcdf_nc_open" >&5
-$as_echo "$ac_cv_lib_netcdf_nc_open" >&6; }
-if test "x$ac_cv_lib_netcdf_nc_open" = x""yes; then :
-  NETCDF_SETTING=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_csf_Mopen" >&5
+$as_echo "$ac_cv_lib_csf_Mopen" >&6; }
+if test "x$ac_cv_lib_csf_Mopen" = xyes; then :
+  PCRASTER_SETTING=external
 else
-  NETCDF_SETTING=no
+  PCRASTER_SETTING=internal
+fi
+
+  for ac_header in csf.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "csf.h" "ac_cv_header_csf_h" "$ac_includes_default"
+if test "x$ac_cv_header_csf_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CSF_H 1
+_ACEOF
+
 fi
 
+done
 
-  if test "$NETCDF_SETTING" = "yes" ; then
-    LIBS="-lnetcdf $LIBS"
-    echo "using pre-installed libnetcdf."
-  else
-    echo "libnetcdf not found - netCDF support disabled"
+
+  if test "$PCRASTER_SETTING" = "external" -a "$ac_cv_header_csf_h" = "no" ; then
+    PCRASTER_SETTING=internal
   fi
 
-  if test "$NETCDF_SETTING" = "yes" -a -d /usr/include/netcdf ; then
-    EXTRA_INCLUDES="-I/usr/include/netcdf $EXTRA_INCLUDES"
-  elif test "$NETCDF_SETTING" = "yes" -a -d /usr/include/netcdf-3 ; then
-    EXTRA_INCLUDES="-I/usr/include/netcdf-3 $EXTRA_INCLUDES"
+  if test "$PCRASTER_SETTING" = "external" ; then
+    LIBS="-lcsf $LIBS"
+    echo "using pre-installed libcsf."
+  else
+    echo "using internal csf code."
   fi
+
+elif test "$with_pcraster" = "internal" ; then
+
+  PCRASTER_SETTING=internal
+
+  echo "using internal csf code."
+
 else
 
-  NETCDF_SETTING=yes
-  LIBS="-L$with_netcdf -L$with_netcdf/lib -lnetcdf $LIBS"
-  EXTRA_INCLUDES="-I$with_netcdf -I$with_netcdf/include $EXTRA_INCLUDES"
+  PCRASTER_SETTING=external
+  LIBS="-L$with_pcraster/lib -lcsf $LIBS"
+  EXTRA_INCLUDES="-I$with_pcraster/include $EXTRA_INCLUDES"
+
+  echo "using libcsf from $with_pcraster."
 
-  echo "using libnetcdf from $with_netcdf."
 fi
 
-NETCDF_SETTING=$NETCDF_SETTING
+PCRASTER_SETTING=$PCRASTER_SETTING
 
 
-if test "$NETCDF_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="netcdf $OPT_GDAL_FORMATS"
+if test "$PCRASTER_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="pcraster $OPT_GDAL_FORMATS"
 fi
 
 
@@ -17689,7 +19432,7 @@ elif test "$with_png" = "yes" -o "$with_png" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for png_set_IHDR in -lpng" >&5
 $as_echo_n "checking for png_set_IHDR in -lpng... " >&6; }
-if test "${ac_cv_lib_png_png_set_IHDR+set}" = set; then :
+if ${ac_cv_lib_png_png_set_IHDR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17723,7 +19466,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_set_IHDR" >&5
 $as_echo "$ac_cv_lib_png_png_set_IHDR" >&6; }
-if test "x$ac_cv_lib_png_png_set_IHDR" = x""yes; then :
+if test "x$ac_cv_lib_png_png_set_IHDR" = xyes; then :
   PNG_SETTING=external
 else
   PNG_SETTING=internal
@@ -17732,7 +19475,7 @@ fi
   for ac_header in png.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "png.h" "ac_cv_header_png_h" "$ac_includes_default"
-if test "x$ac_cv_header_png_h" = x""yes; then :
+if test "x$ac_cv_header_png_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_PNG_H 1
 _ACEOF
@@ -17777,6 +19520,88 @@ fi
 
 
 
+# Check whether --with-gta was given.
+if test "${with_gta+set}" = set; then :
+  withval=$with_gta;
+fi
+
+
+if test "$with_gta" = "no" ; then
+
+  GTA_SETTING=no
+
+  echo "GTA support disabled."
+
+elif test "$with_gta" = "yes" -o "$with_gta" = "" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gta_version in -lgta" >&5
+$as_echo_n "checking for gta_version in -lgta... " >&6; }
+if ${ac_cv_lib_gta_gta_version+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgta  $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 gta_version ();
+int
+main ()
+{
+return gta_version ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_gta_gta_version=yes
+else
+  ac_cv_lib_gta_gta_version=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_gta_gta_version" >&5
+$as_echo "$ac_cv_lib_gta_gta_version" >&6; }
+if test "x$ac_cv_lib_gta_gta_version" = xyes; then :
+  GTA_SETTING=yes
+else
+  GTA_SETTING=no
+fi
+
+
+  if test "$GTA_SETTING" = "yes" ; then
+    LIBS="-lgta $LIBS"
+    echo "using pre-installed libgta."
+  else
+    echo "libgta not found - GTA support disabled"
+  fi
+
+else
+
+  GTA_SETTING=yes
+  LIBS="-L$with_gta -L$with_gta/lib -lgta $LIBS"
+  EXTRA_INCLUDES="-I$with_gta -I$with_gta/include $EXTRA_INCLUDES"
+
+  echo "using libgta from $with_gta."
+fi
+
+GTA_SETTING=$GTA_SETTING
+
+
+if test "$GTA_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="gta $OPT_GDAL_FORMATS"
+fi
+
+
+
 # Check whether --with-pcidsk was given.
 if test "${with_pcidsk+set}" = set; then :
   withval=$with_pcidsk;
@@ -17833,7 +19658,7 @@ if test "x${with_libtiff}" = "xyes" -o "x${with_libtiff}" = "x" ; then
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TIFFScanlineSize64 in -ltiff" >&5
 $as_echo_n "checking for TIFFScanlineSize64 in -ltiff... " >&6; }
-if test "${ac_cv_lib_tiff_TIFFScanlineSize64+set}" = set; then :
+if ${ac_cv_lib_tiff_TIFFScanlineSize64+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17867,7 +19692,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tiff_TIFFScanlineSize64" >&5
 $as_echo "$ac_cv_lib_tiff_TIFFScanlineSize64" >&6; }
-if test "x$ac_cv_lib_tiff_TIFFScanlineSize64" = x""yes; then :
+if test "x$ac_cv_lib_tiff_TIFFScanlineSize64" = xyes; then :
   TIFF_SETTING=external HAVE_BIGTIFF=yes
 else
   TIFF_SETTING=internal HAVE_BIGTIFF=yes
@@ -17877,7 +19702,7 @@ fi
   if test "$TIFF_SETTING" = "external" ; then
                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _TIFFsetDoubleArray in -ltiff" >&5
 $as_echo_n "checking for _TIFFsetDoubleArray in -ltiff... " >&6; }
-if test "${ac_cv_lib_tiff__TIFFsetDoubleArray+set}" = set; then :
+if ${ac_cv_lib_tiff__TIFFsetDoubleArray+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17911,7 +19736,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tiff__TIFFsetDoubleArray" >&5
 $as_echo "$ac_cv_lib_tiff__TIFFsetDoubleArray" >&6; }
-if test "x$ac_cv_lib_tiff__TIFFsetDoubleArray" = x""yes; then :
+if test "x$ac_cv_lib_tiff__TIFFsetDoubleArray" = xyes; then :
   TIFF_SETTING=external
 else
   TIFF_SETTING=internal
@@ -17952,7 +19777,7 @@ $as_echo "using libtiff from ${with_libtiff}." >&6; }
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TIFFScanlineSize64 in -ltiff" >&5
 $as_echo_n "checking for TIFFScanlineSize64 in -ltiff... " >&6; }
-if test "${ac_cv_lib_tiff_TIFFScanlineSize64+set}" = set; then :
+if ${ac_cv_lib_tiff_TIFFScanlineSize64+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -17986,7 +19811,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tiff_TIFFScanlineSize64" >&5
 $as_echo "$ac_cv_lib_tiff_TIFFScanlineSize64" >&6; }
-if test "x$ac_cv_lib_tiff_TIFFScanlineSize64" = x""yes; then :
+if test "x$ac_cv_lib_tiff_TIFFScanlineSize64" = xyes; then :
   HAVE_BIGTIFF=yes
 else
   HAVE_BIGTIFF=no
@@ -18024,7 +19849,7 @@ if test "$with_geotiff" = "yes" -o "$with_geotiff" = "" ; then
   else
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XTIFFClientOpen in -lgeotiff" >&5
 $as_echo_n "checking for XTIFFClientOpen in -lgeotiff... " >&6; }
-if test "${ac_cv_lib_geotiff_XTIFFClientOpen+set}" = set; then :
+if ${ac_cv_lib_geotiff_XTIFFClientOpen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18058,7 +19883,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_geotiff_XTIFFClientOpen" >&5
 $as_echo "$ac_cv_lib_geotiff_XTIFFClientOpen" >&6; }
-if test "x$ac_cv_lib_geotiff_XTIFFClientOpen" = x""yes; then :
+if test "x$ac_cv_lib_geotiff_XTIFFClientOpen" = xyes; then :
   GEOTIFF_SETTING=external
 else
   GEOTIFF_SETTING=internal
@@ -18096,7 +19921,7 @@ else
 
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XTIFFClientOpen in -lgeotiff" >&5
 $as_echo_n "checking for XTIFFClientOpen in -lgeotiff... " >&6; }
-if test "${ac_cv_lib_geotiff_XTIFFClientOpen+set}" = set; then :
+if ${ac_cv_lib_geotiff_XTIFFClientOpen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18130,7 +19955,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_geotiff_XTIFFClientOpen" >&5
 $as_echo "$ac_cv_lib_geotiff_XTIFFClientOpen" >&6; }
-if test "x$ac_cv_lib_geotiff_XTIFFClientOpen" = x""yes; then :
+if test "x$ac_cv_lib_geotiff_XTIFFClientOpen" = xyes; then :
   GEOTIFF_SETTING=external
 else
   GEOTIFF_SETTING=not_found
@@ -18145,7 +19970,7 @@ fi
   else
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XTIFFClientOpen in -lgeotiff" >&5
 $as_echo_n "checking for XTIFFClientOpen in -lgeotiff... " >&6; }
-if test "${ac_cv_lib_geotiff_XTIFFClientOpen+set}" = set; then :
+if ${ac_cv_lib_geotiff_XTIFFClientOpen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18179,7 +20004,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_geotiff_XTIFFClientOpen" >&5
 $as_echo "$ac_cv_lib_geotiff_XTIFFClientOpen" >&6; }
-if test "x$ac_cv_lib_geotiff_XTIFFClientOpen" = x""yes; then :
+if test "x$ac_cv_lib_geotiff_XTIFFClientOpen" = xyes; then :
   GEOTIFF_SETTING=external
 else
   as_fn_error $? "We require at least GeoTIFF 1.2.1. Consider using the one supplied with GDAL" "$LINENO" 5
@@ -18217,7 +20042,7 @@ elif test "$with_jpeg" = "yes" -o "$with_jpeg" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_read_scanlines in -ljpeg" >&5
 $as_echo_n "checking for jpeg_read_scanlines in -ljpeg... " >&6; }
-if test "${ac_cv_lib_jpeg_jpeg_read_scanlines+set}" = set; then :
+if ${ac_cv_lib_jpeg_jpeg_read_scanlines+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18251,7 +20076,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_read_scanlines" >&5
 $as_echo "$ac_cv_lib_jpeg_jpeg_read_scanlines" >&6; }
-if test "x$ac_cv_lib_jpeg_jpeg_read_scanlines" = x""yes; then :
+if test "x$ac_cv_lib_jpeg_jpeg_read_scanlines" = xyes; then :
   JPEG_SETTING=external
 else
   JPEG_SETTING=internal
@@ -18260,7 +20085,7 @@ fi
   for ac_header in jpeglib.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "jpeglib.h" "ac_cv_header_jpeglib_h" "$ac_includes_default"
-if test "x$ac_cv_header_jpeglib_h" = x""yes; then :
+if test "x$ac_cv_header_jpeglib_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_JPEGLIB_H 1
 _ACEOF
@@ -18374,7 +20199,7 @@ elif test "$with_gif" = "yes" -o "$with_gif" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DGifOpenFileName in -lgif" >&5
 $as_echo_n "checking for DGifOpenFileName in -lgif... " >&6; }
-if test "${ac_cv_lib_gif_DGifOpenFileName+set}" = set; then :
+if ${ac_cv_lib_gif_DGifOpenFileName+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18408,12 +20233,24 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gif_DGifOpenFileName" >&5
 $as_echo "$ac_cv_lib_gif_DGifOpenFileName" >&6; }
-if test "x$ac_cv_lib_gif_DGifOpenFileName" = x""yes; then :
+if test "x$ac_cv_lib_gif_DGifOpenFileName" = xyes; then :
   GIF_SETTING=external
 else
   GIF_SETTING=internal
 fi
 
+  for ac_header in gif_lib.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "gif_lib.h" "ac_cv_header_gif_lib_h" "$ac_includes_default"
+if test "x$ac_cv_header_gif_lib_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GIF_LIB_H 1
+_ACEOF
+
+fi
+
+done
+
 
   if test "$GIF_SETTING" = "external" ; then
     LIBS="-lgif $LIBS"
@@ -18467,7 +20304,7 @@ elif test "$with_ogdi" = "yes" -o "$with_ogdi" = "" ; then
   for ac_header in ecs.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "ecs.h" "ac_cv_header_ecs_h" "$ac_includes_default"
-if test "x$ac_cv_header_ecs_h" = x""yes; then :
+if test "x$ac_cv_header_ecs_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_ECS_H 1
 _ACEOF
@@ -18492,7 +20329,7 @@ done
   if test "$OGDI_INCLUDE" != "" -o "$ac_cv_header_ecs_h" = "yes"; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cln_GetLayerCapabilities in -logdi" >&5
 $as_echo_n "checking for cln_GetLayerCapabilities in -logdi... " >&6; }
-if test "${ac_cv_lib_ogdi_cln_GetLayerCapabilities+set}" = set; then :
+if ${ac_cv_lib_ogdi_cln_GetLayerCapabilities+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18526,7 +20363,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogdi_cln_GetLayerCapabilities" >&5
 $as_echo "$ac_cv_lib_ogdi_cln_GetLayerCapabilities" >&6; }
-if test "x$ac_cv_lib_ogdi_cln_GetLayerCapabilities" = x""yes; then :
+if test "x$ac_cv_lib_ogdi_cln_GetLayerCapabilities" = xyes; then :
   HAVE_OGDI=yes
 else
   HAVE_OGDI=no
@@ -18537,7 +20374,7 @@ fi
     else
             { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cln_GetLayerCapabilities in -logdi31" >&5
 $as_echo_n "checking for cln_GetLayerCapabilities in -logdi31... " >&6; }
-if test "${ac_cv_lib_ogdi31_cln_GetLayerCapabilities+set}" = set; then :
+if ${ac_cv_lib_ogdi31_cln_GetLayerCapabilities+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18571,7 +20408,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogdi31_cln_GetLayerCapabilities" >&5
 $as_echo "$ac_cv_lib_ogdi31_cln_GetLayerCapabilities" >&6; }
-if test "x$ac_cv_lib_ogdi31_cln_GetLayerCapabilities" = x""yes; then :
+if test "x$ac_cv_lib_ogdi31_cln_GetLayerCapabilities" = xyes; then :
   HAVE_OGDI=yes
 else
   HAVE_OGDI=no
@@ -18589,7 +20426,7 @@ else
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cln_GetLayerCapabilities in -logdi" >&5
 $as_echo_n "checking for cln_GetLayerCapabilities in -logdi... " >&6; }
-if test "${ac_cv_lib_ogdi_cln_GetLayerCapabilities+set}" = set; then :
+if ${ac_cv_lib_ogdi_cln_GetLayerCapabilities+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18623,7 +20460,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogdi_cln_GetLayerCapabilities" >&5
 $as_echo "$ac_cv_lib_ogdi_cln_GetLayerCapabilities" >&6; }
-if test "x$ac_cv_lib_ogdi_cln_GetLayerCapabilities" = x""yes; then :
+if test "x$ac_cv_lib_ogdi_cln_GetLayerCapabilities" = xyes; then :
   HAVE_OGDI=yes
 else
   HAVE_OGDI=no
@@ -18642,7 +20479,7 @@ fi
   else
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cln_GetLayerCapabilities in -logdi31" >&5
 $as_echo_n "checking for cln_GetLayerCapabilities in -logdi31... " >&6; }
-if test "${ac_cv_lib_ogdi31_cln_GetLayerCapabilities+set}" = set; then :
+if ${ac_cv_lib_ogdi31_cln_GetLayerCapabilities+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18676,7 +20513,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogdi31_cln_GetLayerCapabilities" >&5
 $as_echo "$ac_cv_lib_ogdi31_cln_GetLayerCapabilities" >&6; }
-if test "x$ac_cv_lib_ogdi31_cln_GetLayerCapabilities" = x""yes; then :
+if test "x$ac_cv_lib_ogdi31_cln_GetLayerCapabilities" = xyes; then :
   HAVE_OGDI=yes
 else
   HAVE_OGDI=no
@@ -18809,7 +20646,7 @@ else
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDreaddata in -lmfhdfalt" >&5
 $as_echo_n "checking for SDreaddata in -lmfhdfalt... " >&6; }
-if test "${ac_cv_lib_mfhdfalt_SDreaddata+set}" = set; then :
+if ${ac_cv_lib_mfhdfalt_SDreaddata+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18843,7 +20680,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mfhdfalt_SDreaddata" >&5
 $as_echo "$ac_cv_lib_mfhdfalt_SDreaddata" >&6; }
-if test "x$ac_cv_lib_mfhdfalt_SDreaddata" = x""yes; then :
+if test "x$ac_cv_lib_mfhdfalt_SDreaddata" = xyes; then :
   HDF_LIB_NAME="-lmfhdfalt -ldfalt"
 else
   HDF_LIB_NAME=missing
@@ -18854,7 +20691,7 @@ fi
     unset ac_cv_lib_mfhdf_SDreaddata
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDreaddata in -lmfhdf" >&5
 $as_echo_n "checking for SDreaddata in -lmfhdf... " >&6; }
-if test "${ac_cv_lib_mfhdf_SDreaddata+set}" = set; then :
+if ${ac_cv_lib_mfhdf_SDreaddata+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18888,7 +20725,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mfhdf_SDreaddata" >&5
 $as_echo "$ac_cv_lib_mfhdf_SDreaddata" >&6; }
-if test "x$ac_cv_lib_mfhdf_SDreaddata" = x""yes; then :
+if test "x$ac_cv_lib_mfhdf_SDreaddata" = xyes; then :
   HDF_LIB_NAME="-lmfhdf -ldf"
 else
   HDF_LIB_NAME=missing
@@ -18898,7 +20735,7 @@ fi
       unset ac_cv_lib_mfhdf_SDreaddata
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDreaddata in -lhdf4" >&5
 $as_echo_n "checking for SDreaddata in -lhdf4... " >&6; }
-if test "${ac_cv_lib_hdf4_SDreaddata+set}" = set; then :
+if ${ac_cv_lib_hdf4_SDreaddata+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18932,7 +20769,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hdf4_SDreaddata" >&5
 $as_echo "$ac_cv_lib_hdf4_SDreaddata" >&6; }
-if test "x$ac_cv_lib_hdf4_SDreaddata" = x""yes; then :
+if test "x$ac_cv_lib_hdf4_SDreaddata" = xyes; then :
   HDF_LIB_NAME=-lhdf4
 else
   HDF_LIB_NAME=missing
@@ -18945,7 +20782,7 @@ fi
     unset ac_cv_lib_mfhdf_SDreaddata
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDreaddata in -lmfhdf" >&5
 $as_echo_n "checking for SDreaddata in -lmfhdf... " >&6; }
-if test "${ac_cv_lib_mfhdf_SDreaddata+set}" = set; then :
+if ${ac_cv_lib_mfhdf_SDreaddata+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -18979,7 +20816,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mfhdf_SDreaddata" >&5
 $as_echo "$ac_cv_lib_mfhdf_SDreaddata" >&6; }
-if test "x$ac_cv_lib_mfhdf_SDreaddata" = x""yes; then :
+if test "x$ac_cv_lib_mfhdf_SDreaddata" = xyes; then :
   HDF_LIB_NAME="-lmfhdf -ldf"
 else
   HDF_LIB_NAME=missing
@@ -18991,7 +20828,7 @@ fi
     unset ac_cv_lib_mfhdf_SDreaddata
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDreaddata in -lmfhdf" >&5
 $as_echo_n "checking for SDreaddata in -lmfhdf... " >&6; }
-if test "${ac_cv_lib_mfhdf_SDreaddata+set}" = set; then :
+if ${ac_cv_lib_mfhdf_SDreaddata+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19025,7 +20862,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mfhdf_SDreaddata" >&5
 $as_echo "$ac_cv_lib_mfhdf_SDreaddata" >&6; }
-if test "x$ac_cv_lib_mfhdf_SDreaddata" = x""yes; then :
+if test "x$ac_cv_lib_mfhdf_SDreaddata" = xyes; then :
   HDF_LIB_NAME="-lmfhdf -ldf -lsz"
 else
   HDF_LIB_NAME=missing
@@ -19098,7 +20935,7 @@ elif test "$with_hdf5" = "yes" -o "$with_hdf5" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for H5Fopen in -lhdf5" >&5
 $as_echo_n "checking for H5Fopen in -lhdf5... " >&6; }
-if test "${ac_cv_lib_hdf5_H5Fopen+set}" = set; then :
+if ${ac_cv_lib_hdf5_H5Fopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19132,7 +20969,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hdf5_H5Fopen" >&5
 $as_echo "$ac_cv_lib_hdf5_H5Fopen" >&6; }
-if test "x$ac_cv_lib_hdf5_H5Fopen" = x""yes; then :
+if test "x$ac_cv_lib_hdf5_H5Fopen" = xyes; then :
   HAVE_HDF5=yes
 else
   HAVE_HDF5=no
@@ -19160,7 +20997,7 @@ else
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for H5Fopen in -lhdf5" >&5
 $as_echo_n "checking for H5Fopen in -lhdf5... " >&6; }
-if test "${ac_cv_lib_hdf5_H5Fopen+set}" = set; then :
+if ${ac_cv_lib_hdf5_H5Fopen+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19194,43 +21031,267 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hdf5_H5Fopen" >&5
 $as_echo "$ac_cv_lib_hdf5_H5Fopen" >&6; }
-if test "x$ac_cv_lib_hdf5_H5Fopen" = x""yes; then :
+if test "x$ac_cv_lib_hdf5_H5Fopen" = xyes; then :
   HDF5_LIB_NAME="-lhdf5 "
 else
   HDF5_LIB_NAME=missing
 fi
 
 
-  if test "$HDF5_LIB_NAME" = "missing" ; then
-    as_fn_error $? "HDF5 support requested with arg $with_hdf5, but no hdf5 lib found" "$LINENO" 5
-  fi
+  if test "$HDF5_LIB_NAME" = "missing" ; then
+    as_fn_error $? "HDF5 support requested with arg $with_hdf5, but no hdf5 lib found" "$LINENO" 5
+  fi
+
+  LIBS="-L$HDF5_LIB_DIR $HDF5_LIB_NAME $ORIG_LIBS"
+
+  if test -r "$with_hdf5/hdf5/hdf5.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5/hdf5"
+  elif test -r "$with_hdf5/include/hdf5/hdf5.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5/include/hdf5"
+  elif test -r "$with_hdf5/include/hdf5.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5/include"
+  elif test -r "$with_hdf5/hdf.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5"
+  fi
+
+  HAVE_HDF5=yes
+fi
+
+HAVE_HDF5=$HAVE_HDF5
+
+HDF5_INCLUDE=$HDF5_INCLUDE
+
+
+if test "$HAVE_HDF5" != "no" ; then
+  OPT_GDAL_FORMATS="hdf5 $OPT_GDAL_FORMATS"
+fi
+
+
+NETCDF_SETTING=
+NETCDF_ROOT=
+NETCDF_HAS_NC4=
+NETCDF_HAS_HDF4=
+
+
+# Check whether --with-netcdf was given.
+if test "${with_netcdf+set}" = set; then :
+  withval=$with_netcdf;
+fi
+
+
+if test "$with_netcdf" = "no" ; then
+
+  NETCDF_SETTING=no
+
+  echo "netCDF support disabled."
+
+elif test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nc_open in -lnetcdf" >&5
+$as_echo_n "checking for nc_open in -lnetcdf... " >&6; }
+if ${ac_cv_lib_netcdf_nc_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetcdf  $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 nc_open ();
+int
+main ()
+{
+return nc_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_netcdf_nc_open=yes
+else
+  ac_cv_lib_netcdf_nc_open=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_netcdf_nc_open" >&5
+$as_echo "$ac_cv_lib_netcdf_nc_open" >&6; }
+if test "x$ac_cv_lib_netcdf_nc_open" = xyes; then :
+  NETCDF_SETTING=yes
+else
+  NETCDF_SETTING=no
+fi
+
+
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+        if test -d /usr/include/netcdf ; then
+      EXTRA_INCLUDES="-I/usr/include/netcdf $EXTRA_INCLUDES"
+      NETCDF_ROOT="/usr"
+        elif test -d /usr/include/netcdf-3 ; then
+      EXTRA_INCLUDES="-I/usr/include/netcdf-3 $EXTRA_INCLUDES"
+      NETCDF_ROOT="/usr"
+        elif test -f /usr/include/netcdf.h ; then
+      NETCDF_ROOT="/usr"
+        elif test -f /usr/local/include/netcdf.h ; then
+      NETCDF_ROOT="/usr/local"
+        else
+      echo "using pre-installed libnetcdf."
+      echo -n "libnetcdf is installed but its location cannot be found, "
+      echo "use --with-netcdf=/path_to_netcdf for proper support"
+    fi
+
+    LIBS="-lnetcdf $LIBS"
+    if test "$NETCDF_ROOT" != "" ; then
+      echo "using pre-installed libnetcdf from "$NETCDF_ROOT
+    fi
+
+  else
+    echo "libnetcdf not found - netCDF support disabled"
+  fi
+
+else
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nc_open in -lnetcdf" >&5
+$as_echo_n "checking for nc_open in -lnetcdf... " >&6; }
+if ${ac_cv_lib_netcdf_nc_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetcdf -L$with_netcdf -L$with_netcdf/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 nc_open ();
+int
+main ()
+{
+return nc_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_netcdf_nc_open=yes
+else
+  ac_cv_lib_netcdf_nc_open=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_netcdf_nc_open" >&5
+$as_echo "$ac_cv_lib_netcdf_nc_open" >&6; }
+if test "x$ac_cv_lib_netcdf_nc_open" = xyes; then :
+  NETCDF_SETTING=yes
+else
+  NETCDF_SETTING=no
+fi
+
+
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    NETCDF_SETTING=yes
+    NETCDF_ROOT="$with_netcdf"
+
+    if test -d $with_netcdf/lib ; then
+      LIBS="-L$with_netcdf/lib -lnetcdf $LIBS"
+      EXTRA_INCLUDES="-I$with_netcdf/include $EXTRA_INCLUDES"
+    else
+      LIBS="-L$with_netcdf -lnetcdf $LIBS"
+      EXTRA_INCLUDES="-I$with_netcdf $EXTRA_INCLUDES"
+    fi
 
-  LIBS="-L$HDF5_LIB_DIR $HDF5_LIB_NAME $ORIG_LIBS"
+    echo "using libnetcdf from $with_netcdf"
 
-  if test -r "$with_hdf5/hdf5/hdf5.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5/hdf5"
-  elif test -r "$with_hdf5/include/hdf5/hdf5.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5/include/hdf5"
-  elif test -r "$with_hdf5/include/hdf5.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5/include"
-  elif test -r "$with_hdf5/hdf.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5"
+  else
+    echo "libnetcdf not found in "$with_netcdf" - netCDF support disabled"
   fi
 
-  HAVE_HDF5=yes
 fi
 
-HAVE_HDF5=$HAVE_HDF5
 
-HDF5_INCLUDE=$HDF5_INCLUDE
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    ncdump=$NETCDF_ROOT"/bin/ncdump"
+    nc_config=""
+
+        if { test -x "$ncdump"; }; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking libnetcdf version with $ncdump" >&5
+$as_echo_n "checking libnetcdf version with $ncdump... " >&6; }
+      netcdf_version=`$ncdump 2>&1 | grep "netcdf library version" | awk '{gsub(/"/,"");print $4}'`
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: got $netcdf_version" >&5
+$as_echo "got $netcdf_version" >&6; }
+      if test "$netcdf_version" != "" -a "${netcdf_version:0:1}" == "4" ; then
+          nc_config=$NETCDF_ROOT"/bin/nc-config"
+      fi
+    fi
 
+        if { test -x "$nc_config"; }; then
+      echo "checking libnetcdf config with $nc_config"
 
-if test "$HAVE_HDF5" != "no" ; then
-  OPT_GDAL_FORMATS="hdf5 $OPT_GDAL_FORMATS"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for netcdf-4 (and HDF5) support in libnetcdf" >&5
+$as_echo_n "checking for netcdf-4 (and HDF5) support in libnetcdf... " >&6; }
+        if test "x$($nc_config --has-nc4)" = "xyes"; then :
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+          NETCDF_HAS_NC4=yes
+        else
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+          NETCDF_HAS_NC4=no
+        fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HDF4 support in libnetcdf" >&5
+$as_echo_n "checking for HDF4 support in libnetcdf... " >&6; }
+        if test "x$($nc_config --has-hdf4)" = "xyes"; then :
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+          NETCDF_HAS_HDF4=yes
+        else
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+          NETCDF_HAS_HDF4=no
+        fi
+
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: ncdump and/or nc-config not found, skipping netcdf-4 tests" >&5
+$as_echo "ncdump and/or nc-config not found, skipping netcdf-4 tests" >&6; }
+      NETCDF_HAS_NC4=no
+      NETCDF_HAS_HDF4=no
+    fi
+fi
+
+
+NETCDF_SETTING=$NETCDF_SETTING
+
+NETCDF_ROOT=$NETCDF_ROOT
+
+NETCDF_HAS_NC4=$NETCDF_HAS_NC4
+
+NETCDF_HAS_HDF4=$NETCDF_HAS_HDF4
+
+
+if test "$NETCDF_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="netcdf $OPT_GDAL_FORMATS"
 fi
 
 
 
+
 # Check whether --with-jasper was given.
 if test "${with_jasper+set}" = set; then :
   withval=$with_jasper;
@@ -19248,7 +21309,7 @@ elif test "$with_jasper" = "yes" -o "$with_jasper" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpc_decode in -ljasper" >&5
 $as_echo_n "checking for jpc_decode in -ljasper... " >&6; }
-if test "${ac_cv_lib_jasper_jpc_decode+set}" = set; then :
+if ${ac_cv_lib_jasper_jpc_decode+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19282,7 +21343,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jasper_jpc_decode" >&5
 $as_echo "$ac_cv_lib_jasper_jpc_decode" >&6; }
-if test "x$ac_cv_lib_jasper_jpc_decode" = x""yes; then :
+if test "x$ac_cv_lib_jasper_jpc_decode" = xyes; then :
   HAVE_JASPER=yes
 else
   HAVE_JASPER=no
@@ -19290,7 +21351,7 @@ fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jp2_decode in -ljasper" >&5
 $as_echo_n "checking for jp2_decode in -ljasper... " >&6; }
-if test "${ac_cv_lib_jasper_jp2_decode+set}" = set; then :
+if ${ac_cv_lib_jasper_jp2_decode+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19324,7 +21385,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jasper_jp2_decode" >&5
 $as_echo "$ac_cv_lib_jasper_jp2_decode" >&6; }
-if test "x$ac_cv_lib_jasper_jp2_decode" = x""yes; then :
+if test "x$ac_cv_lib_jasper_jp2_decode" = xyes; then :
   HAVE_JASPER=yes
 else
   HAVE_JASPER=no
@@ -19332,7 +21393,7 @@ fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pgx_decode in -ljasper" >&5
 $as_echo_n "checking for pgx_decode in -ljasper... " >&6; }
-if test "${ac_cv_lib_jasper_pgx_decode+set}" = set; then :
+if ${ac_cv_lib_jasper_pgx_decode+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19366,7 +21427,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jasper_pgx_decode" >&5
 $as_echo "$ac_cv_lib_jasper_pgx_decode" >&6; }
-if test "x$ac_cv_lib_jasper_pgx_decode" = x""yes; then :
+if test "x$ac_cv_lib_jasper_pgx_decode" = xyes; then :
   HAVE_JASPER=yes
 else
   HAVE_JASPER=no
@@ -19392,7 +21453,7 @@ if test "$HAVE_JASPER" != "no" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jp2_encode_uuid in -ljasper" >&5
 $as_echo_n "checking for jp2_encode_uuid in -ljasper... " >&6; }
-if test "${ac_cv_lib_jasper_jp2_encode_uuid+set}" = set; then :
+if ${ac_cv_lib_jasper_jp2_encode_uuid+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19426,7 +21487,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jasper_jp2_encode_uuid" >&5
 $as_echo "$ac_cv_lib_jasper_jp2_encode_uuid" >&6; }
-if test "x$ac_cv_lib_jasper_jp2_encode_uuid" = x""yes; then :
+if test "x$ac_cv_lib_jasper_jp2_encode_uuid" = xyes; then :
   HAVE_JASPER_UUID=yes
 else
   HAVE_JASPER_UUID=no
@@ -19468,7 +21529,7 @@ elif test "$with_openjpeg" = "yes" -o "$with_openjpeg" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for opj_decode_tile_data in -lopenjpeg" >&5
 $as_echo_n "checking for opj_decode_tile_data in -lopenjpeg... " >&6; }
-if test "${ac_cv_lib_openjpeg_opj_decode_tile_data+set}" = set; then :
+if ${ac_cv_lib_openjpeg_opj_decode_tile_data+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19502,7 +21563,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_openjpeg_opj_decode_tile_data" >&5
 $as_echo "$ac_cv_lib_openjpeg_opj_decode_tile_data" >&6; }
-if test "x$ac_cv_lib_openjpeg_opj_decode_tile_data" = x""yes; then :
+if test "x$ac_cv_lib_openjpeg_opj_decode_tile_data" = xyes; then :
   HAVE_OPENJPEG=yes
 else
   HAVE_OPENJPEG=no
@@ -19511,7 +21572,7 @@ fi
   for ac_header in openjpeg.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "openjpeg.h" "ac_cv_header_openjpeg_h" "$ac_includes_default"
-if test "x$ac_cv_header_openjpeg_h" = x""yes; then :
+if test "x$ac_cv_header_openjpeg_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_OPENJPEG_H 1
 _ACEOF
@@ -19544,7 +21605,7 @@ else
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for opj_decode_tile_data in -lopenjpeg" >&5
 $as_echo_n "checking for opj_decode_tile_data in -lopenjpeg... " >&6; }
-if test "${ac_cv_lib_openjpeg_opj_decode_tile_data+set}" = set; then :
+if ${ac_cv_lib_openjpeg_opj_decode_tile_data+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19578,7 +21639,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_openjpeg_opj_decode_tile_data" >&5
 $as_echo "$ac_cv_lib_openjpeg_opj_decode_tile_data" >&6; }
-if test "x$ac_cv_lib_openjpeg_opj_decode_tile_data" = x""yes; then :
+if test "x$ac_cv_lib_openjpeg_opj_decode_tile_data" = xyes; then :
   HAVE_OPENJPEG=yes
 else
   HAVE_OPENJPEG=no
@@ -19600,6 +21661,103 @@ HAVE_OPENJPEG=$HAVE_OPENJPEG
 
 
 
+
+
+# Check whether --with-fgdb was given.
+if test "${with_fgdb+set}" = set; then :
+  withval=$with_fgdb;
+fi
+
+
+if test "$with_fgdb" = "no" ; then
+
+  FGDB_ENABLED=no
+
+  echo "FGDB support disabled."
+
+elif test "$with_fgdb" = "yes" -o "$with_fgdb" = "" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGeodatabase in -lFileGDBAPI" >&5
+$as_echo_n "checking for OpenGeodatabase in -lFileGDBAPI... " >&6; }
+if ${ac_cv_lib_FileGDBAPI_OpenGeodatabase+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lFileGDBAPI -lFileGDBAPI -lfgdblinuxrtl $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 OpenGeodatabase ();
+int
+main ()
+{
+return OpenGeodatabase ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_FileGDBAPI_OpenGeodatabase=yes
+else
+  ac_cv_lib_FileGDBAPI_OpenGeodatabase=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_FileGDBAPI_OpenGeodatabase" >&5
+$as_echo "$ac_cv_lib_FileGDBAPI_OpenGeodatabase" >&6; }
+if test "x$ac_cv_lib_FileGDBAPI_OpenGeodatabase" = xyes; then :
+  FGDB_ENABLED=yes
+else
+  FGDB_ENABLED=no
+fi
+
+
+  if test "$FGDB_ENABLED" = "yes" ; then
+    LIBS="-lFileGDBAPI -lfgdblinuxrtl"
+  fi
+
+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
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdblinuxrtl"
+  else
+    as_fn_error $? "not found." "$LINENO" 5
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FileGDBAPI.h in $with_fgdb/include" >&5
+$as_echo_n "checking for FileGDBAPI.h in $with_fgdb/include... " >&6; }
+  if test -r $with_fgdb/include/FileGDBAPI.h ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found." >&5
+$as_echo "found." >&6; }
+    FGDB_INC="-I$with_fgdb/include"
+  else
+    as_fn_error $? "not found." "$LINENO" 5
+  fi
+
+fi
+
+FGDB_ENABLED=$FGDB_ENABLED
+
+FGDB_LIB=$FGDB_LIB
+
+FGDB_INC=$FGDB_INC
+
+
+
+
 # Check whether --with-ecw was given.
 if test "${with_ecw+set}" = set; then :
   withval=$with_ecw;
@@ -19622,7 +21780,7 @@ elif test "$with_ecw" = "yes" -o "$with_ecw" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NCScbmOpenFileView in -lNCSEcw" >&5
 $as_echo_n "checking for NCScbmOpenFileView in -lNCSEcw... " >&6; }
-if test "${ac_cv_lib_NCSEcw_NCScbmOpenFileView+set}" = set; then :
+if ${ac_cv_lib_NCSEcw_NCScbmOpenFileView+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19656,7 +21814,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_NCSEcw_NCScbmOpenFileView" >&5
 $as_echo "$ac_cv_lib_NCSEcw_NCScbmOpenFileView" >&6; }
-if test "x$ac_cv_lib_NCSEcw_NCScbmOpenFileView" = x""yes; then :
+if test "x$ac_cv_lib_NCSEcw_NCScbmOpenFileView" = xyes; then :
   ECW_SETTING=yes
 else
   ECW_SETTING=no
@@ -19664,13 +21822,13 @@ fi
 
 
   if test "$ECW_SETTING" = "yes" ; then
-    LIBS="-lNCSEcw -lNCSCnet -lNCSUtil $LIBS"
+    LIBS="-lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil $LIBS"
   fi
 
   if test "$ECW_SETTING" = "no" ; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NCScbmOpenFileView in -lecwj2" >&5
 $as_echo_n "checking for NCScbmOpenFileView in -lecwj2... " >&6; }
-if test "${ac_cv_lib_ecwj2_NCScbmOpenFileView+set}" = set; then :
+if ${ac_cv_lib_ecwj2_NCScbmOpenFileView+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -19704,7 +21862,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ecwj2_NCScbmOpenFileView" >&5
 $as_echo "$ac_cv_lib_ecwj2_NCScbmOpenFileView" >&6; }
-if test "x$ac_cv_lib_ecwj2_NCScbmOpenFileView" = x""yes; then :
+if test "x$ac_cv_lib_ecwj2_NCScbmOpenFileView" = xyes; then :
   ECW_SETTING=yes
 else
   ECW_SETTING=no
@@ -19721,15 +21879,15 @@ else
 $as_echo_n "checking for libNCSEcw.so or libecwj2... " >&6; }
   ECW_SETTING=yes
   if test -r $with_ecw/lib/libNCSCnet.so -o -r $with_ecw/lib/libNCSCnet.dylib ; then
-    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSCnet -lNCSUtil $LIBS"
+    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil $LIBS"
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $with_ecw/lib." >&5
 $as_echo "found in $with_ecw/lib." >&6; }
   elif test -r $with_ecw/lib/libNCSCNet.so -o -r $with_ecw/lib/libNCSCNet.dylib ; then
-    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSCNet -lNCSUtil $LIBS"
+    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCNet -lNCSUtil $LIBS"
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $with_ecw/lib." >&5
 $as_echo "found in $with_ecw/lib." >&6; }
   elif test -r $with_ecw/bin/libNCSEcw.so -o -r $with_ecw/bin/libNCSEcw.dylib ; then
-    LIBS="-L$with_ecw/bin -lNCSEcw -lNCSCnet -lNCSUtil $LIBS"
+    LIBS="-L$with_ecw/bin -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil $LIBS"
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $with_ecw/bin." >&5
 $as_echo "found in $with_ecw/bin." >&6; }
   elif test -r $with_ecw/lib/libecwj2.dylib ; then
@@ -19894,7 +22052,8 @@ $as_echo_n "checking for MrSID JPEG2000 support... " >&6; }
         elif test -r "$with_mrsid/3rd-party/$_LIBPART/liblt_kakadu.a" ; then
           with_jp2mrsid=yes
           MRSID_KAKADU_LIB=-llt_kakadu
-        elif test -L "$with_mrsid/lib/libltidsdk.so"; then # v8+ .so has kdu
+        elif test -e "$with_mrsid/lib/libltidsdk.so" \
+               -o -e "$with_mrsid/lib/libltidsdk.dylib"; then # v8+ .so has kdu
           with_jp2mrsid=yes
         elif test x"$with_jp2mrsid" = x"yes" ; then
           as_fn_error $? "MrSID JPEG2000 support requested, but libltikdu.a not found." "$LINENO" 5
@@ -20449,7 +22608,7 @@ if test "$with_mysql" = "yes" ; then
 set dummy mysql_config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_MYSQL_CONFIG+set}" = set; then :
+if ${ac_cv_path_MYSQL_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $MYSQL_CONFIG in
@@ -20667,8 +22826,8 @@ fi
         saved_CPPFLAGS="$CPPFLAGS"
         CPPFLAGS="$CPPFLAGS -I$xerces_include_dir -I$xerces_include_dir2"
 
-        saved_LDFLAGS="$LDFLAGS"
-        LDFLAGS="$LDFLAGS $xerces_lib_flags"
+        saved_LIBS="$LIBS"
+        LIBS="$LIBS $xerces_lib_flags"
 
                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Xerces C++ Parser headers in $xerces_include_dir and $xerces_include_dir2" >&5
 $as_echo_n "checking for Xerces C++ Parser headers in $xerces_include_dir and $xerces_include_dir2... " >&6; }
@@ -20776,7 +22935,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
         fi
 
         CPPFLAGS="$saved_CPPFLAGS"
-        LDFLAGS="$saved_LDFLAGS"
+        LIBS="$saved_LIBS"
     fi
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Xerces C++ Parser" >&5
@@ -20790,6 +22949,7 @@ $as_echo_n "checking for Xerces C++ Parser... " >&6; }
 
             HAVE_XERCES="yes"
         else
+            XERCES_CFLAGS=""
             HAVE_XERCES="no"
         fi
 
@@ -20963,7 +23123,7 @@ fi
         if test -n "$expat_lib_flags"; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML_ParserCreate in -lexpat" >&5
 $as_echo_n "checking for XML_ParserCreate in -lexpat... " >&6; }
-if test "${ac_cv_lib_expat_XML_ParserCreate+set}" = set; then :
+if ${ac_cv_lib_expat_XML_ParserCreate+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -20997,7 +23157,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_expat_XML_ParserCreate" >&5
 $as_echo "$ac_cv_lib_expat_XML_ParserCreate" >&6; }
-if test "x$ac_cv_lib_expat_XML_ParserCreate" = x""yes; then :
+if test "x$ac_cv_lib_expat_XML_ParserCreate" = xyes; then :
   run_expat_test="yes"
 else
   run_expat_test="no"
@@ -21007,7 +23167,7 @@ fi
             if test "$expat_prefix" = "/usr"; then
                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML_ParserCreate in -lexpat" >&5
 $as_echo_n "checking for XML_ParserCreate in -lexpat... " >&6; }
-if test "${ac_cv_lib_expat_XML_ParserCreate+set}" = set; then :
+if ${ac_cv_lib_expat_XML_ParserCreate+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -21041,7 +23201,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_expat_XML_ParserCreate" >&5
 $as_echo "$ac_cv_lib_expat_XML_ParserCreate" >&6; }
-if test "x$ac_cv_lib_expat_XML_ParserCreate" = x""yes; then :
+if test "x$ac_cv_lib_expat_XML_ParserCreate" = xyes; then :
   run_expat_test="yes"
 else
   run_expat_test="no"
@@ -21053,7 +23213,7 @@ fi
             else
                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML_ParserCreate in -lexpat" >&5
 $as_echo_n "checking for XML_ParserCreate in -lexpat... " >&6; }
-if test "${ac_cv_lib_expat_XML_ParserCreate+set}" = set; then :
+if ${ac_cv_lib_expat_XML_ParserCreate+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -21087,7 +23247,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_expat_XML_ParserCreate" >&5
 $as_echo "$ac_cv_lib_expat_XML_ParserCreate" >&6; }
-if test "x$ac_cv_lib_expat_XML_ParserCreate" = x""yes; then :
+if test "x$ac_cv_lib_expat_XML_ParserCreate" = xyes; then :
   run_expat_test="yes"
 else
   run_expat_test="no"
@@ -21558,7 +23718,7 @@ elif test "$with_odbc" = "yes" -o "$with_odbc" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLConnect in -lodbc" >&5
 $as_echo_n "checking for SQLConnect in -lodbc... " >&6; }
-if test "${ac_cv_lib_odbc_SQLConnect+set}" = set; then :
+if ${ac_cv_lib_odbc_SQLConnect+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -21592,7 +23752,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLConnect" >&5
 $as_echo "$ac_cv_lib_odbc_SQLConnect" >&6; }
-if test "x$ac_cv_lib_odbc_SQLConnect" = x""yes; then :
+if test "x$ac_cv_lib_odbc_SQLConnect" = xyes; then :
   ODBC_SETTING=yes
 else
   ODBC_SETTING=no
@@ -21600,7 +23760,7 @@ fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLInstallDriverEx in -lodbcinst" >&5
 $as_echo_n "checking for SQLInstallDriverEx in -lodbcinst... " >&6; }
-if test "${ac_cv_lib_odbcinst_SQLInstallDriverEx+set}" = set; then :
+if ${ac_cv_lib_odbcinst_SQLInstallDriverEx+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -21634,7 +23794,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbcinst_SQLInstallDriverEx" >&5
 $as_echo "$ac_cv_lib_odbcinst_SQLInstallDriverEx" >&6; }
-if test "x$ac_cv_lib_odbcinst_SQLInstallDriverEx" = x""yes; then :
+if test "x$ac_cv_lib_odbcinst_SQLInstallDriverEx" = xyes; then :
   ODBC_SETTING=yes
 else
   ODBC_SETTING=no
@@ -22034,7 +24194,7 @@ else
     DODS_INC="-I$with_dods_root/include -I$with_dods_root/include/libdap -I$with_dods_root/include/dap"
     DODS_BIN=$with_dods_root/bin
 
-rm -f islibdappre310.*
+rm -f islibdappost310.*
 echo '#include "Connect.h"' > islibdappost310.cpp
 echo 'int main(int argc, char** argv) { return 0; } ' >> islibdappost310.cpp
 if test -z "`${CXX} islibdappost310.cpp -c ${DODS_INC} 2>&1`" ; then
@@ -22061,7 +24221,7 @@ $as_echo "libdap >= 3.9" >&6; }
     rm -f islibdappre39.*
 
 fi
-rm -f islibdappre310.*
+rm -f islibdappost310.*
 
 
         if test -x $DODS_BIN/opendap-config ; then
@@ -22119,7 +24279,7 @@ else
 set dummy curl-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_LIBCURL_CONFIG+set}" = set; then :
+if ${ac_cv_path_LIBCURL_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $LIBCURL_CONFIG in
@@ -22168,11 +24328,11 @@ $as_echo "        found libcurl version $CURL_VER" >&6; }
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_global_init in -lcurl" >&5
 $as_echo_n "checking for curl_global_init in -lcurl... " >&6; }
-if test "${ac_cv_lib_curl_curl_global_init+set}" = set; then :
+if ${ac_cv_lib_curl_curl_global_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcurl  $LIBS"
+LIBS="-lcurl `$LIBCURL_CONFIG --libs` $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -22202,7 +24362,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_global_init" >&5
 $as_echo "$ac_cv_lib_curl_curl_global_init" >&6; }
-if test "x$ac_cv_lib_curl_curl_global_init" = x""yes; then :
+if test "x$ac_cv_lib_curl_curl_global_init" = xyes; then :
   CURL_SETTING=yes
 else
   CURL_SETTING=no
@@ -22235,14 +24395,33 @@ fi
 
 
 HAVE_SPATIALITE=no
+SPATIALITE_AMALGAMATION=no
 
 if test -z "$with_spatialite" -o "$with_spatialite" = "no"; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
 $as_echo "disabled" >&6; }
 elif test "$with_spatialite" = "yes"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_init in -lspatialite" >&5
+    for ac_header in sqlite3.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default"
+if test "x$ac_cv_header_sqlite3_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SQLITE3_H 1
+_ACEOF
+
+fi
+
+done
+
+    if test "$ac_cv_header_sqlite3_h" = "yes"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite.h in /usr/include or /usr/local/include" >&5
+$as_echo_n "checking for spatialite.h in /usr/include or /usr/local/include... " >&6; }
+        if test -f "/usr/include/spatialite.h" -o -f "/usr/local/include/spatialite.h"; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_init in -lspatialite" >&5
 $as_echo_n "checking for spatialite_init in -lspatialite... " >&6; }
-if test "${ac_cv_lib_spatialite_spatialite_init+set}" = set; then :
+if ${ac_cv_lib_spatialite_spatialite_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22276,21 +24455,26 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_spatialite_spatialite_init" >&5
 $as_echo "$ac_cv_lib_spatialite_spatialite_init" >&6; }
-if test "x$ac_cv_lib_spatialite_spatialite_init" = x""yes; then :
+if test "x$ac_cv_lib_spatialite_spatialite_init" = xyes; then :
   SPATIALITE_INIT_FOUND=yes
 else
   SPATIALITE_INIT_FOUND=no
 fi
 
-    if test "$SPATIALITE_INIT_FOUND" = "yes"; then
-        HAVE_SPATIALITE=yes
-        LIBS="$LIBS -lspatialite"
-        HAVE_SQLITE3=yes
+            if test "$SPATIALITE_INIT_FOUND" = "yes"; then
+                HAVE_SPATIALITE=yes
+                LIBS="$LIBS -lspatialite"
+                HAVE_SQLITE3=yes
+            fi
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found : spatialite support disabled" >&5
+$as_echo "not found : spatialite support disabled" >&6; }
+        fi
     fi
 else
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spatialite_init in -lspatialite" >&5
 $as_echo_n "checking for spatialite_init in -lspatialite... " >&6; }
-if test "${ac_cv_lib_spatialite_spatialite_init+set}" = set; then :
+if ${ac_cv_lib_spatialite_spatialite_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22324,7 +24508,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_spatialite_spatialite_init" >&5
 $as_echo "$ac_cv_lib_spatialite_spatialite_init" >&6; }
-if test "x$ac_cv_lib_spatialite_spatialite_init" = x""yes; then :
+if test "x$ac_cv_lib_spatialite_spatialite_init" = xyes; then :
   SPATIALITE_INIT_FOUND=yes
 else
   SPATIALITE_INIT_FOUND=no
@@ -22337,14 +24521,38 @@ fi
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
 $as_echo "enabled" >&6; }
         HAVE_SPATIALITE=yes
+        SPATIALITE_AMALGAMATION=yes
 
-        # SpatiaLite availability implies SQLite availability
+        # SpatiaLite amalgamation availability implies SQLite availability
         # Caution : don't include the include/spatialite subdir in the include dir
         # 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"
         HAVE_SQLITE3=yes
+
+    elif test -f "$with_spatialite/include/spatialite.h" -a \
+        "$SPATIALITE_INIT_FOUND" = "yes"; then
+        for ac_header in sqlite3.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default"
+if test "x$ac_cv_header_sqlite3_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SQLITE3_H 1
+_ACEOF
+
+fi
+
+done
+
+        if test "$ac_cv_header_sqlite3_h" = "yes"; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
+$as_echo "enabled" >&6; }
+            SPATIALITE_INC="-I$with_spatialite/include"
+            HAVE_SPATIALITE=yes
+            LIBS="$LIBS -L$with_spatialite/lib -lspatialite"
+            HAVE_SQLITE3=yes
+        fi
     else
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
 $as_echo "disabled" >&6; }
@@ -22353,6 +24561,10 @@ fi
 
 HAVE_SPATIALITE=$HAVE_SPATIALITE
 
+SPATIALITE_INC=$SPATIALITE_INC
+
+SPATIALITE_AMALGAMATION=$SPATIALITE_AMALGAMATION
+
 
 
 if test "${HAVE_SPATIALITE}" = "no" ; then
@@ -22407,7 +24619,7 @@ fi
             LIBS=""
             { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5
 $as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; }
-if test "${ac_cv_lib_sqlite3_sqlite3_open+set}" = set; then :
+if ${ac_cv_lib_sqlite3_sqlite3_open+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22441,7 +24653,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5
 $as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; }
-if test "x$ac_cv_lib_sqlite3_sqlite3_open" = x""yes; then :
+if test "x$ac_cv_lib_sqlite3_sqlite3_open" = xyes; then :
   LIB_SQLITE3_FOUND=yes
 else
   LIB_SQLITE3_FOUND=no
@@ -22464,7 +24676,7 @@ fi
                     LIBS=""
                     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5
 $as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; }
-if test "${ac_cv_lib_sqlite3_sqlite3_open+set}" = set; then :
+if ${ac_cv_lib_sqlite3_sqlite3_open+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22498,7 +24710,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5
 $as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; }
-if test "x$ac_cv_lib_sqlite3_sqlite3_open" = x""yes; then :
+if test "x$ac_cv_lib_sqlite3_sqlite3_open" = xyes; then :
   LIB_SQLITE3_FOUND=yes
 else
   LIB_SQLITE3_FOUND=no
@@ -22513,7 +24725,7 @@ fi
                         LIBS=""
                         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5
 $as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; }
-if test "${ac_cv_lib_sqlite3_sqlite3_open+set}" = set; then :
+if ${ac_cv_lib_sqlite3_sqlite3_open+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22547,7 +24759,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5
 $as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; }
-if test "x$ac_cv_lib_sqlite3_sqlite3_open" = x""yes; then :
+if test "x$ac_cv_lib_sqlite3_sqlite3_open" = xyes; then :
   LIB_SQLITE3_FOUND=yes
 else
   LIB_SQLITE3_FOUND=no
@@ -22746,7 +24958,7 @@ else
     LIBS="${IDB_LIB} -ldl -lcrypt"
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ifx_srvinfo in -lifsql" >&5
 $as_echo_n "checking for ifx_srvinfo in -lifsql... " >&6; }
-if test "${ac_cv_lib_ifsql_ifx_srvinfo+set}" = set; then :
+if ${ac_cv_lib_ifsql_ifx_srvinfo+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22780,7 +24992,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ifsql_ifx_srvinfo" >&5
 $as_echo "$ac_cv_lib_ifsql_ifx_srvinfo" >&6; }
-if test "x$ac_cv_lib_ifsql_ifx_srvinfo" = x""yes; then :
+if test "x$ac_cv_lib_ifsql_ifx_srvinfo" = xyes; then :
   HAVE_IDB=yes
 else
   HAVE_IDB=no
@@ -22836,7 +25048,7 @@ if test "$with_sde" = "yes" ; then
   as_ac_Lib=`$as_echo "ac_cv_lib_sde$SDE_VERSION''_SE_connection_create" | $as_tr_sh`
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SE_connection_create in -lsde$SDE_VERSION" >&5
 $as_echo_n "checking for SE_connection_create in -lsde$SDE_VERSION... " >&6; }
-if eval "test \"\${$as_ac_Lib+set}\"" = set; then :
+if eval \${$as_ac_Lib+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22880,7 +25092,7 @@ fi
       SDE_LIB="-lsde$SDE_VERSION -lpe$SDE_VERSION -lsg$SDE_VERSION"
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
 $as_echo_n "checking for main in -lpthread... " >&6; }
-if test "${ac_cv_lib_pthread_main+set}" = set; then :
+if ${ac_cv_lib_pthread_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22908,13 +25120,13 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
 $as_echo "$ac_cv_lib_pthread_main" >&6; }
-if test "x$ac_cv_lib_pthread_main" = x""yes; then :
+if test "x$ac_cv_lib_pthread_main" = xyes; then :
   SDE_LIB="$SDE_LIB -lpthread"
 fi
 
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
 $as_echo_n "checking for main in -lsocket... " >&6; }
-if test "${ac_cv_lib_socket_main+set}" = set; then :
+if ${ac_cv_lib_socket_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22942,13 +25154,13 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
 $as_echo "$ac_cv_lib_socket_main" >&6; }
-if test "x$ac_cv_lib_socket_main" = x""yes; then :
+if test "x$ac_cv_lib_socket_main" = xyes; then :
   SDE_LIB="$SDE_LIB -lsocket"
 fi
 
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5
 $as_echo_n "checking for main in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_main+set}" = set; then :
+if ${ac_cv_lib_dl_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22976,7 +25188,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5
 $as_echo "$ac_cv_lib_dl_main" >&6; }
-if test "x$ac_cv_lib_dl_main" = x""yes; then :
+if test "x$ac_cv_lib_dl_main" = xyes; then :
   SDE_LIB="$SDE_LIB -ldl"
 fi
 
@@ -23008,7 +25220,7 @@ elif test -n "$with_sde" -a "$with_sde" != "no" ; then
       SDE_LIB="-L$SDE_LIBDIR -lsde$SDE_VERSION -lpe$SDE_VERSION -lsg$SDE_VERSION"
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
 $as_echo_n "checking for main in -lpthread... " >&6; }
-if test "${ac_cv_lib_pthread_main+set}" = set; then :
+if ${ac_cv_lib_pthread_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23036,13 +25248,13 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
 $as_echo "$ac_cv_lib_pthread_main" >&6; }
-if test "x$ac_cv_lib_pthread_main" = x""yes; then :
+if test "x$ac_cv_lib_pthread_main" = xyes; then :
   SDE_LIB="$SDE_LIB -lpthread"
 fi
 
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
 $as_echo_n "checking for main in -lsocket... " >&6; }
-if test "${ac_cv_lib_socket_main+set}" = set; then :
+if ${ac_cv_lib_socket_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23070,13 +25282,13 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
 $as_echo "$ac_cv_lib_socket_main" >&6; }
-if test "x$ac_cv_lib_socket_main" = x""yes; then :
+if test "x$ac_cv_lib_socket_main" = xyes; then :
   SDE_LIB="$SDE_LIB -lsocket"
 fi
 
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5
 $as_echo_n "checking for main in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_main+set}" = set; then :
+if ${ac_cv_lib_dl_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23104,7 +25316,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5
 $as_echo "$ac_cv_lib_dl_main" >&6; }
-if test "x$ac_cv_lib_dl_main" = x""yes; then :
+if test "x$ac_cv_lib_dl_main" = xyes; then :
   SDE_LIB="$SDE_LIB -ldl"
 fi
 
@@ -23112,6 +25324,12 @@ fi
       as_fn_error $? "\"Could not find sdetype.h or libsde$SDE_VERSION.a/libsde$SDE_VERSION.so in $SDE_DIR.\"" "$LINENO" 5
   fi
 
+  if test "`arch`" = "x86_64" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result:         Adding -DSDE64 for 64bit platform." >&5
+$as_echo "        Adding -DSDE64 for 64bit platform." >&6; }
+    SDE_INC="$SDE_INC -DSDE64"
+  fi
+
   SDE_ENABLED=yes
   OPT_GDAL_FORMATS="sde $OPT_GDAL_FORMATS"
   { $as_echo "$as_me:${as_lineno-$LINENO}: result:         using ESRI SDE from $SDE_DIR." >&5
@@ -23167,23 +25385,142 @@ fi
 
 
 
-# Check whether --with-epsilon was given.
-if test "${with_epsilon+set}" = set; then :
-  withval=$with_epsilon;
+# Check whether --with-epsilon was given.
+if test "${with_epsilon+set}" = set; then :
+  withval=$with_epsilon;
+fi
+
+
+EPSILON_SETTING=no
+
+if test "$with_epsilon" = "yes" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for eps_read_block_header in -lepsilon" >&5
+$as_echo_n "checking for eps_read_block_header in -lepsilon... " >&6; }
+if ${ac_cv_lib_epsilon_eps_read_block_header+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lepsilon  $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 eps_read_block_header ();
+int
+main ()
+{
+return eps_read_block_header ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_epsilon_eps_read_block_header=yes
+else
+  ac_cv_lib_epsilon_eps_read_block_header=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_epsilon_eps_read_block_header" >&5
+$as_echo "$ac_cv_lib_epsilon_eps_read_block_header" >&6; }
+if test "x$ac_cv_lib_epsilon_eps_read_block_header" = xyes; then :
+  EPSILON_SETTING=yes
+else
+  EPSILON_SETTING=no
+fi
+
+
+  if test "$EPSILON_SETTING" = "yes" ; then
+    LIBS="-lepsilon $LIBS"
+  else
+    echo "libepsilon not found - EPSILON support disabled"
+  fi
+
+elif test "$with_epsilon" != "no" -a "$with_epsilon" != ""; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for eps_read_block_header in -lepsilon" >&5
+$as_echo_n "checking for eps_read_block_header in -lepsilon... " >&6; }
+if ${ac_cv_lib_epsilon_eps_read_block_header+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lepsilon -L$with_epsilon/lib -lepsilon $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 eps_read_block_header ();
+int
+main ()
+{
+return eps_read_block_header ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_epsilon_eps_read_block_header=yes
+else
+  ac_cv_lib_epsilon_eps_read_block_header=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_epsilon_eps_read_block_header" >&5
+$as_echo "$ac_cv_lib_epsilon_eps_read_block_header" >&6; }
+if test "x$ac_cv_lib_epsilon_eps_read_block_header" = xyes; then :
+  EPSILON_SETTING=yes
+else
+  EPSILON_SETTING=no
+fi
+
+
+  if test "$EPSILON_SETTING" = "yes" ; then
+    LIBS="-L$with_epsilon/lib -lepsilon $LIBS"
+    EXTRA_INCLUDES="-I$with_epsilon/include $EXTRA_INCLUDES"
+  else
+    echo "libepsilon not found - EPSILON support disabled"
+  fi
+
+fi
+
+if test "$EPSILON_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="epsilon $OPT_GDAL_FORMATS"
+fi
+
+
+
+# Check whether --with-webp was given.
+if test "${with_webp+set}" = set; then :
+  withval=$with_webp;
 fi
 
 
-EPSILON_SETTING=no
+WEBP_SETTING=no
 
-if test "$with_epsilon" = "yes" ; then
+if test "$with_webp" = "yes" ; then
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for eps_read_block_header in -lepsilon" >&5
-$as_echo_n "checking for eps_read_block_header in -lepsilon... " >&6; }
-if test "${ac_cv_lib_epsilon_eps_read_block_header+set}" = set; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebPDecodeRGB in -lwebp" >&5
+$as_echo_n "checking for WebPDecodeRGB in -lwebp... " >&6; }
+if ${ac_cv_lib_webp_WebPDecodeRGB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lepsilon  $LIBS"
+LIBS="-lwebp  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -23193,48 +25530,48 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char eps_read_block_header ();
+char WebPDecodeRGB ();
 int
 main ()
 {
-return eps_read_block_header ();
+return WebPDecodeRGB ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_epsilon_eps_read_block_header=yes
+  ac_cv_lib_webp_WebPDecodeRGB=yes
 else
-  ac_cv_lib_epsilon_eps_read_block_header=no
+  ac_cv_lib_webp_WebPDecodeRGB=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_epsilon_eps_read_block_header" >&5
-$as_echo "$ac_cv_lib_epsilon_eps_read_block_header" >&6; }
-if test "x$ac_cv_lib_epsilon_eps_read_block_header" = x""yes; then :
-  EPSILON_SETTING=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_webp_WebPDecodeRGB" >&5
+$as_echo "$ac_cv_lib_webp_WebPDecodeRGB" >&6; }
+if test "x$ac_cv_lib_webp_WebPDecodeRGB" = xyes; then :
+  WEBP_SETTING=yes
 else
-  EPSILON_SETTING=no
+  WEBP_SETTING=no
 fi
 
 
-  if test "$EPSILON_SETTING" = "yes" ; then
-    LIBS="-lepsilon $LIBS"
+  if test "$WEBP_SETTING" = "yes" ; then
+    LIBS="-lwebp $LIBS"
   else
-    echo "libepsilon not found - EPSILON support disabled"
+    echo "libwebp not found - WEBP support disabled"
   fi
 
-elif test "$with_epsilon" != "no" -a "$with_epsilon" != ""; then
+elif test "$with_webp" != "no" -a "$with_webp" != ""; then
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for eps_read_block_header in -lepsilon" >&5
-$as_echo_n "checking for eps_read_block_header in -lepsilon... " >&6; }
-if test "${ac_cv_lib_epsilon_eps_read_block_header+set}" = set; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebPDecodeRGB in -lwebp" >&5
+$as_echo_n "checking for WebPDecodeRGB in -lwebp... " >&6; }
+if ${ac_cv_lib_webp_WebPDecodeRGB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lepsilon -L$with_epsilon/lib -lepsilon $LIBS"
+LIBS="-lwebp -L$with_webp/lib -lwebp $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -23244,44 +25581,44 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char eps_read_block_header ();
+char WebPDecodeRGB ();
 int
 main ()
 {
-return eps_read_block_header ();
+return WebPDecodeRGB ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_epsilon_eps_read_block_header=yes
+  ac_cv_lib_webp_WebPDecodeRGB=yes
 else
-  ac_cv_lib_epsilon_eps_read_block_header=no
+  ac_cv_lib_webp_WebPDecodeRGB=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_epsilon_eps_read_block_header" >&5
-$as_echo "$ac_cv_lib_epsilon_eps_read_block_header" >&6; }
-if test "x$ac_cv_lib_epsilon_eps_read_block_header" = x""yes; then :
-  EPSILON_SETTING=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_webp_WebPDecodeRGB" >&5
+$as_echo "$ac_cv_lib_webp_WebPDecodeRGB" >&6; }
+if test "x$ac_cv_lib_webp_WebPDecodeRGB" = xyes; then :
+  WEBP_SETTING=yes
 else
-  EPSILON_SETTING=no
+  WEBP_SETTING=no
 fi
 
 
-  if test "$EPSILON_SETTING" = "yes" ; then
-    LIBS="-L$with_epsilon/lib -lepsilon $LIBS"
-    EXTRA_INCLUDES="-I$with_epsilon/include $EXTRA_INCLUDES"
+  if test "$WEBP_SETTING" = "yes" ; then
+    LIBS="-L$with_webp/lib -lwebp $LIBS"
+    EXTRA_INCLUDES="-I$with_webp/include $EXTRA_INCLUDES"
   else
-    echo "libepsilon not found - EPSILON support disabled"
+    echo "libwebp not found - WEBP support disabled"
   fi
 
 fi
 
-if test "$EPSILON_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="epsilon $OPT_GDAL_FORMATS"
+if test "$WEBP_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="webp $OPT_GDAL_FORMATS"
 fi
 
 
@@ -23312,7 +25649,7 @@ $as_echo "GEOS support disabled" >&6; }
 set dummy geos-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_GEOS_CONFIG+set}" = set; then :
+if ${ac_cv_path_GEOS_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $GEOS_CONFIG in
@@ -23382,7 +25719,7 @@ $as_echo X"$with_geos" |
 set dummy "$ac_geos_config"; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_GEOS_CONFIG+set}" = set; then :
+if ${ac_cv_prog_GEOS_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$GEOS_CONFIG"; then
@@ -23496,7 +25833,7 @@ $as_echo "$as_me: WARNING: GEOS was found on your system, but geos-config report
 
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GEOSversion in -lgeos_c" >&5
 $as_echo_n "checking for GEOSversion in -lgeos_c... " >&6; }
-if test "${ac_cv_lib_geos_c_GEOSversion+set}" = set; then :
+if ${ac_cv_lib_geos_c_GEOSversion+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23531,13 +25868,17 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_geos_c_GEOSversion" >&5
 $as_echo "$ac_cv_lib_geos_c_GEOSversion" >&6; }
-if test "x$ac_cv_lib_geos_c_GEOSversion" = x""yes; then :
+if test "x$ac_cv_lib_geos_c_GEOSversion" = xyes; then :
   HAVE_GEOS="yes"
 else
   HAVE_GEOS="no"
 fi
 
 
+      if test x"$HAVE_GEOS" = "xno"; then
+          GEOS_CFLAGS=""
+      fi
+
       CFLAGS="${ax_save_CFLAGS}"
       LIBS="${ax_save_LIBS}"
 
@@ -23577,40 +25918,390 @@ if test "${with_opencl_include+set}" = set; then :
   withval=$with_opencl_include;
 fi
 
-
-  OPENCL_SETTING=yes
-
-  if test "x$with_opencl_include" = "x" ; then
-    OPENCL_FLAGS=-DHAVE_OPENCL
-  else
-    OPENCL_FLAGS="-I$with_opencl_include -DHAVE_OPENCL"
+
+  OPENCL_SETTING=yes
+
+  if test "x$with_opencl_include" = "x" ; then
+    OPENCL_FLAGS=-DHAVE_OPENCL
+  else
+    OPENCL_FLAGS="-I$with_opencl_include -DHAVE_OPENCL"
+  fi
+
+
+# Check whether --with-opencl-lib was given.
+if test "${with_opencl_lib+set}" = set; then :
+  withval=$with_opencl_lib;
+fi
+
+
+  if test "x$with_opencl_lib" = "x" ; then
+    if test ! -z "`uname | grep Darwin`" ; then
+      OPENCL_LIB="-framework OpenCL"
+    else
+      OPENCL_LIB=-lOpenCL
+    fi
+  else
+    OPENCL_LIB="$with_opencl_lib"
+  fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENCL_SETTING" >&5
+$as_echo "$OPENCL_SETTING" >&6; }
+
+OPENCL_FLAGS=$OPENCL_FLAGS
+
+OPENCL_LIB=$OPENCL_LIB
+
+
+
+
+
+# Check whether --with-freexl was given.
+if test "${with_freexl+set}" = set; then :
+  withval=$with_freexl;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FreeXL support" >&5
+$as_echo_n "checking for FreeXL support... " >&6; }
+
+HAVE_FREEXL=no
+FREEXL_INCLUDE=
+
+if test "$with_freexl" = "" -o "$with_freexl" = "yes" ; then
+  for ac_header in freexl.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "freexl.h" "ac_cv_header_freexl_h" "$ac_includes_default"
+if test "x$ac_cv_header_freexl_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FREEXL_H 1
+_ACEOF
+
+fi
+
+done
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freexl_open in -lfreexl" >&5
+$as_echo_n "checking for freexl_open in -lfreexl... " >&6; }
+if ${ac_cv_lib_freexl_freexl_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfreexl  $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 freexl_open ();
+int
+main ()
+{
+return freexl_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_freexl_freexl_open=yes
+else
+  ac_cv_lib_freexl_freexl_open=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_freexl_freexl_open" >&5
+$as_echo "$ac_cv_lib_freexl_freexl_open" >&6; }
+if test "x$ac_cv_lib_freexl_freexl_open" = xyes; then :
+  FREEXL_LIBS="-lfreexl"
+else
+  FREEXL_LIBS=missing
+fi
+
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freexl_open in -lfreexl" >&5
+$as_echo_n "checking for freexl_open in -lfreexl... " >&6; }
+if ${ac_cv_lib_freexl_freexl_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfreexl -liconv $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 freexl_open ();
+int
+main ()
+{
+return freexl_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_freexl_freexl_open=yes
+else
+  ac_cv_lib_freexl_freexl_open=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_freexl_freexl_open" >&5
+$as_echo "$ac_cv_lib_freexl_freexl_open" >&6; }
+if test "x$ac_cv_lib_freexl_freexl_open" = xyes; then :
+  FREEXL_LIBS="-lfreexl -liconv"
+else
+  FREEXL_LIBS=missing
+fi
+
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freexl_open in -lfreexl" >&5
+$as_echo_n "checking for freexl_open in -lfreexl... " >&6; }
+if ${ac_cv_lib_freexl_freexl_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfreexl -liconv -lcharset $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 freexl_open ();
+int
+main ()
+{
+return freexl_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_freexl_freexl_open=yes
+else
+  ac_cv_lib_freexl_freexl_open=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_freexl_freexl_open" >&5
+$as_echo "$ac_cv_lib_freexl_freexl_open" >&6; }
+if test "x$ac_cv_lib_freexl_freexl_open" = xyes; then :
+  FREEXL_LIBS="-lfreexl -liconv -lcharset"
+else
+  FREEXL_LIBS=missing
+fi
+
+  fi
+
+  if test "$FREEXL_LIBS" != "missing" -a "$ac_cv_header_freexl_h" = "yes" ; then
+
+    # Check that freexl is recent enough
+    rm -f testrlist.*
+    echo '#include <freexl.h>' > testfreexl.c
+    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
+    if test -z "`${CC} testfreexl.c -c 2>&1`" ; then
+        HAVE_FREEXL=yes
+        LIBS="$FREEXL_LIBS $LIBS"
+    else
+        HAVE_FREEXL=no
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: freexl too old. Needs freexl >= 1.0" >&5
+$as_echo "freexl too old. Needs freexl >= 1.0" >&6; }
+    fi
+    rm -f testfreexl.*
+
+  else
+    HAVE_FREEXL=no
+    echo "libfreexl not found - FreeXL support disabled"
+  fi
+
+elif test "$with_freexl" != "no"; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freexl_open in -lfreexl" >&5
+$as_echo_n "checking for freexl_open in -lfreexl... " >&6; }
+if ${ac_cv_lib_freexl_freexl_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfreexl -L$with_freexl/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 freexl_open ();
+int
+main ()
+{
+return freexl_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_freexl_freexl_open=yes
+else
+  ac_cv_lib_freexl_freexl_open=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_freexl_freexl_open" >&5
+$as_echo "$ac_cv_lib_freexl_freexl_open" >&6; }
+if test "x$ac_cv_lib_freexl_freexl_open" = xyes; then :
+  FREEXL_LIBS="-L$with_freexl/lib -lfreexl"
+else
+  FREEXL_LIBS=missing
+fi
+
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freexl_open in -lfreexl" >&5
+$as_echo_n "checking for freexl_open in -lfreexl... " >&6; }
+if ${ac_cv_lib_freexl_freexl_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfreexl -L$with_freexl/lib -liconv $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 freexl_open ();
+int
+main ()
+{
+return freexl_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_freexl_freexl_open=yes
+else
+  ac_cv_lib_freexl_freexl_open=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_freexl_freexl_open" >&5
+$as_echo "$ac_cv_lib_freexl_freexl_open" >&6; }
+if test "x$ac_cv_lib_freexl_freexl_open" = xyes; then :
+  FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv"
+else
+  FREEXL_LIBS=missing
+fi
+
   fi
 
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freexl_open in -lfreexl" >&5
+$as_echo_n "checking for freexl_open in -lfreexl... " >&6; }
+if ${ac_cv_lib_freexl_freexl_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfreexl -L$with_freexl/lib -liconv -lcharset $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
-# Check whether --with-opencl-lib was given.
-if test "${with_opencl_lib+set}" = set; then :
-  withval=$with_opencl_lib;
+/* 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 freexl_open ();
+int
+main ()
+{
+return freexl_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_freexl_freexl_open=yes
+else
+  ac_cv_lib_freexl_freexl_open=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_freexl_freexl_open" >&5
+$as_echo "$ac_cv_lib_freexl_freexl_open" >&6; }
+if test "x$ac_cv_lib_freexl_freexl_open" = xyes; then :
+  FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv -lcharset"
+else
+  FREEXL_LIBS=missing
 fi
 
+  fi
 
-  if test "x$with_opencl_lib" = "x" ; then
-    if test ! -z "`uname | grep Darwin`" ; then
-      OPENCL_LIB="-framework OpenCL"
+  if test "FREEXL_LIBS" != "missing" -a -f "$with_freexl/include/freexl.h" ; then
+
+    # Check that freexl is recent enough
+    rm -f testrlist.*
+    echo '#include <freexl.h>' > testfreexl.c
+    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
+    if test -z "`${CC} -I$with_freexl/include testfreexl.c -c 2>&1`" ; then
+        HAVE_FREEXL=yes
+        LIBS="$FREEXL_LIBS $LIBS"
+        FREEXL_INCLUDE="-I$with_freexl/include"
     else
-      OPENCL_LIB=-lOpenCL
+        HAVE_FREEXL=no
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: freexl too old. Needs freexl >= 1.0" >&5
+$as_echo "freexl too old. Needs freexl >= 1.0" >&6; }
     fi
+    rm -f testfreexl.*
+
   else
-    OPENCL_LIB="$with_opencl_lib"
+    HAVE_FREEXL=no
+    echo "libfreexl not found - FreeXL support disabled"
   fi
 
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENCL_SETTING" >&5
-$as_echo "$OPENCL_SETTING" >&6; }
-
-OPENCL_FLAGS=$OPENCL_FLAGS
+HAVE_FREEXL=$HAVE_FREEXL
 
-OPENCL_LIB=$OPENCL_LIB
+FREEXL_INCLUDE=$FREEXL_INCLUDE
 
 
 
@@ -23740,6 +26431,104 @@ POPPLER_INC=$POPPLER_INC
 
 
 
+
+# Check whether --with-podofo was given.
+if test "${with_podofo+set}" = set; then :
+  withval=$with_podofo;
+fi
+
+
+HAVE_PODOFO=no
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for podofo" >&5
+$as_echo_n "checking for podofo... " >&6; }
+
+if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
+
+
+# Check whether --with-podofo-lib was given.
+if test "${with_podofo_lib+set}" = set; then :
+  withval=$with_podofo_lib;
+fi
+
+
+    if test "$HAVE_POPPLER" = "yes"; then
+        as_fn_error $? "--with-podofo and --with-poppler cannot be specified at the same time" "$LINENO" 5
+    fi
+
+    if test "$with_podofo" = "yes" ; then
+        TEST_PODOFO_INC="-I/usr/include -I/usr/include/podofo"
+        PODOFO_LIB="-lpodofo"
+    else
+        TEST_PODOFO_INC="-I$with_podofo/include -I$with_podofo/include/podofo"
+        PODOFO_LIB="-L$with_podofo/lib -lpodofo"
+    fi
+
+    if test "x$with_podofo_lib" = "x" ; then
+        rm -f testpodofo.*
+        echo '#include <podofo.h>' > testpodofo.cpp
+        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
+        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB}  2>&1`" ; then
+            HAVE_PODOFO=yes
+            LIBS="${PODOFO_LIB} ${LIBS}"
+            OPT_GDAL_FORMATS="pdf $OPT_GDAL_FORMATS"
+            PODOFO_INC=$TEST_PODOFO_INC
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        fi
+        rm -f testpodofo.*
+        rm -f testpodofo
+    fi
+
+    if test "$HAVE_PODOFO" = "no"; then
+        if test "x$with_podofo_lib" != "x" ; then
+            PODOFO_LIB="$with_podofo_lib"
+        else
+            # This may be a static libpodofo.a, so add dependant libraries
+            PODOFO_LIB="$PODOFO_LIB -lfreetype -lfontconfig -lpthread"
+        fi
+
+
+# Check whether --with-podofo-extra-lib-for-test was given.
+if test "${with_podofo_extra_lib_for_test+set}" = set; then :
+  withval=$with_podofo_extra_lib_for_test;
+fi
+
+
+        if test "x$with_podofo_extra_lib_for_test" = "x" ; then
+            TEST_PODOFO_LIB="$PODOFO_LIB"
+        else
+            TEST_PODOFO_LIB="$PODOFO_LIB $with_podofo_extra_lib_for_test"
+        fi
+
+        rm -f testpodofo.*
+        echo '#include <podofo.h>' > testpodofo.cpp
+        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
+        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>&1`" ; then
+            HAVE_PODOFO=yes
+            LIBS="${PODOFO_LIB} ${LIBS}"
+            OPT_GDAL_FORMATS="pdf $OPT_GDAL_FORMATS"
+            PODOFO_INC=$TEST_PODOFO_INC
+            { $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; }
+        fi
+        rm -f testpodofo.*
+        rm -f testpodofo
+    fi
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+fi
+
+HAVE_PODOFO=$HAVE_PODOFO
+
+PODOFO_INC=$PODOFO_INC
+
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link PROJ.4 library" >&5
 $as_echo_n "checking how to link PROJ.4 library... " >&6; }
 
@@ -23769,7 +26558,7 @@ $as_echo "link statically." >&6; }
     LIBS="$PROJ_LIB $ORIG_LIBS"
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init in -lproj" >&5
 $as_echo_n "checking for pj_init in -lproj... " >&6; }
-if test "${ac_cv_lib_proj_pj_init+set}" = set; then :
+if ${ac_cv_lib_proj_pj_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23803,7 +26592,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init" >&5
 $as_echo "$ac_cv_lib_proj_pj_init" >&6; }
-if test "x$ac_cv_lib_proj_pj_init" = x""yes; then :
+if test "x$ac_cv_lib_proj_pj_init" = xyes; then :
   PROJ_STATIC=yes
 else
   PROJ_STATIC=no
@@ -23814,7 +26603,7 @@ fi
     LIBS="-L$with_static_proj4/lib $PROJ_LIB $ORIG_LIBS"
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init in -lproj" >&5
 $as_echo_n "checking for pj_init in -lproj... " >&6; }
-if test "${ac_cv_lib_proj_pj_init+set}" = set; then :
+if ${ac_cv_lib_proj_pj_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23848,7 +26637,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init" >&5
 $as_echo "$ac_cv_lib_proj_pj_init" >&6; }
-if test "x$ac_cv_lib_proj_pj_init" = x""yes; then :
+if test "x$ac_cv_lib_proj_pj_init" = xyes; then :
   PROJ_STATIC=yes
 else
   PROJ_STATIC=no
@@ -23862,7 +26651,7 @@ fi
       LIBS="-L$with_static_proj4/src $PROJ_LIB $ORIG_LIBS"
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init in -lproj" >&5
 $as_echo_n "checking for pj_init in -lproj... " >&6; }
-if test "${ac_cv_lib_proj_pj_init+set}" = set; then :
+if ${ac_cv_lib_proj_pj_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23896,7 +26685,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init" >&5
 $as_echo "$ac_cv_lib_proj_pj_init" >&6; }
-if test "x$ac_cv_lib_proj_pj_init" = x""yes; then :
+if test "x$ac_cv_lib_proj_pj_init" = xyes; then :
   PROJ_STATIC=yes
 else
   PROJ_STATIC=no
@@ -23909,7 +26698,7 @@ fi
       LIBS="-L$with_static_proj4/src/.libs $PROJ_LIB $ORIG_LIBS"
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init in -lproj" >&5
 $as_echo_n "checking for pj_init in -lproj... " >&6; }
-if test "${ac_cv_lib_proj_pj_init+set}" = set; then :
+if ${ac_cv_lib_proj_pj_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23943,7 +26732,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init" >&5
 $as_echo "$ac_cv_lib_proj_pj_init" >&6; }
-if test "x$ac_cv_lib_proj_pj_init" = x""yes; then :
+if test "x$ac_cv_lib_proj_pj_init" = xyes; then :
   PROJ_STATIC=yes
 else
   PROJ_STATIC=no
@@ -23956,7 +26745,7 @@ fi
       LIBS="-L$with_static_proj4 $PROJ_LIB $ORIG_LIBS"
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init in -lproj" >&5
 $as_echo_n "checking for pj_init in -lproj... " >&6; }
-if test "${ac_cv_lib_proj_pj_init+set}" = set; then :
+if ${ac_cv_lib_proj_pj_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -23990,7 +26779,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init" >&5
 $as_echo "$ac_cv_lib_proj_pj_init" >&6; }
-if test "x$ac_cv_lib_proj_pj_init" = x""yes; then :
+if test "x$ac_cv_lib_proj_pj_init" = xyes; then :
   PROJ_STATIC=yes
 else
   PROJ_STATIC=no
@@ -24003,7 +26792,7 @@ fi
       LIBS="$PROJ_LIB $ORIG_LIBS"
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_init in -lproj" >&5
 $as_echo_n "checking for pj_init in -lproj... " >&6; }
-if test "${ac_cv_lib_proj_pj_init+set}" = set; then :
+if ${ac_cv_lib_proj_pj_init+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -24037,7 +26826,7 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init" >&5
 $as_echo "$ac_cv_lib_proj_pj_init" >&6; }
-if test "x$ac_cv_lib_proj_pj_init" = x""yes; then :
+if test "x$ac_cv_lib_proj_pj_init" = xyes; then :
   PROJ_STATIC=yes
 else
   PROJ_STATIC=no
@@ -24273,7 +27062,7 @@ do
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_PYTHON+set}" = set; then :
+if ${ac_cv_prog_PYTHON+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$PYTHON"; then
@@ -24358,45 +27147,343 @@ fi
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Python modules" >&5
 $as_echo_n "checking where to install Python modules... " >&6; }
 
-        if test "$with_pymoddir" = "" ; then
-            pymoddir=$pyexecdir
-        else
-            pymoddir=$with_pymoddir
+        if test "$with_pymoddir" = "" ; then
+            pymoddir=$pyexecdir
+        else
+            pymoddir=$with_pymoddir
+        fi
+
+        export pymoddir
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pymoddir" >&5
+$as_echo "$pymoddir" >&6; }
+    fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
+$as_echo "enabled" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python setuptools" >&5
+$as_echo_n "checking for python setuptools... " >&6; }
+  SETUPTEST='try:
+  import setuptools
+  print 1
+except ImportError:
+  pass'
+  PY_HAVE_SETUPTOOLS=`python -c "$SETUPTEST"`
+  if test "$PY_HAVE_SETUPTOOLS" = "1"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+fi
+
+
+
+
+
+
+# Check whether --with-java was given.
+if test "${with_java+set}" = set; then :
+  withval=$with_java;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we should include Java support" >&5
+$as_echo_n "checking whether we should include Java support... " >&6; }
+
+JAVA_HOME=""
+JAVA_INC=""
+
+if test "x$with_java" = "xyes"; then
+
+    if test -d /usr/lib/jvm/java-6-openjdk; then
+        with_java="/usr/lib/jvm/java-6-openjdk"
+
+    elif test -d /usr/lib/jvm/java-openjdk; then
+        with_java="/usr/lib/jvm/java-openjdk"
+
+
+    elif test -d /usr/java; then
+        with_java="/usr/java"
+    else
+        as_fn_error $? "\"cannot find JDK root directory.\"" "$LINENO" 5
+    fi
+
+    if test \! -d "$with_java/include" ; then
+        as_fn_error $? "\"$with_java is not a valid JDK.\"" "$LINENO" 5
+    fi
+fi
+
+if test "x$JAVA_INC" != "x"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$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/include/linux"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        elif test -d "$with_java/include/solaris"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/solaris"
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        elif test -d "$with_java/include/freebsd"; then
+            JAVA_HOME="$with_java"
+            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; }
+        else
+            as_fn_error $? "\"Cannot find $with_java/include/linux or solaris or freebsd directory.\"" "$LINENO" 5
+        fi
+    else
+        as_fn_error $? "\"Cannot find $with_java/include directory.\"" "$LINENO" 5
+    fi
+
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+JAVA_HOME=$JAVA_HOME
+
+JAVA_INC=$JAVA_INC
+
+
+
+
+# Check whether --with-mdb was given.
+if test "${with_mdb+set}" = set; then :
+  withval=$with_mdb;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we should include MDB support" >&5
+$as_echo_n "checking whether we should include MDB support... " >&6; }
+
+MDB_ENABLED=no
+JVM_LIB=""
+
+if test "$with_mdb" = "yes" ; then
+    if test "x$JAVA_INC" = "x"; then
+        as_fn_error $? "\"--with-java must be specified.\"" "$LINENO" 5
+    fi
+
+
+# Check whether --with-jvm-lib was given.
+if test "${with_jvm_lib+set}" = set; then :
+  withval=$with_jvm_lib;
+fi
+
+
+
+# Check whether --with-jvm-lib-add-rpath was given.
+if test "${with_jvm_lib_add_rpath+set}" = set; then :
+  withval=$with_jvm_lib_add_rpath;
+fi
+
+
+    if test "x$with_jvm_lib" != "x"; then
+        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
+$as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
+if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljvm  $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 :
+  ac_cv_lib_jvm_JNI_CreateJavaVM=yes
+else
+  ac_cv_lib_jvm_JNI_CreateJavaVM=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_jvm_JNI_CreateJavaVM" >&5
+$as_echo "$ac_cv_lib_jvm_JNI_CreateJavaVM" >&6; }
+if test "x$ac_cv_lib_jvm_JNI_CreateJavaVM" = xyes; then :
+  HAS_LIB_JVM=yes
+else
+  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$with_jvm_lib_add_rpath" = "xyes"; then
+                    JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
+                fi
+            else
+                as_fn_error $? "\"--with-jvm-lib must point to a directory with a libjvm.\"" "$LINENO" 5
+            fi
+        else
+            as_fn_error $? "\"--with-jvm-lib must point to a directory.\"" "$LINENO" 5
+        fi
+    elif test "x$JAVA_HOME" != "x"; then
+        TEST_DIR="$JAVA_HOME/jre/lib/amd64/server"
+        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
+$as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
+if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljvm  $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 :
+  ac_cv_lib_jvm_JNI_CreateJavaVM=yes
+else
+  ac_cv_lib_jvm_JNI_CreateJavaVM=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_jvm_JNI_CreateJavaVM" >&5
+$as_echo "$ac_cv_lib_jvm_JNI_CreateJavaVM" >&6; }
+if test "x$ac_cv_lib_jvm_JNI_CreateJavaVM" = xyes; then :
+  HAS_LIB_JVM=yes
+else
+  HAS_LIB_JVM=no
+fi
+
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                fi
+            fi
         fi
 
-        export pymoddir
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pymoddir" >&5
-$as_echo "$pymoddir" >&6; }
-    fi
-
-
+        TEST_DIR="$JAVA_HOME/jre/lib/i386/server"
+        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
+$as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
+if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljvm  $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 :
+  ac_cv_lib_jvm_JNI_CreateJavaVM=yes
+else
+  ac_cv_lib_jvm_JNI_CreateJavaVM=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_jvm_JNI_CreateJavaVM" >&5
+$as_echo "$ac_cv_lib_jvm_JNI_CreateJavaVM" >&6; }
+if test "x$ac_cv_lib_jvm_JNI_CreateJavaVM" = xyes; then :
+  HAS_LIB_JVM=yes
+else
+  HAS_LIB_JVM=no
+fi
 
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                fi
+            fi
+        fi
 
+        if test "x$JVM_LIB" = "x"; then
+            as_fn_error $? "\"--with-jvm-lib must be specified.\"" "$LINENO" 5
+        fi
+    else
+        as_fn_error $? "\"--with-jvm-lib must be specified.\"" "$LINENO" 5
+    fi
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
-$as_echo "enabled" >&6; }
+    MDB_ENABLED=yes
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python setuptools" >&5
-$as_echo_n "checking for python setuptools... " >&6; }
-  SETUPTEST='try:
-  import setuptools
-  print 1
-except ImportError:
-  pass'
-  PY_HAVE_SETUPTOOLS=`python -c "$SETUPTEST"`
-  if test "$PY_HAVE_SETUPTOOLS" = "1"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
-$as_echo "found" >&6; }
-  else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
-  fi
 else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
-$as_echo "disabled" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
+MDB_ENABLED=$MDB_ENABLED
+
+JVM_LIB=$JVM_LIB
 
 
 
@@ -24416,7 +27503,7 @@ if test "$with_rasdaman" = "yes" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lraslib" >&5
 $as_echo_n "checking for main in -lraslib... " >&6; }
-if test "${ac_cv_lib_raslib_main+set}" = set; then :
+if ${ac_cv_lib_raslib_main+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -24444,13 +27531,14 @@ LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_raslib_main" >&5
 $as_echo "$ac_cv_lib_raslib_main" >&6; }
-if test "x$ac_cv_lib_raslib_main" = x""yes; then :
+if test "x$ac_cv_lib_raslib_main" = xyes; then :
   RASDAMAN_ENABLED=yes
 fi
 
 
   if test -n "$RASDAMAN_ENABLED" ; then
       RASDAMAN_LIB="-lrasodmg -lclientcomm -lcompression -lnetwork -lraslib"
+      OPT_GDAL_FORMATS="rasdaman $OPT_GDAL_FORMATS"
       { $as_echo "$as_me:${as_lineno-$LINENO}: result:         using rasdaman from system libs." >&5
 $as_echo "        using rasdaman from system libs." >&6; }
   else
@@ -24488,6 +27576,43 @@ RASDAMAN_LIB=$RASDAMAN_LIB
 
 
 
+
+# Check whether --with-armadillo was given.
+if test "${with_armadillo+set}" = set; then :
+  withval=$with_armadillo;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we should include Armadillo support" >&5
+$as_echo_n "checking whether we should include Armadillo support... " >&6; }
+
+HAVE_ARMADILLO=no
+
+if test "$with_armadillo" = "yes" ; then
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+    echo '#include <armadillo>' > testarmadillo.cpp
+    echo 'int main(int argc, char** argv) { arma::mat matInput(2,2); const arma::mat& matInv = arma::inv(matInput); return 0; } ' >> testarmadillo.cpp
+    if test -z "`${CXX} testarmadillo.cpp -o testarmadillo -larmadillo 2>&1`" ; then
+        HAVE_ARMADILLO=yes
+        LIBS="-larmadillo ${LIBS}"
+        { $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; }
+    fi
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+HAVE_ARMADILLO=$HAVE_ARMADILLO
+
+
+
 ac_config_files="$ac_config_files GDALmake.opt"
 
 
@@ -24517,7 +27642,7 @@ LTLIBOBJS=$ac_ltlibobjs
 
 
 
-: ${CONFIG_STATUS=./config.status}
+: "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
 ac_clean_files_save=$ac_clean_files
 ac_clean_files="$ac_clean_files $CONFIG_STATUS"
@@ -24618,6 +27743,7 @@ fi
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -24925,7 +28051,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.67.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -24991,7 +28117,7 @@ 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.67,
+configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -25000,6 +28126,7 @@ gives unlimited permission to copy, distribute and modify it."
 
 ac_pwd='$ac_pwd'
 srcdir='$srcdir'
+AWK='$AWK'
 test -n "\$AWK" || AWK=awk
 _ACEOF
 
@@ -25115,186 +28242,212 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 sed_quote_subst='$sed_quote_subst'
 double_quote_subst='$double_quote_subst'
 delay_variable_subst='$delay_variable_subst'
-AS='`$ECHO "X$AS" | $Xsed -e "$delay_single_quote_subst"`'
-DLLTOOL='`$ECHO "X$DLLTOOL" | $Xsed -e "$delay_single_quote_subst"`'
-OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`'
-macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`'
-macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`'
-enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`'
-enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
-pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`'
-enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`'
-host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`'
-host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`'
-host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`'
-build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`'
-build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`'
-build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`'
-SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`'
-Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`'
-GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`'
-EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`'
-FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`'
-LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`'
-NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`'
-LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`'
-max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`'
-ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`'
-exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`'
-lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`'
-lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`'
-lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`'
-reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`'
-reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`'
-file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`'
-AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`'
-AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`'
-STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`'
-RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`'
-old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`'
-CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`'
-compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`'
-GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
-objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`'
-SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`'
-ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`'
-MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`'
-need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`'
-DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`'
-NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`'
-LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`'
-OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`'
-OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`'
-libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`'
-shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`'
-enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`'
-export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
-whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`'
-allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
-no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`'
-inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`'
-link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`'
-fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`'
-always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`'
-export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
-include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
-prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`'
-variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`'
-need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
-need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`'
-version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`'
-runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`'
-shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
-shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`'
-libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`'
-library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`'
-soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`'
-postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`'
-finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`'
-sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
-sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`'
-enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`'
-enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`'
-enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`'
-old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`'
-striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_lib_search_dirs='`$ECHO "X$compiler_lib_search_dirs" | $Xsed -e "$delay_single_quote_subst"`'
-predep_objects='`$ECHO "X$predep_objects" | $Xsed -e "$delay_single_quote_subst"`'
-postdep_objects='`$ECHO "X$postdep_objects" | $Xsed -e "$delay_single_quote_subst"`'
-predeps='`$ECHO "X$predeps" | $Xsed -e "$delay_single_quote_subst"`'
-postdeps='`$ECHO "X$postdeps" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_lib_search_path='`$ECHO "X$compiler_lib_search_path" | $Xsed -e "$delay_single_quote_subst"`'
-LD_CXX='`$ECHO "X$LD_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_cmds_CXX='`$ECHO "X$old_archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_CXX='`$ECHO "X$compiler_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-GCC_CXX='`$ECHO "X$GCC_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "X$lt_prog_compiler_no_builtin_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_wl_CXX='`$ECHO "X$lt_prog_compiler_wl_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_pic_CXX='`$ECHO "X$lt_prog_compiler_pic_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-lt_prog_compiler_static_CXX='`$ECHO "X$lt_prog_compiler_static_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-lt_cv_prog_compiler_c_o_CXX='`$ECHO "X$lt_cv_prog_compiler_c_o_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-archive_cmds_need_lc_CXX='`$ECHO "X$archive_cmds_need_lc_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-enable_shared_with_static_runtimes_CXX='`$ECHO "X$enable_shared_with_static_runtimes_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-export_dynamic_flag_spec_CXX='`$ECHO "X$export_dynamic_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-whole_archive_flag_spec_CXX='`$ECHO "X$whole_archive_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_needs_object_CXX='`$ECHO "X$compiler_needs_object_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_from_new_cmds_CXX='`$ECHO "X$old_archive_from_new_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-old_archive_from_expsyms_cmds_CXX='`$ECHO "X$old_archive_from_expsyms_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-archive_cmds_CXX='`$ECHO "X$archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-archive_expsym_cmds_CXX='`$ECHO "X$archive_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-module_cmds_CXX='`$ECHO "X$module_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-module_expsym_cmds_CXX='`$ECHO "X$module_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-with_gnu_ld_CXX='`$ECHO "X$with_gnu_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-allow_undefined_flag_CXX='`$ECHO "X$allow_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-no_undefined_flag_CXX='`$ECHO "X$no_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec_CXX='`$ECHO "X$hardcode_libdir_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec_ld_CXX='`$ECHO "X$hardcode_libdir_flag_spec_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_libdir_separator_CXX='`$ECHO "X$hardcode_libdir_separator_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_direct_CXX='`$ECHO "X$hardcode_direct_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_direct_absolute_CXX='`$ECHO "X$hardcode_direct_absolute_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_minus_L_CXX='`$ECHO "X$hardcode_minus_L_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_shlibpath_var_CXX='`$ECHO "X$hardcode_shlibpath_var_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_automatic_CXX='`$ECHO "X$hardcode_automatic_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-inherit_rpath_CXX='`$ECHO "X$inherit_rpath_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-link_all_deplibs_CXX='`$ECHO "X$link_all_deplibs_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-fix_srcfile_path_CXX='`$ECHO "X$fix_srcfile_path_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-always_export_symbols_CXX='`$ECHO "X$always_export_symbols_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-export_symbols_cmds_CXX='`$ECHO "X$export_symbols_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-exclude_expsyms_CXX='`$ECHO "X$exclude_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-include_expsyms_CXX='`$ECHO "X$include_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-prelink_cmds_CXX='`$ECHO "X$prelink_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-file_list_spec_CXX='`$ECHO "X$file_list_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-hardcode_action_CXX='`$ECHO "X$hardcode_action_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_lib_search_dirs_CXX='`$ECHO "X$compiler_lib_search_dirs_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-predep_objects_CXX='`$ECHO "X$predep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-postdep_objects_CXX='`$ECHO "X$postdep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-predeps_CXX='`$ECHO "X$predeps_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-postdeps_CXX='`$ECHO "X$postdeps_CXX" | $Xsed -e "$delay_single_quote_subst"`'
-compiler_lib_search_path_CXX='`$ECHO "X$compiler_lib_search_path_CXX" | $Xsed -e "$delay_single_quote_subst"`'
+AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`'
+predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`'
+postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`'
+predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`'
+postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`'
+LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`'
+reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`'
+reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
+GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld_CXX='`$ECHO "$hardcode_libdir_flag_spec_ld_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
+inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
+always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
+predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`'
+postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`'
 
 LTCC='$LTCC'
 LTCFLAGS='$LTCFLAGS'
 compiler='$compiler_DEFAULT'
 
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
 # Quote evaled strings.
-for var in SED \
+for var in AS \
+DLLTOOL \
+OBJDUMP \
+SHELL \
+ECHO \
+SED \
 GREP \
 EGREP \
 FGREP \
@@ -25306,8 +28459,12 @@ lt_NL2SP \
 reload_flag \
 deplibs_check_method \
 file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+sharedlib_from_linklib_cmd \
 AR \
 AR_FLAGS \
+archiver_list_spec \
 STRIP \
 RANLIB \
 CC \
@@ -25317,14 +28474,14 @@ lt_cv_sys_global_symbol_pipe \
 lt_cv_sys_global_symbol_to_cdecl \
 lt_cv_sys_global_symbol_to_c_name_address \
 lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
-SHELL \
-ECHO \
+nm_file_list_spec \
 lt_prog_compiler_no_builtin_flag \
-lt_prog_compiler_wl \
 lt_prog_compiler_pic \
+lt_prog_compiler_wl \
 lt_prog_compiler_static \
 lt_cv_prog_compiler_c_o \
 need_locks \
+MANIFEST_TOOL \
 DSYMUTIL \
 NMEDIT \
 LIPO \
@@ -25340,7 +28497,6 @@ no_undefined_flag \
 hardcode_libdir_flag_spec \
 hardcode_libdir_flag_spec_ld \
 hardcode_libdir_separator \
-fix_srcfile_path \
 exclude_expsyms \
 include_expsyms \
 file_list_spec \
@@ -25348,6 +28504,7 @@ variables_saved_for_relink \
 libname_spec \
 library_names_spec \
 soname_spec \
+install_override_mode \
 finish_eval \
 old_striplib \
 striplib \
@@ -25358,10 +28515,11 @@ predeps \
 postdeps \
 compiler_lib_search_path \
 LD_CXX \
+reload_flag_CXX \
 compiler_CXX \
 lt_prog_compiler_no_builtin_flag_CXX \
-lt_prog_compiler_wl_CXX \
 lt_prog_compiler_pic_CXX \
+lt_prog_compiler_wl_CXX \
 lt_prog_compiler_static_CXX \
 lt_cv_prog_compiler_c_o_CXX \
 export_dynamic_flag_spec_CXX \
@@ -25373,7 +28531,6 @@ no_undefined_flag_CXX \
 hardcode_libdir_flag_spec_CXX \
 hardcode_libdir_flag_spec_ld_CXX \
 hardcode_libdir_separator_CXX \
-fix_srcfile_path_CXX \
 exclude_expsyms_CXX \
 include_expsyms_CXX \
 file_list_spec_CXX \
@@ -25383,9 +28540,9 @@ postdep_objects_CXX \
 predeps_CXX \
 postdeps_CXX \
 compiler_lib_search_path_CXX; do
-    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
     *[\\\\\\\`\\"\\\$]*)
-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
       ;;
     *)
       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
@@ -25407,11 +28564,13 @@ module_cmds \
 module_expsym_cmds \
 export_symbols_cmds \
 prelink_cmds \
+postlink_cmds \
 postinstall_cmds \
 postuninstall_cmds \
 finish_cmds \
 sys_lib_search_path_spec \
 sys_lib_dlsearch_path_spec \
+reload_cmds_CXX \
 old_archive_cmds_CXX \
 old_archive_from_new_cmds_CXX \
 old_archive_from_expsyms_cmds_CXX \
@@ -25420,10 +28579,11 @@ archive_expsym_cmds_CXX \
 module_cmds_CXX \
 module_expsym_cmds_CXX \
 export_symbols_cmds_CXX \
-prelink_cmds_CXX; do
-    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+prelink_cmds_CXX \
+postlink_cmds_CXX; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
     *[\\\\\\\`\\"\\\$]*)
-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
       ;;
     *)
       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
@@ -25431,12 +28591,6 @@ prelink_cmds_CXX; do
     esac
 done
 
-# Fix-up fallback echo if it was mangled by the above quoting rules.
-case \$lt_ECHO in
-*'\\\$0 --fallback-echo"')  lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\`
-  ;;
-esac
-
 ac_aux_dir='$ac_aux_dir'
 xsi_shell='$xsi_shell'
 lt_shell_append='$lt_shell_append'
@@ -25467,7 +28621,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 for ac_config_target in $ac_config_targets
 do
   case $ac_config_target in
-    "port/cpl_config.h") CONFIG_HEADERS="$CONFIG_HEADERS port/cpl_config.h:port/cpl_config.h.in:port/cpl_config_extras.h" ;;
+    "port/cpl_config.h") CONFIG_HEADERS="$CONFIG_HEADERS port/cpl_config.h:port/cpl_config.h.in" ;;
     "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
     "GDALmake.opt") CONFIG_FILES="$CONFIG_FILES GDALmake.opt" ;;
 
@@ -25494,9 +28648,10 @@ fi
 # after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
-  tmp=
+  tmp= ac_tmp=
   trap 'exit_status=$?
-  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
 ' 0
   trap 'as_fn_exit 1' 1 2 13 15
 }
@@ -25504,12 +28659,13 @@ $debug ||
 
 {
   tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
+  test -d "$tmp"
 }  ||
 {
   tmp=./conf$$-$RANDOM
   (umask 077 && mkdir "$tmp")
 } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
 
 # Set up the scripts for CONFIG_FILES section.
 # No need to generate them if there are no CONFIG_FILES.
@@ -25531,7 +28687,7 @@ else
   ac_cs_awk_cr=$ac_cr
 fi
 
-echo 'BEGIN {' >"$tmp/subs1.awk" &&
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
 _ACEOF
 
 
@@ -25559,7 +28715,7 @@ done
 rm -f conf$$subs.sh
 
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
 _ACEOF
 sed -n '
 h
@@ -25607,7 +28763,7 @@ t delim
 rm -f conf$$subs.awk
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 _ACAWK
-cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
   for (key in S) S_is_set[key] = 1
   FS = ""
 
@@ -25639,7 +28795,7 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
   sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
 else
   cat
-fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
   || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
 _ACEOF
 
@@ -25673,7 +28829,7 @@ fi # test -n "$CONFIG_FILES"
 # No need to generate them if there are no CONFIG_HEADERS.
 # This happens for instance with `./config.status Makefile'.
 if test -n "$CONFIG_HEADERS"; then
-cat >"$tmp/defines.awk" <<\_ACAWK ||
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
 BEGIN {
 _ACEOF
 
@@ -25685,8 +28841,8 @@ _ACEOF
 # handling of long lines.
 ac_delim='%!_!# '
 for ac_last_try in false false :; do
-  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
-  if test -z "$ac_t"; then
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
     break
   elif $ac_last_try; then
     as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
@@ -25806,7 +28962,7 @@ do
     for ac_f
     do
       case $ac_f in
-      -) ac_f="$tmp/stdin";;
+      -) ac_f="$ac_tmp/stdin";;
       *) # Look for the file first in the build tree, then in the source tree
 	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
 	 # because $ac_f cannot contain `:'.
@@ -25841,7 +28997,7 @@ $as_echo "$as_me: creating $ac_file" >&6;}
     esac
 
     case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin" \
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
       || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
     esac
     ;;
@@ -25967,21 +29123,22 @@ s&@abs_builddir@&$ac_abs_builddir&;t t
 s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
 $ac_datarootdir_hack
 "
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
-  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 
 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&5
 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&2;}
 
-  rm -f "$tmp/stdin"
+  rm -f "$ac_tmp/stdin"
   case $ac_file in
-  -) cat "$tmp/out" && rm -f "$tmp/out";;
-  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
   esac \
   || as_fn_error $? "could not create $ac_file" "$LINENO" 5
  ;;
@@ -25992,20 +29149,20 @@ which seems to be undefined.  Please make sure it is defined" >&2;}
   if test x"$ac_file" != x-; then
     {
       $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
-    } >"$tmp/config.h" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
 $as_echo "$as_me: $ac_file is unchanged" >&6;}
     else
       rm -f "$ac_file"
-      mv "$tmp/config.h" "$ac_file" \
+      mv "$ac_tmp/config.h" "$ac_file" \
 	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
     fi
   else
     $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
       || as_fn_error $? "could not create -" "$LINENO" 5
   fi
  ;;
@@ -26038,7 +29195,8 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 #
 #   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#                 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
+#                 Inc.
 #   Written by Gordon Matzigkeit, 1996
 #
 #   This file is part of GNU Libtool.
@@ -26071,13 +29229,13 @@ available_tags="CXX "
 # ### BEGIN LIBTOOL CONFIG
 
 # Assembler program.
-AS=$AS
+AS=$lt_AS
 
 # DLL creation program.
-DLLTOOL=$DLLTOOL
+DLLTOOL=$lt_DLLTOOL
 
 # Object dumper program.
-OBJDUMP=$OBJDUMP
+OBJDUMP=$lt_OBJDUMP
 
 # Which release of libtool.m4 was used?
 macro_version=$macro_version
@@ -26095,6 +29253,12 @@ pic_mode=$pic_mode
 # Whether or not to optimize for fast installation.
 fast_install=$enable_fast_install
 
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
 # The host system.
 host_alias=$host_alias
 host=$host
@@ -26144,20 +29308,36 @@ SP2NL=$lt_lt_SP2NL
 # turn newlines into spaces.
 NL2SP=$lt_lt_NL2SP
 
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
 
 # Method to check whether dependent libraries are shared objects.
 deplibs_check_method=$lt_deplibs_check_method
 
-# Command to use when deplibs_check_method == "file_magic".
+# Command to use when deplibs_check_method = "file_magic".
 file_magic_cmd=$lt_file_magic_cmd
 
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
 # The archiver.
 AR=$lt_AR
+
+# Flags to create an archive.
 AR_FLAGS=$lt_AR_FLAGS
 
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
 # A symbol stripping program.
 STRIP=$lt_STRIP
 
@@ -26166,6 +29346,9 @@ RANLIB=$lt_RANLIB
 old_postinstall_cmds=$lt_old_postinstall_cmds
 old_postuninstall_cmds=$lt_old_postuninstall_cmds
 
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
 # A C compiler.
 LTCC=$lt_CC
 
@@ -26184,14 +29367,14 @@ global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
 # Transform the output of nm in a C name address pair when lib prefix is needed.
 global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
 
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
 
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
+# The root where to search for dependent libraries,and in which our libraries should be installed.
+lt_sysroot=$lt_sysroot
 
-# An echo program that does not interpret backslashes.
-ECHO=$lt_ECHO
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
 
 # Used to examine libraries when file_magic_cmd begins with "file".
 MAGIC_CMD=$MAGIC_CMD
@@ -26199,6 +29382,9 @@ MAGIC_CMD=$MAGIC_CMD
 # Must we lock files when doing compilation?
 need_locks=$lt_need_locks
 
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
 # Tool to manipulate archived DWARF debug symbol files on Mac OS X.
 DSYMUTIL=$lt_DSYMUTIL
 
@@ -26255,6 +29441,9 @@ library_names_spec=$lt_library_names_spec
 # The coded name of the library, if different from the real name.
 soname_spec=$lt_soname_spec
 
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
 # Command to use after installation of a shared archive.
 postinstall_cmds=$lt_postinstall_cmds
 
@@ -26294,6 +29483,10 @@ striplib=$lt_striplib
 # The linker used to build libraries.
 LD=$lt_LD
 
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
 # Commands used to build an old-style archive.
 old_archive_cmds=$lt_old_archive_cmds
 
@@ -26306,12 +29499,12 @@ with_gcc=$GCC
 # Compiler flag to turn off builtin functions.
 no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
 
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl
-
 # Additional compiler flags for building library objects.
 pic_flag=$lt_lt_prog_compiler_pic
 
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
 # Compiler flag to prevent dynamic linking.
 link_static_flag=$lt_lt_prog_compiler_static
 
@@ -26398,9 +29591,6 @@ inherit_rpath=$inherit_rpath
 # Whether libtool must link a program against all its dependency libraries.
 link_all_deplibs=$link_all_deplibs
 
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path=$lt_fix_srcfile_path
-
 # Set to "yes" if exported symbols are required.
 always_export_symbols=$always_export_symbols
 
@@ -26416,6 +29606,9 @@ include_expsyms=$lt_include_expsyms
 # Commands necessary for linking programs (against libraries) with templates.
 prelink_cmds=$lt_prelink_cmds
 
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
 # Specify filename containing input files.
 file_list_spec=$lt_file_list_spec
 
@@ -26462,212 +29655,169 @@ ltmain="$ac_aux_dir/ltmain.sh"
   # if finds mixed CR/LF and LF-only lines.  Since sed operates in
   # text mode, it properly converts lines to CR/LF.  This bash problem
   # is reportedly fixed, but why not run on old versions too?
-  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
-    || (rm -f "$cfgfile"; exit 1)
-
-  case $xsi_shell in
-  yes)
-    cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
-  case ${1} in
-    */*) func_dirname_result="${1%/*}${2}" ;;
-    *  ) func_dirname_result="${3}" ;;
-  esac
-}
-
-# func_basename file
-func_basename ()
-{
-  func_basename_result="${1##*/}"
-}
-
-# func_dirname_and_basename file append nondir_replacement
-# perform func_basename and func_dirname in a single function
-# call:
-#   dirname:  Compute the dirname of FILE.  If nonempty,
-#             add APPEND to the result, otherwise set result
-#             to NONDIR_REPLACEMENT.
-#             value returned in "$func_dirname_result"
-#   basename: Compute filename of FILE.
-#             value retuned in "$func_basename_result"
-# Implementation must be kept synchronized with func_dirname
-# and func_basename. For efficiency, we do not delegate to
-# those functions but instead duplicate the functionality here.
-func_dirname_and_basename ()
-{
-  case ${1} in
-    */*) func_dirname_result="${1%/*}${2}" ;;
-    *  ) func_dirname_result="${3}" ;;
-  esac
-  func_basename_result="${1##*/}"
-}
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-func_stripname ()
-{
-  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
-  # positional parameters, so assign one to ordinary parameter first.
-  func_stripname_result=${3}
-  func_stripname_result=${func_stripname_result#"${1}"}
-  func_stripname_result=${func_stripname_result%"${2}"}
-}
-
-# func_opt_split
-func_opt_split ()
-{
-  func_opt_split_opt=${1%%=*}
-  func_opt_split_arg=${1#*=}
-}
-
-# func_lo2o object
-func_lo2o ()
-{
-  case ${1} in
-    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
-    *)    func_lo2o_result=${1} ;;
-  esac
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
-  func_xform_result=${1%.*}.lo
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
-  func_arith_result=$(( $* ))
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
-  func_len_result=${#1}
-}
-
-_LT_EOF
-    ;;
-  *) # Bourne compatible functions.
-    cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
-  # Extract subdirectory from the argument.
-  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
-  if test "X$func_dirname_result" = "X${1}"; then
-    func_dirname_result="${3}"
-  else
-    func_dirname_result="$func_dirname_result${2}"
-  fi
-}
-
-# func_basename file
-func_basename ()
-{
-  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
-}
-
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-# func_strip_suffix prefix name
-func_stripname ()
-{
-  case ${2} in
-    .*) func_stripname_result=`$ECHO "X${3}" \
-           | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
-    *)  func_stripname_result=`$ECHO "X${3}" \
-           | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
-  esac
-}
-
-# sed scripts:
-my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
-my_sed_long_arg='1s/^-[^=]*=//'
-
-# func_opt_split
-func_opt_split ()
-{
-  func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
-  func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
-}
-
-# func_lo2o object
-func_lo2o ()
-{
-  func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
-  func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'`
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
-  func_arith_result=`expr "$@"`
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
-  func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
-}
-
-_LT_EOF
-esac
-
-case $lt_shell_append in
-  yes)
-    cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
-  eval "$1+=\$2"
-}
-_LT_EOF
-    ;;
-  *)
-    cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
-  eval "$1=\$$1\$2"
-}
-
-_LT_EOF
-    ;;
-  esac
-
-
-  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
-    || (rm -f "$cfgfile"; exit 1)
-
-  mv -f "$cfgfile" "$ofile" ||
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+  if test x"$xsi_shell" = xyes; then
+  sed -e '/^func_dirname ()$/,/^} # func_dirname /c\
+func_dirname ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_basename ()$/,/^} # func_basename /c\
+func_basename ()\
+{\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\
+func_dirname_and_basename ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_stripname ()$/,/^} # func_stripname /c\
+func_stripname ()\
+{\
+\    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\
+\    # positional parameters, so assign one to ordinary parameter first.\
+\    func_stripname_result=${3}\
+\    func_stripname_result=${func_stripname_result#"${1}"}\
+\    func_stripname_result=${func_stripname_result%"${2}"}\
+} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\
+func_split_long_opt ()\
+{\
+\    func_split_long_opt_name=${1%%=*}\
+\    func_split_long_opt_arg=${1#*=}\
+} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\
+func_split_short_opt ()\
+{\
+\    func_split_short_opt_arg=${1#??}\
+\    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\
+} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\
+func_lo2o ()\
+{\
+\    case ${1} in\
+\      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\
+\      *)    func_lo2o_result=${1} ;;\
+\    esac\
+} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_xform ()$/,/^} # func_xform /c\
+func_xform ()\
+{\
+    func_xform_result=${1%.*}.lo\
+} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_arith ()$/,/^} # func_arith /c\
+func_arith ()\
+{\
+    func_arith_result=$(( $* ))\
+} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_len ()$/,/^} # func_len /c\
+func_len ()\
+{\
+    func_len_result=${#1}\
+} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+fi
+
+if test x"$lt_shell_append" = xyes; then
+  sed -e '/^func_append ()$/,/^} # func_append /c\
+func_append ()\
+{\
+    eval "${1}+=\\${2}"\
+} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\
+func_append_quoted ()\
+{\
+\    func_quote_for_eval "${2}"\
+\    eval "${1}+=\\\\ \\$func_quote_for_eval_result"\
+} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5
+$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;}
+fi
+
+
+   mv -f "$cfgfile" "$ofile" ||
     (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
   chmod +x "$ofile"
 
@@ -26679,6 +29829,10 @@ _LT_EOF
 # The linker used to build libraries.
 LD=$lt_LD_CXX
 
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag_CXX
+reload_cmds=$lt_reload_cmds_CXX
+
 # Commands used to build an old-style archive.
 old_archive_cmds=$lt_old_archive_cmds_CXX
 
@@ -26691,12 +29845,12 @@ with_gcc=$GCC_CXX
 # Compiler flag to turn off builtin functions.
 no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
 
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl_CXX
-
 # Additional compiler flags for building library objects.
 pic_flag=$lt_lt_prog_compiler_pic_CXX
 
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
 # Compiler flag to prevent dynamic linking.
 link_static_flag=$lt_lt_prog_compiler_static_CXX
 
@@ -26783,9 +29937,6 @@ inherit_rpath=$inherit_rpath_CXX
 # Whether libtool must link a program against all its dependency libraries.
 link_all_deplibs=$link_all_deplibs_CXX
 
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path=$lt_fix_srcfile_path_CXX
-
 # Set to "yes" if exported symbols are required.
 always_export_symbols=$always_export_symbols_CXX
 
@@ -26801,6 +29952,9 @@ include_expsyms=$lt_include_expsyms_CXX
 # Commands necessary for linking programs (against libraries) with templates.
 prelink_cmds=$lt_prelink_cmds_CXX
 
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds_CXX
+
 # Specify filename containing input files.
 file_list_spec=$lt_file_list_spec_CXX
 
@@ -26908,10 +30062,10 @@ echo "  CFITSIO support:           ${FITS_SETTING}"
 echo "  PCRaster support:          ${PCRASTER_SETTING}"
 
 
-echo "  NetCDF support:            ${NETCDF_SETTING}"
+echo "  LIBPNG support:            ${PNG_SETTING}"
 
 
-echo "  LIBPNG support:            ${PNG_SETTING}"
+echo "  GTA support:               ${GTA_SETTING}"
 
 
 echo "  LIBTIFF support:           ${TIFF_SETTING} (BigTIFF=${HAVE_BIGTIFF})"
@@ -26938,6 +30092,9 @@ echo "  HDF4 support:              ${HAVE_HDF4}"
 echo "  HDF5 support:              ${HAVE_HDF5}"
 
 
+echo "  NetCDF support:            ${NETCDF_SETTING}"
+
+
 echo "  Kakadu support:            ${HAVE_KAKADU}"
 
 if test "x$HAVE_JASPER_UUID" != "x" ; then
@@ -26971,6 +30128,9 @@ echo "  GRIB support:              ${HAVE_GRIB}"
 echo "  EPSILON support:           ${EPSILON_SETTING}"
 
 
+echo "  WebP support:              ${WEBP_SETTING}"
+
+
 echo "  cURL support (wms/wcs/...):${CURL_SETTING}"
 
 
@@ -27001,6 +30161,12 @@ echo "  ODBC support:              ${ODBC_SETTING}"
 echo "  PGeo support:              ${ODBC_SETTING}"
 
 
+echo "  FGDB support:              ${FGDB_ENABLED}"
+
+
+echo "  MDB support:               ${MDB_ENABLED}"
+
+
 echo "  PCIDSK support:            ${PCIDSK_SETTING}"
 
 
@@ -27040,9 +30206,18 @@ echo "  VFK support:               ${HAVE_VFK}"
 echo "  Poppler support:           ${HAVE_POPPLER}"
 
 
+echo "  Podofo support:            ${HAVE_PODOFO}"
+
+
 echo "  OpenCL support:            ${OPENCL_SETTING}"
 
 
+echo "  Armadillo support:         ${HAVE_ARMADILLO}"
+
+
+echo "  FreeXL support:            ${HAVE_FREEXL}"
+
+
 echo ""
 
 if test ! -z "`uname | grep Darwin`" ; then
@@ -27074,6 +30249,9 @@ echo "  enable OGR building:       ${OGR_ENABLED}"
 echo "  enable pthread support:    ${PTHREAD_ENABLED}"
 
 
+echo "  enable POSIX iconv support:${am_cv_func_iconv}"
+
+
 echo "  hide internal symbols:     ${HAVE_HIDE_INTERNAL_SYMBOLS}"
 
 
diff --git a/configure.in b/configure.in
index f674a56..a2f6ead 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 21532 2011-01-19 18:12:34Z kirk $
+dnl $Id: configure.in 23690 2012-01-03 18:56:17Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure source file.
@@ -34,7 +34,8 @@ define([AC_CACHE_SAVE], )
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(GDALmake.opt.in)
 AC_CONFIG_MACRO_DIR(m4)
-AC_CONFIG_HEADER(port/cpl_config.h:port/cpl_config.h.in:port/cpl_config_extras.h)
+AC_CONFIG_HEADERS([port/cpl_config.h:port/cpl_config.h.in])
+AH_BOTTOM([#include "cpl_config_extras.h"])
 
 dnl We require autoconf 2.52+ for libtool support on cygwin/mingw hosts
 AC_PREREQ(2.52)
@@ -60,7 +61,20 @@ AC_ARG_WITH(libtool, [  --without-libtool     Don't use libtool to build the lib
 
 if test "$with_libtool" = "no"; then
 AC_PROG_RANLIB
-AC_COMPILER_PIC
+
+dnl AC_COMPILER_PIC as expanded by autoconf-2.68 doesn't work for the C++ part with clang++ 3.0 that doesn't like compiling .c programs
+dnl so we inline the expanded code and fix it at hand.
+dnl AC_COMPILER_PIC
+	echo 'void f(){}' > conftest.c
+	if test -z "`${CC-cc} $CFLAGS -fPIC -c conftest.c 2>&1`"; then
+	  CFLAGS="$CFLAGS -fPIC"
+	fi
+	echo 'void f(){}' > conftest.cpp
+	if test -z "`${CXX-g++} $CXXFLAGS -fPIC -c conftest.cpp 2>&1`"; then
+	  CXXFLAGS="$CXXFLAGS -fPIC"
+	fi
+	rm -f conftest*
+
 AC_LD_SHARED
 else
 with_libtool=yes
@@ -207,7 +221,7 @@ dnl ---------------------------------------------------------------------------
 dnl Check if user requests hidding internal symbols
 dnl ---------------------------------------------------------------------------
 
-AC_ARG_WITH(with_hide_internal_symbols,[  --with-hide-internal-symbols[=ARG] Try to hide internal symbols (ARG=yes/no)],,)
+AC_ARG_WITH(hide_internal_symbols,[  --with-hide-internal-symbols[=ARG] Try to hide internal symbols (ARG=yes/no)],,)
 
 HAVE_HIDE_INTERNAL_SYMBOLS=no
 
@@ -243,6 +257,27 @@ fi
 AC_SUBST(HAVE_HIDE_INTERNAL_SYMBOLS,$HAVE_HIDE_INTERNAL_SYMBOLS)
 
 dnl ---------------------------------------------------------------------------
+dnl Check if user requests renaming internal libtiff symbols
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(rename_internal_libtiff_symbols,[  --with-rename-internal-libtiff-symbols[=ARG] Prefix internal libtiff symbols with gdal_ (ARG=yes/no)],,)
+if test "$with_rename_internal_libtiff_symbols" = ""; then
+    with_rename_internal_libtiff_symbols=no
+fi
+AC_SUBST(RENAME_INTERNAL_LIBTIFF_SYMBOLS,$with_rename_internal_libtiff_symbols)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if user requests renaming internal libgeotiff symbols
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(rename_internal_libgeotiff_symbols,[  --with-rename-internal-libgeotiff-symbols[=ARG] Prefix internal libgeotiff symbols with gdal_ (ARG=yes/no)],,)
+if test "$with_rename_internal_libgeotiff_symbols" = ""; then
+    with_rename_internal_libgeotiff_symbols=no
+fi
+AC_SUBST(RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS,$with_rename_internal_libgeotiff_symbols)
+
+
+dnl ---------------------------------------------------------------------------
 dnl Check if user requests /usr/local to be included.
 dnl ---------------------------------------------------------------------------
 
@@ -381,6 +416,35 @@ fi
 AC_SUBST(LIBZ_SETTING,$LIBZ_SETTING)
 
 dnl ---------------------------------------------------------------------------
+dnl Check for iconv/libiconv.
+dnl A rationale for this macro is described in "GNU `gettext' utilities"
+dnl manual at
+dnl http://www.gnu.org/software/gettext/manual/html_node/AM_005fICONV.html
+dnl ---------------------------------------------------------------------------
+AM_ICONV
+
+dnl Extra test needed for GCC 4.5 on Solaris 11, where there is
+dnl a different behaviour if the tests are compiled with gcc or g++.
+dnl So we introduce a ICONV_CPP_CONST that must be used instead of
+dnl ICONV_CONST when used from .cpp files.
+if test "$am_func_iconv" = "yes"; then
+    rm -f testiconv.*
+    echo '#include <iconv.h>' > testiconv.cpp
+    echo 'int main(int argc, char** argv) { iconv_t cd; return iconv (cd, (const char **) 0, 0, 0, 0); } ' >> testiconv.cpp
+    if test -z "`${CXX} testiconv.cpp -c 2>&1`" ; then
+        AC_MSG_RESULT([using ICONV_CPP_CONST="const"])
+        ICONV_CPP_CONST="const"
+    else
+        AC_MSG_RESULT([using ICONV_CPP_CONST=""])
+        ICONV_CPP_CONST=""
+    fi
+    rm -f testiconv.*
+
+    AC_DEFINE_UNQUOTED(ICONV_CPP_CONST,$ICONV_CPP_CONST, [For.cpp files, define as const if the declaration of iconv() needs const.])
+fi
+
+
+dnl ---------------------------------------------------------------------------
 dnl Check if liblzma is available.
 dnl ---------------------------------------------------------------------------
 
@@ -630,51 +694,6 @@ if test "$PCRASTER_SETTING" != "no" ; then
 fi
 
 dnl ---------------------------------------------------------------------------
-dnl Check if netcdf library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([netcdf],[  --with-netcdf[=ARG]     Include netCDF support (ARG=no or netCDF tree prefix)],,)
-
-if test "$with_netcdf" = "no" ; then
-
-  NETCDF_SETTING=no
-
-  echo "netCDF support disabled."
-
-elif test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
-
-  AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no],)
-
-  if test "$NETCDF_SETTING" = "yes" ; then   
-    LIBS="-lnetcdf $LIBS"
-    echo "using pre-installed libnetcdf."
-  else
-    echo "libnetcdf not found - netCDF support disabled"
-  fi
-
-dnl Fedora has netcdf headers in /usr/include/netcdf
-  if test "$NETCDF_SETTING" = "yes" -a -d /usr/include/netcdf ; then
-    EXTRA_INCLUDES="-I/usr/include/netcdf $EXTRA_INCLUDES"
-dnl RHEL 5 has netcdf headers in /usr/include/netcdf-3
-  elif test "$NETCDF_SETTING" = "yes" -a -d /usr/include/netcdf-3 ; then
-    EXTRA_INCLUDES="-I/usr/include/netcdf-3 $EXTRA_INCLUDES"
-  fi
-else
-
-  NETCDF_SETTING=yes
-  LIBS="-L$with_netcdf -L$with_netcdf/lib -lnetcdf $LIBS"
-  EXTRA_INCLUDES="-I$with_netcdf -I$with_netcdf/include $EXTRA_INCLUDES"
-
-  echo "using libnetcdf from $with_netcdf."
-fi
-
-AC_SUBST([NETCDF_SETTING], [$NETCDF_SETTING])
-
-if test "$NETCDF_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="netcdf $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
 dnl Select a PNG Library to use, or disable driver.
 dnl ---------------------------------------------------------------------------
 
@@ -726,6 +745,44 @@ if test "$PNG_SETTING" != "no" ; then
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl Check if GTA library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([gta],[  --with-gta[=ARG]        Include GTA support (ARG=no or libgta tree prefix)],,)
+
+if test "$with_gta" = "no" ; then
+
+  GTA_SETTING=no
+
+  echo "GTA support disabled."
+
+elif test "$with_gta" = "yes" -o "$with_gta" = "" ; then
+
+  AC_CHECK_LIB([gta], [gta_version], [GTA_SETTING=yes], [GTA_SETTING=no],)
+
+  if test "$GTA_SETTING" = "yes" ; then
+    LIBS="-lgta $LIBS"
+    echo "using pre-installed libgta."
+  else
+    echo "libgta not found - GTA support disabled"
+  fi
+
+else
+
+  GTA_SETTING=yes
+  LIBS="-L$with_gta -L$with_gta/lib -lgta $LIBS"
+  EXTRA_INCLUDES="-I$with_gta -I$with_gta/include $EXTRA_INCLUDES"
+
+  echo "using libgta from $with_gta."
+fi
+
+AC_SUBST([GTA_SETTING], [$GTA_SETTING])
+
+if test "$GTA_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="gta $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
 dnl Select PCIDSK options.
 dnl ---------------------------------------------------------------------------
 
@@ -1000,6 +1057,7 @@ if test "$with_gif" = "no" ; then
 elif test "$with_gif" = "yes" -o "$with_gif" = "" ; then
 
   AC_CHECK_LIB(gif,DGifOpenFileName,GIF_SETTING=external,GIF_SETTING=internal,)
+  AC_CHECK_HEADERS(gif_lib.h)
 
   if test "$GIF_SETTING" = "external" ; then   
     LIBS="-lgif $LIBS"
@@ -1345,6 +1403,143 @@ if test "$HAVE_HDF5" != "no" ; then
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl Check if netcdf library is available.
+dnl ---------------------------------------------------------------------------
+
+NETCDF_SETTING=
+NETCDF_ROOT=
+NETCDF_HAS_NC4=
+NETCDF_HAS_HDF4=
+
+AC_ARG_WITH([netcdf],[  --with-netcdf[=ARG]     Include netCDF support (ARG=no or netCDF tree prefix)],,)
+
+if test "$with_netcdf" = "no" ; then
+
+  NETCDF_SETTING=no
+
+  echo "netCDF support disabled."
+
+elif test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
+
+  AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no],)
+
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    dnl Fedora has netcdf headers in /usr/include/netcdf
+    if test -d /usr/include/netcdf ; then
+      EXTRA_INCLUDES="-I/usr/include/netcdf $EXTRA_INCLUDES"
+      NETCDF_ROOT="/usr"
+    dnl RHEL 5 has netcdf headers in /usr/include/netcdf-3
+    elif test -d /usr/include/netcdf-3 ; then
+      EXTRA_INCLUDES="-I/usr/include/netcdf-3 $EXTRA_INCLUDES"
+      NETCDF_ROOT="/usr"
+    dnl ubuntu and fedora have netcdf headers in /usr/include
+    elif test -f /usr/include/netcdf.h ; then
+      NETCDF_ROOT="/usr"
+    dnl try /usr/local
+    elif test -f /usr/local/include/netcdf.h ; then
+      NETCDF_ROOT="/usr/local"
+    dnl print warning if include cannot be found
+    else
+      echo "using pre-installed libnetcdf."
+      echo -n "libnetcdf is installed but its location cannot be found, "
+      echo "use --with-netcdf=/path_to_netcdf for proper support"
+    fi
+
+    LIBS="-lnetcdf $LIBS"
+    if test "$NETCDF_ROOT" != "" ; then
+      echo "using pre-installed libnetcdf from "$NETCDF_ROOT
+    fi
+
+  else
+    echo "libnetcdf not found - netCDF support disabled"
+  fi
+
+else
+
+  AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no],-L$with_netcdf -L$with_netcdf/lib)
+
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    NETCDF_SETTING=yes
+    NETCDF_ROOT="$with_netcdf"
+
+    if test -d $with_netcdf/lib ; then
+      LIBS="-L$with_netcdf/lib -lnetcdf $LIBS"
+      EXTRA_INCLUDES="-I$with_netcdf/include $EXTRA_INCLUDES"
+    else
+      LIBS="-L$with_netcdf -lnetcdf $LIBS"
+      EXTRA_INCLUDES="-I$with_netcdf $EXTRA_INCLUDES"
+    fi
+
+    echo "using libnetcdf from $with_netcdf"
+
+  else
+    echo "libnetcdf not found in "$with_netcdf" - netCDF support disabled"
+  fi
+
+fi
+
+dnl start new test
+
+dnl test for NC4 and HDF4 support
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    ncdump=$NETCDF_ROOT"/bin/ncdump" 
+    nc_config=""
+
+    dnl test for libnetcdf v4
+    if { test -x "$ncdump"; }; then
+      AC_MSG_CHECKING([libnetcdf version with $ncdump]) 
+      netcdf_version=`$ncdump 2>&1 | grep "netcdf library version" | awk '{gsub(/"/,"");print $4}'`
+      AC_MSG_RESULT([got $netcdf_version])
+      if test "$netcdf_version" != "" -a "${netcdf_version:0:1}" == "4" ; then
+          nc_config=$NETCDF_ROOT"/bin/nc-config"
+      fi
+    fi
+
+    dnl if nc-config is found (only for libnetcdf-4), test for netcdf-4 and HDF4 support 
+    if { test -x "$nc_config"; }; then
+      echo "checking libnetcdf config with $nc_config"
+
+      AC_MSG_CHECKING([for netcdf-4 (and HDF5) support in libnetcdf])
+        if test "x$($nc_config --has-nc4)" = "xyes"; then :
+          AC_MSG_RESULT([yes])
+          NETCDF_HAS_NC4=yes
+        else
+          AC_MSG_RESULT([no])
+          NETCDF_HAS_NC4=no
+        fi
+
+      AC_MSG_CHECKING([for HDF4 support in libnetcdf])
+        if test "x$($nc_config --has-hdf4)" = "xyes"; then :
+          AC_MSG_RESULT([yes])
+          NETCDF_HAS_HDF4=yes
+        else
+          AC_MSG_RESULT([no])
+          NETCDF_HAS_HDF4=no
+        fi
+
+    else
+      AC_MSG_RESULT([ncdump and/or nc-config not found, skipping netcdf-4 tests])
+      NETCDF_HAS_NC4=no
+      NETCDF_HAS_HDF4=no
+    fi
+fi
+
+dnl end new test
+
+AC_SUBST([NETCDF_SETTING], [$NETCDF_SETTING])
+AC_SUBST([NETCDF_ROOT], [$NETCDF_ROOT])
+AC_SUBST([NETCDF_HAS_NC4], [$NETCDF_HAS_NC4])
+AC_SUBST([NETCDF_HAS_HDF4], [$NETCDF_HAS_HDF4])
+
+if test "$NETCDF_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="netcdf $OPT_GDAL_FORMATS"
+fi
+
+
+dnl ---------------------------------------------------------------------------
 dnl Select a JasPer Library to use, or disable driver.
 dnl ---------------------------------------------------------------------------
 
@@ -1444,6 +1639,53 @@ fi
 
 AC_SUBST([HAVE_OPENJPEG],$HAVE_OPENJPEG)
 
+
+
+dnl ---------------------------------------------------------------------------
+dnl Select a FGDB API to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(fgdb,[  --with-fgdb[=ARG]        Include ESRI File Geodatabase support (ARG=FGDP API Path, yes or no)],,)
+
+if test "$with_fgdb" = "no" ; then
+
+  FGDB_ENABLED=no
+
+  echo "FGDB support disabled."
+
+elif test "$with_fgdb" = "yes" -o "$with_fgdb" = "" ; then
+
+  AC_CHECK_LIB(FileGDBAPI,OpenGeodatabase,FGDB_ENABLED=yes,FGDB_ENABLED=no,-lFileGDBAPI -lfgdblinuxrtl)
+
+  if test "$FGDB_ENABLED" = "yes" ; then   
+    LIBS="-lFileGDBAPI -lfgdblinuxrtl"
+  fi
+
+else
+
+  AC_MSG_CHECKING([for libFileGDBAPI.so in in $with_fgdb/lib])
+  FGDB_ENABLED=yes
+  if test -r $with_fgdb/lib/libFileGDBAPI.so ; then
+    AC_MSG_RESULT([found.])
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdblinuxrtl"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+  AC_MSG_CHECKING([for FileGDBAPI.h in $with_fgdb/include])
+  if test -r $with_fgdb/include/FileGDBAPI.h ; then  
+    AC_MSG_RESULT([found.])
+    FGDB_INC="-I$with_fgdb/include"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+fi
+
+AC_SUBST(FGDB_ENABLED, $FGDB_ENABLED)
+AC_SUBST(FGDB_LIB, $FGDB_LIB)
+AC_SUBST(FGDB_INC, $FGDB_INC)
+
 dnl ---------------------------------------------------------------------------
 dnl Select a ECW Library to use, or disable driver.
 dnl ---------------------------------------------------------------------------
@@ -1467,7 +1709,7 @@ elif test "$with_ecw" = "yes" -o "$with_ecw" = "" ; then
   AC_CHECK_LIB(NCSEcw,NCScbmOpenFileView,ECW_SETTING=yes,ECW_SETTING=no,-lNCSCnet -lNCSUtil)
 
   if test "$ECW_SETTING" = "yes" ; then   
-    LIBS="-lNCSEcw -lNCSCnet -lNCSUtil $LIBS"
+    LIBS="-lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil $LIBS"
   fi
 
   if test "$ECW_SETTING" = "no" ; then
@@ -1482,13 +1724,13 @@ else
   AC_MSG_CHECKING([for libNCSEcw.so or libecwj2])
   ECW_SETTING=yes
   if test -r $with_ecw/lib/libNCSCnet.so -o -r $with_ecw/lib/libNCSCnet.dylib ; then
-    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSCnet -lNCSUtil $LIBS"
+    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil $LIBS"
     AC_MSG_RESULT([found in $with_ecw/lib.])
   elif test -r $with_ecw/lib/libNCSCNet.so -o -r $with_ecw/lib/libNCSCNet.dylib ; then
-    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSCNet -lNCSUtil $LIBS"
+    LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCNet -lNCSUtil $LIBS"
     AC_MSG_RESULT([found in $with_ecw/lib.])
   elif test -r $with_ecw/bin/libNCSEcw.so -o -r $with_ecw/bin/libNCSEcw.dylib ; then
-    LIBS="-L$with_ecw/bin -lNCSEcw -lNCSCnet -lNCSUtil $LIBS"
+    LIBS="-L$with_ecw/bin -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil $LIBS"
     AC_MSG_RESULT([found in $with_ecw/bin.])
   elif test -r $with_ecw/lib/libecwj2.dylib ; then
     LIBS="-L$with_ecw/lib -lecwj2 $CARBON_FRAMEWORK $LIBS"
@@ -1625,7 +1867,8 @@ else
         elif test -r "$with_mrsid/3rd-party/$_LIBPART/liblt_kakadu.a" ; then 
           with_jp2mrsid=yes
           MRSID_KAKADU_LIB=-llt_kakadu
-        elif test -L "$with_mrsid/lib/libltidsdk.so"; then # v8+ .so has kdu
+        elif test -e "$with_mrsid/lib/libltidsdk.so" \
+               -o -e "$with_mrsid/lib/libltidsdk.dylib"; then # v8+ .so has kdu
           with_jp2mrsid=yes
         elif test x"$with_jp2mrsid" = x"yes" ; then
           AC_MSG_ERROR([MrSID JPEG2000 support requested, but libltikdu.a not found.])
@@ -2028,7 +2271,7 @@ else
 
 dnl Test if we have libdap >= 3.10
 dnl From libdap 3.10, AISConnect.h has been renamed as Connect.h
-rm -f islibdappre310.*
+rm -f islibdappost310.*
 echo '#include "Connect.h"' > islibdappost310.cpp
 echo 'int main(int argc, char** argv) { return 0; } ' >> islibdappost310.cpp
 if test -z "`${CXX} islibdappost310.cpp -c ${DODS_INC} 2>&1`" ; then
@@ -2056,7 +2299,7 @@ else
     rm -f islibdappre39.*
 
 fi
-rm -f islibdappre310.*
+rm -f islibdappost310.*
 
 
     dnl Add the DODS libraries to LIBS
@@ -2125,7 +2368,7 @@ if test "$LIBCURL_CONFIG" != "no" ; then
 
   AC_MSG_RESULT([        found libcurl version $CURL_VER])
   
-  AC_CHECK_LIB(curl,curl_global_init,CURL_SETTING=yes,CURL_SETTING=no,)
+  AC_CHECK_LIB(curl,curl_global_init,CURL_SETTING=yes,CURL_SETTING=no,`$LIBCURL_CONFIG --libs`)
 
 fi
 
@@ -2150,15 +2393,25 @@ AC_ARG_WITH(spatialite,
     ,,)
 
 HAVE_SPATIALITE=no
+SPATIALITE_AMALGAMATION=no
 
 if test -z "$with_spatialite" -o "$with_spatialite" = "no"; then
     AC_MSG_RESULT(disabled)
 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"
-        HAVE_SQLITE3=yes
+    AC_CHECK_HEADERS(sqlite3.h)
+    if test "$ac_cv_header_sqlite3_h" = "yes"; then
+        AC_MSG_CHECKING([for spatialite.h in /usr/include or /usr/local/include])
+        if test -f "/usr/include/spatialite.h" -o -f "/usr/local/include/spatialite.h"; then
+            AC_MSG_RESULT(found)
+            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"
+                HAVE_SQLITE3=yes
+            fi
+        else
+            AC_MSG_RESULT(not found : spatialite support disabled)
+        fi
     fi
 else
     AC_CHECK_LIB(spatialite,spatialite_init,SPATIALITE_INIT_FOUND=yes,SPATIALITE_INIT_FOUND=no,-L$with_spatialite/lib -lspatialite)
@@ -2168,20 +2421,34 @@ else
 
         AC_MSG_RESULT(enabled)
         HAVE_SPATIALITE=yes
+        SPATIALITE_AMALGAMATION=yes
 
-        # SpatiaLite availability implies SQLite availability
+        # SpatiaLite amalgamation availability implies SQLite availability
         # Caution : don't include the include/spatialite subdir in the include dir
         # 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"
         HAVE_SQLITE3=yes
+
+    elif test -f "$with_spatialite/include/spatialite.h" -a \
+        "$SPATIALITE_INIT_FOUND" = "yes"; then
+        AC_CHECK_HEADERS(sqlite3.h)
+        if test "$ac_cv_header_sqlite3_h" = "yes"; then
+            AC_MSG_RESULT(enabled)
+            SPATIALITE_INC="-I$with_spatialite/include"
+            HAVE_SPATIALITE=yes
+            LIBS="$LIBS -L$with_spatialite/lib -lspatialite"
+            HAVE_SQLITE3=yes
+        fi
     else
         AC_MSG_RESULT(disabled)
     fi
 fi
 
 AC_SUBST([HAVE_SPATIALITE], $HAVE_SPATIALITE)
+AC_SUBST([SPATIALITE_INC], $SPATIALITE_INC)
+AC_SUBST([SPATIALITE_AMALGAMATION], $SPATIALITE_AMALGAMATION)
 
 dnl ---------------------------------------------------------------------------
 dnl Check for SQLite (only if SpatiaLite is not detected)
@@ -2335,6 +2602,11 @@ elif test -n "$with_sde" -a "$with_sde" != "no" ; then
       AC_MSG_ERROR("Could not find sdetype.h or libsde$SDE_VERSION.a/libsde$SDE_VERSION.so in $SDE_DIR.")
   fi
 
+  if test "`arch`" = "x86_64" ; then
+    AC_MSG_RESULT([        Adding -DSDE64 for 64bit platform.])
+    SDE_INC="$SDE_INC -DSDE64"
+  fi
+
   SDE_ENABLED=yes
   OPT_GDAL_FORMATS="sde $OPT_GDAL_FORMATS"
   AC_MSG_RESULT([        using ESRI SDE from $SDE_DIR.])
@@ -2413,6 +2685,41 @@ if test "$EPSILON_SETTING" != "no" ; then
 fi
 
 dnl ---------------------------------------------------------------------------
+dnl Check if webp library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(webp,[  --with-webp[=ARG]    Include WEBP support (ARG=no, yes or libwebp install root path)],,)
+
+WEBP_SETTING=no
+
+if test "$with_webp" = "yes" ; then
+
+  AC_CHECK_LIB(webp,WebPDecodeRGB,WEBP_SETTING=yes,WEBP_SETTING=no,)
+
+  if test "$WEBP_SETTING" = "yes" ; then
+    LIBS="-lwebp $LIBS"
+  else
+    echo "libwebp not found - WEBP support disabled"
+  fi
+
+elif test "$with_webp" != "no" -a "$with_webp" != ""; then
+
+  AC_CHECK_LIB(webp,WebPDecodeRGB,WEBP_SETTING=yes,WEBP_SETTING=no,-L$with_webp/lib -lwebp)
+
+  if test "$WEBP_SETTING" = "yes" ; then
+    LIBS="-L$with_webp/lib -lwebp $LIBS"
+    EXTRA_INCLUDES="-I$with_webp/include $EXTRA_INCLUDES"
+  else
+    echo "libwebp not found - WEBP support disabled"
+  fi
+
+fi
+
+if test "$WEBP_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="webp $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
 dnl Check if geos library is available.
 dnl ---------------------------------------------------------------------------
 
@@ -2471,6 +2778,92 @@ AC_MSG_RESULT([$OPENCL_SETTING])
 AC_SUBST(OPENCL_FLAGS,  $OPENCL_FLAGS)
 AC_SUBST(OPENCL_LIB,    $OPENCL_LIB)
 
+
+dnl ---------------------------------------------------------------------------
+dnl Check if FreeXL library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(freexl,[  --with-freexl[=ARG]    Include freexl support (ARG=no, yes (default) or libfreexl install path)],,)
+
+AC_MSG_CHECKING([for FreeXL support])
+
+HAVE_FREEXL=no
+FREEXL_INCLUDE=
+
+if test "$with_freexl" = "" -o "$with_freexl" = "yes" ; then
+  AC_CHECK_HEADERS(freexl.h)
+  AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl",FREEXL_LIBS=missing)
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv",FREEXL_LIBS=missing,-liconv)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv -lcharset",FREEXL_LIBS=missing,-liconv -lcharset)
+  fi
+
+  if test "$FREEXL_LIBS" != "missing" -a "$ac_cv_header_freexl_h" = "yes" ; then
+
+    # Check that freexl is recent enough
+    rm -f testrlist.*
+    echo '#include <freexl.h>' > testfreexl.c
+    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
+    if test -z "`${CC} testfreexl.c -c 2>&1`" ; then
+        HAVE_FREEXL=yes
+        LIBS="$FREEXL_LIBS $LIBS"
+    else
+        HAVE_FREEXL=no
+        AC_MSG_RESULT([freexl too old. Needs freexl >= 1.0])
+    fi
+    rm -f testfreexl.*
+
+  else
+    HAVE_FREEXL=no
+    echo "libfreexl not found - FreeXL support disabled"
+  fi
+
+elif test "$with_freexl" != "no"; then
+
+  AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl",FREEXL_LIBS=missing,-L$with_freexl/lib)
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv -lcharset",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv -lcharset)
+  fi
+
+  if test "FREEXL_LIBS" != "missing" -a -f "$with_freexl/include/freexl.h" ; then
+
+    # Check that freexl is recent enough
+    rm -f testrlist.*
+    echo '#include <freexl.h>' > testfreexl.c
+    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
+    if test -z "`${CC} -I$with_freexl/include testfreexl.c -c 2>&1`" ; then
+        HAVE_FREEXL=yes
+        LIBS="$FREEXL_LIBS $LIBS"
+        FREEXL_INCLUDE="-I$with_freexl/include"
+    else
+        HAVE_FREEXL=no
+        AC_MSG_RESULT([freexl too old. Needs freexl >= 1.0])
+    fi
+    rm -f testfreexl.*
+
+  else
+    HAVE_FREEXL=no
+    echo "libfreexl not found - FreeXL support disabled"
+  fi
+
+fi
+
+AC_SUBST(HAVE_FREEXL,  $HAVE_FREEXL)
+AC_SUBST(FREEXL_INCLUDE,  $FREEXL_INCLUDE)
+
 dnl ---------------------------------------------------------------------------
 dnl Check if we must enable PAM
 dnl ---------------------------------------------------------------------------
@@ -2576,6 +2969,87 @@ AC_SUBST(POPPLER_BASE_STREAM_HAS_TWO_ARGS, $POPPLER_BASE_STREAM_HAS_TWO_ARGS)
 AC_SUBST(POPPLER_INC, $POPPLER_INC)
 
 dnl ---------------------------------------------------------------------------
+dnl Check if libpodofo is available
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(podofo,[  --with-podofo[=ARG]    Include podofo(for PDF) support (ARG=no(default), yes or podofo install path)],,)
+
+HAVE_PODOFO=no
+
+AC_MSG_CHECKING([for podofo])
+
+if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
+
+    AC_ARG_WITH(podofo-lib,
+      [  --with-podofo-lib=ARG   podofo Link Flags (ie. -L/xxx -lpodofo ...). Mainly for static libpodofo],,,)
+
+    if test "$HAVE_POPPLER" = "yes"; then
+        AC_MSG_ERROR([--with-podofo and --with-poppler cannot be specified at the same time])
+    fi
+
+    if test "$with_podofo" = "yes" ; then
+        TEST_PODOFO_INC="-I/usr/include -I/usr/include/podofo"
+        PODOFO_LIB="-lpodofo"
+    else
+        TEST_PODOFO_INC="-I$with_podofo/include -I$with_podofo/include/podofo"
+        PODOFO_LIB="-L$with_podofo/lib -lpodofo"
+    fi
+
+    if test "x$with_podofo_lib" = "x" ; then
+        rm -f testpodofo.*
+        echo '#include <podofo.h>' > testpodofo.cpp
+        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
+        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB}  2>&1`" ; then
+            HAVE_PODOFO=yes
+            LIBS="${PODOFO_LIB} ${LIBS}"
+            OPT_GDAL_FORMATS="pdf $OPT_GDAL_FORMATS"
+            PODOFO_INC=$TEST_PODOFO_INC
+            AC_MSG_RESULT([yes])
+        fi
+        rm -f testpodofo.*
+        rm -f testpodofo
+    fi
+
+    if test "$HAVE_PODOFO" = "no"; then
+        if test "x$with_podofo_lib" != "x" ; then
+            PODOFO_LIB="$with_podofo_lib"
+        else
+            # This may be a static libpodofo.a, so add dependant libraries
+            PODOFO_LIB="$PODOFO_LIB -lfreetype -lfontconfig -lpthread"
+        fi
+
+        AC_ARG_WITH(podofo-extra-lib-for-test,
+          [  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (ie. -ljpeg ...). Mainly for static libpodofo],,,)
+
+        if test "x$with_podofo_extra_lib_for_test" = "x" ; then
+            TEST_PODOFO_LIB="$PODOFO_LIB"
+        else
+            TEST_PODOFO_LIB="$PODOFO_LIB $with_podofo_extra_lib_for_test"
+        fi
+
+        rm -f testpodofo.*
+        echo '#include <podofo.h>' > testpodofo.cpp
+        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
+        if test -z "`${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>&1`" ; then
+            HAVE_PODOFO=yes
+            LIBS="${PODOFO_LIB} ${LIBS}"
+            OPT_GDAL_FORMATS="pdf $OPT_GDAL_FORMATS"
+            PODOFO_INC=$TEST_PODOFO_INC
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testpodofo.*
+        rm -f testpodofo
+    fi
+else
+    AC_MSG_RESULT([disabled])
+fi
+
+AC_SUBST(HAVE_PODOFO, $HAVE_PODOFO)
+AC_SUBST(PODOFO_INC, $PODOFO_INC)
+
+dnl ---------------------------------------------------------------------------
 dnl PROJ.4 related stuff.
 dnl ---------------------------------------------------------------------------
 
@@ -2852,6 +3326,161 @@ AC_SUBST([PY_HAVE_SETUPTOOLS])
 AC_SUBST([BINDINGS])
 
 dnl ---------------------------------------------------------------------------
+dnl Java support
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(java,[  --with-java       Include Java support (ARG=yes, no or JDK home path)  [[default=no]]],,)
+
+AC_MSG_CHECKING([whether we should include Java support])
+
+JAVA_HOME=""
+JAVA_INC=""
+
+if test "x$with_java" = "xyes"; then
+
+dnl Ubuntu
+    if test -d /usr/lib/jvm/java-6-openjdk; then
+        with_java="/usr/lib/jvm/java-6-openjdk"
+
+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"
+    else
+        AC_MSG_ERROR("cannot find JDK root directory.")
+    fi
+
+    if test \! -d "$with_java/include" ; then
+        AC_MSG_ERROR("$with_java is not a valid JDK.")
+    fi
+fi
+
+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/include/linux"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
+            AC_MSG_RESULT([yes])
+        elif test -d "$with_java/include/solaris"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/solaris"
+            AC_MSG_RESULT([yes])
+        elif test -d "$with_java/include/freebsd"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/freebsd"
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_ERROR("Cannot find $with_java/include/linux or solaris or freebsd directory.")
+        fi
+    else
+        AC_MSG_ERROR("Cannot find $with_java/include directory.")
+    fi
+
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(JAVA_HOME,$JAVA_HOME)
+AC_SUBST(JAVA_INC,$JAVA_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl MDB driver
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(mdb,[  --with-mdb       Include MDB driver],,)
+
+AC_MSG_CHECKING([whether we should include MDB support])
+
+MDB_ENABLED=no
+JVM_LIB=""
+
+if test "$with_mdb" = "yes" ; then
+    if test "x$JAVA_INC" = "x"; then
+        AC_MSG_ERROR("--with-java must be specified.")
+    fi
+
+    AC_ARG_WITH(jvm-lib,          [  --with-jvm-lib=[ARG]        ARG points to Java libjvm path],,)
+
+    AC_ARG_WITH(jvm-lib-add-rpath,[  --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)],,)
+
+    if test "x$with_jvm_lib" != "x"; 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,)
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$with_jvm_lib -ljvm"
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
+                fi
+            else
+                AC_MSG_ERROR("--with-jvm-lib must point to a directory with a libjvm.")
+            fi
+        else
+            AC_MSG_ERROR("--with-jvm-lib must point to a directory.")
+        fi
+    elif test "x$JAVA_HOME" != "x"; then
+        TEST_DIR="$JAVA_HOME/jre/lib/amd64/server"
+        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,)
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                fi
+            fi
+        fi
+
+        TEST_DIR="$JAVA_HOME/jre/lib/i386/server"
+        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,)
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                fi
+            fi
+        fi
+
+        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
+
+    MDB_ENABLED=yes
+    AC_MSG_RESULT([yes])
+
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MDB_ENABLED,$MDB_ENABLED)
+AC_SUBST(JVM_LIB,$JVM_LIB)
+
+
+dnl ---------------------------------------------------------------------------
 dnl Select Rasdaman or disable driver.
 dnl ---------------------------------------------------------------------------
 
@@ -2867,6 +3496,7 @@ if test "$with_rasdaman" = "yes" ; then
 
   if test -n "$RASDAMAN_ENABLED" ; then
       RASDAMAN_LIB="-lrasodmg -lclientcomm -lcompression -lnetwork -lraslib"
+      OPT_GDAL_FORMATS="rasdaman $OPT_GDAL_FORMATS"
       AC_MSG_RESULT([        using rasdaman from system libs.])
   else
       AC_MSG_WARN([        rasdaman not found in system libs... use --with-rasdaman=DIR.])
@@ -2896,6 +3526,36 @@ AC_SUBST(RASDAMAN_ENABLED,$RASDAMAN_ENABLED)
 AC_SUBST(RASDAMAN_INC,    $RASDAMAN_INC)
 AC_SUBST(RASDAMAN_LIB,    $RASDAMAN_LIB)
 
+dnl ---------------------------------------------------------------------------
+dnl Armadillo support
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(armadillo,[  --with-armadillo=ARG       Include Armadillo support for faster TPS transform computation (ARG=yes/no) [[default=no]]],,)
+
+AC_MSG_CHECKING([whether we should include Armadillo support])
+
+HAVE_ARMADILLO=no
+
+if test "$with_armadillo" = "yes" ; then
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+    echo '#include <armadillo>' > testarmadillo.cpp
+    echo 'int main(int argc, char** argv) { arma::mat matInput(2,2); const arma::mat& matInv = arma::inv(matInput); return 0; } ' >> testarmadillo.cpp
+    if test -z "`${CXX} testarmadillo.cpp -o testarmadillo -larmadillo 2>&1`" ; then
+        HAVE_ARMADILLO=yes
+        LIBS="-larmadillo ${LIBS}"
+        AC_MSG_RESULT([yes])
+    else
+        AC_MSG_RESULT([no])
+    fi
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(HAVE_ARMADILLO,$HAVE_ARMADILLO)
+
 
 AC_OUTPUT(GDALmake.opt)
 
@@ -2917,8 +3577,8 @@ LOC_MSG([  LIBLZMA support:           ${LIBLZMA_SETTING}])
 LOC_MSG([  GRASS support:             ${GRASS_SETTING}])
 LOC_MSG([  CFITSIO support:           ${FITS_SETTING}])
 LOC_MSG([  PCRaster support:          ${PCRASTER_SETTING}])
-LOC_MSG([  NetCDF support:            ${NETCDF_SETTING}])
 LOC_MSG([  LIBPNG support:            ${PNG_SETTING}])
+LOC_MSG([  GTA support:               ${GTA_SETTING}]) 
 LOC_MSG([  LIBTIFF support:           ${TIFF_SETTING} (BigTIFF=${HAVE_BIGTIFF})])
 LOC_MSG([  LIBGEOTIFF support:        ${GEOTIFF_SETTING}])
 LOC_MSG([  LIBJPEG support:           ${JPEG_SETTING}])
@@ -2927,6 +3587,7 @@ LOC_MSG([  LIBGIF support:            ${GIF_SETTING}])
 LOC_MSG([  OGDI support:              ${HAVE_OGDI}])
 LOC_MSG([  HDF4 support:              ${HAVE_HDF4}])
 LOC_MSG([  HDF5 support:              ${HAVE_HDF5}])
+LOC_MSG([  NetCDF support:            ${NETCDF_SETTING}])
 LOC_MSG([  Kakadu support:            ${HAVE_KAKADU}])
 if test "x$HAVE_JASPER_UUID" != "x" ; then
   LOC_MSG([  JasPer support:            ${HAVE_JASPER} (GeoJP2=${HAVE_JASPER_UUID})])
@@ -2940,6 +3601,7 @@ LOC_MSG([  MrSID/MG4 Lidar support:   ${HAVE_MRSID_LIDAR}])
 LOC_MSG([  MSG support:               ${HAVE_MSG}])
 LOC_MSG([  GRIB support:              ${HAVE_GRIB}])
 LOC_MSG([  EPSILON support:           ${EPSILON_SETTING}])
+LOC_MSG([  WebP support:              ${WEBP_SETTING}])
 LOC_MSG([  cURL support (wms/wcs/...):${CURL_SETTING}])
 LOC_MSG([  PostgreSQL support:        ${HAVE_PG}])
 LOC_MSG([  MySQL support:             ${HAVE_MYSQL}])
@@ -2950,6 +3612,8 @@ LOC_MSG([  Expat support:             ${HAVE_EXPAT}])
 LOC_MSG([  Google libkml support:     ${HAVE_LIBKML}])
 LOC_MSG([  ODBC support:              ${ODBC_SETTING}])
 LOC_MSG([  PGeo support:              ${ODBC_SETTING}])
+LOC_MSG([  FGDB support:              ${FGDB_ENABLED}])
+LOC_MSG([  MDB support:               ${MDB_ENABLED}])
 LOC_MSG([  PCIDSK support:            ${PCIDSK_SETTING}])
 LOC_MSG([  OCI support:               ${HAVE_OCI}])
 LOC_MSG([  GEORASTER support:         ${HAVE_GEORASTER}])
@@ -2963,7 +3627,10 @@ LOC_MSG([  INFORMIX DataBlade support:${HAVE_IDB}])
 LOC_MSG([  GEOS support:              ${HAVE_GEOS_RESULT}])
 LOC_MSG([  VFK support:               ${HAVE_VFK}])
 LOC_MSG([  Poppler support:           ${HAVE_POPPLER}])
+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()
 if test ! -z "`uname | grep Darwin`" ; then
   LOC_MSG([  Mac OS X Framework :       ${MACOSX_FRAMEWORK}])
@@ -2979,6 +3646,7 @@ LOC_MSG()
 LOC_MSG([  Statically link PROJ.4:    ${PROJ_STATIC}])
 LOC_MSG([  enable OGR building:       ${OGR_ENABLED}])
 LOC_MSG([  enable pthread support:    ${PTHREAD_ENABLED}])
+LOC_MSG([  enable POSIX iconv support:${am_cv_func_iconv}])
 LOC_MSG([  hide internal symbols:     ${HAVE_HIDE_INTERNAL_SYMBOLS}])
 LOC_MSG()
 
diff --git a/data/compdcs.csv b/data/compdcs.csv
index a620c12..1a0c666 100644
--- a/data/compdcs.csv
+++ b/data/compdcs.csv
@@ -1,14 +1,18 @@
 "COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","CMPD_HORIZCRS_CODE","CMPD_VERTCRS_CODE","SHOW_CRS","DEPRECATED"
+3901,"KKJ / Finland Uniform Coordinate System + N60 height",2393,5717,1,0
+3902,"ETRS89 / TM35FIN(N,E) + N60 height",5048,5717,1,0
+3903,"ETRS89 / TM35FIN(N,E) + N2000 height",5048,3900,1,0
 4097,"ETRS89 / DKTM1 + DVR90 height",4093,5799,1,0
 4098,"ETRS89 / DKTM2 + DVR90 height",4094,5799,1,0
 4099,"ETRS89 / DKTM3 + DVR90 height",4095,5799,1,0
 4100,"ETRS89 / DKTM4 + DVR90 height",4096,5799,1,0
+5318,"ETRS89 / Faroe TM + FVR09 height",5316,5317,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
 7403,"NTF (Paris) / France III + NGF IGN69",27583,5720,1,1
 7404,"RT90 + RH70 height",4124,5718,1,0
-7405,"OSGB36 / British National Grid + ODN height",27700,5701,1,0
+7405,"OSGB 1936 / British National Grid + ODN height",27700,5701,1,0
 7406,"NAD27 + NGVD29 height",4267,5702,1,0
 7407,"NAD27 / Texas North + NGVD29 height",32037,5702,1,0
 7408,"RD/NAP",4289,5709,1,1
diff --git a/data/coordinate_axis.csv b/data/coordinate_axis.csv
index 31aceea..29042a4 100644
--- a/data/coordinate_axis.csv
+++ b/data/coordinate_axis.csv
@@ -1,6 +1,14 @@
 coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviation,uom_code,coord_axis_order
 1024,9906,east,M,9001,1
 1024,9907,north,P,9001,2
+1025,9906,North along 130°W,X,9001,1
+1025,9907,North along 140°E,Y,9001,2
+1026,9906,South along 90°E,E,9001,1
+1026,9907,South along 180°E,N,9001,2
+1027,9906,North along 90°E,E,9001,1
+1027,9907,North along 0°E,N,9001,2
+1028,9906,east,E,9037,1
+1028,9907,north,N,9037,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 f62f284..a04e095 100644
--- a/data/datum_shift.csv
+++ b/data/datum_shift.csv
@@ -2,714 +2,758 @@
 1,1825,4611,4326,Published 1st March 2002.,Accuracy to 1m level.,1118,22.16,22.62,113.89,114.57,1,0,9606,-162.619,-276.959,-161.764,0.067753,-2.243649,-1.158827,-1.094246,1
 2,1826,4612,4326,,"Approximation at the +/- 1m level.",1129,19.01,45.92,122.49,160.09,1,0,9603,0,0,0,,,,,1
 3,1838,4613,4326,Datum shift derived through ITRF93.,Oil exploration.,1328,-1.35,0,116.9,118,1,0,9603,-404.78,685.68,45.47,,,,,0
-4,1897,4613,4326,Accuracy estimate not available.,For military purposes.,2354,-5.72,4.4,104.94,119.62,1,0,9603,-403,684,41,,,,,1
+4,1897,4613,4326,Accuracy estimate not available.,For military purposes.,1360,-5.72,4.4,113.69,119.62,1,0,9603,-403,684,41,,,,,1
 5,1898,4613,4326,,Oil exploration.,1360,-5.72,4.4,113.69,119.62,1,0,9603,-387.06,636.53,46.29,,,,,0
 6,1899,4613,4326,,Oil exploration.,2770,-2.35,4.4,113.7,119.62,1,0,9603,-403.4,681.12,46.56,,,,,0
 7,1840,4614,4326,"Transformation defines QND95. May be approximated to 1m throughout Qatar by geocentric translation transformation with dX=-127.78098m, dY=-283.37477m, dZ=+21.24081m.",Parameter values are defined and therefore exact.,1346,24.48,26.18,50.75,51.64,1,0,9606,-119.4248,-303.65872,-11.00061,1.164298,0.174458,1.096259,3.657065,1
 8,1888,4615,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1314,32.39,33.15,-17.27,-16.25,1,0,9603,-499,-249,314,,,,,1
 9,1889,4616,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,2779,30.1,30.2,-15.9,-15.8,1,1,9603,-289,-124,60,,,,,0
 10,1965,4616,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,2779,30.1,30.2,-15.9,-15.8,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,41.68,85.05,-141.15,-48.06,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,41.68,85.05,-141.15,-48.06,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.",1341,-56.15,13,-82,-34,1,0,9603,-57,1,-41,,,,,1
-14,1865,4618,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-60.04,-21.8,-73.62,-53.5,1,0,9603,-62,-1,-37,,,,,0
-15,1866,4618,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.91,-9.69,-69.69,-57.49,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.",1053,-35.89,7.25,-74.05,-26.12,1,0,9603,-60,-2,-41,,,,,0
-17,1868,4618,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-60.04,-17.52,-113.28,-66.39,1,0,9603,-75,-1,-44,,,,,0
-18,1869,4618,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.22,15.93,-85.79,-66.91,1,0,9603,-44,6,-36,,,,,0
-19,1870,4618,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,3241,-5.01,1.5,-81.45,-75.26,1,0,9603,-48,3,-44,,,,,0
-20,1871,4618,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.6,1.75,-92,-89,1,0,9603,-47,26,-42,,,,,0
-21,1872,4618,4326,Derived at 5 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",1114,1.19,11.98,-61.43,-55.72,1,0,9603,-53,3,-47,,,,,0
-22,1873,4618,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.6,-19.31,-62.68,-54.28,1,0,9603,-61,2,-33,,,,,0
-23,1874,4618,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-20.72,-0.03,-84.73,-68.72,1,0,9603,-58,0,-44,,,,,0
-24,1875,4618,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.82,11.68,-62.08,-58.53,1,0,9603,-45,12,-33,,,,,0
-25,1876,4618,4326,Derived at 5 stations.,"For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",1251,0.65,16.76,-73.36,-57.38,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).",Medium and small scale mapping.,1053,-35.89,7.25,-74.05,-26.12,1,0,9603,-66.87,4.37,-38.52,,,,,0
+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
+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
+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
+20,1871,4618,4326,"Derived at 1 station. Note: SAD69 not adopted in Ecuador.",For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.17,-91.71,-89.2,1,0,9603,-47,26,-42,,,,,0
+21,1872,4618,4326,"Derived at 5 stations. Note: SAD69 not adopted in Guyana.","For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",3259,1.19,8.57,-61.39,-56.47,1,0,9603,-53,3,-47,,,,,0
+22,1873,4618,4326,"Derived at 4 stations. Note: SAD69 not adopted in Paraguay.",For military purposes. Accuracy 15m in each axis.,1188,-27.58,-19.3,-62.64,-54.24,1,0,9603,-61,2,-33,,,,,0
+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,55.2,69.1,10.57,24.18,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,9.4,15.71,-5.52,4.63,1,0,9603,-106,-129,165,,,,,1
-29,1903,4621,4326,,"Accuracy +/- 10 metres.",2828,17.65,18.2,-63.18,-62.7,1,0,9603,137,248,-430,,,,,1
-30,1904,4622,4326,,"Accuracy +/- 10 metres.",2829,14.35,16.51,-61.8,-60.75,1,0,9603,-467,-16,-300,,,,,1
-31,1905,4622,4326,,"Accuracy +/- 0.1 metre.",2829,14.35,16.51,-61.8,-60.75,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,2.11,5.95,-54.65,-51.05,1,0,9603,-186,230,110,,,,,1
-33,1907,4624,4326,,"Accuracy +/- 2 metres.",1097,2.11,9.06,-54.65,-49.62,1,0,9603,2,2,-2,,,,,1
-34,1909,4625,4326,,"Accuracy +/- 10 metres.",1156,14.14,16.77,-62.57,-57.51,1,0,9603,186,482,151,,,,,1
-35,1910,4625,4326,,"Accuracy +/- 0.1 metre.",1156,14.14,16.77,-62.57,-57.51,1,0,9606,126.93,547.94,130.41,-2.7867,5.1612,-0.8584,13.8227,0
-36,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
-37,15751,4626,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,1196,-25.92,-10.6,37.58,58.27,1,0,9603,94,-948,-1262,,,,,1
-38,1912,4627,4326,,"Accuracy +/- 1 metre.",1196,-25.92,-10.6,37.58,58.27,1,0,9603,0,0,0,,,,,1
-39,1924,4628,4326,,"Accuracy +/- 10 metres.",2811,-17.91,-17.45,-149.96,-149.07,1,0,9603,162,117,154,,,,,1
-40,1913,4629,4326,,"Accuracy +/- 10 metres.",2812,-16.95,-16.62,-151.8,-150.9,1,0,9603,65,342,77,,,,,0
-41,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.62,-151.8,-150.9,1,0,9607,72.438,345.918,79.486,-1.6045,-0.8823,-0.5565,1.3746,1
-42,1914,4630,4326,,"Accuracy +/- 10 metres.",3129,-9.5,-8.75,-140.25,-139.45,1,0,9603,84,274,65,,,,,1
-43,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,-8.75,-140.25,-139.95,1,0,9607,165.732,216.72,180.505,-0.6434,-0.4512,-0.0791,7.4204,0
-44,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,-9,-8.85,-139.6,-139.45,1,0,9607,1363.785,1362.687,398.811,-4.5322,-6.7579,-1.0574,268.361,0
-45,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.5,-9.33,-140.17,-140,1,0,9607,259.551,297.612,197.833,1.4866,2.1224,0.4612,27.0249,0
-46,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.75,-48.5,68.5,70.6,1,1,9603,145,-187,103,,,,,0
-47,1916,4632,4326,,"Accuracy +/- 10 metres.",1159,-14.37,-11.32,44.13,45.77,1,0,9603,-382,-59,-262,,,,,1
-48,1272,4121,4326,,For applications requiring 1m or better accuracy.,1106,33.23,41.77,18.27,29.97,1,0,9603,-199.87,74.79,246.62,,,,,1
-49,1918,4634,4326,,"Accuracy +/- 10 metres.",1174,-23.46,-17.26,157.09,173.89,1,1,9603,-13,-348,292,,,,,0
-50,1929,4634,4326,,"Accuracy better than +/- 1 metre.",2822,-22.5,-20,163.9,167.1,1,1,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
-51,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.,1095,59.3,70.13,19.09,31.59,1,0,9606,-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37,0
-52,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.,1095,59.3,70.13,19.09,31.59,1,0,9607,-96.062,-82.428,-121.753,-4.801,-0.345,1.376,1.496,1
-53,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,55.2,69.1,10.57,24.18,1,0,9607,419.3836,99.3335,591.3451,-0.850389,-1.817277,7.862238,-0.99496,1
-54,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,55.2,69.1,10.57,24.18,1,1,9607,414.1,41.3,603.1,-0.855,2.141,-7.023,0,0
-55,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,55.2,69.1,10.57,24.18,1,0,9607,414.1,41.3,603.1,0.855,-2.141,7.023,0,0
-56,1282,4125,4326,Datum shift derived through ITRF93.,Oil exploration.,1328,-1.35,0,116.9,118,1,1,9603,-404.78,685.68,45.47,,,,,0
-57,1923,4638,4326,,"Accuracy +/- 10 metres.",1220,43.53,47.39,-58.02,-55.12,1,0,9603,30,430,368,,,,,1
-58,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.,1167,-26.88,-9.56,30.23,43,1,0,9607,-115.064,-87.39,-101.716,0.058,-4.001,2.062,9.366,1
-59,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.88,-24,31.8,35.6,1,0,9607,-82.875,-57.097,-156.768,2.158,-1.524,0.982,-0.359,0
-60,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,-20,31.33,35.6,1,0,9607,-138.527,-91.999,-114.591,0.14,-3.363,2.217,11.748,0
-61,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,-20,-16,31.18,40.15,1,0,9607,-73.472,-51.66,-112.482,-0.953,-4.6,2.368,0.586,0
-62,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,-9.56,30.23,40.9,1,0,9607,219.315,168.975,-166.145,-0.198,-5.926,2.356,-57.104,0
-63,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.4,16.51,-61.8,-60.82,1,1,9603,0,0,0,,,,,0
-64,1928,4641,4326,Withdrawn by information source and replaced by improved information - see tfm code 15901.,"Accuracy better than +/- 1 metre.",2819,-21.7,-21.3,167.75,168.15,1,0,9606,-408.809,366.856,-412.987,1.8842,-0.5308,2.1655,-121.0993,1
-65,15783,4641,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15901.,Accuracy 5 metres.,2819,-21.7,-21.3,167.75,168.15,1,0,9603,287,178,-136,,,,,0
-66,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.7,-21.3,167.75,168.15,1,0,9603,287.58,177.78,-135.41,,,,,0
-67,1302,4130,4326,,For many purposes Moznet can be considered to be coincident with WGS 84. Accuracy better than 1 metre.,1167,-26.88,-9.56,30.23,43,1,0,9607,0,0,0,0,0,0,0,1
-68,1542,4131,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2359,15.9,16.1,107.45,108.4,1,0,9603,198,881,317,,,,,1
-69,1543,4131,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2360,8.62,8.76,106.53,106.75,1,0,9603,182,915,344,,,,,0
-70,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.7,28.2,51.8,52.5,1,0,9603,-241.54,-163.64,396.06,,,,,0
-71,1854,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2782,26.2,26.8,52.4,53.3,1,0,9603,-239.1,-170.02,397.5,,,,,1
-72,1855,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2781,29,29.33,50.15,50.4,1,0,9603,-244.72,-162.773,400.75,,,,,0
-73,1333,4133,4326,,"?",1090,57.57,59.7,21.84,28,1,0,9607,0.055,-0.541,-0.185,-0.0183,0.0003,0.007,-0.014,1
-74,1439,4134,4326,"Replaced PSD93 to WGS 84 (2) (code 8581) in 1997.","Oil exploration. Residuals 0.5m at 67% probability level.",1183,14.01,26.75,51.9,63.05,1,0,9606,-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.71006,1
-75,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
-76,15824,4135,4326,Derived at 15 satellite stations.,"Military mapping. Accuracy +/- 25m in X axis, +/- 20m in Y and Z axes.",1334,18.9,22.24,-160.55,-154.8,1,0,9603,61,-285,-181,,,,,1
-77,15825,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1546,18.9,20.27,-156.06,-154.8,1,0,9603,89,-279,-183,,,,,0
-78,15826,4135,4326,Derived at 3 satellite stations.,"Military mapping. Accuracy +/- 20m in each axis.",1549,21.87,22.24,-159.79,-159.29,1,0,9603,45,-290,-172,,,,,0
-79,15827,4135,4326,Derived at 2 satellite stations.,"Military mapping. Accuracy +/- 25m in each axis.",1547,20.49,21.22,-157.31,-155.97,1,0,9603,65,-290,-190,,,,,0
-80,15828,4135,4326,Derived at 8 satellite stations.,"Military mapping only. Accuracy +/- 10m in X axis, +/- 6m in Y and Z axes.",1548,21.12,21.72,-158.39,-157.52,1,0,9603,58,-283,-182,,,,,0
-81,1893,4139,4326,Derived at 11 stations.,For military purposes only. Accuracy 3m in each axis.,1335,17.67,18.8,-67.3,-64.25,1,0,9603,11,72,-101,,,,,1
-82,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
-83,1073,4141,4326,For more accurate transformation contact Survey of Israel.,"Accuracy: 2m",1126,29.51,33.98,33.47,35.69,1,0,9603,-48,55,52,,,,,1
-84,1469,4142,4326,,"?",2282,5.13,5.92,-4.8,-3.4,1,0,9603,-125,53,467,,,,,1
-85,1470,4143,4326,,"?",2282,5.13,5.92,-4.8,-3.4,1,0,9603,-124.76,53,466.79,,,,,1
-86,1155,4144,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 12m in X, Y and Z axes.",1041,15.09,26.65,88.1,92.72,1,0,9603,282,726,254,,,,,1
-87,1533,4144,4326,,Oil exploration.,2361,14.5,16.5,94,98,1,0,9603,214,804,268,,,,,0
-88,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.,1184,20.59,37.08,60.91,77.87,1,0,9603,283,682,231,,,,,1
-89,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,26.5,27.5,68.25,69.25,1,0,9603,274.164,677.282,226.704,,,,,0
-90,15701,4145,4326,Derived at Geodetic Survey office in Karachi in 1997.,Oil exploration.,2985,22,25.5,65,69,1,0,9603,275.57,676.78,229.6,,,,,0
-91,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.36,67.8,68.79,1,0,9603,278.9,684.39,226.05,,,,,0
-92,15703,4145,4326,Derived at Chitrawala triangulation station by Fugro-Geodetic for UTP.,Oil exploration.,2982,24.8,25.1,66.8,67.2,1,0,9603,271.905,669.593,231.495,,,,,0
-93,15704,4145,4326,Derived by Western Geophysical for UTP 1996 East Sind 2D survey.,Oil exploration.,2983,26,27,68,71.1,1,0,9606,230.25,632.76,161.03,-1.114,1.115,1.212,12.584,0
-94,1156,4146,4326,"Care! DMA ellipsoid is inconsistent with EPSG ellipsoid - transformation parameter values may not be appropriate. Derived at 7 stations.","For military purposes. Accuracy 12m, 10m and 15m in X, Y and Z axes.",2411,6.75,35.51,68.14,97.38,1,0,9603,295,736,257,,,,,1
-95,1544,4147,4326,Derived in Vung Tau area.,Oil exploration.,1494,8.54,12.33,104.5,107.5,1,0,9603,-17.51,-108.32,-62.39,,,,,1
-96,1505,4148,4326,,For many purposes Hartebeesthoek94 datum can be considered to be coincident with WGS 84.,1215,-50.34,-22.14,14.03,41.16,1,0,9603,0,0,0,,,,,1
-97,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
-98,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
-99,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
-100,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
-101,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
-102,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
-103,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.57,49.39,140.08,-63.88,1,0,9603,0,0,0,,,,,1
-104,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.53,49.39,-124.85,-67.07,1,0,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
-105,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.53,49.39,-124.85,-67.07,1,0,9607,-0.991,1.9072,0.5129,-0.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
-106,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.53,49.39,-124.85,-67.07,1,1,9603,0,0,0,,,,,0
-107,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
-108,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.8,44.06,63.37,1,0,9603,-117,-132,-164,,,,,1
-109,1514,4154,4326,"Used for South Pars phases 6, 7 and 8.","Transformation for whole country: accuracy about 1m.",1123,23.35,39.8,44.06,63.37,1,0,9606,-110.33,-97.73,-119.85,0.3423,1.1634,0.2715,0.063,0
-110,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.55,26.75,52.05,52.3,1,0,9603,-122.89,-159.08,-168.74,,,,,0
-111,1857,4154,4326,Derived in 1999 on Lavan island by Geoid for Elf.,Petroleum Exploration and Production.,2782,26.2,26.8,52.4,53.3,1,0,9603,-84.78,-107.55,-137.25,,,,,0
-112,1858,4154,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Petroleum Exploration and Production.,2781,29,29.33,50.15,50.4,1,0,9603,-123.92,-155.515,-157.721,,,,,0
-113,15745,4154,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11.,Petroleum Exploration and Production.,3140,26.67,26.95,52.17,52.45,1,0,9603,-123.02,-158.95,-168.47,,,,,0
-114,1518,4155,4326,,Accuracy 25m in each axis.,1112,6.38,12.69,-17.07,-7.65,1,0,9603,-83,37,124,,,,,1
-115,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.",For applications to an accuracy of 1 metre.,1079,48.56,51.09,12.11,18.98,1,0,9606,570.8,85.7,462.8,4.998,1.587,5.261,3.56,0
-116,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.65,16.84,22.58,1,1,9606,559,68.7,451.5,7.92,4.073,4.251,5.71,0
-117,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.65,16.84,22.58,1,0,9606,485,169.5,483.5,7.786,4.398,4.103,0,0
-118,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
-119,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.92,56.48,21.07,26.82,1,0,9603,0,0,0,,,,,1
-120,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.,1127,34.49,47.12,5.95,18.97,1,0,9603,0,0,0,,,,,1
-121,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,24,28,13,19,1,0,9603,-69.06,-90.71,-142.56,,,,,0
-122,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,24,28,13,19,1,0,9603,-113.997,-97.076,-152.312,,,,,0
-123,1861,4159,4326,Derived by GEOID in 1994 from Transit satellite data. Used by TotalFinaElf.,Oil Exploration,2786,29.6,29.9,17.2,17.5,1,0,9603,-114.5,-96.1,-151.9,,,,,0
-124,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.6,29.9,17.2,17.5,1,0,9606,-194.513,-63.978,-25.759,-3.4027,3.756,-3.352,-0.9175,0
-125,1863,4159,4326,"Derived for the Great Man-made River Authority (GMRA).",Engineering survey and oil exploration,2786,29.6,29.9,17.2,17.5,1,0,9607,-389.691,64.502,210.209,-0.086,-14.314,6.39,0.9264,0
-126,15707,4159,4326,"Used by Petrocanada and previous licence holders in Amal field, concession 12.",Oil exploration and production,2987,29.2,29.6,21,21.3,1,0,9603,-118.996,-111.177,-198.687,,,,,0
-127,15778,4159,4326,"Derived by Total at stations SDL 130-03, 04 and 05 in May 2005.",Oil exploration and production.,3142,27.83,28.67,21.17,21.83,1,0,9603,-114.7,-98.5,-150.7,,,,,0
-128,15909,4159,4326,Derived at 29 stations throughout Libya in May 2006.,For applications to an accuracy of 5 metres.,3271,19.51,32.9,9.31,25.15,1,0,9603,-115.8543,-99.0583,-152.4616,,,,,1
-129,15923,4159,4326,"Derived by SDL for Total in Cyrenaica blocks 2 & 4.",Oil and gas exploration.,3477,32,32.67,22.5,23,1,0,9603,-117.7,-100.3,-152.4,,,,,0
-130,1080,4672,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,2889,-45,-43,-178,-175,1,0,9603,175,-38,113,,,,,1
-131,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,-45,-43,-178,-175,1,0,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263,1
-132,15894,4674,4326,,Accuracy 1m.,3418,-56.15,32.74,-118.5,-34,1,0,9603,0,0,0,,,,,1
-133,1070,4675,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,1110,12.76,14.01,140.08,145.59,1,0,9603,-100,-248,259,,,,,1
-134,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 +/- 1m level.",1340,12,15,42.5,53,1,0,9603,-76,-138,67,,,,,1
-135,1547,4165,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1113,8.22,12.69,-18.52,-13.65,1,0,9603,-173,253,27,,,,,1
-136,1065,4678,4326,Derived at 25 stations.,Accuracy 5m.,1138,13.92,22.51,100.15,107.76,1,0,9603,44.585,-131.212,-39.544,,,,,1
-137,1565,4167,4326,,Assumes NZGD2000 is coincident to WGS 84 to the 1m accuracy level.,1175,-55.95,-22.74,157.41,-170.89,1,0,9603,0,0,0,,,,,1
-138,1569,4168,4326,Derived at 3 common points.,Military survey,1104,1.08,11.17,-3.9,1.34,1,0,9603,-199,32,322,,,,,1
-139,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.08,6.1,-3.9,1.34,1,0,9606,-171.16,17.29,325.21,0,0,0.814,-0.38,0
-140,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.38,-14.16,-170.85,-169.41,1,0,9603,-115,118,426,,,,,1
-141,1581,4170,4326,,For military purposes. Accuracy 1m in each axis.,3448,-56.15,13,-82,-34,1,0,9603,0,0,0,,,,,1
-142,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.18,51.54,-9.62,10.3,1,0,9603,0,0,0,,,,,1
-143,1598,4172,4326,,"?",1033,-60.04,-21.8,-73.62,-53.5,1,1,9603,0,0,0,,,,,0
-144,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.33,55.4,-10.6,-5.33,1,0,9603,0,0,0,,,,,1
-145,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.22,15.93,-85.79,-66.91,1,0,9603,0,0,0,,,,,1
-146,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.",1209,4.27,10,-15.68,-10.27,1,0,9603,-88,4,101,,,,,1
-147,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.",1031,-90,-60,-180,180,1,0,9603,0,0,0,,,,,1
-148,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.67,-139.18,-138.8,1,0,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311,1
-149,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.05,-9.88,-139.15,-139,1,0,9607,374.716,-58.407,-0.957,-16.2111,-11.4626,-5.5357,-0.5409,0
-150,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.17,54.72,9.87,15.03,1,0,9607,24,-123,-94,-0.02,0.25,0.13,1.1,0
-151,15996,4178,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.78,48.6,16.12,22.91,1,0,9603,28,-121,-77,,,,,0
-152,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
-153,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.,1192,49.03,55.95,14.14,24.16,1,0,9606,33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84,1
-154,15496,4179,4326,,Oil exploration,1197,43.62,48.26,20.26,31.5,1,0,9603,44.107,-116.147,-54.648,,,,,0
-155,15497,4179,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.62,48.26,20.26,31.5,1,0,9603,28,-121,-77,,,,,0
-156,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.62,48.26,20.26,31.5,1,0,9607,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69,0
-157,15997,4179,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49.03,55.95,14.14,24.16,1,0,9603,23,-124,-82,,,,,0
-158,15999,4179,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.67,42.69,18.45,21.06,1,0,9603,24,-130,-92,,,,,0
-159,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.57,59.7,21.84,28,1,0,9603,0,0,0,,,,,1
-160,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.48,50.21,5.73,6.53,1,0,9606,-193,13.7,-39.3,-0.41,-2.933,2.688,0.43,1
-161,1210,4694,4326,,POSGAR 94 is a local realisation of WGS 84.,1033,-60.04,-21.8,-73.62,-53.5,1,0,9603,0,0,0,,,,,1
-162,1886,4183,4326,Derived at 5 stations.,For military purposes only. Accuracy 3m in each axis.,1301,38.35,39.15,-28.85,-27,1,0,9603,-104,167,-38,,,,,1
-163,1885,4184,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1345,36.9,37.95,-25.9,-24.95,1,0,9603,-203,141,53,,,,,1
-164,15794,4708,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1069,-15.54,-5.89,93.54,102.43,1,0,9603,-491,-22,435,,,,,1
-165,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.75,-48.5,68.5,70.6,1,0,9603,145,-187,103,,,,,1
-166,15784,4699,4326,Derived at 17 stations in 1994 by University of East London. Residuals less than 2m.,Accuracy 2m.,3209,-20.5,-19.95,57.3,57.8,1,0,9603,-770.1,158.4,-498.2,,,,,1
-167,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,54.01,55.31,-8.2,-5.42,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-168,1768,4189,4326,,"Approximation at the +/- 1m level.",1251,0.65,16.76,-73.36,-57.38,1,0,9603,0,0,0,,,,,1
-169,1773,4190,4326,,"Approximation at the +/- 1m level.",1033,-60.04,-21.8,-73.62,-53.5,1,0,9603,0,0,0,,,,,1
-170,15780,4190,4326,,"Approximation at the +/- 1m level.",1033,-60.04,-21.8,-73.62,-53.5,1,1,9603,0,0,0,,,,,0
-171,15873,4192,4326,Derived at Manoca tower assuming the pyramid on the tower and the centre of the tower resevoir are co-located. This assumption carries a few metres uncertainty.,Oil exploration.,2555,1.5,5,8.4,12,1,0,9603,-206.1,-174.7,-87.7,,,,,1
-172,1796,4193,4326,"Derived at two points, checked at a third by Stolt Comex Seaway and Geoid for Elf.",Oil industry,2555,1.5,5,8.4,12,1,0,9603,-70.9,-151.8,-41.4,,,,,1
-173,1797,4194,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,0,9603,164,138,-189,,,,,0
-174,1798,4194,4326,,Topographic mapping.,3362,59.75,79,-73,-42,1,0,9606,163.511,127.533,-159.789,0,0,0.814,-0.6,1
-175,1799,4195,4326,,Topographic mapping.,2570,68,75,-30,-21,1,0,9606,105,326,-102.5,0,0,0.814,-0.6,1
-176,1800,4196,4326,,Topographic mapping.,2571,65,68,-40,-28,1,0,9606,-45,417,-3.5,0,0,0.814,-0.6,1
-177,15796,4709,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3200,24.74,24.823,141.28,141.36,1,0,9603,145,75,-272,,,,,1
-178,15798,4710,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3183,-16.03,-15.88,-5.81,-5.63,1,0,9603,-320,550,-494,,,,,1
-179,15799,4711,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3203,24.26,24.32,153.95,154.01,1,0,9603,124,-234,-25,,,,,1
-180,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 GosStandard of Russia Decree #327 of August 9, 2001.",Accuracy 1 metre.,1198,41.17,82,19.2,-168.98,1,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12,1
-181,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
-182,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
-183,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.66,13.09,8.51,16.22,1,0,9603,-134,-2,210,,,,,0
-184,1103,4201,4326,Derived at 8 stations.,For military purposes. Accuracy 3m in each axis.,1091,3.4,14.88,32.99,48.12,1,0,9603,-165,-11,206,,,,,0
-185,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.15,25.02,-12.25,4.26,1,0,9603,-123,-20,220,,,,,0
-186,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.32,16.7,-17.55,-11.37,1,0,9603,-128,-18,224,,,,,0
-187,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.25,21.84,38.6,1,0,9603,-161,-14,205,,,,,0
-188,1108,4202,4326,Derived at 105 stations.,For military purposes only. Accuracy 3m in each axis.,2575,-45,-10,108,155,1,0,9603,-133,-48,148,,,,,0
-189,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.16,148.77,149.4,1,0,9607,-129.193,-41.212,130.73,-0.246,-0.374,-0.329,-2.955,0
-190,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.15,-28.15,140.95,153.62,1,0,9607,-119.353,-48.301,139.484,-0.415,-0.26,-0.437,-0.613,0
-191,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.8,-39.57,143.83,148.96,1,0,9607,-120.271,-64.543,161.632,-0.217,0.067,0.129,2.499,0
-192,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,-11.02,129,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
-193,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,-45,-10,108,155,1,0,9603,-127.8,-52.3,152.9,,,,,0
-194,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,-60.04,-8.86,110.77,174.1,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
-195,1109,4203,4326,Derived at 90 stations.,For military purposes only. Accuracy 2m in each axis.,2575,-45,-10,108,155,1,0,9603,-134,-48,149,,,,,1
-196,1236,4203,4326,"""Higgins parameters"". Replaced by AGD84 to GDA94 (2) (code 1280) and AGD84 to WGS 84 (7) (code 1669).",Preliminary estimate.,2575,-45,-10,108,155,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
-197,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).",1m accuracy.,2575,-45,-10,108,155,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
-198,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 transformation.",5m accuracy.,2575,-45,-10,108,155,1,0,9603,-128.5,-53,153.4,,,,,0
-199,1055,4204,4326,Derived at station K1.,1 metre accuracy.,1136,28.56,30.1,46.57,49.24,1,0,9603,-145.7,-249.1,1.5,,,,,0
-200,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.,1136,28.56,30.1,46.57,49.24,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
-201,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.1,46.57,49.24,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
-202,1058,4204,4326,,1 metre accuracy.,2957,28.56,29.33,46.57,48.45,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
-203,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1040,25.57,27.18,50.3,51.41,1,0,9603,-150,-250,-1,,,,,0
-204,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,1206,15.9,32.26,34.27,55.7,1,0,9603,-143,-236,7,,,,,1
-205,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,1214,-2.39,13.4,41.01,54.98,1,0,9603,-43,-163,45,,,,,1
-206,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.15,-8,156.7,156.9,1,0,9603,230,-199,-752,,,,,0
-207,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.96,-9.24,159.56,160.91,1,0,9603,252,-209,-751,,,,,1
-208,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,37.01,42.15,-9.5,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
-209,1984,4207,4326,,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
-210,1988,4207,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
-211,1549,4208,4326,,Oil exploration.,2307,-27.83,-18.18,-48.45,-38,1,1,9603,-158,315,-148,,,,,0
-212,1550,4208,4326,,Oil exploration.,2308,-9.8,-9,-39,-37.5,1,0,9603,-139.62,290.53,-150.29,,,,,0
-213,1551,4208,4326,,Oil exploration.,2309,-10.6,-9.8,-39,-37.5,1,0,9603,-141.15,293.44,-150.56,,,,,0
-214,1552,4208,4326,,Oil exploration.,2310,-11.4,-10.6,-39,-37.5,1,0,9603,-142.48,296.03,-149.74,,,,,0
-215,10089,4208,4326,Used by ExxonMobil for block BMS1.,Oil exploration.,2962,-27.83,-23.5,-48.45,-41.5,1,0,9603,-163.466,317.396,-147.538,,,,,0
-216,10090,4208,4326,"Used by ExxonMobil for block BC10. Derived from earlier Shell position vector tfm where dX = -181m, dY = +294m, dZ = -144.5m, rX = rY = 0, rZ = +0.554s, dS = +0.219 ppm.",Oil exploration.,2963,-24.42,-21,-41.5,-38.5,1,0,9603,-170,305,-145,,,,,0
-217,10091,4208,4326,Used by ExxonMobil for block BMES1.,Oil exploration.,2964,-21.29,-18.18,-39.37,-38,1,0,9603,-162.904,312.531,-137.109,,,,,0
-218,10092,4208,4326,Used by ExxonMobil for block BP1.,Oil exploration.,2965,-34,-32,-51.3,-48.5,1,0,9603,-158,309,-151,,,,,0
-219,10093,4208,4326,Used by ExxonMobil for offshore regional studies.,Oil exploration.,2966,-34,-18,-53,-36,1,0,9603,-161,308,-142,,,,,1
-220,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.8,18.3,-18.1,-15.75,1,1,9603,124.5,-63.5,-281,,,,,0
-221,15710,4208,4326,Provided by Petrobras for Barracuda Caratinga project. Understood to be Petrobras preferred parameters for all purposes in the area.,Oil exploration.,2963,-24.42,-21,-41.5,-38.5,1,0,9603,-160,315,-142,,,,,0
-222,15711,4208,4326,Provided by Petrobras for Barracuda Caratinga project. Understood to be Petrobras preferred parameters for all purposes in the area.,Oil exploration.,2962,-27.83,-23.5,-48.45,-41.5,1,0,9603,-158,309,-147,,,,,0
-223,15712,4208,4326,Provided by Petrobras for Barracuda Caratinga project. Understood to be Petrobras preferred parameters for all purposes in the area.,Oil exploration.,2964,-21.29,-18.18,-39.37,-38,1,0,9603,-161,310,-145,,,,,0
-224,15754,4208,4326,"Mean for 3 basins. See Aratu to WGS 84 (10) through (12) (codes 15710-12) for transformations for individual basins.",Oil exploration.,2307,-27.83,-18.18,-48.45,-38,1,0,9603,-158,315,-148,,,,,0
-225,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.2,20,35.92,1,0,9603,-143,-90,-294,,,,,1
-226,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
-227,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.46,-2.3,29,30.87,1,1,9603,-153,-5,-292,,,,,0
-228,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.68,-28.59,27.03,29.47,1,0,9603,-125,-108,-295,,,,,0
-229,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.15,-9.38,32.7,35.95,1,0,9603,-161,-73,-317,,,,,0
-230,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.31,-25.74,30.82,32.15,1,0,9603,-134,-105,-295,,,,,0
-231,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.38,12.21,31.3,1,1,9603,-169,-19,-278,,,,,0
-232,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.09,-8.2,22.01,33.72,1,0,9603,-147,-74,-283,,,,,0
-233,1121,4209,4326,Derived at 10 stations.,"For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.43,-15.63,25.25,33.09,1,0,9603,-142,-96,-293,,,,,0
-234,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
-235,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",1132,-4.9,5.03,33.93,45.17,1,0,9603,-157,-2,-299,,,,,0
-236,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",1230,-11.75,-1,29.36,43.51,1,0,9603,-175,-23,-303,,,,,0
-237,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.46,-2.3,29,30.87,1,0,9603,-153,-5,-292,,,,,0
-238,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,-6.5,6,95,108.55,1,0,9603,-377,681,-50,,,,,1
-239,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6,-2.75,106,110,1,0,9603,-378.873,676.002,-46.255,,,,,0
-240,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-7,-4,112,118.5,1,0,9603,-377.7,675.1,-52.2,,,,,0
-241,15793,4212,4326,"Derived at 2 stations (S40 and M1, St Annes Tower) in 2004.",Accuracy 2.5m.,1042,11.04,14.75,-60.71,-57.5,1,0,9603,31.95,300.99,419.19,,,,,1
-242,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,16.81,-169.63,-169.3,1,0,9603,189,-79,-202,,,,,1
-243,15814,4726,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",3186,19.65,19.76,-80.1,-79.71,1,0,9603,42,124,147,,,,,1
-244,15829,4726,4326,Determined from 2 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.65,19.76,-80.1,-79.71,1,0,9603,44.4,109,151.7,,,,,0
-245,15800,4713,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.83,41.78,44.05,1,0,9603,-79,-129,145,,,,,1
-246,1124,4216,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1047,28.87,35.77,-68.23,-61.34,1,0,9603,-73,213,296,,,,,1
-247,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.",1047,28.87,35.77,-68.23,-61.34,1,0,9607,-292.295,248.758,429.447,-4.9971,-2.99,-6.6906,1.0289,0
-248,15819,4729,4326,Derived at 1 satellite station.,"Millitary and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.16,-25,-130.18,-129.99,1,0,9603,185,165,42,,,,,1
-249,1125,4218,4326,Derived in 1987 at 7 stations.,"For military purposes. Accuracy 6m, 5m and 6m in X, Y and Z axes.",1070,-4.22,15.93,-85.79,-66.91,1,0,9603,307,304,-318,,,,,1
-250,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
-251,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,10,13,-73,-71,1,0,9607,-806.413,-263.5,-622.671,12.4142185637707,-2.99084175323096,-39.0346863906349,-20.81616,0
-252,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.6,-76,-73,1,0,9607,100.783,187.382,-47,-9.22383004903209,2.42380329967319,-8.30827832824698,-13.56561,0
-253,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.6,-74.4,1,0,9607,336.026,348.565,252.978,-17.2412894390071,-6.30649282215535,1.56204977191825,-5.771909,0
-254,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
-255,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,-78,-74.4,1,0,9607,-90.29,247.559,-21.989,-8.69688534851263,-4.18803362841004,-12.8082668496251,2.181658,0
-256,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,-78,-74.4,1,0,9607,-0.562,244.299,-456.938,6.8668709851194,-8.25267346177889,-9.2967797230575,3.74656,0
-257,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,3,-79,-74,1,0,9607,-305.356,222.004,-30.023,-9.69049385992583,1.03196819622539,-19.7573941768278,6.325747,0
-258,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,3,7.3,-74.4,-66.5,1,0,9607,221.899,274.136,-397.554,2.80844591036278,-0.44850858891268,-2.81017234679107,-2.199943,0
-259,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.25,-1.49,105.12,108.29,1,0,9603,-384,664,-48,,,,,1
-260,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.58,-7.75,12.58,13.4,1,0,9603,-42.01,-332.21,-229.75,,,,,0
-261,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7,-6.03,12.08,12.84,1,0,9603,-40,-354,-224,,,,,0
-262,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
-263,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.17,-6.03,10,13.86,1,0,9603,-41.8,-342.2,-228.2,,,,,1
-264,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
-265,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.67,13.4,1,0,9603,-43,-337,-233,,,,,0
-266,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,-6.58,-6.03,10.83,11.67,1,0,9603,-48,-345,-231,,,,,0
-267,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.03,12.08,12.84,1,0,9603,-48.6,-345.1,-230.8,,,,,0
-268,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
-269,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.03,10.47,12.84,1,0,9603,-50.9,-347.6,-231,,,,,0
-270,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,1033,-60.04,-21.8,-73.62,-53.5,1,0,9603,-148,136,90,,,,,1
-271,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.8,-37,-70.7,-69.9,1,0,9603,-154.5,150.7,100.4,,,,,0
-272,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",1215,-50.34,-22.14,14.03,41.16,1,0,9603,-136,-108,-292,,,,,1
-273,1129,4222,4326,"Residuals should not exceed 15 metres. Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation.","?",1215,-50.34,-22.14,14.03,41.16,1,0,9603,-134.73,-110.92,-292.66,,,,,0
-274,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.25,38.43,7.5,13.74,1,0,9603,-263,6,431,,,,,1
-275,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.13,38.43,8.62,13.74,1,0,9603,-260.1,5.5,432.2,,,,,0
-276,1131,4224,4326,Derived at 6 stations.,"For military purposes. Accuracy 6m, 9m and 5m in X, Y and Z axes.",1188,-27.6,-19.31,-62.68,-54.28,1,0,9603,-134,229,-29,,,,,1
-277,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,-16.04,-15.5,-48.28,-47.3,1,0,9603,-143.87,243.37,-33.52,,,,,0
-278,1132,4225,4326,Derived at 17 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",1293,-35.89,-2.8,-58.2,-34.5,1,0,9603,-206,172,-6,,,,,1
-279,1585,4227,4326,,"?",1227,32.33,37.34,35.08,42.4,1,1,9603,-177.5,14.1,237.6,,,,,0
-280,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.5,35.7,39.9,40.15,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
-281,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.8,36.5,40.5,41.5,1,0,9603,-191.77,15.01,235.07,,,,,0
-282,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,35.25,35.5,40,40.5,1,0,9603,-187.5,14.1,237.6,,,,,0
-283,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,1227,32.33,37.34,35.08,42.4,1,0,9603,-190.421,8.532,238.69,,,,,1
-284,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,35.25,35.5,40,40.5,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
-285,1244,4740,4326,"Mandated for use in Russia by GosStandard of Russia Decree #327 of August 9, 2001.",Geodetic applications. Accuracy better than 0.5 metre.,1198,41.17,82,19.2,-168.98,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
-286,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
-287,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.99,33.75,24.71,36.9,1,0,9603,-130,110,-13,,,,,1
-288,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.3,29.96,32.3,34.25,1,1,9603,-146.21,112.63,4.05,,,,,0
-289,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.33,42.5,28.15,41.5,1,0,9603,-89.05,-87.03,-124.56,,,,,0
-290,1087,4230,4326,Information has not been confirmed by National Mapping Agency.,Topographic mapping.,1130,29.21,33.4,34.98,39.33,1,0,9603,-112,-110.3,-140.2,,,,,0
-291,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,36,71.05,-9.4,31.6,1,0,9603,-87,-98,-121,,,,,1
-292,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.5,57.5,-4.6,22.5,1,0,9603,-87,-96,-120,,,,,0
-293,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,16.38,37.38,34.27,55.67,1,0,9603,-103,-106,-141,,,,,0
-294,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,33.05,36.31,29.94,35.22,1,0,9603,-104,-101,-140,,,,,0
-295,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",1086,21.99,33.75,24.71,36.9,1,0,9603,-130,-117,-151,,,,,0
-296,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,48.17,63.9,-27,3.4,1,0,9603,-86,-96,-120,,,,,0
-297,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.87,71.05,5.3,31.6,1,0,9603,-87,-95,-120,,,,,0
-298,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,1106,33.23,41.77,18.27,29.97,1,0,9603,-84,-95,-130,,,,,0
-299,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.5,41.5,8,10,1,0,9603,-97,-103,-120,,,,,0
-300,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.5,38.5,12,16,1,0,9603,-97,-88,-135,,,,,0
-301,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1154,35.07,36.61,13.48,15.37,1,0,9603,-107,-88,-149,,,,,0
-302,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.95,43.78,-9.5,3.3,1,0,9603,-84,-107,-120,,,,,0
-303,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.25,38.43,7.5,13.74,1,0,9603,-112,-77,-145,,,,,0
-304,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.18,51.54,-9.62,10.3,1,0,9603,-84,-97,-117,,,,,0
-305,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,49.05,63.9,-15.6,8,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
-306,1440,4230,4326,,Used in oil industry.,1106,33.23,41.77,18.27,29.97,1,0,9603,-86,-92.2,-127.5,,,,,0
-307,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,80.75,-0.5,32.02,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
-308,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.12,62,1.5,8,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
-309,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.,1080,54.39,58.79,3.25,15.49,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
-310,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.13,36.17,-5.39,-5.37,1,0,9603,-116.8,-106.4,-154.4,,,,,0
-311,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.62,40.08,1.2,4.33,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
-312,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.98,41.5,-7.5,3.27,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
-313,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.8,-9.3,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
-314,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.47,43.93,25.59,44.85,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
-315,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,27.5,30.82,25,30.74,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
-316,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.75,-11.6,-9.5,1,0,9603,-82.31,-95.23,-114.96,,,,,0
-317,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.5,55.8,2.5,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
-318,1985,4230,4326,,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
-319,1989,4230,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
-320,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.9,3.3,8.5,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
-321,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.5,55.8,2.5,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-322,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.5,55.8,2.5,6.4,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,0
-323,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,35,41.9,-13.8,-7.3,1,0,9603,-86.277,-108.879,-120.181,,,,,0
-324,1146,4231,4326,,"?",2330,52,62,-4,8,1,0,9606,-82.981,-99.719,-110.709,-0.104700015651026,0.0310016003789386,0.0804020214751182,-0.3143,0
-325,1960,4231,4326,,Scientific research.,1297,36,71.05,-8.95,31.6,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-326,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,36,71.05,-8.95,31.6,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,1
-327,1256,4232,4326,Derived at 7 stations.,"For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",1183,14.01,26.75,51.9,63.05,1,0,9603,-346,-1,224,,,,,1
-328,1438,4232,4326,,Oil exploration.,1183,14.01,26.75,51.9,63.05,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,0
-329,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-4.04,8.09,69.22,77.13,1,1,9603,-133,-321,50,,,,,0
-330,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.18,28.29,-177.42,-177.3,1,0,9603,912,-58,1227,,,,,1
-331,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.18,28.29,-177.42,-177.3,1,0,9603,403,-81,277,,,,,0
-332,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1228,21.43,26.36,118.07,122.49,1,0,9603,-637,-549,-203,,,,,1
-333,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.78,48.6,16.12,22.91,1,0,9603,52.17,-71.82,-14.9,,,,,1
-334,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.78,48.6,16.12,22.91,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
-335,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.78,48.6,16.12,22.91,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
-336,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.78,48.6,16.12,22.91,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
-337,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.78,48.6,16.12,22.91,1,0,9603,57.01,-69.97,-9.29,,,,,0
-338,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,1122,-13.01,7.92,91.66,141.1,1,0,9603,-24,-15,5,,,,,1
-339,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.,1122,-13.01,7.92,91.66,141.1,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
-340,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.",1122,-13.01,7.92,91.66,141.1,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
-341,1153,4239,4326,Derived at 11 stations.,"For military purposes. Accuracy 15m, 6m and 12m in X, Y and Z axes.",1231,5.63,20.47,95.59,105.7,1,0,9603,217,823,299,,,,,1
-342,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.",1231,5.63,20.47,95.59,105.7,1,0,9603,209,818,290,,,,,1
-343,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.",1231,5.63,20.47,95.59,105.7,1,0,9603,210,814,289,,,,,0
-344,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,7.3,8.3,102.2,102.7,1,0,9603,204.64,834.74,293.8,,,,,0
-345,1812,4240,4326,,Cadastral survey.,1231,5.63,20.47,95.59,105.7,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
-346,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.6,-78.4,-76.1,1,0,9603,70,207,389.5,,,,,1
-347,1085,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 2m accuracy.,3342,17.65,18.6,-78.4,-76.1,1,0,9603,65.334,212.46,387.63,,,,,0
-348,1086,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 1m accuracy.,3342,17.65,18.6,-78.4,-76.1,1,1,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,-8.95,0
-349,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.6,-78.4,-76.1,1,0,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,8.95,0
-350,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.75,-22.5,167.3,167.55,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
-351,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.75,-22.5,167.3,167.55,1,0,9603,-13,-348,292,,,,,1
-352,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1218,2.51,11.04,77.06,87.55,1,0,9603,-97,787,86,,,,,1
-353,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",1309,1.26,6.71,99.64,104.29,1,0,9603,-11,851,5,,,,,1
-354,1059,4246,4326,,1 metre accuracy.,1136,28.56,30.1,46.57,49.24,1,0,9603,-294.7,-200.1,525.5,,,,,1
-355,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,7,10.8,-66,-57.38,1,0,9603,-273.5,110.6,-357.9,,,,,1
-356,1201,4248,4326,Derived at 63 stations.,"For military purposes only. Accuracy 17m, 27m and 27m in X, Y and Z axes.",2399,-17.8,12.5,-82,-57,1,0,9603,-288,175,-376,,,,,1
-357,1202,4248,4326,Derived at 5 stations.,"For military purposes only. Accuracy 5m, 11m and 14m in X, Y and Z axes.",1049,-22.91,-9.69,-69.69,-57.49,1,0,9603,-270,188,-388,,,,,0
-358,1203,4248,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2402,-21.46,-17.51,-70.41,-68.44,1,0,9603,-270,183,-390,,,,,0
-359,1204,4248,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2403,-49.25,-39.29,-75.72,-71.11,1,0,9603,-305,243,-442,,,,,0
-360,1205,4248,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1070,-4.22,15.93,-85.79,-66.91,1,0,9603,-282,169,-371,,,,,0
-361,1206,4248,4326,Derived at 11 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3241,-5.01,1.5,-81.45,-75.26,1,0,9603,-278,171,-367,,,,,0
-362,1207,4248,4326,Derived at 9 stations.,"For military purposes. Accuracy 6m, 14m and 5m in X, Y and Z axes.",1114,1.19,11.98,-61.43,-55.72,1,0,9603,-298,159,-369,,,,,0
-363,1208,4248,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 12m in X, Y and Z axes.",1189,-20.72,-0.03,-84.73,-68.72,1,0,9603,-279,175,-379,,,,,0
-364,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.76,-73.36,-57.38,1,0,9603,-295,173,-371,,,,,0
-365,1582,4248,4326,Derived May 1995 by Geoid for Total. OSU91A geoid model used.,Oil exploration.,2400,-21.8,-21.5,-64,-63.67,1,0,9603,-259.73,173.12,-398.27,,,,,0
-366,1583,4248,4326,Derived July 1997 by Geoid from data recorded by UGA for Total. OSU91A geoid model used.,Oil exploration.,2401,-21.8,-21.5,-64,-63.67,1,0,9603,-307.7,265.3,-363.5,,,,,0
-367,1811,4248,4326,Used by Petrobras for shelf operations.,Oil industry exploration.,1754,-2,5,-50,-47,1,0,9603,-291.87,106.37,-364.52,,,,,0
-368,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.01,1.5,-81.45,-75.26,1,0,9607,-60.31,245.935,31.008,-12.324,-3.755,7.37,0.447,0
-369,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,42.3,46.57,13.02,19.5,1,0,9603,0,0,0,,,,,1
-370,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.08,11.17,-3.9,1.34,1,0,9603,-130,29,364,,,,,1
-371,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1142,0.84,8.57,-13.67,-7.37,1,0,9603,-90,40,88,,,,,1
-372,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.35,39.75,-31.3,-31,1,0,9603,-425,-169,81,,,,,1
-373,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.35,39.75,-31.3,-31,1,0,9603,-422.651,-172.995,84.02,,,,,0
-374,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.5,21,116,127,1,0,9603,-133,-77,-51,,,,,1
-375,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,4,10,119,127,1,0,9603,-133,-79,-72,,,,,0
-376,1529,4254,4326,"Derived through ties at 3 stations (RC03, TOTAL11 and MP12) to 3 IGS stations in November 1995",Oil exploration.,2357,-55.05,-52.64,-68.64,-63.81,1,0,9606,18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013,0
-377,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.9,-48.64,-75.64,-66.52,1,0,9603,16,196,93,,,,,1
-378,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.41,38.5,60.54,74.96,1,0,9603,-333,-222,114,,,,,1
-379,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-5,-4.5,55,56,1,0,9603,41,-220,-134,,,,,1
-380,1837,4257,4326,,Oil exploration.,1316,-7.9,2,117.6,121,1,0,9603,-587.8,519.75,145.76,,,,,1
-381,1149,4258,4326,,ETRS89 is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1298,34.5,71.05,-10.67,31.55,1,0,9603,0,0,0,,,,,1
-382,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.78,55.8,2.48,7.37,1,1,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
-383,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,-5.03,10.85,12.43,1,0,9603,-252.95,-4.11,-96.38,,,,,0
-384,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,-5.03,10.85,12.43,1,0,9603,-254.1,-5.36,-100.29,,,,,0
-385,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.,3179,-6,-4.37,10.85,13.11,1,0,9603,-259.99,-5.28,-97.09,,,,,1
-386,1316,4260,4326,,"?",1060,1.66,13.09,8.38,16.22,1,1,9603,-70.9,-151.8,-41.4,,,,,0
-387,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",1166,27.68,36.23,-13.77,-1.01,1,0,9603,31,146,47,,,,,1
-388,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.33,18.57,36.4,43.3,1,0,9603,639,405,60,,,,,1
-389,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.,1717,2.25,6.2,2.7,8,1,0,9603,-92.1,-89.9,114.9,,,,,0
-390,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.66,13.09,8.51,16.22,1,0,9603,-81,-84,115,,,,,0
-391,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,0.93,13.9,2.7,14.68,1,0,9603,-92,-93,122,,,,,1
-392,1534,4263,4326,,Oil exploration.,2371,3,6.5,5,8.5,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-393,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,3,6.5,5,8.5,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-394,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,2.25,6.2,2.7,8,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
-395,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,3,6.5,5,8.5,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-396,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.,1717,2.25,6.2,2.7,8,1,0,9603,-93.2,-93.31,121.156,,,,,0
-397,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.,1717,2.25,6.2,2.7,8,1,0,9603,-88.98,-83.23,113.55,,,,,0
-398,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.,1717,2.25,6.2,2.7,8,1,0,9603,-92.726,-90.304,115.735,,,,,0
-399,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.,1717,2.25,6.2,2.7,8,1,0,9603,-93.134,-86.647,114.196,,,,,0
-400,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,2371,3,6.5,5,8.5,1,0,9603,-93,-94,124,,,,,0
-401,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
-402,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.,1717,2.25,6.2,2.7,8,1,0,9606,-83.13,-104.95,114.63,0,0,0.554,0,0
-403,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,2.25,6.2,2.7,8,1,0,9603,-93.6,-83.7,113.8,,,,,0
-404,15755,4263,4326,Derived in 1995 at unspecified DMA ADOS stations and Racal stations M101 and ZVS3003. Used by Elf in onshore Blocks OML 58.,Oil industry exploration and production. Accuracy 0.5m.,3113,5.05,5.31,6.54,6.83,1,0,9603,-90.2,-87.32,114.17,,,,,0
-405,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,-5.03,10.6,12.23,1,1,9603,-252.95,-4.11,-96.38,,,,,0
-406,1088,4265,4326,,Oil exploration and production,2882,43,47.25,12,19.5,1,0,9603,-223.7,-67.38,1.34,,,,,0
-407,1089,4265,4326,,Oil exploration and production,2883,41.75,43.75,13.25,19,1,0,9603,-225.4,-67.7,7.85,,,,,0
-408,1090,4265,4326,,Oil exploration and production,2884,39.75,42,16,20,1,0,9603,-227.1,-68.1,14.4,,,,,0
-409,1091,4265,4326,,Marine navigation,2885,39.5,41,18,20,1,0,9603,-231.61,-68.21,13.93,,,,,0
-410,1092,4265,4326,,Marine navigation,2886,37,40.5,16,21,1,0,9603,-225.06,-67.37,14.61,,,,,0
-411,1093,4265,4326,,Marine navigation,2887,36,37.5,13,16,1,0,9603,-229.08,-65.73,20.21,,,,,0
-412,1094,4265,4326,,Marine navigation,2888,36.5,38.5,10,13,1,0,9603,-230.47,-56.08,22.43,,,,,0
-413,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.5,41.5,8,10,1,0,9603,-225,-65,9,,,,,0
-414,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.75,47.09,6.65,18.53,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
-415,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.5,41.5,8,10,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
-416,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.5,38.5,12,16,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
-417,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.39,2.33,5.91,14.55,1,0,9603,-74,-130,42,,,,,1
-418,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.39,2.33,5.91,14.55,1,0,9603,-80.7,-132.5,41.1,,,,,0
-419,1170,4267,4326,Derived at 15 stations.,"For military purposes. Accuracy 3m, 9m and 12m in X, Y and Z axes.",2418,16.5,23.77,-85.16,-61.62,1,0,9603,-3,142,183,,,,,0
-420,1171,4267,4326,Derived at 19 stations.,"For military purposes only. Accuracy 8m, 3m and 5m in X, Y and Z axes.",2419,8.03,18.49,-92.25,-82.56,1,0,9603,0,125,194,,,,,0
-421,1172,4267,4326,Derived at 112 stations.,"For military purposes only. Accuracy 15m, 11m and 6m in X, Y and Z axes.",1061,41.68,85.05,-141.15,-48.06,1,0,9603,-10,158,187,,,,,1
-422,1173,4267,4326,Derived at 405 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",1323,24.53,49.39,-124.85,-67.07,1,0,9603,-8,160,176,,,,,0
-423,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.53,48.72,-94.41,-67.07,1,0,9603,-9,161,179,,,,,0
-424,1175,4267,4326,Derived at 276 stations.,"For military purposes only. Accuracy 5m, 3m and 3m in X, Y and Z axes.",2390,25.83,49.39,-124.85,-89.1,1,0,9603,-8,159,175,,,,,0
-425,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.35,-173.11,-129.99,1,0,9603,-5,135,172,,,,,0
-426,1177,4267,4326,Derived at 11 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",2413,20.37,30.48,-80.95,-70.67,1,0,9603,-4,154,178,,,,,0
-427,1178,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2414,23.94,24.13,-74.57,-74.42,1,0,9603,1,140,165,,,,,0
-428,1179,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 8m, 8m and 6m in X, Y and Z axes.",2384,48.3,60,-139.05,-110,1,0,9603,-7,162,188,,,,,0
-429,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.32,1,0,9603,-9,157,184,,,,,0
-430,1181,4267,4326,Derived at 37 stations.,"For military purposes only. Accuracy 6m, 6m and 3m in X, Y and Z axes.",2416,43.46,62.56,-79.76,-52.62,1,0,9603,-22,160,190,,,,,0
-431,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.11,-136.45,-61.08,1,0,9603,4,159,188,,,,,0
-432,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.65,-141,-123.82,1,0,9603,-7,139,181,,,,,0
-433,1184,4267,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2385,8.95,9.35,-79.9,-79.5,1,0,9603,0,125,201,,,,,0
-434,1185,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,1077,19.08,24.96,-86.99,-73.61,1,0,9603,-9,152,178,,,,,0
-435,1186,4267,4326,"Derived at 2 stations. Note: NAD27 is not used in Greenland.",For military purposes. Accuracy 25m in each axis.,2386,76,80,-70,-60,1,0,9603,11,114,195,,,,,0
-436,1187,4267,4326,Derived at 22 stations.,"For military purposes only. Accuracy 8m, 6m and 6m in X, Y and Z axes.",1160,12.24,32.74,-121.91,-84.69,1,0,9603,-12,130,190,,,,,0
-437,1249,4267,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 10m in X, Y and Z axes.",2387,51.2,55.05,-180,-163.05,1,0,9603,-2,152,149,,,,,0
-438,1250,4267,4326,Derived at 5 stations.,For military purposes. Accuracy 10m in each axis.,2388,51.35,52.13,172.4,180,1,0,9603,2,204,105,,,,,0
-439,1530,4267,4326,,Accuracy 3m.,1077,19.08,24.96,-86.99,-73.61,1,0,9603,-4.2,135.4,181.9,,,,,0
-440,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,18.25,20.64,-94.67,-90.44,1,0,9603,-2,124.7,196,,,,,0
-441,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.35,-87.25,-81.18,1,0,9603,-3,154,177,,,,,0
-442,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.5,30.33,-95,-87.25,1,0,9603,-7,151,175,,,,,0
-443,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,26,29.2,-97.5,-95,1,0,9603,-7,151,178,,,,,0
-444,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.5,22.4,-97.8,-97,1,0,9603,-8,125,190,,,,,0
-445,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.35,-97.5,-81.18,1,0,9603,-7,158,172,,,,,0
-446,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.64,23,-94.6,-89,1,0,9603,0,125,196,,,,,0
-447,15978,4267,4326,,Accuracy 1m.,1077,19.08,24.96,-86.99,-73.61,1,0,9607,2.478,149.752,197.726,-0.526,-0.498,0.501,0.685,0
-448,1188,4269,4326,Derived at 312 stations.,Accuracy 2m in each axis.,1325,23.94,80,170,-44,1,0,9603,0,0,0,,,,,1
-449,1251,4269,4326,Derived at 42 stations.,"For military purposes only. Accuracy 5m, 2m and 5m in X, Y and Z axes.",2157,51.2,55.05,172.4,-163.05,1,0,9603,-2,0,4,,,,,0
-450,1252,4269,4326,Derived at 6 stations.,For military purposes only. Accuracy 2m in each axis.,1334,18.9,22.24,-160.55,-154.8,1,0,9603,1,1,-1,,,,,0
-451,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.53,49.39,-124.85,-67.07,1,1,9607,-0.9738,1.9453,0.5486,-0.0275507901704247,-0.0100492213603585,-0.0113590028800276,0,0
-452,1515,4269,4326,"Strictly between NAD83 and ITRF96(1997.0). Supersedes NAD83 to WGS 84 (4) (code 1308).",Geodesy.,1323,24.53,49.39,-124.85,-67.07,1,1,9607,-0.991,1.9072,0.5129,-0.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
-453,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20,20.9,58.5,59.5,1,0,9603,-247,-148,369,,,,,0
-454,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1206,15.9,32.26,34.27,55.7,1,0,9603,-243,-192,477,,,,,1
-455,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.64,26.29,51.57,57.03,1,0,9603,-249,-156,381,,,,,0
-456,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.5,53,53.33,1,0,9603,-245,-153.9,382.8,,,,,0
-457,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.6,27.03,50.61,53.07,1,0,9603,-250.2,-153.09,391.7,,,,,0
-458,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.,1124,29.06,37.41,38.82,49.4,1,0,9603,-242.2,-144.9,370.3,,,,,0
-459,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,26,52.5,54.5,1,0,9603,-245.8,-152.2,382.9,,,,,0
-460,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,26,52.5,54.5,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
-461,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,25.25,25.75,54,54.5,1,0,9603,-244.2,-149.8,379.3,,,,,0
-462,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,25,25.4,55.1,55.4,1,0,9603,-250.7,-157.9,380.4,,,,,0
-463,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.,1235,9.82,11.68,-62.08,-58.53,1,0,9603,-10,375,165,,,,,1
-464,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.08,11.39,-60.91,-60.37,1,0,9603,-2,374,172,,,,,0
-465,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.4,-34,166.33,178.6,1,0,9603,84,-22,209,,,,,0
-466,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.4,-34,166.33,178.6,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
-467,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.4,-34,166.33,178.6,1,0,9603,54.4,-20.1,183.1,,,,,0
-468,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.95,71.2,4.6,32.02,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
-469,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,37.01,42.15,-9.5,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
-470,1983,4274,4326,,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
-471,1987,4274,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
-472,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.,1096,41.18,51.54,-9.62,10.3,1,0,9603,-168,-60,320,,,,,1
-473,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.96,60.84,-7.56,1.78,1,0,9603,375,-111,431,,,,,0
-474,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.94,55.81,-6.37,1.78,1,0,9603,371,-112,434,,,,,0
-475,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.94,55.81,-6.37,1.78,1,0,9603,371,-111,434,,,,,0
-476,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.62,58.67,-7.67,-0.72,1,0,9603,384,-111,425,,,,,0
-477,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.37,53.43,-5.34,-2.64,1,0,9603,370,-108,434,,,,,0
-478,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.,2394,49.15,63.83,-6,3.4,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,1
-479,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.4,16.51,-61.8,-60.82,1,0,9603,0,0,0,,,,,1
-480,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).",1126,29.51,33.98,33.47,35.69,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
-481,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-7.13,3.72,8.87,18.65,1,0,9603,-148,51,-291,,,,,1
-482,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-5.5,-4,11,12,1,0,9603,-145,52.7,-291.6,,,,,0
-483,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,-5.5,-4,11,12,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
-484,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,-45,-10,108,155,1,0,9603,0,0,0,,,,,1
-485,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,41.17,82,19.2,-168.98,1,0,9603,28,-130,-95,,,,,0
-486,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 GosStandard of Russia Decree #327 of August 9, 2001.",Accuracy 4 metres.,1198,41.17,82,19.2,-168.98,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
-487,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.78,48.6,16.12,22.91,1,1,9603,28,-121,-77,,,,,0
-488,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49.03,55.95,14.14,24.16,1,1,9603,23,-124,-82,,,,,0
-489,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
-490,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.64,58.12,20.98,28.23,1,0,9603,24,-124,-82,,,,,0
-491,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.67,55.57,46.52,87.41,1,0,9603,15,-130,-84,,,,,0
-492,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.67,42.69,18.45,21.06,1,1,9603,24,-130,-92,,,,,0
-493,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.62,48.26,20.26,31.5,1,1,9603,28,-121,-77,,,,,0
-494,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,36.57,47.2,46.7,54.76,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
-495,1334,4284,4326,,"?",1090,57.57,59.7,21.84,28,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
-496,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 +/- 1m level.",1145,53.92,56.48,21.07,26.82,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
-497,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).
+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.4,-20.8,55.2,55.8,1,0,9603,94,-948,-1262,,,,,1
+39,1912,4627,4326,,"Accuracy +/- 1 metre.",1196,-25.92,-10.6,37.58,58.27,1,0,9603,0,0,0,,,,,1
+40,1924,4628,4326,,"Accuracy +/- 10 metres.",2811,-17.91,-17.45,-149.96,-149.07,1,0,9603,162,117,154,,,,,1
+41,1913,4629,4326,,"Accuracy +/- 10 metres.",2812,-16.95,-16.62,-151.8,-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.62,-151.8,-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.5,-8.75,-140.25,-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,-8.75,-140.25,-139.95,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,-9,-8.85,-139.6,-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.5,-9.33,-140.17,-140,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.75,-48.5,68.5,70.6,1,1,9603,145,-187,103,,,,,0
+48,1916,4632,4326,,"Accuracy +/- 10 metres.",1159,-14.37,-11.32,44.13,45.77,1,0,9603,-382,-59,-262,,,,,1
+49,1272,4121,4326,,For applications requiring 1m or better accuracy.,3254,33.23,41.77,18.27,29.97,1,0,9603,-199.87,74.79,246.62,,,,,1
+50,1918,4634,4326,,"Accuracy +/- 10 metres.",1174,-23.46,-17.26,157.09,173.89,1,1,9603,-13,-348,292,,,,,0
+51,1929,4634,4326,,"Accuracy better than +/- 1 metre.",2822,-22.5,-20,163.9,167.1,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.3,70.09,19.3,31.59,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.3,70.09,19.3,31.59,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,55.2,69.1,10.57,24.18,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,55.2,69.1,10.57,24.18,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,55.2,69.1,10.57,24.18,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.35,0,116.9,118,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.88,-10.4,30.23,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.88,-24,31.8,35.6,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,-20,31.33,35.6,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,-20,-16,31.18,40.15,1,0,9607,-73.472,-51.66,-112.482,-0.953,-4.6,2.368,0.586,0
+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,-9.56,30.23,40.9,1,0,9607,219.315,168.975,-166.145,-0.198,-5.926,2.356,-57.104,1
+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.7,-21.3,167.75,168.15,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.7,-21.3,167.75,168.15,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.7,-21.3,167.75,168.15,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,-26.88,-9.56,30.23,43,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,15.9,16.1,107.45,108.4,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.62,8.76,106.53,106.75,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.7,28.2,51.8,52.5,1,0,9603,-241.54,-163.64,396.06,,,,,0
+72,1854,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2782,26.2,26.8,52.4,53.3,1,0,9603,-239.1,-170.02,397.5,,,,,1
+73,1855,4132,4326,Derived by Geoid for Elf in 1999. EGM96 geoid used.,Oil Exploration,2781,29,29.33,50.15,50.4,1,0,9603,-244.72,-162.773,400.75,,,,,0
+74,1333,4133,4326,,"?",3246,57.57,59.66,21.84,28,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.4,51.9,59.89,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.49,33.27,34.22,35.68,1,0,9603,-48,55,52,,,,,1
+85,1469,4142,4326,,"?",2282,5.13,5.92,-4.8,-3.4,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,0.84,10.74,-8.61,-2.49,1,0,9603,-124.76,53,466.79,,,,,1
+87,1155,4144,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 12m in X, Y and Z axes.",3217,20.63,26.65,88.1,92.72,1,0,9603,282,726,254,,,,,1
+88,1533,4144,4326,,Oil exploration.,2361,14.5,16.5,94,98,1,0,9603,214,804,268,,,,,0
+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.6,37.08,60.91,77.87,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,26.5,27.5,68.25,69.25,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,22,25.5,65,69,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.36,67.8,68.79,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.8,25.1,66.8,67.2,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,26,27,68,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. Derived at 7 stations.","For military purposes. Accuracy 12m, 10m and 15m in X, Y and Z axes.",2411,6.75,35.51,68.14,97.38,1,0,9603,295,736,257,,,,,1
+96,1544,4147,4326,Derived in Vung Tau area.,Oil exploration.,1494,8.54,12.33,104.5,107.5,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.34,-22.14,14.03,41.16,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.0257899075194932,-0.0096500989602704,-0.0116599432323421,0,0
+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.8,44.06,63.37,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.8,44.06,63.37,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.55,26.75,52.05,52.3,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.2,26.8,52.4,53.3,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,29.33,50.15,50.4,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.67,26.95,52.17,52.45,1,0,9603,-123.02,-158.95,-168.47,,,,,0
+115,1518,4155,4326,,Accuracy 25m in each axis.,3257,7.16,12.69,-15.12,-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.56,51.09,12.11,18.98,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.65,16.84,22.58,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.65,16.84,22.58,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.65,16.84,22.58,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.56,51.09,12.11,18.98,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.92,56.48,21.07,26.82,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.49,47.12,5.95,18.97,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,24,28,13,19,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,24,28,13,19,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.6,29.9,17.2,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.6,29.9,17.2,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.6,29.9,17.2,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.2,29.6,21,21.3,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.83,28.67,21.17,21.83,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.51,32.9,9.31,25.15,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.67,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,-45,-43,-178,-175,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,-45,-43,-178,-175,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 +/- 1m level.",1340,12,15,42.5,53,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.89,12.69,-16.73,-13.65,1,0,9603,-173,253,27,,,,,1
+139,1065,4678,4326,Derived at 25 stations.,Accuracy 5m.,1138,13.92,22.51,100.15,107.76,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,-22.74,157.41,-170.89,1,0,9603,0,0,0,,,,,1
+141,1569,4168,4326,Derived at 3 common points.,Military survey,1104,1.08,11.17,-3.9,1.34,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.08,6.1,-3.9,1.34,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.18,51.54,-9.62,10.3,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.",3744,51.33,55.4,-10.6,-5.33,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.89,10,-13.3,-10.27,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.67,-139.18,-138.8,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.05,-9.88,-139.15,-139,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.17,54.72,9.87,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.78,48.6,16.12,22.91,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.03,54.87,14.14,24.16,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.62,48.26,20.26,31.5,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.62,48.26,20.26,31.5,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.62,48.26,20.26,31.5,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.03,54.87,14.14,24.16,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.67,42.69,19.25,21.06,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.57,59.7,21.84,28,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.48,50.21,5.73,6.53,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.48,50.21,5.73,6.53,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.37,39.15,-28.8,-27.05,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.9,37.95,-25.9,-24.95,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,-15.54,-5.89,93.54,102.43,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.75,-48.5,68.5,70.6,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.5,-19.95,57.3,57.8,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,54.01,55.31,-8.2,-5.42,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,1.5,5,8.4,12,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,1.5,5,8.4,12,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.74,24.823,141.28,141.36,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.03,-15.88,-5.81,-5.63,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.,3203,24.26,24.32,153.95,154.01,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,41.17,82,19.2,-168.98,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,41.17,82,19.2,-168.98,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.66,13.09,8.51,16.22,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.4,14.88,32.99,48.12,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.15,25.02,-12.25,4.26,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.32,16.7,-17.55,-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.25,21.84,38.6,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,-45,-10,108,155,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.16,148.77,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.15,-28.15,140.95,153.62,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.8,-39.57,143.83,148.96,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,-11.02,129,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
+198,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,-45,-10,108,155,1,0,9603,-127.8,-52.3,152.9,,,,,0
+199,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,-60.04,-8.86,110.77,174.1,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
+200,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,-45,-10,108,155,1,0,9603,-134,-48,149,,,,,1
+201,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,-45,-10,108,155,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
+202,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,-45,-10,108,155,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
+203,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,-45,-10,108,155,1,0,9603,-128.5,-53,153.4,,,,,0
+204,1055,4204,4326,Derived at station K1.,1 metre accuracy.,1136,28.56,30.1,46.57,49.24,1,0,9603,-145.7,-249.1,1.5,,,,,0
+205,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.,1136,28.56,30.1,46.57,49.24,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
+206,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.1,46.57,49.24,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
+207,1058,4204,4326,,1 metre accuracy.,2957,28.56,29.33,46.57,48.45,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
+208,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1040,25.57,27.18,50.3,51.41,1,0,9603,-150,-250,-1,,,,,0
+209,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,1206,15.9,32.26,34.27,55.7,1,0,9603,-143,-236,7,,,,,1
+210,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,1214,-2.39,13.4,41.01,54.98,1,0,9603,-43,-163,45,,,,,1
+211,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.15,-8,156.7,156.9,1,0,9603,230,-199,-752,,,,,0
+212,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.96,-9.24,159.56,160.91,1,0,9603,252,-209,-751,,,,,1
+213,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,37.01,42.15,-9.5,-6.19,1,0,9606,-280.9,-89.8,130.2,-1.721,0.355,-0.371,-5.92,0
+214,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,37.01,42.15,-9.5,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
+215,1984,4207,4326,,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
+216,1988,4207,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
+217,1549,4208,4326,,Oil exploration.,2307,-28.4,-17.59,-48.79,-35.19,1,1,9603,-158,315,-148,,,,,0
+218,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
+219,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
+220,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
+221,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
+222,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
+223,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
+224,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
+225,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
+226,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.8,18.3,-16.67,-15.75,1,1,9603,124.5,-63.5,-281,,,,,0
+227,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
+228,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
+229,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
+230,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
+231,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
+232,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
+233,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
+234,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
+235,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
+236,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
+237,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
+238,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
+239,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
+240,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.2,20,35.92,1,0,9603,-143,-90,-294,,,,,1
+241,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
+242,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.46,-2.3,29,30.87,1,1,9603,-153,-5,-292,,,,,0
+243,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.68,-28.59,27.03,29.47,1,0,9603,-125,-108,-295,,,,,0
+244,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.15,-9.38,32.7,35.95,1,0,9603,-161,-73,-317,,,,,0
+245,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.31,-25.74,30.82,32.15,1,0,9603,-134,-105,-295,,,,,0
+246,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.38,12.21,31.3,1,1,9603,-169,-19,-278,,,,,0
+247,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.09,-8.2,22.01,33.72,1,0,9603,-147,-74,-283,,,,,0
+248,1121,4209,4326,Derived at 10 stations.,"For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.43,-15.63,25.25,33.09,1,0,9603,-142,-96,-293,,,,,0
+249,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
+250,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",1132,-4.9,5.03,33.93,45.17,1,0,9603,-157,-2,-299,,,,,0
+251,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",1230,-11.75,-1,29.36,43.51,1,0,9603,-175,-23,-303,,,,,0
+252,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.46,-2.3,29,30.87,1,0,9603,-153,-5,-292,,,,,0
+253,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,-6.5,6,95,108.55,1,0,9603,-377,681,-50,,,,,1
+254,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6,-2.75,106,110,1,0,9603,-378.873,676.002,-46.255,,,,,0
+255,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-7,-4,112,118.5,1,0,9603,-377.7,675.1,-52.2,,,,,0
+256,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
+257,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,16.81,-169.63,-169.3,1,0,9603,189,-79,-202,,,,,1
+258,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
+259,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
+260,15800,4713,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.83,41.78,44.05,1,0,9603,-79,-129,145,,,,,1
+261,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
+262,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
+263,15819,4729,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.16,-25,-130.18,-129.99,1,0,9603,185,165,42,,,,,1
+264,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
+265,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
+266,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
+267,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
+268,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
+269,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
+270,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
+271,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
+272,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
+273,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
+274,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.25,-1.49,105.12,108.29,1,0,9603,-384,664,-48,,,,,1
+275,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.58,-7.75,12.58,13.4,1,0,9603,-42.01,-332.21,-229.75,,,,,0
+276,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7,-6.03,12.08,12.84,1,0,9603,-40,-354,-224,,,,,0
+277,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
+278,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.17,-6.03,10,13.86,1,0,9603,-41.8,-342.2,-228.2,,,,,0
+279,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
+280,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.67,13.4,1,0,9603,-43,-337,-233,,,,,0
+281,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,-6.58,-6.03,10.83,11.67,1,0,9603,-48,-345,-231,,,,,0
+282,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.03,12.08,12.84,1,0,9603,-48.6,-345.1,-230.8,,,,,0
+283,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
+284,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.03,10.47,12.84,1,0,9603,-50.9,-347.6,-231,,,,,1
+285,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,3843,-54.92,-21.78,-73.58,-56.65,1,0,9603,-148,136,90,,,,,1
+286,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
+287,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",1215,-50.34,-22.14,14.03,41.16,1,0,9603,-136,-108,-292,,,,,1
+288,1129,4222,4326,"Residuals should not exceed 15 metres. Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation.","?",1215,-50.34,-22.14,14.03,41.16,1,0,9603,-134.73,-110.92,-292.66,,,,,0
+289,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.25,38.43,7.5,13.74,1,0,9603,-263,6,431,,,,,1
+290,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.13,38.43,8.62,13.74,1,0,9603,-260.1,5.5,432.2,,,,,0
+291,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
+292,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
+293,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
+294,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
+295,1585,4227,4326,,"?",1227,32.33,37.34,35.08,42.4,1,1,9603,-177.5,14.1,237.6,,,,,0
+296,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.5,35.7,39.9,40.15,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
+297,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.8,36.5,40.5,41.5,1,0,9603,-191.77,15.01,235.07,,,,,0
+298,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,35.25,35.5,40,40.5,1,0,9603,-187.5,14.1,237.6,,,,,0
+299,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,3314,32.33,37.34,35.7,42.4,1,0,9603,-190.421,8.532,238.69,,,,,1
+300,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,35.25,35.5,40,40.5,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
+301,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,41.17,82,19.2,-168.98,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
+302,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
+303,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.99,33.75,24.71,36.9,1,0,9603,-130,110,-13,,,,,1
+304,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.3,29.96,32.3,34.25,1,1,9603,-146.21,112.63,4.05,,,,,0
+305,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.33,42.5,28.15,41.5,1,0,9603,-89.05,-87.03,-124.56,,,,,0
+306,1087,4230,4326,,Topographic mapping.,1130,29.21,33.4,34.98,39.33,1,0,9603,-112,-110.3,-140.2,,,,,0
+307,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,36,71.05,-9.4,31.6,1,0,9603,-87,-98,-121,,,,,1
+308,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.5,57.5,-4.6,22.5,1,0,9603,-87,-96,-120,,,,,0
+309,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,16.38,37.38,34.27,55.67,1,0,9603,-103,-106,-141,,,,,0
+310,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,33.05,36.31,29.94,35.22,1,0,9603,-104,-101,-140,,,,,0
+311,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",1086,21.99,33.75,24.71,36.9,1,0,9603,-130,-117,-151,,,,,0
+312,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,48.17,63.9,-27,3.4,1,0,9603,-86,-96,-120,,,,,0
+313,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.87,71.05,5.3,31.6,1,0,9603,-87,-95,-120,,,,,0
+314,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3254,33.23,41.77,18.27,29.97,1,0,9603,-84,-95,-130,,,,,0
+315,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.5,41.5,8,10,1,0,9603,-97,-103,-120,,,,,0
+316,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.5,38.5,12,16,1,0,9603,-97,-88,-135,,,,,0
+317,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3275,35.8,36.09,14.18,14.6,1,0,9603,-107,-88,-149,,,,,0
+318,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.95,43.78,-9.5,3.3,1,0,9603,-84,-107,-120,,,,,0
+319,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.25,38.43,7.5,13.74,1,0,9603,-112,-77,-145,,,,,0
+320,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.18,51.54,-9.62,10.3,1,0,9603,-84,-97,-117,,,,,0
+321,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,49.05,63.9,-15.6,8,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
+322,1440,4230,4326,,Used in oil industry.,3254,33.23,41.77,18.27,29.97,1,0,9603,-86,-92.2,-127.5,,,,,0
+323,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,80.75,-0.5,32.02,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
+324,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.12,62,1.5,8,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
+325,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.5,57.9,7.8,12.9,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
+326,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.13,36.17,-5.39,-5.37,1,0,9603,-116.8,-106.4,-154.4,,,,,0
+327,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.62,40.08,1.2,4.33,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
+328,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.98,43.8,-7.5,3.27,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
+329,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.8,-9.3,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
+330,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.47,43.93,25.59,44.85,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
+331,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,27.5,30.82,25,30.74,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
+332,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.75,-11.6,-9.5,1,0,9603,-82.31,-95.23,-114.96,,,,,0
+333,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.5,55.8,2.5,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
+334,1985,4230,4326,May be taken as a transformation from ED50 to ETRS89 - see tfm code 5040.,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
+335,1989,4230,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
+336,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.9,3.3,8.5,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
+337,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.5,55.8,2.5,6.4,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+338,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.5,55.8,2.5,6.4,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,0
+339,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,35,41.9,-13.8,-7.3,1,0,9603,-86.277,-108.879,-120.181,,,,,0
+340,1146,4231,4326,,"?",2330,52,62,-4,8,1,0,9606,-82.981,-99.719,-110.709,-0.104700015651026,0.0310016003789386,0.0804020214751182,-0.3143,0
+341,1960,4231,4326,,Scientific research.,1297,36,71.05,-8.95,31.6,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+342,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,36,71.05,-8.95,31.6,1,0,9606,-83.11,-97.38,-117.22,0.00569290865241986,-0.0446975835137458,0.0442850539012516,0.1218,1
+343,1256,4232,4326,Derived at 7 stations.,"For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",3288,16.6,26.4,51.9,59.89,1,0,9603,-346,-1,224,,,,,1
+344,1438,4232,4326,,Oil exploration.,3288,16.6,26.4,51.9,59.89,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,0
+345,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-4.04,8.09,69.22,77.13,1,1,9603,-133,-321,50,,,,,0
+346,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.18,28.29,-177.42,-177.3,1,0,9603,912,-58,1227,,,,,0
+347,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.18,28.29,-177.42,-177.3,1,0,9603,403,-81,277,,,,,1
+348,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,3315,21.8,25.4,119.4,122.05,1,0,9603,-637,-549,-203,,,,,1
+349,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.78,48.6,16.12,22.91,1,0,9603,52.17,-71.82,-14.9,,,,,1
+350,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.78,48.6,16.12,22.91,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
+351,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.78,48.6,16.12,22.91,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
+352,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.78,48.6,16.12,22.91,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
+353,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.78,48.6,16.12,22.91,1,0,9603,57.01,-69.97,-9.29,,,,,0
+354,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,1122,-13.01,7.92,91.66,141.1,1,0,9603,-24,-15,5,,,,,1
+355,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.,1122,-13.01,7.92,91.66,141.1,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
+356,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.",1122,-13.01,7.92,91.66,141.1,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
+357,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.47,98.1,105.7,1,0,9603,217,823,299,,,,,1
+358,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.47,98,105.7,1,0,9603,209,818,290,,,,,0
+359,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.47,98,105.7,1,0,9603,210,814,289,,,,,1
+360,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,7.3,8.3,102.2,102.7,1,0,9603,204.64,834.74,293.8,,,,,0
+361,1812,4240,4326,,Cadastral survey.,3741,5.63,20.47,98,105.7,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
+362,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
+363,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
+364,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
+365,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
+366,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.75,-22.5,167.3,167.55,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
+367,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.75,-22.5,167.3,167.55,1,0,9603,-13,-348,292,,,,,1
+368,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3310,5.85,9.92,79.6,81.95,1,0,9603,-97,787,86,,,,,1
+369,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",1309,1.26,6.71,99.64,104.29,1,0,9603,-11,851,5,,,,,1
+370,1059,4246,4326,,1 metre accuracy.,3267,28.56,30.1,46.57,48.45,1,0,9603,-294.7,-200.1,525.5,,,,,1
+371,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,3.36,10.8,-67.49,-59.8,1,0,9603,-273.5,110.6,-357.9,,,,,1
+372,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
+373,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
+374,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
+375,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
+376,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
+377,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
+378,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
+379,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
+380,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
+381,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
+382,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
+383,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
+384,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
+385,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,42.3,46.57,13.02,19.5,1,0,9603,0,0,0,,,,,1
+386,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.08,11.17,-3.9,1.34,1,0,9603,-130,29,364,,,,,1
+387,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,3270,4.27,8.57,-11.5,-7.37,1,0,9603,-90,40,88,,,,,1
+388,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.35,39.75,-31.3,-31.06,1,0,9603,-425,-169,81,,,,,1
+389,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.35,39.75,-31.3,-31.06,1,0,9603,-422.651,-172.995,84.02,,,,,0
+390,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.5,21,116,127,1,0,9603,-133,-77,-51,,,,,1
+391,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,4,10,119,127,1,0,9603,-133,-79,-72,,,,,0
+392,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
+393,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
+394,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.41,38.5,60.54,74.96,1,0,9603,-333,-222,114,,,,,1
+395,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-5,-4.5,55,56,1,0,9603,41,-220,-134,,,,,1
+396,1837,4257,4326,,Oil exploration.,1316,-7.9,2,117.6,121,1,0,9603,-587.8,519.75,145.76,,,,,1
+397,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,34.5,71.05,-10.67,31.55,1,0,9603,0,0,0,,,,,1
+398,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.78,55.8,2.48,7.37,1,1,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
+399,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,-5.03,10.85,12.43,1,0,9603,-252.95,-4.11,-96.38,,,,,0
+400,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,-5.03,10.85,12.43,1,0,9603,-254.1,-5.36,-100.29,,,,,1
+401,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.,3179,-6,-4.37,10.85,13.11,1,0,9603,-259.99,-5.28,-97.09,,,,,0
+402,1316,4260,4326,,"?",1060,1.66,13.09,8.38,16.22,1,1,9603,-70.9,-151.8,-41.4,,,,,0
+403,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",3280,27.68,36.23,-13.77,-1.01,1,0,9603,31,146,47,,,,,1
+404,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.33,18.57,36.4,43.3,1,0,9603,639,405,60,,,,,1
+405,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.53,4.42,6.28,1,0,9603,-92.1,-89.9,114.9,,,,,0
+406,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.66,13.09,8.51,16.22,1,0,9603,-81,-84,115,,,,,0
+407,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,0.93,13.9,2.7,14.68,1,0,9603,-92,-93,122,,,,,1
+408,1534,4263,4326,,Oil exploration.,2371,3,6.5,5,8.5,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+409,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,3,6.5,5,8.5,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+410,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,2.25,6.2,2.7,8,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
+411,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,3,6.5,5,8.5,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+412,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.53,4.02,6.95,1,0,9603,-93.2,-93.31,121.156,,,,,0
+413,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
+414,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
+415,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.59,8.03,1,0,9603,-93.134,-86.647,114.196,,,,,0
+416,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,3824,9.5,11,10,11.5,1,0,9603,-93,-94,124,,,,,0
+417,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
+418,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
+419,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,2.25,6.2,2.7,8,1,0,9603,-93.6,-83.7,113.8,,,,,0
+420,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.31,6.54,6.83,1,0,9603,-90.2,-87.32,114.17,,,,,0
+421,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,-5.03,10.6,12.23,1,1,9603,-252.95,-4.11,-96.38,,,,,0
+422,1088,4265,4326,,Oil exploration and production,2882,43,47.25,12,19.5,1,0,9603,-223.7,-67.38,1.34,,,,,0
+423,1089,4265,4326,,Oil exploration and production,2883,41.75,43.75,13.25,19,1,0,9603,-225.4,-67.7,7.85,,,,,0
+424,1090,4265,4326,,Oil exploration and production,2884,39.75,42,16,20,1,0,9603,-227.1,-68.1,14.4,,,,,0
+425,1091,4265,4326,,Marine navigation,2885,39.5,41,18,20,1,0,9603,-231.61,-68.21,13.93,,,,,0
+426,1092,4265,4326,,Marine navigation,2886,37,40.5,16,21,1,0,9603,-225.06,-67.37,14.61,,,,,0
+427,1093,4265,4326,,Marine navigation,2887,36,37.5,13,16,1,0,9603,-229.08,-65.73,20.21,,,,,0
+428,1094,4265,4326,,Marine navigation,2888,36.5,38.5,10,13,1,0,9603,-230.47,-56.08,22.43,,,,,0
+429,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.5,41.5,8,10,1,0,9603,-225,-65,9,,,,,0
+430,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.75,47.09,6.65,18.53,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
+431,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.5,41.5,8,10,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
+432,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.5,38.5,12,16,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
+433,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.39,2.33,5.91,14.55,1,0,9603,-74,-130,42,,,,,1
+434,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.39,2.33,5.91,14.55,1,0,9603,-80.7,-132.5,41.1,,,,,0
+435,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
+436,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
+437,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
+438,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
+439,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.9,49.37,-97.23,-66.92,1,0,9603,-9,161,179,,,,,0
+440,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
+441,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
+442,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
+443,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
+444,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
+445,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
+446,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
+447,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
+448,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
+449,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
+450,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
+451,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
+452,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
+453,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
+454,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
+455,1530,4267,4326,,Accuracy 3m.,1077,18.83,25.5,-87.01,-73.57,1,0,9603,-4.2,135.4,181.9,,,,,0
+456,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
+457,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
+458,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
+459,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
+460,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
+461,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
+462,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
+463,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
+464,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
+465,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
+466,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
+467,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
+468,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
+469,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20,20.9,58.5,59.5,1,0,9603,-247,-148,369,,,,,0
+470,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1206,15.9,32.26,34.27,55.7,1,0,9603,-243,-192,477,,,,,1
+471,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.64,26.29,51.57,57.03,1,0,9603,-249,-156,381,,,,,0
+472,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.5,53,53.33,1,0,9603,-245,-153.9,382.8,,,,,0
+473,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.6,27.03,50.61,53.07,1,0,9603,-250.2,-153.09,391.7,,,,,0
+474,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.,1124,29.06,37.41,38.82,49.4,1,0,9603,-242.2,-144.9,370.3,,,,,0
+475,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,26,52.5,54.5,1,0,9603,-245.8,-152.2,382.9,,,,,0
+476,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,26,52.5,54.5,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
+477,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,25.25,25.75,54,54.5,1,0,9603,-244.2,-149.8,379.3,,,,,0
+478,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,25,25.4,55.1,55.4,1,0,9603,-250.7,-157.9,380.4,,,,,0
+479,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
+480,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
+481,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.4,-34,166.33,178.6,1,0,9603,84,-22,209,,,,,0
+482,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.4,-34,166.33,178.6,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
+483,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.4,-34,166.33,178.6,1,0,9603,54.4,-20.1,183.1,,,,,0
+484,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.95,71.2,4.6,31.16,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
+485,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,37.01,42.15,-9.5,-6.19,1,0,9606,-238.2,85.2,29.9,0.166,0.046,1.248,2.03,0
+486,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,37.01,42.15,-9.5,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
+487,1983,4274,4326,,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
+488,1987,4274,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
+489,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.33,51.1,-5.2,9.6,1,0,9603,-168,-60,320,,,,,1
+490,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.96,60.84,-7.56,1.78,1,0,9603,375,-111,431,,,,,1
+491,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.94,55.81,-6.37,1.78,1,0,9603,371,-112,434,,,,,0
+492,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.94,55.81,-6.37,1.78,1,0,9603,371,-111,434,,,,,0
+493,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.62,58.67,-7.67,-0.72,1,0,9603,384,-111,425,,,,,0
+494,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.37,53.43,-5.34,-2.64,1,0,9603,370,-108,434,,,,,0
+495,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.96,60.84,-7.56,1.78,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,0
+496,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
+497,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.49,33.27,34.22,35.68,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
+498,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-7.13,3.72,8.87,18.65,1,0,9603,-148,51,-291,,,,,1
+499,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-5.5,-4,11,12,1,0,9603,-145,52.7,-291.6,,,,,0
+500,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,-5.5,-4,11,12,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
+501,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,-45,-10,108,155,1,0,9603,0,0,0,,,,,1
+502,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,41.17,82,19.2,-168.98,1,0,9603,28,-130,-95,,,,,0
+503,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,41.17,82,19.2,-168.98,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
+504,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.78,48.6,16.12,22.91,1,1,9603,28,-121,-77,,,,,0
+505,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49.03,55.95,14.14,24.16,1,1,9603,23,-124,-82,,,,,0
+506,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
+507,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.64,58.12,20.98,28.23,1,0,9603,24,-124,-82,,,,,0
+508,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.67,55.57,46.52,87.41,1,0,9603,15,-130,-84,,,,,0
+509,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.67,42.69,18.45,21.06,1,1,9603,24,-130,-92,,,,,0
+510,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.62,48.26,20.26,31.5,1,1,9603,28,-121,-77,,,,,0
+511,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,36.57,47.2,46.7,54.76,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
+512,1334,4284,4326,,"?",3246,57.57,59.66,21.84,28,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
+513,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 +/- 1m level.",1145,53.92,56.48,21.07,26.82,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
+514,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,38.41,41.94,44.82,50.41,1,0,9606,27,-135,-84.5,0,0,0.554,0.2263,0
-498,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,38.26,43.58,40,51.68,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
-499,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.41,40.42,48.7,50.4,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
-500,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,82,19.2,-168.98,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
-501,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1195,24.48,27.03,50.61,53.07,1,0,9603,-128,-283,22,,,,,1
-502,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.6,27.03,50.61,53.07,1,0,9603,-128.16,-282.42,21.93,,,,,0
-503,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.48,26.18,50.75,51.64,1,0,9603,-128.033,-283.697,21.052,,,,,0
-504,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
-505,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.75,3.2,7.24,1,0,9606,593.16,26.15,478.54,-1.30439800822601,-0.103297414968546,-1.14450153042326,4.0775,0
-506,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.75,3.2,7.24,1,0,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
-507,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.75,3.2,7.24,1,0,9607,565.4171,50.3319,465.5524,0.398957388243134,-0.343987817378283,1.87740163998045,4.0725,1
-508,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.75,3.2,7.24,1,0,9607,565.2369,50.0087,465.658,0.406857330322398,-0.350732676542563,1.8703473836068,4.0812,0
-509,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
-510,1213,4291,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-60.04,-21.8,-73.62,-53.5,1,1,9603,-62,-1,-37,,,,,0
-511,1214,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.91,-9.69,-69.69,-57.49,1,1,9603,-61,2,-48,,,,,0
-512,1215,4291,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",1053,-35.89,7.25,-74.05,-26.12,1,1,9603,-60,-2,-41,,,,,0
-513,1216,4291,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-60.04,-17.52,-113.28,-66.39,1,1,9603,-75,-1,-44,,,,,0
-514,1217,4291,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.22,15.93,-85.79,-66.91,1,1,9603,-44,6,-36,,,,,0
-515,1218,4291,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,1085,-5.01,4.89,-95.43,-75.26,1,1,9603,-48,3,-44,,,,,0
-516,1219,4291,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.6,1.75,-92,-89,1,1,9603,-47,26,-42,,,,,0
-517,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,11.98,-61.43,-55.72,1,1,9603,-53,3,-47,,,,,0
-518,1221,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.6,-19.31,-62.68,-54.28,1,1,9603,-61,2,-33,,,,,0
-519,1222,4291,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-20.72,-0.03,-84.73,-68.72,1,1,9603,-58,0,-44,,,,,0
-520,1223,4291,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.82,11.68,-62.08,-58.53,1,1,9603,-45,12,-33,,,,,0
-521,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.76,-73.36,-57.38,1,1,9603,-45,8,-33,,,,,0
-522,1548,4291,4326,"Derived by Brazilean Institute of Geography and Statistics (IGBE) in 1989. Used by ANP.",Medium and small scale mapping.,1053,-35.89,7.25,-74.05,-26.12,1,1,9603,-66.87,4.37,-38.52,,,,,0
-523,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.5,-51.25,-59.75,-57.5,1,0,9603,-355,21,72,,,,,1
-524,1226,4293,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1169,-31.2,-16.99,8.32,25.28,1,0,9603,616,97,-251,,,,,1
-525,1271,4293,4326,"Beware!  Schwarzeck CRS uses German legal metres. Example: Schwarzeck Lat 19d 35m 46.952s S Long 20d 41m 50.649s E; X=5623409.40 Y=2124618.00 Z=-2125847.62 GLM; X=5623485.86 Y=2124646.89 Z=-2125876.53 m; WGS84 X=5624101.50 Y=2124748.97 Z=2126132.34 m.","?",1169,-31.2,-16.99,8.32,25.28,1,0,9603,615.64,102.08,-255.81,,,,,0
-526,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-5.72,4.4,104.94,119.62,1,1,9603,-403,684,41,,,,,0
-527,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-5.72,4.4,104.94,119.62,1,1,9603,-403,684,41,,,,,0
-528,1835,4294,4326,,Oil exploration.,1360,-5.72,4.4,113.69,119.62,1,1,9603,-387.06,636.53,46.29,,,,,0
-529,1836,4294,4326,,Oil exploration.,2770,-2.35,4.4,113.7,119.62,1,1,9603,-403.4,681.12,46.56,,,,,0
-530,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-28.89,-10.6,41.14,55.34,1,0,9603,-189,-242,-91,,,,,1
-531,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.35,109.55,119.26,1,0,9603,-679,669,-48,,,,,0
-532,1592,4298,4326,,Offshore oil exploration.,2348,4.58,6.1,113,115.15,1,0,9603,-678,670,-48,,,,,0
-533,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.05,114.1,115.36,1,0,9603,-726.282,703.611,-48.999,,,,,0
-534,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.5,12,109.5,119,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,1
-535,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.33,55.4,-10.6,-5.33,1,1,9603,506,-122,611,,,,,0
-536,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.,1125,48.13,56.72,-13.42,-5.2,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-537,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.33,55.4,-10.6,-5.33,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-538,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.33,55.4,-10.6,-5.33,1,0,9603,506,-122,611,,,,,0
-539,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,24.25,45.49,123.68,145.81,1,0,9603,-148,507,685,,,,,0
-540,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",1129,19.01,45.92,122.49,160.09,1,0,9603,-148,507,685,,,,,1
-541,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.
-.",1135,31.6,39.16,122.52,132.1,1,0,9603,-146,507,687,,,,,0
-542,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,26,27.5,127.5,128.5,1,0,9603,-158,507,676,,,,,0
-543,1305,4301,4326,"Derived at 29 stations. Replaces Tokyo to WGS 84 (3) (code 1232).",For military purposes. Accuracy 2m in each axis.,1135,31.6,39.16,122.52,132.1,1,0,9603,-147,506,687,,,,,0
-544,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.",1129,19.01,45.92,122.49,160.09,1,0,9603,-146.414,507.337,680.507,,,,,0
-545,1296,4302,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,1339,9.82,11.68,-62.08,-58.53,1,0,9603,-61.702,284.488,472.052,,,,,1
-546,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.82,11.68,-62.08,-58.53,1,0,9603,-61,285.2,471.6,,,,,0
-547,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.35,-22.1,166.3,166.5,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
-548,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.35,-22.1,166.3,166.5,1,0,9603,-10.18,-350.43,291.37,,,,,1
-549,1294,4304,4326,Accuracy estimate not available.,For military purposes.,2347,31.5,37.09,-3.89,9.23,1,0,9603,-73,-247,227,,,,,1
-550,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3199,27.6,29.5,-18.3,-13.3,1,0,9603,-307,-92,127,,,,,1
-551,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,1026,18.98,37.09,-8.67,11.99,1,0,9603,-186,-93,310,,,,,1
-552,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.09,-2.92,9.09,1,0,9603,-123,-206,219,,,,,0
-553,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1.5,3.25,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
-554,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.25,9,9.7,1,0,9603,-95.7,10.2,158.9,,,,,0
-555,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.3,31.5,6.8,7.2,1,0,9603,-165.914,-70.607,305.009,,,,,0
-556,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.52,1,0,9603,-169.559,-72.34,303.102,,,,,0
-557,1234,4309,4326,Accuracy estimate not available.,For military purposes.,1247,-37.87,-30.12,-58.51,-50.45,1,0,9603,-155,171,37,,,,,1
-558,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.51,-58.11,-52.87,1,0,9603,-265,120,-358,,,,,1
-559,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.6,47.9,13.5,16.2,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
-560,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,41.85,46.88,13.38,23.01,1,1,9603,682,-203,480,,,,,0
-561,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
-562,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
-563,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,42.3,46.57,13.02,19.5,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-564,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.44,46.91,13.37,16.68,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-565,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.82,43.55,18.44,20.39,1,1,9603,695.5,-216.6,491.1,,,,,0
-566,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.44,46.91,13.37,16.68,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-567,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.,1044,49.53,51.83,2.12,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
-568,1610,4313,4326,,For applications to an accuracy of 5 metres.,1044,49.53,51.83,2.12,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
-569,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.53,51.83,2.12,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,1
-570,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.,1044,49.53,51.83,2.12,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,0
-571,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.04,5.87,13.83,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,1
-572,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.04,5.87,13.83,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,0
-573,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.17,54.72,9.87,15.03,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
-574,1517,4315,4326,,"?",1112,6.38,12.69,-17.07,-7.65,1,0,9603,-23,259,-9,,,,,1
-575,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.62,48.26,20.26,31.5,1,1,9603,103.25,-100.4,-307.19,,,,,0
-576,1995,4316,4326,,Oil exploration,1197,43.62,48.26,20.26,31.5,1,0,9603,103.25,-100.4,-307.19,,,,,1
-577,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.62,48.26,20.26,31.5,1,1,9603,28,-121,-77,,,,,0
-578,1996,4317,4326,,Oil exploration,1197,43.62,48.26,20.26,31.5,1,1,9603,44.107,-116.147,-54.648,,,,,0
-579,1060,4318,4326,,1 metre accuracy.,1136,28.56,30.1,46.57,49.24,1,0,9603,-3.2,-5.7,2.8,,,,,1
-580,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1136,28.56,30.1,46.57,49.24,1,0,9603,-20.8,11.3,2.4,,,,,1
-581,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1136,28.56,30.1,46.57,49.24,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
-582,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
-583,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
-584,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.6,-17.26,177.02,178.87,1,1,9603,51,391,-36,,,,,0
-585,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
-586,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.4,-14.61,166.5,168.31,1,0,9603,170,42,84,,,,,1
-587,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.64,19.34,162.03,168,1,0,9603,102,52,-38,,,,,1
-588,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.78,48.6,16.12,22.91,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
-589,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-23.46,-17.26,157.09,173.89,1,1,9603,0,0,0,,,,,0
-590,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.26,19.34,166.58,166.66,1,0,9603,276,-57,149,,,,,1
-591,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,21.43,26.36,118.07,122.49,1,0,9603,0,0,0,,,,,1
-592,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-37.43,-37.05,-12.73,-12.21,1,0,9603,-632,438,-609,,,,,1
-593,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.49,-7.21,72.34,72.5,1,0,9603,208,-435,-229,,,,,1
-594,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,4,12.76,136.66,168.43,1,0,9603,647,1777,-1124,,,,,1
-595,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-64.1,-62.86,-61,-60.18,1,0,9603,260,12,-147,,,,,1
-596,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.61,23.88,-166.33,-166.03,1,0,9603,114,-116,-333,,,,,1
-597,15801,4714,4326,Derived at 3 satellite stations.,"Millitary and topographic mapping; Accuracy +/- 20 m in each axis",3193,-19.7,-17.4,168.1,169.64,1,0,9603,-127,-769,472,,,,,1
-598,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,31.6,39.16,122.52,132.1,1,0,9603,0,0,0,,,,,1
-599,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.52,-16.33,-152.33,-152.16,1,0,9603,217.037,86.959,23.956,,,,,1
-600,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
-601,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.16,22.62,113.89,114.57,1,0,9603,-156,-271,-189,,,,,1
-602,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-14,-13,-177,-176,1,1,9603,252,-132,-125,,,,,0
-603,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-14,-13,-177,-176,1,0,9603,253,-132,-127,,,,,1
-604,15802,4715,4326,No accuracy estimate available.,Miltiary and scientific mapping.,3205,-78,-77,165.5,167,1,0,9603,-104,-129,239,,,,,1
-605,1994,4657,4326,,Low accuracy applications.,1120,59.87,69.23,-28.64,-10.32,1,0,9603,-28,199,5,,,,,1
-606,15872,4743,4326,Derived from shifts in UTM rectangular coordinates for Basra area provided by Iraq National Oil Exploration Company.,Oil exploration.,3397,29.06,31,46,49.4,1,0,9603,84.1,-320.1,218.7,,,,,1
-607,1951,4658,4326,Derived at 6 stations.,"Accuracy 3m, 3m and 5m in X, Y and Z axes.",1120,59.87,69.23,-28.64,-10.32,1,0,9603,-73,46,-86,,,,,1
-608,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.41,38.82,49.4,1,0,9603,0,0,0,,,,,1
-609,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.87,69.23,-28.64,-10.32,1,0,9603,0,0,0,,,,,1
-610,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.8,71.2,-9.15,-7.9,1,0,9606,982.6087,552.753,-540.873,6.68162662527694,-31.6114924086422,-19.8481610048168,16.805,1
-611,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.64,58.12,20.98,28.23,1,0,9603,0,0,0,,,,,1
-612,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.6,16.5,8,15.5,1,0,9603,-106,-87,188,,,,,1
-613,15803,4716,4326,Derived at 4 satellite stations.,"Miltary and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.64,-2.72,-174.2,-171.3,1,0,9603,298,-304,-375,,,,,1
-614,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.44,46.91,13.37,16.68,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-615,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.44,46.91,13.37,16.68,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-616,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,41.85,46.88,13.38,23.01,1,0,9603,682,-203,480,,,,,1
-617,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.,1076,42.3,46.57,13.02,19.5,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-618,3965,3906,4326,,Oil industry,3536,41.82,43.55,18.44,20.39,1,0,9603,695.5,-216.6,491.1,,,,,0
-619,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,53.7,85.05,-75.1,5.37,1,0,9603,0,0,0,,,,,1
-620,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.5,-20,163.9,167.1,1,0,9603,-13,-348,292,,,,,1
-621,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.5,-20,163.9,167.1,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
-622,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.5,-20,163.9,167.1,1,0,9603,-11.64,-348.6,291.98,,,,,0
-623,15878,4748,4326,"Approximation at the +/- 50m level assuming that Vanua Levu 1915 is equivalent to Vitu Levu 1912 within the accuracy of the transformation. Parameter values taken from Vitu Levu 1912 to WGS 84 (1) (tfm code 15897).","For applications with an accuracy of +/-50m.",3401,-17.05,-16,178.25,-179.5,1,0,9603,51,391,-36,,,,,1
-624,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.62,33.15,-17.27,-16.25,1,0,9603,-502.862,-247.438,312.724,,,,,1
-625,1967,4663,4326,,For medium resolution applications.,2870,32.62,33.15,-17.27,-16.25,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
-626,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-23.46,-17.26,157.09,173.89,1,0,9603,0,0,0,,,,,1
-627,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.65,37.95,-25.9,-25.1,1,0,9603,-204.633,140.216,55.199,,,,,0
-628,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.65,37.95,-25.9,-25.1,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
-629,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.9,37.95,-25.9,-24.95,1,0,9603,-204.619,140.176,55.226,,,,,1
-630,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.9,37.95,-25.9,-24.95,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
-631,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.75,-20.35,166.35,166.7,1,0,9603,-56.263,16.136,-22.856,,,,,1
-632,1972,4665,4326,,For low resolution applications.,2872,38.6,38.85,-27.4,-27.05,1,0,9603,-106.301,166.27,-37.916,,,,,0
-633,1973,4665,4326,,For medium resolution applications.,2872,38.6,38.85,-27.4,-27.05,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
-634,1974,4665,4326,,For low resolution applications.,2873,38.5,38.65,-28.8,-28.58,1,0,9603,-106.248,166.244,-37.845,,,,,0
-635,1975,4665,4326,,For medium resolution applications.,2873,38.5,38.65,-28.8,-28.58,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
-636,1976,4665,4326,,For low resolution applications.,2874,38.37,38.57,-28.55,-28,1,0,9603,-106.044,166.655,-37.876,,,,,0
-637,1977,4665,4326,,For medium resolution applications.,2874,38.37,38.57,-28.55,-28,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
-638,1978,4665,4326,,For low resolution applications.,2875,38.5,38.75,-28.35,-27.75,1,0,9603,-106.253,166.239,-37.854,,,,,0
-639,1979,4665,4326,,For medium resolution applications.,2875,38.5,38.75,-28.35,-27.75,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
-640,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.35,39.15,-28.85,-27,1,0,9603,-106.226,166.366,-37.893,,,,,1
-641,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.35,39.15,-28.85,-27,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
-642,1986,4666,4326,,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
-643,1990,4666,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
-644,15804,4717,4326,Derived at 19 satellite stations.,"US space and military operations. Accuracy +/- 3 m in each axis.",3206,20.8,30.69,-82,-72.72,1,0,9603,-2,151,181,,,,,1
-645,15897,4752,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.6,-17.26,177.02,178.87,1,0,9603,51,391,-36,,,,,1
-646,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.05,30.1,46.5,48,1,0,9603,0,0,0,,,,,1
-647,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,3111,36,71.05,-8.95,31.6,1,0,9603,-86,-98,-119,,,,,1
-648,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.51,36,9.31,25.98,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
-649,4477,4463,4326,"Approximation at the +/- 1m level assuming that RGSPM06 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1220,43.53,47.39,-58.02,-55.12,1,0,9603,0,0,0,,,,,1
-650,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.01,7.92,91.66,141.1,1,0,9603,0,0,0,,,,,1
-651,1555,4158,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,3143,10.04,10.84,-61.93,-60.91,1,0,9603,-0.465,372.095,171.736,,,,,1
-652,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,10.04,10.84,-61.93,-60.91,1,0,9603,-2,374,172,,,,,0
-653,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.37,-11.32,44.13,45.77,1,0,9603,0,0,0,,,,,1
-654,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.85,-19.54,163.55,163.7,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
-655,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,-12.6,44.97,45.32,1,0,9603,-381.788,-57.501,-256.673,,,,,1
-656,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.1,-3.95,12.21,16.5,1,0,9603,-79.9,-158,-168.9,,,,,1
-657,4832,4483,4326,,Accuracy 1m.,1160,12.24,32.74,-121.91,-84.69,1,0,9603,0,0,0,,,,,1
-658,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.2,-20.7,167,167.5,1,0,9603,336,223,-231,,,,,1
-659,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.2,-20.7,167,167.5,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
-660,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.2,-20.7,167,167.5,1,0,9603,335.47,222.58,-230.94,,,,,0
-661,15925,4758,4326,,For all practical purposes JAD2001 can be considered to be coincident with WGS 84.,1128,14.63,19.42,-80.74,-74.38,1,0,9603,0,0,0,,,,,1
-662,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
-663,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,-15.17,71.35,172.4,-63.89,1,0,9603,0,0,0,,,,,1
-664,1540,4163,4326,,Accuracy better than 1 metre.,1257,11.61,19.01,41.44,55.03,1,0,9603,0,0,0,,,,,1
-665,15806,4719,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis",3188,-27.21,-27.06,-109.47,-109.23,1,0,9603,211,147,111,,,,,1
-666,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.31,-20.41,-4.81,1,0,9603,0,0,0,,,,,1
-667,15971,4762,4326,"Approximation at the +/- 1m level assuming that BDA2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1047,28.87,35.77,-68.23,-61.34,1,0,9603,0,0,0,,,,,1
-668,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.16,-25,-130.18,-129.99,1,0,9603,0,0,0,,,,,1
-669,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,1135,31.6,39.16,122.52,132.1,1,0,9603,0,0,0,,,,,1
-670,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,27.6,29.5,-18.3,-13.3,1,0,9603,0,0,0,,,,,1
-671,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-60,145,-140,1,0,9603,0,0,0,,,,,1
-672,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.36,21.25,-17.5,-16,1,0,9603,-80.01,253.26,291.19,,,,,1
-673,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.44,46.91,13.37,16.68,1,0,9603,0,0,0,,,,,1
-674,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.8,18.3,-18.1,-15.75,1,0,9603,124.5,-63.5,-281,,,,,1
-675,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,-25.1,-9.79,172.87,-176.16,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
-676,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,-18.5,-16,177,-179.5,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
-677,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,15.09,26.65,88.1,92.72,1,1,9603,283.8,735.9,261.1,,,,,0
-678,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,15.09,26.65,88.1,92.72,1,0,9603,283.7,735.9,261.1,,,,,1
-679,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.75,-20.35,166.35,166.7,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
-680,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,2.25,21.43,116.09,140.08,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
-681,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-4.04,8.09,69.22,77.13,1,0,9603,-133,-321,50,,,,,1
-682,15830,4723,4326,Determined from 6 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.65,19.76,-80.1,-79.71,1,0,9603,67.8,106.1,138.8,,,,,1
-683,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.3,28.5,30.78,1,0,9603,0,0,0,,,,,1
-684,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.3,29.96,32.3,34.25,1,0,9603,-146.21,112.63,4.05,,,,,1
-685,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,37.75,38.25,108,108.5,1,0,9603,12.646,-155.176,-80.863,,,,,0
-686,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.4,37,119.2,124.2,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
-687,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,19.5,22,111,117,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
-688,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,42,77.5,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
-689,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,19,21.4,108,109.6,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
-690,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,37.75,38.25,108,108.5,1,0,9603,11.911,-154.833,-80.079,,,,,0
-691,15875,4721,4326,Derived at 20 stations.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-18.5,-16,177,-179.5,1,0,9603,265.025,384.929,-194.046,,,,,1
-692,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,-29,-7,-155,-132,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
-693,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-29,-7,-155,-132,1,0,9603,0,0,0,,,,,0
-694,1921,4636,4326,,"Accuracy +/- 10 metres.",2818,-68,-66,135,142,1,0,9603,365,194,166,,,,,1
-695,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.55,-10.33,-138.7,-138.55,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
-696,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.82,46.23,18.83,23.05,1,0,9603,0,0,0,,,,,1
-697,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-68,-66,135,142,1,0,9603,325,154,172,,,,,1
-698,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-7.99,-7.88,-14.42,-14.29,1,0,9603,-205,107,53,,,,,1
-699,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.61,-17.45,-149.96,-149.69,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
-700,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3187,-55.22,-53.8,-38.46,-34.63,1,0,9603,-794,119,-298,,,,,1
-701,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,-11.9,-10.8,26.66,27.7,1,0,9603,-103.746,-9.614,-255.95,,,,,1
-702,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.7,27.8,52.1,52.25,1,0,9603,0,-0.15,0.68,,,,,1
-703,1441,4601,4326,,"?",1273,16.99,17.72,-61.89,-61.67,1,0,9603,-255,-15,71,,,,,1
-704,15811,4601,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",1273,16.99,17.72,-61.89,-61.67,1,0,9603,-270,13,62,,,,,0
-705,1442,4602,4326,,"?",1082,14.78,17.28,-62.52,-57.64,1,0,9603,725,685,536,,,,,1
-706,1443,4603,4326,,"?",3118,11.95,12.25,-61.8,-61.55,1,0,9603,72,213.7,93,,,,,1
-707,1444,4604,4326,Derived at 1 satellite station.,Accuracy 25m in each axis.,1165,16.09,17.04,-63.16,-61.88,1,0,9603,174,359,365,,,,,1
-708,1445,4605,4326,,"?",1200,16.58,17.75,-63.63,-62.21,1,0,9603,9,183,236,,,,,1
-709,15750,4605,4326,Dereived at 2 stations.,"For military purposes. Accuracy 25m in each of X, Y and Z axes.",1200,16.58,17.75,-63.63,-62.21,1,0,9603,-7,215,225,,,,,0
-710,1446,4606,4326,,"?",1201,13.38,14.37,-62.71,-60.14,1,0,9603,-149,128,296,,,,,1
-711,1959,4607,4326,Derived at 4 points.,1m accuracy.,1202,12.15,13.76,-62.75,-60.39,1,0,9603,195.671,332.517,274.607,,,,,1
+515,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,38.26,43.58,40,51.68,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
+516,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.41,40.42,48.7,50.4,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
+517,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,41.17,82,19.2,-168.98,1,0,9607,23.57,-140.95,-79.8,0,-0.35,-0.79,-0.22,0
+518,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,82,19.2,-168.98,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
+519,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1346,24.48,26.18,50.75,51.64,1,0,9603,-128,-283,22,,,,,0
+520,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.6,27.03,50.61,53.07,1,0,9603,-128.16,-282.42,21.93,,,,,1
+521,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.48,26.18,50.75,51.64,1,0,9603,-128.033,-283.697,21.052,,,,,0
+522,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
+523,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.75,3.2,7.24,1,0,9606,593.16,26.15,478.54,-1.30439800822601,-0.103297414968546,-1.14450153042326,4.0775,0
+524,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.75,3.2,7.24,1,0,9607,565.04,49.91,465.84,0.409394387439237,-0.359705195614311,1.86849100035057,4.0772,0
+525,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.75,3.2,7.24,1,0,9607,565.4171,50.3319,465.5524,0.398957388243134,-0.343987817378283,1.87740163998045,4.0725,1
+526,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.75,3.2,7.24,1,0,9607,565.2369,50.0087,465.658,0.406857330322398,-0.350732676542563,1.8703473836068,4.0812,0
+527,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
+528,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
+529,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
+530,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
+531,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
+532,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
+533,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
+534,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
+535,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
+536,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
+537,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
+538,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
+539,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
+540,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
+541,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.5,-51.25,-59.75,-57.5,1,0,9603,-355,21,72,,,,,1
+542,1226,4293,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1169,-31.2,-16.99,8.32,25.28,1,0,9603,616,97,-251,,,,,1
+543,1271,4293,4326,"Beware!  Schwarzeck CRS uses German legal metres. Example: Schwarzeck Lat 19d 35m 46.952s S Long 20d 41m 50.649s E; X=5623409.40 Y=2124618.00 Z=-2125847.62 GLM; X=5623485.86 Y=2124646.89 Z=-2125876.53 m; WGS84 X=5624101.50 Y=2124748.97 Z=2126132.34 m.","?",1169,-31.2,-16.99,8.32,25.28,1,0,9603,615.64,102.08,-255.81,,,,,0
+544,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-5.72,4.4,104.94,119.62,1,1,9603,-403,684,41,,,,,0
+545,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-5.72,4.4,104.94,119.62,1,1,9603,-403,684,41,,,,,0
+546,1835,4294,4326,,Oil exploration.,1360,-5.72,4.4,113.69,119.62,1,1,9603,-387.06,636.53,46.29,,,,,0
+547,1836,4294,4326,,Oil exploration.,2770,-2.35,4.4,113.7,119.62,1,1,9603,-403.4,681.12,46.56,,,,,0
+548,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-28.89,-10.6,41.14,55.34,1,0,9603,-189,-242,-91,,,,,1
+549,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.35,109.55,119.26,1,0,9603,-679,669,-48,,,,,0
+550,1592,4298,4326,"Originally used by BSP offshore only, use extended to onshore in 2010.",Oil exploration and production.,1055,4,6.37,112.5,115.36,1,0,9603,-678,670,-48,,,,,0
+551,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,5.05,114.1,115.36,1,0,9603,-726.282,703.611,-48.999,,,,,0
+552,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.5,12,109.5,119,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,1
+553,5248,4298,4326,,Oil exploration.,1055,4,6.37,112.5,115.36,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+554,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,6.37,112.5,115.36,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+555,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.33,55.4,-10.6,-5.33,1,1,9603,506,-122,611,,,,,0
+556,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.33,55.4,-10.6,-5.33,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+557,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.33,55.4,-10.6,-5.33,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+558,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.33,55.4,-10.6,-5.33,1,0,9603,506,-122,611,,,,,0
+559,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,24.25,45.49,123.68,145.81,1,0,9603,-148,507,685,,,,,0
+560,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3263,30.15,45.92,128.5,146.09,1,0,9603,-148,507,685,,,,,0
+561,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.18,38.67,125.8,129.72,1,0,9603,-146,507,687,,,,,0
+562,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,26,27.5,127.5,128.5,1,0,9603,-158,507,676,,,,,0
+563,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.18,38.67,125.8,129.72,1,0,9603,-147,506,687,,,,,0
+564,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.",1129,19.01,45.92,122.49,160.09,1,0,9603,-146.414,507.337,680.507,,,,,1
+565,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
+566,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
+567,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.35,-22.1,166.3,166.5,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
+568,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.35,-22.1,166.3,166.5,1,0,9603,-10.18,-350.43,291.37,,,,,1
+569,1294,4304,4326,Accuracy estimate not available.,For military purposes.,1365,32,37.09,-2.92,9.09,1,0,9603,-73,-247,227,,,,,1
+570,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3873,27.6,29.5,-18.3,-13.3,1,0,9603,-307,-92,127,,,,,1
+571,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,3213,18.98,37,-8.67,11.99,1,0,9603,-186,-93,310,,,,,1
+572,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.09,-2.92,9.09,1,0,9603,-123,-206,219,,,,,0
+573,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1.5,3.25,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
+574,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.25,9,9.7,1,0,9603,-95.7,10.2,158.9,,,,,0
+575,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.3,31.5,6.8,7.2,1,0,9603,-165.914,-70.607,305.009,,,,,0
+576,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.52,1,0,9603,-169.559,-72.34,303.102,,,,,0
+577,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
+578,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
+579,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-37.43,-37.05,-12.73,-12.21,1,0,9603,-632,438,-609,,,,,1
+580,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
+581,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.6,47.9,13.5,16.2,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
+582,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,41.85,46.88,13.38,23.01,1,1,9603,682,-203,480,,,,,0
+583,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
+584,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
+585,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,42.3,46.57,13.02,19.5,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+586,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.44,46.91,13.37,16.68,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+587,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.82,43.55,18.44,20.39,1,1,9603,695.5,-216.6,491.1,,,,,0
+588,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.44,46.91,13.37,16.68,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+589,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.54,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
+590,1610,4313,4326,,For applications to an accuracy of 5 metres.,1347,49.51,51.5,2.54,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
+591,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.53,51.83,2.12,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,0
+592,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.54,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,1
+593,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.04,5.87,13.83,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,0
+594,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.04,5.87,13.83,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,1
+595,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.17,54.72,9.87,15.03,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
+596,1517,4315,4326,,"?",3257,7.16,12.69,-15.12,-7.65,1,0,9603,-23,259,-9,,,,,1
+597,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.62,48.26,20.26,31.5,1,1,9603,103.25,-100.4,-307.19,,,,,0
+598,1995,4316,4326,,Oil exploration,3295,43.62,48.26,20.26,29.67,1,0,9603,103.25,-100.4,-307.19,,,,,1
+599,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.62,48.26,20.26,31.5,1,1,9603,28,-121,-77,,,,,0
+600,1996,4317,4326,,Oil exploration,1197,43.62,48.26,20.26,31.5,1,1,9603,44.107,-116.147,-54.648,,,,,0
+601,1060,4318,4326,,1 metre accuracy.,3267,28.56,30.1,46.57,48.45,1,0,9603,-3.2,-5.7,2.8,,,,,1
+602,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.25,29.45,47.67,48.15,1,0,9603,-20.8,11.3,2.4,,,,,1
+603,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.25,29.45,47.67,48.15,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
+604,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
+605,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
+606,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.6,-17.26,177.02,178.87,1,1,9603,51,391,-36,,,,,0
+607,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
+608,5521,4646,4326,,For military purposes. Accuracy unknown.,2807,-11.9,-11.4,43.2,43.5,1,0,9603,-963,510,-359,,,,,1
+609,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.64,19.34,162.03,168,1,0,9603,102,52,-38,,,,,1
+610,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.87,69.23,-28.64,-10.32,1,0,9603,0,0,0,,,,,1
+611,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.78,48.6,16.12,22.91,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
+612,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-23.46,-17.26,157.09,173.89,1,1,9603,0,0,0,,,,,0
+613,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.26,19.34,166.58,166.66,1,0,9603,276,-57,149,,,,,1
+614,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,21.43,26.36,118.07,122.49,1,0,9603,0,0,0,,,,,1
+615,5376,5365,4326,,Accuracy 1m.,1074,2.15,11.77,-90.44,-81.43,1,0,9603,0,0,0,,,,,1
+616,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.49,-7.21,72.34,72.5,1,0,9603,208,-435,-229,,,,,1
+617,5377,5371,4326,,Accuracy 1m.,1186,5,12.5,-84.32,-77.05,1,0,9603,0,0,0,,,,,1
+618,5378,5373,4326,,Accuracy 1m.,1189,-21.05,-0.04,-84.67,-68.67,1,0,9603,0,0,0,,,,,1
+619,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-64.1,-62.86,-61,-60.18,1,0,9603,260,12,-147,,,,,1
+620,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
+621,5384,5381,4326,,Accuracy 1m.,1247,-37.77,-30.1,-58.49,-50.01,1,0,9603,0,0,0,,,,,1
+622,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,31.6,39.16,122.52,132.1,1,0,9603,0,0,0,,,,,1
+623,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.56,51.09,12.11,18.98,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,1
+624,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.52,-16.33,-152.33,-152.16,1,0,9603,217.037,86.959,23.956,,,,,1
+625,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
+626,5395,5393,4326,,Accuracy 1m.,1087,9.97,14.43,-91.42,-87.65,1,0,9603,0,0,0,,,,,1
+627,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.16,22.62,113.89,114.57,1,0,9603,-156,-271,-189,,,,,1
+628,5261,5252,4326,,"Approximation at the +/- 1m level as both TUREF and WGS 84 are realisations of ITRS.",1237,34.47,43.93,25.59,44.85,1,0,9603,0,0,0,,,,,1
+629,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-14,-13,-177,-176,1,1,9603,252,-132,-125,,,,,0
+630,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-14,-13,-177,-176,1,0,9603,253,-132,-127,,,,,1
+631,15801,4714,4326,Derived at 3 satellite stations.,"Military and topographic mapping; Accuracy +/- 20 m in each axis",3193,-19.7,-17.4,168.1,169.64,1,0,9603,-127,-769,472,,,,,1
+632,15802,4715,4326,No accuracy estimate available.,Military and scientific mapping.,3205,-78,-77,165.5,167,1,0,9603,-104,-129,239,,,,,1
+633,1994,4657,4326,,Low accuracy applications.,3262,63.25,66.6,-24.6,-13.4,1,0,9603,-28,199,5,,,,,1
+634,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
+635,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.41,38.82,49.4,1,0,9603,70.995,-335.916,262.898,,,,,1
+636,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.06,31,46,49.4,1,0,9603,84.1,-320.1,218.7,,,,,0
+637,1951,4658,4326,Derived at 6 stations.,"Accuracy 3m, 3m and 5m in X, Y and Z axes.",3262,63.25,66.6,-24.6,-13.4,1,0,9603,-73,46,-86,,,,,1
+638,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.41,38.82,49.4,1,0,9603,0,0,0,,,,,1
+639,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.87,69.23,-28.64,-10.32,1,0,9603,0,0,0,,,,,1
+640,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.8,71.2,-9.15,-7.9,1,0,9606,982.6087,552.753,-540.873,6.68162662527694,-31.6114924086422,-19.8481610048168,16.805,1
+641,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.64,58.12,20.98,28.23,1,0,9603,0,0,0,,,,,1
+642,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.6,16.5,8,15.5,1,0,9603,-106,-87,188,,,,,1
+643,15803,4716,4326,Derived at 4 satellite stations.,"Military and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.64,-2.72,-174.2,-171.3,1,0,9603,298,-304,-375,,,,,1
+644,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.44,46.91,13.37,16.68,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+645,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.44,46.91,13.37,16.68,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+646,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,41.85,46.88,13.38,23.01,1,0,9603,682,-203,480,,,,,1
+647,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.39,46.57,13.47,19.5,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+648,3965,3906,4326,,Oil industry,3536,41.82,43.55,18.44,20.39,1,0,9603,695.5,-216.6,491.1,,,,,0
+649,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
+650,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.5,-20,163.9,167.1,1,0,9603,-13,-348,292,,,,,0
+651,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.5,-20,163.9,167.1,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
+652,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.5,-20,163.9,167.1,1,0,9603,-11.64,-348.6,291.98,,,,,1
+653,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.05,-16,178.25,-179.5,1,0,9603,51,391,-36,,,,,1
+654,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.62,33.15,-17.27,-16.25,1,0,9603,-502.862,-247.438,312.724,,,,,1
+655,1967,4663,4326,,For medium resolution applications.,2870,32.62,33.15,-17.27,-16.25,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
+656,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-23.46,-17.26,157.09,173.89,1,0,9603,0,0,0,,,,,1
+657,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.65,37.95,-25.9,-25.1,1,0,9603,-204.633,140.216,55.199,,,,,0
+658,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.65,37.95,-25.9,-25.1,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
+659,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.9,37.95,-25.9,-24.95,1,0,9603,-204.619,140.176,55.226,,,,,1
+660,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.9,37.95,-25.9,-24.95,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
+661,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.75,-20.35,166.35,166.7,1,0,9603,-56.263,16.136,-22.856,,,,,1
+662,1972,4665,4326,,For low resolution applications.,2872,38.6,38.85,-27.4,-27.05,1,0,9603,-106.301,166.27,-37.916,,,,,0
+663,1973,4665,4326,,For medium resolution applications.,2872,38.6,38.85,-27.4,-27.05,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
+664,1974,4665,4326,,For low resolution applications.,2873,38.5,38.65,-28.8,-28.58,1,0,9603,-106.248,166.244,-37.845,,,,,0
+665,1975,4665,4326,,For medium resolution applications.,2873,38.5,38.65,-28.8,-28.58,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
+666,1976,4665,4326,,For low resolution applications.,2874,38.37,38.57,-28.55,-28,1,0,9603,-106.044,166.655,-37.876,,,,,0
+667,1977,4665,4326,,For medium resolution applications.,2874,38.37,38.57,-28.55,-28,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
+668,1978,4665,4326,,For low resolution applications.,2875,38.5,38.75,-28.35,-27.75,1,0,9603,-106.253,166.239,-37.854,,,,,0
+669,1979,4665,4326,,For medium resolution applications.,2875,38.5,38.75,-28.35,-27.75,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
+670,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.37,39.15,-28.8,-27.05,1,0,9603,-106.226,166.366,-37.893,,,,,1
+671,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.37,39.15,-28.8,-27.05,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
+672,1986,4666,4326,May be taken as a transformation from Lisbon 1890 to ETRS89 - see tfm code 5039.,For low resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
+673,1990,4666,4326,,For medium resolution applications.,1294,37.01,42.15,-9.5,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
+674,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
+675,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.25,88.74,92.13,1,0,9603,0,0,0,,,,,1
+676,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,2.25,21.43,116.09,140.08,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
+677,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.05,30.1,46.5,48,1,0,9603,0,0,0,,,,,1
+678,15897,4752,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.6,-17.26,177.02,178.87,1,0,9603,51,391,-36,,,,,1
+679,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,1297,36,71.05,-8.95,31.6,1,0,9603,-86,-98,-119,,,,,1
+680,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,4,12.76,136.66,168.43,1,0,9603,647,1777,-1124,,,,,1
+681,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.51,36,9.31,25.98,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
+682,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
+683,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
+684,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.01,7.92,91.66,141.1,1,0,9603,0,0,0,,,,,1
+685,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
+686,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
+687,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.37,-11.32,44.13,45.77,1,0,9603,0,0,0,,,,,1
+688,5194,4756,4326,Used by Total in Mekong delta.,Academic research not officially adopted.,3770,9.35,11.05,104.25,107.1,1,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188,1
+689,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.85,-19.54,163.55,163.7,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
+690,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,-12.6,44.97,45.32,1,0,9603,-381.788,-57.501,-256.673,,,,,1
+691,5374,5354,4326,,Accuracy 1m.,1049,-22.9,-9.68,-69.66,-57.52,1,0,9603,0,0,0,,,,,1
+692,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.1,-3.95,12.21,16.5,1,0,9603,-79.9,-158,-168.9,,,,,1
+693,4832,4483,4326,,Accuracy 1m.,1160,12.1,32.72,-122.18,-84.64,1,0,9603,0,0,0,,,,,1
+694,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.2,-20.7,167,167.5,1,0,9603,336,223,-231,,,,,0
+695,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.2,-20.7,167,167.5,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
+696,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.2,-20.7,167,167.5,1,0,9603,335.47,222.58,-230.94,,,,,1
+697,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
+698,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
+699,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
+700,1540,4163,4326,,Accuracy better than 1 metre.,1257,11.61,19.01,41.44,55.03,1,0,9603,0,0,0,,,,,1
+701,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,28,41.5,-33,-14,1,0,9603,0,0,0,,,,,1
+702,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
+703,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.31,-20.41,-4.81,1,0,9603,0,0,0,,,,,1
+704,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
+705,5375,5360,4326,,Accuracy 1m.,1066,-59.86,-17.51,-113.2,-65.73,1,0,9603,0,0,0,,,,,1
+706,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.16,-25,-130.18,-129.99,1,0,9603,0,0,0,,,,,1
+707,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,3266,33.18,38.67,125.8,129.72,1,0,9603,0,0,0,,,,,1
+708,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,27.6,29.5,-18.3,-13.3,1,0,9603,0,0,0,,,,,1
+709,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-60,145,-140,1,0,9603,0,0,0,,,,,1
+710,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,-12.01,2.6,140.93,164.1,1,0,9603,0,0,0,,,,,1
+711,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.36,21.25,-17.5,-16,1,0,9603,-80.01,253.26,291.19,,,,,1
+712,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.44,46.91,13.37,16.68,1,0,9603,0,0,0,,,,,1
+713,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.4,-14.61,166.5,168.31,1,0,9603,170,42,84,,,,,1
+714,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.8,18.3,-16.67,-15.75,1,0,9603,124.5,-63.5,-281,,,,,1
+715,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.48,48.52,26.61,30.16,1,0,9603,0,0,0,,,,,1
+716,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,-25.1,-9.79,172.87,-176.16,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
+717,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,-18.5,-16,177,-179.5,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
+718,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,15.09,26.65,88.1,92.72,1,1,9603,283.8,735.9,261.1,,,,,0
+719,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,15.09,26.65,88.1,92.72,1,0,9603,283.7,735.9,261.1,,,,,1
+720,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.75,-20.35,166.35,166.7,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
+721,5470,5451,4326,,Topographic mapping.,3876,7.98,17.82,-92.29,-82.53,1,0,9603,213.11,9.37,-74.95,,,,,1
+722,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
+723,5474,5451,4326,,Topographic mapping.,3876,7.98,17.82,-92.29,-82.53,1,0,9603,205.435,-29.099,292.202,,,,,0
+724,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3274,3.9,4.5,73.33,73.7,1,0,9603,-133,-321,50,,,,,1
+725,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
+726,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.3,28.5,30.78,1,0,9603,0,0,0,,,,,1
+727,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.3,29.96,32.3,34.25,1,0,9603,-146.21,112.63,4.05,,,,,1
+728,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,37.75,38.25,108,108.5,1,0,9603,12.646,-155.176,-80.863,,,,,0
+729,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.4,37,119.2,124.2,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
+730,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,19.5,22,111,117,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
+731,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,42,77.5,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
+732,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,19,21.4,108,109.6,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
+733,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,37.75,38.25,108,108.5,1,0,9603,11.911,-154.833,-80.079,,,,,0
+734,15875,4721,4326,Derived at 20 stations.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-18.5,-16,177,-179.5,1,0,9603,265.025,384.929,-194.046,,,,,1
+735,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,-29,-7,-155,-132,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
+736,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-29,-7,-155,-132,1,0,9603,0,0,0,,,,,0
+737,1921,4636,4326,,"Accuracy +/- 10 metres.",2817,-66.9,-66.5,139.5,140.5,1,0,9603,365,194,166,,,,,1
+738,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.55,-10.33,-138.7,-138.55,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
+739,5236,5233,4326,Derived at 58 stations.,Accuracy 14m.,3310,5.85,9.92,79.6,81.95,1,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338,1
+740,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.82,46.23,18.83,23.05,1,0,9603,0,0,0,,,,,1
+741,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.91,-17.45,-149.69,-149.07,1,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741,1
+742,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-68,-66,135,142,1,0,9603,325,154,172,,,,,1
+743,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-7.99,-7.88,-14.42,-14.29,1,0,9603,-205,107,53,,,,,1
+744,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.61,-17.45,-149.96,-149.69,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
+745,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3187,-55.22,-53.8,-38.46,-34.63,1,0,9603,-794,119,-298,,,,,1
+746,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,-11.9,-10.8,26.66,27.7,1,0,9603,-103.746,-9.614,-255.95,,,,,1
+747,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.7,27.8,52.1,52.25,1,0,9603,0,-0.15,0.68,,,,,1
+748,1441,4601,4326,,"?",1273,16.94,17.21,-61.94,-61.62,1,0,9603,-255,-15,71,,,,,1
+749,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
+750,1442,4602,4326,,"?",3239,15.15,15.68,-61.54,-61.2,1,0,9603,725,685,536,,,,,1
+751,1443,4603,4326,,"?",3118,11.95,12.29,-61.83,-61.55,1,0,9603,72,213.7,93,,,,,1
+752,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
+753,1445,4605,4326,,"?",3297,17.07,17.46,-62.91,-62.5,1,0,9603,9,183,236,,,,,1
+754,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
+755,1446,4606,4326,,"?",3298,13.66,14.16,-61.13,-60.83,1,0,9603,-149,128,296,,,,,1
+756,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 c9a5939..b3c9c9b 100644
--- a/data/ellipsoid.csv
+++ b/data/ellipsoid.csv
@@ -6,7 +6,7 @@ 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","""Ellipsoidisch Parameter der Erdfigur (1800-1950)"" by Georg Strasser.",OGP,2005/08/14,1999.700 2005.370,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 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
 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
@@ -32,7 +32,7 @@ ellipsoid_code,ellipsoid_name,semi_major_axis,uom_code,inv_flattening,semi_minor
 7033,OSU91A,6378136.3,9001,298.257223563,,1,Used for OSU91 gravity potential (geoidal) model.,,OGP,1995/06/02,1998.320,0
 7034,Clarke 1880,20926202,9005,,20854895,1,Clarke gave a and b and also 1/f=293.465 (to 3 decimal places exactly). In the 19th century b was normally given as the second defining parameter.,"""Ellipsoidisch Parameter der Erdfigur (1800-1950)"" by Georg Strasser.",OGP,2008/06/26,2008.057,0
 7035,Sphere,6371000,9001,,6371000,0,Authalic sphere.  1/f is infinite. Superseded by GRS 1980 authalic sphere (code 7047).,,OGP,1995/06/02,,1
-7036,GRS 1967,6378160,9001,298.247167427,,1,"Adopted by IUGG 1967 Lucerne.  Inverse flattening given is derived from geocentric gravitational constant (GM)= 398603e9 m*m*m/s/s; dynamic form factor (J2) = 0.0010827 and Earth's angular velocity w = 7.2921151467e-5 rad/s. See also GRS 1967 (SAD69).","""Geodetic Reference System 1967""; International Association of Geodesy special publication number 3; August 1971.",OGP,2002/09/19,1996.090 1997.252 1998.320 2002.500,0
+7036,GRS 1967,6378160,9001,298.247167427,,1,"Adopted by IUGG 1967 Lucerne.  1/f given is derived from geocentric gravitational constant (GM)= 398603e9 m*m*m/s/s; dynamic form factor (J2) = 0.0010827 and Earth's angular velocity w = 7.2921151467e-5 rad/s. See also GRS 1967 Modified (code 7050).","""Geodetic Reference System 1967""; International Association of Geodesy special publication number 3; August 1971.",OGP,2011/02/25,1996.090 1997.252 1998.320 2002.500 2011.016,0
 7041,Average Terrestrial System 1977,6378135,9001,298.257,,1,,New Brunswick Geographic Information Corporation land and water information standards manual,OGP,1997/07/22,1998.321,0
 7042,Everest (1830 Definition),20922931.8,9080,,20853374.58,1,Everest gave a and b to 2 decimal places and also 1/f=300.8017 (to 4 decimal places exactly). In the 19th century b was normally given as the second defining parameter.,"""Ellipsoidisch Parameter der Erdfigur (1800-1950)"" by Georg Strasser",OGP,2008/06/26,1997.231 2008.057,0
 7043,WGS 72,6378135,9001,298.26,,1,,,OGP,1999/04/22,1999.030,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/esri_StatePlane_extra.wkt b/data/esri_StatePlane_extra.wkt
new file mode 100644
index 0000000..edbfa83
--- /dev/null
+++ b/data/esri_StatePlane_extra.wkt
@@ -0,0 +1,631 @@
+1010,PROJCS["NAD_1983_HARN_StatePlane_Alabama_East_FIPS_0101",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-85.83333333333333],PARAMETER["Scale_Factor",0.99996],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Meter",1]]
+1011,PROJCS["NAD_1983_StatePlane_Alabama_East_FIPS_0101",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-85.83333333333333],PARAMETER["Scale_Factor",0.99996],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Meter",1]]
+1012,PROJCS["NAD_1983_StatePlane_Alabama_East_FIPS_0101_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-85.83333333333333],PARAMETER["Scale_Factor",0.99996],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Foot_US",0.304800609601219241]]
+1014,PROJCS["NAD_1927_StatePlane_Alabama_East_FIPS_0101",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-85.83333333333333],PARAMETER["Scale_Factor",0.99996],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Foot_US",0.304800609601219241]]
+1020,PROJCS["NAD_1983_HARN_StatePlane_Alabama_West_FIPS_0102",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",30],UNIT["Meter",1]]
+1021,PROJCS["NAD_1983_StatePlane_Alabama_West_FIPS_0102",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",30],UNIT["Meter",1]]
+1022,PROJCS["NAD_1983_StatePlane_Alabama_West_FIPS_0102_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",30],UNIT["Foot_US",0.304800609601219241]]
+1024,PROJCS["NAD_1927_StatePlane_Alabama_West_FIPS_0102",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",30],UNIT["Foot_US",0.304800609601219241]]
+2010,PROJCS["NAD_1983_HARN_StatePlane_Arizona_East_FIPS_0201",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",213360],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-110.1666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+2011,PROJCS["NAD_1983_StatePlane_Arizona_East_FIPS_0201",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",213360],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-110.1666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+2012,PROJCS["NAD_1983_StatePlane_Arizona_East_FIPS_0201_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",699998.5999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-110.1666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+2013,PROJCS["NAD_1983_HARN_StatePlane_Arizona_East_FIPS_0201_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-110.1666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2014,PROJCS["NAD_1927_StatePlane_Arizona_East_FIPS_0201",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-110.1666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+2015,PROJCS["NAD_1983_HARN_StatePlane_Arizona_East_FIPS_0201_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-110.1666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2016,PROJCS["NAD_1983_StatePlane_Arizona_East_FIPS_0201_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-110.1666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2020,PROJCS["NAD_1983_HARN_StatePlane_Arizona_Central_FIPS_0202",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",213360],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-111.9166666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+2021,PROJCS["NAD_1983_StatePlane_Arizona_Central_FIPS_0202",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",213360],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-111.9166666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+2022,PROJCS["NAD_1983_StatePlane_Arizona_Central_FIPS_0202_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",699998.5999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-111.9166666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+2023,PROJCS["NAD_1983_HARN_StatePlane_Arizona_Central_FIPS_0202_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-111.9166666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2024,PROJCS["NAD_1927_StatePlane_Arizona_Central_FIPS_0202",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-111.9166666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+2025,PROJCS["NAD_1983_HARN_StatePlane_Arizona_Central_FIPS_0202_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-111.9166666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2026,PROJCS["NAD_1983_StatePlane_Arizona_Central_FIPS_0202_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-111.9166666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2030,PROJCS["NAD_1983_HARN_StatePlane_Arizona_West_FIPS_0203",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",213360],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-113.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+2031,PROJCS["NAD_1983_StatePlane_Arizona_West_FIPS_0203",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",213360],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-113.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+2032,PROJCS["NAD_1983_StatePlane_Arizona_West_FIPS_0203_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",699998.5999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-113.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+2033,PROJCS["NAD_1983_HARN_StatePlane_Arizona_West_FIPS_0203_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-113.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2034,PROJCS["NAD_1927_StatePlane_Arizona_West_FIPS_0203",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-113.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+2035,PROJCS["NAD_1983_HARN_StatePlane_Arizona_West_FIPS_0203_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-113.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+2036,PROJCS["NAD_1983_StatePlane_Arizona_West_FIPS_0203_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-113.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot",0.3048]]
+3010,PROJCS["NAD_1983_HARN_StatePlane_Arkansas_North_FIPS_0301",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-92.0],PARAMETER["Standard_Parallel_1",34.93333333333333],PARAMETER["Standard_Parallel_2",36.23333333333333],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Meter",1.0]]
+3011,PROJCS["NAD_1983_StatePlane_Arkansas_North_FIPS_0301",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92],PARAMETER["Standard_Parallel_1",34.93333333333333],PARAMETER["Standard_Parallel_2",36.23333333333333],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Meter",1]]
+3012,PROJCS["NAD_1983_StatePlane_Arkansas_North_FIPS_0301_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92],PARAMETER["Standard_Parallel_1",34.93333333333333],PARAMETER["Standard_Parallel_2",36.23333333333333],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+3013,PROJCS["NAD_1983_HARN_StatePlane_Arkansas_North_FIPS_0301_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-92.0],PARAMETER["Standard_Parallel_1",34.93333333333333],PARAMETER["Standard_Parallel_2",36.23333333333333],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+3014,PROJCS["NAD_1927_StatePlane_Arkansas_North_FIPS_0301",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92],PARAMETER["Standard_Parallel_1",34.93333333333333],PARAMETER["Standard_Parallel_2",36.23333333333333],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+3020,PROJCS["NAD_1983_HARN_StatePlane_Arkansas_South_FIPS_0302",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000.0],PARAMETER["False_Northing",400000.0],PARAMETER["Central_Meridian",-92.0],PARAMETER["Standard_Parallel_1",33.3],PARAMETER["Standard_Parallel_2",34.76666666666667],PARAMETER["Latitude_Of_Origin",32.66666666666666],UNIT["Meter",1.0]]
+3021,PROJCS["NAD_1983_StatePlane_Arkansas_South_FIPS_0302",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",400000],PARAMETER["Central_Meridian",-92],PARAMETER["Standard_Parallel_1",33.3],PARAMETER["Standard_Parallel_2",34.76666666666667],PARAMETER["Latitude_Of_Origin",32.66666666666666],UNIT["Meter",1]]
+3022,PROJCS["NAD_1983_StatePlane_Arkansas_South_FIPS_0302_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",1312333.333333333],PARAMETER["Central_Meridian",-92],PARAMETER["Standard_Parallel_1",33.3],PARAMETER["Standard_Parallel_2",34.76666666666667],PARAMETER["Latitude_Of_Origin",32.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+3023,PROJCS["NAD_1983_HARN_StatePlane_Arkansas_South_FIPS_0302_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",1312333.333333333],PARAMETER["Central_Meridian",-92.0],PARAMETER["Standard_Parallel_1",33.3],PARAMETER["Standard_Parallel_2",34.76666666666667],PARAMETER["Latitude_Of_Origin",32.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+3024,PROJCS["NAD_1927_StatePlane_Arkansas_South_FIPS_0302",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92],PARAMETER["Standard_Parallel_1",33.3],PARAMETER["Standard_Parallel_2",34.76666666666667],PARAMETER["Latitude_Of_Origin",32.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+4010,PROJCS["NAD_1983_HARN_StatePlane_California_I_FIPS_0401",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",40],PARAMETER["Standard_Parallel_2",41.66666666666666],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Meter",1]]
+4011,PROJCS["NAD_1983_StatePlane_California_I_FIPS_0401",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",40],PARAMETER["Standard_Parallel_2",41.66666666666666],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Meter",1]]
+4012,PROJCS["NAD_1983_StatePlane_California_I_FIPS_0401_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",40],PARAMETER["Standard_Parallel_2",41.66666666666666],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+4013,PROJCS["NAD_1983_HARN_StatePlane_California_I_FIPS_0401_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-122.0],PARAMETER["Standard_Parallel_1",40.0],PARAMETER["Standard_Parallel_2",41.66666666666666],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+4014,PROJCS["NAD_1927_StatePlane_California_I_FIPS_0401",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",40],PARAMETER["Standard_Parallel_2",41.66666666666666],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+4020,PROJCS["NAD_1983_HARN_StatePlane_California_II_FIPS_0402",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Meter",1]]
+4021,PROJCS["NAD_1983_StatePlane_California_II_FIPS_0402",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Meter",1]]
+4022,PROJCS["NAD_1983_StatePlane_California_II_FIPS_0402_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+4023,PROJCS["NAD_1983_HARN_StatePlane_California_II_FIPS_0402_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-122.0],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+4024,PROJCS["NAD_1927_StatePlane_California_II_FIPS_0402",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+4030,PROJCS["NAD_1983_HARN_StatePlane_California_III_FIPS_0403",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",37.06666666666667],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.5],UNIT["Meter",1]]
+4031,PROJCS["NAD_1983_StatePlane_California_III_FIPS_0403",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",37.06666666666667],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.5],UNIT["Meter",1]]
+4032,PROJCS["NAD_1983_StatePlane_California_III_FIPS_0403_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",37.06666666666667],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.5],UNIT["Foot_US",0.304800609601219241]]
+4033,PROJCS["NAD_1983_HARN_StatePlane_California_III_FIPS_0403_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",37.06666666666667],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.5],UNIT["Foot_US",0.3048006096012192]]
+4034,PROJCS["NAD_1927_StatePlane_California_III_FIPS_0403",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",37.06666666666667],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.5],UNIT["Foot_US",0.304800609601219241]]
+4040,PROJCS["NAD_1983_HARN_StatePlane_California_IV_FIPS_0404",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-119],PARAMETER["Standard_Parallel_1",36],PARAMETER["Standard_Parallel_2",37.25],PARAMETER["Latitude_Of_Origin",35.33333333333334],UNIT["Meter",1]]
+4041,PROJCS["NAD_1983_StatePlane_California_IV_FIPS_0404",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-119],PARAMETER["Standard_Parallel_1",36],PARAMETER["Standard_Parallel_2",37.25],PARAMETER["Latitude_Of_Origin",35.33333333333334],UNIT["Meter",1]]
+4042,PROJCS["NAD_1983_StatePlane_California_IV_FIPS_0404_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-119],PARAMETER["Standard_Parallel_1",36],PARAMETER["Standard_Parallel_2",37.25],PARAMETER["Latitude_Of_Origin",35.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+4043,PROJCS["NAD_1983_HARN_StatePlane_California_IV_FIPS_0404_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-119.0],PARAMETER["Standard_Parallel_1",36.0],PARAMETER["Standard_Parallel_2",37.25],PARAMETER["Latitude_Of_Origin",35.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+4044,PROJCS["NAD_1927_StatePlane_California_IV_FIPS_0404",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-119],PARAMETER["Standard_Parallel_1",36],PARAMETER["Standard_Parallel_2",37.25],PARAMETER["Latitude_Of_Origin",35.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+4050,PROJCS["NAD_1983_HARN_StatePlane_California_V_FIPS_0405",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-118],PARAMETER["Standard_Parallel_1",34.03333333333333],PARAMETER["Standard_Parallel_2",35.46666666666667],PARAMETER["Latitude_Of_Origin",33.5],UNIT["Meter",1]]
+4051,PROJCS["NAD_1983_StatePlane_California_V_FIPS_0405",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-118],PARAMETER["Standard_Parallel_1",34.03333333333333],PARAMETER["Standard_Parallel_2",35.46666666666667],PARAMETER["Latitude_Of_Origin",33.5],UNIT["Meter",1]]
+4052,PROJCS["NAD_1983_StatePlane_California_V_FIPS_0405_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-118],PARAMETER["Standard_Parallel_1",34.03333333333333],PARAMETER["Standard_Parallel_2",35.46666666666667],PARAMETER["Latitude_Of_Origin",33.5],UNIT["Foot_US",0.304800609601219241]]
+4053,PROJCS["NAD_1983_HARN_StatePlane_California_V_FIPS_0405_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-118.0],PARAMETER["Standard_Parallel_1",34.03333333333333],PARAMETER["Standard_Parallel_2",35.46666666666667],PARAMETER["Latitude_Of_Origin",33.5],UNIT["Foot_US",0.3048006096012192]]
+4054,PROJCS["NAD_1927_StatePlane_California_V_FIPS_0405",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-118],PARAMETER["Standard_Parallel_1",34.03333333333333],PARAMETER["Standard_Parallel_2",35.46666666666667],PARAMETER["Latitude_Of_Origin",33.5],UNIT["Foot_US",0.304800609601219241]]
+4060,PROJCS["NAD_1983_HARN_StatePlane_California_VI_FIPS_0406",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-116.25],PARAMETER["Standard_Parallel_1",32.78333333333333],PARAMETER["Standard_Parallel_2",33.88333333333333],PARAMETER["Latitude_Of_Origin",32.16666666666666],UNIT["Meter",1]]
+4061,PROJCS["NAD_1983_StatePlane_California_VI_FIPS_0406",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-116.25],PARAMETER["Standard_Parallel_1",32.78333333333333],PARAMETER["Standard_Parallel_2",33.88333333333333],PARAMETER["Latitude_Of_Origin",32.16666666666666],UNIT["Meter",1]]
+4062,PROJCS["NAD_1983_StatePlane_California_VI_FIPS_0406_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-116.25],PARAMETER["Standard_Parallel_1",32.78333333333333],PARAMETER["Standard_Parallel_2",33.88333333333333],PARAMETER["Latitude_Of_Origin",32.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+4063,PROJCS["NAD_1983_HARN_StatePlane_California_VI_FIPS_0406_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-116.25],PARAMETER["Standard_Parallel_1",32.78333333333333],PARAMETER["Standard_Parallel_2",33.88333333333333],PARAMETER["Latitude_Of_Origin",32.16666666666666],UNIT["Foot_US",0.3048006096012192]]
+4064,PROJCS["NAD_1927_StatePlane_California_VI_FIPS_0406",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-116.25],PARAMETER["Standard_Parallel_1",32.78333333333333],PARAMETER["Standard_Parallel_2",33.88333333333333],PARAMETER["Latitude_Of_Origin",32.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+4074,PROJCS["NAD_1927_StatePlane_California_VII_FIPS_0407",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4186692.58],PARAMETER["False_Northing",4160926.74],PARAMETER["Central_Meridian",-118.3333333333333],PARAMETER["Standard_Parallel_1",33.86666666666667],PARAMETER["Standard_Parallel_2",34.41666666666666],PARAMETER["Latitude_Of_Origin",34.13333333333333],UNIT["Foot_US",0.304800609601219241]]
+5010,PROJCS["NAD_1983_HARN_StatePlane_Colorado_North_FIPS_0501",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",914401.8289],PARAMETER["False_Northing",304800.6096],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",39.71666666666667],PARAMETER["Standard_Parallel_2",40.78333333333333],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Meter",1]]
+5011,PROJCS["NAD_1983_StatePlane_Colorado_North_FIPS_0501",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",914401.8289],PARAMETER["False_Northing",304800.6096],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",39.71666666666667],PARAMETER["Standard_Parallel_2",40.78333333333333],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Meter",1]]
+5012,PROJCS["NAD_1983_StatePlane_Colorado_North_FIPS_0501_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3000000.000316083],PARAMETER["False_Northing",999999.999996],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",39.71666666666667],PARAMETER["Standard_Parallel_2",40.78333333333333],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+5013,PROJCS["NAD_1983_HARN_StatePlane_Colorado_North_FIPS_0501_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3000000.000316083],PARAMETER["False_Northing",999999.999996],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",39.71666666666667],PARAMETER["Standard_Parallel_2",40.78333333333333],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+5014,PROJCS["NAD_1927_StatePlane_Colorado_North_FIPS_0501",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",39.71666666666667],PARAMETER["Standard_Parallel_2",40.78333333333333],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+5020,PROJCS["NAD_1983_HARN_StatePlane_Colorado_Central_FIPS_0502",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",914401.8289],PARAMETER["False_Northing",304800.6096],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",38.45],PARAMETER["Standard_Parallel_2",39.75],PARAMETER["Latitude_Of_Origin",37.83333333333334],UNIT["Meter",1]]
+5021,PROJCS["NAD_1983_StatePlane_Colorado_Central_FIPS_0502",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",914401.8289],PARAMETER["False_Northing",304800.6096],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",38.45],PARAMETER["Standard_Parallel_2",39.75],PARAMETER["Latitude_Of_Origin",37.83333333333334],UNIT["Meter",1]]
+5022,PROJCS["NAD_1983_StatePlane_Colorado_Central_FIPS_0502_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3000000.000316083],PARAMETER["False_Northing",999999.999996],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",38.45],PARAMETER["Standard_Parallel_2",39.75],PARAMETER["Latitude_Of_Origin",37.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+5023,PROJCS["NAD_1983_HARN_StatePlane_Colorado_Central_FIPS_0502_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3000000.000316083],PARAMETER["False_Northing",999999.999996],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",38.45],PARAMETER["Standard_Parallel_2",39.75],PARAMETER["Latitude_Of_Origin",37.83333333333334],UNIT["Foot_US",0.3048006096012192]]
+5024,PROJCS["NAD_1927_StatePlane_Colorado_Central_FIPS_0502",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",38.45],PARAMETER["Standard_Parallel_2",39.75],PARAMETER["Latitude_Of_Origin",37.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+5030,PROJCS["NAD_1983_HARN_StatePlane_Colorado_South_FIPS_0503",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",914401.8289],PARAMETER["False_Northing",304800.6096],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",37.23333333333333],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+5031,PROJCS["NAD_1983_StatePlane_Colorado_South_FIPS_0503",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",914401.8289],PARAMETER["False_Northing",304800.6096],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",37.23333333333333],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+5032,PROJCS["NAD_1983_StatePlane_Colorado_South_FIPS_0503_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3000000.000316083],PARAMETER["False_Northing",999999.999996],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",37.23333333333333],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+5033,PROJCS["NAD_1983_HARN_StatePlane_Colorado_South_FIPS_0503_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3000000.000316083],PARAMETER["False_Northing",999999.999996],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",37.23333333333333],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+5034,PROJCS["NAD_1927_StatePlane_Colorado_South_FIPS_0503",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-105.5],PARAMETER["Standard_Parallel_1",37.23333333333333],PARAMETER["Standard_Parallel_2",38.43333333333333],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+6000,PROJCS["NAD_1983_HARN_StatePlane_Connecticut_FIPS_0600",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",304800.6096],PARAMETER["False_Northing",152400.3048],PARAMETER["Central_Meridian",-72.75],PARAMETER["Standard_Parallel_1",41.2],PARAMETER["Standard_Parallel_2",41.86666666666667],PARAMETER["Latitude_Of_Origin",40.83333333333334],UNIT["Meter",1]]
+6001,PROJCS["NAD_1983_StatePlane_Connecticut_FIPS_0600",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",304800.6096],PARAMETER["False_Northing",152400.3048],PARAMETER["Central_Meridian",-72.75],PARAMETER["Standard_Parallel_1",41.2],PARAMETER["Standard_Parallel_2",41.86666666666667],PARAMETER["Latitude_Of_Origin",40.83333333333334],UNIT["Meter",1]]
+6002,PROJCS["NAD_1983_StatePlane_Connecticut_FIPS_0600_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",999999.999996],PARAMETER["False_Northing",499999.999998],PARAMETER["Central_Meridian",-72.75],PARAMETER["Standard_Parallel_1",41.2],PARAMETER["Standard_Parallel_2",41.86666666666667],PARAMETER["Latitude_Of_Origin",40.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+6003,PROJCS["NAD_1983_HARN_StatePlane_Connecticut_FIPS_0600_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",999999.999996],PARAMETER["False_Northing",499999.999998],PARAMETER["Central_Meridian",-72.75],PARAMETER["Standard_Parallel_1",41.2],PARAMETER["Standard_Parallel_2",41.86666666666667],PARAMETER["Latitude_Of_Origin",40.83333333333334],UNIT["Foot_US",0.3048006096012192]]
+6004,PROJCS["NAD_1927_StatePlane_Connecticut_FIPS_0600",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-72.75],PARAMETER["Standard_Parallel_1",41.2],PARAMETER["Standard_Parallel_2",41.86666666666667],PARAMETER["Latitude_Of_Origin",40.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+7000,PROJCS["NAD_1983_HARN_StatePlane_Delaware_FIPS_0700",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-75.41666666666667],PARAMETER["Scale_Factor",0.999995],PARAMETER["Latitude_Of_Origin",38],UNIT["Meter",1]]
+7001,PROJCS["NAD_1983_StatePlane_Delaware_FIPS_0700",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-75.41666666666667],PARAMETER["Scale_Factor",0.999995],PARAMETER["Latitude_Of_Origin",38],UNIT["Meter",1]]
+7002,PROJCS["NAD_1983_StatePlane_Delaware_FIPS_0700_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-75.41666666666667],PARAMETER["Scale_Factor",0.999995],PARAMETER["Latitude_Of_Origin",38],UNIT["Foot_US",0.304800609601219241]]
+7003,PROJCS["NAD_1983_HARN_StatePlane_Delaware_FIPS_0700_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-75.41666666666667],PARAMETER["Scale_Factor",0.999995],PARAMETER["Latitude_Of_Origin",38.0],UNIT["Foot_US",0.3048006096012192]]
+7004,PROJCS["NAD_1927_StatePlane_Delaware_FIPS_0700",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-75.41666666666667],PARAMETER["Scale_Factor",0.999995],PARAMETER["Latitude_Of_Origin",38],UNIT["Foot_US",0.304800609601219241]]
+9010,PROJCS["NAD_1983_HARN_StatePlane_Florida_East_FIPS_0901",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Meter",1]]
+9011,PROJCS["NAD_1983_StatePlane_Florida_East_FIPS_0901",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Meter",1]]
+9012,PROJCS["NAD_1983_StatePlane_Florida_East_FIPS_0901_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Foot_US",0.304800609601219241]]
+9013,PROJCS["NAD_1983_HARN_StatePlane_Florida_East_FIPS_0901_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-81.0],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Foot_US",0.3048006096012192]]
+9014,PROJCS["NAD_1927_StatePlane_Florida_East_FIPS_0901",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Foot_US",0.304800609601219241]]
+9020,PROJCS["NAD_1983_HARN_StatePlane_Florida_West_FIPS_0902",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Meter",1]]
+9021,PROJCS["NAD_1983_StatePlane_Florida_West_FIPS_0902",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Meter",1]]
+9022,PROJCS["NAD_1983_StatePlane_Florida_West_FIPS_0902_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Foot_US",0.304800609601219241]]
+9023,PROJCS["NAD_1983_HARN_StatePlane_Florida_West_FIPS_0902_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-82.0],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Foot_US",0.3048006096012192]]
+9024,PROJCS["NAD_1927_StatePlane_Florida_West_FIPS_0902",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",24.33333333333333],UNIT["Foot_US",0.304800609601219241]]
+9030,PROJCS["NAD_1983_HARN_StatePlane_Florida_North_FIPS_0903",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.5],PARAMETER["Standard_Parallel_1",29.58333333333333],PARAMETER["Standard_Parallel_2",30.75],PARAMETER["Latitude_Of_Origin",29],UNIT["Meter",1]]
+9031,PROJCS["NAD_1983_StatePlane_Florida_North_FIPS_0903",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.5],PARAMETER["Standard_Parallel_1",29.58333333333333],PARAMETER["Standard_Parallel_2",30.75],PARAMETER["Latitude_Of_Origin",29],UNIT["Meter",1]]
+9032,PROJCS["NAD_1983_StatePlane_Florida_North_FIPS_0903_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.5],PARAMETER["Standard_Parallel_1",29.58333333333333],PARAMETER["Standard_Parallel_2",30.75],PARAMETER["Latitude_Of_Origin",29],UNIT["Foot_US",0.304800609601219241]]
+9033,PROJCS["NAD_1983_HARN_StatePlane_Florida_North_FIPS_0903_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.5],PARAMETER["Standard_Parallel_1",29.58333333333333],PARAMETER["Standard_Parallel_2",30.75],PARAMETER["Latitude_Of_Origin",29.0],UNIT["Foot_US",0.3048006096012192]]
+9034,PROJCS["NAD_1927_StatePlane_Florida_North_FIPS_0903",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.5],PARAMETER["Standard_Parallel_1",29.58333333333333],PARAMETER["Standard_Parallel_2",30.75],PARAMETER["Latitude_Of_Origin",29],UNIT["Foot_US",0.304800609601219241]]
+10010,PROJCS["NAD_1983_HARN_StatePlane_Georgia_East_FIPS_1001",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Meter",1]]
+10011,PROJCS["NAD_1983_StatePlane_Georgia_East_FIPS_1001",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Meter",1]]
+10012,PROJCS["NAD_1983_StatePlane_Georgia_East_FIPS_1001_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Foot_US",0.304800609601219241]]
+10013,PROJCS["NAD_1983_HARN_StatePlane_Georgia_East_FIPS_1001_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-82.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30.0],UNIT["Foot_US",0.3048006096012192]]
+10014,PROJCS["NAD_1927_StatePlane_Georgia_East_FIPS_1001",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Foot_US",0.304800609601219241]]
+10020,PROJCS["NAD_1983_HARN_StatePlane_Georgia_West_FIPS_1002",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Meter",1]]
+10021,PROJCS["NAD_1983_StatePlane_Georgia_West_FIPS_1002",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Meter",1]]
+10022,PROJCS["NAD_1983_StatePlane_Georgia_West_FIPS_1002_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Foot_US",0.304800609601219241]]
+10023,PROJCS["NAD_1983_HARN_StatePlane_Georgia_West_FIPS_1002_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30.0],UNIT["Foot_US",0.3048006096012192]]
+10024,PROJCS["NAD_1927_StatePlane_Georgia_West_FIPS_1002",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.16666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",30],UNIT["Foot_US",0.304800609601219241]]
+11010,PROJCS["NAD_1983_HARN_StatePlane_Idaho_East_FIPS_1101",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-112.1666666666667],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+11011,PROJCS["NAD_1983_StatePlane_Idaho_East_FIPS_1101",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-112.1666666666667],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+11012,PROJCS["NAD_1983_StatePlane_Idaho_East_FIPS_1101_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-112.1666666666667],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+11013,PROJCS["NAD_1983_HARN_StatePlane_Idaho_East_FIPS_1101_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-112.1666666666667],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+11014,PROJCS["NAD_1927_StatePlane_Idaho_East_FIPS_1101",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-112.1666666666667],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+11020,PROJCS["NAD_1983_HARN_StatePlane_Idaho_Central_FIPS_1102",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-114],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+11021,PROJCS["NAD_1983_StatePlane_Idaho_Central_FIPS_1102",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-114],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+11022,PROJCS["NAD_1983_StatePlane_Idaho_Central_FIPS_1102_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-114],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+11023,PROJCS["NAD_1983_HARN_StatePlane_Idaho_Central_FIPS_1102_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-114.0],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+11024,PROJCS["NAD_1927_StatePlane_Idaho_Central_FIPS_1102",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-114],PARAMETER["Scale_Factor",0.9999473684210526],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+11030,PROJCS["NAD_1983_HARN_StatePlane_Idaho_West_FIPS_1103",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-115.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+11031,PROJCS["NAD_1983_StatePlane_Idaho_West_FIPS_1103",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-115.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+11032,PROJCS["NAD_1983_StatePlane_Idaho_West_FIPS_1103_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-115.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+11033,PROJCS["NAD_1983_HARN_StatePlane_Idaho_West_FIPS_1103_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-115.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+11034,PROJCS["NAD_1927_StatePlane_Idaho_West_FIPS_1103",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-115.75],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+12010,PROJCS["NAD_1983_HARN_StatePlane_Illinois_East_FIPS_1201",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.33333333333333],PARAMETER["Scale_Factor",0.9999749999999999],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+12011,PROJCS["NAD_1983_StatePlane_Illinois_East_FIPS_1201",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.33333333333333],PARAMETER["Scale_Factor",0.9999749999999999],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+12012,PROJCS["NAD_1983_StatePlane_Illinois_East_FIPS_1201_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984249.9999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.33333333333333],PARAMETER["Scale_Factor",0.9999749999999999],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+12013,PROJCS["NAD_1983_HARN_StatePlane_Illinois_East_FIPS_1201_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984250.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-88.33333333333333],PARAMETER["Scale_Factor",0.999975],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+12014,PROJCS["NAD_1927_StatePlane_Illinois_East_FIPS_1201",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.33333333333333],PARAMETER["Scale_Factor",0.9999749999999999],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+12020,PROJCS["NAD_1983_HARN_StatePlane_Illinois_West_FIPS_1202",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.16666666666667],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+12021,PROJCS["NAD_1983_StatePlane_Illinois_West_FIPS_1202",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.16666666666667],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+12022,PROJCS["NAD_1983_StatePlane_Illinois_West_FIPS_1202_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.16666666666667],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+12023,PROJCS["NAD_1983_HARN_StatePlane_Illinois_West_FIPS_1202_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-90.16666666666667],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+12024,PROJCS["NAD_1927_StatePlane_Illinois_West_FIPS_1202",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.16666666666667],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+13010,PROJCS["NAD_1983_HARN_StatePlane_Indiana_East_FIPS_1301",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",100000],PARAMETER["False_Northing",250000],PARAMETER["Central_Meridian",-85.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Meter",1]]
+13011,PROJCS["NAD_1983_StatePlane_Indiana_East_FIPS_1301",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",100000],PARAMETER["False_Northing",250000],PARAMETER["Central_Meridian",-85.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Meter",1]]
+13012,PROJCS["NAD_1983_StatePlane_Indiana_East_FIPS_1301_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",328083.3333333333],PARAMETER["False_Northing",820208.3333333333],PARAMETER["Central_Meridian",-85.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.304800609601219241]]
+13013,PROJCS["NAD_1983_HARN_StatePlane_Indiana_East_FIPS_1301_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",328083.3333333333],PARAMETER["False_Northing",820208.3333333333],PARAMETER["Central_Meridian",-85.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.3048006096012192]]
+13014,PROJCS["NAD_1927_StatePlane_Indiana_East_FIPS_1301",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-85.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.304800609601219241]]
+13020,PROJCS["NAD_1983_HARN_StatePlane_Indiana_West_FIPS_1302",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",900000],PARAMETER["False_Northing",250000],PARAMETER["Central_Meridian",-87.08333333333333],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Meter",1]]
+13021,PROJCS["NAD_1983_StatePlane_Indiana_West_FIPS_1302",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",900000],PARAMETER["False_Northing",250000],PARAMETER["Central_Meridian",-87.08333333333333],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Meter",1]]
+13022,PROJCS["NAD_1983_StatePlane_Indiana_West_FIPS_1302_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2952750],PARAMETER["False_Northing",820208.3333333333],PARAMETER["Central_Meridian",-87.08333333333333],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.304800609601219241]]
+13023,PROJCS["NAD_1983_HARN_StatePlane_Indiana_West_FIPS_1302_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2952750.0],PARAMETER["False_Northing",820208.3333333333],PARAMETER["Central_Meridian",-87.08333333333333],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.3048006096012192]]
+13024,PROJCS["NAD_1927_StatePlane_Indiana_West_FIPS_1302",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87.08333333333333],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.304800609601219241]]
+14010,PROJCS["NAD_1983_HARN_StatePlane_Iowa_North_FIPS_1401",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1500000.0],PARAMETER["False_Northing",1000000.0],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",42.06666666666667],PARAMETER["Standard_Parallel_2",43.26666666666667],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Meter",1.0]]
+14011,PROJCS["NAD_1983_StatePlane_Iowa_North_FIPS_1401",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1500000],PARAMETER["False_Northing",1000000],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",42.06666666666667],PARAMETER["Standard_Parallel_2",43.26666666666667],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Meter",1]]
+14012,PROJCS["NAD_1983_StatePlane_Iowa_North_FIPS_1401_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921249.999999999],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",42.06666666666667],PARAMETER["Standard_Parallel_2",43.26666666666667],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot_US",0.304800609601219241]]
+14013,PROJCS["NAD_1983_HARN_StatePlane_Iowa_North_FIPS_1401_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921250.0],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",42.06666666666667],PARAMETER["Standard_Parallel_2",43.26666666666667],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot_US",0.3048006096012192]]
+14014,PROJCS["NAD_1927_StatePlane_Iowa_North_FIPS_1401",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",42.06666666666667],PARAMETER["Standard_Parallel_2",43.26666666666667],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot_US",0.304800609601219241]]
+14020,PROJCS["NAD_1983_HARN_StatePlane_Iowa_South_FIPS_1402",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",40.61666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.0],UNIT["Meter",1.0]]
+14021,PROJCS["NAD_1983_StatePlane_Iowa_South_FIPS_1402",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",40.61666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40],UNIT["Meter",1]]
+14022,PROJCS["NAD_1983_StatePlane_Iowa_South_FIPS_1402_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",40.61666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40],UNIT["Foot_US",0.304800609601219241]]
+14023,PROJCS["NAD_1983_HARN_StatePlane_Iowa_South_FIPS_1402_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",40.61666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.0],UNIT["Foot_US",0.3048006096012192]]
+14024,PROJCS["NAD_1927_StatePlane_Iowa_South_FIPS_1402",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-93.5],PARAMETER["Standard_Parallel_1",40.61666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40],UNIT["Foot_US",0.304800609601219241]]
+15010,PROJCS["NAD_1983_HARN_StatePlane_Kansas_North_FIPS_1501",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",38.71666666666667],PARAMETER["Standard_Parallel_2",39.78333333333333],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Meter",1]]
+15011,PROJCS["NAD_1983_StatePlane_Kansas_North_FIPS_1501",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",38.71666666666667],PARAMETER["Standard_Parallel_2",39.78333333333333],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Meter",1]]
+15012,PROJCS["NAD_1983_StatePlane_Kansas_North_FIPS_1501_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",38.71666666666667],PARAMETER["Standard_Parallel_2",39.78333333333333],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+15013,PROJCS["NAD_1983_HARN_StatePlane_Kansas_North_FIPS_1501_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-98.0],PARAMETER["Standard_Parallel_1",38.71666666666667],PARAMETER["Standard_Parallel_2",39.78333333333333],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+15014,PROJCS["NAD_1927_StatePlane_Kansas_North_FIPS_1501",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",38.71666666666667],PARAMETER["Standard_Parallel_2",39.78333333333333],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+15020,PROJCS["NAD_1983_HARN_StatePlane_Kansas_South_FIPS_1502",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",400000],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",37.26666666666667],PARAMETER["Standard_Parallel_2",38.56666666666667],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+15021,PROJCS["NAD_1983_StatePlane_Kansas_South_FIPS_1502",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",400000],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",37.26666666666667],PARAMETER["Standard_Parallel_2",38.56666666666667],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+15022,PROJCS["NAD_1983_StatePlane_Kansas_South_FIPS_1502_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",1312333.333333333],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",37.26666666666667],PARAMETER["Standard_Parallel_2",38.56666666666667],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+15023,PROJCS["NAD_1983_HARN_StatePlane_Kansas_South_FIPS_1502_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",1312333.333333333],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",37.26666666666667],PARAMETER["Standard_Parallel_2",38.56666666666667],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+15024,PROJCS["NAD_1927_StatePlane_Kansas_South_FIPS_1502",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",37.26666666666667],PARAMETER["Standard_Parallel_2",38.56666666666667],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+16000,PROJCS["NAD_1983_HARN_StatePlane_Kentucky_FIPS_1600",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1500000.0],PARAMETER["False_Northing",1000000.0],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",37.08333333333334],PARAMETER["Standard_Parallel_2",38.66666666666666],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Meter",1.0]]
+16001,PROJCS["NAD_1983_StatePlane_Kentucky_FIPS_1600",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1500000.0],PARAMETER["False_Northing",1000000.0],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",37.08333333333334],PARAMETER["Standard_Parallel_2",38.66666666666666],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Meter",1.0]]
+16002,PROJCS["NAD_1983_StatePlane_Kentucky_FIPS_1600_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921250.0],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",37.08333333333334],PARAMETER["Standard_Parallel_2",38.66666666666666],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+16003,PROJCS["NAD_1983_HARN_StatePlane_Kentucky_FIPS_1600_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921250.0],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",37.08333333333334],PARAMETER["Standard_Parallel_2",38.66666666666666],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+16010,PROJCS["NAD_1983_HARN_StatePlane_Kentucky_North_FIPS_1601",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.25],PARAMETER["Standard_Parallel_1",37.96666666666667],PARAMETER["Standard_Parallel_2",38.96666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Meter",1]]
+16011,PROJCS["NAD_1983_StatePlane_Kentucky_North_FIPS_1601",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.25],PARAMETER["Standard_Parallel_1",37.96666666666667],PARAMETER["Standard_Parallel_2",38.96666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Meter",1]]
+16012,PROJCS["NAD_1983_StatePlane_Kentucky_North_FIPS_1601_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.25],PARAMETER["Standard_Parallel_1",37.96666666666667],PARAMETER["Standard_Parallel_2",38.96666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.304800609601219241]]
+16013,PROJCS["NAD_1983_HARN_StatePlane_Kentucky_North_FIPS_1601_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.25],PARAMETER["Standard_Parallel_1",37.96666666666667],PARAMETER["Standard_Parallel_2",38.96666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.3048006096012192]]
+16014,PROJCS["NAD_1927_StatePlane_Kentucky_North_FIPS_1601",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.25],PARAMETER["Standard_Parallel_1",37.96666666666667],PARAMETER["Standard_Parallel_2",38.96666666666667],PARAMETER["Latitude_Of_Origin",37.5],UNIT["Foot_US",0.304800609601219241]]
+16020,PROJCS["NAD_1983_HARN_StatePlane_Kentucky_South_FIPS_1602",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",36.73333333333333],PARAMETER["Standard_Parallel_2",37.93333333333333],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Meter",1]]
+16021,PROJCS["NAD_1983_StatePlane_Kentucky_South_FIPS_1602",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",500000],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",36.73333333333333],PARAMETER["Standard_Parallel_2",37.93333333333333],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Meter",1]]
+16022,PROJCS["NAD_1983_StatePlane_Kentucky_South_FIPS_1602_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",36.73333333333333],PARAMETER["Standard_Parallel_2",37.93333333333333],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+16023,PROJCS["NAD_1983_HARN_StatePlane_Kentucky_South_FIPS_1602_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",36.73333333333333],PARAMETER["Standard_Parallel_2",37.93333333333333],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+16024,PROJCS["NAD_1927_StatePlane_Kentucky_South_FIPS_1602",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-85.75],PARAMETER["Standard_Parallel_1",36.73333333333333],PARAMETER["Standard_Parallel_2",37.93333333333333],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+17010,PROJCS["NAD_1983_HARN_StatePlane_Louisiana_North_FIPS_1701",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Standard_Parallel_1",31.16666666666667],PARAMETER["Standard_Parallel_2",32.66666666666666],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Meter",1]]
+17011,PROJCS["NAD_1983_StatePlane_Louisiana_North_FIPS_1701",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Standard_Parallel_1",31.16666666666667],PARAMETER["Standard_Parallel_2",32.66666666666666],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Meter",1]]
+17012,PROJCS["NAD_1983_StatePlane_Louisiana_North_FIPS_1701_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3280833.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Standard_Parallel_1",31.16666666666667],PARAMETER["Standard_Parallel_2",32.66666666666666],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Foot_US",0.304800609601219241]]
+17013,PROJCS["NAD_1983_HARN_StatePlane_Louisiana_North_FIPS_1701_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3280833.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Standard_Parallel_1",31.16666666666667],PARAMETER["Standard_Parallel_2",32.66666666666666],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Foot_US",0.3048006096012192]]
+17014,PROJCS["NAD_1927_StatePlane_Louisiana_North_FIPS_1701",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Standard_Parallel_1",31.16666666666667],PARAMETER["Standard_Parallel_2",32.66666666666666],PARAMETER["Latitude_Of_Origin",30.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+17020,PROJCS["NAD_1983_HARN_StatePlane_Louisiana_South_FIPS_1702",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",29.3],PARAMETER["Standard_Parallel_2",30.7],PARAMETER["Latitude_Of_Origin",28.5],UNIT["Meter",1]]
+17021,PROJCS["NAD_1983_StatePlane_Louisiana_South_FIPS_1702",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",29.3],PARAMETER["Standard_Parallel_2",30.7],PARAMETER["Latitude_Of_Origin",28.5],UNIT["Meter",1]]
+17022,PROJCS["NAD_1983_StatePlane_Louisiana_South_FIPS_1702_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3280833.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",29.3],PARAMETER["Standard_Parallel_2",30.7],PARAMETER["Latitude_Of_Origin",28.5],UNIT["Foot_US",0.304800609601219241]]
+17023,PROJCS["NAD_1983_HARN_StatePlane_Louisiana_South_FIPS_1702_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3280833.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",29.3],PARAMETER["Standard_Parallel_2",30.7],PARAMETER["Latitude_Of_Origin",28.5],UNIT["Foot_US",0.3048006096012192]]
+17024,PROJCS["NAD_1927_StatePlane_Louisiana_South_FIPS_1702",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",29.3],PARAMETER["Standard_Parallel_2",30.7],PARAMETER["Latitude_Of_Origin",28.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+17031,PROJCS["NAD_1983_StatePlane_Louisiana_Offshore_FIPS_1703",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1000000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.5],UNIT["Meter",1.0]]
+17032,PROJCS["NAD_1983_StatePlane_Louisiana_Offshore_FIPS_1703_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3280833.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.5],UNIT["Foot_US",0.3048006096012192]]
+17034,PROJCS["NAD_1927_StatePlane_Louisiana_Offshore_FIPS_1703",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-91.33333333333333],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.66666666666667],UNIT["Foot_US",0.3048006096012192]]
+18010,PROJCS["NAD_1983_HARN_StatePlane_Maine_East_FIPS_1801",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-68.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Meter",1]]
+18011,PROJCS["NAD_1983_StatePlane_Maine_East_FIPS_1801",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-68.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Meter",1]]
+18012,PROJCS["NAD_1983_StatePlane_Maine_East_FIPS_1801_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984249.9999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-68.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+18014,PROJCS["NAD_1927_StatePlane_Maine_East_FIPS_1801",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-68.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+18020,PROJCS["NAD_1983_HARN_StatePlane_Maine_West_FIPS_1802",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",900000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.16666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.83333333333334],UNIT["Meter",1]]
+18021,PROJCS["NAD_1983_StatePlane_Maine_West_FIPS_1802",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",900000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.16666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.83333333333334],UNIT["Meter",1]]
+18022,PROJCS["NAD_1983_StatePlane_Maine_West_FIPS_1802_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2952750],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.16666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+18024,PROJCS["NAD_1927_StatePlane_Maine_West_FIPS_1802",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.16666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+19000,PROJCS["NAD_1983_HARN_StatePlane_Maryland_FIPS_1900",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77],PARAMETER["Standard_Parallel_1",38.3],PARAMETER["Standard_Parallel_2",39.45],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Meter",1]]
+19001,PROJCS["NAD_1983_StatePlane_Maryland_FIPS_1900",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77],PARAMETER["Standard_Parallel_1",38.3],PARAMETER["Standard_Parallel_2",39.45],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Meter",1]]
+19002,PROJCS["NAD_1983_StatePlane_Maryland_FIPS_1900_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77],PARAMETER["Standard_Parallel_1",38.3],PARAMETER["Standard_Parallel_2",39.45],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+19003,PROJCS["NAD_1983_HARN_StatePlane_Maryland_FIPS_1900_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-77.0],PARAMETER["Standard_Parallel_1",38.3],PARAMETER["Standard_Parallel_2",39.45],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+19004,PROJCS["NAD_1927_StatePlane_Maryland_FIPS_1900",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77],PARAMETER["Standard_Parallel_1",38.3],PARAMETER["Standard_Parallel_2",39.45],PARAMETER["Latitude_Of_Origin",37.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+20010,PROJCS["NAD_1983_HARN_StatePlane_Massachusetts_Mainland_FIPS_2001",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",750000],PARAMETER["Central_Meridian",-71.5],PARAMETER["Standard_Parallel_1",41.71666666666667],PARAMETER["Standard_Parallel_2",42.68333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Meter",1]]
+20011,PROJCS["NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",750000],PARAMETER["Central_Meridian",-71.5],PARAMETER["Standard_Parallel_1",41.71666666666667],PARAMETER["Standard_Parallel_2",42.68333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Meter",1]]
+20012,PROJCS["NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",2460625],PARAMETER["Central_Meridian",-71.5],PARAMETER["Standard_Parallel_1",41.71666666666667],PARAMETER["Standard_Parallel_2",42.68333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Foot_US",0.304800609601219241]]
+20013,PROJCS["NAD_1983_HARN_StatePlane_Massachusetts_Mainland_FIPS_2001_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",2460625.0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Standard_Parallel_1",41.71666666666667],PARAMETER["Standard_Parallel_2",42.68333333333333],PARAMETER["Latitude_Of_Origin",41.0],UNIT["Foot_US",0.3048006096012192]]
+20014,PROJCS["NAD_1927_StatePlane_Massachusetts_Mainland_FIPS_2001",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Standard_Parallel_1",41.71666666666667],PARAMETER["Standard_Parallel_2",42.68333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Foot_US",0.304800609601219241]]
+20020,PROJCS["NAD_1983_HARN_StatePlane_Massachusetts_Island_FIPS_2002",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.5],PARAMETER["Standard_Parallel_1",41.28333333333333],PARAMETER["Standard_Parallel_2",41.48333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Meter",1]]
+20021,PROJCS["NAD_1983_StatePlane_Massachusetts_Island_FIPS_2002",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.5],PARAMETER["Standard_Parallel_1",41.28333333333333],PARAMETER["Standard_Parallel_2",41.48333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Meter",1]]
+20022,PROJCS["NAD_1983_StatePlane_Massachusetts_Island_FIPS_2002_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.5],PARAMETER["Standard_Parallel_1",41.28333333333333],PARAMETER["Standard_Parallel_2",41.48333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Foot_US",0.304800609601219241]]
+20023,PROJCS["NAD_1983_HARN_StatePlane_Massachusetts_Island_FIPS_2002_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-70.5],PARAMETER["Standard_Parallel_1",41.28333333333333],PARAMETER["Standard_Parallel_2",41.48333333333333],PARAMETER["Latitude_Of_Origin",41.0],UNIT["Foot_US",0.3048006096012192]]
+20024,PROJCS["NAD_1927_StatePlane_Massachusetts_Island_FIPS_2002",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-70.5],PARAMETER["Standard_Parallel_1",41.28333333333333],PARAMETER["Standard_Parallel_2",41.48333333333333],PARAMETER["Latitude_Of_Origin",41],UNIT["Foot_US",0.304800609601219241]]
+21110,PROJCS["NAD_1983_HARN_StatePlane_Michigan_North_FIPS_2111",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",8000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87],PARAMETER["Standard_Parallel_1",45.48333333333333],PARAMETER["Standard_Parallel_2",47.08333333333334],PARAMETER["Latitude_Of_Origin",44.78333333333333],UNIT["Meter",1]]
+21111,PROJCS["NAD_1983_StatePlane_Michigan_North_FIPS_2111",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",8000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87],PARAMETER["Standard_Parallel_1",45.48333333333333],PARAMETER["Standard_Parallel_2",47.08333333333334],PARAMETER["Latitude_Of_Origin",44.78333333333333],UNIT["Meter",1]]
+21112,PROJCS["NAD_1983_StatePlane_Michigan_North_FIPS_2111_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",26246666.66666666],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87],PARAMETER["Standard_Parallel_1",45.48333333333333],PARAMETER["Standard_Parallel_2",47.08333333333334],PARAMETER["Latitude_Of_Origin",44.78333333333333],UNIT["Foot_US",0.304800609601219241]]
+21113,PROJCS["NAD_1983_HARN_StatePlane_Michigan_North_FIPS_2111_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",26246719.16010498],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-87.0],PARAMETER["Standard_Parallel_1",45.48333333333333],PARAMETER["Standard_Parallel_2",47.08333333333334],PARAMETER["Latitude_Of_Origin",44.78333333333333],UNIT["Foot",0.3048]]
+21114,PROJCS["NAD_1927_StatePlane_Michigan_North_FIPS_2111",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-87],PARAMETER["Standard_Parallel_1",45.48333333333333],PARAMETER["Standard_Parallel_2",47.08333333333334],PARAMETER["Latitude_Of_Origin",44.78333333333333],UNIT["Foot_US",0.304800609601219241]]
+21115,PROJCS["NAD_1983_HARN_StatePlane_Michigan_North_FIPS_2111_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",26246719.16010498],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-87.0],PARAMETER["Standard_Parallel_1",45.48333333333333],PARAMETER["Standard_Parallel_2",47.08333333333334],PARAMETER["Latitude_Of_Origin",44.78333333333333],UNIT["Foot",0.3048]]
+21116,PROJCS["NAD_1983_StatePlane_Michigan_North_FIPS_2111_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",26246719.16010498],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-87.0],PARAMETER["Standard_Parallel_1",45.48333333333333],PARAMETER["Standard_Parallel_2",47.08333333333334],PARAMETER["Latitude_Of_Origin",44.78333333333333],UNIT["Foot",0.3048]]
+21120,PROJCS["NAD_1983_HARN_StatePlane_Michigan_Central_FIPS_2112",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",44.18333333333333],PARAMETER["Standard_Parallel_2",45.7],PARAMETER["Latitude_Of_Origin",43.31666666666667],UNIT["Meter",1]]
+21121,PROJCS["NAD_1983_StatePlane_Michigan_Central_FIPS_2112",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",44.18333333333333],PARAMETER["Standard_Parallel_2",45.7],PARAMETER["Latitude_Of_Origin",43.31666666666667],UNIT["Meter",1]]
+21122,PROJCS["NAD_1983_StatePlane_Michigan_Central_FIPS_2112_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",19685000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",44.18333333333333],PARAMETER["Standard_Parallel_2",45.7],PARAMETER["Latitude_Of_Origin",43.31666666666667],UNIT["Foot_US",0.304800609601219241]]
+21123,PROJCS["NAD_1983_HARN_StatePlane_Michigan_Central_FIPS_2112_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",19685039.37007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",44.18333333333333],PARAMETER["Standard_Parallel_2",45.7],PARAMETER["Latitude_Of_Origin",43.31666666666667],UNIT["Foot",0.3048]]
+21124,PROJCS["NAD_1927_StatePlane_Michigan_Central_FIPS_2112",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.33333333333333],PARAMETER["Standard_Parallel_1",44.18333333333333],PARAMETER["Standard_Parallel_2",45.7],PARAMETER["Latitude_Of_Origin",43.31666666666667],UNIT["Foot_US",0.304800609601219241]]
+21125,PROJCS["NAD_1983_HARN_StatePlane_Michigan_Central_FIPS_2112_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",19685039.37007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",44.18333333333333],PARAMETER["Standard_Parallel_2",45.7],PARAMETER["Latitude_Of_Origin",43.31666666666667],UNIT["Foot",0.3048]]
+21126,PROJCS["NAD_1983_StatePlane_Michigan_Central_FIPS_2112_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",19685039.37007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",44.18333333333333],PARAMETER["Standard_Parallel_2",45.7],PARAMETER["Latitude_Of_Origin",43.31666666666667],UNIT["Foot",0.3048]]
+21130,PROJCS["NAD_1983_HARN_StatePlane_Michigan_South_FIPS_2113",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",42.1],PARAMETER["Standard_Parallel_2",43.66666666666666],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Meter",1]]
+21131,PROJCS["NAD_1983_StatePlane_Michigan_South_FIPS_2113",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",42.1],PARAMETER["Standard_Parallel_2",43.66666666666666],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Meter",1]]
+21132,PROJCS["NAD_1983_StatePlane_Michigan_South_FIPS_2113_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",13123333.33333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",42.1],PARAMETER["Standard_Parallel_2",43.66666666666666],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot_US",0.304800609601219241]]
+21133,PROJCS["NAD_1983_HARN_StatePlane_Michigan_South_FIPS_2113_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",13123359.58005249],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",42.1],PARAMETER["Standard_Parallel_2",43.66666666666666],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot",0.3048]]
+21134,PROJCS["NAD_1927_StatePlane_Michigan_South_FIPS_2113",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-84.33333333333333],PARAMETER["Standard_Parallel_1",42.1],PARAMETER["Standard_Parallel_2",43.66666666666666],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot_US",0.304800609601219241]]
+21135,PROJCS["NAD_1983_HARN_StatePlane_Michigan_South_FIPS_2113_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",13123359.58005249],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",42.1],PARAMETER["Standard_Parallel_2",43.66666666666666],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot",0.3048]]
+21136,PROJCS["NAD_1983_StatePlane_Michigan_South_FIPS_2113_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",13123359.58005249],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-84.36666666666666],PARAMETER["Standard_Parallel_1",42.1],PARAMETER["Standard_Parallel_2",43.66666666666666],PARAMETER["Latitude_Of_Origin",41.5],UNIT["Foot",0.3048]]
+22010,PROJCS["NAD_1983_HARN_StatePlane_Minnesota_North_FIPS_2201",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",800000.0],PARAMETER["False_Northing",100000.0],PARAMETER["Central_Meridian",-93.1],PARAMETER["Standard_Parallel_1",47.03333333333333],PARAMETER["Standard_Parallel_2",48.63333333333333],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1.0]]
+22011,PROJCS["NAD_1983_StatePlane_Minnesota_North_FIPS_2201",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-93.09999999999999],PARAMETER["Standard_Parallel_1",47.03333333333333],PARAMETER["Standard_Parallel_2",48.63333333333333],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Meter",1]]
+22012,PROJCS["NAD_1983_StatePlane_Minnesota_North_FIPS_2201_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-93.09999999999999],PARAMETER["Standard_Parallel_1",47.03333333333333],PARAMETER["Standard_Parallel_2",48.63333333333333],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Foot_US",0.304800609601219241]]
+22013,PROJCS["NAD_1983_HARN_StatePlane_Minnesota_North_FIPS_2201_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-93.1],PARAMETER["Standard_Parallel_1",47.03333333333333],PARAMETER["Standard_Parallel_2",48.63333333333333],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Foot_US",0.3048006096012192]]
+22014,PROJCS["NAD_1927_StatePlane_Minnesota_North_FIPS_2201",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-93.09999999999999],PARAMETER["Standard_Parallel_1",47.03333333333333],PARAMETER["Standard_Parallel_2",48.63333333333333],PARAMETER["Latitude_Of_Origin",46.5],UNIT["Foot_US",0.304800609601219241]]
+22020,PROJCS["NAD_1983_HARN_StatePlane_Minnesota_Central_FIPS_2202",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",800000.0],PARAMETER["False_Northing",100000.0],PARAMETER["Central_Meridian",-94.25],PARAMETER["Standard_Parallel_1",45.61666666666667],PARAMETER["Standard_Parallel_2",47.05],PARAMETER["Latitude_Of_Origin",45.0],UNIT["Meter",1.0]]
+22021,PROJCS["NAD_1983_StatePlane_Minnesota_Central_FIPS_2202",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-94.25],PARAMETER["Standard_Parallel_1",45.61666666666667],PARAMETER["Standard_Parallel_2",47.05],PARAMETER["Latitude_Of_Origin",45],UNIT["Meter",1]]
+22022,PROJCS["NAD_1983_StatePlane_Minnesota_Central_FIPS_2202_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-94.25],PARAMETER["Standard_Parallel_1",45.61666666666667],PARAMETER["Standard_Parallel_2",47.05],PARAMETER["Latitude_Of_Origin",45],UNIT["Foot_US",0.304800609601219241]]
+22023,PROJCS["NAD_1983_HARN_StatePlane_Minnesota_Central_FIPS_2202_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-94.25],PARAMETER["Standard_Parallel_1",45.61666666666667],PARAMETER["Standard_Parallel_2",47.05],PARAMETER["Latitude_Of_Origin",45.0],UNIT["Foot_US",0.3048006096012192]]
+22024,PROJCS["NAD_1927_StatePlane_Minnesota_Central_FIPS_2202",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-94.25],PARAMETER["Standard_Parallel_1",45.61666666666667],PARAMETER["Standard_Parallel_2",47.05],PARAMETER["Latitude_Of_Origin",45],UNIT["Foot_US",0.304800609601219241]]
+22030,PROJCS["NAD_1983_HARN_StatePlane_Minnesota_South_FIPS_2203",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",800000.0],PARAMETER["False_Northing",100000.0],PARAMETER["Central_Meridian",-94.0],PARAMETER["Standard_Parallel_1",43.78333333333333],PARAMETER["Standard_Parallel_2",45.21666666666667],PARAMETER["Latitude_Of_Origin",43.0],UNIT["Meter",1.0]]
+22031,PROJCS["NAD_1983_StatePlane_Minnesota_South_FIPS_2203",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-94],PARAMETER["Standard_Parallel_1",43.78333333333333],PARAMETER["Standard_Parallel_2",45.21666666666667],PARAMETER["Latitude_Of_Origin",43],UNIT["Meter",1]]
+22032,PROJCS["NAD_1983_StatePlane_Minnesota_South_FIPS_2203_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-94],PARAMETER["Standard_Parallel_1",43.78333333333333],PARAMETER["Standard_Parallel_2",45.21666666666667],PARAMETER["Latitude_Of_Origin",43],UNIT["Foot_US",0.304800609601219241]]
+22033,PROJCS["NAD_1983_HARN_StatePlane_Minnesota_South_FIPS_2203_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-94.0],PARAMETER["Standard_Parallel_1",43.78333333333333],PARAMETER["Standard_Parallel_2",45.21666666666667],PARAMETER["Latitude_Of_Origin",43.0],UNIT["Foot_US",0.3048006096012192]]
+22034,PROJCS["NAD_1927_StatePlane_Minnesota_South_FIPS_2203",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-94],PARAMETER["Standard_Parallel_1",43.78333333333333],PARAMETER["Standard_Parallel_2",45.21666666666667],PARAMETER["Latitude_Of_Origin",43],UNIT["Foot_US",0.304800609601219241]]
+23010,PROJCS["NAD_1983_HARN_StatePlane_Mississippi_East_FIPS_2301",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.83333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Meter",1]]
+23011,PROJCS["NAD_1983_StatePlane_Mississippi_East_FIPS_2301",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.83333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Meter",1]]
+23012,PROJCS["NAD_1983_StatePlane_Mississippi_East_FIPS_2301_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984249.9999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.83333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Foot_US",0.304800609601219241]]
+23013,PROJCS["NAD_1983_HARN_StatePlane_Mississippi_East_FIPS_2301_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984250.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-88.83333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Foot_US",0.3048006096012192]]
+23014,PROJCS["NAD_1927_StatePlane_Mississippi_East_FIPS_2301",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-88.83333333333333],PARAMETER["Scale_Factor",0.99996],PARAMETER["Latitude_Of_Origin",29.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+23020,PROJCS["NAD_1983_HARN_StatePlane_Mississippi_West_FIPS_2302",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.33333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Meter",1]]
+23021,PROJCS["NAD_1983_StatePlane_Mississippi_West_FIPS_2302",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.33333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Meter",1]]
+23022,PROJCS["NAD_1983_StatePlane_Mississippi_West_FIPS_2302_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.33333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Foot_US",0.304800609601219241]]
+23023,PROJCS["NAD_1983_HARN_StatePlane_Mississippi_West_FIPS_2302_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-90.33333333333333],PARAMETER["Scale_Factor",0.99995],PARAMETER["Latitude_Of_Origin",29.5],UNIT["Foot_US",0.3048006096012192]]
+23024,PROJCS["NAD_1927_StatePlane_Mississippi_West_FIPS_2302",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.33333333333333],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",30.5],UNIT["Foot_US",0.304800609601219241]]
+24010,PROJCS["NAD_1983_HARN_StatePlane_Missouri_East_FIPS_2401",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",250000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-90.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Meter",1.0]]
+24011,PROJCS["NAD_1983_StatePlane_Missouri_East_FIPS_2401",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",250000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Meter",1]]
+24012,PROJCS["NAD_1983_StatePlane_Missouri_East_FIPS_2401_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",820208.3333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+24014,PROJCS["NAD_1927_StatePlane_Missouri_East_FIPS_2401",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+24020,PROJCS["NAD_1983_HARN_StatePlane_Missouri_Central_FIPS_2402",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Meter",1.0]]
+24021,PROJCS["NAD_1983_StatePlane_Missouri_Central_FIPS_2402",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Meter",1]]
+24022,PROJCS["NAD_1983_StatePlane_Missouri_Central_FIPS_2402_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+24024,PROJCS["NAD_1927_StatePlane_Missouri_Central_FIPS_2402",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-92.5],PARAMETER["Scale_Factor",0.9999333333333333],PARAMETER["Latitude_Of_Origin",35.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+24030,PROJCS["NAD_1983_HARN_StatePlane_Missouri_West_FIPS_2403",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",850000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-94.5],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.16666666666666],UNIT["Meter",1.0]]
+24031,PROJCS["NAD_1983_StatePlane_Missouri_West_FIPS_2403",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",850000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-94.5],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.16666666666666],UNIT["Meter",1]]
+24032,PROJCS["NAD_1983_StatePlane_Missouri_West_FIPS_2403_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2788708.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-94.5],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+24034,PROJCS["NAD_1927_StatePlane_Missouri_West_FIPS_2403",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-94.5],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",36.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+25000,PROJCS["NAD_1983_HARN_StatePlane_Montana_FIPS_2500",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",45],PARAMETER["Standard_Parallel_2",49],PARAMETER["Latitude_Of_Origin",44.25],UNIT["Meter",1]]
+25001,PROJCS["NAD_1983_StatePlane_Montana_FIPS_2500",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",45],PARAMETER["Standard_Parallel_2",49],PARAMETER["Latitude_Of_Origin",44.25],UNIT["Meter",1]]
+25002,PROJCS["NAD_1983_StatePlane_Montana_FIPS_2500_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",45],PARAMETER["Standard_Parallel_2",49],PARAMETER["Latitude_Of_Origin",44.25],UNIT["Foot_US",0.304800609601219241]]
+25003,PROJCS["NAD_1983_HARN_StatePlane_Montana_FIPS_2500_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",45.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",44.25],UNIT["Foot",0.3048]]
+25005,PROJCS["NAD_1983_HARN_StatePlane_Montana_FIPS_2500_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",45.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",44.25],UNIT["Foot",0.3048]]
+25006,PROJCS["NAD_1983_StatePlane_Montana_FIPS_2500_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",45.0],PARAMETER["Standard_Parallel_2",49.0],PARAMETER["Latitude_Of_Origin",44.25],UNIT["Foot",0.3048]]
+25014,PROJCS["NAD_1927_StatePlane_Montana_North_FIPS_2501",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",47.85],PARAMETER["Standard_Parallel_2",48.71666666666667],PARAMETER["Latitude_Of_Origin",47],UNIT["Foot_US",0.304800609601219241]]
+25024,PROJCS["NAD_1927_StatePlane_Montana_Central_FIPS_2502",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",46.45],PARAMETER["Standard_Parallel_2",47.88333333333333],PARAMETER["Latitude_Of_Origin",45.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+25034,PROJCS["NAD_1927_StatePlane_Montana_South_FIPS_2503",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-109.5],PARAMETER["Standard_Parallel_1",44.86666666666667],PARAMETER["Standard_Parallel_2",46.4],PARAMETER["Latitude_Of_Origin",44],UNIT["Foot_US",0.304800609601219241]]
+26000,PROJCS["NAD_1983_HARN_StatePlane_Nebraska_FIPS_2600",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",40],PARAMETER["Standard_Parallel_2",43],PARAMETER["Latitude_Of_Origin",39.83333333333334],UNIT["Meter",1]]
+26001,PROJCS["NAD_1983_StatePlane_Nebraska_FIPS_2600",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",40],PARAMETER["Standard_Parallel_2",43],PARAMETER["Latitude_Of_Origin",39.83333333333334],UNIT["Meter",1]]
+26002,PROJCS["NAD_1983_StatePlane_Nebraska_FIPS_2600_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",40],PARAMETER["Standard_Parallel_2",43],PARAMETER["Latitude_Of_Origin",39.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+26014,PROJCS["NAD_1927_StatePlane_Nebraska_North_FIPS_2601",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",41.85],PARAMETER["Standard_Parallel_2",42.81666666666667],PARAMETER["Latitude_Of_Origin",41.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+26024,PROJCS["NAD_1927_StatePlane_Nebraska_South_FIPS_2602",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-99.5],PARAMETER["Standard_Parallel_1",40.28333333333333],PARAMETER["Standard_Parallel_2",41.71666666666667],PARAMETER["Latitude_Of_Origin",39.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+27010,PROJCS["NAD_1983_HARN_StatePlane_Nevada_East_FIPS_2701",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",8000000],PARAMETER["Central_Meridian",-115.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Meter",1]]
+27011,PROJCS["NAD_1983_StatePlane_Nevada_East_FIPS_2701",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",8000000],PARAMETER["Central_Meridian",-115.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Meter",1]]
+27012,PROJCS["NAD_1983_StatePlane_Nevada_East_FIPS_2701_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",26246666.66666666],PARAMETER["Central_Meridian",-115.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.304800609601219241]]
+27013,PROJCS["NAD_1983_HARN_StatePlane_Nevada_East_FIPS_2701_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",26246666.66666666],PARAMETER["Central_Meridian",-115.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.3048006096012192]]
+27014,PROJCS["NAD_1927_StatePlane_Nevada_East_FIPS_2701",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-115.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.304800609601219241]]
+27020,PROJCS["NAD_1983_HARN_StatePlane_Nevada_Central_FIPS_2702",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",6000000],PARAMETER["Central_Meridian",-116.6666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Meter",1]]
+27021,PROJCS["NAD_1983_StatePlane_Nevada_Central_FIPS_2702",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",6000000],PARAMETER["Central_Meridian",-116.6666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Meter",1]]
+27022,PROJCS["NAD_1983_StatePlane_Nevada_Central_FIPS_2702_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",19685000],PARAMETER["Central_Meridian",-116.6666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.304800609601219241]]
+27023,PROJCS["NAD_1983_HARN_StatePlane_Nevada_Central_FIPS_2702_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",19685000.0],PARAMETER["Central_Meridian",-116.6666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.3048006096012192]]
+27024,PROJCS["NAD_1927_StatePlane_Nevada_Central_FIPS_2702",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-116.6666666666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.304800609601219241]]
+27030,PROJCS["NAD_1983_HARN_StatePlane_Nevada_West_FIPS_2703",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",4000000],PARAMETER["Central_Meridian",-118.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Meter",1]]
+27031,PROJCS["NAD_1983_StatePlane_Nevada_West_FIPS_2703",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",4000000],PARAMETER["Central_Meridian",-118.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Meter",1]]
+27032,PROJCS["NAD_1983_StatePlane_Nevada_West_FIPS_2703_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",13123333.33333333],PARAMETER["Central_Meridian",-118.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.304800609601219241]]
+27033,PROJCS["NAD_1983_HARN_StatePlane_Nevada_West_FIPS_2703_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",13123333.33333333],PARAMETER["Central_Meridian",-118.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.3048006096012192]]
+27034,PROJCS["NAD_1927_StatePlane_Nevada_West_FIPS_2703",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-118.5833333333333],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",34.75],UNIT["Foot_US",0.304800609601219241]]
+28000,PROJCS["NAD_1983_HARN_StatePlane_New_Hampshire_FIPS_2800",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Meter",1]]
+28001,PROJCS["NAD_1983_StatePlane_New_Hampshire_FIPS_2800",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Meter",1]]
+28002,PROJCS["NAD_1983_StatePlane_New_Hampshire_FIPS_2800_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984249.9999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Foot_US",0.304800609601219241]]
+28003,PROJCS["NAD_1983_HARN_StatePlane_New_Hampshire_FIPS_2800_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984250.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-71.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Foot_US",0.3048006096012192]]
+28004,PROJCS["NAD_1927_StatePlane_New_Hampshire_FIPS_2800",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.66666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Foot_US",0.304800609601219241]]
+29000,PROJCS["NAD_1983_HARN_StatePlane_New_Jersey_FIPS_2900",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",150000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Meter",1]]
+29001,PROJCS["NAD_1983_StatePlane_New_Jersey_FIPS_2900",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",150000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Meter",1]]
+29002,PROJCS["NAD_1983_StatePlane_New_Jersey_FIPS_2900_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",492124.9999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+29003,PROJCS["NAD_1983_HARN_StatePlane_New_Jersey_FIPS_2900_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",492125.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Foot_US",0.3048006096012192]]
+29004,PROJCS["NAD_1927_StatePlane_New_Jersey_FIPS_2900",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.66666666666667],PARAMETER["Scale_Factor",0.9999749999999999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+30010,PROJCS["NAD_1983_HARN_StatePlane_New_Mexico_East_FIPS_3001",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",165000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-104.3333333333333],PARAMETER["Scale_Factor",0.9999090909090909],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+30011,PROJCS["NAD_1983_StatePlane_New_Mexico_East_FIPS_3001",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",165000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-104.3333333333333],PARAMETER["Scale_Factor",0.9999090909090909],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+30012,PROJCS["NAD_1983_StatePlane_New_Mexico_East_FIPS_3001_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",541337.4999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-104.3333333333333],PARAMETER["Scale_Factor",0.9999090909090909],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+30013,PROJCS["NAD_1983_HARN_StatePlane_New_Mexico_East_FIPS_3001_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",541337.5],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-104.3333333333333],PARAMETER["Scale_Factor",0.9999090909090909],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot_US",0.3048006096012192]]
+30014,PROJCS["NAD_1927_StatePlane_New_Mexico_East_FIPS_3001",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-104.3333333333333],PARAMETER["Scale_Factor",0.9999090909090909],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+30020,PROJCS["NAD_1983_HARN_StatePlane_New_Mexico_Central_FIPS_3002",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-106.25],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+30021,PROJCS["NAD_1983_StatePlane_New_Mexico_Central_FIPS_3002",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-106.25],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+30022,PROJCS["NAD_1983_StatePlane_New_Mexico_Central_FIPS_3002_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-106.25],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+30023,PROJCS["NAD_1983_HARN_StatePlane_New_Mexico_Central_FIPS_3002_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-106.25],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot_US",0.3048006096012192]]
+30024,PROJCS["NAD_1927_StatePlane_New_Mexico_Central_FIPS_3002",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-106.25],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+30030,PROJCS["NAD_1983_HARN_StatePlane_New_Mexico_West_FIPS_3003",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",830000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-107.8333333333333],PARAMETER["Scale_Factor",0.9999166666666667],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+30031,PROJCS["NAD_1983_StatePlane_New_Mexico_West_FIPS_3003",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",830000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-107.8333333333333],PARAMETER["Scale_Factor",0.9999166666666667],PARAMETER["Latitude_Of_Origin",31],UNIT["Meter",1]]
+30032,PROJCS["NAD_1983_StatePlane_New_Mexico_West_FIPS_3003_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2723091.666666666],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-107.8333333333333],PARAMETER["Scale_Factor",0.9999166666666667],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+30033,PROJCS["NAD_1983_HARN_StatePlane_New_Mexico_West_FIPS_3003_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2723091.666666666],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-107.8333333333333],PARAMETER["Scale_Factor",0.9999166666666667],PARAMETER["Latitude_Of_Origin",31.0],UNIT["Foot_US",0.3048006096012192]]
+30034,PROJCS["NAD_1927_StatePlane_New_Mexico_West_FIPS_3003",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-107.8333333333333],PARAMETER["Scale_Factor",0.9999166666666667],PARAMETER["Latitude_Of_Origin",31],UNIT["Foot_US",0.304800609601219241]]
+31010,PROJCS["NAD_1983_HARN_StatePlane_New_York_East_FIPS_3101",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",150000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Meter",1]]
+31011,PROJCS["NAD_1983_StatePlane_New_York_East_FIPS_3101",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",150000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Meter",1]]
+31012,PROJCS["NAD_1983_StatePlane_New_York_East_FIPS_3101_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",492124.9999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+31013,PROJCS["NAD_1983_HARN_StatePlane_New_York_East_FIPS_3101_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",492125.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Foot_US",0.3048006096012192]]
+31014,PROJCS["NAD_1927_StatePlane_New_York_East_FIPS_3101",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74.33333333333333],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",40],UNIT["Foot_US",0.304800609601219241]]
+31020,PROJCS["NAD_1983_HARN_StatePlane_New_York_Central_FIPS_3102",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",250000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-76.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Meter",1]]
+31021,PROJCS["NAD_1983_StatePlane_New_York_Central_FIPS_3102",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",250000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-76.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Meter",1]]
+31022,PROJCS["NAD_1983_StatePlane_New_York_Central_FIPS_3102_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",820208.3333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-76.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Foot_US",0.304800609601219241]]
+31023,PROJCS["NAD_1983_HARN_StatePlane_New_York_Central_FIPS_3102_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",820208.3333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-76.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.0],UNIT["Foot_US",0.3048006096012192]]
+31024,PROJCS["NAD_1927_StatePlane_New_York_Central_FIPS_3102",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-76.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Foot_US",0.304800609601219241]]
+31030,PROJCS["NAD_1983_HARN_StatePlane_New_York_West_FIPS_3103",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",350000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-78.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Meter",1]]
+31031,PROJCS["NAD_1983_StatePlane_New_York_West_FIPS_3103",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",350000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-78.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Meter",1]]
+31032,PROJCS["NAD_1983_StatePlane_New_York_West_FIPS_3103_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1148291.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-78.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Foot_US",0.304800609601219241]]
+31033,PROJCS["NAD_1983_HARN_StatePlane_New_York_West_FIPS_3103_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1148291.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-78.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.0],UNIT["Foot_US",0.3048006096012192]]
+31034,PROJCS["NAD_1927_StatePlane_New_York_West_FIPS_3103",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-78.58333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40],UNIT["Foot_US",0.304800609601219241]]
+31040,PROJCS["NAD_1983_HARN_StatePlane_New_York_Long_Island_FIPS_3104",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74],PARAMETER["Standard_Parallel_1",40.66666666666666],PARAMETER["Standard_Parallel_2",41.03333333333333],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Meter",1]]
+31041,PROJCS["NAD_1983_StatePlane_New_York_Long_Island_FIPS_3104",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74],PARAMETER["Standard_Parallel_1",40.66666666666666],PARAMETER["Standard_Parallel_2",41.03333333333333],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Meter",1]]
+31042,PROJCS["NAD_1983_StatePlane_New_York_Long_Island_FIPS_3104_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",984249.9999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-74],PARAMETER["Standard_Parallel_1",40.66666666666666],PARAMETER["Standard_Parallel_2",41.03333333333333],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+31043,PROJCS["NAD_1983_HARN_StatePlane_New_York_Long_Island_FIPS_3104_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",984250.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-74.0],PARAMETER["Standard_Parallel_1",40.66666666666666],PARAMETER["Standard_Parallel_2",41.03333333333333],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Foot_US",0.3048006096012192]]
+31044,PROJCS["NAD_1927_StatePlane_New_York_Long_Island_FIPS_3104",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-74],PARAMETER["Standard_Parallel_1",40.66666666666666],PARAMETER["Standard_Parallel_2",41.03333333333333],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.304800609601219241]]
+32000,PROJCS["NAD_1983_HARN_StatePlane_North_Carolina_FIPS_3200",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",609601.2192024384],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-79.0],PARAMETER["Standard_Parallel_1",34.33333333333334],PARAMETER["Standard_Parallel_2",36.16666666666666],PARAMETER["Latitude_Of_Origin",33.75],UNIT["Meter",1.0]]
+32001,PROJCS["NAD_1983_StatePlane_North_Carolina_FIPS_3200",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",609601.22],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-79],PARAMETER["Standard_Parallel_1",34.33333333333334],PARAMETER["Standard_Parallel_2",36.16666666666666],PARAMETER["Latitude_Of_Origin",33.75],UNIT["Meter",1]]
+32002,PROJCS["NAD_1983_StatePlane_North_Carolina_FIPS_3200_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000.002616666],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-79],PARAMETER["Standard_Parallel_1",34.33333333333334],PARAMETER["Standard_Parallel_2",36.16666666666666],PARAMETER["Latitude_Of_Origin",33.75],UNIT["Foot_US",0.304800609601219241]]
+32003,PROJCS["NAD_1983_HARN_StatePlane_North_Carolina_FIPS_3200_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-79.0],PARAMETER["Standard_Parallel_1",34.33333333333334],PARAMETER["Standard_Parallel_2",36.16666666666666],PARAMETER["Latitude_Of_Origin",33.75],UNIT["Foot_US",0.3048006096012192]]
+32004,PROJCS["NAD_1927_StatePlane_North_Carolina_FIPS_3200",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-79],PARAMETER["Standard_Parallel_1",34.33333333333334],PARAMETER["Standard_Parallel_2",36.16666666666666],PARAMETER["Latitude_Of_Origin",33.75],UNIT["Foot_US",0.304800609601219241]]
+33010,PROJCS["NAD_1983_HARN_StatePlane_North_Dakota_North_FIPS_3301",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",47.43333333333333],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Meter",1]]
+33011,PROJCS["NAD_1983_StatePlane_North_Dakota_North_FIPS_3301",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",47.43333333333333],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Meter",1]]
+33012,PROJCS["NAD_1983_StatePlane_North_Dakota_North_FIPS_3301_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",47.43333333333333],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Foot_US",0.304800609601219241]]
+33013,PROJCS["NAD_1983_HARN_StatePlane_North_Dakota_North_FIPS_3301_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",47.43333333333333],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47.0],UNIT["Foot",0.3048]]
+33014,PROJCS["NAD_1927_StatePlane_North_Dakota_North_FIPS_3301",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",47.43333333333333],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Foot_US",0.304800609601219241]]
+33015,PROJCS["NAD_1983_HARN_StatePlane_North_Dakota_North_FIPS_3301_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",47.43333333333333],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47.0],UNIT["Foot",0.3048]]
+33016,PROJCS["NAD_1983_StatePlane_North_Dakota_North_FIPS_3301_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",47.43333333333333],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47.0],UNIT["Foot",0.3048]]
+33020,PROJCS["NAD_1983_HARN_StatePlane_North_Dakota_South_FIPS_3302",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",46.18333333333333],PARAMETER["Standard_Parallel_2",47.48333333333333],PARAMETER["Latitude_Of_Origin",45.66666666666666],UNIT["Meter",1]]
+33021,PROJCS["NAD_1983_StatePlane_North_Dakota_South_FIPS_3302",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",46.18333333333333],PARAMETER["Standard_Parallel_2",47.48333333333333],PARAMETER["Latitude_Of_Origin",45.66666666666666],UNIT["Meter",1]]
+33022,PROJCS["NAD_1983_StatePlane_North_Dakota_South_FIPS_3302_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",46.18333333333333],PARAMETER["Standard_Parallel_2",47.48333333333333],PARAMETER["Latitude_Of_Origin",45.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+33023,PROJCS["NAD_1983_HARN_StatePlane_North_Dakota_South_FIPS_3302_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",46.18333333333333],PARAMETER["Standard_Parallel_2",47.48333333333333],PARAMETER["Latitude_Of_Origin",45.66666666666666],UNIT["Foot",0.3048]]
+33024,PROJCS["NAD_1927_StatePlane_North_Dakota_South_FIPS_3302",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",46.18333333333333],PARAMETER["Standard_Parallel_2",47.48333333333333],PARAMETER["Latitude_Of_Origin",45.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+33025,PROJCS["NAD_1983_HARN_StatePlane_North_Dakota_South_FIPS_3302_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",46.18333333333333],PARAMETER["Standard_Parallel_2",47.48333333333333],PARAMETER["Latitude_Of_Origin",45.66666666666666],UNIT["Foot",0.3048]]
+33026,PROJCS["NAD_1983_StatePlane_North_Dakota_South_FIPS_3302_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968503.937007874],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.5],PARAMETER["Standard_Parallel_1",46.18333333333333],PARAMETER["Standard_Parallel_2",47.48333333333333],PARAMETER["Latitude_Of_Origin",45.66666666666666],UNIT["Foot",0.3048]]
+34004,PROJCS["NAD_1927_StatePlane_Vermont_FIPS_3400",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-72.5],PARAMETER["Scale_Factor",0.9999642857142857],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Foot_US",0.304800609601219241]]
+34010,PROJCS["NAD_1983_HARN_StatePlane_Ohio_North_FIPS_3401",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",40.43333333333333],PARAMETER["Standard_Parallel_2",41.7],PARAMETER["Latitude_Of_Origin",39.66666666666666],UNIT["Meter",1]]
+34011,PROJCS["NAD_1983_StatePlane_Ohio_North_FIPS_3401",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",40.43333333333333],PARAMETER["Standard_Parallel_2",41.7],PARAMETER["Latitude_Of_Origin",39.66666666666666],UNIT["Meter",1]]
+34012,PROJCS["NAD_1983_StatePlane_Ohio_North_FIPS_3401_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",40.43333333333333],PARAMETER["Standard_Parallel_2",41.7],PARAMETER["Latitude_Of_Origin",39.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+34013,PROJCS["NAD_1983_HARN_StatePlane_Ohio_North_FIPS_3401_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",40.43333333333333],PARAMETER["Standard_Parallel_2",41.7],PARAMETER["Latitude_Of_Origin",39.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+34014,PROJCS["NAD_1927_StatePlane_Ohio_North_FIPS_3401",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",40.43333333333333],PARAMETER["Standard_Parallel_2",41.7],PARAMETER["Latitude_Of_Origin",39.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+34020,PROJCS["NAD_1983_HARN_StatePlane_Ohio_South_FIPS_3402",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",38.73333333333333],PARAMETER["Standard_Parallel_2",40.03333333333333],PARAMETER["Latitude_Of_Origin",38],UNIT["Meter",1]]
+34021,PROJCS["NAD_1983_StatePlane_Ohio_South_FIPS_3402",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",38.73333333333333],PARAMETER["Standard_Parallel_2",40.03333333333333],PARAMETER["Latitude_Of_Origin",38],UNIT["Meter",1]]
+34022,PROJCS["NAD_1983_StatePlane_Ohio_South_FIPS_3402_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",38.73333333333333],PARAMETER["Standard_Parallel_2",40.03333333333333],PARAMETER["Latitude_Of_Origin",38],UNIT["Foot_US",0.304800609601219241]]
+34023,PROJCS["NAD_1983_HARN_StatePlane_Ohio_South_FIPS_3402_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",38.73333333333333],PARAMETER["Standard_Parallel_2",40.03333333333333],PARAMETER["Latitude_Of_Origin",38.0],UNIT["Foot_US",0.3048006096012192]]
+34024,PROJCS["NAD_1927_StatePlane_Ohio_South_FIPS_3402",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-82.5],PARAMETER["Standard_Parallel_1",38.73333333333333],PARAMETER["Standard_Parallel_2",40.03333333333333],PARAMETER["Latitude_Of_Origin",38],UNIT["Foot_US",0.304800609601219241]]
+35010,PROJCS["NAD_1983_HARN_StatePlane_Oklahoma_North_FIPS_3501",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",35.56666666666667],PARAMETER["Standard_Parallel_2",36.76666666666667],PARAMETER["Latitude_Of_Origin",35],UNIT["Meter",1]]
+35011,PROJCS["NAD_1983_StatePlane_Oklahoma_North_FIPS_3501",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",35.56666666666667],PARAMETER["Standard_Parallel_2",36.76666666666667],PARAMETER["Latitude_Of_Origin",35],UNIT["Meter",1]]
+35012,PROJCS["NAD_1983_StatePlane_Oklahoma_North_FIPS_3501_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",35.56666666666667],PARAMETER["Standard_Parallel_2",36.76666666666667],PARAMETER["Latitude_Of_Origin",35],UNIT["Foot_US",0.304800609601219241]]
+35013,PROJCS["NAD_1983_HARN_StatePlane_Oklahoma_North_FIPS_3501_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-98.0],PARAMETER["Standard_Parallel_1",35.56666666666667],PARAMETER["Standard_Parallel_2",36.76666666666667],PARAMETER["Latitude_Of_Origin",35.0],UNIT["Foot_US",0.3048006096012192]]
+35014,PROJCS["NAD_1927_StatePlane_Oklahoma_North_FIPS_3501",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",35.56666666666667],PARAMETER["Standard_Parallel_2",36.76666666666667],PARAMETER["Latitude_Of_Origin",35],UNIT["Foot_US",0.304800609601219241]]
+35020,PROJCS["NAD_1983_HARN_StatePlane_Oklahoma_South_FIPS_3502",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",33.93333333333333],PARAMETER["Standard_Parallel_2",35.23333333333333],PARAMETER["Latitude_Of_Origin",33.33333333333334],UNIT["Meter",1]]
+35021,PROJCS["NAD_1983_StatePlane_Oklahoma_South_FIPS_3502",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",33.93333333333333],PARAMETER["Standard_Parallel_2",35.23333333333333],PARAMETER["Latitude_Of_Origin",33.33333333333334],UNIT["Meter",1]]
+35022,PROJCS["NAD_1983_StatePlane_Oklahoma_South_FIPS_3502_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",33.93333333333333],PARAMETER["Standard_Parallel_2",35.23333333333333],PARAMETER["Latitude_Of_Origin",33.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+35023,PROJCS["NAD_1983_HARN_StatePlane_Oklahoma_South_FIPS_3502_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-98.0],PARAMETER["Standard_Parallel_1",33.93333333333333],PARAMETER["Standard_Parallel_2",35.23333333333333],PARAMETER["Latitude_Of_Origin",33.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+35024,PROJCS["NAD_1927_StatePlane_Oklahoma_South_FIPS_3502",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98],PARAMETER["Standard_Parallel_1",33.93333333333333],PARAMETER["Standard_Parallel_2",35.23333333333333],PARAMETER["Latitude_Of_Origin",33.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+36010,PROJCS["NAD_1983_HARN_StatePlane_Oregon_North_FIPS_3601",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",44.33333333333334],PARAMETER["Standard_Parallel_2",46],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Meter",1]]
+36011,PROJCS["NAD_1983_StatePlane_Oregon_North_FIPS_3601",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",44.33333333333334],PARAMETER["Standard_Parallel_2",46],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Meter",1]]
+36012,PROJCS["NAD_1983_StatePlane_Oregon_North_FIPS_3601_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",8202083.333333332],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",44.33333333333334],PARAMETER["Standard_Parallel_2",46],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+36013,PROJCS["NAD_1983_HARN_StatePlane_Oregon_North_FIPS_3601_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",8202099.737532808],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",44.33333333333334],PARAMETER["Standard_Parallel_2",46.0],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Foot",0.3048]]
+36014,PROJCS["NAD_1927_StatePlane_Oregon_North_FIPS_3601",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",44.33333333333334],PARAMETER["Standard_Parallel_2",46],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+36015,PROJCS["NAD_1983_HARN_StatePlane_Oregon_North_FIPS_3601_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",8202099.737532808],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",44.33333333333334],PARAMETER["Standard_Parallel_2",46.0],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Foot",0.3048]]
+36016,PROJCS["NAD_1983_StatePlane_Oregon_North_FIPS_3601_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",8202099.737532808],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",44.33333333333334],PARAMETER["Standard_Parallel_2",46.0],PARAMETER["Latitude_Of_Origin",43.66666666666666],UNIT["Foot",0.3048]]
+36020,PROJCS["NAD_1983_HARN_StatePlane_Oregon_South_FIPS_3602",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",42.33333333333334],PARAMETER["Standard_Parallel_2",44],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+36021,PROJCS["NAD_1983_StatePlane_Oregon_South_FIPS_3602",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",42.33333333333334],PARAMETER["Standard_Parallel_2",44],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Meter",1]]
+36022,PROJCS["NAD_1983_StatePlane_Oregon_South_FIPS_3602_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921249.999999999],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",42.33333333333334],PARAMETER["Standard_Parallel_2",44],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+36023,PROJCS["NAD_1983_HARN_StatePlane_Oregon_South_FIPS_3602_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921259.842519685],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",42.33333333333334],PARAMETER["Standard_Parallel_2",44.0],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot",0.3048]]
+36024,PROJCS["NAD_1927_StatePlane_Oregon_South_FIPS_3602",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",42.33333333333334],PARAMETER["Standard_Parallel_2",44],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+36025,PROJCS["NAD_1983_HARN_StatePlane_Oregon_South_FIPS_3602_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921259.842519685],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",42.33333333333334],PARAMETER["Standard_Parallel_2",44.0],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot",0.3048]]
+36026,PROJCS["NAD_1983_StatePlane_Oregon_South_FIPS_3602_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",4921259.842519685],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",42.33333333333334],PARAMETER["Standard_Parallel_2",44.0],PARAMETER["Latitude_Of_Origin",41.66666666666666],UNIT["Foot",0.3048]]
+37010,PROJCS["NAD_1983_HARN_StatePlane_Pennsylvania_North_FIPS_3701",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",40.88333333333333],PARAMETER["Standard_Parallel_2",41.95],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Meter",1.0]]
+37011,PROJCS["NAD_1983_StatePlane_Pennsylvania_North_FIPS_3701",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",40.88333333333333],PARAMETER["Standard_Parallel_2",41.95],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Meter",1]]
+37012,PROJCS["NAD_1983_StatePlane_Pennsylvania_North_FIPS_3701_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",40.88333333333333],PARAMETER["Standard_Parallel_2",41.95],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+37013,PROJCS["NAD_1983_HARN_StatePlane_Pennsylvania_North_FIPS_3701_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",40.88333333333333],PARAMETER["Standard_Parallel_2",41.95],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Foot_US",0.3048006096012192]]
+37014,PROJCS["NAD_1927_StatePlane_Pennsylvania_North_FIPS_3701",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",40.88333333333333],PARAMETER["Standard_Parallel_2",41.95],PARAMETER["Latitude_Of_Origin",40.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+37020,PROJCS["NAD_1983_HARN_StatePlane_Pennsylvania_South_FIPS_3702",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",39.93333333333333],PARAMETER["Standard_Parallel_2",40.96666666666667],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Meter",1.0]]
+37021,PROJCS["NAD_1983_StatePlane_Pennsylvania_South_FIPS_3702",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",39.93333333333333],PARAMETER["Standard_Parallel_2",40.96666666666667],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Meter",1]]
+37022,PROJCS["NAD_1983_StatePlane_Pennsylvania_South_FIPS_3702_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",39.93333333333333],PARAMETER["Standard_Parallel_2",40.96666666666667],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+37023,PROJCS["NAD_1983_HARN_StatePlane_Pennsylvania_South_FIPS_3702_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",39.93333333333333],PARAMETER["Standard_Parallel_2",40.96666666666667],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+37024,PROJCS["NAD_1927_StatePlane_Pennsylvania_South_FIPS_3702",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-77.75],PARAMETER["Standard_Parallel_1",39.93333333333333],PARAMETER["Standard_Parallel_2",40.96666666666667],PARAMETER["Latitude_Of_Origin",39.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+38000,PROJCS["NAD_1983_HARN_StatePlane_Rhode_Island_FIPS_3800",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",100000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Scale_Factor",0.99999375],PARAMETER["Latitude_Of_Origin",41.08333333333334],UNIT["Meter",1]]
+38001,PROJCS["NAD_1983_StatePlane_Rhode_Island_FIPS_3800",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",100000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Scale_Factor",0.99999375],PARAMETER["Latitude_Of_Origin",41.08333333333334],UNIT["Meter",1]]
+38002,PROJCS["NAD_1983_StatePlane_Rhode_Island_FIPS_3800_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",328083.3333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Scale_Factor",0.99999375],PARAMETER["Latitude_Of_Origin",41.08333333333334],UNIT["Foot_US",0.304800609601219241]]
+38003,PROJCS["NAD_1983_HARN_StatePlane_Rhode_Island_FIPS_3800_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",328083.3333333333],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Scale_Factor",0.99999375],PARAMETER["Latitude_Of_Origin",41.08333333333334],UNIT["Foot_US",0.3048006096012192]]
+38004,PROJCS["NAD_1927_StatePlane_Rhode_Island_FIPS_3800",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Scale_Factor",0.99999375],PARAMETER["Latitude_Of_Origin",41.08333333333334],UNIT["Foot_US",0.304800609601219241]]
+39000,PROJCS["NAD_1983_HARN_StatePlane_South_Carolina_FIPS_3900",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",609600.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-81.0],PARAMETER["Standard_Parallel_1",32.5],PARAMETER["Standard_Parallel_2",34.83333333333334],PARAMETER["Latitude_Of_Origin",31.83333333333333],UNIT["Meter",1.0]]
+39001,PROJCS["NAD_1983_StatePlane_South_Carolina_FIPS_3900",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",609600],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",32.5],PARAMETER["Standard_Parallel_2",34.83333333333334],PARAMETER["Latitude_Of_Origin",31.83333333333333],UNIT["Meter",1]]
+39002,PROJCS["NAD_1983_StatePlane_South_Carolina_FIPS_3900_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1999996],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",32.5],PARAMETER["Standard_Parallel_2",34.83333333333334],PARAMETER["Latitude_Of_Origin",31.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+39003,PROJCS["NAD_1983_HARN_StatePlane_South_Carolina_FIPS_3900_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-81.0],PARAMETER["Standard_Parallel_1",32.5],PARAMETER["Standard_Parallel_2",34.83333333333334],PARAMETER["Latitude_Of_Origin",31.83333333333333],UNIT["Foot",0.3048]]
+39005,PROJCS["NAD_1983_HARN_StatePlane_South_Carolina_FIPS_3900_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-81.0],PARAMETER["Standard_Parallel_1",32.5],PARAMETER["Standard_Parallel_2",34.83333333333334],PARAMETER["Latitude_Of_Origin",31.83333333333333],UNIT["Foot",0.3048]]
+39006,PROJCS["NAD_1983_StatePlane_South_Carolina_FIPS_3900_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-81.0],PARAMETER["Standard_Parallel_1",32.5],PARAMETER["Standard_Parallel_2",34.83333333333334],PARAMETER["Latitude_Of_Origin",31.83333333333333],UNIT["Foot",0.3048]]
+39014,PROJCS["NAD_1927_StatePlane_South_Carolina_North_FIPS_3901",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",33.76666666666667],PARAMETER["Standard_Parallel_2",34.96666666666667],PARAMETER["Latitude_Of_Origin",33],UNIT["Foot_US",0.304800609601219241]]
+39024,PROJCS["NAD_1927_StatePlane_South_Carolina_South_FIPS_3902",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",32.33333333333334],PARAMETER["Standard_Parallel_2",33.66666666666666],PARAMETER["Latitude_Of_Origin",31.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+40010,PROJCS["NAD_1983_HARN_StatePlane_South_Dakota_North_FIPS_4001",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",44.41666666666666],PARAMETER["Standard_Parallel_2",45.68333333333333],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Meter",1]]
+40011,PROJCS["NAD_1983_StatePlane_South_Dakota_North_FIPS_4001",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",44.41666666666666],PARAMETER["Standard_Parallel_2",45.68333333333333],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Meter",1]]
+40012,PROJCS["NAD_1983_StatePlane_South_Dakota_North_FIPS_4001_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",44.41666666666666],PARAMETER["Standard_Parallel_2",45.68333333333333],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+40013,PROJCS["NAD_1983_HARN_StatePlane_South_Dakota_North_FIPS_4001_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.0],PARAMETER["Standard_Parallel_1",44.41666666666666],PARAMETER["Standard_Parallel_2",45.68333333333333],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Foot_US",0.3048006096012192]]
+40014,PROJCS["NAD_1927_StatePlane_South_Dakota_North_FIPS_4001",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100],PARAMETER["Standard_Parallel_1",44.41666666666666],PARAMETER["Standard_Parallel_2",45.68333333333333],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+40020,PROJCS["NAD_1983_HARN_StatePlane_South_Dakota_South_FIPS_4002",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",42.83333333333334],PARAMETER["Standard_Parallel_2",44.4],PARAMETER["Latitude_Of_Origin",42.33333333333334],UNIT["Meter",1]]
+40021,PROJCS["NAD_1983_StatePlane_South_Dakota_South_FIPS_4002",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",42.83333333333334],PARAMETER["Standard_Parallel_2",44.4],PARAMETER["Latitude_Of_Origin",42.33333333333334],UNIT["Meter",1]]
+40022,PROJCS["NAD_1983_StatePlane_South_Dakota_South_FIPS_4002_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",42.83333333333334],PARAMETER["Standard_Parallel_2",44.4],PARAMETER["Latitude_Of_Origin",42.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+40023,PROJCS["NAD_1983_HARN_StatePlane_South_Dakota_South_FIPS_4002_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",42.83333333333334],PARAMETER["Standard_Parallel_2",44.4],PARAMETER["Latitude_Of_Origin",42.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+40024,PROJCS["NAD_1927_StatePlane_South_Dakota_South_FIPS_4002",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",42.83333333333334],PARAMETER["Standard_Parallel_2",44.4],PARAMETER["Latitude_Of_Origin",42.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+41000,PROJCS["NAD_1983_HARN_StatePlane_Tennessee_FIPS_4100",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-86],PARAMETER["Standard_Parallel_1",35.25],PARAMETER["Standard_Parallel_2",36.41666666666666],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Meter",1]]
+41001,PROJCS["NAD_1983_StatePlane_Tennessee_FIPS_4100",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-86],PARAMETER["Standard_Parallel_1",35.25],PARAMETER["Standard_Parallel_2",36.41666666666666],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Meter",1]]
+41002,PROJCS["NAD_1983_StatePlane_Tennessee_FIPS_4100_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-86],PARAMETER["Standard_Parallel_1",35.25],PARAMETER["Standard_Parallel_2",36.41666666666666],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+41003,PROJCS["NAD_1983_HARN_StatePlane_Tennessee_FIPS_4100_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-86.0],PARAMETER["Standard_Parallel_1",35.25],PARAMETER["Standard_Parallel_2",36.41666666666666],PARAMETER["Latitude_Of_Origin",34.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+41004,PROJCS["NAD_1927_StatePlane_Tennessee_FIPS_4100",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-86],PARAMETER["Standard_Parallel_1",35.25],PARAMETER["Standard_Parallel_2",36.41666666666666],PARAMETER["Latitude_Of_Origin",34.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+42010,PROJCS["NAD_1983_HARN_StatePlane_Texas_North_FIPS_4201",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",1000000],PARAMETER["Central_Meridian",-101.5],PARAMETER["Standard_Parallel_1",34.65],PARAMETER["Standard_Parallel_2",36.18333333333333],PARAMETER["Latitude_Of_Origin",34],UNIT["Meter",1]]
+42011,PROJCS["NAD_1983_StatePlane_Texas_North_FIPS_4201",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",1000000],PARAMETER["Central_Meridian",-101.5],PARAMETER["Standard_Parallel_1",34.65],PARAMETER["Standard_Parallel_2",36.18333333333333],PARAMETER["Latitude_Of_Origin",34],UNIT["Meter",1]]
+42012,PROJCS["NAD_1983_StatePlane_Texas_North_FIPS_4201_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-101.5],PARAMETER["Standard_Parallel_1",34.65],PARAMETER["Standard_Parallel_2",36.18333333333333],PARAMETER["Latitude_Of_Origin",34],UNIT["Foot_US",0.304800609601219241]]
+42013,PROJCS["NAD_1983_HARN_StatePlane_Texas_North_FIPS_4201_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-101.5],PARAMETER["Standard_Parallel_1",34.65],PARAMETER["Standard_Parallel_2",36.18333333333333],PARAMETER["Latitude_Of_Origin",34.0],UNIT["Foot_US",0.3048006096012192]]
+42014,PROJCS["NAD_1927_StatePlane_Texas_North_FIPS_4201",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-101.5],PARAMETER["Standard_Parallel_1",34.65],PARAMETER["Standard_Parallel_2",36.18333333333333],PARAMETER["Latitude_Of_Origin",34],UNIT["Foot_US",0.304800609601219241]]
+42020,PROJCS["NAD_1983_HARN_StatePlane_Texas_North_Central_FIPS_4202",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",2000000],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",32.13333333333333],PARAMETER["Standard_Parallel_2",33.96666666666667],PARAMETER["Latitude_Of_Origin",31.66666666666667],UNIT["Meter",1]]
+42021,PROJCS["NAD_1983_StatePlane_Texas_North_Central_FIPS_4202",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",2000000],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",32.13333333333333],PARAMETER["Standard_Parallel_2",33.96666666666667],PARAMETER["Latitude_Of_Origin",31.66666666666667],UNIT["Meter",1]]
+42022,PROJCS["NAD_1983_StatePlane_Texas_North_Central_FIPS_4202_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",6561666.666666666],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",32.13333333333333],PARAMETER["Standard_Parallel_2",33.96666666666667],PARAMETER["Latitude_Of_Origin",31.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+42023,PROJCS["NAD_1983_HARN_StatePlane_Texas_North_Central_FIPS_4202_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",6561666.666666666],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",32.13333333333333],PARAMETER["Standard_Parallel_2",33.96666666666667],PARAMETER["Latitude_Of_Origin",31.66666666666667],UNIT["Foot_US",0.3048006096012192]]
+42024,PROJCS["NAD_1927_StatePlane_Texas_North_Central_FIPS_4202",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-97.5],PARAMETER["Standard_Parallel_1",32.13333333333333],PARAMETER["Standard_Parallel_2",33.96666666666667],PARAMETER["Latitude_Of_Origin",31.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+42030,PROJCS["NAD_1983_HARN_StatePlane_Texas_Central_FIPS_4203",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",3000000],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",30.11666666666667],PARAMETER["Standard_Parallel_2",31.88333333333333],PARAMETER["Latitude_Of_Origin",29.66666666666667],UNIT["Meter",1]]
+42031,PROJCS["NAD_1983_StatePlane_Texas_Central_FIPS_4203",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",3000000],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",30.11666666666667],PARAMETER["Standard_Parallel_2",31.88333333333333],PARAMETER["Latitude_Of_Origin",29.66666666666667],UNIT["Meter",1]]
+42032,PROJCS["NAD_1983_StatePlane_Texas_Central_FIPS_4203_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",9842499.999999998],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",30.11666666666667],PARAMETER["Standard_Parallel_2",31.88333333333333],PARAMETER["Latitude_Of_Origin",29.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+42033,PROJCS["NAD_1983_HARN_StatePlane_Texas_Central_FIPS_4203_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2296583.333333333],PARAMETER["False_Northing",9842500.0],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",30.11666666666667],PARAMETER["Standard_Parallel_2",31.88333333333333],PARAMETER["Latitude_Of_Origin",29.66666666666667],UNIT["Foot_US",0.3048006096012192]]
+42034,PROJCS["NAD_1927_StatePlane_Texas_Central_FIPS_4203",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-100.3333333333333],PARAMETER["Standard_Parallel_1",30.11666666666667],PARAMETER["Standard_Parallel_2",31.88333333333333],PARAMETER["Latitude_Of_Origin",29.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+42040,PROJCS["NAD_1983_HARN_StatePlane_Texas_South_Central_FIPS_4204",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",4000000],PARAMETER["Central_Meridian",-99],PARAMETER["Standard_Parallel_1",28.38333333333333],PARAMETER["Standard_Parallel_2",30.28333333333333],PARAMETER["Latitude_Of_Origin",27.83333333333333],UNIT["Meter",1]]
+42041,PROJCS["NAD_1983_StatePlane_Texas_South_Central_FIPS_4204",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",4000000],PARAMETER["Central_Meridian",-99],PARAMETER["Standard_Parallel_1",28.38333333333333],PARAMETER["Standard_Parallel_2",30.28333333333333],PARAMETER["Latitude_Of_Origin",27.83333333333333],UNIT["Meter",1]]
+42042,PROJCS["NAD_1983_StatePlane_Texas_South_Central_FIPS_4204_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",13123333.33333333],PARAMETER["Central_Meridian",-99],PARAMETER["Standard_Parallel_1",28.38333333333333],PARAMETER["Standard_Parallel_2",30.28333333333333],PARAMETER["Latitude_Of_Origin",27.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+42043,PROJCS["NAD_1983_HARN_StatePlane_Texas_South_Central_FIPS_4204_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",13123333.33333333],PARAMETER["Central_Meridian",-99.0],PARAMETER["Standard_Parallel_1",28.38333333333333],PARAMETER["Standard_Parallel_2",30.28333333333333],PARAMETER["Latitude_Of_Origin",27.83333333333333],UNIT["Foot_US",0.3048006096012192]]
+42044,PROJCS["NAD_1927_StatePlane_Texas_South_Central_FIPS_4204",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-99],PARAMETER["Standard_Parallel_1",28.38333333333333],PARAMETER["Standard_Parallel_2",30.28333333333333],PARAMETER["Latitude_Of_Origin",27.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+42050,PROJCS["NAD_1983_HARN_StatePlane_Texas_South_FIPS_4205",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",5000000],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.66666666666667],UNIT["Meter",1]]
+42051,PROJCS["NAD_1983_StatePlane_Texas_South_FIPS_4205",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",300000],PARAMETER["False_Northing",5000000],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.66666666666667],UNIT["Meter",1]]
+42052,PROJCS["NAD_1983_StatePlane_Texas_South_FIPS_4205_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",984249.9999999999],PARAMETER["False_Northing",16404166.66666666],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+42053,PROJCS["NAD_1983_HARN_StatePlane_Texas_South_FIPS_4205_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",984250.0],PARAMETER["False_Northing",16404166.66666666],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.66666666666667],UNIT["Foot_US",0.3048006096012192]]
+42054,PROJCS["NAD_1927_StatePlane_Texas_South_FIPS_4205",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-98.5],PARAMETER["Standard_Parallel_1",26.16666666666667],PARAMETER["Standard_Parallel_2",27.83333333333333],PARAMETER["Latitude_Of_Origin",25.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+43010,PROJCS["NAD_1983_HARN_StatePlane_Utah_North_FIPS_4301",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",1000000],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",40.71666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.33333333333334],UNIT["Meter",1]]
+43011,PROJCS["NAD_1983_StatePlane_Utah_North_FIPS_4301",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",1000000],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",40.71666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.33333333333334],UNIT["Meter",1]]
+43012,PROJCS["NAD_1983_StatePlane_Utah_North_FIPS_4301_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",40.71666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+43013,PROJCS["NAD_1983_HARN_StatePlane_Utah_North_FIPS_4301_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",40.71666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+43014,PROJCS["NAD_1927_StatePlane_Utah_North_FIPS_4301",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",40.71666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+43015,PROJCS["NAD_1983_HARN_StatePlane_Utah_North_FIPS_4301_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640419.947506561],PARAMETER["False_Northing",3280839.895013123],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",40.71666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.33333333333334],UNIT["Foot",0.3048]]
+43016,PROJCS["NAD_1983_StatePlane_Utah_North_FIPS_4301_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640419.947506561],PARAMETER["False_Northing",3280839.895013123],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",40.71666666666667],PARAMETER["Standard_Parallel_2",41.78333333333333],PARAMETER["Latitude_Of_Origin",40.33333333333334],UNIT["Foot",0.3048]]
+43020,PROJCS["NAD_1983_HARN_StatePlane_Utah_Central_FIPS_4302",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",2000000],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",39.01666666666667],PARAMETER["Standard_Parallel_2",40.65],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Meter",1]]
+43021,PROJCS["NAD_1983_StatePlane_Utah_Central_FIPS_4302",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",2000000],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",39.01666666666667],PARAMETER["Standard_Parallel_2",40.65],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Meter",1]]
+43022,PROJCS["NAD_1983_StatePlane_Utah_Central_FIPS_4302_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",6561666.666666666],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",39.01666666666667],PARAMETER["Standard_Parallel_2",40.65],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+43023,PROJCS["NAD_1983_HARN_StatePlane_Utah_Central_FIPS_4302_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",6561666.666666666],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",39.01666666666667],PARAMETER["Standard_Parallel_2",40.65],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+43024,PROJCS["NAD_1927_StatePlane_Utah_Central_FIPS_4302",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",39.01666666666667],PARAMETER["Standard_Parallel_2",40.65],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+43025,PROJCS["NAD_1983_HARN_StatePlane_Utah_Central_FIPS_4302_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640419.947506561],PARAMETER["False_Northing",6561679.790026246],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",39.01666666666667],PARAMETER["Standard_Parallel_2",40.65],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot",0.3048]]
+43026,PROJCS["NAD_1983_StatePlane_Utah_Central_FIPS_4302_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640419.947506561],PARAMETER["False_Northing",6561679.790026246],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",39.01666666666667],PARAMETER["Standard_Parallel_2",40.65],PARAMETER["Latitude_Of_Origin",38.33333333333334],UNIT["Foot",0.3048]]
+43030,PROJCS["NAD_1983_HARN_StatePlane_Utah_South_FIPS_4303",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",3000000],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",37.21666666666667],PARAMETER["Standard_Parallel_2",38.35],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+43031,PROJCS["NAD_1983_StatePlane_Utah_South_FIPS_4303",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",3000000],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",37.21666666666667],PARAMETER["Standard_Parallel_2",38.35],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Meter",1]]
+43032,PROJCS["NAD_1983_StatePlane_Utah_South_FIPS_4303_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",9842499.999999998],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",37.21666666666667],PARAMETER["Standard_Parallel_2",38.35],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+43033,PROJCS["NAD_1983_HARN_StatePlane_Utah_South_FIPS_4303_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",9842500.0],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",37.21666666666667],PARAMETER["Standard_Parallel_2",38.35],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+43034,PROJCS["NAD_1927_StatePlane_Utah_South_FIPS_4303",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",37.21666666666667],PARAMETER["Standard_Parallel_2",38.35],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+43035,PROJCS["NAD_1983_HARN_StatePlane_Utah_South_FIPS_4303_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640419.947506561],PARAMETER["False_Northing",9842519.685039369],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",37.21666666666667],PARAMETER["Standard_Parallel_2",38.35],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot",0.3048]]
+43036,PROJCS["NAD_1983_StatePlane_Utah_South_FIPS_4303_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640419.947506561],PARAMETER["False_Northing",9842519.685039369],PARAMETER["Central_Meridian",-111.5],PARAMETER["Standard_Parallel_1",37.21666666666667],PARAMETER["Standard_Parallel_2",38.35],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot",0.3048]]
+44000,PROJCS["NAD_1983_HARN_StatePlane_Vermont_FIPS_4400",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-72.5],PARAMETER["Scale_Factor",0.9999642857142857],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Meter",1]]
+44001,PROJCS["NAD_1983_StatePlane_Vermont_FIPS_4400",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-72.5],PARAMETER["Scale_Factor",0.9999642857142857],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Meter",1]]
+44002,PROJCS["NAD_1983_StatePlane_Vermont_FIPS_4400_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-72.5],PARAMETER["Scale_Factor",0.9999642857142857],PARAMETER["Latitude_Of_Origin",42.5],UNIT["Foot_US",0.304800609601219241]]
+45010,PROJCS["NAD_1983_HARN_StatePlane_Virginia_North_FIPS_4501",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3500000],PARAMETER["False_Northing",2000000],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",38.03333333333333],PARAMETER["Standard_Parallel_2",39.2],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Meter",1]]
+45011,PROJCS["NAD_1983_StatePlane_Virginia_North_FIPS_4501",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3500000],PARAMETER["False_Northing",2000000],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",38.03333333333333],PARAMETER["Standard_Parallel_2",39.2],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Meter",1]]
+45012,PROJCS["NAD_1983_StatePlane_Virginia_North_FIPS_4501_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",11482916.66666666],PARAMETER["False_Northing",6561666.666666666],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",38.03333333333333],PARAMETER["Standard_Parallel_2",39.2],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+45013,PROJCS["NAD_1983_HARN_StatePlane_Virginia_North_FIPS_4501_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",11482916.66666666],PARAMETER["False_Northing",6561666.666666666],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",38.03333333333333],PARAMETER["Standard_Parallel_2",39.2],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.3048006096012192]]
+45014,PROJCS["NAD_1927_StatePlane_Virginia_North_FIPS_4501",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",38.03333333333333],PARAMETER["Standard_Parallel_2",39.2],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+45020,PROJCS["NAD_1983_HARN_StatePlane_Virginia_South_FIPS_4502",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3500000],PARAMETER["False_Northing",1000000],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",36.76666666666667],PARAMETER["Standard_Parallel_2",37.96666666666667],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Meter",1]]
+45021,PROJCS["NAD_1983_StatePlane_Virginia_South_FIPS_4502",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3500000],PARAMETER["False_Northing",1000000],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",36.76666666666667],PARAMETER["Standard_Parallel_2",37.96666666666667],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Meter",1]]
+45022,PROJCS["NAD_1983_StatePlane_Virginia_South_FIPS_4502_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",11482916.66666666],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",36.76666666666667],PARAMETER["Standard_Parallel_2",37.96666666666667],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+45023,PROJCS["NAD_1983_HARN_StatePlane_Virginia_South_FIPS_4502_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",11482916.66666666],PARAMETER["False_Northing",3280833.333333333],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",36.76666666666667],PARAMETER["Standard_Parallel_2",37.96666666666667],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+45024,PROJCS["NAD_1927_StatePlane_Virginia_South_FIPS_4502",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-78.5],PARAMETER["Standard_Parallel_1",36.76666666666667],PARAMETER["Standard_Parallel_2",37.96666666666667],PARAMETER["Latitude_Of_Origin",36.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+46010,PROJCS["NAD_1983_HARN_StatePlane_Washington_North_FIPS_4601",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.8333333333333],PARAMETER["Standard_Parallel_1",47.5],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Meter",1]]
+46011,PROJCS["NAD_1983_StatePlane_Washington_North_FIPS_4601",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.8333333333333],PARAMETER["Standard_Parallel_1",47.5],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Meter",1]]
+46012,PROJCS["NAD_1983_StatePlane_Washington_North_FIPS_4601_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.8333333333333],PARAMETER["Standard_Parallel_1",47.5],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Foot_US",0.304800609601219241]]
+46013,PROJCS["NAD_1983_HARN_StatePlane_Washington_North_FIPS_4601_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.8333333333333],PARAMETER["Standard_Parallel_1",47.5],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47.0],UNIT["Foot_US",0.3048006096012192]]
+46014,PROJCS["NAD_1927_StatePlane_Washington_North_FIPS_4601",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.8333333333333],PARAMETER["Standard_Parallel_1",47.5],PARAMETER["Standard_Parallel_2",48.73333333333333],PARAMETER["Latitude_Of_Origin",47],UNIT["Foot_US",0.304800609601219241]]
+46020,PROJCS["NAD_1983_HARN_StatePlane_Washington_South_FIPS_4602",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",45.83333333333334],PARAMETER["Standard_Parallel_2",47.33333333333334],PARAMETER["Latitude_Of_Origin",45.33333333333334],UNIT["Meter",1]]
+46021,PROJCS["NAD_1983_StatePlane_Washington_South_FIPS_4602",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",45.83333333333334],PARAMETER["Standard_Parallel_2",47.33333333333334],PARAMETER["Latitude_Of_Origin",45.33333333333334],UNIT["Meter",1]]
+46022,PROJCS["NAD_1983_StatePlane_Washington_South_FIPS_4602_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",45.83333333333334],PARAMETER["Standard_Parallel_2",47.33333333333334],PARAMETER["Latitude_Of_Origin",45.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+46023,PROJCS["NAD_1983_HARN_StatePlane_Washington_South_FIPS_4602_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",45.83333333333334],PARAMETER["Standard_Parallel_2",47.33333333333334],PARAMETER["Latitude_Of_Origin",45.33333333333334],UNIT["Foot_US",0.3048006096012192]]
+46024,PROJCS["NAD_1927_StatePlane_Washington_South_FIPS_4602",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",45.83333333333334],PARAMETER["Standard_Parallel_2",47.33333333333334],PARAMETER["Latitude_Of_Origin",45.33333333333334],UNIT["Foot_US",0.304800609601219241]]
+47010,PROJCS["NAD_1983_HARN_StatePlane_West_Virginia_North_FIPS_4701",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-79.5],PARAMETER["Standard_Parallel_1",39],PARAMETER["Standard_Parallel_2",40.25],PARAMETER["Latitude_Of_Origin",38.5],UNIT["Meter",1]]
+47011,PROJCS["NAD_1983_StatePlane_West_Virginia_North_FIPS_4701",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-79.5],PARAMETER["Standard_Parallel_1",39],PARAMETER["Standard_Parallel_2",40.25],PARAMETER["Latitude_Of_Origin",38.5],UNIT["Meter",1]]
+47012,PROJCS["NAD_1983_StatePlane_West_Virginia_North_FIPS_4701_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-79.5],PARAMETER["Standard_Parallel_1",39],PARAMETER["Standard_Parallel_2",40.25],PARAMETER["Latitude_Of_Origin",38.5],UNIT["Foot_US",0.304800609601219241]]
+47014,PROJCS["NAD_1927_StatePlane_West_Virginia_North_FIPS_4701",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-79.5],PARAMETER["Standard_Parallel_1",39],PARAMETER["Standard_Parallel_2",40.25],PARAMETER["Latitude_Of_Origin",38.5],UNIT["Foot_US",0.304800609601219241]]
+47020,PROJCS["NAD_1983_HARN_StatePlane_West_Virginia_South_FIPS_4702",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",37.48333333333333],PARAMETER["Standard_Parallel_2",38.88333333333333],PARAMETER["Latitude_Of_Origin",37],UNIT["Meter",1]]
+47021,PROJCS["NAD_1983_StatePlane_West_Virginia_South_FIPS_4702",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",37.48333333333333],PARAMETER["Standard_Parallel_2",38.88333333333333],PARAMETER["Latitude_Of_Origin",37],UNIT["Meter",1]]
+47022,PROJCS["NAD_1983_StatePlane_West_Virginia_South_FIPS_4702_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",37.48333333333333],PARAMETER["Standard_Parallel_2",38.88333333333333],PARAMETER["Latitude_Of_Origin",37],UNIT["Foot_US",0.304800609601219241]]
+47024,PROJCS["NAD_1927_StatePlane_West_Virginia_South_FIPS_4702",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-81],PARAMETER["Standard_Parallel_1",37.48333333333333],PARAMETER["Standard_Parallel_2",38.88333333333333],PARAMETER["Latitude_Of_Origin",37],UNIT["Foot_US",0.304800609601219241]]
+48010,PROJCS["NAD_1983_HARN_StatePlane_Wisconsin_North_FIPS_4801",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",45.56666666666667],PARAMETER["Standard_Parallel_2",46.76666666666667],PARAMETER["Latitude_Of_Origin",45.16666666666666],UNIT["Meter",1]]
+48011,PROJCS["NAD_1983_StatePlane_Wisconsin_North_FIPS_4801",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",45.56666666666667],PARAMETER["Standard_Parallel_2",46.76666666666667],PARAMETER["Latitude_Of_Origin",45.16666666666666],UNIT["Meter",1]]
+48012,PROJCS["NAD_1983_StatePlane_Wisconsin_North_FIPS_4801_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",45.56666666666667],PARAMETER["Standard_Parallel_2",46.76666666666667],PARAMETER["Latitude_Of_Origin",45.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+48013,PROJCS["NAD_1983_HARN_StatePlane_Wisconsin_North_FIPS_4801_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-90.0],PARAMETER["Standard_Parallel_1",45.56666666666667],PARAMETER["Standard_Parallel_2",46.76666666666667],PARAMETER["Latitude_Of_Origin",45.16666666666666],UNIT["Foot_US",0.3048006096012192]]
+48014,PROJCS["NAD_1927_StatePlane_Wisconsin_North_FIPS_4801",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",45.56666666666667],PARAMETER["Standard_Parallel_2",46.76666666666667],PARAMETER["Latitude_Of_Origin",45.16666666666666],UNIT["Foot_US",0.304800609601219241]]
+48020,PROJCS["NAD_1983_HARN_StatePlane_Wisconsin_Central_FIPS_4802",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",44.25],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Meter",1]]
+48021,PROJCS["NAD_1983_StatePlane_Wisconsin_Central_FIPS_4802",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",44.25],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Meter",1]]
+48022,PROJCS["NAD_1983_StatePlane_Wisconsin_Central_FIPS_4802_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",44.25],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+48023,PROJCS["NAD_1983_HARN_StatePlane_Wisconsin_Central_FIPS_4802_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-90.0],PARAMETER["Standard_Parallel_1",44.25],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Foot_US",0.3048006096012192]]
+48024,PROJCS["NAD_1927_StatePlane_Wisconsin_Central_FIPS_4802",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",44.25],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",43.83333333333334],UNIT["Foot_US",0.304800609601219241]]
+48030,PROJCS["NAD_1983_HARN_StatePlane_Wisconsin_South_FIPS_4803",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",42.73333333333333],PARAMETER["Standard_Parallel_2",44.06666666666667],PARAMETER["Latitude_Of_Origin",42],UNIT["Meter",1]]
+48031,PROJCS["NAD_1983_StatePlane_Wisconsin_South_FIPS_4803",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",42.73333333333333],PARAMETER["Standard_Parallel_2",44.06666666666667],PARAMETER["Latitude_Of_Origin",42],UNIT["Meter",1]]
+48032,PROJCS["NAD_1983_StatePlane_Wisconsin_South_FIPS_4803_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",42.73333333333333],PARAMETER["Standard_Parallel_2",44.06666666666667],PARAMETER["Latitude_Of_Origin",42],UNIT["Foot_US",0.304800609601219241]]
+48033,PROJCS["NAD_1983_HARN_StatePlane_Wisconsin_South_FIPS_4803_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-90.0],PARAMETER["Standard_Parallel_1",42.73333333333333],PARAMETER["Standard_Parallel_2",44.06666666666667],PARAMETER["Latitude_Of_Origin",42.0],UNIT["Foot_US",0.3048006096012192]]
+48034,PROJCS["NAD_1927_StatePlane_Wisconsin_South_FIPS_4803",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",2000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-90],PARAMETER["Standard_Parallel_1",42.73333333333333],PARAMETER["Standard_Parallel_2",44.06666666666667],PARAMETER["Latitude_Of_Origin",42],UNIT["Foot_US",0.304800609601219241]]
+49010,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_East_FIPS_4901",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-105.1666666666667],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49011,PROJCS["NAD_1983_StatePlane_Wyoming_East_FIPS_4901",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-105.1666666666667],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49012,PROJCS["NAD_1983_StatePlane_Wyoming_East_FIPS_4901_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-105.1666666666667],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.304800609601219241]]
+49013,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_East_FIPS_4901_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-105.1666666666667],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.3048006096012192]]
+49014,PROJCS["NAD_1927_StatePlane_Wyoming_East_FIPS_4901",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-105.1666666666667],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",40.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+49020,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_East_Central_FIPS_4902",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-107.3333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49021,PROJCS["NAD_1983_StatePlane_Wyoming_East_Central_FIPS_4902",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",400000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-107.3333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49022,PROJCS["NAD_1983_StatePlane_Wyoming_East_Central_FIPS_4902_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-107.3333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.304800609601219241]]
+49023,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_East_Central_FIPS_4902_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1312333.333333333],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-107.3333333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.3048006096012192]]
+49024,PROJCS["NAD_1927_StatePlane_Wyoming_East_Central_FIPS_4902",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-107.3333333333333],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",40.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+49030,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_West_Central_FIPS_4903",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-108.75],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49031,PROJCS["NAD_1983_StatePlane_Wyoming_West_Central_FIPS_4903",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-108.75],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49032,PROJCS["NAD_1983_StatePlane_Wyoming_West_Central_FIPS_4903_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1968500],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-108.75],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.304800609601219241]]
+49033,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_West_Central_FIPS_4903_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-108.75],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.3048006096012192]]
+49034,PROJCS["NAD_1927_StatePlane_Wyoming_West_Central_FIPS_4903",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-108.75],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",40.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+49040,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_West_FIPS_4904",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-110.0833333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49041,PROJCS["NAD_1983_StatePlane_Wyoming_West_FIPS_4904",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",800000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-110.0833333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Meter",1]]
+49042,PROJCS["NAD_1983_StatePlane_Wyoming_West_FIPS_4904_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-110.0833333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.304800609601219241]]
+49043,PROJCS["NAD_1983_HARN_StatePlane_Wyoming_West_FIPS_4904_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2624666.666666666],PARAMETER["False_Northing",328083.3333333333],PARAMETER["Central_Meridian",-110.0833333333333],PARAMETER["Scale_Factor",0.9999375],PARAMETER["Latitude_Of_Origin",40.5],UNIT["Foot_US",0.3048006096012192]]
+49044,PROJCS["NAD_1927_StatePlane_Wyoming_West_FIPS_4904",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-110.0833333333333],PARAMETER["Scale_Factor",0.9999411764705882],PARAMETER["Latitude_Of_Origin",40.66666666666666],UNIT["Foot_US",0.304800609601219241]]
+50011,PROJCS["NAD_1983_StatePlane_Alaska_1_FIPS_5001",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Hotine_Oblique_Mercator_Azimuth_Natural_Origin"],PARAMETER["False_Easting",5000000],PARAMETER["False_Northing",-5000000],PARAMETER["Scale_Factor",0.9999],PARAMETER["Azimuth",-36.86989764583333],PARAMETER["Longitude_Of_Center",-133.6666666666667],PARAMETER["Latitude_Of_Center",57],UNIT["Meter",1]]
+50012,PROJCS["NAD_1983_StatePlane_Alaska_1_FIPS_5001_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Hotine_Oblique_Mercator_Azimuth_Natural_Origin"],PARAMETER["False_Easting",16404166.66666666],PARAMETER["False_Northing",-16404166.66666666],PARAMETER["Scale_Factor",0.9999],PARAMETER["Azimuth",-36.86989764583333],PARAMETER["Longitude_Of_Center",-133.6666666666667],PARAMETER["Latitude_Of_Center",57],UNIT["Foot_US",0.304800609601219241]]
+50014,PROJCS["NAD_1927_StatePlane_Alaska_1_FIPS_5001",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Hotine_Oblique_Mercator_Azimuth_Natural_Origin"],PARAMETER["False_Easting",16404166.666667],PARAMETER["False_Northing",-16404166.666667],PARAMETER["Scale_Factor",0.9999],PARAMETER["Azimuth",-36.86989764583333],PARAMETER["Longitude_Of_Center",-133.6666666666667],PARAMETER["Latitude_Of_Center",57],UNIT["Foot_US",0.304800609601219241]]
+50021,PROJCS["NAD_1983_StatePlane_Alaska_2_FIPS_5002",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-142],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50022,PROJCS["NAD_1983_StatePlane_Alaska_2_FIPS_5002_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-142],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50024,PROJCS["NAD_1927_StatePlane_Alaska_2_FIPS_5002",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-142],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50031,PROJCS["NAD_1983_StatePlane_Alaska_3_FIPS_5003",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-146],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50032,PROJCS["NAD_1983_StatePlane_Alaska_3_FIPS_5003_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-146],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50034,PROJCS["NAD_1927_StatePlane_Alaska_3_FIPS_5003",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-146],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50041,PROJCS["NAD_1983_StatePlane_Alaska_4_FIPS_5004",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-150],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50042,PROJCS["NAD_1983_StatePlane_Alaska_4_FIPS_5004_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-150],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50044,PROJCS["NAD_1927_StatePlane_Alaska_4_FIPS_5004",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-150],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50051,PROJCS["NAD_1983_StatePlane_Alaska_5_FIPS_5005",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-154],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50052,PROJCS["NAD_1983_StatePlane_Alaska_5_FIPS_5005_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-154],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50054,PROJCS["NAD_1927_StatePlane_Alaska_5_FIPS_5005",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-154],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50061,PROJCS["NAD_1983_StatePlane_Alaska_6_FIPS_5006",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-158],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50062,PROJCS["NAD_1983_StatePlane_Alaska_6_FIPS_5006_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-158],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50064,PROJCS["NAD_1927_StatePlane_Alaska_6_FIPS_5006",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-158],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50071,PROJCS["NAD_1983_StatePlane_Alaska_7_FIPS_5007",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-162],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50072,PROJCS["NAD_1983_StatePlane_Alaska_7_FIPS_5007_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-162],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50074,PROJCS["NAD_1927_StatePlane_Alaska_7_FIPS_5007",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",700000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-162],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50081,PROJCS["NAD_1983_StatePlane_Alaska_8_FIPS_5008",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-166],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50082,PROJCS["NAD_1983_StatePlane_Alaska_8_FIPS_5008_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-166],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50084,PROJCS["NAD_1927_StatePlane_Alaska_8_FIPS_5008",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-166],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50091,PROJCS["NAD_1983_StatePlane_Alaska_9_FIPS_5009",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-170],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Meter",1]]
+50092,PROJCS["NAD_1983_StatePlane_Alaska_9_FIPS_5009_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-170],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50094,PROJCS["NAD_1927_StatePlane_Alaska_9_FIPS_5009",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",600000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-170],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",54],UNIT["Foot_US",0.304800609601219241]]
+50101,PROJCS["NAD_1983_StatePlane_Alaska_10_FIPS_5010",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-176],PARAMETER["Standard_Parallel_1",51.83333333333334],PARAMETER["Standard_Parallel_2",53.83333333333334],PARAMETER["Latitude_Of_Origin",51],UNIT["Meter",1]]
+50102,PROJCS["NAD_1983_StatePlane_Alaska_10_FIPS_5010_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3280833.333333333],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-176],PARAMETER["Standard_Parallel_1",51.83333333333334],PARAMETER["Standard_Parallel_2",53.83333333333334],PARAMETER["Latitude_Of_Origin",51],UNIT["Foot_US",0.304800609601219241]]
+50104,PROJCS["NAD_1927_StatePlane_Alaska_10_FIPS_5010",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",3000000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-176],PARAMETER["Standard_Parallel_1",51.83333333333334],PARAMETER["Standard_Parallel_2",53.83333333333334],PARAMETER["Latitude_Of_Origin",51],UNIT["Foot_US",0.304800609601219241]]
+51010,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_1_FIPS_5101",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-155.5],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",18.83333333333333],UNIT["Meter",1]]
+51011,PROJCS["NAD_1983_StatePlane_Hawaii_1_FIPS_5101",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-155.5],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",18.83333333333333],UNIT["Meter",1]]
+51012,PROJCS["NAD_1983_StatePlane_Hawaii_1_FIPS_5101_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-155.5],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",18.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+51013,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_1_FIPS_5101_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-155.5],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",18.83333333333333],UNIT["Foot_US",0.3048006096012192]]
+51014,PROJCS["Old_Hawaiian_StatePlane_Hawaii_1_FIPS_5101",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-155.5],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",18.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+51020,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_2_FIPS_5102",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-156.6666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",20.33333333333333],UNIT["Meter",1]]
+51021,PROJCS["NAD_1983_StatePlane_Hawaii_2_FIPS_5102",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-156.6666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",20.33333333333333],UNIT["Meter",1]]
+51022,PROJCS["NAD_1983_StatePlane_Hawaii_2_FIPS_5102_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-156.6666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",20.33333333333333],UNIT["Foot_US",0.304800609601219241]]
+51023,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_2_FIPS_5102_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-156.6666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",20.33333333333333],UNIT["Foot_US",0.3048006096012192]]
+51024,PROJCS["Old_Hawaiian_StatePlane_Hawaii_2_FIPS_5102",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-156.6666666666667],PARAMETER["Scale_Factor",0.9999666666666667],PARAMETER["Latitude_Of_Origin",20.33333333333333],UNIT["Foot_US",0.304800609601219241]]
+51030,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_3_FIPS_5103",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-158],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.16666666666667],UNIT["Meter",1]]
+51031,PROJCS["NAD_1983_StatePlane_Hawaii_3_FIPS_5103",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-158],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.16666666666667],UNIT["Meter",1]]
+51032,PROJCS["NAD_1983_StatePlane_Hawaii_3_FIPS_5103_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-158],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.16666666666667],UNIT["Foot_US",0.304800609601219241]]
+51033,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_3_FIPS_5103_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-158.0],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.16666666666667],UNIT["Foot_US",0.3048006096012192]]
+51034,PROJCS["Old_Hawaiian_StatePlane_Hawaii_3_FIPS_5103",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-158],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.16666666666667],UNIT["Foot_US",0.304800609601219241]]
+51040,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_4_FIPS_5104",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-159.5],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.83333333333333],UNIT["Meter",1]]
+51041,PROJCS["NAD_1983_StatePlane_Hawaii_4_FIPS_5104",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-159.5],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.83333333333333],UNIT["Meter",1]]
+51042,PROJCS["NAD_1983_StatePlane_Hawaii_4_FIPS_5104_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-159.5],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+51043,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_4_FIPS_5104_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-159.5],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.83333333333333],UNIT["Foot_US",0.3048006096012192]]
+51044,PROJCS["Old_Hawaiian_StatePlane_Hawaii_4_FIPS_5104",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-159.5],PARAMETER["Scale_Factor",0.99999],PARAMETER["Latitude_Of_Origin",21.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+51050,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_5_FIPS_5105",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-160.1666666666667],PARAMETER["Scale_Factor",1],PARAMETER["Latitude_Of_Origin",21.66666666666667],UNIT["Meter",1]]
+51051,PROJCS["NAD_1983_StatePlane_Hawaii_5_FIPS_5105",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-160.1666666666667],PARAMETER["Scale_Factor",1],PARAMETER["Latitude_Of_Origin",21.66666666666667],UNIT["Meter",1]]
+51052,PROJCS["NAD_1983_StatePlane_Hawaii_5_FIPS_5105_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-160.1666666666667],PARAMETER["Scale_Factor",1],PARAMETER["Latitude_Of_Origin",21.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+51053,PROJCS["NAD_1983_HARN_StatePlane_Hawaii_5_FIPS_5105_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1640416.666666667],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-160.1666666666667],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",21.66666666666667],UNIT["Foot_US",0.3048006096012192]]
+51054,PROJCS["Old_Hawaiian_StatePlane_Hawaii_5_FIPS_5105",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-160.1666666666667],PARAMETER["Scale_Factor",1],PARAMETER["Latitude_Of_Origin",21.66666666666667],UNIT["Foot_US",0.304800609601219241]]
+52000,PROJCS["NAD_1983_HARN_StatePlane_Puerto_Rico_Virgin_Islands_FIPS_5200",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",200000],PARAMETER["Central_Meridian",-66.43333333333334],PARAMETER["Standard_Parallel_1",18.03333333333333],PARAMETER["Standard_Parallel_2",18.43333333333333],PARAMETER["Latitude_Of_Origin",17.83333333333333],UNIT["Meter",1]]
+52001,PROJCS["NAD_1983_StatePlane_Puerto_Rico_Virgin_Islands_FIPS_5200",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000],PARAMETER["False_Northing",200000],PARAMETER["Central_Meridian",-66.43333333333334],PARAMETER["Standard_Parallel_1",18.03333333333333],PARAMETER["Standard_Parallel_2",18.43333333333333],PARAMETER["Latitude_Of_Origin",17.83333333333333],UNIT["Meter",1]]
+52002,PROJCS["NAD_1983_StatePlane_Puerto_Rico_Virgin_Islands_FIPS_5200_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",656166.6666666665],PARAMETER["False_Northing",656166.6666666665],PARAMETER["Central_Meridian",-66.43333333333334],PARAMETER["Standard_Parallel_1",18.03333333333333],PARAMETER["Standard_Parallel_2",18.43333333333333],PARAMETER["Latitude_Of_Origin",17.83333333333333],UNIT["Foot_US",0.3048006096012192]]
+52014,PROJCS["NAD_1927_StatePlane_Puerto_Rico_FIPS_5201",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",-66.43333333333334],PARAMETER["Standard_Parallel_1",18.03333333333333],PARAMETER["Standard_Parallel_2",18.43333333333333],PARAMETER["Latitude_Of_Origin",17.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+52020,PROJCS["Puerto_Rico_StatePlane_Virgin_Islands_St_Croix_FIPS_5202",GEOGCS["GCS_Puerto_Rico",DATUM["D_Puerto_Rico",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-66.43333333333334],PARAMETER["Standard_Parallel_1",18.03333333333333],PARAMETER["Standard_Parallel_2",18.43333333333333],PARAMETER["Latitude_Of_Origin",17.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+52024,PROJCS["Puerto_Rico_StatePlane_Virgin_Islands_St_Croix_FIPS_5202",GEOGCS["GCS_Puerto_Rico",DATUM["D_Puerto_Rico",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",500000],PARAMETER["False_Northing",100000],PARAMETER["Central_Meridian",-66.43333333333334],PARAMETER["Standard_Parallel_1",18.03333333333333],PARAMETER["Standard_Parallel_2",18.43333333333333],PARAMETER["Latitude_Of_Origin",17.83333333333333],UNIT["Foot_US",0.304800609601219241]]
+54000,PROJCS["NAD_1983_StatePlane_Guam_FIPS_5400",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Polyconic"],PARAMETER["False_Easting",50000],PARAMETER["False_Northing",50000],PARAMETER["Central_Meridian",144.7487507055556],PARAMETER["Latitude_Of_Origin",13.47246635277778],UNIT["Meter",1]]
+54001,PROJCS["NAD_1983_StatePlane_Guam_FIPS_5400",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Polyconic"],PARAMETER["False_Easting",50000],PARAMETER["False_Northing",50000],PARAMETER["Central_Meridian",144.7487507055556],PARAMETER["Latitude_Of_Origin",13.47246635277778],UNIT["Meter",1]]
+54002,PROJCS["NAD_1983_StatePlane_Guam_FIPS_5400_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Polyconic"],PARAMETER["False_Easting",164041.6666666666],PARAMETER["False_Northing",164041.6666666666],PARAMETER["Central_Meridian",144.7487507055556],PARAMETER["Latitude_Of_Origin",13.47246635277778],UNIT["Foot_US",0.304800609601219241]]
+54004,PROJCS["NAD_1927_StatePlane_Guam_FIPS_5400",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199432955]],PROJECTION["Polyconic"],PARAMETER["False_Easting",164041.6666666667],PARAMETER["False_Northing",164041.6666666667],PARAMETER["Central_Meridian",144.7487507055556],PARAMETER["Latitude_Of_Origin",13.47246635277778],UNIT["Foot_US",0.304800609601219241]]
+102964,PROJCS["NAD_1927_Alaska_Albers_Feet",GEOGCS["GCS_North_American_1927",DATUM["D_North_American_1927",SPHEROID["Clarke_1866",6378206.4,294.9786982]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Albers"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-154.0],PARAMETER["Standard_Parallel_1",55.0],PARAMETER["Standard_Parallel_2",65.0],PARAMETER["Latitude_Of_Origin",50.0],UNIT["Foot_US",0.3048006096012192]]
+102991,PROJCS["NAD_1983_Oregon_Statewide_Lambert",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",43.0],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",41.75],UNIT["Meter",1.0]]
+102993,PROJCS["NAD_1983_HARN_Oregon_Statewide_Lambert",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",400000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",43.0],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",41.75],UNIT["Meter",1.0]]
+102994,PROJCS["NAD_1983_HARN_Oregon_Statewide_Lambert_Feet_Intl",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312335.958005249],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",43.0],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",41.75],UNIT["Foot",0.3048]]
+102996,PROJCS["NAD_1983_Oregon_Statewide_Lambert_Feet_Intl",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",1312335.958005249],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-120.5],PARAMETER["Standard_Parallel_1",43.0],PARAMETER["Standard_Parallel_2",45.5],PARAMETER["Latitude_Of_Origin",41.75],UNIT["Foot",0.3048]]
diff --git a/data/esri_Wisconsin_extra.wkt b/data/esri_Wisconsin_extra.wkt
new file mode 100644
index 0000000..85716fb
--- /dev/null
+++ b/data/esri_Wisconsin_extra.wkt
@@ -0,0 +1,144 @@
+103300,PROJCS["NAD_1983_HARN_WISCRS_Adams_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",147218.6942],PARAMETER["False_Northing",0.0037],PARAMETER["Central_Meridian",-90.0],PARAMETER["Scale_Factor",1.0000365285],PARAMETER["Latitude_Of_Origin",43.36666666666667],UNIT["Meter",1.0]]
+103301,PROJCS["NAD_1983_HARN_WISCRS_Ashland_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",172821.9461],PARAMETER["False_Northing",0.0017],PARAMETER["Central_Meridian",-90.62222222222222],PARAMETER["Scale_Factor",1.0000495683],PARAMETER["Latitude_Of_Origin",45.70611111111111],UNIT["Meter",1.0]]
+103302,PROJCS["NAD_1983_HARN_WISCRS_Barron_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",93150.0],PARAMETER["False_Northing",0.0029],PARAMETER["Central_Meridian",-91.85],PARAMETER["Scale_Factor",1.0000486665],PARAMETER["Latitude_Of_Origin",45.13333333333333],UNIT["Meter",1.0]]
+103303,PROJCS["NAD_1983_HARN_WISCRS_Bayfield_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",228600.4575],PARAMETER["False_Northing",148551.4837],PARAMETER["Central_Meridian",-91.15277777777779],PARAMETER["Standard_Parallel_1",46.66964837722222],PARAMETER["Scale_Factor",1.0000331195],PARAMETER["Latitude_Of_Origin",46.66964837722222],UNIT["Meter",1.0]]
+103304,PROJCS["NAD_1983_HARN_WISCRS_Brown_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",31600.0],PARAMETER["False_Northing",4600.0],PARAMETER["Central_Meridian",-88.0],PARAMETER["Scale_Factor",1.00002],PARAMETER["Latitude_Of_Origin",43.0],UNIT["Meter",1.0]]
+103305,PROJCS["NAD_1983_HARN_WISCRS_Buffalo_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",175260.3502],PARAMETER["False_Northing",0.0048],PARAMETER["Central_Meridian",-91.79722222222222],PARAMETER["Scale_Factor",1.0000382778],PARAMETER["Latitude_Of_Origin",43.48138888888889],UNIT["Meter",1.0]]
+103306,PROJCS["NAD_1983_HARN_WISCRS_Burnett_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",64008.1276],PARAMETER["False_Northing",59445.9043],PARAMETER["Central_Meridian",-92.45777777777778],PARAMETER["Standard_Parallel_1",45.89871486583333],PARAMETER["Scale_Factor",1.0000383841],PARAMETER["Latitude_Of_Origin",45.89871486583333],UNIT["Meter",1.0]]
+103307,PROJCS["NAD_1983_HARN_WISCRS_Calumet_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",244754.8893],PARAMETER["False_Northing",0.0049],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Meter",1.0]]
+103308,PROJCS["NAD_1983_HARN_WISCRS_Chippewa_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",60045.72],PARAMETER["False_Northing",44091.4346],PARAMETER["Central_Meridian",-91.29444444444444],PARAMETER["Standard_Parallel_1",44.97785689861112],PARAMETER["Scale_Factor",1.0000391127],PARAMETER["Latitude_Of_Origin",44.97785689861112],UNIT["Meter",1.0]]
+103309,PROJCS["NAD_1983_HARN_WISCRS_Clark_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",199949.1989],PARAMETER["False_Northing",0.0086],PARAMETER["Central_Meridian",-90.70833333333334],PARAMETER["Scale_Factor",1.0000463003],PARAMETER["Latitude_Of_Origin",43.6],UNIT["Meter",1.0]]
+103310,PROJCS["NAD_1983_HARN_WISCRS_Columbia_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",169164.3381],PARAMETER["False_Northing",111569.6134],PARAMETER["Central_Meridian",-89.39444444444445],PARAMETER["Standard_Parallel_1",43.46254664583333],PARAMETER["Scale_Factor",1.00003498],PARAMETER["Latitude_Of_Origin",43.46254664583333],UNIT["Meter",1.0]]
+103311,PROJCS["NAD_1983_HARN_WISCRS_Crawford_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",113690.6274],PARAMETER["False_Northing",53703.1201],PARAMETER["Central_Meridian",-90.9388888888889],PARAMETER["Standard_Parallel_1",43.200055605],PARAMETER["Scale_Factor",1.0000349151],PARAMETER["Latitude_Of_Origin",43.200055605],UNIT["Meter",1.0]]
+103312,PROJCS["NAD_1983_HARN_WISCRS_Dane_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",247193.2944],PARAMETER["False_Northing",146591.9896],PARAMETER["Central_Meridian",-89.42222222222223],PARAMETER["Standard_Parallel_1",43.0695160375],PARAMETER["Scale_Factor",1.0000384786],PARAMETER["Latitude_Of_Origin",43.0695160375],UNIT["Meter",1.0]]
+103313,PROJCS["NAD_1983_HARN_WISCRS_Dodge_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",263347.7263],PARAMETER["False_Northing",0.0076],PARAMETER["Central_Meridian",-88.775],PARAMETER["Scale_Factor",1.0000346418],PARAMETER["Latitude_Of_Origin",41.47222222222222],UNIT["Meter",1.0]]
+103314,PROJCS["NAD_1983_HARN_WISCRS_Door_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",158801.1176],PARAMETER["False_Northing",0.0023],PARAMETER["Central_Meridian",-87.27222222222223],PARAMETER["Scale_Factor",1.0000187521],PARAMETER["Latitude_Of_Origin",44.4],UNIT["Meter",1.0]]
+103315,PROJCS["NAD_1983_HARN_WISCRS_Douglas_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",59131.3183],PARAMETER["False_Northing",0.0041],PARAMETER["Central_Meridian",-91.91666666666667],PARAMETER["Scale_Factor",1.0000385418],PARAMETER["Latitude_Of_Origin",45.88333333333333],UNIT["Meter",1.0]]
+103316,PROJCS["NAD_1983_HARN_WISCRS_Dunn_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",51816.104],PARAMETER["False_Northing",0.003],PARAMETER["Central_Meridian",-91.89444444444445],PARAMETER["Scale_Factor",1.0000410324],PARAMETER["Latitude_Of_Origin",44.40833333333333],UNIT["Meter",1.0]]
+103317,PROJCS["NAD_1983_HARN_WISCRS_EauClaire_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",120091.4402],PARAMETER["False_Northing",91687.9239],PARAMETER["Central_Meridian",-91.28888888888889],PARAMETER["Standard_Parallel_1",45.87228112638889],PARAMETER["Scale_Factor",1.000035079],PARAMETER["Latitude_Of_Origin",45.87228112638889],UNIT["Meter",1.0]]
+103318,PROJCS["NAD_1983_HARN_WISCRS_Florence_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",133502.6683],PARAMETER["False_Northing",0.0063],PARAMETER["Central_Meridian",-88.14166666666668],PARAMETER["Scale_Factor",1.0000552095],PARAMETER["Latitude_Of_Origin",45.43888888888888],UNIT["Meter",1.0]]
+103319,PROJCS["NAD_1983_HARN_WISCRS_Fond_du_Lac_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",244754.8893],PARAMETER["False_Northing",0.0049],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Meter",1.0]]
+103320,PROJCS["NAD_1983_HARN_WISCRS_Forest_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",275844.5533],PARAMETER["False_Northing",0.0157],PARAMETER["Central_Meridian",-88.63333333333334],PARAMETER["Scale_Factor",1.0000673004],PARAMETER["Latitude_Of_Origin",44.00555555555555],UNIT["Meter",1.0]]
+103321,PROJCS["NAD_1983_HARN_WISCRS_Grant_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",242316.4841],PARAMETER["False_Northing",0.01],PARAMETER["Central_Meridian",-90.8],PARAMETER["Scale_Factor",1.0000349452],PARAMETER["Latitude_Of_Origin",41.41111111111111],UNIT["Meter",1.0]]
+103322,PROJCS["NAD_1983_HARN_WISCRS_Green_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",170078.7403],PARAMETER["False_Northing",45830.2947],PARAMETER["Central_Meridian",-89.83888888888889],PARAMETER["Standard_Parallel_1",42.63756227694444],PARAMETER["Scale_Factor",1.0000390487],PARAMETER["Latitude_Of_Origin",42.63756227694444],UNIT["Meter",1.0]]
+103323,PROJCS["NAD_1983_HARN_WISCRS_GreenLake_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",150876.3018],PARAMETER["False_Northing",79170.7795],PARAMETER["Central_Meridian",-89.24166666666667],PARAMETER["Standard_Parallel_1",43.80700011777778],PARAMETER["Scale_Factor",1.0000344057],PARAMETER["Latitude_Of_Origin",43.80700011777778],UNIT["Meter",1.0]]
+103324,PROJCS["NAD_1983_HARN_WISCRS_Iowa_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",113081.0261],PARAMETER["False_Northing",0.0045],PARAMETER["Central_Meridian",-90.16111111111111],PARAMETER["Scale_Factor",1.0000394961],PARAMETER["Latitude_Of_Origin",42.53888888888888],UNIT["Meter",1.0]]
+103325,PROJCS["NAD_1983_HARN_WISCRS_Iron_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",220980.4419],PARAMETER["False_Northing",0.0085],PARAMETER["Central_Meridian",-90.25555555555556],PARAMETER["Scale_Factor",1.0000677153],PARAMETER["Latitude_Of_Origin",45.43333333333333],UNIT["Meter",1.0]]
+103326,PROJCS["NAD_1983_HARN_WISCRS_Jackson_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",27000.0],PARAMETER["False_Northing",25000.0],PARAMETER["Central_Meridian",-90.84429651944444],PARAMETER["Scale_Factor",1.0000353],PARAMETER["Latitude_Of_Origin",44.25333512777778],UNIT["Meter",1.0]]
+103327,PROJCS["NAD_1983_HARN_WISCRS_Jefferson_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",263347.7263],PARAMETER["False_Northing",0.0076],PARAMETER["Central_Meridian",-88.775],PARAMETER["Scale_Factor",1.0000346418],PARAMETER["Latitude_Of_Origin",41.47222222222222],UNIT["Meter",1.0]]
+103328,PROJCS["NAD_1983_HARN_WISCRS_Juneau_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",147218.6942],PARAMETER["False_Northing",0.0037],PARAMETER["Central_Meridian",-90.0],PARAMETER["Scale_Factor",1.0000365285],PARAMETER["Latitude_Of_Origin",43.36666666666667],UNIT["Meter",1.0]]
+103329,PROJCS["NAD_1983_HARN_WISCRS_Kenosha_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",185928.3728],PARAMETER["False_Northing",0.0009],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Meter",1.0]]
+103330,PROJCS["NAD_1983_HARN_WISCRS_Kewaunee_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",79857.7614],PARAMETER["False_Northing",0.0012],PARAMETER["Central_Meridian",-87.55],PARAMETER["Scale_Factor",1.0000233704],PARAMETER["Latitude_Of_Origin",43.26666666666667],UNIT["Meter",1.0]]
+103331,PROJCS["NAD_1983_HARN_WISCRS_LaCrosse_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",130454.6598],PARAMETER["False_Northing",0.0033],PARAMETER["Central_Meridian",-91.31666666666666],PARAMETER["Scale_Factor",1.0000319985],PARAMETER["Latitude_Of_Origin",43.45111111111111],UNIT["Meter",1.0]]
+103332,PROJCS["NAD_1983_HARN_WISCRS_Lafayette_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",170078.7403],PARAMETER["False_Northing",45830.2947],PARAMETER["Central_Meridian",-89.83888888888889],PARAMETER["Standard_Parallel_1",42.63756227694444],PARAMETER["Scale_Factor",1.0000390487],PARAMETER["Latitude_Of_Origin",42.63756227694444],UNIT["Meter",1.0]]
+103333,PROJCS["NAD_1983_HARN_WISCRS_Langlade_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",198425.197],PARAMETER["False_Northing",105279.7829],PARAMETER["Central_Meridian",-89.03333333333333],PARAMETER["Standard_Parallel_1",45.15423710527778],PARAMETER["Scale_Factor",1.0000627024],PARAMETER["Latitude_Of_Origin",45.15423710527778],UNIT["Meter",1.0]]
+103334,PROJCS["NAD_1983_HARN_WISCRS_Lincoln_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",116129.0323],PARAMETER["False_Northing",0.0058],PARAMETER["Central_Meridian",-89.73333333333333],PARAMETER["Scale_Factor",1.0000599003],PARAMETER["Latitude_Of_Origin",44.84444444444445],UNIT["Meter",1.0]]
+103335,PROJCS["NAD_1983_HARN_WISCRS_Manitowoc_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",79857.7614],PARAMETER["False_Northing",0.0012],PARAMETER["Central_Meridian",-87.55],PARAMETER["Scale_Factor",1.0000233704],PARAMETER["Latitude_Of_Origin",43.26666666666667],UNIT["Meter",1.0]]
+103336,PROJCS["NAD_1983_HARN_WISCRS_Marathon_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",74676.1493],PARAMETER["False_Northing",55049.2669],PARAMETER["Central_Meridian",-89.77],PARAMETER["Standard_Parallel_1",44.90090442361111],PARAMETER["Scale_Factor",1.000053289],PARAMETER["Latitude_Of_Origin",44.90090442361111],UNIT["Meter",1.0]]
+103337,PROJCS["NAD_1983_HARN_WISCRS_Marinette_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",238658.8794],PARAMETER["False_Northing",0.0032],PARAMETER["Central_Meridian",-87.71111111111111],PARAMETER["Scale_Factor",1.0000234982],PARAMETER["Latitude_Of_Origin",44.69166666666666],UNIT["Meter",1.0]]
+103338,PROJCS["NAD_1983_HARN_WISCRS_Marquette_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",150876.3018],PARAMETER["False_Northing",79170.7795],PARAMETER["Central_Meridian",-89.24166666666667],PARAMETER["Standard_Parallel_1",43.80700011777778],PARAMETER["Scale_Factor",1.0000344057],PARAMETER["Latitude_Of_Origin",43.80700011777778],UNIT["Meter",1.0]]
+103339,PROJCS["NAD_1983_HARN_WISCRS_Menominee_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",105461.0121],PARAMETER["False_Northing",0.0029],PARAMETER["Central_Meridian",-88.41666666666667],PARAMETER["Scale_Factor",1.0000362499],PARAMETER["Latitude_Of_Origin",44.71666666666667],UNIT["Meter",1.0]]
+103340,PROJCS["NAD_1983_HARN_WISCRS_Milwaukee_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",185928.3728],PARAMETER["False_Northing",0.0009],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Meter",1.0]]
+103341,PROJCS["NAD_1983_HARN_WISCRS_Monroe_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",204521.209],PARAMETER["False_Northing",121923.9861],PARAMETER["Central_Meridian",-90.64166666666668],PARAMETER["Standard_Parallel_1",44.00007392861111],PARAMETER["Scale_Factor",1.0000434122],PARAMETER["Latitude_Of_Origin",44.00007392861111],UNIT["Meter",1.0]]
+103342,PROJCS["NAD_1983_HARN_WISCRS_Oconto_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",182880.3676],PARAMETER["False_Northing",0.0033],PARAMETER["Central_Meridian",-87.90833333333335],PARAMETER["Scale_Factor",1.0000236869],PARAMETER["Latitude_Of_Origin",44.39722222222222],UNIT["Meter",1.0]]
+103343,PROJCS["NAD_1983_HARN_WISCRS_Oneida_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",70104.1401],PARAMETER["False_Northing",57588.0346],PARAMETER["Central_Meridian",-89.54444444444444],PARAMETER["Standard_Parallel_1",45.70422377027778],PARAMETER["Scale_Factor",1.0000686968],PARAMETER["Latitude_Of_Origin",45.70422377027778],UNIT["Meter",1.0]]
+103344,PROJCS["NAD_1983_HARN_WISCRS_Outagamie_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",244754.8893],PARAMETER["False_Northing",0.0049],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Meter",1.0]]
+103345,PROJCS["NAD_1983_HARN_WISCRS_Ozaukee_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",185928.3728],PARAMETER["False_Northing",0.0009],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Meter",1.0]]
+103346,PROJCS["NAD_1983_HARN_WISCRS_Pepin_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",167640.3354],PARAMETER["False_Northing",86033.0876],PARAMETER["Central_Meridian",-92.22777777777777],PARAMETER["Standard_Parallel_1",44.63614887194444],PARAMETER["Scale_Factor",1.0000362977],PARAMETER["Latitude_Of_Origin",44.63614887194444],UNIT["Meter",1.0]]
+103347,PROJCS["NAD_1983_HARN_WISCRS_Pierce_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",167640.3354],PARAMETER["False_Northing",86033.0876],PARAMETER["Central_Meridian",-92.22777777777777],PARAMETER["Standard_Parallel_1",44.63614887194444],PARAMETER["Scale_Factor",1.0000362977],PARAMETER["Latitude_Of_Origin",44.63614887194444],UNIT["Meter",1.0]]
+103348,PROJCS["NAD_1983_HARN_WISCRS_Polk_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",141732.2823],PARAMETER["False_Northing",0.0059],PARAMETER["Central_Meridian",-92.63333333333334],PARAMETER["Scale_Factor",1.0000433849],PARAMETER["Latitude_Of_Origin",44.66111111111111],UNIT["Meter",1.0]]
+103349,PROJCS["NAD_1983_HARN_WISCRS_Portage_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",56388.1128],PARAMETER["False_Northing",50022.1874],PARAMETER["Central_Meridian",-89.5],PARAMETER["Standard_Parallel_1",44.41682397527777],PARAMETER["Scale_Factor",1.000039936],PARAMETER["Latitude_Of_Origin",44.41682397527777],UNIT["Meter",1.0]]
+103350,PROJCS["NAD_1983_HARN_WISCRS_Price_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",227990.8546],PARAMETER["False_Northing",0.0109],PARAMETER["Central_Meridian",-90.48888888888889],PARAMETER["Scale_Factor",1.0000649554],PARAMETER["Latitude_Of_Origin",44.55555555555555],UNIT["Meter",1.0]]
+103351,PROJCS["NAD_1983_HARN_WISCRS_Racine_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",185928.3728],PARAMETER["False_Northing",0.0009],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Meter",1.0]]
+103352,PROJCS["NAD_1983_HARN_WISCRS_Richland_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",202387.6048],PARAMETER["False_Northing",134255.4253],PARAMETER["Central_Meridian",-90.43055555555556],PARAMETER["Standard_Parallel_1",43.3223129275],PARAMETER["Scale_Factor",1.0000375653],PARAMETER["Latitude_Of_Origin",43.3223129275],UNIT["Meter",1.0]]
+103353,PROJCS["NAD_1983_HARN_WISCRS_Rock_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",146304.2926],PARAMETER["False_Northing",0.0068],PARAMETER["Central_Meridian",-89.07222222222222],PARAMETER["Scale_Factor",1.0000337311],PARAMETER["Latitude_Of_Origin",41.94444444444444],UNIT["Meter",1.0]]
+103354,PROJCS["NAD_1983_HARN_WISCRS_Rusk_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",250546.1013],PARAMETER["False_Northing",0.0234],PARAMETER["Central_Meridian",-91.06666666666666],PARAMETER["Scale_Factor",1.0000495976],PARAMETER["Latitude_Of_Origin",43.91944444444444],UNIT["Meter",1.0]]
+103355,PROJCS["NAD_1983_HARN_WISCRS_Sauk_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",185623.5716],PARAMETER["False_Northing",0.0051],PARAMETER["Central_Meridian",-89.9],PARAMETER["Scale_Factor",1.0000373868],PARAMETER["Latitude_Of_Origin",42.81944444444445],UNIT["Meter",1.0]]
+103356,PROJCS["NAD_1983_HARN_WISCRS_Sawyer_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",216713.2336],PARAMETER["False_Northing",120734.1631],PARAMETER["Central_Meridian",-91.11666666666666],PARAMETER["Standard_Parallel_1",45.90009913138888],PARAMETER["Scale_Factor",1.0000573461],PARAMETER["Latitude_Of_Origin",45.90009913138888],UNIT["Meter",1.0]]
+103357,PROJCS["NAD_1983_HARN_WISCRS_Shawano_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",262433.3253],PARAMETER["False_Northing",0.0096],PARAMETER["Central_Meridian",-88.60555555555555],PARAMETER["Scale_Factor",1.000032144],PARAMETER["Latitude_Of_Origin",44.03611111111111],UNIT["Meter",1.0]]
+103358,PROJCS["NAD_1983_HARN_WISCRS_Sheboygan_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",79857.7614],PARAMETER["False_Northing",0.0012],PARAMETER["Central_Meridian",-87.55],PARAMETER["Scale_Factor",1.0000233704],PARAMETER["Latitude_Of_Origin",43.26666666666667],UNIT["Meter",1.0]]
+103359,PROJCS["NAD_1983_HARN_WISCRS_St_Croix_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",165506.7302],PARAMETER["False_Northing",0.0103],PARAMETER["Central_Meridian",-92.63333333333334],PARAMETER["Scale_Factor",1.0000381803],PARAMETER["Latitude_Of_Origin",44.03611111111111],UNIT["Meter",1.0]]
+103360,PROJCS["NAD_1983_HARN_WISCRS_Taylor_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",187147.5744],PARAMETER["False_Northing",107746.7522],PARAMETER["Central_Meridian",-90.48333333333333],PARAMETER["Standard_Parallel_1",45.17782208583333],PARAMETER["Scale_Factor",1.0000597566],PARAMETER["Latitude_Of_Origin",45.17782208583333],UNIT["Meter",1.0]]
+103361,PROJCS["NAD_1983_HARN_WISCRS_Trempealeau_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",256946.9138],PARAMETER["False_Northing",0.0041],PARAMETER["Central_Meridian",-91.36666666666666],PARAMETER["Scale_Factor",1.0000361538],PARAMETER["Latitude_Of_Origin",43.16111111111111],UNIT["Meter",1.0]]
+103362,PROJCS["NAD_1983_HARN_WISCRS_Vernon_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",222504.4451],PARAMETER["False_Northing",47532.0602],PARAMETER["Central_Meridian",-90.78333333333333],PARAMETER["Standard_Parallel_1",43.57503293972223],PARAMETER["Scale_Factor",1.0000408158],PARAMETER["Latitude_Of_Origin",43.57503293972223],UNIT["Meter",1.0]]
+103363,PROJCS["NAD_1983_HARN_WISCRS_Vilas_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",134417.0689],PARAMETER["False_Northing",50337.1092],PARAMETER["Central_Meridian",-89.48888888888889],PARAMETER["Standard_Parallel_1",46.07784409055556],PARAMETER["Scale_Factor",1.0000730142],PARAMETER["Latitude_Of_Origin",46.07784409055556],UNIT["Meter",1.0]]
+103364,PROJCS["NAD_1983_HARN_WISCRS_Walworth_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",232562.8651],PARAMETER["False_Northing",111088.2224],PARAMETER["Central_Meridian",-88.54166666666667],PARAMETER["Standard_Parallel_1",42.66946209694444],PARAMETER["Scale_Factor",1.0000367192],PARAMETER["Latitude_Of_Origin",42.66946209694444],UNIT["Meter",1.0]]
+103365,PROJCS["NAD_1983_HARN_WISCRS_Washburn_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",234086.8682],PARAMETER["False_Northing",188358.6058],PARAMETER["Central_Meridian",-91.78333333333333],PARAMETER["Standard_Parallel_1",45.96121983333334],PARAMETER["Scale_Factor",1.0000475376],PARAMETER["Latitude_Of_Origin",45.96121983333334],UNIT["Meter",1.0]]
+103366,PROJCS["NAD_1983_HARN_WISCRS_Washington_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",120091.4415],PARAMETER["False_Northing",0.003],PARAMETER["Central_Meridian",-88.06388888888888],PARAMETER["Scale_Factor",1.00003738],PARAMETER["Latitude_Of_Origin",42.91805555555555],UNIT["Meter",1.0]]
+103367,PROJCS["NAD_1983_HARN_WISCRS_Waukesha_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",208788.418],PARAMETER["False_Northing",0.0034],PARAMETER["Central_Meridian",-88.225],PARAMETER["Scale_Factor",1.0000346179],PARAMETER["Latitude_Of_Origin",42.56944444444445],UNIT["Meter",1.0]]
+103368,PROJCS["NAD_1983_HARN_WISCRS_Waupaca_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",185013.9709],PARAMETER["False_Northing",0.007],PARAMETER["Central_Meridian",-88.81666666666666],PARAMETER["Scale_Factor",1.0000333645],PARAMETER["Latitude_Of_Origin",43.42027777777778],UNIT["Meter",1.0]]
+103369,PROJCS["NAD_1983_HARN_WISCRS_Waushara_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",120091.4402],PARAMETER["False_Northing",45069.7587],PARAMETER["Central_Meridian",-89.24166666666667],PARAMETER["Standard_Parallel_1",44.11394404583334],PARAMETER["Scale_Factor",1.0000392096],PARAMETER["Latitude_Of_Origin",44.11394404583334],UNIT["Meter",1.0]]
+103370,PROJCS["NAD_1983_HARN_WISCRS_Winnebago_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",244754.8893],PARAMETER["False_Northing",0.0049],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Meter",1.0]]
+103371,PROJCS["NAD_1983_HARN_WISCRS_Wood_County_Meters",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",208483.6173],PARAMETER["False_Northing",134589.754],PARAMETER["Central_Meridian",-90.0],PARAMETER["Standard_Parallel_1",44.36259546944444],PARAMETER["Scale_Factor",1.0000421209],PARAMETER["Latitude_Of_Origin",44.36259546944444],UNIT["Meter",1.0]]
+103400,PROJCS["NAD_1983_HARN_WISCRS_Adams_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",482999.999],PARAMETER["False_Northing",0.012],PARAMETER["Central_Meridian",-90.0],PARAMETER["Scale_Factor",1.0000365285],PARAMETER["Latitude_Of_Origin",43.36666666666667],UNIT["Foot_US",0.3048006096012192]]
+103401,PROJCS["NAD_1983_HARN_WISCRS_Ashland_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",567000.001],PARAMETER["False_Northing",0.006],PARAMETER["Central_Meridian",-90.62222222222222],PARAMETER["Scale_Factor",1.0000495683],PARAMETER["Latitude_Of_Origin",45.70611111111111],UNIT["Foot_US",0.3048006096012192]]
+103402,PROJCS["NAD_1983_HARN_WISCRS_Barron_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",305609.625],PARAMETER["False_Northing",0.01],PARAMETER["Central_Meridian",-91.85],PARAMETER["Scale_Factor",1.0000486665],PARAMETER["Latitude_Of_Origin",45.13333333333333],UNIT["Foot_US",0.3048006096012192]]
+103403,PROJCS["NAD_1983_HARN_WISCRS_Bayfield_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",750000.001],PARAMETER["False_Northing",487372.659],PARAMETER["Central_Meridian",-91.15277777777779],PARAMETER["Standard_Parallel_1",46.66964837722222],PARAMETER["Scale_Factor",1.0000331195],PARAMETER["Latitude_Of_Origin",46.66964837722222],UNIT["Foot_US",0.3048006096012192]]
+103404,PROJCS["NAD_1983_HARN_WISCRS_Brown_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",103674.333],PARAMETER["False_Northing",15091.833],PARAMETER["Central_Meridian",-88.0],PARAMETER["Scale_Factor",1.00002],PARAMETER["Latitude_Of_Origin",43.0],UNIT["Foot_US",0.3048006096012192]]
+103405,PROJCS["NAD_1983_HARN_WISCRS_Buffalo_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",574999.999],PARAMETER["False_Northing",0.016],PARAMETER["Central_Meridian",-91.79722222222222],PARAMETER["Scale_Factor",1.0000382778],PARAMETER["Latitude_Of_Origin",43.48138888888889],UNIT["Foot_US",0.3048006096012192]]
+103406,PROJCS["NAD_1983_HARN_WISCRS_Burnett_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",209999.999],PARAMETER["False_Northing",195032.104],PARAMETER["Central_Meridian",-92.45777777777778],PARAMETER["Standard_Parallel_1",45.89871486583333],PARAMETER["Scale_Factor",1.0000383841],PARAMETER["Latitude_Of_Origin",45.89871486583333],UNIT["Foot_US",0.3048006096012192]]
+103407,PROJCS["NAD_1983_HARN_WISCRS_Calumet_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",802999.999],PARAMETER["False_Northing",0.016],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Foot_US",0.3048006096012192]]
+103408,PROJCS["NAD_1983_HARN_WISCRS_Chippewa_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",197000.0],PARAMETER["False_Northing",144656.648],PARAMETER["Central_Meridian",-91.29444444444444],PARAMETER["Standard_Parallel_1",44.97785689861112],PARAMETER["Scale_Factor",1.0000391127],PARAMETER["Latitude_Of_Origin",44.97785689861112],UNIT["Foot_US",0.3048006096012192]]
+103409,PROJCS["NAD_1983_HARN_WISCRS_Clark_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",655999.997],PARAMETER["False_Northing",0.028],PARAMETER["Central_Meridian",-90.70833333333334],PARAMETER["Scale_Factor",1.0000463003],PARAMETER["Latitude_Of_Origin",43.6],UNIT["Foot_US",0.3048006096012192]]
+103410,PROJCS["NAD_1983_HARN_WISCRS_Columbia_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",554999.999],PARAMETER["False_Northing",366041.307],PARAMETER["Central_Meridian",-89.39444444444445],PARAMETER["Standard_Parallel_1",43.46254664583333],PARAMETER["Scale_Factor",1.00003498],PARAMETER["Latitude_Of_Origin",43.46254664583333],UNIT["Foot_US",0.3048006096012192]]
+103411,PROJCS["NAD_1983_HARN_WISCRS_Crawford_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",373000.0],PARAMETER["False_Northing",176190.987],PARAMETER["Central_Meridian",-90.9388888888889],PARAMETER["Standard_Parallel_1",43.200055605],PARAMETER["Scale_Factor",1.0000349151],PARAMETER["Latitude_Of_Origin",43.200055605],UNIT["Foot_US",0.3048006096012192]]
+103412,PROJCS["NAD_1983_HARN_WISCRS_Dane_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",811000.0],PARAMETER["False_Northing",480943.886],PARAMETER["Central_Meridian",-89.42222222222223],PARAMETER["Standard_Parallel_1",43.0695160375],PARAMETER["Scale_Factor",1.0000384786],PARAMETER["Latitude_Of_Origin",43.0695160375],UNIT["Foot_US",0.3048006096012192]]
+103413,PROJCS["NAD_1983_HARN_WISCRS_Dodge_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",863999.999],PARAMETER["False_Northing",0.025],PARAMETER["Central_Meridian",-88.775],PARAMETER["Scale_Factor",1.0000346418],PARAMETER["Latitude_Of_Origin",41.47222222222222],UNIT["Foot_US",0.3048006096012192]]
+103414,PROJCS["NAD_1983_HARN_WISCRS_Door_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",521000.0],PARAMETER["False_Northing",0.008],PARAMETER["Central_Meridian",-87.27222222222223],PARAMETER["Scale_Factor",1.0000187521],PARAMETER["Latitude_Of_Origin",44.4],UNIT["Foot_US",0.3048006096012192]]
+103415,PROJCS["NAD_1983_HARN_WISCRS_Douglas_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",194000.0],PARAMETER["False_Northing",0.013],PARAMETER["Central_Meridian",-91.91666666666667],PARAMETER["Scale_Factor",1.0000385418],PARAMETER["Latitude_Of_Origin",45.88333333333333],UNIT["Foot_US",0.3048006096012192]]
+103416,PROJCS["NAD_1983_HARN_WISCRS_Dunn_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",170000.001],PARAMETER["False_Northing",0.01],PARAMETER["Central_Meridian",-91.89444444444445],PARAMETER["Scale_Factor",1.0000410324],PARAMETER["Latitude_Of_Origin",44.40833333333333],UNIT["Foot_US",0.3048006096012192]]
+103417,PROJCS["NAD_1983_HARN_WISCRS_EauClaire_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",394000.0],PARAMETER["False_Northing",300812.797],PARAMETER["Central_Meridian",-91.28888888888889],PARAMETER["Standard_Parallel_1",45.87228112638889],PARAMETER["Scale_Factor",1.000035079],PARAMETER["Latitude_Of_Origin",45.87228112638889],UNIT["Foot_US",0.3048006096012192]]
+103418,PROJCS["NAD_1983_HARN_WISCRS_Florence_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",438000.004],PARAMETER["False_Northing",0.021],PARAMETER["Central_Meridian",-88.14166666666668],PARAMETER["Scale_Factor",1.0000552095],PARAMETER["Latitude_Of_Origin",45.43888888888888],UNIT["Foot_US",0.3048006096012192]]
+103419,PROJCS["NAD_1983_HARN_WISCRS_Fond_du_Lac_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",802999.999],PARAMETER["False_Northing",0.016],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Foot_US",0.3048006096012192]]
+103420,PROJCS["NAD_1983_HARN_WISCRS_Forest_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",905000.005],PARAMETER["False_Northing",0.052],PARAMETER["Central_Meridian",-88.63333333333334],PARAMETER["Scale_Factor",1.0000673004],PARAMETER["Latitude_Of_Origin",44.00555555555555],UNIT["Foot_US",0.3048006096012192]]
+103421,PROJCS["NAD_1983_HARN_WISCRS_Grant_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",794999.998],PARAMETER["False_Northing",0.033],PARAMETER["Central_Meridian",-90.8],PARAMETER["Scale_Factor",1.0000349452],PARAMETER["Latitude_Of_Origin",41.41111111111111],UNIT["Foot_US",0.3048006096012192]]
+103422,PROJCS["NAD_1983_HARN_WISCRS_Green_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",558000.0],PARAMETER["False_Northing",150361.559],PARAMETER["Central_Meridian",-89.83888888888889],PARAMETER["Standard_Parallel_1",42.63756227694444],PARAMETER["Scale_Factor",1.0000390487],PARAMETER["Latitude_Of_Origin",42.63756227694444],UNIT["Foot_US",0.3048006096012192]]
+103423,PROJCS["NAD_1983_HARN_WISCRS_GreenLake_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",495000.0],PARAMETER["False_Northing",259746.132],PARAMETER["Central_Meridian",-89.24166666666667],PARAMETER["Standard_Parallel_1",43.80700011777778],PARAMETER["Scale_Factor",1.0000344057],PARAMETER["Latitude_Of_Origin",43.80700011777778],UNIT["Foot_US",0.3048006096012192]]
+103424,PROJCS["NAD_1983_HARN_WISCRS_Iowa_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",371000.0],PARAMETER["False_Northing",0.015],PARAMETER["Central_Meridian",-90.16111111111111],PARAMETER["Scale_Factor",1.0000394961],PARAMETER["Latitude_Of_Origin",42.53888888888888],UNIT["Foot_US",0.3048006096012192]]
+103425,PROJCS["NAD_1983_HARN_WISCRS_Iron_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",725000.0],PARAMETER["False_Northing",0.028],PARAMETER["Central_Meridian",-90.25555555555556],PARAMETER["Scale_Factor",1.0000677153],PARAMETER["Latitude_Of_Origin",45.43333333333333],UNIT["Foot_US",0.3048006096012192]]
+103426,PROJCS["NAD_1983_HARN_WISCRS_Jackson_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",88582.5],PARAMETER["False_Northing",82020.833],PARAMETER["Central_Meridian",-90.84429651944444],PARAMETER["Scale_Factor",1.0000353],PARAMETER["Latitude_Of_Origin",44.25333512777778],UNIT["Foot_US",0.3048006096012192]]
+103427,PROJCS["NAD_1983_HARN_WISCRS_Jefferson_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",863999.999],PARAMETER["False_Northing",0.025],PARAMETER["Central_Meridian",-88.775],PARAMETER["Scale_Factor",1.0000346418],PARAMETER["Latitude_Of_Origin",41.47222222222222],UNIT["Foot_US",0.3048006096012192]]
+103428,PROJCS["NAD_1983_HARN_WISCRS_Juneau_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",482999.999],PARAMETER["False_Northing",0.012],PARAMETER["Central_Meridian",-90.0],PARAMETER["Scale_Factor",1.0000365285],PARAMETER["Latitude_Of_Origin",43.36666666666667],UNIT["Foot_US",0.3048006096012192]]
+103429,PROJCS["NAD_1983_HARN_WISCRS_Kenosha_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",610000.003],PARAMETER["False_Northing",0.003],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Foot_US",0.3048006096012192]]
+103430,PROJCS["NAD_1983_HARN_WISCRS_Kewaunee_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",262000.006],PARAMETER["False_Northing",0.004],PARAMETER["Central_Meridian",-87.55],PARAMETER["Scale_Factor",1.0000233704],PARAMETER["Latitude_Of_Origin",43.26666666666667],UNIT["Foot_US",0.3048006096012192]]
+103431,PROJCS["NAD_1983_HARN_WISCRS_LaCrosse_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",427999.996],PARAMETER["False_Northing",0.011],PARAMETER["Central_Meridian",-91.31666666666666],PARAMETER["Scale_Factor",1.0000319985],PARAMETER["Latitude_Of_Origin",43.45111111111111],UNIT["Foot_US",0.3048006096012192]]
+103432,PROJCS["NAD_1983_HARN_WISCRS_Lafayette_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",558000.0],PARAMETER["False_Northing",150361.559],PARAMETER["Central_Meridian",-89.83888888888889],PARAMETER["Standard_Parallel_1",42.63756227694444],PARAMETER["Scale_Factor",1.0000390487],PARAMETER["Latitude_Of_Origin",42.63756227694444],UNIT["Foot_US",0.3048006096012192]]
+103433,PROJCS["NAD_1983_HARN_WISCRS_Langlade_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",651000.0],PARAMETER["False_Northing",345405.421],PARAMETER["Central_Meridian",-89.03333333333333],PARAMETER["Standard_Parallel_1",45.15423710527778],PARAMETER["Scale_Factor",1.0000627024],PARAMETER["Latitude_Of_Origin",45.15423710527778],UNIT["Foot_US",0.3048006096012192]]
+103434,PROJCS["NAD_1983_HARN_WISCRS_Lincoln_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",381000.0],PARAMETER["False_Northing",0.019],PARAMETER["Central_Meridian",-89.73333333333333],PARAMETER["Scale_Factor",1.0000599003],PARAMETER["Latitude_Of_Origin",44.84444444444445],UNIT["Foot_US",0.3048006096012192]]
+103435,PROJCS["NAD_1983_HARN_WISCRS_Manitowoc_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",262000.006],PARAMETER["False_Northing",0.004],PARAMETER["Central_Meridian",-87.55],PARAMETER["Scale_Factor",1.0000233704],PARAMETER["Latitude_Of_Origin",43.26666666666667],UNIT["Foot_US",0.3048006096012192]]
+103436,PROJCS["NAD_1983_HARN_WISCRS_Marathon_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",245000.0],PARAMETER["False_Northing",180607.47],PARAMETER["Central_Meridian",-89.77],PARAMETER["Standard_Parallel_1",44.90090442361111],PARAMETER["Scale_Factor",1.000053289],PARAMETER["Latitude_Of_Origin",44.90090442361111],UNIT["Foot_US",0.3048006096012192]]
+103437,PROJCS["NAD_1983_HARN_WISCRS_Marinette_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",783000.007],PARAMETER["False_Northing",0.01],PARAMETER["Central_Meridian",-87.71111111111111],PARAMETER["Scale_Factor",1.0000234982],PARAMETER["Latitude_Of_Origin",44.69166666666666],UNIT["Foot_US",0.3048006096012192]]
+103438,PROJCS["NAD_1983_HARN_WISCRS_Marquette_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",495000.0],PARAMETER["False_Northing",259746.132],PARAMETER["Central_Meridian",-89.24166666666667],PARAMETER["Standard_Parallel_1",43.80700011777778],PARAMETER["Scale_Factor",1.0000344057],PARAMETER["Latitude_Of_Origin",43.80700011777778],UNIT["Foot_US",0.3048006096012192]]
+103439,PROJCS["NAD_1983_HARN_WISCRS_Menominee_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",346000.004],PARAMETER["False_Northing",0.01],PARAMETER["Central_Meridian",-88.41666666666667],PARAMETER["Scale_Factor",1.0000362499],PARAMETER["Latitude_Of_Origin",44.71666666666667],UNIT["Foot_US",0.3048006096012192]]
+103440,PROJCS["NAD_1983_HARN_WISCRS_Milwaukee_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",610000.003],PARAMETER["False_Northing",0.003],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Foot_US",0.3048006096012192]]
+103441,PROJCS["NAD_1983_HARN_WISCRS_Monroe_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",671000.0],PARAMETER["False_Northing",400012.278],PARAMETER["Central_Meridian",-90.64166666666668],PARAMETER["Standard_Parallel_1",44.00007392861111],PARAMETER["Scale_Factor",1.0000434122],PARAMETER["Latitude_Of_Origin",44.00007392861111],UNIT["Foot_US",0.3048006096012192]]
+103442,PROJCS["NAD_1983_HARN_WISCRS_Oconto_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",600000.006],PARAMETER["False_Northing",0.011],PARAMETER["Central_Meridian",-87.90833333333335],PARAMETER["Scale_Factor",1.0000236869],PARAMETER["Latitude_Of_Origin",44.39722222222222],UNIT["Foot_US",0.3048006096012192]]
+103443,PROJCS["NAD_1983_HARN_WISCRS_Oneida_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",230000.0],PARAMETER["False_Northing",188936.744],PARAMETER["Central_Meridian",-89.54444444444444],PARAMETER["Standard_Parallel_1",45.70422377027778],PARAMETER["Scale_Factor",1.0000686968],PARAMETER["Latitude_Of_Origin",45.70422377027778],UNIT["Foot_US",0.3048006096012192]]
+103444,PROJCS["NAD_1983_HARN_WISCRS_Outagamie_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",802999.999],PARAMETER["False_Northing",0.016],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Foot_US",0.3048006096012192]]
+103445,PROJCS["NAD_1983_HARN_WISCRS_Ozaukee_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",610000.003],PARAMETER["False_Northing",0.003],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Foot_US",0.3048006096012192]]
+103446,PROJCS["NAD_1983_HARN_WISCRS_Pepin_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",550000.0],PARAMETER["False_Northing",282260.222],PARAMETER["Central_Meridian",-92.22777777777777],PARAMETER["Standard_Parallel_1",44.63614887194444],PARAMETER["Scale_Factor",1.0000362977],PARAMETER["Latitude_Of_Origin",44.63614887194444],UNIT["Foot_US",0.3048006096012192]]
+103447,PROJCS["NAD_1983_HARN_WISCRS_Pierce_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",550000.0],PARAMETER["False_Northing",282260.222],PARAMETER["Central_Meridian",-92.22777777777777],PARAMETER["Standard_Parallel_1",44.63614887194444],PARAMETER["Scale_Factor",1.0000362977],PARAMETER["Latitude_Of_Origin",44.63614887194444],UNIT["Foot_US",0.3048006096012192]]
+103448,PROJCS["NAD_1983_HARN_WISCRS_Polk_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",464999.996],PARAMETER["False_Northing",0.019],PARAMETER["Central_Meridian",-92.63333333333334],PARAMETER["Scale_Factor",1.0000433849],PARAMETER["Latitude_Of_Origin",44.66111111111111],UNIT["Foot_US",0.3048006096012192]]
+103449,PROJCS["NAD_1983_HARN_WISCRS_Portage_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",185000.0],PARAMETER["False_Northing",164114.46],PARAMETER["Central_Meridian",-89.5],PARAMETER["Standard_Parallel_1",44.41682397527777],PARAMETER["Scale_Factor",1.000039936],PARAMETER["Latitude_Of_Origin",44.41682397527777],UNIT["Foot_US",0.3048006096012192]]
+103450,PROJCS["NAD_1983_HARN_WISCRS_Price_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",747999.995],PARAMETER["False_Northing",0.036],PARAMETER["Central_Meridian",-90.48888888888889],PARAMETER["Scale_Factor",1.0000649554],PARAMETER["Latitude_Of_Origin",44.55555555555555],UNIT["Foot_US",0.3048006096012192]]
+103451,PROJCS["NAD_1983_HARN_WISCRS_Racine_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",610000.003],PARAMETER["False_Northing",0.003],PARAMETER["Central_Meridian",-87.89444444444445],PARAMETER["Scale_Factor",1.0000260649],PARAMETER["Latitude_Of_Origin",42.21666666666667],UNIT["Foot_US",0.3048006096012192]]
+103452,PROJCS["NAD_1983_HARN_WISCRS_Richland_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",664000.0],PARAMETER["False_Northing",440469.675],PARAMETER["Central_Meridian",-90.43055555555556],PARAMETER["Standard_Parallel_1",43.3223129275],PARAMETER["Scale_Factor",1.0000375653],PARAMETER["Latitude_Of_Origin",43.3223129275],UNIT["Foot_US",0.3048006096012192]]
+103453,PROJCS["NAD_1983_HARN_WISCRS_Rock_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",480000.0],PARAMETER["False_Northing",0.022],PARAMETER["Central_Meridian",-89.07222222222222],PARAMETER["Scale_Factor",1.0000337311],PARAMETER["Latitude_Of_Origin",41.94444444444444],UNIT["Foot_US",0.3048006096012192]]
+103454,PROJCS["NAD_1983_HARN_WISCRS_Rusk_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",822000.001],PARAMETER["False_Northing",0.077],PARAMETER["Central_Meridian",-91.06666666666666],PARAMETER["Scale_Factor",1.0000495976],PARAMETER["Latitude_Of_Origin",43.91944444444444],UNIT["Foot_US",0.3048006096012192]]
+103455,PROJCS["NAD_1983_HARN_WISCRS_Sauk_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",609000.001],PARAMETER["False_Northing",0.017],PARAMETER["Central_Meridian",-89.9],PARAMETER["Scale_Factor",1.0000373868],PARAMETER["Latitude_Of_Origin",42.81944444444445],UNIT["Foot_US",0.3048006096012192]]
+103456,PROJCS["NAD_1983_HARN_WISCRS_Sawyer_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",711000.001],PARAMETER["False_Northing",396108.667],PARAMETER["Central_Meridian",-91.11666666666666],PARAMETER["Standard_Parallel_1",45.90009913138888],PARAMETER["Scale_Factor",1.0000573461],PARAMETER["Latitude_Of_Origin",45.90009913138888],UNIT["Foot_US",0.3048006096012192]]
+103457,PROJCS["NAD_1983_HARN_WISCRS_Shawano_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",861000.001],PARAMETER["False_Northing",0.031],PARAMETER["Central_Meridian",-88.60555555555555],PARAMETER["Scale_Factor",1.000032144],PARAMETER["Latitude_Of_Origin",44.03611111111111],UNIT["Foot_US",0.3048006096012192]]
+103458,PROJCS["NAD_1983_HARN_WISCRS_Sheboygan_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",262000.006],PARAMETER["False_Northing",0.004],PARAMETER["Central_Meridian",-87.55],PARAMETER["Scale_Factor",1.0000233704],PARAMETER["Latitude_Of_Origin",43.26666666666667],UNIT["Foot_US",0.3048006096012192]]
+103459,PROJCS["NAD_1983_HARN_WISCRS_St_Croix_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",542999.997],PARAMETER["False_Northing",0.034],PARAMETER["Central_Meridian",-92.63333333333334],PARAMETER["Scale_Factor",1.0000381803],PARAMETER["Latitude_Of_Origin",44.03611111111111],UNIT["Foot_US",0.3048006096012192]]
+103460,PROJCS["NAD_1983_HARN_WISCRS_Taylor_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",614000.0],PARAMETER["False_Northing",353499.136],PARAMETER["Central_Meridian",-90.48333333333333],PARAMETER["Standard_Parallel_1",45.17782208583333],PARAMETER["Scale_Factor",1.0000597566],PARAMETER["Latitude_Of_Origin",45.17782208583333],UNIT["Foot_US",0.3048006096012192]]
+103461,PROJCS["NAD_1983_HARN_WISCRS_Trempealeau_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",843000.0],PARAMETER["False_Northing",0.013],PARAMETER["Central_Meridian",-91.36666666666666],PARAMETER["Scale_Factor",1.0000361538],PARAMETER["Latitude_Of_Origin",43.16111111111111],UNIT["Foot_US",0.3048006096012192]]
+103462,PROJCS["NAD_1983_HARN_WISCRS_Vernon_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",730000.0],PARAMETER["False_Northing",155944.768],PARAMETER["Central_Meridian",-90.78333333333333],PARAMETER["Standard_Parallel_1",43.57503293972223],PARAMETER["Scale_Factor",1.0000408158],PARAMETER["Latitude_Of_Origin",43.57503293972223],UNIT["Foot_US",0.3048006096012192]]
+103463,PROJCS["NAD_1983_HARN_WISCRS_Vilas_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",441000.0],PARAMETER["False_Northing",165147.666],PARAMETER["Central_Meridian",-89.48888888888889],PARAMETER["Standard_Parallel_1",46.07784409055556],PARAMETER["Scale_Factor",1.0000730142],PARAMETER["Latitude_Of_Origin",46.07784409055556],UNIT["Foot_US",0.3048006096012192]]
+103464,PROJCS["NAD_1983_HARN_WISCRS_Walworth_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",763000.0],PARAMETER["False_Northing",364461.943],PARAMETER["Central_Meridian",-88.54166666666667],PARAMETER["Standard_Parallel_1",42.66946209694444],PARAMETER["Scale_Factor",1.0000367192],PARAMETER["Latitude_Of_Origin",42.66946209694444],UNIT["Foot_US",0.3048006096012192]]
+103465,PROJCS["NAD_1983_HARN_WISCRS_Washburn_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",768000.0],PARAMETER["False_Northing",617973.193],PARAMETER["Central_Meridian",-91.78333333333333],PARAMETER["Standard_Parallel_1",45.96121983333334],PARAMETER["Scale_Factor",1.0000475376],PARAMETER["Latitude_Of_Origin",45.96121983333334],UNIT["Foot_US",0.3048006096012192]]
+103466,PROJCS["NAD_1983_HARN_WISCRS_Washington_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",394000.004],PARAMETER["False_Northing",0.01],PARAMETER["Central_Meridian",-88.06388888888888],PARAMETER["Scale_Factor",1.00003738],PARAMETER["Latitude_Of_Origin",42.91805555555555],UNIT["Foot_US",0.3048006096012192]]
+103467,PROJCS["NAD_1983_HARN_WISCRS_Waukesha_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",685000.001],PARAMETER["False_Northing",0.011],PARAMETER["Central_Meridian",-88.225],PARAMETER["Scale_Factor",1.0000346179],PARAMETER["Latitude_Of_Origin",42.56944444444445],UNIT["Foot_US",0.3048006096012192]]
+103468,PROJCS["NAD_1983_HARN_WISCRS_Waupaca_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",607000.003],PARAMETER["False_Northing",0.023],PARAMETER["Central_Meridian",-88.81666666666666],PARAMETER["Scale_Factor",1.0000333645],PARAMETER["Latitude_Of_Origin",43.42027777777778],UNIT["Foot_US",0.3048006096012192]]
+103469,PROJCS["NAD_1983_HARN_WISCRS_Waushara_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",394000.0],PARAMETER["False_Northing",147866.367],PARAMETER["Central_Meridian",-89.24166666666667],PARAMETER["Standard_Parallel_1",44.11394404583334],PARAMETER["Scale_Factor",1.0000392096],PARAMETER["Latitude_Of_Origin",44.11394404583334],UNIT["Foot_US",0.3048006096012192]]
+103470,PROJCS["NAD_1983_HARN_WISCRS_Winnebago_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",802999.999],PARAMETER["False_Northing",0.016],PARAMETER["Central_Meridian",-88.5],PARAMETER["Scale_Factor",1.0000286569],PARAMETER["Latitude_Of_Origin",42.71944444444445],UNIT["Foot_US",0.3048006096012192]]
+103471,PROJCS["NAD_1983_HARN_WISCRS_Wood_County_Feet",GEOGCS["GCS_North_American_1983_HARN",DATUM["D_North_American_1983_HARN",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",684000.001],PARAMETER["False_Northing",441566.551],PARAMETER["Central_Meridian",-90.0],PARAMETER["Standard_Parallel_1",44.36259546944444],PARAMETER["Scale_Factor",1.0000421209],PARAMETER["Latitude_Of_Origin",44.36259546944444],UNIT["Foot_US",0.3048006096012192]]
diff --git a/data/esri_extra.wkt b/data/esri_extra.wkt
index 9ebaa7a..ea93176 100644
--- a/data/esri_extra.wkt
+++ b/data/esri_extra.wkt
@@ -7,6 +7,11 @@
 # NOTE: I'm not too clear on what version of ArcGIS these definitions were
 # derived from. 
 #
+31491,PROJCS["Germany_Zone_1",GEOGCS["GCS_Deutsches_Hauptdreiecksnetz",DATUM["D_Deutsches_Hauptdreiecksnetz",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",1500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",3.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG","31491"]]
+31492,PROJCS["Germany_Zone_2",GEOGCS["GCS_Deutsches_Hauptdreiecksnetz",DATUM["D_Deutsches_Hauptdreiecksnetz",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",2500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",6.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG","31492"]]
+31493,PROJCS["Germany_Zone_3",GEOGCS["GCS_Deutsches_Hauptdreiecksnetz",DATUM["D_Deutsches_Hauptdreiecksnetz",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",3500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",9.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG","31493"]]
+31494,PROJCS["Germany_Zone_4",GEOGCS["GCS_Deutsches_Hauptdreiecksnetz",DATUM["D_Deutsches_Hauptdreiecksnetz",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",4500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",12.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG","31494"]]
+31495,PROJCS["Germany_Zone_5",GEOGCS["GCS_Deutsches_Hauptdreiecksnetz",DATUM["D_Deutsches_Hauptdreiecksnetz",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",5500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",15.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG","31495"]]
 37001,GEOGCS["GCS_WGS_1966",DATUM["WGS_1966",SPHEROID["WGS_1966",6378145,298.25]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["EPSG","37001"]]
 37002,GEOGCS["GCS_Fischer_1960",DATUM["Fischer_1960",SPHEROID["Fischer_1960",6378166,298.3]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["EPSG","37002"]]
 37003,GEOGCS["GCS_Fischer_1968",DATUM["Fischer_1968",SPHEROID["Fischer_1968",6378150,298.3]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["EPSG","37003"]]
@@ -454,3 +459,7 @@
 104261,GEOGCS["GCS_Merchich_Degree",DATUM["Merchich",SPHEROID["Clarke_1880_IGN",6378249.2,293.46602]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["EPSG","104261"]]
 104304,GEOGCS["GCS_Voirol_1875_Degree",DATUM["Voirol_1875",SPHEROID["Clarke_1880_IGN",6378249.2,293.46602]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["EPSG","104304"]]
 104305,GEOGCS["GCS_Voirol_Unifie_1960_Degree",DATUM["Voirol_Unifie_1960",SPHEROID["Clarke_1880_RGS",6378249.145,293.465]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["EPSG","104305"]]
+
+# 102113 is defined in http://www.spatialreference.org/ref/sr-org/45/ as equivalent to EPSG:3857
+# and is used by the http://137.227.242.85/ArcGIS/services/FWS_Wetlands_WMS/mapserver/wmsserver? WMS server
+102113,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["Meter",1.0],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs"],AUTHORITY["EPSG","102113"]]
diff --git a/data/gcs.csv b/data/gcs.csv
index 8d1e345..c560fdc 100644
--- a/data/gcs.csv
+++ b/data/gcs.csv
@@ -25,7 +25,7 @@
 4020,Unknown datum based upon the Helmert 1906 ellipsoid,6020,"Not specified (based on Helmert 1906 ellipsoid)",6020,9122,7020,8901,0,0,6422,,0,,,,,,,,
 4021,Unknown datum based upon the Indonesian National Spheroid,6021,"Not specified (based on Indonesian National Spheroid)",6021,9122,7021,8901,0,0,6422,,0,,,,,,,,
 4022,Unknown datum based upon the International 1924 ellipsoid,6022,"Not specified (based on International 1924 ellipsoid)",6022,9122,7022,8901,0,0,6422,,0,,,,,,,,
-4023,MOLDREF99,1032,MOLDREF99,1032,9122,7019,8901,1,0,6422,,0,,,,,,,,
+4023,MOLDREF99,1032,MOLDREF99,1032,9122,7019,8901,1,0,6422,5585,0,9603,0,0,0,,,,
 4024,Unknown datum based upon the Krassowsky 1940 ellipsoid,6024,"Not specified (based on Krassowsky 1940 ellipsoid)",6024,9122,7024,8901,0,0,6422,,0,,,,,,,,
 4025,Unknown datum based upon the NWL 9D ellipsoid,6025,"Not specified (based on NWL 9D ellipsoid)",6025,9122,7025,8901,0,0,6422,,0,,,,,,,,
 4027,Unknown datum based upon the Plessis 1817 ellipsoid,6027,"Not specified (based on Plessis 1817 ellipsoid)",6027,9122,7027,8901,0,0,6422,,0,,,,,,,,
@@ -83,11 +83,11 @@
 4149,CH1903,6149,CH1903,6149,9122,7004,8901,1,0,6422,1766,1,9603,674.4,15.1,405.3,,,,
 4150,"CH1903+",6150,"CH1903+",6150,9122,7004,8901,1,0,6422,1676,0,9603,674.374,15.056,405.346,,,,
 4151,CHTRF95,6151,Swiss Terrestrial Reference Frame 1995,6151,9122,7019,8901,1,0,6422,1511,0,9603,0,0,0,,,,
-4152,"NAD83(HARN)",6152,"NAD83 (High Accuracy Regional Network)",6152,9122,7019,8901,1,0,6422,1580,1,9603,0,0,0,,,,
+4152,"NAD83(HARN)",6152,"NAD83 (High Accuracy Reference Network)",6152,9122,7019,8901,1,0,6422,1580,1,9603,0,0,0,,,,
 4153,Rassadiran,6153,Rassadiran,6153,9122,7022,8901,1,0,6422,1512,0,9603,-133.63,-157.5,-158.62,,,,
 4154,"ED50(ED77)",6154,"European Datum 1950(1977)",6154,9122,7022,8901,1,0,6422,1141,1,9603,-117,-132,-164,,,,
 4155,Dabola 1981,6155,Dabola 1981,6155,9122,7011,8901,1,0,6422,1518,0,9603,-83,37,124,,,,
-4156,S-JTSK,6156,Jednotne Trigonometricke Site Katastralni,6156,9122,7004,8901,1,0,6422,15965,1,9603,589,76,480,,,,
+4156,S-JTSK,6156,System Jednotne Trigonometricke Site Katastralni,6156,9122,7004,8901,1,0,6422,15965,1,9603,589,76,480,,,,
 4157,Mount Dillon,6157,Mount Dillon,6157,9122,7007,8901,1,0,6422,,0,,,,,,,,
 4158,Naparima 1955,6158,Naparima 1955,6158,9122,7022,8901,1,0,6422,1555,1,9603,-0.465,372.095,171.736,,,,
 4159,ELD79,6159,European Libyan Datum 1979,6159,9122,7022,8901,1,0,6422,15909,1,9603,-115.8543,-99.0583,-152.4616,,,,
@@ -111,7 +111,7 @@
 4178,"Pulkovo 1942(83)",6178,"Pulkovo 1942(83)",6178,9122,7024,8901,1,0,6422,15998,1,9603,26,-121,-78,,,,
 4179,"Pulkovo 1942(58)",6179,"Pulkovo 1942(58)",6179,9122,7024,8901,1,0,6422,1645,1,9606,33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84
 4180,EST97,6180,Estonia 1997,6180,9122,7019,8901,1,0,6422,1649,0,9603,0,0,0,,,,
-4181,Luxembourg 1930,6181,Luxembourg 1930,6181,9122,7022,8901,1,0,6422,1643,0,9606,-193,13.7,-39.3,-0.41,-2.933,2.688,0.43
+4181,Luxembourg 1930,6181,Luxembourg 1930,6181,9122,7022,8901,1,0,6422,5486,1,9607,-189.6806,18.3463,-42.7695,0.33746,3.09264,-2.53861,0.4598
 4182,Azores Occidental 1939,6182,Azores Occidental Islands 1939,6182,9122,7022,8901,1,0,6422,1887,1,9603,-425,-169,81,,,,
 4183,Azores Central 1948,6183,Azores Central Islands 1948,6183,9122,7022,8901,1,0,6422,1886,0,9603,-104,167,-38,,,,
 4184,Azores Oriental 1940,6184,Azores Oriental Islands 1940,6184,9122,7022,8901,1,0,6422,1885,0,9603,-203,141,53,,,,
@@ -122,13 +122,13 @@
 4191,Albanian 1987,6191,Albanian 1987,6191,9122,7024,8901,1,0,6422,,0,,,,,,,,
 4192,Douala 1948,6192,Douala 1948,6192,9122,7022,8901,1,0,6422,15873,0,9603,-206.1,-174.7,-87.7,,,,
 4193,Manoca 1962,6193,Manoca 1962,6193,9122,7011,8901,1,0,6422,1796,0,9603,-70.9,-151.8,-41.4,,,,
-4194,Qornoq 1927,6194,Qornoq 1927,6194,9122,7022,8901,1,0,6422,1798,1,9606,163.511,127.533,-159.789,0,0,0.814,-0.6
+4194,Qornoq 1927,6194,Qornoq 1927,6194,9122,7022,8901,1,0,6422,1797,1,9603,164,138,-189,,,,
 4195,Scoresbysund 1952,6195,Scoresbysund 1952,6195,9122,7022,8901,1,0,6422,1799,0,9606,105,326,-102.5,0,0,0.814,-0.6
 4196,Ammassalik 1958,6196,Ammassalik 1958,6196,9122,7022,8901,1,0,6422,1800,0,9606,-45,417,-3.5,0,0,0.814,-0.6
 4197,Garoua,6197,Garoua,6197,9122,7012,8901,1,0,6422,,0,,,,,,,,
 4198,Kousseri,6198,Kousseri,6198,9122,7012,8901,1,0,6422,,0,,,,,,,,
 4199,Egypt 1930,6199,Egypt 1930,6199,9122,7022,8901,1,0,6422,,0,,,,,,,,
-4200,Pulkovo 1995,6200,Pulkovo 1995,6200,9122,7024,8901,1,0,6422,1281,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12
+4200,Pulkovo 1995,6200,Pulkovo 1995,6200,9122,7024,8901,1,0,6422,5043,1,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22
 4201,Adindan,6201,Adindan,6201,9122,7012,8901,1,0,6422,1100,1,9603,-166,-15,204,,,,
 4202,AGD66,6202,Australian Geodetic Datum 1966,6202,9122,7003,8901,1,0,6422,15980,1,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29
 4203,AGD84,6203,Australian Geodetic Datum 1984,6203,9122,7003,8901,1,0,6422,1109,1,9603,-134,-48,149,,,,
@@ -136,7 +136,7 @@
 4205,Afgooye,6205,Afgooye,6205,9122,7024,8901,1,0,6422,1107,0,9603,-43,-163,45,,,,
 4206,Agadez,6206,Agadez,6206,9122,7011,8901,1,0,6422,,0,,,,,,,,
 4207,Lisbon,6207,Lisbon 1937,6207,9122,7022,8901,1,0,6422,1984,1,9603,-304.046,-60.576,103.64,,,,
-4208,Aratu,6208,Aratu,6208,9122,7022,8901,1,0,6422,10093,1,9603,-161,308,-142,,,,
+4208,Aratu,6208,Aratu,6208,9122,7022,8901,1,0,6422,5067,1,9603,-151.99,287.04,-147.45,,,,
 4209,Arc 1950,6209,Arc 1950,6209,9122,7013,8901,1,0,6422,1113,1,9603,-143,-90,-294,,,,
 4210,Arc 1960,6210,Arc 1960,6210,9122,7012,8901,1,0,6422,1122,1,9603,-160,-6,-302,,,,
 4211,Batavia,6211,Batavia,6211,9122,7004,8901,1,0,6422,1123,1,9603,-377,681,-50,,,,
@@ -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,6225,Corrego Alegre,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,0,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,,,,,,,,
@@ -195,7 +195,7 @@
 4265,Monte Mario,6265,Monte Mario,6265,9122,7022,8901,1,0,6422,1660,1,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68
 4266,"M'poraloko",6266,"M'poraloko",6266,9122,7011,8901,1,0,6422,1163,1,9603,-74,-130,42,,,,
 4267,NAD27,6267,North American Datum 1927,6267,9122,7008,8901,1,0,6422,,0,,,,,,,,
-4268,NAD27 Michigan,6268,NAD Michigan,6268,9122,7009,8901,1,0,6422,,0,,,,,,,,
+4268,NAD27 Michigan,6268,NAD27 Michigan,6268,9122,7009,8901,1,0,6422,,0,,,,,,,,
 4269,NAD83,6269,North American Datum 1983,6269,9122,7019,8901,1,0,6422,1188,1,9603,0,0,0,,,,
 4270,Nahrwan 1967,6270,Nahrwan 1967,6270,9122,7012,8901,1,0,6422,1190,1,9603,-243,-192,477,,,,
 4271,Naparima 1972,6271,Naparima 1972,6271,9122,7022,8901,1,0,6422,1192,1,9603,-10,375,165,,,,
@@ -204,7 +204,7 @@
 4274,Datum 73,6274,Datum 73,6274,9122,7022,8901,1,0,6422,1983,1,9603,-223.237,110.193,36.649,,,,
 4275,NTF,6275,Nouvelle Triangulation Francaise,6275,9122,7011,8901,1,0,6422,1193,0,9603,-168,-60,320,,,,
 4276,NSWC 9Z-2,6276,NSWC 9Z-2,6276,9122,7025,8901,1,0,6422,,0,,,,,,,,
-4277,OSGB 1936,6277,OSGB 1936,6277,9122,7001,8901,1,0,6422,1314,1,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489
+4277,OSGB 1936,6277,OSGB 1936,6277,9122,7001,8901,1,0,6422,1195,1,9603,375,-111,431,,,,
 4278,OSGB70,6278,"OSGB 1970 (SN)",6278,9122,7001,8901,1,0,6422,,0,,,,,,,,
 4279,"OS(SN)80",6279,"OS (SN) 1980",6279,9122,7001,8901,1,0,6422,,0,,,,,,,,
 4280,Padang,6280,Padang 1884,6280,9122,7004,8901,1,0,6422,,0,,,,,,,,
@@ -212,7 +212,7 @@
 4282,Pointe Noire,6282,Congo 1960 Pointe Noire,6282,9122,7011,8901,1,0,6422,1200,1,9603,-148,51,-291,,,,
 4283,GDA94,6283,Geocentric Datum of Australia 1994,6283,9122,7019,8901,1,0,6422,1150,0,9603,0,0,0,,,,
 4284,Pulkovo 1942,6284,Pulkovo 1942,6284,9122,7024,8901,1,0,6422,1267,1,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12
-4285,Qatar 1974,6285,Qatar 1974,6285,9122,7022,8901,1,0,6422,1561,1,9603,-128,-283,22,,,,
+4285,Qatar 1974,6285,Qatar 1974,6285,9122,7022,8901,1,0,6422,1562,1,9603,-128.16,-282.42,21.93,,,,
 4286,Qatar 1948,6286,Qatar 1948,6286,9122,7020,8901,1,0,6422,,0,,,,,,,,
 4287,Qornoq,6287,Qornoq,6287,9108,7022,8901,1,1,6402,1211,0,9603,164,138,-189,,,,
 4288,Loma Quintana,6288,Loma Quintana,6288,9122,7022,8901,1,0,6422,,0,,,,,,,,
@@ -227,18 +227,18 @@
 4298,Timbalai 1948,6298,Timbalai 1948,6298,9122,7016,8901,1,0,6422,1852,1,9606,-533.4,669.2,-52.5,0,0,4.28,9.4
 4299,TM65,6299,TM65,6299,9122,7002,8901,1,0,6422,1641,1,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15
 4300,TM75,6300,Geodetic Datum of 1965,6300,9122,7002,8901,1,0,6422,1954,1,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15
-4301,Tokyo,6301,Tokyo,6301,9122,7004,8901,1,0,6422,1231,1,9603,-148,507,685,,,,
+4301,Tokyo,6301,Tokyo,6301,9122,7004,8901,1,0,6422,15484,1,9603,-146.414,507.337,680.507,,,,
 4302,Trinidad 1903,6302,Trinidad 1903,6302,9122,7007,8901,1,0,6422,1296,1,9603,-61.702,284.488,472.052,,,,
 4303,"TC(1948)",6303,Trucial Coast 1948,6303,9122,7020,8901,1,0,6422,,0,,,,,,,,
 4304,Voirol 1875,6304,Voirol 1875,6304,9122,7011,8901,1,0,6422,1294,0,9603,-73,-247,227,,,,
 4306,Bern 1938,6306,Bern 1938,6306,9122,7004,8901,1,0,6422,,0,,,,,,,,
 4307,Nord Sahara 1959,6307,Nord Sahara 1959,6307,9122,7012,8901,1,0,6422,1253,1,9603,-186,-93,310,,,,
 4308,RT38,6308,Stockholm 1938,6308,9122,7004,8901,1,0,6422,,0,,,,,,,,
-4309,Yacare,6309,Yacare,6309,9122,7022,8901,1,0,6422,1234,0,9603,-155,171,37,,,,
+4309,Yacare,6309,Yacare,6309,9122,7022,8901,1,0,6422,1234,1,9603,-155,171,37,,,,
 4310,Yoff,6310,Yoff,6310,9122,7011,8901,1,0,6422,,0,,,,,,,,
 4311,Zanderij,6311,Zanderij,6311,9122,7022,8901,1,0,6422,1235,0,9603,-265,120,-358,,,,
 4312,MGI,6312,Militar-Geographische Institut,6312,9122,7004,8901,1,0,6422,1618,1,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232
-4313,Belge 1972,6313,Reseau National Belge 1972,6313,9122,7022,8901,1,0,6422,15749,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747
+4313,Belge 1972,6313,Reseau National Belge 1972,6313,9122,7022,8901,1,0,6422,15929,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747
 4314,DHDN,6314,Deutsches Hauptdreiecksnetz,6314,9122,7004,8901,1,0,6422,1777,1,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7
 4315,Conakry 1905,6315,Conakry 1905,6315,9122,7011,8901,1,0,6422,1517,0,9603,-23,259,-9,,,,
 4316,Dealul Piscului 1930,6316,Dealul Piscului 1930,6316,9122,7022,8901,1,0,6422,1995,1,9603,103.25,-100.4,-307.19,,,,
@@ -279,7 +279,7 @@
 4621,Fort Marigot,6621,Fort Marigot,6621,9122,7022,8901,1,0,6422,1903,0,9603,137,248,-430,,,,
 4622,Guadeloupe 1948,6622,Guadeloupe 1948,6622,9122,7022,8901,1,0,6422,1904,1,9603,-467,-16,-300,,,,
 4623,CSG67,6623,Centre Spatial Guyanais 1967,6623,9122,7022,8901,1,0,6422,1906,0,9603,-186,230,110,,,,
-4624,RGFG95,6624,Reseau Geodesique Francais Guyane 1995,6624,9122,7019,8901,1,0,6422,1907,0,9603,2,2,-2,,,,
+4624,RGFG95,6624,Reseau Geodesique Francais Guyane 1995,6624,9122,7019,8901,1,0,6422,4840,1,9603,0,0,0,,,,
 4625,Martinique 1938,6625,Martinique 1938,6625,9122,7022,8901,1,0,6422,1909,1,9603,186,482,151,,,,
 4626,Reunion 1947,6626,Reunion 1947,6626,9122,7022,8901,1,0,6422,15751,1,9603,94,-948,-1262,,,,
 4627,RGR92,6627,Reseau Geodesique de la Reunion 1992,6627,9122,7019,8901,1,0,6422,1912,0,9603,0,0,0,,,,
@@ -301,10 +301,10 @@
 4643,ST71 Belep,6643,ST71 Belep,6643,9122,7022,8901,1,0,6422,1931,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002
 4644,NEA74 Noumea,6644,NEA74 Noumea,6644,9122,7022,8901,1,0,6422,15904,1,9603,-10.18,-350.43,291.37,,,,
 4645,RGNC 1991,6645,Reseau Geodesique Nouvelle Caledonie 1991,6645,9122,7022,8901,1,1,6422,1920,0,9603,0,0,0,,,,
-4646,Grand Comoros,6646,Grand Comoros,6646,9122,7022,8901,1,0,6422,,0,,,,,,,,
+4646,Grand Comoros,6646,Grand Comoros,6646,9122,7022,8901,1,0,6422,5521,0,9603,-963,510,-359,,,,
 4657,Reykjavik 1900,6657,Reykjavik 1900,6657,9122,7051,8901,1,0,6422,1994,0,9603,-28,199,5,,,,
 4658,Hjorsey 1955,6658,Hjorsey 1955,6658,9122,7022,8901,1,0,6422,1951,0,9603,-73,46,-86,,,,
-4659,ISN93,6659,Islands Network 1993,6659,9122,7019,8901,1,0,6422,1952,0,9603,0,0,0,,,,
+4659,ISN93,6659,Islands Net 1993,6659,9122,7019,8901,1,0,6422,1952,0,9603,0,0,0,,,,
 4660,Helle 1954,6660,Helle 1954,6660,9122,7022,8901,1,0,6422,1957,0,9606,982.6087,552.753,-540.873,6.68162662527694,-31.6114924086422,-19.8481610048168,16.805
 4661,LKS92,6661,Latvia 1992,6661,9122,7019,8901,1,0,6422,1958,0,9603,0,0,0,,,,
 4662,IGN72 Grande Terre,6634,IGN72 Grande Terre,6634,9122,7022,8901,1,0,6422,15903,1,9603,-11.64,-348.6,291.98,,,,
@@ -319,7 +319,7 @@
 4671,Voirol 1879,6671,Voirol 1879,6671,9122,7011,8901,1,0,6422,,0,,,,,,,,
 4672,Chatham Islands 1971,6672,Chatham Islands Datum 1971,6672,9122,7022,8901,1,0,6422,1080,0,9603,175,-38,113,,,,
 4673,Chatham Islands 1979,6673,Chatham Islands Datum 1979,6673,9122,7022,8901,1,0,6422,1081,0,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263
-4674,SIRGAS 2000,6674,Sistema de Referencia Geocentrico para America del Sur 2000,6674,9122,7019,8901,1,0,6422,15894,0,9603,0,0,0,,,,
+4674,SIRGAS 2000,6674,Sistema de Referencia Geocentrico para las AmericaS 2000,6674,9122,7019,8901,1,0,6422,15894,0,9603,0,0,0,,,,
 4675,Guam 1963,6675,Guam 1963,6675,9122,7008,8901,1,0,6422,1070,0,9603,-100,-248,259,,,,
 4676,Vientiane 1982,6676,Vientiane 1982,6676,9122,7024,8901,1,0,6422,,0,,,,,,,,
 4677,Lao 1993,6677,Lao 1993,6677,9122,7024,8901,1,0,6422,,0,,,,,,,,
@@ -335,7 +335,7 @@
 4687,RGPF,6687,Reseau Geodesique de la Polynesie Francaise,6687,9122,7019,8901,1,0,6422,15832,1,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093
 4688,Fatu Iva 72,6688,Fatu Iva 72,6688,9122,7022,8901,1,0,6422,15772,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074
 4689,IGN63 Hiva Oa,6689,IGN63 Hiva Oa,6689,9122,7022,8901,1,0,6422,15773,1,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311
-4690,Tahiti 79,6690,Tahiti 79,6690,9122,7022,8901,1,0,6422,,0,,,,,,,,
+4690,Tahiti 79,6690,Tahiti 79,6690,9122,7022,8901,1,0,6422,4835,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741
 4691,Moorea 87,6691,Moorea 87,6691,9122,7022,8901,1,0,6422,15769,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773
 4692,Maupiti 83,6692,Maupiti 83,6692,9122,7022,8901,1,0,6422,15771,0,9603,217.037,86.959,23.956,,,,
 4693,Nakhl-e Ghanem,6693,Nakhl-e Ghanem,6693,9122,7030,8901,1,0,6422,15746,0,9603,0,-0.15,0.68,,,,
@@ -388,7 +388,7 @@
 4740,PZ-90,6740,Parametrop Zemp 1990,6740,9122,7054,8901,1,0,6422,15843,1,9607,0,0,1.5,0,0,-0.076,0
 4741,FD54,6741,Faroe Datum 1954,6741,9122,7022,8901,1,0,6422,,0,,,,,,,,
 4742,GDM2000,6742,Geodetic Datum of Malaysia 2000,6742,9122,7019,8901,1,0,6422,,0,,,,,,,,
-4743,Karbala 1979,6743,Karbala 1979,6743,9122,7012,8901,1,0,6422,15872,0,9603,84.1,-320.1,218.7,,,,
+4743,Karbala 1979,6743,Karbala 1979,6743,9122,7012,8901,1,0,6422,5078,1,9603,70.995,-335.916,262.898,,,,
 4744,Nahrwan 1934,6744,Nahrwan 1934,6744,9122,7012,8901,1,0,6422,,0,,,,,,,,
 4745,"RD/83",6745,"Rauenberg Datum/83",6745,9122,7004,8901,1,0,6422,,0,,,,,,,,
 4746,"PD/83",6746,"Potsdam Datum/83",6746,9122,7004,8901,1,0,6422,,0,,,,,,,,
@@ -401,7 +401,7 @@
 4753,fk89,6753,fk89,6753,9122,7022,8901,1,0,6422,,0,,,,,,,,
 4754,LGD2006,6754,Libyan Geodetic Datum 2006,6754,9122,7022,8901,1,0,6422,15908,0,9603,-208.4058,-109.8777,-2.5764,,,,
 4755,DGN95,6755,Datum Geodesi Nasional 1995,6755,9122,7030,8901,1,0,6422,15912,0,9603,0,0,0,,,,
-4756,VN-2000,6756,Vietnam 2000,6756,9122,7030,8901,1,0,6422,,0,,,,,,,,
+4756,VN-2000,6756,Vietnam 2000,6756,9122,7030,8901,1,0,6422,5194,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188
 4757,SVY21,6757,SVY21,6757,9122,7030,8901,1,0,6422,,0,,,,,,,,
 4758,JAD2001,6758,Jamaica 2001,6758,9122,7030,8901,1,0,6422,15925,0,9603,0,0,0,,,,
 4759,"NAD83(NSRS2007)",6759,"NAD83 (National Spatial Reference System 2007)",6759,9122,7019,8901,1,0,6422,15931,0,9603,0,0,0,,,,
@@ -427,7 +427,7 @@
 4815,"Greek (Athens)",6815,"Greek (Athens)",6120,9122,7004,8912,1,0,6422,,0,,,,,,,,
 4816,"Carthage (Paris)",6816,"Carthage (Paris)",6223,9105,7011,8903,1,0,6403,1130,1,9603,-263,6,431,,,,
 4817,"NGO 1948 (Oslo)",6817,"NGO 1948 (Oslo)",6273,9122,7005,8913,1,0,6422,1654,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21
-4818,"S-JTSK (Ferro)",6818,"S-JTSK (Ferro)",6156,9122,7004,8909,1,0,6422,15965,1,9603,589,76,480,,,,
+4818,"S-JTSK (Ferro)",6818,"System Jednotne Trigonometricke Site Katastralni (Ferro)",6156,9122,7004,8909,1,0,6422,15965,1,9603,589,76,480,,,,
 4819,"Nord Sahara 1959 (Paris)",6819,"Nord Sahara 1959 (Paris)",6307,9105,7012,8903,1,1,6403,1253,1,9603,-186,-93,310,,,,
 4820,"Segara (Jakarta)",6820,"Gunung Segara (Jakarta)",6613,9122,7004,8908,1,0,6422,1897,1,9603,-403,684,41,,,,
 4821,"Voirol 1879 (Paris)",6821,"Voirol 1879 (Paris)",6821,9105,7011,8903,1,0,6403,,0,,,,,,,,
@@ -437,3 +437,27 @@
 4902,"NDG (Paris)",6902,"Nord de Guerre (Paris)",6902,9105,7027,8903,1,1,6403,,0,,,,,,,,
 4903,"Madrid 1870 (Madrid)",6903,"Madrid 1870 (Madrid)",6903,9122,7028,8905,1,0,6422,,0,,,,,,,,
 4904,"Lisbon 1890 (Lisbon)",6904,"Lisbon 1890 (Lisbon)",6666,9122,7004,8902,1,0,6422,1986,1,9603,508.088,-191.042,565.223,,,,
+5013,PTRA08,1041,Autonomous Regions of Portugal 2008,1041,9122,7019,8901,1,0,6422,4905,0,9603,0,0,0,,,,
+5132,Tokyo 1892,1048,Tokyo 1892,6162,9122,7004,8901,1,0,6422,,0,,,,,,,,
+5228,"S-JTSK/05",1052,"System Jednotne Trigonometricke Site Katastralni/05",1052,9122,7004,8901,1,0,6422,5227,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378
+5229,"S-JTSK/05 (Ferro)",1055,"System Jednotne Trigonometricke Site Katastralni/05 (Ferro)",1052,9122,7004,8909,1,0,6422,5227,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378
+5233,SLD99,1053,Sri Lanka Datum 1999,1053,9122,7015,8901,1,0,6422,5236,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338
+5246,GDBD2009,1056,Geocentric Datum Brunei Darussalam 2009,1056,9122,7019,8901,1,0,6422,,0,,,,,,,,
+5252,TUREF,1057,Turkish National Reference Frame,1057,9122,7019,8901,1,0,6422,5261,0,9603,0,0,0,,,,
+5264,DRUKREF 03,1058,Bhutan National Geodetic Datum,1058,9122,7019,8901,1,0,6422,5267,0,9603,0,0,0,,,,
+5324,ISN2004,1060,Islands Net 2004,1060,9122,7019,8901,1,0,6422,5327,0,9603,0,0,0,,,,
+5340,POSGAR 2007,1062,Posiciones Geodesicas Argentinas 2007,1062,9122,7019,8901,1,0,6422,5351,0,9603,0,0,0,,,,
+5354,MARGEN,1063,Marco Geodesico Nacional,1063,9122,7019,8901,1,0,6422,5374,0,9603,0,0,0,,,,
+5360,SIRGAS-Chile,1064,SIRGAS-Chile,1064,9122,7019,8901,1,0,6422,5375,0,9603,0,0,0,,,,
+5365,CR05,1065,Costa Rica 2005,1065,9122,7030,8901,1,0,6422,5376,0,9603,0,0,0,,,,
+5371,MACARIO SOLIS,1066,Sistema Geodesico Nacional de Panama MACARIO SOLIS,1066,9122,7019,8901,1,0,6422,5377,0,9603,0,0,0,,,,
+5373,Peru96,1067,Peru96,1067,9122,7019,8901,1,0,6422,5378,0,9603,0,0,0,,,,
+5381,SIRGAS-ROU98,1068,SIRGAS-ROU98,1068,9122,7030,8901,1,0,6422,5384,0,9603,0,0,0,,,,
+5393,"SIRGAS_ES2007.8",1069,"SIRGAS_ES2007.8",1069,9122,7019,8901,1,0,6422,5395,0,9603,0,0,0,,,,
+5451,Ocotepeque 1935,1070,Ocotepeque 1935,1070,9122,7008,8901,1,0,6422,5470,1,9603,213.11,9.37,-74.95,,,,
+5464,Sibun Gorge 1922,1071,Sibun Gorge 1922,1071,9122,7007,8901,1,0,6422,,0,,,,,,,,
+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,,,,,,,,
+5546,PNG94,1076,Papua New Guinea Geodetic Datum 1994,1076,9122,7019,8901,1,0,6422,5553,0,9603,0,0,0,,,,
diff --git a/data/gdal_datum.csv b/data/gdal_datum.csv
index 902ee33..87ecdd2 100644
--- a/data/gdal_datum.csv
+++ b/data/gdal_datum.csv
@@ -3,28 +3,60 @@
 1025,Taiwan Datum 1967,geodetic,"Fundamental point: Hu Tzu Shan. Latitude: 23°58'32.34""N, longitude: 120°58'25.975""E (of Greenwich).",1967,7050,8901,3315,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Adopted in 1980. TWD67 uses the GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places.","National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,
 1026,Taiwan Datum 1997,geodetic,ITRF94 at epoch 1997.0,1997,7019,8901,1228,"Geodetic survey, GIS, topographic mapping, engineering survey.",Adopted in 1998.,"National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,
 1027,EGM2008 geoid,vertical,WGS 84 ellipsoid.,2008,,,1262,Geodesy.,,"http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/egm08_wgs84.html",OGP,"2009/01/30",2008.097,0,
-1028,Fao 1979,vertical,"Average sea level at Fao during two-year period in mid/late 1970s.",1979,,,3625,"Topographic mapping, geodetic survey.","Replaces Fao (datum code 5149) in Iraq.","Survey Division, Ministry of Water Resources (MoWR).",OGP,"2009/03/01",2009.003,0,
+1028,Fao 1979,vertical,"Average sea level at Fao during two-year period in mid/late 1970s.",1979,,,3625,"Topographic mapping, geodetic survey.","Levelling network established by Polservice consortium.  Replaces Fao (datum code 5149) in Iraq.","Survey Division, Ministry of Water Resources (MoWR).",OGP,"2010/03/01",2009.003 2010.014,0,
 1029,Iraqi Geospatial Reference System,geodetic,ITRF2000 at epoch 1997.0,2000,7019,8901,1124,Geodetic survey.,,"Survey Division, Ministry of Water Resources (MoWR).",OGP,"2009/02/03",2009.003,0,
+1030,N2000,vertical,"Height at Metsaahovi (latitude 60.21762°N, longitude 24.39517°E) of 54.4233m related to EVRF2000 origin through Baltic Levelling Ring adjustment at epoch 2000.0.",2000,,,3333,"Topographic mapping, geodetic survey.","Realised through the third precise levelling network. Uses normal heights. Replaces N60 (datum code 5116). To account for isostatic land uplift use NKG2005 model.","National Land Survey of Finland;
+http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 1031,MGI 1901,geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 16°17'55.04""E (of Greenwich).",1901,7004,8901,2370,Geodetic survey.,"The longitude of the datum origin equates to the Albrecht 1902 value for the Ferro meridian of 17°39'46.02"" west of Greenwich. Densified in 1948.","The Ferro prime meridian, Gabor Timar (2007), Geodezia es Kartografia vol 59 issue 12 pages 3-7.",OGP,"2009/05/10",2009.015,0,
-1032,MOLDREF99,geodetic,Densification of ETRS89.,1999,7019,8901,1162,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"State Agency for Land Relations & Cadastre.",OGP,"2009/05/11",2009.026,0,"D_International_1967"
+1032,MOLDREF99,geodetic,Densification of ETRS89.,1999,7019,8901,1162,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"State Agency for Land Relations & Cadastre.",OGP,"2009/05/11",2009.026,0,"D_MOLDREF99"
 1033,Reseau Geodesique de la RDC 2005,geodetic,ITRF2000 at epoch 2005.4.,2005,7019,8901,3613,Geodetic survey.,,"""Revision du Tiers Meridional du Reseau Geodesique de la RDC"", COPIREP Reclus project report, 2005.",OGP,"2009/04/16",2009.011,0,
 1034,Serbian Reference Network 1998,geodetic,"Densification of ETRS89 in Serbia at epoch 1998.7 based on coordinates of 6 stations in Serbia of Yugoslav Reference Frame (YUREF) 1998 campaign.",1998,7019,8901,3534,Geodesy.,Observed 1998-2003.,"Delcev et al, FIG Working Week May 2009; http://www.gig.net/pub",OGP,"2009/05/11",2009.015,0,
 1035,Red Geodesica de Canarias 1995,geodetic,ITRF93 at epoch 1994.9 at VLBI station Maspalomas on Grand Canary.,1995,7019,8901,3199,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Pico de las Nieves 1984 (PN84).","IGN Madrid. http://www.fomento.es.",OGP,"2009/05/15",2009.033,0,
 1036,Reseau Geodesique de Mayotte 2004,geodetic,ITRF2000 at epoch 2004.0,2004,7019,8901,1159,"Geodetic survey, topographic mapping, engineering survey.","Replaces Combani 1950 (datum code 6632) except for cadastral purposes. (Cadastre 1997 (datum code 1037) used for cadastral purposes).",IGN Paris.,OGP,"2009/10/02",2009.072,0,
 1037,Cadastre 1997,geodetic,Coordinates of 1 station of Combani 1950 adjustment held fixed.,1997,7022,8901,3340,Cadastral survey.,Derived by adjustment of GPS-observed network which was constrained to Combani 1950 coordinates of one station.,CERTU.,OGP,"2009/10/02",2009.072,0,
 1038,Reseau Geodesique de Saint Pierre et Miquelon 2006,geodetic,ITRF2000 at epoch 2006.0,2006,7019,8901,1220,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Saint Pierre et Miquelon 1950 (datum code 6638).",IGN Paris.,OGP,"2009/10/02",2009.072,0,
-1039,New Zealand Vertical Datum 2009,vertical,New Zealand Quasigeoid 2009 which is defined by the application of the NZ geoid 2009 grid to NZGD2000 ellipsoidal heights. See transformation code 4459.,2009,,,1175,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2009/10/28",2009.081,0,
-1040,Dunedin-Bluff 1960,vertical,Common adjustment of Dunedin 1958 and Bluff 1955 networks.,1960,,,1501,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2009/10/20",2009.081,0,
-1042,Mexican Datum of 1993,geodetic,ITRF1992 at epoch 1988.00.,1993,7019,8901,1160,Geodetic survey.,"Realised by a frame of 20 active GPS stations observed and adjusted in the ITRF1992. Includes ties to tide gauges. Replaces NAD27 (code 6267). Replaced by SIRGAS 2000 (code 6674).","National Densifications per http://www.sirgas.org. See also www.fig.net/pub/cairo/papers/ts_13/ts13_03_hansen.pdf.",OGP,"2009/11/24",2009.087,0,
+1039,New Zealand Vertical Datum 2009,vertical,New Zealand Quasigeoid 2009 which is defined by the application of the NZ geoid 2009 grid to NZGD2000 ellipsoidal heights. See transformation code 4459.,2009,,,3285,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2011/01/25",2009.081 2011.004,0,
+1040,Dunedin-Bluff 1960,vertical,Common adjustment of Dunedin 1958 and Bluff 1955 networks.,1960,,,3806,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2011/01/25",2009.081 2011.005,0,
+1041,Autonomous Regions of Portugal 2008,geodetic,"ITRF93 as derived from the 1994 TransAtlantic Network for Geodynamics and Oceanography (TANGO) project.",1994,7019,8901,3670,Geodetic survey.,Replaces older classical datums for Azores and Madeira archipelagos.,"Instituto Geografico Portugues; http://www.igeo.pt",OGP,"2010/03/30",2010.006,0,
+1042,Mexican Datum of 1993,geodetic,ITRF1992 at epoch 1988.00.,1993,7019,8901,1160,Geodetic survey.,"Realised by a frame of 15 active GPS stations observed and adjusted in the ITRF1992. Includes ties to tide gauges. Replaces NAD27 (code 6267).","National Densifications per http://www.sirgas.org. See also www.fig.net/pub/cairo/papers/ts_13/ts13_03_hansen.pdf.",OGP,"2010/11/02",2009.087 2010.090,0,
 1043,China 2000,geodetic,ITRF97 at epoch 2000.0,2000,1024,8901,3228,"Geodetic survey, topographic and engineering survey.",Combined adjustment of astro-geodetic observations as used for Xian 1980 and GPS control network observed 2000-2003. Adopted July 2008.,Chinese Academy of Surveying and Mapping.,OGP,"2009/11/12",2009.084,0,
 1044,Sao Tome,geodetic,"Fundamental point: Fortaleza. Latitude: 0°20'49.02""N, longitude: 6°44'41.85""E (of Greenwich).",,7022,8901,3645,"Topographic mapping, geodetic survey.",,"US Department of State Bureau of Intelligence and Research ""Limits in the Sea"" series #98.",OGP,"2009/11/24",2009.098,0,
-1045,New Beijing,geodetic,Derived by conformal transformation of Xian 1980 adjustment onto Krassowsky ellipsoid.,1982,7024,8901,1067,Topographic mapping.,From 1982 replaces Beijing 1954.,"Chinese Science Bulletin, 2009, 54:2714-2721.",OGP,"2009/11/15",2009.092,0,
+1045,New Beijing,geodetic,Derived by conformal transformation of Xian 1980 adjustment onto Krassowsky ellipsoid.,1982,7024,8901,3228,Topographic mapping.,From 1982 replaces Beijing 1954.,"Chinese Science Bulletin, 2009, 54:2714-2721.",OGP,"2010/03/01",2009.092 2010.014,0,
 1046,Principe,geodetic,"Fundamental point: Morro do Papagaio. Latitude: 1°36'46.87""N, longitude: 7°23'39.65""E (of Greenwich).",,7022,8901,3646,"Topographic mapping, geodetic survey.",,"US Department of State Bureau of Intelligence and Research ""Limits in the Sea"" series #98.",OGP,"2009/11/24",2009.098,0,
-1047,Reseau de Reference des Antilles Francaises 1991,geodetic,WGS 84 coordinates of a single station determined during the 1988 Tango mission.,1991,7019,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Fort Marigot and Sainte Anne (datum codes 6621-22) in Guadeloupe and Fort Desaix (datum code 6625) in Martinique.",IGN Paris.,OGP,"2009/11/05",2009.073,0,
+1047,Reseau de Reference des Antilles Francaises 1991,geodetic,WGS 84 coordinates of a single station determined during the 1988 Tango mission.,1991,7019,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Fort Marigot and Sainte Anne (datum codes 6621-22) in Guadeloupe and Fort Desaix (datum code 6625) in Martinique. Replaced by Reseau Geodesique des Antilles Francaises 2009 (datum code 1073).",IGN Paris.,OGP,"2011/05/09",2009.073 2011.030,0,
+1048,Tokyo 1892,geodetic,"Fundamental point: Nikon-Keido-Genten. Latitude: 35°39'17.5148""N, longitude: 139°44'30.0970""E (of Greenwich). Longitude derived in 1892.",1892,7004,8901,1364,"Cadastre, topographic mapping, engineering survey.","Extended from Japan to Korea in 1898. In Japan replaced by Tokyo 1918 (datum code 6301). In South Korea replaced by Tokyo 1918 (code 6301) only for geodetic purposes; for all other purposes replaced by Korean 1985 (code 6162).",Korean Association of Surveying and Mapping.,OGP,"2010/06/30",2010.050,0,
+1049,Incheon,vertical,MSL 1913-1916 at Incheon Bay.,1963,,,3739,"Topographic mapping, geodetic survey.",,"National Geographic Information Institute (NGII).",OGP,"2010/06/30",2010.050,0,
+1050,Trieste,vertical,"Reference point HM1(BV1)-Trieste defined relative to mean sea level at Trieste in 1875.",1875,,,2370,"Geodetic survey, topographic mapping, engineering survey.","Normal-orthometric heights. In Croatia replaced by HVRS71 (datum code 5207).","Eurogeographics, http://www.crs-geo.eu",OGP,"2010/07/12",2010.064,0,
+1051,Genoa,vertical,,1942,,,3736,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://www.crs-geo.eu",OGP,"2010/07/12",2010.064,0,
+1052,"System Jednotne Trigonometricke Site Katastralni/05",geodetic,Constrained to S-JTSK but realised through readjustment in projected CRS domain. Related to ETRS89 R05 realisation through transformation code 5226.,2009,7004,8901,1079,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Land Survey Office (ZU), Prague. www.cuzk.cz/zu",OGP,"2010/10/29",2010.071,0,
+1053,Sri Lanka Datum 1999,geodetic,"Fundamental point: ISM Diyatalawa. Latitude: 6°49'02.687""N, longitude: 80°57'40.880""E.",1999,7015,8901,3310,Topographic mapping.,Introduced in 2000.,"Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/08/07",2010.080,0,
+1054,Sri Lanka Vertical Datum,vertical,MSL at Colombo 1884-1889.,1932,,,3310,"Geodetic survey, topographic mapping, engineering survey.","Normal-orthometric heights, but often referred to as ""orthometric"".","Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/08/07",2010.080,0,
+1055,"System Jednotne Trigonometricke Site Katastralni/05 (Ferro)",geodetic,Constrained to S-JTSK but realised through readjustment in projected CRS domain.,2009,7004,8909,1079,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Land Survey Office (ZU), Prague. www.cuzk.cz/zu",OGP,"2010/10/29",2010.071,0,
+1056,Geocentric Datum Brunei Darussalam 2009,geodetic,ITRF2005 at epoch 2009.45,2009,7019,8901,1055,Geodetic survey.,Replaces use of Timbalai from July 2009.,"Survey Department, Brunei.",OGP,"2010/09/22",2010.057,0,
+1057,Turkish National Reference Frame,geodetic,ITRF96 at epoch 2005.0,2005,7019,8901,1237,Geodetic survey.,,"General Command of Mapping via EuroGeographics; http://www.crs-geo.eu/",OGP,"2010/09/06",2010.085,0,
+1058,Bhutan National Geodetic Datum,geodetic,ITRF2000 at epoch 2003.87,2000,7019,8901,1048,Geodetic survey.,,"Department of Survey and Land Records (DSLR), National Land Commission of Bhutan (NLC) via Lantmäteriet Sweden.",OGP,"2010/09/06",2010.086,0,
+1059,Faroe Islands Vertical Reference 2009,vertical,,2009,,,3248,Topographic mapping and engineering survey,Mean Tidal Height System.,"Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2010/10/27",2010.092,0,
+1060,Islands Net 2004,geodetic,ITRF2000 at epoch 2004.6.,2004,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces ISN93 (datum code 6659).","Landmaelingar Islands (National Land Survey of Iceland). http://www.lmi.is",OGP,"2010/11/12",2010.101,0,
+1061,International Terrestrial Reference Frame 2008,geodetic,Origin at geocentre. The ITRF2008 origin is defined in such a way that there are null translation parameters at epoch 2005.0 and null translation rates between the ITRF2008 and the ILRS SLR time series.,2008,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2008.0. Replaces ITRF2005 (code 6896).","IGN Paris http://itrf.ensg.ign.fr/itrs_itrf.php",OGP,"2011/01/13",2011.002,0,
+1062,Posiciones Geodesicas Argentinas 2007,geodetic,"A geodetic network of 211 high accuracy surveyed points (178 passive and 33 continuous operating) based on ITRF2005, Epoch 2006.6, that define the National Geodetic System (Sistema Geodésico Nacional) effective 15 May 2009.",2009,7019,8901,1033,"Topographic mapping, geodetic survey.","POSGAR 07 has been adopted by order of the Director of the National Geographic Institute on May 15, 2009, as the new National Geodetic Reference Frame and replaces the pre-existing POSGAR 94.","Instituto Geográfico Militar de la República Argentina, http://www.ign.gob.ar/proyectos/posgar2007/introduccion",OGP,"2011/03/24",2009.028,0,
+1063,Marco Geodesico Nacional,geodetic,"ITRF94 at epoch 1995.4.  Densification of SIRGAS95 network in Bolivia, consisting of 125 passive geodetic stations and 8 continuous recording GPS stations.",2007,7019,8901,1049,Geodetic survey.,"Densification of SIRGAS 1995 within Bolivia. Replaces PSAD56 (datum code 6248) in Bolivia.","Sistema de Referencia Geocentrico para las Americas (SIRGAS) Boletin Informativo No 12, Aug 2007 and www.sirgas.org/fileadmin/docs/Boletines/Bol12/09_Actividades_SIRGAS_en_Bolivia_Herbas.pdf by Instituto Geográfico Militar de Bolivia, June 2007.",OGP,"2011/03/20",2011.018,0,
+1064,SIRGAS-Chile,geodetic,"ITRF2000 at epoch 2002.0.  Densification of SIRGAS 2000 network in Chile, consisting of 650 monumented stations.",2007,7019,8901,1066,Geodetic survey.,"Densification of SIRGAS 2000 within Chile. Replaces PSAD56 (datum code 6248) in Chile, replaces HITO XVIII (datum code 6254) in Chilean Tierra del Fuego and replaces Easter Island 1967 (datum code 6719)  in Easter Island.","IGM Chile Report: 31_Parra_Baez_Chilean_part_of_SIRGAS.pdf on sirgas.org website (www.sirgas.org website national networks list shows 269 passive and 13 continuous stations in this network whereas IGM Chile source document cites 650 stations).",OGP,"2011/03/20",2011.018,0,
+1065,Costa Rica 2005,geodetic,"ITRF2000 at epoch 2005.8.  Network of 34 GPS stations throughout the country, five of which were connected to four Caribbean area ITRF stations.",2005,7030,8901,1074,Geodetic survey.,"Replaces Ocotepeque (datum code 1070) in Costa Rica from March 2007.","Instituto Geografico Nacional Costa Rica report: El Sistema de Referencia CR05 y la Proyeccion Transversal de Mercator para Costa Rica CRTM05. (Report available through www.sirgas.org website in national networks list).",OGP,"2011/03/20",2011.018,0,
+1066,Sistema Geodesico Nacional de Panama MACARIO SOLIS,geodetic,"ITRF2000 at epoch 2000.0. Densification of SIRGAS 2000 network in Panama, consisting of 20 GPS stations throughout the country.",,7019,8901,1186,Geodetic survey.,,Details taken from summary on national networks list on www.sirgas.org website.,OGP,"2011/03/20",2011.018,0,
+1067,Peru96,geodetic,"ITRF94 at epoch 1995.4.  Densification of SIRGAS95 network in Peru, consisting of 47 passive geodetic stations and 3 continuous recording GPS stations.",1996,7019,8901,1189,Geodetic survey.,"Densification of SIRGAS 1995 within Peru. Replaces PSAD56 (datum code 6248) in Peru.","Details taken from national realizations page of WWW.SIRGAS.ORG, confirmed by reports from IGN Peru.",OGP,"2011/03/20",2011.018,0,
+1068,SIRGAS-ROU98,geodetic,"ITRF94 at epoch 1995.4.  Densification of SIRGAS95 network in Uruguay, consisting of 17 passive geodetic stations and 3 continuous recording GPS stations.",1998,7030,8901,1247,Geodetic survey.,"Densification of SIRGAS 1995 within Uruguay. Replaces Yacare (datum code 6309) in Uruguay. Uruguay documentation clearly states use of WGS 84 reference ellipsoid.","Sistema de Referencia Geocentrico para las Americas: SIRGAS, Boletin Informativo No 12, Aug 2007; www.sirgas.org.national network densification summary and NuevoMarco Uruguay_param.pdf by Servicio Geográfico Militar of Uruguay, May 2004.",OGP,"2011/03/20",2011.018,0,
+1069,"SIRGAS_ES2007.8",geodetic,"ITRF2005 at epoch 2007.8.  Densification of SIRGAS-CON network in El Salvador, consisting of 38 monumented stations.",2007,7019,8901,1087,Geodetic survey.,SIRGAS-ES2007.8 is the national SIRGAS densification.,"Integration of the reference frame of El Salvador into SIRGAS (SIRGAS-ES2007.8) report by GG-IGCN (El Salvador) & DGFI (Germany) available from www.sirgas.org.  (Information also summarised on www.sirgas.org website national networks list).",OGP,"2011/07/20",2011.018 2011.061,0,
+1070,Ocotepeque 1935,geodetic,"Fundamental point: Base Norte. Latitude: 14°26'20.168""N, longitude: 89°11'33.964""W.",1935,7008,8901,3876,Topographic mapping and engineering survey.,"Replaced in Costa Rica by Costa Rica 2005 (CR05) from March 2007 and replaced in El Salvador by SIRGAS_ES2007 from August 2007.","Clifford Mugnier's PE&RS articles on Belize, Costa Rica, El Salvador, Guatemala, Honduras, Nicaragua, Panama (www.asprs.org/resources/grids/) also substantiated in IGN Costa Rica report on CR05 / CRTM05 (Report available from WWW.SIRGAS.ORG website).",OGP,"2011/03/26",2011.026,0,
+1071,Sibun Gorge 1922,geodetic,"Latitude: 17º03'40.471""N, longitude: 88º37'54.687""W.",1922,7007,8901,3219,Topographic mapping and engineering survey.,,"Clifford Mugnier's March 2009 PE&RS ""Grids and Datums"" article on Belize (www.asprs.org/resources/grids/).",OGP,"2011/03/26",2011.026,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, (www.asprs.org/resources/grids/).",OGP,"2011/03/26",2011.026,0,
+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,
+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,
 5100,Mean Sea Level,vertical,,,,,1262,Hydrography.,"msl has geographic and temporal components.  Users are advised to not use this generic vertical datum but to define specific instances of msl based on knowledge of these components; for instance ""msl at xxx during 19yy"".",,OGP,"1996/04/12",,0,"D_Mean_Sea_Level"
 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,
-5103,North American Vertical Datum 1988,vertical,"Father's Point, Rimouski, Quebec.",1988,,,1325,"Topographic mapping, geodetic survey.",Helmert orthometric heights.,,OGP,"2006/01/16",2005.880,0,
+5103,North American Vertical Datum 1988,vertical,"Father's Point, Rimouski, Quebec.",1988,,,3664,"Topographic mapping, geodetic survey.",Helmert orthometric heights.,,OGP,"2010/03/30",2005.880 2009.108,0,
 5104,Yellow Sea 1956,vertical,2 years tide readings at Qingdao.,1956,,,3228,"Topographic mapping, geodetic survey.",Replaced by Yellow Sea 1985 datum.,,OGP,"2002/06/22",2002.160,0,
 5105,Baltic Sea,vertical,"Datum: average water level at Kronstadt 1833. Network adjusted in 1977.",1977,,,1284,"Topographic mapping, geodetic survey.",Uses Normal heights.,,OGP,"2005/05/27",2004.100 2005.180,0,
 5106,Caspian Sea,vertical,Defined as -28.0m Baltic datum,,,,1291,Hydrography.,,,OGP,"1996/09/12",,0,
@@ -36,8 +68,8 @@
 5113,Sea Level,vertical,,,,,1262,Hydrography.,An unspecified local vertical datum not recommended for use.,,OGP,"1996/09/12",,0,
 5114,Canadian Geodetic Vertical Datum of 1928,vertical,Based on the mean sea level determined from several tidal gauges located in strategic areas of the country,1928,,,1289,"Topographic mapping, geodetic survey.",,"Geodetic Survey Division, Natural Resources Canada. http://maps.nrcan.gc.ca/asdb/asdb_datum.html and http://www.geod.nrcan.gc.ca/index_e/help_e/acron_e.html",OGP,"2004/11/26",2004.723,0,
 5115,Piraeus Harbour 1986,vertical,MSL determined during 1986.,1986,,,3254,"Topographic mapping, geodetic survey.",,"Geodesy Department; Public Pertoleum Corporation of Greece",OGP,"1997/06/16",,0,
-5116,Helsinki 1960,vertical,MSL at Helsinki during 1960.,1960,,,3333,"Topographic mapping, geodetic survey.",,"National Land Survey of Finland;
-http://www.maanmittauslaitos.fi",OGP,"1997/07/22",,0,
+5116,Helsinki 1960,vertical,MSL at Helsinki during 1960.,1960,,,3333,"Topographic mapping, geodetic survey.","Uses orthometric heights. Replaced by N2000 (datum code 1030).","National Land Survey of Finland;
+http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
 5117,Rikets hojdsystem 1970,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 1970.0 using uplift values computed from repeated levelling observations.",1970,,,3313,"Topographic mapping, geodetic survey.",Realised through the second precise levelling network of 1951-1967. Uses Normal heights. Replaces RH00. Replaced in 2005 by RH2000.,National Land Survey of Sweden,OGP,"2008/03/14",2002.480 2004.100 2008.013,0,
 5118,Nivellement General de la France - Lallemand,vertical,"Rivet number M.ac O-VIII on the Marseille tide gauge site, with the height fixed in 1897 at 1.661 metre above mean sea level between February 2nd 1885 and January 1st 1897.",,,,1326,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"1997/11/13",2001.470 2004.060,0,
 5119,Nivellement General de la France - IGN69,vertical,"Rivet number M.ac O-VIII on the Marseille tide gauge site, with the height fixed in 1897 at 1.661 metre above mean sea level between February 2nd 1885 and January 1st 1897.",1969,,,1326,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"1997/11/13",2001.470,0,
@@ -55,7 +87,7 @@ http://www.maanmittauslaitos.fi",OGP,"1997/07/22",,0,
 5131,Belfast Lough,vertical,"Mean sea level between 1951 and 1956 at Clarendon Dock, Belfast.",1957,,,2530,"Large scale (1:1,250, 1:2,500 and 1:10,000) topographic mapping.","Orthometric heights. Malin Head (datum code 5130) used for 1:50,000 and smaller mapping.",Ordnance Survey of Northern Ireland,OGP,"2002/09/19",2002.620,0,
 5132,Dansk Normal Nul,vertical,Mean Sea Level at 10 gauges.,,,,3237,Topographic mapping and engineering survey,Orthometric heights.,"Kort & Matrikelstyrelsen",OGP,"2001/11/06",,0,
 5133,AIOC 1995,vertical,Average level of Caspian Sea at the Oil Rocks tide gauge June-September 1995.,1995,,,2592,Oil industry mapping.,AIOC 1995 datum is 1.7m above Caspian datum and 26.3m below Baltic datum.,BP,OGP,"2002/02/12",,0,
-5134,Black Sea,vertical,,,,,1102,Hydrographic surveying and since break-up of Former Soviet Union also topographic mapping.,Black Sea datum is 0.4m below Baltic datum.,BP,OGP,"2002/02/12",,0,
+5134,Black Sea,vertical,,,,,3251,Nearshore hydrographic surveying and since break-up of Former Soviet Union also topographic mapping.,Black Sea datum is 0.4m below Baltic datum.,BP,OGP,"2011/07/20",2011.061,0,
 5135,Hong Kong Principal Datum,vertical,"1.23m below the mean of 19 years (1965-83) observations of tide levels at North Point, Victoria Harbour.",1980,,,3334,"Geodetic survey, engineering survey, cadastre.",,"Survey and Mapping Office, Lands Department. Http://www.info.gov.hk/landsd/mapping/tindex.htm",OGP,"2002/06/22",,0,
 5136,Hong Kong Chart Datum,vertical,"Approximates to Lowest Astronomic Tide level (LAT).",,,,3335,Hydrographic survey and charting.,"Chart datum is 0.15 metres below Hong Kong Principal Datum (code 5135) and 1.38m below MSL at Quarry Bay.","Survey and Mapping Office, Lands Department. Http://www.info.gov.hk/landsd/mapping/tindex.htm",OGP,"2009/06/02",2009.022,0,
 5137,Yellow Sea 1985,vertical,20 years tide readings at Qingdao.,1985,,,3228,"Topographic mapping, geodetic survey.",Replaces Yellow Sea 1956 datum.,Guangdong Province Land Resource Information Centre,OGP,"2002/06/22",,0,
@@ -71,26 +103,26 @@ http://www.maanmittauslaitos.fi",OGP,"1997/07/22",,0,
 5147,St Marys,vertical,,,,,2802,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
 5148,Douglas,vertical,,,,,2803,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
 5149,Fao,vertical,,,,,3390,"Topographic mapping, geodetic survey.","Established by Hunting Surveys for IPC. In Iran replaced by Bandar Abbas (code 5150). At time of record creation NIOC data in Ahwaz area still usually referenced to Fao. In Iraq replaced by Fao 1979 (code 1028).","National Iranian Oil Company (NIOC).",OGP,"2009/06/02",2009.003,0,
-5150,Bandar Abbas,vertical,Average sea level at Bandar Abbass 1995-2001.,2001,,,3336,"Topographic mapping, geodetic survey.","Replaces Fao (code 5149).",National Cartographic Centre of Iran,OGP,"2002/09/19",,0,
+5150,Bandar Abbas,vertical,Average sea level at Bandar Abbas 1995-2001.,2001,,,3336,"Topographic mapping, geodetic survey.","Replaces Fao (datum code 5149) in Iran.",National Cartographic Centre of Iran,OGP,"2010/03/01",2010.014,0,
 5151,Nivellement General de Nouvelle Caledonie,vertical,"Rivet AB01 established by SHOM (Service Hydrographique de la Marine)  in 1937 on the Quai des Volontaires in Noumea. Height i: 1.885 metre above mean sea level.",1969,,,2822,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,Service Topographique de la Nouvelle Caledonie.,OGP,"2004/03/15",2004.060,0,
 5152,Poolbeg,vertical,"Low water mark of the spring tide on the 8 April 1837 at Poolbeg Lighthouse, Dublin.",1837,,,1305,Topographic mapping before 1956 in Northern Ireland and 1970 in the Republic of Ireland.,"Replaced by Belfast Lough and Malin Head (datum codes 5130-31).","""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,"2003/06/27",,0,
 5153,Nivellement General Guyanais 1977,vertical,"Mean sea level 1936 at Cayenne. Origin = marker BM35 on stone on St Francois battery, Cayenne, with defined elevation of 1.64m above msl. NGG1977 height 0.00m is 1.96m above sounding datum defined at Cayenne in 1936 by SHM.",1977,,,3146,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",2008.087,0,
 5154,Martinique 1987,vertical,"Mean sea level 1939 at Fort de France. Origin = marker Nbc2 on rebuilt quay wall with defined elevation of 1.38m above msl. Martinique 1987 height 0.00m is 0.56m above SHOM sounding datum.",1987,,,3276,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaces Martinique 1955 (datum code 5192).",IGN Paris,OGP,"2008/09/19",2004.561 2008.087,0,
 5155,Guadeloupe 1988,vertical,"Mean sea level July 1947 to June 1948 at Pointe-Fouillole (Pointe-à-Pitre harbour). Origin = marker GO-7 (formerly AO'-5) with defined height of 2.67m above msl adopted from 1951 value. Guadeloupe 1988 height 0.00m is 0.46m above 1984 sounding datum.",1988,,,2892,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaces Guadeloupe 1951 (datum code 5193).",IGN Paris,OGP,"2008/09/17",2004.561 2008.087,0,
 5156,Reunion 1989,vertical,"Mean sea level during part of November 1949 at port of Saint-Pierre. Origin = marker AB-100 with defined elevation of 13.808m above msl.",1989,,,3337,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights. Replaces Reunion IGN58. Value of marker AB-100 retains height from 1958 adjustment.,IGN Paris,OGP,"2008/09/17",2004.561 2008.087,0,
-5157,Auckland 1946,vertical,MSL at Auckland harbour 1909-1923.,1946,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5158,Bluff 1955,vertical,MSL at Invercargill harbour over 8 years between 1918 and 1934.,1955,,,1501,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5159,Dunedin 1958,vertical,MSL at Dunedin harbour 1918-1937.,1958,,,1501,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5160,Gisborne 1926,vertical,MSL at Gisborne harbour 1926.,1926,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5161,Lyttelton 1937,vertical,MSL at Lyttelton harbour over 9 years between 1918 and 1933.,1937,,,1501,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5162,Moturiki 1953,vertical,MSL at Moturiki Island February 1949 to December 1952.,1953,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5163,Napier 1962,vertical,MSL at Napier harbour. Period of derivation unknown.,1962,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5164,Nelson 1955,vertical,MSL at Nelson harbour 1939-1942.,1955,,,1501,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5165,One Tree Point 1964,vertical,MSL at Whangarei harbour 1960-1963.,1964,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5166,Tararu 1952,vertical,MSL at Tararu Point 1922-1923.,1952,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5167,Taranaki 1970,vertical,MSL at Taranaki harbour 1918-1921.,1970,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5168,Wellington 1953,vertical,MSL at Wellington harbour 1909-1946.,1953,,,1500,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2008/04/04",2008.023,0,
-5169,"Waitangi (Chatham Island) 1959",vertical,MSL at Waitangi harbour collected in 1959.,1959,,,2889,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2008/04/04",2008.023,0,
+5157,Auckland 1946,vertical,MSL at Auckland harbour 1909-1923.,1946,,,3764,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5158,Bluff 1955,vertical,MSL at Invercargill harbour over 8 years between 1918 and 1934.,1955,,,3801,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5159,Dunedin 1958,vertical,MSL at Dunedin harbour 1918-1937.,1958,,,3803,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5160,Gisborne 1926,vertical,MSL at Gisborne harbour 1926.,1926,,,3771,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5161,Lyttelton 1937,vertical,MSL at Lyttelton harbour over 9 years between 1918 and 1933.,1937,,,3804,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5162,Moturiki 1953,vertical,MSL at Moturiki Island February 1949 to December 1952.,1953,,,3768,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5163,Napier 1962,vertical,MSL at Napier harbour. Period of derivation unknown.,1962,,,3772,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5164,Nelson 1955,vertical,MSL at Nelson harbour 1939-1942.,1955,,,3802,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5165,One Tree Point 1964,vertical,MSL at Whangarei harbour 1960-1963.,1964,,,3762,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5166,Tararu 1952,vertical,MSL at Tararu Point 1922-1923.,1952,,,3818,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5167,Taranaki 1970,vertical,MSL at Taranaki harbour 1918-1921.,1970,,,3769,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5168,Wellington 1953,vertical,MSL at Wellington harbour 1909-1946.,1953,,,3773,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5169,"Waitangi (Chatham Island) 1959",vertical,MSL at Waitangi harbour collected in 1959.,1959,,,3894,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2011/06/20",2008.023 2011.048,0,
 5170,Stewart Island 1977,vertical,MSL at 3-5 high and low tides at two different locations.,1977,,,3338,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2008/04/04",2008.023,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,
@@ -102,8 +134,8 @@ http://www.maanmittauslaitos.fi",OGP,"1997/07/22",,0,
 5178,Cascais,vertical,Mean Sea Level at Cascais 1938.,1938,,,1294,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5179,Constanta,vertical,Mean Sea Level at Constanta.,,,,3295,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/evrs/Relations.html",OGP,"2004/03/09",,0,
 5180,Alicante,vertical,Mean Sea Level at Alicante between 1870 and 1882.,,,,2366,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
-5181,Deutches Haupthohennetz 1992,vertical,"Network adjusted in 1992. Geopotential number at reference point Wallenhorst defined as value from the UELN-73/86 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1992,,,3339,"Geodetic survey, topographic mapping, engineering survey.",Replaces DHHN85 in West Germany and SNN76 in East Germany. Uses Normal heights.,"Bundesamt für Kartographie und Geodäsie (BKG), http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
-5182,Deutches Haupthohennetz 1985,vertical,"Network adjusted in 1985. Height of reference point Wallenhorst defined as value from 1928 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1985,,,2326,"Geodetic survey, topographic mapping, engineering survey.",Replaced by DHHN92. Uses Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
+5181,Deutsches Haupthoehennetz 1992,vertical,"Network adjusted in 1992. Geopotential number at reference point Wallenhorst defined as value from the UELN-73/86 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1992,,,3339,"Geodetic survey, topographic mapping, engineering survey.",Replaces DHHN85 in West Germany and SNN76 in East Germany. Uses Normal heights.,"Bundesamt für Kartographie und Geodäsie (BKG), http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03",2011.071,0,
+5182,Deutsches Haupthoehennetz 1985,vertical,"Network adjusted in 1985. Height of reference point Wallenhorst defined as value from 1928 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1985,,,2326,"Geodetic survey, topographic mapping, engineering survey.",Replaced by DHHN92. Uses Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03",2011.071,0,
 5183,SNN76,vertical,Network adjusted in 1976. Height at reference point Hoppegarten defined as 1957 value from the UPLN adjustment. Datum at Kronstadt is mean sea level of Baltic in 1833.,1976,,,1343,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights. Replaced by DHHN92.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5184,Baltic 1982,vertical,Network adjusted in 1982. Height at reference point Varna defined as 1958 value from the UPLN adjustment. Datum at Kronstadt is mean sea level of Baltic in 1833.,1982,,,3224,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5185,Baltic 1980,vertical,,,,,1119,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
@@ -128,7 +160,7 @@ http://www.maanmittauslaitos.fi",OGP,"1997/07/22",,0,
 5204,International Great Lakes Datum 1955,vertical,"Pointe-au-Père (Father's Point), Quebec",1955,,,3468,Hydrology.,Dynamic heights. Adopted in 1962. Replaced by IGLD 1985 in January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2006/11/11",,0,
 5205,International Great Lakes Datum 1985,vertical,"Rimouski, Quebec.",1985,,,3468,Hydrology.,Dynamic heights. Replaces IGLD 1955 from January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2006/11/11",,0,
 5206,Dansk Vertikal Reference 1990,vertical,"Benchmark at Århus cathedral referenced to mean sea level determined during 1990 at 10 tide gauges: Esbjerg, Fredericia, Frederikshavn, Gedser, Hirtshals, Hornbæk, Korsør, København, Slipshavn and Århus.",,,,3237,Topographic mapping and engineering survey,Normal Orthometric heights.,"Kort & Matrikelstyrelsen",OGP,"2006/12/01",,0,
-5207,Croatian Vertical Reference System 1971,vertical,"Mean sea level at five tide gauges in Dubrovnik, Split, Bakar, Rovinj and Kopar at epoch 1971.5",1971,,,3234,Geodesy.,,State Geodetic Administration of the Republic of Croatia.,OGP,"2008/06/09",2008.043,0,
+5207,Croatian Vertical Reference System 1971,vertical,"Mean sea level at five tide gauges in Dubrovnik, Split, Bakar, Rovinj and Kopar at epoch 1971.5",1971,,,3234,Geodesy.,"Replaces Trieste (datum code 1050).",State Geodetic Administration of the Republic of Croatia.,OGP,"2010/07/13",2008.043 2010.064,0,
 5208,Rikets hojdsystem 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 RH 2000 LU (=NKG2005LU) uplift model.",2000,,,3313,"Topographic mapping, geodetic survey.","Realised through the third precise levelling network of 1979-2003. Adopted in 2005, replacing RH70. Uses Normal heights.",National Land Survey of Sweden,OGP,"2008/03/14",,0,
 5209,Rikets hojdsystem 1900,vertical,"Adjustment is referenced to mean sea level at Slussen, Stockholm.",1900,,,3313,"Topographic mapping, engineering survey.",Realised through the first precise levelling network of 1886-1905. Replaced by RH70.,National Land Survey of Sweden,OGP,"2008/03/14",,0,
 5210,IGN 1988 LS,vertical,"Mean sea level 1984 at Terre de Haut. Origin = marker O de -5 with defined height of 1.441m above msl. IGN 1988 LS height 0.00m is 0.46m above 1987 sounding datum; this approximately corresponds with msl at Pointe-à-Pitre (see datum code 5155, CRS 5757).",1988,,,2895,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
@@ -180,11 +212,11 @@ http://www.maanmittauslaitos.fi",OGP,"1997/07/22",,0,
 6053,"Not specified (based on International 1924 Authalic Sphere)",geodetic,,,7057,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2006/09/22",,0,
 6054,"Not specified (based on Hughes 1980 ellipsoid)",geodetic,,,7058,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2006/09/22",,0,
 6055,Popular Visualisation Datum,geodetic,Not specified in the classical sense of defining a geodetic datum.,,7059,8901,1262,Used by certain popular Web mapping and visualisation applications.,Not recognised by geodetic authorities.,Microsoft.,OGP,"2008/03/13",2008.114,1,
-6120,Greek,geodetic,"Fundamental point: Athens Observatory. Latitude 37°58'20.132""N, longitude 23°42'58.815""E (of Greenwich)",,7004,8901,1106,Topographic mapping.,"See geodetic datum alias 6404.  Used as basis of topographic mapping based on Hatt projection. Replaced by GGRS87 (code 6121).","Topography Department; National Technical University of Athens",OGP,"2008/06/24",2004.183 2008.045,0,"D_Greek"
-6121,Greek Geodetic Reference System 1987,geodetic,"Fundamental point: Dionysos. Latitude 38°04'33.8""N, longitude 23°55'51.0""E of Greenwich; geoid height 7.0 m.",1987,7019,8901,1106,Topographic mapping.,"Replaced (old) Greek datum.  Oil industry work based on ED50.","L. Portokalakis; Public Petroleum Corporation of Greece",OGP,"2008/06/24",2008.045,0,"D_GGRS_1987"
+6120,Greek,geodetic,"Fundamental point: Athens Observatory. Latitude 37°58'20.132""N, longitude 23°42'58.815""E (of Greenwich)",,7004,8901,3254,Topographic mapping.,"See geodetic datum alias 6404.  Used as basis of topographic mapping based on Hatt projection. Replaced by GGRS87 (code 6121).","Topography Department; National Technical University of Athens",OGP,"2011/07/20",2004.183 2008.045 2011.062,0,"D_Greek"
+6121,Greek Geodetic Reference System 1987,geodetic,"Fundamental point: Dionysos. Latitude 38°04'33.8""N, longitude 23°55'51.0""E of Greenwich; geoid height 7.0 m.",1987,7019,8901,3254,Topographic mapping.,"Replaced (old) Greek datum.  Oil industry work based on ED50.","L. Portokalakis; Public Petroleum Corporation of Greece",OGP,"2011/07/20",2008.045 2011.062,0,"D_GGRS_1987"
 6122,Average Terrestrial System 1977,geodetic,,1977,7041,8901,1283,Topographic mapping.,"In use from 1979.  To be phased out in late 1990's.",New Brunswick Geographic Information Corporation land and water information standards manual.,OGP,"1997/07/02",,0,"D_ATS_1977"
-6123,"Kartastokoordinaattijarjestelma (1966)",geodetic,Adjustment with fundamental point SF31 based on ED50 transformed to best fit the older VVJ adjustment.,1966,7022,8901,1095,"Geodetic survey, cadastre, topographic mapping, engineering survey.",Adopted in 1970.,"National Land Survey of Finland;
-http://www.maanmittauslaitos.fi",OGP,"2006/03/31",2006.270,0,"D_KKJ"
+6123,"Kartastokoordinaattijarjestelma (1966)",geodetic,Adjustment with fundamental point SF31 based on ED50 transformed to best fit the older VVJ adjustment.,1966,7022,8901,3333,"Geodetic survey, cadastre, topographic mapping, engineering survey.",Adopted in 1970.,"National Land Survey of Finland;
+http://www.maanmittauslaitos.fi",OGP,"2011/06/30",2006.270 2011.055,0,"D_KKJ"
 6124,Rikets koordinatsystem 1990,geodetic,,1982,7004,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces RT38 adjustment (datum code 6308)",National Land Survey of Sweden,OGP,"1997/11/13",,0,"D_RT_1990"
 6125,Samboja,geodetic,Original origin station P2 Exc now destroyed.  Extensions recomputed using Toran station T9 as origin.,,7004,8901,1328,Topographic mapping.,,Total Indonesia.,OGP,"1997/11/13",,1,"D_Samboja"
 6126,"Lithuania 1994 (ETRS89)",geodetic,Constrained to 4 ETRS89 points in Lithuania from the EUREF Baltic 1992 campaign..,1994,7019,8901,1145,"Topographic mapping, geodetic survey.",Densification of ETRS89 during the 1992 Baltic campaign.,HNIT-Baltic GeoInfoServisas,OGP,"1998/03/12",,0,"D_Lithuania_1994"
@@ -194,7 +226,7 @@ http://www.maanmittauslaitos.fi",OGP,"2006/03/31",2006.270,0,"D_KKJ"
 6130,"Moznet (ITRF94)",geodetic,ITRF94 at epoch 1996.9,,7030,8901,1167,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2006/08/18",2006.770,0,"D_Moznet"
 6131,Indian 1960,geodetic,DMA extension over IndoChina of the Indian 1954 network adjusted  to better fit local geoid.,,7015,8901,1302,Topographic mapping.,"Also known as Indian (DMA Reduced).",,OGP,"2003/12/31",2003.361,0,"D_Indian_1960"
 6132,Final Datum 1958,geodetic,"Fundamental point: Maniyur.  Latitude: 31°23'59.19""N, longitude: 48°32'31.38""E (of Greenwich).",,7012,8901,1300,Oil industry mapping.,Network included in Nahrwan 1967 adjustment.,IOEPC records,OGP,"2008/06/24",2008.045,0,"D_FD_1958"
-6133,Estonia 1992,geodetic,Densification from 4 ETRS89 points.,1992,7019,8901,1090,"Topographic mapping, Geodetic survey.","Based on ETRS89 as established during the 1992 Baltic campaign. Replaced by Estonia 1997 adjustment (code 6180).","http://www.geo.ut.ee",OGP,"2005/09/06",2005.460,0,"D_Estonia_1992"
+6133,Estonia 1992,geodetic,Densification from 4 ETRS89 points.,1992,7019,8901,3246,"Topographic mapping, Geodetic survey.","Based on ETRS89 as established during the 1992 Baltic campaign. Replaced by Estonia 1997 adjustment (code 6180).","http://www.geo.ut.ee",OGP,"2011/06/30",2005.460 2011.055,0,"D_Estonia_1992"
 6134,PDO Survey Datum 1993,geodetic,Adjustment best fitted to Fahud network.,1993,7012,8901,3288,Oil industry mapping.,"Replaces Fahud datum (code 6232). Maximum differences to Fahud adjustment are 20 metres.",Petroleum Development Oman,OGP,"1999/04/22",,0,"D_PDO_1993"
 6135,Old Hawaiian,geodetic,"Fundamental point: Oahu West Base Astro.  Latitude: 21°18'13.89""N, longitude 157°50'55.79""W (of Greenwich)",,7008,8901,1334,Topographic mapping.,"Hawaiian Islands were never on NAD27 but rather on Old Hawaiian Datum.  NADCON conversion program provides transformation from Old Hawaiian Datum to NAD83 (original 1986 realization) but making the transformation appear to user as if from NAD27.","http://www.ngs.noaa.gov/ (NADCON readme file).",OGP,"2008/06/24",2005.460 2008.045,0,"D_Old_Hawaiian"
 6136,St. Lawrence Island,geodetic,,,7008,8901,1332,Topographic mapping.,"Many Alaskan islands were never on NAD27 but rather on independent datums.  NADCON conversion program provides transformation from St. Lawrence Island Datum to NAD83 (original 1986 realization) - making the transformation appear to user as if from NAD27.","http://www.ngs.noaa.gov/ (NADCON readme file)",OGP,"1999/05/24",,0,"D_St_Lawrence_Island"
@@ -213,17 +245,17 @@ http://www.maanmittauslaitos.fi",OGP,"2006/03/31",2006.270,0,"D_KKJ"
 6149,CH1903,geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'08.660""N, longitude: 7°26'22.500""E (of Greenwich).",1903,7004,8901,1286,Topographic mapping.,,"Bundesamt für Landestopographie",OGP,"2008/06/24",2008.045,0,"D_CH1903"
 6150,"CH1903+",geodetic,"Fundamental point: Zimmerwald observatory.",,7004,8901,1286,"Geodetic survey, topographic mapping.",,"Bundesamt für Landestopographie.  Aufbau der Landesvermessung der Schweiz 'LV95' Teil 3: Terrestrische Bezugssysteme und Bezugsrahmen. L+T 1999.",OGP,"2001/11/06",2001.520,0,"D_CH1903+"
 6151,Swiss Terrestrial Reference Frame 1995,geodetic,ETRF89 at epoch 1993.0,1995,7019,8901,1286,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Bundesamt für Landestopographie.  Aufbau der Landesvermessung der Schweiz 'LV95' Teil 3: Terrestrische Bezugssysteme und Bezugsrahmen. L+T 1999.",OGP,"2006/08/18",2006.770,0,"D_Swiss_TRF_1995"
-6152,"NAD83 (High Accuracy Regional Network)",geodetic,,,7019,8901,1337,Geodetic survey.,,National Geodetic Survey,OGP,"2009/07/29",2009.044,0,"D_North_American_1983_HARN"
+6152,"NAD83 (High Accuracy Reference Network)",geodetic,,,7019,8901,1337,Geodetic survey.,,National Geodetic Survey,OGP,"2011/02/04",2009.044 2010.061 2011.009,0,"D_North_American_1983_HARN"
 6153,Rassadiran,geodetic,"Fundamental point: Total1. Latitude: 27°31'07.784""N, longitude: 52°36'12.741""E (of Greenwich).",1998,7022,8901,1338,Oil industry mapping.,,Total-Fina,OGP,"2008/06/24",2008.045,0,"D_Rassadiran"
 6154,"European Datum 1950(1977)",geodetic,Extension of ED50 over Iran.,1977,7022,8901,1123,Topographic mapping.,Sometimes referred to as ED50-ED77.,National Cartographic Centre of Iran,OGP,"1999/11/20",,0,"D_European_1950_ED77"
 6155,Dabola 1981,geodetic,,1981,7011,8901,3257,Topographic mapping.,,IGN Paris,OGP,"1999/12/09",,0,"D_Dabola_1981"
-6156,Jednotne Trigonometricke Site Katastralni,geodetic,"Modification of Austrian MGI datum, code 6312.",,7004,8901,1306,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Research Institute for Geodesy Topography and Cartography (VUGTK); Prague.",OGP,"2001/11/06",2001.260 2001.510,0,"D_S_JTSK"
+6156,System Jednotne Trigonometricke Site Katastralni,geodetic,"Modification of Austrian MGI datum, code 6312.",,7004,8901,1306,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Research Institute for Geodesy Topography and Cartography (VUGTK); Prague.",OGP,"2010/11/02",2001.260 2001.510 2010.071,0,"D_S_JTSK"
 6157,Mount Dillon,geodetic,"Fundamental point: Mount Dillon triangulation station. Latitude: 11°15'07.843""N, longitude: 60°41'09.632""W (of Greenwich).",,7007,8901,1322,Topographic mapping.,,University of the West Indies Geodetic Services.,OGP,"2008/06/24",2003.361 2008.045,0,"D_Mount_Dillon"
 6158,Naparima 1955,geodetic,"Fundamental point: Naparima. Latitude: 10°16'44.860""N, longitude: 61°27'34.620""W (of Greenwich).",1955,7022,8901,3143,Topographic mapping.,Naparima 1972 is an extension of the Naparima 1955 network of Trinidad to include Tobago.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Naparima_1955"
 6159,European Libyan Datum 1979,geodetic,Extension of ED50 over Libya.,1979,7022,8901,1143,Topographic mapping.,,Brown and Root,OGP,"2003/12/31",2003.362,0,"D_European_Libyan_1979"
 6160,Chos Malal 1914,geodetic,Chos Malal police station.,1914,7022,8901,1292,Oil industry mapping.,"Also known as Quini-Huao.  Replaced by Campo Inchauspe (code 6221).",Various oil company records.,OGP,"2000/03/07",,0,"D_Chos_Malal_1914"
 6161,Pampa del Castillo,geodetic,,,7022,8901,1265,Oil industry mapping.,"Used in Comodoro Rivadavia area.  Replaced by Campo Inchauspe (code 6221).",Various oil company records.,OGP,"2000/03/07",,0,"D_Pampa_del_Castillo"
-6162,Korean Datum 1985,geodetic,"Fundamental point: Suwon. Latitude 37°16'31.9034""N, longitude 127°03'05.1451""E of Greenwich.",1985,7004,8901,3266,Topographic mapping.,,"Clifford J. Mugnier; in Photogrammetric Engineering & Remote Sensing November 1999. http://www.asprs.org/",OGP,"2008/06/24",2001.280 2005.460 2008.045,0,"D_Korean_Datum_1985"
+6162,Korean Datum 1985,geodetic,"Fundamental point: Suwon. Latitude 37°16'31.9034""N, longitude 127°03'05.1451""E of Greenwich. This is consistent with the Tokyo 1918 datum latitude and longitude.",1985,7004,8901,3266,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Tokyo 1918 (datum code 6301). Replaced by Korea 2000 (datum code 6737).","Clifford J. Mugnier; in Photogrammetric Engineering & Remote Sensing November 1999. http://www.asprs.org/",OGP,"2010/06/30",2001.280 2005.460 2008.045 2010.050,0,"D_Korean_Datum_1985"
 6163,Yemen National Geodetic Network 1996,geodetic,"Sana'a IGN reference marker.",1996,7030,8901,1257,Topographic mapping.,,IGN Paris,OGP,"2000/03/07",,0,"D_Yemen_NGN_1996"
 6164,South Yemen,geodetic,,,7024,8901,1340,Topographic mapping.,,IGN Paris,OGP,"2000/03/07",,0,"D_South_Yemen"
 6165,Bissau,geodetic,,,7022,8901,3258,Topographic mapping.,,"NIMA TR8350.2  ftp://164.214.2.65/pub/gig/tr8350.2/changes.pdf",OGP,"2005/09/05",2005.460,0,"D_Bissau"
@@ -235,7 +267,7 @@ http://www.maanmittauslaitos.fi",OGP,"2006/03/31",2006.270,0,"D_KKJ"
 6171,Reseau Geodesique Francais 1993,geodetic,Coincident with ETRS89 at epoch 1993.0,1993,7019,8901,1096,Geodetic survey.,,"http://www.ign.fr/ via TotalFinaElf",OGP,"2005/09/05",2001.510 2005.460,0,"D_RGF_1993"
 6172,Posiciones Geodesicas Argentinas,geodetic,,1994,7019,8901,1033,"Topographic mapping, geodetic survey.","Una red geodésica de 127 puntos materializados
 en el terreno que definen el Sistema Geodésico Nacional.  [A geodetic network of 127 points defining the National Geodetic System.] Replaced by POSGAR98 (code 6190).","http://www.igm.gov.ar/posgar.html",OGP,"2000/10/19",,1,"D_POSGAR"
-6173,IRENET95,geodetic,ETRS89 stations in Ireland,1995,7019,8901,1305,Geodetic survey.,Densification of ETRS89,Ordnance Survey of Ireland,OGP,"2004/04/07",2004.220,0,"D_IRENET95"
+6173,IRENET95,geodetic,ETRS89 stations in Ireland,1995,7019,8901,3744,Geodetic survey.,Densification of ETRS89,Ordnance Survey of Ireland,OGP,"2011/01/25",2004.220 2011.004,0,"D_IRENET95"
 6174,Sierra Leone Colony 1924,geodetic,"Fundamental point: Kortright. Latitude: 8°28'44.4""N, longitude: 13°13'03.81""W (of Greenwich).",1924,7029,8901,1342,"Topographic mapping, engineering survey.",,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Sierra_Leone_1924"
 6175,Sierra Leone 1968,geodetic,"Fundamental point: SLX2 Astro. Latitude: 8°27'17.567""N, longitude: 12°49'40.186""W (of Greenwich).",1968,7012,8901,3306,"Topographic mapping, engineering survey.",Extension and readjustment with additional observations of 1960 network.  Coordinates of 1960 stations change by less than 3 metres.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Sierra_Leone_1968"
 6176,Australian Antarctic Datum 1998,geodetic,,1998,7019,8901,1278,Topographic mapping.,,Standards Australia,OGP,"2006/01/30",2006.080,0,"D_Australian_Antarctic_1998"
@@ -249,8 +281,8 @@ en el terreno que definen el Sistema Geodésico Nacional.  [A geodetic network o
 6185,Madeira 1936,geodetic,"Fundamental point: Madeira SE Base.",1936,7022,8901,1314,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2001/06/05",,1,"D_Madeira_1936"
 6188,OSNI 1952,geodetic,Position fixed to the coordinates from the 19th century Principle Triangulation of station Divis. Scale and orientation controlled by position of Principle Triangulation stations Knocklayd and Trostan.,1952,7001,8901,2530,Geodetic survey and topographic mapping.,"Replaced by Geodetic Datum of 1965 alias 1975 Mapping Adjustment or TM75 (datum code 6300).",Ordnance Survey of Northern Ireland.,OGP,"2001/11/06",,0,"D_OSNI_1952"
 6189,Red Geodesica Venezolana,geodetic,Realised by a frame of 67 stations observed in 1995 as a densification of the SIRGAS campaign and adjusted in the ITRF94.,2000,7019,8901,1251,Geodetic survey.,,Servicio Autonomo de Geografia y Cartografia Nacional.,OGP,"2001/06/11",,0,"D_REGVEN"
-6190,Posiciones Geodesicas Argentinas 1998,geodetic,"A geodetic network of 136 high accuracy surveyed points. Densification of SIRGAS 1995; ITRF94 at epoch 1995.42.",1998,7019,8901,1033,Geodetic survey.,"Technically, but at this record revision date not legally, replaces the 1994 POSGAR adjustment (code 6694).","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.ar",OGP,"2005/09/12",2003.361 2005.460 2005.480 2006.770,0,"D_POSGAR_1998"
-6191,Albanian 1987,geodetic,,1987,7024,8901,1025,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2001/11/06",,0,"D_Albanian_1987"
+6190,Posiciones Geodesicas Argentinas 1998,geodetic,"A geodetic network of 136 high accuracy surveyed points. Densification of SIRGAS 1995; ITRF94 at epoch 1995.42.",1998,7019,8901,1033,Geodetic survey.,"Technically, but not legally, this datum replaced the 1994 POSGAR adjustment (code 6694) until adoption of the 2007 POSGAR adjustment (code 1062) in May 2009.","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.ar",OGP,"2011/03/28",2003.361 2005.460 2005.480 2006.770 2009.028,0,"D_POSGAR_1998"
+6191,Albanian 1987,geodetic,,1987,7024,8901,3212,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2011/07/20",2011.062,0,"D_Albanian_1987"
 6192,Douala 1948,geodetic,"South pillar of Douala base; 4°00'40.64""N, 9°42'30.41""E (of Greenwich).",1948,7022,8901,2555,Topographic mapping.,"Replaced  by Manoca 1962 datum (code 6193).",TotalFinaElf,OGP,"2008/06/24",2005.830 2008.045,0,"D_Douala_1948"
 6193,Manoca 1962,geodetic,"Reservoir centre at the  Manoca tower (""tube Suel""), 3°51'49.896""N, 9°36'49.347""E (of Greenwich).",1962,7011,8901,2555,Topographic mapping.,"The intent of the Bukavu 1953 conference was to adopt the Clarke 1880 (RGS) ellipsoid (code 7012) but in practice this datum has used the IGN version.  Replaces Douala 1948 (code 6192).",TotalFinaElf,OGP,"2008/06/24",2008.045,0,"D_Manoca_1962"
 6194,Qornoq 1927,geodetic,"Fundamental point: Station 7008. Latitude: 64°31'06.27""N, longitude: 51°12'24.86""W (of Greenwich).",1927,7022,8901,3362,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen. Origin coordinates from NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2006.220 2008.045,0,"D_Qornoq_1927"
@@ -270,20 +302,20 @@ en el terreno que definen el Sistema Geodésico Nacional.  [A geodetic network o
 6208,Aratu,geodetic,,,7022,8901,1274,Oil industry geodetic purposes.,,,OGP,"1995/06/02",,0,"D_Aratu"
 6209,Arc 1950,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",1950,7013,8901,1276,"Topographic mapping, geodetic survey.",,,OGP,"2008/06/24",2008.045,0,"D_Arc_1950"
 6210,Arc 1960,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",1960,7012,8901,1277,"Topographic mapping, geodetic survey.",,,OGP,"2008/06/24",2008.045,0,"D_Arc_1960"
-6211,Batavia,geodetic,"Fundamental point: Longitude at Batavia Astro. Station. Latitude: 6°07'39.522""S, longitude: 106°48'27.790""E (of Greenwich). Latitude and azimuth at Genuk.",,7004,8901,1285,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Batavia"
-6212,Barbados 1938,geodetic,"Fundamental point: HMS Challenger astro station M1, St. Anne's Tower. Latitude 13°04'32.53""N, longitude 59°36'29.34""W (of Greenwich).",1938,7012,8901,1042,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2008/06/24",1999.170 2006.030 2008.045,0,"D_Barbados_1938"
+6211,Batavia,geodetic,"Fundamental point: Longitude at Batavia Astro. Station. Latitude: 6°07'39.522""S, longitude: 106°48'27.790""E (of Greenwich). Latitude and azimuth at Genuk.",,7004,8901,3666,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2008.045 2009.106,0,"D_Batavia"
+6212,Barbados 1938,geodetic,"Fundamental point: HMS Challenger astro station M1, St. Anne's Tower. Latitude 13°04'32.53""N, longitude 59°36'29.34""W (of Greenwich).",1938,7012,8901,3218,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2011/06/30",1999.170 2006.030 2008.045 2011.051,0,"D_Barbados_1938"
 6213,Beduaram,geodetic,,,7011,8901,2771,Topographic mapping.,,,OGP,"2004/09/01",2004.490,0,"D_Beduaram"
 6214,Beijing 1954,geodetic,"Pulkovo, transferred through Russian triangulation.",1954,7024,8901,3228,Topographic mapping.,Scale determined through three baselines in northeast China. Discontinuities at boundaries of adjustment blocks. From 1982 replaced by Xian 1980 and New Beijing.,"Chinese Science Bulletin, 2009, 54:2714-2721",OGP,"2009/11/24",2009.084,0,"D_Beijing_1954"
 6215,Reseau National Belge 1950,geodetic,"Fundamental point: Lommel (tower). Latitude: 51°13'47.334""N, longitude: 5°18'49.483""E (of Greenwich).",1950,7022,8901,1347,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Belge_1950"
-6216,Bermuda 1957,geodetic,"Fundamental point: Fort George base. Latitude 32°22'44.36""N, longitude 64°40'58.11""W (of Greenwich).",1957,7008,8901,1047,Topographic mapping.,,Various oil industry sources.,OGP,"2008/06/24",2003.362 2008.045,0,"D_Bermuda_1957"
-6218,Bogota 1975,geodetic,"Fundamental point: Bogota observatory. Latitude: 4°35'56.570""N, longitude: 74°04'51.300""W (of Greenwich).",1975,7022,8901,3229,Topographic mapping.,"Replaces 1951 adjustment. Replaced by MAGNA-SIRGAS (datum code 6685).","Instituto Geografico Agustin Codazzi (IGAC) special publication no. 1, 4th edition (1975) ""Geodesia: Resultados Definitvos de Parte de las Redes Geodesicas Establecidas en el Pais"".",OGP,"2008/06/24",2000.200 2005.060 2007.060 2008.045,0,"D_Bogota"
+6216,Bermuda 1957,geodetic,"Fundamental point: Fort George base. Latitude 32°22'44.36""N, longitude 64°40'58.11""W (of Greenwich).",1957,7008,8901,3221,Topographic mapping.,,Various oil industry sources.,OGP,"2011/01/25",2003.362 2008.045 2011.004,0,"D_Bermuda_1957"
+6218,Bogota 1975,geodetic,"Fundamental point: Bogota observatory. Latitude: 4°35'56.570""N, longitude: 74°04'51.300""W (of Greenwich).",1975,7022,8901,3686,Topographic mapping.,"Replaces 1951 adjustment. Replaced by MAGNA-SIRGAS (datum code 6685).","Instituto Geografico Agustin Codazzi (IGAC) special publication no. 1, 4th edition (1975) ""Geodesia: Resultados Definitvos de Parte de las Redes Geodesicas Establecidas en el Pais"".",OGP,"2010/03/30",2000.200 2005.060 2007.060 2008.045 2009.106,0,"D_Bogota"
 6219,Bukit Rimpah,geodetic,"2°00'40.16""S, 105°51'39.76""E (of Greenwich).",,7004,8901,1287,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Bukit_Rimpah"
 6220,Camacupa,geodetic,"Fundamental point: Campo de Aviaçao. Latitude: 12°01'09.070""S, Longitude = 17°27'19.800""E (of Greenwich)",1948,7012,8901,1288,Coastal hydrography.,,"Portuguese Hydrographic Institute and Clifford J. Mugnier, PE&RS journal, March 2001.",OGP,"2008/06/24",2003.361 2006.973 2008.045,0,"D_Camacupa"
-6221,Campo Inchauspe,geodetic,"Fundamental point: Campo Inchauspe. Latitude: 35°58'16.56""S, longitude: 62°10'12.03""W (of Greenwich).",,7022,8901,1033,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.361 2005.460 2008.045,0,"D_Campo_Inchauspe"
+6221,Campo Inchauspe,geodetic,"Fundamental point: Campo Inchauspe. Latitude: 35°58'16.56""S, longitude: 62°10'12.03""W (of Greenwich).",,7022,8901,3843,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2011/03/28",2003.361 2005.460 2008.045 2011.021,0,"D_Campo_Inchauspe"
 6222,Cape,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",,7013,8901,1290,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Private Communication, Directorate of Surveys and Land Information, Cape Town.",OGP,"2008/06/24",1996.250 1999.690 2008.045,0,"D_Cape"
 6223,Carthage,geodetic,"Fundamental point: Carthage. Latitude: 40.9464506g = 36°51'06.50""N, longitude: 8.8724368g E of Paris = 10°19'20.72""E (of Greenwich).",1925,7011,8901,1236,Topographic mapping.,Fundamental point astronomic coordinates determined in 1878.,,OGP,"2008/06/24",2003.362 2003.050 2008.045,0,"D_Carthage"
 6224,Chua,geodetic,"Fundamental point: Chua. Latitude: 19°45'41.160""S, longitude: 48°06'07.560""W (of Greenwich).",,7022,8901,3356,Geodetic survey.,The Chua origin and associated network is in Brazil with a connecting traverse through northern Paraguay. It was used in Brazil only as input into the Corrego Allegre adjustment and for government work in Distrito Federal.,"NIMA http://earth-info.nima.mil/",OGP,"2009/06/02",2003.361 2005.460 2005.840 2006.490 2008.045 2009.021,0,"D_Chua"
-6225,Corrego Alegre,geodetic,"Fundamental point: Corrego Alegre. Latitude: 19°50'15.140""S, longitude: 48°57'42.750""W (of Greenwich).",,7022,8901,1293,"Topographic mapping, geodetic survey. Superseded by SAD69.","NIMA gives coordinates of origin as latitude: 19°50'15.140""S, longitude: 48°57'42.750""W.","IBGE and NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2005.841 2008.045,0,"D_Corrego_Alegre"
+6225,Corrego Alegre 1970-72,geodetic,"Fundamental point: Corrego Alegre. Latitude: 19°50'14.91""S, longitude: 48°57'41.98""W (of Greenwich).",1972,7022,8901,1293,"Topographic mapping, geodetic survey. Superseded by SAD69.","Replaces 1961 adjustment (datum code 1074). NIMA gives coordinates of origin as latitude: 19°50'15.14""S, longitude: 48°57'42.75""W; these may refer to 1961 adjustment.",IBGE.,OGP,"2011/07/27",2005.841 2008.045 2011.053,0,"D_Corrego_Alegre"
 6226,"Cote d'Ivoire",geodetic,,,7011,8901,1075,Topographic mapping.,,,OGP,"1995/06/02",2001.110,1,"D_Cote_d_Ivoire"
 6227,Deir ez Zor,geodetic,"Fundamental point: Trig. 254 Deir. Latitude: 35°21'49.975""N, longitude: 40°05'46.770""E (of Greenwich).",,7011,8901,1623,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Deir_ez_Zor"
 6228,Douala,geodetic,,,7011,8901,1060,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Douala"
@@ -299,14 +331,14 @@ US NGA, http://earth-info.nga.mil/GandG/index.html",OGP,"2008/08/12",2003.362 20
 6237,Hungarian Datum 1972,geodetic,"Fundamental point: Szolohegy. Latitude: 47°17'32,6156""N, longitude 19°36'09.9865""E (of Greenwich); geoid height 6.56m.",1972,7036,8901,1119,Topographic mapping.,"Replaced Hungarian Datum 1909 (EPSG datum code 1024).","http://lazarus.elte.hu/gb/geodez/geod3.htm",OGP,"2008/08/02",1996.090 2008.045 2008.047,0,"D_Hungarian_1972"
 6238,Indonesian Datum 1974,geodetic,"Fundamental point: Padang. Latitude: 0°56'38.414""S, longitude: 100°22' 8.804""E (of Greenwich). Ellipsoidal height 3.190m, gravity-related height 14.0m above mean sea level.",1974,7021,8901,1122,Topographic mapping.,Replaced by DGN95.,Bakosurtanal 1979 paper by Jacob Rais.,OGP,"2008/06/24",2002.151 2006.810 2008.045,0,"D_Indonesian_1974"
 6239,Indian 1954,geodetic,Extension of Kalianpur 1937 over Myanmar and Thailand.,1954,7015,8901,1304,Topographic mapping.,,,OGP,"2003/12/31",2003.361,0,"D_Indian_1954"
-6240,Indian 1975,geodetic,"Fundamental point: Khau Sakaerang.",1975,7015,8901,1231,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Indian_1975"
+6240,Indian 1975,geodetic,"Fundamental point: Khau Sakaerang.",1975,7015,8901,3741,Topographic mapping.,,,OGP,"2011/01/25",2011.004,0,"D_Indian_1975"
 6241,Jamaica 1875,geodetic,"Fundamental point: Fort Charles Flagstaff. Latitude: 17°55'55.800""N, longitude: 76°56'37.260""W (of Greenwich).",1875,7034,8901,3342,Topographic mapping.,,"Survey Department, Government of Jamaica, 1983.",OGP,"2008/06/24",2004.510 2008.045,0,"D_Jamaica_1875"
 6242,Jamaica 1969,geodetic,"Fundamental point: Fort Charles Flagstaff. Latitude: 17°55'55.800""N, longitude: 76°56'37.260""W (of Greenwich).",1969,7008,8901,3342,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Survey Department, Government of Jamaica, 1983.",OGP,"2008/06/24",2004.510 2008.045,0,"D_Jamaica_1969"
 6243,Kalianpur 1880,geodetic,"Fundamental point: Kalianpur. Latitude: 24°07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1880,7042,8901,1307,Topographic mapping.,"Includes 1916 extension into Burma (Myanmar).  Replaced by 1937 adjustment.","G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,"2008/06/24",1997.231 2004.290 2008.045,0,"D_Kalianpur_1880"
-6244,Kandawala,geodetic,,,7015,8901,3310,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Kandawala"
+6244,Kandawala,geodetic,"Fundamental point: Kandawala. Latitude: 7°14'06.838""N, longitude: 79°52'36.670""E.",1930,7015,8901,3310,Topographic mapping.,,"Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/09/24",2010.080,0,"D_Kandawala"
 6245,Kertau 1968,geodetic,"Fundamental point: Kertau. Latitude: 3°27'50.710""N, longitude: 102°37'24.550""E (of Greenwich).",1968,7018,8901,1309,"Geodetic survey, cadastre.","Replaces MRT48 and earlier adjustments. Adopts metric conversion of 39.370113 inches per metre. Not used for 1969 metrication of RSO grid - see Kertau (RSO) (code 6751).",Defence Geographic Centre.,OGP,"2008/06/24",2006.251 2008.045,0,"D_Kertau"
 6246,Kuwait Oil Company,geodetic,"Fundamental point: K28.  Latitude: 29°03'42.348""N, longitude: 48°08'42.558""E (of Greenwich).",1952,7012,8901,3267,Oil industry mapping.,,,OGP,"2008/06/24",2004.410 2008.045,0,"D_Kuwait_Oil_Company"
-6247,La Canoa,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",,7022,8901,3327,"Geodetic survey, topographic mapping, engineering survey.",Origin also adopted for PSAD56.,,OGP,"2008/06/24",2008.045,0,"D_La_Canoa"
+6247,La Canoa,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",,7022,8901,3327,"Geodetic survey, topographic mapping, engineering survey.","Origin and network incorporated within PSAD56 (datum code 6248).",,OGP,"2011/01/25",2008.045 2011.001,0,"D_La_Canoa"
 6248,Provisional South American Datum 1956,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",1956,7022,8901,1348,Topographic mapping.,Same origin as La Canoa datum.,,OGP,"2008/06/24",2008.045,0,"D_Provisional_S_American_1956"
 6249,Lake,geodetic,"Fundamental point: Maracaibo Cathedral. Latitude: 10°38'34.678""N, longitude: 71°36'20.224""W (of Greenwich).",,7022,8901,1312,Oil industry mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Lake"
 6250,Leigon,geodetic,"Fundamental point: GCS Station 121, Leigon. Latitude: 5°38'52.27""N, longitude: 0°11'46.08""W (of Greenwich).",,7012,8901,1104,Topographic mapping.,"Replaced Accra datum (code 6168) from 1978.  Coordinates at Leigon fundamental point defined as Accra datum values for that point.",Ordnance Survey International,OGP,"2008/06/24",2008.045,0,"D_Leigon"
@@ -327,22 +359,22 @@ US NGA, http://earth-info.nga.mil/GandG/index.html",OGP,"2008/08/12",2003.362 20
 6265,Monte Mario,geodetic,"Fundamental point: Monte Mario. Latitude: 41°55'25.51""N, longitude: 12°27'08.4""E (of Greenwich).",1940,7022,8901,3343,Topographic mapping.,"Replaced Genova datum, Bessel 1841 ellipsoid, from 1940.",,OGP,"2008/06/24",2003.360 2008.045,0,"D_Monte_Mario"
 6266,"M'poraloko",geodetic,,,7011,8901,1100,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Mporaloko"
 6267,North American Datum 1927,geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",1927,7008,8901,1349,Topographic mapping.,"In United States (USA) and Canada, replaced by North American Datum 1983 (NAD83) (code 6269) ; in Mexico, replaced by Mexican Datum of 1993 (code 1042).",,OGP,"2009/11/24",2008.024 2008.045 2009.087,0,"D_North_American_1927"
-6268,NAD Michigan,geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",,7009,8901,1391,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_North_American_Michigan"
+6268,NAD27 Michigan,geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",,7009,8901,1391,Topographic mapping.,Ellipsoid taken to be 800ft above the NAD27 reference ellipsoid.,"USGS Professional Paper #1395.",OGP,"2011/02/25",2008.045 2011.013,0,"D_North_American_Michigan"
 6269,North American Datum 1983,geodetic,Origin at geocentre.,1986,7019,8901,1350,Topographic mapping.,"Although the 1986 adjustment included connections to Greenland and Mexico, it has not been adopted there. In Canada and US, replaced NAD27.",,OGP,"2008/04/11",2006.464 2008.024,0,"D_North_American_1983"
 6270,Nahrwan 1967,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1967,7012,8901,1351,Topographic mapping.,"In Iraq, replaces Nahrwan 1934.",,OGP,"2008/06/24",2006.340 2008.045,0,"D_Nahrwan_1967"
 6271,Naparima 1972,geodetic,"Fundamental point: Naparima. Latitude: 10°16'44.860""N, longitude: 61°27'34.620""W (of Greenwich).",1972,7022,8901,1322,Topographic mapping.,Naparima 1972 is an extension of the Naparima 1955 network of Trinidad to include Tobago.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Naparima_1972"
 6272,New Zealand Geodetic Datum 1949,geodetic,"Fundamental point: Papatahi. Latitude: 41°19' 8.900""S, longitude: 175°02'51.000""E (of Greenwich).",1949,7022,8901,3285,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by New Zealand Geodetic Datum 2000 (code 6167) from March 2000.","Land Information New Zealand. http://www.linz.govt.nz/rcs/linz/pub/web/root/core/SurveySystem/GeodeticInfo/GeodeticDatums/nzgd2000factsheet/index.jsp",OGP,"2008/06/24",2000.702 2004.110 2008.045,0,"D_New_Zealand_1949"
 6273,NGO 1948,geodetic,"Fundamental point: Oslo observatory. Latitude: 59°54'43.7""N, longitude: 10°43'22.5""E (of Greenwich).",1948,7005,8901,1352,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/06/24",2003.362 2008.045,0,"D_NGO_1948"
 6274,Datum 73,geodetic,"Fundamental point:  TF4, Melrica. Latitude: 39°41'37.30""N, longitude: 8°07'53.31""W (of Greenwich).",1964,7022,8901,1294,Topographic mapping.,,"Instituto Geografico e Cadastral; Lisbon",OGP,"2008/06/24",2008.045,0,"D_Datum_73"
-6275,Nouvelle Triangulation Francaise,geodetic,"Fundamental point: Pantheon. Latitude: 48°50'46.522""N, longitude: 2°20'48.667""E (of Greenwich).",1895,7011,8901,1326,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_NTF"
+6275,Nouvelle Triangulation Francaise,geodetic,"Fundamental point: Pantheon. Latitude: 48°50'46.522""N, longitude: 2°20'48.667""E (of Greenwich).",1895,7011,8901,3694,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2008.045 2009.106,0,"D_NTF"
 6276,NSWC 9Z-2,geodetic,,,7025,8901,1262,Satellite navigation.,Transit precise ephemeris before 1991.,,OGP,"1995/06/02",,0,"D_NSWC_9Z_2"
-6277,OSGB 1936,geodetic,"Fundamental point: Pre 2002: Herstmonceux, Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich). From April 2002 the datum is defined through the application of the OSTN02 transformation (tfm code 1039) to ETRS89.",1936,7001,8901,1264,Topographic mapping.,,Ordnance Survey of Great Britain,OGP,"2009/07/22",2002.620 2008.045 2009.055,0,"D_OSGB_1936"
+6277,OSGB 1936,geodetic,"From April 2002 the datum is defined through the application of the OSTN02 transformation (tfm code 1039) to ETRS89. Prior to 2002, fundamental point: Herstmonceux, Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1936,7001,8901,1264,Topographic mapping.,"The average accuracy of OSTN02 compared to the old triangulation network (down to 3rd order) is 0.1m.",Ordnance Survey of Great Britain,OGP,"2011/03/14",2002.620 2008.045 2009.055 2010.106,0,"D_OSGB_1936"
 6278,"OSGB 1970 (SN)",geodetic,"Fundamental point: Herstmonceux. Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1970,7001,8901,1264,Scientific network.,,,OGP,"2008/06/24",2005.880 2008.045,0,"D_OSGB_1970_SN"
 6279,"OS (SN) 1980",geodetic,"Fundamental point: Herstmonceux. Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1980,7001,8901,1354,Scientific network.,,,OGP,"2008/06/24",2008.045,0,"D_OS_SN_1980"
 6280,Padang 1884,geodetic,"Fundamental point: Padang.",1884,7004,8901,1355,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Padang_1884"
 6281,Palestine 1923,geodetic,"Fundamental point: Point 82'M  Jerusalem. Latitude: 31°44' 2.749""N, longitude: 35°12'43.490""E (of Greenwich).",1923,7010,8901,1356,Topographic mapping.,,,OGP,"2008/06/24",2004.150 2008.045,0,"D_Palestine_1923"
 6282,Congo 1960 Pointe Noire,geodetic,"Fundamental point: Point Noire Astro. Latitude: 4°47'00.10""S, longitude: 11°51'01.55""E (of Greenwich).",1960,7011,8901,1072,Topographic mapping.,,Elf,OGP,"2008/06/24",2002.050 2003.361 2008.045,0,"D_Pointe_Noire"
-6283,Geocentric Datum of Australia 1994,geodetic,ITRF92 at epoch 1994.0.,1994,7019,8901,2575,"Topographic mapping, geodetic survey.",Coincident with WGS84 to within 1 metre.,"Australian Surveying and Land Information Group Internet WWW page. http://www.auslig.gov.au/geodesy/datums/gda.htm#specs",OGP,"1995/06/02",,0,"D_GDA_1994"
+6283,Geocentric Datum of Australia 1994,geodetic,ITRF92 at epoch 1994.0.,1994,7019,8901,1036,"Topographic mapping, geodetic survey.",Coincident with WGS84 to within 1 metre.,"Australian Surveying and Land Information Group Internet WWW page. http://www.auslig.gov.au/geodesy/datums/gda.htm#specs",OGP,"2011/01/25",2011.004,0,"D_GDA_1994"
 6284,Pulkovo 1942,geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'18.550""N, longitude: 30°19'42.090""E (of Greenwich).",1942,7024,8901,2423,Topographic mapping.,,,OGP,"2008/09/24",2008.011 2008.045,0,"D_Pulkovo_1942"
 6285,Qatar 1974,geodetic,"Fundamental point: Station G3.",1974,7022,8901,1346,Topographic mapping.,,,OGP,"2001/08/28",2001.270,0,"D_Qatar"
 6286,Qatar 1948,geodetic,"Fundamental point: Sokey 0 M. Latitude: 25°22'56.500""N, longitude: 50°45'41.000""E (of Greenwich).",1948,7020,8901,1346,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Qatar_1948"
@@ -355,19 +387,19 @@ US NGA, http://earth-info.nga.mil/GandG/index.html",OGP,"2008/08/12",2003.362 20
 6294,Segora,geodetic,,,7004,8901,1359,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Segora"
 6295,Serindung,geodetic,"Fundamental point: Ep A. Latitude: 1°06'10.60""N, longitude: 105°00'59.82""E (of Greenwich).",,7004,8901,1360,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2008.045,0,"D_Serindung"
 6296,Sudan,geodetic,,,7011,8901,1361,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Sudan"
-6297,Tananarive 1925,geodetic,"Fundamental point: Tananarive observatory. Latitude: 18°55'02.10""S, longitude: 47°33'06.75""E (of Greenwich).",2025,7022,8901,3273,Topographic mapping.,,IGN Paris,OGP,"2008/06/24",2003.361 2008.045,0,"D_Tananarive_1925"
+6297,Tananarive 1925,geodetic,"Fundamental point: Tananarive observatory. Latitude: 18°55'02.10""S, longitude: 47°33'06.75""E (of Greenwich).",2025,7022,8901,1149,Topographic mapping.,,IGN Paris,OGP,"2010/03/30",2003.361 2008.045 2009.106,0,"D_Tananarive_1925"
 6298,Timbalai 1948,geodetic,"Fundamental point: Station P85 at Timbalai. Latitude: 5°17' 3.548""N, longitude: 115°10'56.409""E (of Greenwich).",1948,7016,8901,1362,Topographic mapping.,"In 1968, the original adjustment was densified in Sarawak and extended to Sabah.",Defence Geographic Centre.,OGP,"2008/06/24",2006.252 2008.045,0,"D_Timbalai_1948"
 6299,TM65,geodetic,Adjusted to best mean fit 12 stations of the OSNI 1952 primary adjustment.,1965,7002,8901,1305,Topographic mapping.,"Differences between OSNI 1952 and TM65 at these stations are RMS 0.25m east, 0.23m north, maximum vector 0.57m. TM65 replaced by and not to be confused with Geodetic Datum of 1965 alias 1975 Mapping Adjustment or TM75 (datum code 6300).","""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,"2003/06/27",2002.621,0,"D_TM65"
 6300,Geodetic Datum of 1965,geodetic,Adjusted to best mean fit 9 stations of the OSNI 1952 primary adjustment in Northern Ireland plus the 1965 values of 3 stations in the Republic of Ireland.,1975,7002,8901,1305,"Geodetic survey, topographic mapping and engineering survey.","Differences from the 1965 adjustment (datum code 6299) are: average difference in Eastings 0.092m; average difference in Northings 0.108m; maximum vector difference 0.548m.","""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,"2003/06/27",2002.621,0,"D_TM75"
-6301,Tokyo,geodetic,"Fundamental point: Nikon-Keido-Genten. Latitude: 35°39'17.5148""N, longitude: 139°44'40.5020""E (of Greenwich).",,7004,8901,1364,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by Japanese Geodetic Datum 2000 (code 6611).","Geographic Survey Institute; Japan; Bulletin 40 (March 1994).  Also http://vldb.gsi.go.jp/sokuchi/datum/tokyodatum.html",OGP,"2008/06/24",1998.460 2002.080 2008.045,0,"D_Tokyo"
+6301,Tokyo,geodetic,"Fundamental point: Nikon-Keido-Genten. Latitude: 35°39'17.5148""N, longitude: 139°44'40.5020""E (of Greenwich). Longitude derived in 1918.",1918,7004,8901,1364,"Geodetic survey, cadastre, topographic mapping, engineering survey.","In Japan, replaces Tokyo 1892 (code 1048) and replaced by Japanese Geodetic Datum 2000 (code 6611). In Korea used only for geodetic applications before being replaced by Korean 1985 (code 6162).","Geographic Survey Institute; Japan; Bulletin 40 (March 1994).  Also http://vldb.gsi.go.jp/sokuchi/datum/tokyodatum.html",OGP,"2010/06/30",1998.460 2002.080 2008.045 2010.050,0,"D_Tokyo"
 6302,Trinidad 1903,geodetic,"Station 00, Harbour Master's Flagstaff, Port of Spain. 
 Trinidad 1903 / Trinidad Grid coordinates (Clarke's links): 333604.30 E, 436366.91 N (Latitude: 10°38'39.01""N,  Longitude: 61°30'38.00""W of Greenwich)",1903,7007,8901,1339,Topographic mapping.,,"""Land Surveyor's Handbook"", 1935, published under the direction of JW MacGillivray, Surveyor General, Land & Survey's Department, Trinidad & Tobago.",OGP,"2008/06/24",2003.362 2004.130 2008.045,0,"D_Trinidad_1903"
 6303,Trucial Coast 1948,geodetic,"Fundamental point: TC1. Latitude: 25°23'50.190""N, longitude: 55°26'43.950""E (of Greenwich).",1948,7020,8901,1363,Oil industry mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Trucial_Coast_1948"
 6304,Voirol 1875,geodetic,"Fundamental point: Voirol. Latitude: 36°45'07.927""N, longitude: 3°02'49.435""E of Greenwich. Uses RGS (and old IGN) value of 2°20'13.95""for Greenwich-Paris meridian difference.",1875,7011,8901,1365,Topographic mapping.,"Replaced by Voirol 1879 (code 6671).",IGN Paris,OGP,"2008/06/24",2003.361 2008.045,0,"D_Voirol_1875"
 6306,Bern 1938,geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'07.890""N, longitude: 7°26'22.335""E (of Greenwich).",1938,7004,8901,1286,Topographic mapping.,"This redetermination of the coordinates of fundamental point is used for scientific purposes and as the graticule overprinted on topographic maps constructed on the CH1903 / LV03 projected CS (code 21781).","""Die Projektionen der schweizerischen Plan- und Kartenwerke""; J. Bolliger 1967",OGP,"2008/06/24",2008.045,0,"D_Bern_1938"
-6307,Nord Sahara 1959,geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959,7012,8901,1365,Topographic mapping.,"Sometimes incorrectly referred to as Voirol Unifie 1960. Voirol Unifie 1960 is NOT a datum:  it is two projected coordinate systems based on  Nord Sahara 1959.  See coordinate system codes 30791 and 30792.","""Le System Geodesique Nord-Sahara""; IGN Paris",OGP,"2006/01/16",1999.620 2003.361 2005.880,0,"D_Nord_Sahara_1959"
+6307,Nord Sahara 1959,geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959,7012,8901,3213,Topographic mapping.,"Adjustment includes Morocco and Tunisia but use only in Algeria. Within Algeria the adjustment is north of 32°N but use has been extended southwards in many disconnected projects, some based on independent astro stations rather than the geodetic network.","""Le System Geodesique Nord-Sahara""; IGN Paris",OGP,"2010/03/30",1999.620 2003.361 2005.880 2009.106,0,"D_Nord_Sahara_1959"
 6308,Stockholm 1938,geodetic,"Fundamental point: Stockholm observatory.",1938,7004,8901,3313,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RT90 adjustment (datum code 6124)",,OGP,"1996/04/12",,0,"D_Stockholm_1938"
-6309,Yacare,geodetic,"Fundamental point: Yacare. Latitude: 30°35'53.68""S, longitude: 57°25'01.30""W (of Greenwich).",,7022,8901,1247,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2008.045,0,"D_Yacare"
+6309,Yacare,geodetic,"Fundamental point: Yacare. Latitude: 30°35'53.68""S, longitude: 57°25'01.30""W (of Greenwich).",,7022,8901,3326,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2011/03/28",2003.362 2005.460 2008.045 2011.018 2011.021,0,"D_Yacare"
 6310,Yoff,geodetic,"Fundamental point: Yoff. Latitude: 14°44'41.62""N, longitude: 17°29'07.02""W (of Greenwich).",,7011,8901,1207,Topographic mapping.,,,OGP,"2008/06/24",2003.362 2008.045,0,"D_Yoff"
 6311,Zanderij,geodetic,,,7022,8901,1222,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Zanderij"
 6312,Militar-Geographische Institut,geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 16°17'41.06""E (of Greenwich).",1901,7004,8901,1037,Geodetic survey.,"The longitude of the datum origin equates to a value for the Ferro meridian of 17°40' exactly west of Greenwich.","Bundesamt fur Eich- und Vermessungswesen; Wien",OGP,"2009/06/02",2008.045 2009.015,0,"D_MGI"
@@ -399,14 +431,14 @@ http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf",OGP,"2006/08/25",2002.151 2
 6614,Qatar National Datum 1995,geodetic,Defined by transformation from WGS 84 - see coordinate operation code 1840.,1995,7022,8901,1346,Topographic mapping.,,Qatar Centre for Geographic Information.,OGP,"2002/06/28",,0,"D_QND_1995"
 6615,Porto Santo 1936,geodetic,SE Base on Porto Santo island.,1936,7022,8901,1314,Topographic mapping.,"Replaced by 1995 adjustment (datum code 6663). For Selvagens see Selvagem Grande (code 6616).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2003/08/14",2003.231 2003.232,0,"D_Porto_Santo_1936"
 6616,Selvagem Grande,geodetic,,,7022,8901,2779,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2003/08/14",2003.232,0,
-6618,South American Datum 1969,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"").",1969,7050,8901,1358,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places.",DMA 1974.,OGP,"2008/06/24",2003.362 2008.045,0,"D_South_American_1969"
-6619,SWEREF99,geodetic,Densification of ETRS89.,1982,7019,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"National Land Survey of Sweden http://www.lantmateriet.se",OGP,"2002/09/19",,0,"D_SWEREF99"
+6618,South American Datum 1969,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"").",1969,7050,8901,1358,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. In Brazil only, replaced by SAD69(96) (datum code 1075).",DMA 1974.,OGP,"2011/07/27",2003.362 2008.045 2011.053,0,"D_South_American_1969"
+6619,SWEREF99,geodetic,Densification of ETRS89.,1999,7019,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","The solution was calculated in ITRF 97 epoch 1999.5, and has subsequently been corrected to ETRS 89 in accordance with guidelines given by EUREF.","National Land Survey of Sweden http://www.lantmateriet.se",OGP,"2010/03/01",2009.024,0,"D_SWEREF99"
 6620,Point 58,geodetic,"Fundamental point: Point 58. Latitude: 3°58'37.040""N, longitude: 12°52'44.045""E (of Greenwich).",1969,7012,8901,2790,Geodetic survey,Used as the basis for computation of the 12th Parallel traverse conducted 1966-70 from Senegal to Chad and connecting to the Adindan triangulation in Sudan.,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Point_58"
 6621,Fort Marigot,geodetic,,,7022,8901,2828,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2009.073,0,"D_Fort_Marigot"
 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,1196,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Piton des Neiges (code 6626).",IGN Paris.,OGP,"2006/08/18",2006.770,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"
@@ -419,7 +451,7 @@ http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf",OGP,"2006/08/25",2002.151 2
 6635,ST87 Ouvea,geodetic,,1987,7022,8901,2813,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,1,"D_ST87_Ouvea"
 6636,Petrels 1972,geodetic,"Fundamental point: Astro station DZ on Ile de Petrels. Latitude: 66°40'00""S, longitude: 140°00'46""E (of Greenwich).",1972,7022,8901,2817,"Geodetic survey,  topographic mapping.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Petrels_1972"
 6637,Pointe Geologie Perroud 1950,geodetic,"Fundamental point: Astro station G.0 on Pointe Geologie. Latitude: 66°39'30""S, longitude: 140°01'00""E (of Greenwich).",1950,7022,8901,2818,"Geodetic survey,  topographic mapping.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Pointe_Geologie_Perroud_1950"
-6638,Saint Pierre et Miquelon 1950,geodetic,,1950,7008,8901,1220,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGSPM06 (datum code 1038).",IGN Paris.,OGP,"2009/10/29",2006.060 2009.072,0,"D_Saint_Pierre_et_Miquelon_1950"
+6638,Saint Pierre et Miquelon 1950,geodetic,,1950,7008,8901,3299,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGSPM06 (datum code 1038).",IGN Paris.,OGP,"2011/01/25",2006.060 2009.072 2011.004,0,"D_Saint_Pierre_et_Miquelon_1950"
 6639,MOP78,geodetic,,1978,7022,8901,2815,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2002/11/29",,0,"D_MOP78"
 6640,Reseau de Reference des Antilles Francaises 1991,geodetic,WGS 84 coordinates of a single station determined during the 1988 Tango mission.,1991,7030,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Fort Marigot and Sainte Anne (datum codes 6621-22) in Guadeloupe and Fort Desaix (datum code 6625) in Martinique.",IGN Paris.,OGP,"2004/03/26",2004.200 2009.073,1,"D_RRAF_1991"
 6641,IGN53 Mare,geodetic,South-east end of the La Roche base.,1953,7022,8901,2819,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_IGN53_Mare"
@@ -437,10 +469,10 @@ http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf",OGP,"2006/08/25",2002.151 2
 6653,International Terrestrial Reference Frame 1994,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1994,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1994.0. Replaces ITRF93 (code 6652). Replaced by ITRF96 (code 6654).","International Earth Rotation Service (IERS) Technical Note No. 20. Also IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2006/10/13",2006.770 2006.892,0,
 6654,International Terrestrial Reference Frame 1996,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1996,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1996.0. Replaces ITRF94 (code 6653). Replaced by ITRF97 (code 6655).","International Earth Rotation Service (IERS) Technical Note No. 24. Also IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2006/10/13",2006.770 2006.892,0,
 6655,International Terrestrial Reference Frame 1997,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1997.0. Replaces ITRF96 (code 6654). Replaced by ITRF2000 (code 6656).","International Earth Rotation Service (IERS) Technical Note No. 27. Also IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2006/10/13",2006.770 2006.892,0,
-6656,International Terrestrial Reference Frame 2000,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",2000,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2000.0. Replaces ITRF97 (code 6655). Replaced by ITRF2005 (code 6758).","IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2006/10/13",2006.770 2006.892,0,
+6656,International Terrestrial Reference Frame 2000,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",2000,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2000.0. Replaces ITRF97 (code 6655). Replaced by ITRF2005 (code 6896).","IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2011/02/25",2006.770 2006.892 2011.002,0,
 6657,Reykjavik 1900,geodetic,"Fundamental point:  Latitude: 64°08'31.88""N, longitude: 21°55'51.15""W (of Greenwich).",1900,7051,8901,3262,Medium scale topographic mapping.,,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Reykjavik_1900"
 6658,Hjorsey 1955,geodetic,"Fundamental point:  Latitude: 64°31'29.26""N, longitude: 22°22'05.84""W (of Greenwich).",1955,7022,8901,3262,"1/50,000 scale topographic mapping.",,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Hjorsey_1955"
-6659,Islands Network 1993,geodetic,ITRF93 at epoch 1993.6.,1996,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2006/08/18",2006.770,0,"D_Islands_Network_1993"
+6659,Islands Net 1993,geodetic,ITRF93 at epoch 1993.6.,1996,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by ISN2004 (datum code 1060).","Landmaelingar Islands (National Survey of Iceland).",OGP,"2010/11/12",2006.770 2010.101,0,"D_Islands_Network_1993"
 6660,Helle 1954,geodetic,,1954,7022,8901,2869,"Geodetic survey, topographic mapping..",,Statens kartverk.,OGP,"2003/06/27",,0,"D_Helle_1954"
 6661,Latvia 1992,geodetic,Constrained to 4 ETRS89 points in Latvia from the EUREF Baltic 1992 campaign.,1992,7019,8901,1139,"Topographic mapping, geodetic survey.",Densification of ETRS89 during the 1992 Baltic campaign.,"Latvijas Republikas Valsts zemes dienests (State Land Service of the Republic of Latvia) via EuroGeographics. http://crs.bkg.bund.de/crs-eu/",OGP,"2003/06/27",,0,"D_Latvia_1992"
 6663,Porto Santo 1995,geodetic,SE Base on Porto Santo island. Origin and orientation constrained to those of the 1936 adjustment.,1995,7022,8901,1314,Topographic mapping.,"Classical and GPS observations. Replaces 1936 adjustment (datum code 6615). 
@@ -450,11 +482,11 @@ For Selvagens see Selvagem Grande (datum code 6616).","Instituto Geografico e Ca
 6666,Lisbon 1890,geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 9°07'54.862""W of Greenwich.",1937,7004,8901,1294,Topographic mapping.,"Replaced by Lisbon 1937 adjustment (which uses International 1924 ellipsoid).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2008/06/24",2003.361 2008.045,0,"D_Lisbon_1890"
 6667,Iraq-Kuwait Boundary Datum 1992,geodetic,Four stations established between September and December 1991 determined by GPS and Doppler observations.,1992,7030,8901,2876,International boundary demarcation,,"United Nations Iraq-Kuwait Boundary Demarcation Commission, Final Report, May 1993.",OGP,"2003/09/01",,0,"D_Iraq_Kuwait_Boundary_1992"
 6668,European Datum 1979,geodetic,"Fundamental point: Potsdam (Helmert Tower). Latitude: 52°22'51.4456""N, longitude: 13°03'58.9283""E (of Greenwich).",1979,7022,8901,1297,Scientific network.,Replaced by 1987 adjustment.,,OGP,"2008/06/24",2008.045,0,"D_European_1979"
-6670,Istituto Geografico Militaire 1995,geodetic,Network of 1296 points observed 1992-1995 and adjusted in 1996 constrained to 9 ETRS89 points. Densification of ETRS89 in Italy.,1995,7030,8901,1127,Geodetic survey and scientific study.,,ENI,OGP,"2004/01/07",,0,"D_IGM_1995"
+6670,Istituto Geografico Militaire 1995,geodetic,Network of 1296 points observed 1992-1995 and adjusted in 1996 constrained to 9 ETRS89 points. Densification of ETRS89 in Italy.,1995,7030,8901,3343,Geodetic survey and scientific study.,,ENI,OGP,"2011/01/25",2011.004,0,"D_IGM_1995"
 6671,Voirol 1879,geodetic,"Fundamental point: Voirol. Latitude: 36°45'08.199""N, longitude: 3°02'49.435""E (of Greenwich). Uses RGS (and old IGN) value of 2°20'13.95""for Greenwich-Paris meridian difference.",1879,7011,8901,1365,Topographic mapping.,"Replaces Voirol 1875 (code 6304).",IGN Paris,OGP,"2008/06/24",2008.045,0,"D_Voirol_1879"
 6672,Chatham Islands Datum 1971,geodetic,,1971,7022,8901,2889,"Geodetic survey, topographic mapping, engineering survey.","Replaced by Chatham Islands Datum 1979 (code 6673).","Office of Surveyor General (OSG) Technical Report 14, June 2001.",OGP,"2004/02/17",,0,"D_Chatham_Island_1971"
 6673,Chatham Islands Datum 1979,geodetic,"Fundamental point: station Astro. Latitude: 43°57'23.60""S, longitude: 176°34'28.65""W (of Greenwich).",1979,7022,8901,2889,"Geodetic survey, topographic mapping, engineering survey.","Replaces Chatham Islands Datum 1971 (code 6672). Replaced by New Zealand Geodetic Datum 2000 (code 6167) from March 2000.","Office of Surveyor General (OSG) Technical Report 14, June 2001.",OGP,"2008/06/24",2008.045,0,"D_Chatham_Islands_1979"
-6674,Sistema de Referencia Geocentrico para America del Sur 2000,geodetic,ITRF2000 at epoch 2000.40.,2000,7019,8901,3418,Geodetic survey.,"Realised by a frame of 184 stations observed in 2000 and adjusted in the ITRF2000. Includes ties to tide gauges. Replaces SIRGAS 1995 system for South America; expands SIRGAS to Mexico and Central America.  In Mexico, replaces Mexico 1992 (code 1042).","IBGE Brazil,  http://www1.ibge.gov.br/",OGP,"2009/11/24",2005.460 2005.830 2006.465 2006.770 2009.087,0,"D_SIRGAS_2000"
+6674,Sistema de Referencia Geocentrico para las AmericaS 2000,geodetic,ITRF2000 at epoch 2000.40.,2000,7019,8901,3418,Geodetic survey.,"Realised by a frame of 184 stations observed in 2000 and adjusted in the ITRF2000. Includes ties to tide gauges. Replaces SIRGAS 1995 system for South America; expands SIRGAS to Central America.  Name changed in 2001 for use in all of Latin America.","IBGE Brazil,  http://www1.ibge.gov.br/",OGP,"2011/07/27",2005.460 2005.830 2006.465 2006.770 2009.087 2010.090 2011.053,0,"D_SIRGAS_2000"
 6675,Guam 1963,geodetic,"Fundamental point: Tagcha. Latitude: 13°22'38.49""N, longitude: 144°45'51.56""E (of Greenwich).",1963,7008,8901,3255,Topographic mapping.,"Replaced by NAD83(HARN)","US National Geospatial Intelligence Agency (NGA). http://earth-info.nga.mil/",OGP,"2008/06/24",2005.460 2008.045,0,"D_Guam_1963"
 6676,Vientiane 1982,geodetic,"Fundamental point: Vientiane (Nongteng) Astro Pillar. Latitude: 18°01'31.6301""N, longitude: 102°30'56.6999""E (of Greenwich).",1982,7024,8901,1138,Topographic mapping.,Replaced by Lao 1993.,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Vientiane_1982"
 6677,Lao 1993,geodetic,"Fundamental point: Lao 1982 coordinates of Pakxa pillar. Latitude: 18°23'57.0056""N, longitude: 103°38'41.8020""E (of Greenwich). Orientation parallel with WGS 84.",1993,7024,8901,1138,Topographic mapping.,Replaces Vientiane 1982. Replaced by Lao 1997,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Lao_1993"
@@ -463,10 +495,10 @@ For Selvagens see Selvagem Grande (datum code 6616).","Instituto Geografico e Ca
 6680,Nouakchott 1965,geodetic,Nouakchott astronomical point.,1965,7012,8901,2968,Topographic survey.,"Triangulation limited to environs of Nouakchott. Extended in 1982 by satellite translocation from a single station ""Ruines"" to support Syledis chain for offshore operations. Replaced by Mauritania 1999 (datum code 6602).",IGN Paris and various industry sources.,OGP,"2006/06/12",2006.440,0,"D_Nouakchott_1965"
 6681,Mauritania 1999,geodetic,,1999,7012,8901,1157,"Minerals management, topographic mapping.","A network of 36 GPS stations tied to ITRF96, 8 of which are IGN astronomic points.",Woodside,OGP,"2004/10/14",,1,"D_Mauritania_1999"
 6682,Gulshan 303,geodetic,"Gulshan garden, Dhaka.",1995,7015,8901,1041,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Network of more than 140 control points observed and adjusted in 1995 by Japan International Cooperation Agency (JICA).",Survey of Bangladesh via IGN Paris and Tullow Oil.,OGP,"2006/06/22",2006.470,0,"D_Gulshan_303"
-6683,Philippine Reference System 1992,geodetic,"Fundamental point: Balacan. Latitude: 13°33'41.000""N, longitude: 121°52'03.000""E (of Greenwich), geoid-ellipsoid separation 0.34m.",1992,7008,8901,1190,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Luzon 1911 datum (code 6253).","National Mapping and Resource Information Authority, Coast and Geodetic Survey Department.",OGP,"2008/06/24",2008.045,0,"D_Phillipine_Reference_System_1992"
+6683,Philippine Reference System 1992,geodetic,"Fundamental point: Balacan. Latitude: 13°33'41.000""N, longitude: 121°52'03.000""E (of Greenwich), geoid-ellipsoid separation 0.34m.",1992,7008,8901,1190,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Luzon 1911 datum (code 6253).","National Mapping and Resource Information Authority, Coast and Geodetic Survey Department.",OGP,"2008/06/24",2008.045,0,"D_Philippine_Reference_System_1992"
 6684,Gan 1970,geodetic,,1970,7022,8901,3274,Topographic mapping.,"In some references incorrectly named ""Gandajika 1970"". See datum code 6685.",Various industry sources.,OGP,"2005/04/14",,0,"D_Gan_1970"
 6685,Gandajika,geodetic,Gandajika base.,1953,7022,8901,1259,Topographic mapping.,In some references incorrectly attributed to the Maldives. See datum code 6684.,Various industry sources.,OGP,"2005/04/14",,1,
-6686,Marco Geocentrico Nacional de Referencia,geodetic,"ITRF94 at epoch 1995.4.  Bogota observatory coordinates: Latitude: 4°35'46.3215""N, longitude: 74°04'39.0285""W (of Greenwich).",2004,7019,8901,3229,Geodetic survey.,"Densification of SIRGAS 1995 within Colombia. Replaces Bogota 1975 (datum code 6218).","Instituto Geografico Agustin Codazzi (IGAC) publication ""Aspectos prácticos de la adopción del Marco Geocéntrico Nacional de Referencia MAGNA-SIRGAS como datum oficial de Colombia"". http://www.igac.gov.co/MAGNAWEB/DocumentosMAGNA.htm",OGP,"2008/06/24",2006.770 2007.060 2008.045,0,"D_MAGNA"
+6686,Marco Geocentrico Nacional de Referencia,geodetic,"ITRF94 at epoch 1995.4.  Bogota observatory coordinates: Latitude: 4°35'46.3215""N, longitude: 74°04'39.0285""W (of Greenwich).",2004,7019,8901,1070,Geodetic survey.,"Densification of SIRGAS 1995 within Colombia. Replaces Bogota 1975 (datum code 6218).","Instituto Geografico Agustin Codazzi (IGAC) publication ""Aspectos prácticos de la adopción del Marco Geocéntrico Nacional de Referencia MAGNA-SIRGAS como datum oficial de Colombia"". http://www.igac.gov.co/MAGNAWEB/DocumentosMAGNA.htm",OGP,"2011/01/25",2006.770 2007.060 2008.045 2011.004,0,"D_MAGNA"
 6687,Reseau Geodesique de la Polynesie Francaise,geodetic,"ITRF92 at epoch 1993.0. Densification by GPS of the Reference Network of French Polynesia, a coordinate set of 13 stations determined through DORIS observations.",1993,7019,8901,1098,Geodetic survey.,"Replaces Tahaa 54 (datum code 6629), IGN 63 Hiva Oa (6689), IGN 72 Nuku Hiva (6630), Maupiti 83 (6692), MHEFO 55 (6688), Moorea 87 (6691) and Tahiti 79 (6690).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie. Also www.shom.fr, technical report 002/199.",OGP,"2006/08/18",2006.770,0,"D_Reseau_Geodesique_de_la_Polynesie_Francaise"
 6688,Fatu Iva 72,geodetic,"Fundamental point: Latitude: 9°25'58.00""S, longitude: 138°55'06.25""W (of Greenwich).",1972,7022,8901,3133,Hydrographic and topographic survey.,"Recomputed by IGN in 1972 using origin and observations of 1953-1955 Mission Hydrographique des Establissements Francais d'Oceanie (MHEFO 55). Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Fatu_Iva_1972"
 6689,IGN63 Hiva Oa,geodetic,"Fundamental point: Atuona. Latitude: 9°48'27.20""S, longitude: 139°02'15.45""W (of Greenwich).",1963,7022,8901,3130,Hydrographic and topographic survey.,"Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_IGN63_Hiva_Oa"
@@ -474,9 +506,7 @@ For Selvagens see Selvagem Grande (datum code 6616).","Instituto Geografico e Ca
 6691,Moorea 87,geodetic,Two stations on Tahiti whose coordinates from the Tahiti 1979 adjustment were held fixed.,1987,7022,8901,3125,Hydrographic and topographic survey.,"Replaces Tahiti 52 (datum code 6628) in Moorea. Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,"D_Moorea_1987"
 6692,Maupiti 83,geodetic,"Fundamental point: Pitiahe South Base. Latitude: 16°28'28.942""S, longitude: 152°14'55.059""W (of Greenwich).",1983,7022,8901,3126,Hydrographic and topographic survey.,"Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Maupiti_1983"
 6693,Nakhl-e Ghanem,geodetic,"Coordinates of two stations determined with respect to ITRF 2000 at epoch 2005.2: BMT1 latitude 27°42'09.8417""N, longitude 52°12'11.0362""E (of Greenwich); Total1 latitude 27°31'03.8896""N, longitude 52°36'13.1312""E (of Greenwich).",2005,7030,8901,2362,Engineering survey for onshore facilities for South Pars phase 11 and Pars LNG.,,Total,OGP,"2008/06/24",2006.770 2008.045,0,"D_Nakhl-e_Ghanem"
-6694,Posiciones Geodesicas Argentinas 1994,geodetic,"A geodetic network of 127 high accuracy surveyed points based on WGS 84 that define the National Geodetic System (Sistema Geodésico Nacional).",1994,7030,8901,1033,"Topographic mapping, geodetic survey.","Una red geodésica de 127 puntos materializados
-en el terreno que definen el Sistema Geodésico Nacional. 
-Technically, but at this record revision date not legally, replaced by POSGAR 98 (code 6190).","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.ar",OGP,"2008/06/23",2008.052,0,"D_POSGAR_1994"
+6694,Posiciones Geodesicas Argentinas 1994,geodetic,"A geodetic network of 127 high accuracy surveyed points based on WGS 84 that define the National Geodetic System (Sistema Geodésico Nacional).",1994,7030,8901,1033,"Topographic mapping, geodetic survey.","Technically, but not legally, replaced by POSGAR 98 (code 6190) until May 2009, when POSGAR 2007 was officially accepted and officially replaced POSGAR 94.","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.ar",OGP,"2011/03/28",2008.052 2009.028,0,"D_POSGAR_1994"
 6695,Katanga 1955,geodetic,"Fundamental point: Tshinsenda A. Latitude: 12°30'31.568""S, longitude: 28°01'02.971""E (of Greenwich).",1955,7008,8901,3147,"Cadastre, topographic mapping, engineering survey.",Replaces earlier adjustments.,"Clifford J. Mugnier, in Photogrammetric Engineering and Remote Sensing, June 2005.",OGP,"2009/06/02",2008.045 2009.011,0,"D_Katanga_1955"
 6696,Kasai 1953,geodetic,"Two stations of the Katanga triangulation with ellipsoid change applied: Kabila, latitude 6°58'34.023""S, longitude 23°50'24.028""E (of Greenwich); and Gandajika NW base, latitude 6°45'01.057""S, longitude 23°57'03.038""E (of Greenwich).",1955,7012,8901,3148,"Cadastre, topographic mapping, engineering survey.",Replaced by IGC 1962 Arc of the 6th Parallel South.,Institute Geographique du Congo,OGP,"2008/06/24",2008.045,0,"D_Kasai_1955"
 6697,IGC 1962 Arc of the 6th Parallel South,geodetic,"Coordinates of 3 stations determined with respect to Arc 1950: Mulungu 4°47'39.2325""S, 29°59'37.5864""E; Nyakawembe 4°14'57.3618""S, 29°42'52.8032""E; Kavula 4°35'15.8634""S, 29°41'14.2693""E (all longitude w.r.t. Greenwich).",1962,7012,8901,3149,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Institute Geographique du Congo,OGP,"2008/06/24",2006.721 2008.045,0,"D_IGC_1962_Arc_of_the_6th_Parallel_South"
@@ -510,7 +540,7 @@ Technically, but at this record revision date not legally, replaced by POSGAR 98
 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"
 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,3199,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,"2009/06/02",2009.033,0,"D_Pico_de_Las_Nieves"
+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"
 6730,Santo 1965,geodetic,,1965,7022,8901,3194,Military and topographic mapping,"Datum covers all the major islands of Vanuatu in two different adjustment blocks, but practical usage is as given in the area of use.","DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/07/29",2006.510,0,"D_Santo_DOS_1965"
 6731,Viti Levu 1916,geodetic,,1916,7012,8901,3195,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,1,"D_Viti_Levu_1916"
@@ -522,10 +552,10 @@ Technically, but at this record revision date not legally, replaced by POSGAR 98
 6737,Geocentric datum of Korea,geodetic,ITRF2000 at epoch 2002.0.,2002,7019,8901,1135,Geodetic survey.,,"Permanent Committee for GIS Infrastructure for Asia and the Pacific (PCGIAP), http://www.gsi.go.jp/PCGIAP",OGP,"2006/08/18",2006.770,0,"D_Korea_2000"
 6738,Hong Kong 1963,geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82""N, longitude 114°10'18.75""E (of Greenwich).",1963,7007,8901,1118,Topographic mapping and hydrographic charting.,"Replaced by Hong Kong 1963(67) for military purposes only in 1967.  Replaced by Hong Kong 1980.","Survey and Mapping Office, Lands Department. http://www.info.gov.hk/landsd/",OGP,"2008/06/24",2008.045,0,"D_Hong_Kong_1963"
 6739,"Hong Kong 1963(67)",geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82""N, longitude 114°10'18.75""E (of Greenwich).",1967,7022,8901,1118,Military mapping and charting.,Replaces Hong Kong 1963 for military purposes only in 1967.  Replaced by Hong Kong 1980.,UK Hydrographic Office.,OGP,"2008/06/24",2008.045,0,"D_Hong_Kong_1963_67"
-6740,Parametrop Zemp 1990,geodetic,Geocentre.,1990,7054,8901,1262,Geodetic survey.,Derived through satellite tracking techniques.,"Geodeziya i Katografiya, 1993.",OGP,"2006/02/03",,0,"D_Parametrop_Zemp_1990"
+6740,Parametrop Zemp 1990,geodetic,Geocentre.,1990,7054,8901,1262,Geodetic survey.,"Derived through satellite tracking techniques. EPSG's PZ-90 datum has been the then current realisation. No distinction is made between the original PZ-90 frame and the PZ-90.02 improvement which was introduced in 2007.","Geodeziya i Katografiya, 1993.",OGP,"2010/03/30",2010.031,0,"D_Parametrop_Zemp_1990"
 6741,Faroe Datum 1954,geodetic,Astronomical observations at 3 points.,1954,7022,8901,3248,"Geodetic survey, topographic mapping, engineering and cadastral survey.","Replaced by ED50 in late 1970's for all purposes other than cadastre. Replaced by fk89 for cadastre.","Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/04",2005.472,0,"D_Faroe_Datum_1954"
 6742,Geodetic Datum of Malaysia 2000,geodetic,"ITRF2000, epoch 2000.0.",2000,7019,8901,1151,"Geodetic survey, topographic mapping, engineering and cadastrral survey.",Replaces all older Malaysian datums.,"GDM2000 Technical Manual; Department of Survey and Mapping Malaysia. www.jupem.gov.my",OGP,"2006/03/16",,0,"D_GDM_2000"
-6743,Karbala 1979,geodetic,"Fundamental point: Karbala. Latitude: 32°34'14.4941""N, longitude: 44°00'49.6379""E.",1979,7012,8901,1124,Geodetic survey.,National geodetic network established by Polservice consortium.,Various industry sources.,OGP,"2009/06/02",2009.003,0,"D_Karbala_1979_Polservice"
+6743,Karbala 1979,geodetic,"Fundamental point: Karbala. Latitude: 32°34'14.4941""N, longitude: 44°00'49.6379""E.",1979,7012,8901,3625,Geodetic survey.,National geodetic network established by Polservice consortium.,Various industry sources.,OGP,"2011/01/25",2009.003 2011.004,0,"D_Karbala_1979_Polservice"
 6744,Nahrwan 1934,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1934,7012,8901,3390,Oil exploration and production.,"This adjustment later discovered to have a significant orientation error. In Iran replaced by FD58. In Iraq, replaced by Nahrwan 1967.",Various industry sources.,OGP,"2008/06/24",2008.045,0,"D_Nahrwan_1934"
 6745,"Rauenberg Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990,7004,8901,2545,"Geodetic survey, cadastre, topographic mapping, engineering survey.","RD/83 is the realisation of DHDN in Saxony. It is the resultant of applying a transformation derived at 106 points throughout former East Germany to Pulkovo 1942/83 points in Saxony.","BKG via EuroGeographics. http://crs.bkg.bund.de",OGP,"2008/06/24",2008.045,0,
 6746,"Potsdam Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990,7004,8901,2544,"Geodetic survey, cadastre, topographic mapping, engineering survey.","PD/83 is the realisation of DHDN in Thuringen. It is the resultant of applying a transformation derived at 13 points on the border between East and West Germany to Pulkovo 1942/83 points in Thuringen.","BKG via EuroGeographics. http://crs.bkg.bund.de",OGP,"2008/06/24",2008.045,0,
@@ -538,7 +568,7 @@ Technically, but at this record revision date not legally, replaced by POSGAR 98
 6753,fk89,geodetic,,1989,7022,8901,3248,Cadastre,Replaces FD54 for cadastre.,"Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/04",,0,"D_fk89"
 6754,Libyan Geodetic Datum 2006,geodetic,5 stations tied to ITRF2000 through 8 days of continuous observations in May 2006.,2006,7022,8901,1143,"Geodetic survey, topographic mapping, engineering survey.",Replaces ELD79.,Survey Department of Libya.,OGP,"2006/08/25",,0,"D_Libyan_Geodetic_Datum_2006"
 6755,Datum Geodesi Nasional 1995,geodetic,ITRF91at epoch 1992.0.,1995,7030,8901,1122,"Geodetic survey, topographic mapping, engineering survey.",Replaces ID74 and all older datums.,Bakosurtanal.,OGP,"2006/08/25",,0,"D_Datum_Geodesi_Nasional_1995"
-6756,Vietnam 2000,geodetic,"Point N00, located in the premises of the Land Administration Research Institute, Hoang Quoc Viet Street, Hanoi.",2000,7030,8901,1252,"Geodetic survey, topographic mapping, engineering survey.",Replaces Hanoi 1972.,General Director of Land Administration.,OGP,"2006/09/13",,0,"D_Vietnam_2000"
+6756,Vietnam 2000,geodetic,"Point N00, located in the premises of the Land Administration Research Institute, Hoang Quoc Viet Street, Hanoi.",2000,7030,8901,3328,"Geodetic survey, topographic mapping, engineering survey.",Replaces Hanoi 1972.,General Director of Land Administration.,OGP,"2011/01/25",2011.004,0,"D_Vietnam_2000"
 6757,SVY21,geodetic,"Fundamental point: Base 7 at Pierce Resevoir. Latitude: 1°22'02.9154""N, longitude: 103°49'31.9752""E (of Greenwich).",2004,7030,8901,1210,Cadastre.,Replaces Kertau 1968 for cadastral purposes from August 2004.,Singapore Land Authority,OGP,"2008/06/24",2008.045,0,"D_SVY21"
 6758,Jamaica 2001,geodetic,Aligned to WGS 84.,2001,7030,8901,1128,"Geodetic survey, cadastre, topographic mapping, hydrographic charting, engineering survey.",,National Land Agency.,OGP,"2007/01/19",,0,"D_Jamaica_2001"
 6759,"NAD83 (National Spatial Reference System 2007)",geodetic,"Coordinates of 486 national continually operating reference system (CORS) and 195 collaborative GPS (CGPS) sites constrained to their CORS96 values, ITRF2000 at epoch 2002.0.",2007,7019,8901,1511,Geodetic survey.,,"U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2007/03/13",,0,
@@ -554,21 +584,21 @@ Technically, but at this record revision date not legally, replaced by POSGAR 98
 6804,"Makassar (Jakarta)",geodetic,"Fundamental point: station P1, Moncongloe. Latitude 5°08'41.42""S, longitude 12°35'47.15""E (of Jakarta).",,7004,8908,1316,Topographic mapping.,,OGP,OGP,"2008/06/24",2003.361 2008.045,0,"D_Makassar"
 6805,"Militar-Geographische Institut (Ferro)",geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 33°57'41.06""E (of Ferro).",1901,7004,8909,1321,Geodetic survey.,Replaced by MGI in Austria and MGI 1901 in former Yugoslavia.,"Bundesamt fur Eich- und Vermessungswesen; Wien",OGP,"2009/06/02",2008.045 2009.015,0,"D_MGI"
 6806,"Monte Mario (Rome)",geodetic,"Fundamental point: Monte Mario. Latitude: 41°55'25.51""N, longitude: 0°00' 00.00""E (of Rome).",,7022,8906,3343,Topographic mapping.,"Replaced Genova datum, Bessel 1841 ellipsoid, from 1940.",,OGP,"2008/06/24",2003.360 2008.045,0,"D_Monte_Mario"
-6807,"Nouvelle Triangulation Francaise (Paris)",geodetic,"Fundamental point: Pantheon. Latitude: 54.273618g N, longitude: 0.0106921g E (of Paris).",1895,7011,8903,1326,Topographic mapping.,,,OGP,"2004/01/07",2003.361,0,"D_NTF"
+6807,"Nouvelle Triangulation Francaise (Paris)",geodetic,"Fundamental point: Pantheon. Latitude: 54.273618g N, longitude: 0.0106921g E (of Paris).",1895,7011,8903,3694,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2009.106,0,"D_NTF"
 6808,"Padang 1884 (Jakarta)",geodetic,"Fundamental point: Padang",1884,7004,8908,1355,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Padang_1884"
 6809,"Reseau National Belge 1950 (Brussels)",geodetic,"Fundamental point: Lommel (tower). Latitude: 51°13'47.334""N, longitude: 0°56'44.773""E (of Brussels).",1950,7022,8910,1347,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Belge_1950"
 6810,"Tananarive 1925 (Paris)",geodetic,"Fundamental point: Tananarive observatory. Latitude: 21.0191667g S, longitude: 50.23849537g E (of Paris)",1925,7022,8903,3273,Topographic mapping.,,IGN Paris,OGP,"2003/12/31",2003.361,0,"D_Tananarive_1925"
 6811,"Voirol 1875 (Paris)",geodetic,"Fundamental point: Voirol. Latitude: 40.83578 grads N, longitude: 0.78873 grads E (of Paris).",1875,7011,8903,1365,Topographic mapping.,,IGN Paris,OGP,"2004/01/07",2003.361,0,"D_Voirol_1875"
 6813,"Batavia (Jakarta)",geodetic,"Fundamental point: Longitude at Batavia astronomical station. Latitude: 6°07'39.522""S, longitude: 0°00'00.0""E (of Jakarta). Latitude and azimuth at Genuk.",,7004,8908,1285,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Batavia"
 6814,"Stockholm 1938 (Stockholm)",geodetic,"Fundamental point: Stockholm observatory",1938,7004,8911,3313,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RT90 adjustment (datum code 6124)",,OGP,"1996/04/12",,0,"D_Stockholm_1938"
-6815,"Greek (Athens)",geodetic,"Fundamental point: Athens Observatory. Latitude 37°58'20.132""N, longitude 0°E (of Athens).",,7004,8912,1106,Topographic mapping.,See geodetic datum alias 6404.  Used as basis of topographic mapping based on Hatt projection.,"Topography Department; National Technical University of Athens",OGP,"2008/06/24",2008.045,0,"D_Greek"
+6815,"Greek (Athens)",geodetic,"Fundamental point: Athens Observatory. Latitude 37°58'20.132""N, longitude 0°E (of Athens).",,7004,8912,3254,Topographic mapping.,See geodetic datum alias 6404.  Used as basis of topographic mapping based on Hatt projection.,"Topography Department; National Technical University of Athens",OGP,"2011/07/20",2008.045 2011.062,0,"D_Greek"
 6816,"Carthage (Paris)",geodetic,"Fundamental point: Carthage. Latitude: 40.9464506g N, longitude: 8.8724368g E (of Paris).",1925,7011,8903,1618,Topographic mapping.,Fundamental point astronomic coordinates determined in 1878.,,OGP,"2004/01/15",2003.362 2003.050,0,"D_Carthage"
 6817,"NGO 1948 (Oslo)",geodetic,"Fundamental point: Oslo observatory. Latitude: 59°54'43.7""N, longitude: 0°00'00.0""E (of Oslo).",1948,7005,8913,1352,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,,OGP,"2008/06/24",2003.362 2008.045,0,"D_NGO_1948"
-6818,"S-JTSK (Ferro)",geodetic,"Modification of Austrian MGI (Ferro) datum.",1920,7004,8909,1306,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Research Institute for Geodesy Topography and Cartography (VUGTK); Prague.",OGP,"2001/08/28",2001.260,0,"D_S_JTSK"
+6818,"System Jednotne Trigonometricke Site Katastralni (Ferro)",geodetic,"Modification of Austrian MGI (Ferro) datum.",1920,7004,8909,1306,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Research Institute for Geodesy Topography and Cartography (VUGTK); Prague.",OGP,"2010/11/02",2001.260 2010.071,0,"D_S_JTSK"
 6819,"Nord Sahara 1959 (Paris)",geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959,7012,8903,1366,Topographic mapping.,,"""Le System Geodesique Nord-Sahara""; IGN Paris",OGP,"2000/06/23",,1,"D_Nord_Sahara_1959"
 6820,"Gunung Segara (Jakarta)",geodetic,"Station P5 (Gunung Segara) 0°32'12.83""S, 117°08'48.47""E (of Greenwich). Longitude 8°20'20.68""E (of Jakarta).",,7004,8908,1360,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Gunung_Segara"
 6821,"Voirol 1879 (Paris)",geodetic,"Fundamental point: Voirol. Latitude: 40.835864 grads N, longitude: 0.788735 grads E (of Paris).",1879,7011,8903,1365,Topographic mapping.,"Replaces Voirol 1875 (Paris) (code 6811).",IGN Paris,OGP,"2004/01/07",,0,"D_Voirol_1879"
-6896,International Terrestrial Reference Frame 2005,geodetic,"Origin at geocentre, originally orientated to the BIH Terrestrial System at epoch 1984.0 then adjusted to ensure zero net rotation to earth's overall tectonic motion. Defined by time series of Cartesian station coordinates and Earth Rotation parameters.",2005,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2005.0. Replaces ITRF2000 (code 6656).","IGN Paris http://itrf.ensg.ign.fr/itrs_itrf.php",OGP,"2007/01/19",,0,
+6896,International Terrestrial Reference Frame 2005,geodetic,"Origin at geocentre, originally orientated to the BIH Terrestrial System at epoch 1984.0 then adjusted to ensure zero net rotation to earth's overall tectonic motion. Defined by time series of Cartesian station coordinates and Earth Rotation parameters.",2005,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 2005.0. Replaces ITRF2000 (code 6656). Replaced by ITRF2008 (datum code 1061).","IGN Paris http://itrf.ensg.ign.fr/itrs_itrf.php",OGP,"2011/02/25",2011.002,0,
 6901,"Ancienne Triangulation Francaise (Paris)",geodetic,,,7027,8914,1326,Topographic mapping.,"Uses the RGS value for the Paris meridian.  In Alsace, data suspected to be transformation of German network into ATF. Replaced by Nouvelle Triangulation Francaise (Paris) (code 6807) which uses the 1936 IGN value for the Paris meridian.",,OGP,"2007/11/01",2007.083,0,"D_ATF"
 6902,"Nord de Guerre (Paris)",geodetic,,,7027,8903,1369,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Nord_de_Guerre"
 6903,"Madrid 1870 (Madrid)",geodetic,"Fundamental point: Madrid observatory.",1870,7028,8905,2366,Topographic mapping.,,"Institut de Geomatica; Barcelona",OGP,"1998/11/11",,0,"D_Madrid_1870"
diff --git a/data/geoccs.csv b/data/geoccs.csv
new file mode 100644
index 0000000..d93a342
--- /dev/null
+++ b/data/geoccs.csv
@@ -0,0 +1,115 @@
+"COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","DATUM_CODE","DATUM_NAME","GREENWICH_DATUM","UOM_CODE","ELLIPSOID_CODE","PRIME_MERIDIAN_CODE","SHOW_CRS","DEPRECATED","COORD_SYS_CODE"
+3822,TWD97,1026,Taiwan Datum 1997,1026,9001,7019,8901,1,0,6500
+3887,IGRS,1029,Iraqi Geospatial Reference System,1029,9001,7019,8901,1,0,6500
+4000,MOLDREF99,1032,MOLDREF99,1032,9001,7019,8901,1,0,6500
+4039,RGRDC 2005,1033,Reseau Geodesique de la RDC 2005,1033,9001,7019,8901,1,0,6500
+4073,SREF98,1034,Serbian Reference Network 1998,1034,9001,7019,8901,1,0,6500
+4079,REGCAN95,1035,Red Geodesica de Canarias 1995,1035,9001,7019,8901,1,0,6500
+4328,"WGS 84 (geocentric)",6326,World Geodetic System 1984,6326,9001,7030,8901,1,1,6500
+4330,"ITRF88 (geocentric)",6647,International Terrestrial Reference Frame 1988,6647,9001,7019,8901,1,1,6500
+4331,"ITRF89 (geocentric)",6648,International Terrestrial Reference Frame 1989,6648,9001,7019,8901,1,1,6500
+4332,"ITRF90 (geocentric)",6649,International Terrestrial Reference Frame 1990,6649,9001,7019,8901,1,1,6500
+4333,"ITRF91 (geocentric)",6650,International Terrestrial Reference Frame 1991,6650,9001,7019,8901,1,1,6500
+4334,"ITRF92 (geocentric)",6651,International Terrestrial Reference Frame 1992,6651,9001,7019,8901,1,1,6500
+4335,"ITRF93 (geocentric)",6652,International Terrestrial Reference Frame 1993,6652,9001,7019,8901,1,1,6500
+4336,"ITRF94 (geocentric)",6653,International Terrestrial Reference Frame 1994,6653,9001,7019,8901,1,1,6500
+4337,"ITRF96 (geocentric)",6654,International Terrestrial Reference Frame 1996,6654,9001,7019,8901,1,1,6500
+4338,"ITRF97 (geocentric)",6655,International Terrestrial Reference Frame 1997,6655,9001,7019,8901,1,1,6500
+4340,"Australian Antarctic (geocentric)",6176,Australian Antarctic Datum 1998,6176,9001,7019,8901,1,1,6500
+4342,"EST97 (geocentric)",6180,Estonia 1997,6180,9001,7019,8901,1,1,6500
+4344,"CHTRF95 (geocentric)",6151,Swiss Terrestrial Reference Frame 1995,6151,9001,7019,8901,1,1,6500
+4346,"ETRS89 (geocentric)",6258,European Terrestrial Reference System 1989,6258,9001,7019,8901,1,1,6500
+4348,"GDA94 (geocentric)",6283,Geocentric Datum of Australia 1994,6283,9001,7019,8901,1,1,6500
+4350,"Hartebeesthoek94 (geocentric)",6148,Hartebeesthoek94,6148,9001,7030,8901,1,1,6500
+4352,"IRENET95 (geocentric)",6173,IRENET95,6173,9001,7019,8901,1,1,6500
+4354,"JGD2000 (geocentric)",6612,Japanese Geodetic Datum 2000,6612,9001,7019,8901,1,1,6500
+4356,"LKS94 (ETRS89) (geocentric)",6126,"Lithuania 1994 (ETRS89)",6126,9001,7019,8901,1,1,6500
+4358,"Moznet (geocentric)",6130,"Moznet (ITRF94)",6130,9001,7030,8901,1,1,6500
+4360,"NAD83(CSRS) (geocentric)",6140,NAD83 Canadian Spatial Reference System,6140,9001,7019,8901,1,1,6500
+4362,"NAD83(HARN) (geocentric)",6152,"NAD83 (High Accuracy Reference Network)",6152,9001,7019,8901,1,1,6500
+4364,"NZGD2000 (geocentric)",6167,New Zealand Geodetic Datum 2000,6167,9001,7019,8901,1,1,6500
+4366,"POSGAR 98 (geocentric)",6190,Posiciones Geodesicas Argentinas 1998,6190,9001,7019,8901,1,1,6500
+4368,"REGVEN (geocentric)",6189,Red Geodesica Venezolana,6189,9001,7019,8901,1,1,6500
+4370,"RGF93 (geocentric)",6171,Reseau Geodesique Francais 1993,6171,9001,7019,8901,1,1,6500
+4372,"RGFG95 (geocentric)",6624,Reseau Geodesique Francais Guyane 1995,6624,9001,7019,8901,1,1,6500
+4374,"RGR92 (geocentric)",6627,Reseau Geodesique de la Reunion 1992,6627,9001,7019,8901,1,1,6500
+4376,"SIRGAS (geocentric)",6170,Sistema de Referencia Geocentrico para America del Sur 1995,6170,9001,7019,8901,1,1,6500
+4378,"SWEREF99 (geocentric)",6619,SWEREF99,6619,9001,7019,8901,1,1,6500
+4380,"Yemen NGN96 (geocentric)",6163,Yemen National Geodetic Network 1996,6163,9001,7030,8901,1,1,6500
+4382,"RGNC 1991 (geocentric)",6645,Reseau Geodesique Nouvelle Caledonie 1991,6645,9001,7022,8901,1,1,6500
+4384,"RRAF 1991 (geocentric)",6640,Reseau de Reference des Antilles Francaises 1991,6640,9001,7030,8901,1,1,6500
+4385,"ITRF2000 (geocentric)",6656,International Terrestrial Reference Frame 2000,6656,9001,7019,8901,1,1,6500
+4387,"ISN93 (geocentric)",6659,Islands Network 1993,6659,9001,7019,8901,1,1,6500
+4389,"LKS92 (geocentric)",6661,Latvia 1992,6661,9001,7019,8901,1,1,6500
+4465,RGSPM06,1038,Reseau Geodesique de Saint Pierre et Miquelon 2006,1038,9001,7019,8901,1,0,6500
+4468,RGM04,1036,Reseau Geodesique de Mayotte 2004,1036,9001,7019,8901,1,0,6500
+4473,Cadastre 1997,1037,Cadastre 1997,1037,9001,7022,8901,1,0,6500
+4479,China Geodetic Coordinate System 2000,1043,China 2000,1043,9001,1024,8901,1,0,6500
+4481,Mexican Datum of 1993,1042,Mexican Datum of 1993,1042,9001,7019,8901,1,0,6500
+4556,RRAF 1991,1047,Reseau de Reference des Antilles Francaises 1991,1047,9001,7019,8901,1,0,6500
+4882,Slovenia 1996,6765,Slovenia Geodetic Datum 1996,6765,9001,7019,8901,1,0,6500
+4884,RSRGD2000,6764,Ross Sea Region Geodetic Datum 2000,6764,9001,7019,8901,1,0,6500
+4886,BDA2000,6762,Bermuda 2000,6762,9001,7030,8901,1,0,6500
+4888,HTRS96,6761,Croatian Terrestrial Reference System,6761,9001,7019,8901,1,0,6500
+4890,WGS 66,6760,World Geodetic System 1966,6760,9001,7025,8901,1,0,6500
+4892,"NAD83(NSRS2007)",6759,"NAD83 (National Spatial Reference System 2007)",6759,9001,7019,8901,1,0,6500
+4894,JAD2001,6758,Jamaica 2001,6758,9001,7030,8901,1,0,6500
+4896,ITRF2005,6896,International Terrestrial Reference Frame 2005,6896,9001,7019,8901,1,0,6500
+4897,DGN95,6755,Datum Geodesi Nasional 1995,6755,9001,7030,8901,1,0,6500
+4899,LGD2006,6754,Libyan Geodetic Datum 2006,6754,9001,7022,8901,1,0,6500
+4906,RGNC91-93,6749,Reseau Geodesique de Nouvelle Caledonie 91-93,6749,9001,7019,8901,1,0,6500
+4908,GR96,6747,Greenland 1996,6747,9001,7019,8901,1,0,6500
+4910,ITRF88,6647,International Terrestrial Reference Frame 1988,6647,9001,7019,8901,1,0,6500
+4911,ITRF89,6648,International Terrestrial Reference Frame 1989,6648,9001,7019,8901,1,0,6500
+4912,ITRF90,6649,International Terrestrial Reference Frame 1990,6649,9001,7019,8901,1,0,6500
+4913,ITRF91,6650,International Terrestrial Reference Frame 1991,6650,9001,7019,8901,1,0,6500
+4914,ITRF92,6651,International Terrestrial Reference Frame 1992,6651,9001,7019,8901,1,0,6500
+4915,ITRF93,6652,International Terrestrial Reference Frame 1993,6652,9001,7019,8901,1,0,6500
+4916,ITRF94,6653,International Terrestrial Reference Frame 1994,6653,9001,7019,8901,1,0,6500
+4917,ITRF96,6654,International Terrestrial Reference Frame 1996,6654,9001,7019,8901,1,0,6500
+4918,ITRF97,6655,International Terrestrial Reference Frame 1997,6655,9001,7019,8901,1,0,6500
+4919,ITRF2000,6656,International Terrestrial Reference Frame 2000,6656,9001,7019,8901,1,0,6500
+4920,GDM2000,6742,Geodetic Datum of Malaysia 2000,6742,9001,7019,8901,1,0,6500
+4922,PZ-90,6740,Parametrop Zemp 1990,6740,9001,7054,8901,1,0,6500
+4924,Mauritania 1999,6702,Mauritania 1999,6702,9001,7019,8901,1,0,6500
+4926,Korea 2000,6737,Geocentric datum of Korea,6737,9001,7019,8901,1,0,6500
+4928,POSGAR 94,6694,Posiciones Geodesicas Argentinas 1994,6694,9001,7030,8901,1,0,6500
+4930,Australian Antarctic,6176,Australian Antarctic Datum 1998,6176,9001,7019,8901,1,0,6500
+4932,CHTRF95,6151,Swiss Terrestrial Reference Frame 1995,6151,9001,7019,8901,1,0,6500
+4934,EST97,6180,Estonia 1997,6180,9001,7019,8901,1,0,6500
+4936,ETRS89,6258,European Terrestrial Reference System 1989,6258,9001,7019,8901,1,0,6500
+4938,GDA94,6283,Geocentric Datum of Australia 1994,6283,9001,7019,8901,1,0,6500
+4940,Hartebeesthoek94,6148,Hartebeesthoek94,6148,9001,7030,8901,1,0,6500
+4942,IRENET95,6173,IRENET95,6173,9001,7019,8901,1,0,6500
+4944,ISN93,6659,Islands Network 1993,6659,9001,7019,8901,1,0,6500
+4946,JGD2000,6612,Japanese Geodetic Datum 2000,6612,9001,7019,8901,1,0,6500
+4948,LKS92,6661,Latvia 1992,6661,9001,7019,8901,1,0,6500
+4950,LKS94,6126,"Lithuania 1994 (ETRS89)",6126,9001,7019,8901,1,0,6500
+4952,Moznet,6130,"Moznet (ITRF94)",6130,9001,7030,8901,1,0,6500
+4954,"NAD83(CSRS)",6140,NAD83 Canadian Spatial Reference System,6140,9001,7019,8901,1,0,6500
+4956,"NAD83(HARN)",6152,"NAD83 (High Accuracy Reference Network)",6152,9001,7019,8901,1,0,6500
+4958,NZGD2000,6167,New Zealand Geodetic Datum 2000,6167,9001,7019,8901,1,0,6500
+4960,POSGAR 98,6190,Posiciones Geodesicas Argentinas 1998,6190,9001,7019,8901,1,0,6500
+4962,REGVEN,6189,Red Geodesica Venezolana,6189,9001,7019,8901,1,0,6500
+4964,RGF93,6171,Reseau Geodesique Francais 1993,6171,9001,7019,8901,1,0,6500
+4966,RGFG95,6624,Reseau Geodesique Francais Guyane 1995,6624,9001,7019,8901,1,0,6500
+4968,RGNC 1991,6645,Reseau Geodesique Nouvelle Caledonie 1991,6645,9001,7022,8901,1,1,6500
+4970,RGR92,6627,Reseau Geodesique de la Reunion 1992,6627,9001,7019,8901,1,0,6500
+4972,RRAF 1991,6640,Reseau de Reference des Antilles Francaises 1991,6640,9001,7030,8901,1,1,6500
+4974,SIRGAS 1995,6170,Sistema de Referencia Geocentrico para America del Sur 1995,6170,9001,7019,8901,1,0,6500
+4976,SWEREF99,6619,SWEREF99,6619,9001,7019,8901,1,0,6500
+4978,WGS 84,6326,World Geodetic System 1984,6326,9001,7030,8901,1,0,6500
+4980,Yemen NGN96,6163,Yemen National Geodetic Network 1996,6163,9001,7030,8901,1,0,6500
+4982,IGM95,6670,Istituto Geografico Militaire 1995,6670,9001,7030,8901,1,0,6500
+4984,WGS 72,6322,World Geodetic System 1972,6322,9001,7043,8901,1,0,6500
+4986,WGS 72BE,6324,WGS 72 Transit Broadcast Ephemeris,6324,9001,7043,8901,1,0,6500
+4988,SIRGAS 2000,6674,Sistema de Referencia Geocentrico para las AmericaS 2000,6674,9001,7019,8901,1,0,6500
+4990,Lao 1993,6677,Lao 1993,6677,9001,7024,8901,1,0,6500
+4992,Lao 1997,6678,Lao National Datum 1997,6678,9001,7024,8901,1,0,6500
+4994,PRS92,6683,Philippine Reference System 1992,6683,9001,7008,8901,1,0,6500
+4996,MAGNA-SIRGAS,6686,Marco Geocentrico Nacional de Referencia,6686,9001,7019,8901,1,0,6500
+4998,RGPF,6687,Reseau Geodesique de la Polynesie Francaise,6687,9001,7019,8901,1,0,6500
+5011,PTRA08,1041,Autonomous Regions of Portugal 2008,1041,9001,7019,8901,1,0,6500
+5244,GDBD2009,1056,Geocentric Datum Brunei Darussalam 2009,1056,9001,7019,8901,1,0,6500
+5250,TUREF,1057,Turkish National Reference Frame,1057,9001,7019,8901,1,0,6500
+5262,DRUKREF 03,1058,Bhutan National Geodetic Datum,1058,9001,7019,8901,1,0,6500
diff --git a/data/nitf_spec.xml b/data/nitf_spec.xml
new file mode 100644
index 0000000..f432ac5
--- /dev/null
+++ b/data/nitf_spec.xml
@@ -0,0 +1,1100 @@
+<?xml version="1.0"?>
+<!--
+/******************************************************************************
+ * $Id: nitf_spec.xml 22869 2011-08-06 14:17:54Z rouault $
+ *
+ * Project:  NITF Library
+ * Purpose:  Description of NITF TREs
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2011, 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.
+ ****************************************************************************/
+-->
+
+<!-- This file should validate against nitf_spec.xsd -->
+
+<tres>
+
+    <tre name="ACCPOB" minlength="17" maxlength="99985" location="image">
+        <field name="NUM_ACPO" length="2" type="integer" minval="1" maxval="99"/>
+        <loop counter="NUM_ACPO" md_prefix="ACCPO_%02d_" name="ACCPO">
+            <field name="UNIAAH" length="3" type="string"/>
+            <if cond="UNIAAH!=">
+                <field name="AAH" length="5" type="integer"/>
+            </if>
+            <field name="UNIAAV" length="3" type="string"/>
+            <if cond="UNIAAV!=">
+                <field name="AAV" length="5" type="integer"/>
+            </if>
+            <field name="UNIAPH" length="3" type="string"/>
+            <if cond="UNIAPH!=">
+                <field name="APH" length="5" type="integer"/>
+            </if>
+            <field name="UNIAPV" length="3" type="string"/>
+            <if cond="UNIAPV!=">
+                <field name="APV" length="5" type="integer"/>
+            </if>
+            <field name="NUM_PTS" length="3" type="integer"/>
+            <loop counter="NUM_PTS" md_prefix="POINT_%03d_" name="POINT">
+                <field name="LON" length="15" type="real"/>
+                <field name="LAT" length="15" type="real"/>
+            </loop>
+        </loop>
+    </tre>
+
+    <tre name="BLOCKA" length="123" location="image">
+        <field name="BLOCK_INSTANCE" length="2" type="integer" minval="1" maxval="99"/>
+        <field name="N_GRAY" length="5" type="integer" minval="0" maxval="99999"/>
+        <field name="L_LINES" length="5" type="integer" minval="1" maxval="99999"/>
+        <field name="LAYOVER_ANGLE" length="3" type="integer" minval="0" maxval="359" unit="degrees"/>
+        <field name="SHADOW_ANGLE" length="3" type="integer" minval="0" maxval="359" unit="degrees"/>
+        <field length="16"/>
+        <field name="FRLC_LOC" length="21"/>
+        <field name="LRLC_LOC" length="21"/>
+        <field name="LRFC_LOC" length="21"/>
+        <field name="FRFC_LOC" length="21"/>
+        <field length="5"/>
+    </tre>
+
+    <tre name="BNDPLB" minlength="124" maxlength="99964" location="image">
+        <field name="NUM_PTS" length="4" type="integer" minval="4" maxval="3332"/>
+        <loop counter="NUM_PTS" md_prefix="POINT_%04d_" name="POINT">
+            <field name="LON" length="15" type="real"/>
+            <field name="LAT" length="15" type="real"/>
+        </loop>
+    </tre>
+
+    <tre name="CSDIDA" md_prefix="NITF_CSDIDA_" length="70" location="file">
+        <field name="DAY" length="2"/>
+        <field name="MONTH" length="3"/>
+        <field name="YEAR" length="4"/>
+        <field name="PLATFORM_CODE" length="2"/>
+        <field name="VEHICLE_ID" length="2"/>
+        <field name="PASS" length="2"/>
+        <field name="OPERATION" length="3"/>
+        <field name="SENSOR_ID" length="2"/>
+        <field name="PRODUCT_ID" length="2"/>
+        <field name="RESERVED_0" length="4"/>
+        <field name="TIME" length="14"/>
+        <field name="PROCESS_TIME" length="14"/>
+        <field name="RESERVED_1" length="2"/>
+        <field name="RESERVED_2" length="2"/>
+        <field name="RESERVED_3" length="1"/>
+        <field name="RESERVED_4" length="1"/>
+        <field name="SOFTWARE_VERSION_NUMBER" length="10"/>
+    </tre>
+
+    <tre name="CSEPHA" minlength="257" maxlength="36005" location="des">
+        <field name="EPHEM_FLAG" length="12"/>
+        <field name="DT_EPHEM" length="5"/>
+        <field name="DATE_EPHEM" length="8"/>
+        <field name="T0_EPHEM" length="13"/>
+        <field name="NUM_EPHEM" length="3"/>
+        <loop counter="NUM_EPHEM" md_prefix="EPHEM_%03d_" name="EPHEM">
+            <field name="X" longname="EPHEM_X" length="12"/>
+            <field name="Y" longname="EPHEM_Y" length="12"/>
+            <field name="Z" longname="EPHEM_Z" length="12"/>
+        </loop>
+    </tre>
+
+    <tre name="CSCRNA" length="109" location="image">
+        <field name="PREDICT_CORNERS" length="1"/>
+        <field name="ULCNR_LAT" length="9"/>
+        <field name="ULCNR_LONG" length="10"/>
+        <field name="ULCNR_HT" length="8"/>
+        <field name="URCNR_LAT" length="9"/>
+        <field name="URCNR_LONG" length="10"/>
+        <field name="URCNR_HT" length="8"/>
+        <field name="LRCNR_LAT" length="9"/>
+        <field name="LRCNR_LONG" length="10"/>
+        <field name="LRCNR_HT" length="8"/>
+        <field name="LLCNR_LAT" length="9"/>
+        <field name="LLCNR_LONG" length="10"/>
+        <field name="LLCNR_HT" length="8"/>
+    </tre>
+
+    <tre name="CSEXRA" md_prefix="NITF_CSEXRA_" length="132" location="image">
+        <field name="SENSOR" length="6"/>
+        <field name="TIME_FIRST_LINE_IMAGE" length="12"/>
+        <field name="TIME_IMAGE_DURATION" length="12"/>
+        <field name="MAX_GSD" length="5"/>
+        <field name="ALONG_SCAN_GSD" length="5"/>
+        <field name="CROSS_SCAN_GSD" length="5"/>
+        <field name="GEO_MEAN_GSD" length="5"/>
+        <field name="A_S_VERT_GSD" length="5"/>
+        <field name="C_S_VERT_GSD" length="5"/>
+        <field name="GEO_MEAN_VERT_GSD" length="5"/>
+        <field name="GSD_BETA_ANGLE" length="5"/>
+        <field name="DYNAMIC_RANGE" length="5"/>
+        <field name="NUM_LINES" length="7"/>
+        <field name="NUM_SAMPLES" length="5"/>
+        <field name="ANGLE_TO_NORTH" length="7"/>
+        <field name="OBLIQUITY_ANGLE" length="6"/>
+        <field name="AZ_OF_OBLIQUITY" length="7"/>
+        <field name="GRD_COVER" length="1"/>
+        <field name="SNOW_DEPTH_CAT" length="1"/>
+        <field name="SUN_AZIMUTH" length="7"/>
+        <field name="SUN_ELEVATION" length="7"/>
+        <field name="PREDICTED_NIIRS" length="3"/>
+        <field name="CIRCL_ERR" length="3"/>
+        <field name="LINEAR_ERR" length="3"/>
+    </tre>
+
+    <tre name="CSPROA" length="120" location="image">
+        <field length="12"/>
+        <field length="12"/>
+        <field length="12"/>
+        <field length="12"/>
+        <field length="12"/>
+        <field length="12"/>
+        <field length="12"/>
+        <field length="12"/>
+        <field length="12"/>
+        <field name="BWC" length="12"/>
+    </tre>
+
+    <tre name="CSSFAA" minlength="107" maxlength="425" location="image">
+        <field name="NUM_BANDS" length="1"/>
+        <loop counter="NUM_BANDS" md_prefix="BAND_%d_" name="BAND">
+            <field name="BAND_TYPE" length="1"/>
+            <field name="BAND_ID" length="6"/>
+            <field name="FOC_LENGTH" length="11"/>
+            <field name="NUM_DAP" length="8"/>
+            <field name="NUM_FIR" length="8"/>
+            <field name="DELTA" length="7"/>
+            <field name="OPPOFF_X" length="7"/>
+            <field name="OPPOFF_Y" length="7"/>
+            <field name="OPPOFF_Z" length="7"/>
+            <field name="START_X" length="11"/>
+            <field name="START_Y" length="11"/>
+            <field name="FINISH_X" length="11"/>
+            <field name="FINISH_Y" length="11"/>
+        </loop>
+    </tre>
+
+    <tre name="GEOLOB" length="48" location="image">
+        <field name="ARV" length="9" type="real"/>
+        <field name="BRV" length="9" type="real"/>
+        <field name="LSO" length="15" type="real"/>
+        <field name="PSO" length="15" type="real"/>
+    </tre>
+
+    <tre name="GEOPSB" length="443" location="file">
+        <field name="TYP" length="3" type="string"/>
+        <field name="UNI" length="3" type="string"/>
+        <field name="DAG" length="80" type="string"/>
+        <field name="DCD" length="4" type="string"/>
+        <field name="ELL" length="80" type="string"/>
+        <field name="ELC" length="3" type="string"/>
+        <field name="DVR" length="80" type="string"/>
+        <field name="VDCDVR" length="4" type="string"/>
+        <field name="SDA" length="80" type="string"/>
+        <field name="VDCSDA" length="4" type="string"/>
+        <field name="ZOR" length="15" type="integer" minval="0"/>
+        <field name="GRD" length="3" type="string"/>
+        <field name="GRN" length="80" type="string"/>
+        <field name="ZNA" length="4" type="integer" minval="0"/>
+    </tre>
+
+    <tre name="HISTOA" minlength="115" maxlength="83512" location="image">
+        <field name="SYSTYPE" length="20"/>
+        <field name="PC" length="12"/>
+        <field name="PE" length="4"/>
+        <field name="REMAP_FLAG" length="1"/>
+        <field name="LUTID" length="2"/>
+        <field name="NEVENTS" length="2"/>
+        <loop counter="NEVENTS" md_prefix="EVENT_%02d_" name="EVENT">
+            <field name="PDATE" length="14"/>
+            <field name="PSITE" length="10"/>
+            <field name="PAS" length="10"/>
+            <field name="NIPCOM" length="1"/>
+            <loop counter="NIPCOM" md_prefix="IPCOM_%d" name="IPCOM">
+                <field name="" longname="IPCOM" length="80"/>
+            </loop>
+            <field name="IBPP" length="2"/>
+            <field name="IPVTYPE" length="3"/>
+            <field name="INBWC" length="10"/>
+            <field name="DISP_FLAG" length="1"/>
+            <field name="ROT_FLAG" length="1"/>
+            <if cond="ROT_FLAG=1">
+                <field name="ROT_ANGLE" length="8"/>
+            </if>
+            <field name="PROJ_FLAG" length="1"/>
+            <field name="ASYM_FLAG" length="1"/>
+            <if cond="ASYM_FLAG=1">
+                <field name="ZOOMROW" length="7"/>
+                <field name="ZOOMCOL" length="7"/>
+            </if>
+            <field name="SHARP_FLAG" length="1"/>
+            <if cond="SHARP_FLAG=1">
+                <field name="SHARPFAM" length="2"/>
+                <field name="SHARPMEM" length="2"/>
+            </if>
+            <field name="MAG_FLAG" length="1"/>
+            <if cond="MAG_FLAG=1">
+                <field name="MAG_LEVEL" length="7"/>
+            </if>
+            <field name="DRA_FLAG" length="1"/>
+            <if cond="DRA_FLAG=1">
+                <field name="DRA_MULT" length="7"/>
+                <field name="DRA_SUB" length="5"/>
+            </if>
+            <field name="TTC_FLAG" length="1"/>
+            <if cond="TTC_FLAG=1">
+                <field name="TTCFAM" length="2"/>
+                <field name="TTCMEM" length="2"/>
+            </if>
+            <field name="DEVLUT_FLAG" length="1"/>
+            <field name="OBPP" length="2"/>
+            <field name="OPVTYPE" length="3"/>
+            <field name="OUTBWC" length="10"/>
+        </loop>
+    </tre>
+
+    <tre name="ICHIPB" length="224" location="image">
+        <field name="XFRM_FLAG" length="2" type="integer"/>
+        <field name="SCALE_FACTOR" length="10" type="real"/>
+        <field name="ANAMRPH_CORR" length="2" type="integer"/>
+        <field name="SCANBLK_NUM" length="2" type="integer"/>
+        <field name="OP_ROW_11" length="12" type="real"/>
+        <field name="OP_COL_11" length="12" type="real"/>
+        <field name="OP_ROW_12" length="12" type="real"/>
+        <field name="OP_COL_12" length="12" type="real"/>
+        <field name="OP_ROW_21" length="12" type="real"/>
+        <field name="OP_COL_21" length="12" type="real"/>
+        <field name="OP_ROW_22" length="12" type="real"/>
+        <field name="OP_COL_22" length="12" type="real"/>
+        <field name="FI_ROW_11" length="12" type="real"/>
+        <field name="FI_COL_11" length="12" type="real"/>
+        <field name="FI_ROW_12" length="12" type="real"/>
+        <field name="FI_COL_12" length="12" type="real"/>
+        <field name="FI_ROW_21" length="12" type="real"/>
+        <field name="FI_COL_21" length="12" type="real"/>
+        <field name="FI_ROW_22" length="12" type="real"/>
+        <field name="FI_COL_22" length="12" type="real"/>
+        <field name="FI_ROW" length="8" type="integer"/>
+        <field name="FI_COL" length="8" type="integer"/>
+    </tre>
+
+    <tre name="J2KLRA" location="image">
+        <field name="ORIG" length="1"/>
+        <field name="NLEVELS_O" length="2"/>
+        <field name="NBANDS_O" length="5"/>
+        <field name="NLAYERS_O" length="3"/>
+        <loop counter="NLAYERS_O" md_prefix="LAYER_%03d_" name="LAYER">
+            <field name="LAYER_ID" length="3"/>
+            <field name="BITRATE" length="9"/>
+        </loop>
+        <if_remaining_bytes>
+            <field name="NLEVELS_I" length="2"/>
+            <field name="NBANDS_I" length="5"/>
+            <field name="NLAYERS_I" length="3"/>
+        </if_remaining_bytes>
+    </tre>
+
+    <tre name="MAPLOB" length="43" location="image">
+        <field name="UNILOA" length="3" type="string"/>
+        <field name="LOD" length="5" type="integer" minval="1" maxval="99999"/>
+        <field name="LAD" length="5" type="integer" minval="1" maxval="99999"/>
+        <field name="LSO" length="15" type="real"/>
+        <field name="PSO" length="15" type="real"/>
+    </tre>
+
+    <tre name="PIAIMB" md_prefix="NITF_PIAIMB_" length="337" location="image">
+        <field name="CLOUDCVR" length="3"/>
+        <field name="SRP" length="1"/>
+        <field name="SENSMODE" length="12"/>
+        <field name="SENSNAME" length="18"/>
+        <field name="SOURCE" length="255"/>
+        <field name="COMGEN" length="2"/>
+        <field name="SUBQUAL" length="1"/>
+        <field name="PIAMSNNUM" length="7"/>
+        <field name="CAMSPECS" length="32"/>
+        <field name="PROJID" length="2"/>
+        <field name="GENERATION" length="1"/>
+        <field name="ESD" length="1"/>
+        <field name="OTHERCOND" length="2"/>
+    </tre>
+
+    <tre name="PIAIMC" md_prefix="NITF_PIAIMC_" length="362" location="image">
+        <field name="CLOUDCVR" length="3"/>
+        <field name="SRP" length="1"/>
+        <field name="SENSMODE" length="12"/>
+        <field name="SENSNAME" length="18"/>
+        <field name="SOURCE" length="255"/>
+        <field name="COMGEN" length="2"/>
+        <field name="SUBQUAL" length="1"/>
+        <field name="PIAMSNNUM" length="7"/>
+        <field name="CAMSPECS" length="32"/>
+        <field name="PROJID" length="2"/>
+        <field name="GENERATION" length="1"/>
+        <field name="ESD" length="1"/>
+        <field name="OTHERCOND" length="2"/>
+        <field name="MEANGSD" length="7"/>
+        <field name="IDATUM" length="3"/>
+        <field name="IELLIP" length="3"/>
+        <field name="PREPROC" length="2"/>
+        <field name="IPROJ" length="2"/>
+        <field name="SATTRACK" length="8"/>
+    </tre>
+
+    <tre name="PIAPEA" length="92" location="image">
+        <field name="LASTNME" length="28" type="string"/>
+        <field name="FIRSTNME" length="28" type="string"/>
+        <field name="MIDNME" length="28" type="string"/>
+        <field name="DOB" length="6" type="string"/>
+        <field name="ASSOCTRY" length="2" type="string"/>
+    </tre>
+
+    <tre name="PIAPRC" minlength="201" maxlength="63759" location="file"> <!-- same as PIAPRD apparently ? -->
+        <field name="ACCESSID" length="64" type="string"/>
+        <field name="FMCONTROL" length="32" type="string"/>
+        <field name="SUBDET" length="1" type="string"/>
+        <field name="PRODCODE" length="2" type="string"/>
+        <field name="PRODUCERSE" length="6" type="string"/>
+        <field name="PRODIDNO" length="20" type="string"/>
+        <field name="PRODSNME" length="10" type="string"/>
+        <field name="PRODUCERCD" length="2" type="string"/>
+        <field name="PRODCRTIME" length="14" type="string"/>
+        <field name="MAPID" length="40" type="string"/>
+        <field name="SECTITLEREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="SECTITLEREP" md_prefix="SECTITLE_%02d_" name="SECTITLE">
+            <field name="SECTITLE" length="40" type="string"/>
+            <field name="PPNUM" length="5" type="string"/>
+            <field name="TPP" length="3" type="integer" minval="1" maxval="999"/>
+        </loop>
+        <field name="REQORGREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="REQORGREP" md_prefix="REQORG_%02d" name="REQORG">
+            <field name="" longname="REQORG" length="64" type="string"/>
+        </loop>
+        <field name="KEYWORDREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="KEYWORDREP" md_prefix="KEYWORD_%02d" name="KEYWORD">
+            <field name="" longname="KEYWORD" length="255" type="string"/>
+        </loop>
+        <field name="ASSRPTREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="ASSRPTREP" md_prefix="ASSRPT_%02d" name="ASSRPT">
+            <field name="" longname="ASSRPT" length="20" type="string"/>
+        </loop>
+        <field name="ATEXTREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="ATEXTREP" md_prefix="ATEXT_%02d" name="ATEXT">
+            <field name="" longname="ATEXT" length="255" type="string"/>
+        </loop>
+    </tre>
+
+    <tre name="PIAPRD" minlength="201" maxlength="63759" location="image">
+        <field name="ACCESSID" length="64" type="string"/>
+        <field name="FMCONTROL" length="32" type="string"/>
+        <field name="SUBDET" length="1" type="string"/>
+        <field name="PRODCODE" length="2" type="string"/>
+        <field name="PRODUCERSE" length="6" type="string"/>
+        <field name="PRODIDNO" length="20" type="string"/>
+        <field name="PRODSNME" length="10" type="string"/>
+        <field name="PRODUCERCD" length="2" type="string"/>
+        <field name="PRODCRTIME" length="14" type="string"/>
+        <field name="MAPID" length="40" type="string"/>
+        <field name="SECTITLEREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="SECTITLEREP" md_prefix="SECTITLE_%02d_" name="SECTITLE">
+            <field name="SECTITLE" length="40" type="string"/>
+            <field name="PPNUM" length="5" type="string"/>
+            <field name="TPP" length="3" type="integer" minval="1" maxval="999"/>
+        </loop>
+        <field name="REQORGREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="REQORGREP" md_prefix="REQORG_%02d" name="REQORG">
+            <field name="" longname="REQORG" length="64" type="string"/>
+        </loop>
+        <field name="KEYWORDREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="KEYWORDREP" md_prefix="KEYWORD_%02d" name="KEYWORD">
+            <field name="" longname="KEYWORD" length="255" type="string"/>
+        </loop>
+        <field name="ASSRPTREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="ASSRPTREP" md_prefix="ASSRPT_%02d" name="ASSRPT">
+            <field name="" longname="ASSRPT" length="20" type="string"/>
+        </loop>
+        <field name="ATEXTREP" length="2" type="integer" minval="0" maxval="99"/>
+        <loop counter="ATEXTREP" md_prefix="ATEXT_%02d" name="ATEXT">
+            <field name="" longname="ATEXT" length="255" type="string"/>
+        </loop>
+    </tre>
+
+    <tre name="PRJPSB" minlength="113" maxlength="248" location="file">
+        <field name="PRN" length="80" type="string"/>
+        <field name="PCO" length="2" type="string"/>
+        <field name="NUM_PRJ" length="1" type="integer" minval="0" maxval="9"/>
+        <loop counter="NUM_PRJ" md_prefix="PRJ%d" name="PRJ">
+            <field name="" longname="PRJ" length="15" type="string"/>
+        </loop>
+        <field name="XOR" length="15" type="integer" minval="0"/>
+        <field name="YOR" length="15" type="integer" minval="0"/>
+    </tre>
+
+    <!-- RPC00A and RPC00B differ by the order of coefficients. See NITFReadRPC00B() -->
+    <tre name="RPC00A" length="1041" location="image">
+        <field name="SUCCESS" length="1" type="string" fixed_value="1"/>
+        <field name="ERR_BIAS" length="7" unit="meters" type="real" minval="0000.00" maxval="9999.99"/>
+        <field name="ERR_RAND" length="7" unit="meters" type="real" minval="0000.00" maxval="9999.99"/>
+        <field name="LINE_OFF" length="6" unit="pixels" type="integer"/>
+        <field name="SAMP_OFF" length="5" unit="pixels" type="integer"/>
+        <field name="LAT_OFF" length="8" unit="degrees" type="real" minval="-90.0" maxval="90.0"/>
+        <field name="LONG_OFF" length="9" unit="degrees" type="real" minval="-180.0" maxval="180.0"/>
+        <field name="HEIGHT_OFF" length="5" unit="meters" type="integer" minval="-9999" maxval="9999"/>
+        <field name="LINE_SCALE" length="6" unit="pixels" type="integer" minval="1" maxval="999999"/>
+        <field name="SAMP_SCALE" length="5" unit="pixels" type="integer" minval="1" maxval="99999"/>
+        <field name="LAT_SCALE" length="8" unit="degrees" type="real" minval="-90.0" maxval="90.0"/>
+        <field name="LONG_SCALE" length="9" unit="degrees" type="real" minval="-180.0" maxval="180.0"/>
+        <field name="HEIGHT_SCALE" length="5" unit="meters" type="integer" minval="-9999" maxval="9999"/>
+        <loop iterations="20" md_prefix="LINE_NUM_COEFF_%02d" name="LINE_NUM_COEFF">
+            <field name="" longname="LINE_NUM_COEFF" length="12" type="real"/>
+        </loop>
+        <loop iterations="20" md_prefix="LINE_DEN_COEFF_%02d" name="LINE_DEN_COEFF">
+            <field name="" longname="LINE_DEN_COEFF" length="12" type="real"/>
+        </loop>
+        <loop iterations="20" md_prefix="SAMP_NUM_COEFF_%02d" name="SAMP_NUM_COEFF">
+            <field name="" longname="SAMP_NUM_COEFF" length="12" type="real"/>
+        </loop>
+        <loop iterations="20" md_prefix="SAMP_DEN_COEFF_%02d" name="SAMP_DEN_COEFF">
+            <field name="" longname="SAMP_DEN_COEFF" length="12" type="real"/>
+        </loop>
+    </tre>
+
+    <tre name="RPC00B" length="1041" location="image">
+        <field name="SUCCESS" length="1" type="string" fixed_value="1"/>
+        <field name="ERR_BIAS" length="7" unit="meters" type="real" minval="0000.00" maxval="9999.99"/>
+        <field name="ERR_RAND" length="7" unit="meters" type="real" minval="0000.00" maxval="9999.99"/>
+        <field name="LINE_OFF" length="6" unit="pixels" type="integer"/>
+        <field name="SAMP_OFF" length="5" unit="pixels" type="integer"/>
+        <field name="LAT_OFF" length="8" unit="degrees" type="real" minval="-90.0" maxval="90.0"/>
+        <field name="LONG_OFF" length="9" unit="degrees" type="real" minval="-180.0" maxval="180.0"/>
+        <field name="HEIGHT_OFF" length="5" unit="meters" type="integer" minval="-9999" maxval="9999"/>
+        <field name="LINE_SCALE" length="6" unit="pixels" type="integer" minval="1" maxval="999999"/>
+        <field name="SAMP_SCALE" length="5" unit="pixels" type="integer" minval="1" maxval="99999"/>
+        <field name="LAT_SCALE" length="8" unit="degrees" type="real" minval="-90.0" maxval="90.0"/>
+        <field name="LONG_SCALE" length="9" unit="degrees" type="real" minval="-180.0" maxval="180.0"/>
+        <field name="HEIGHT_SCALE" length="5" unit="meters" type="integer" minval="-9999" maxval="9999"/>
+        <loop iterations="20" md_prefix="LINE_NUM_COEFF_%02d" name="LINE_NUM_COEFF">
+            <field name="" longname="LINE_NUM_COEFF" length="12" type="real"/>
+        </loop>
+        <loop iterations="20" md_prefix="LINE_DEN_COEFF_%02d" name="LINE_DEN_COEFF">
+            <field name="" longname="LINE_DEN_COEFF" length="12" type="real"/>
+        </loop>
+        <loop iterations="20" md_prefix="SAMP_NUM_COEFF_%02d" name="SAMP_NUM_COEFF">
+            <field name="" longname="SAMP_NUM_COEFF" length="12" type="real"/>
+        </loop>
+        <loop iterations="20" md_prefix="SAMP_DEN_COEFF_%02d" name="SAMP_DEN_COEFF">
+            <field name="" longname="SAMP_DEN_COEFF" length="12" type="real"/>
+        </loop>
+    </tre>
+
+    <tre name="RSMAPA" minlength="507" maxlength="1243" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="TID" length="40" type="string"/>
+        <field name="NPAR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="XUOL" length="21" type="real" unit="meters"/>
+        <field name="YUOL" length="21" type="real" unit="meters"/>
+        <field name="ZUOL" length="21" type="real" unit="meters"/>
+        <field name="XUXL" length="21" type="real"/>
+        <field name="XUYL" length="21" type="real"/>
+        <field name="XUZL" length="21" type="real"/>
+        <field name="YUXL" length="21" type="real"/>
+        <field name="YUYL" length="21" type="real"/>
+        <field name="YUZL" length="21" type="real"/>
+        <field name="ZUXL" length="21" type="real"/>
+        <field name="ZUYL" length="21" type="real"/>
+        <field name="ZUZL" length="21" type="real"/>
+        <field name="IRO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRXX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRXY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRXZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRYY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRYZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRZZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IC0" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICXX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICXY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICXZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICYY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICYZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICZZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GS" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZZ" length="2" type="integer" minval="1" maxval="36"/>
+        <loop counter="NPAR" md_prefix="PAR_%02d_" name="PAR">
+            <field name="PARVAL" length="21" type="real"/>
+        </loop>
+    </tre>
+
+    <tre name="RSMDCA" minlength="597" maxlength="99988" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="TID" length="40" type="string"/>
+        <field name="NPAR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="NIMGE" length="3" type="integer" minval="1" maxval="999"/>
+        <field name="NPART" length="5" type="integer" minval="1" maxval="99999"/>
+        <loop counter="NIMGE" md_prefix="IMAGEF_%03d_" name="IMAGE">
+            <field name="IID" length="80" type="string"/>
+            <field name="NPARI" length="2" type="integer" minval="1" maxval="36"/>
+        </loop>
+        <field name="XUOL" length="21" type="real" unit="meters"/>
+        <field name="YUOL" length="21" type="real" unit="meters"/>
+        <field name="ZUOL" length="21" type="real" unit="meters"/>
+        <field name="XUXL" length="21" type="real"/>
+        <field name="XUYL" length="21" type="real"/>
+        <field name="XUZL" length="21" type="real"/>
+        <field name="YUXL" length="21" type="real"/>
+        <field name="YUYL" length="21" type="real"/>
+        <field name="YUZL" length="21" type="real"/>
+        <field name="ZUXL" length="21" type="real"/>
+        <field name="ZUYL" length="21" type="real"/>
+        <field name="ZUZL" length="21" type="real"/>
+        <field name="IRO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRXX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRXY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRXZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRYY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRYZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IRZZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="IC0" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICXX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICXY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICXZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICYY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICYZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="ICZZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZO" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZR" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GS" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GXZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GYZ" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZX" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZY" length="2" type="integer" minval="1" maxval="36"/>
+        <field name="GZZ" length="2" type="integer" minval="1" maxval="36"/>
+        <loop formula="(NPART+1)*(NPART)/2" name="DERCOV" md_prefix="DERCOV_%05d"> <!--Warning: this condition is currently hardcoded in the interpreter -->
+            <field name="" longname="DERCOV" length="21" type="real"/>
+        </loop>
+    </tre>
+
+    <tre name="RSMECA" minlength="354" maxlength="42864" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="TID" length="40" type="string"/>
+        <field name="INCLIC" length="1" type="string"/>
+        <field name="INCLUC" length="1" type="string"/>
+        <if cond="INCLIC=Y">
+            <field name="NPAR" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="NPARO" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IGN" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="CVDATE" length="8" type="string"/>
+            <field name="XUOL" length="21" type="real" unit="meters"/>
+            <field name="YUOL" length="21" type="real" unit="meters"/>
+            <field name="ZUOL" length="21" type="real" unit="meters"/>
+            <field name="XUXL" length="21" type="real"/>
+            <field name="XUYL" length="21" type="real"/>
+            <field name="XUZL" length="21" type="real"/>
+            <field name="YUXL" length="21" type="real"/>
+            <field name="YUYL" length="21" type="real"/>
+            <field name="YUZL" length="21" type="real"/>
+            <field name="ZUXL" length="21" type="real"/>
+            <field name="ZUYL" length="21" type="real"/>
+            <field name="ZUZL" length="21" type="real"/>
+            <field name="IRO" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRX" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRXX" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRXY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRXZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRYY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRYZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IRZZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="IC0" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICX" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICXX" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICXY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICXZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICYY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICYZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="ICZZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GXO" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GYO" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GZO" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GXR" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GYR" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GZR" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GS" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GXX" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GXY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GXZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GYX" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GYY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GYZ" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GZX" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GZY" length="2" type="integer" minval="1" maxval="36"/>
+            <field name="GZZ" length="2" type="integer" minval="1" maxval="36"/>
+            <loop counter="IGN" name="IG" md_prefix="IG_%02d_">
+                <field name="NUMOPG" length="2" type="integer" minval="1" maxval="36"/>
+                <loop formula="(NUMOPG+1)*(NUMOPG)/2" name="EG" md_prefix="EG_%02d"> <!--Warning: this condition is currently hardcoded in the interpreter -->
+                    <field name="" longname="ERRCVG" length="21" type="real"/>
+                </loop>
+                <field name="TCDF" length="1" type="integer" minval="0" maxval="2"/>
+                <field name="NCSEG" length="1" type="integer" minval="2" maxval="9"/>
+                <loop counter="NCSEG" name="CORSEG" md_prefix="CORSEG_%d_">
+                    <field name="CORSEG" length="21" type="real"/>
+                    <field name="TAUSEG" length="21" type="real" unit="seconds"/>
+                </loop>
+            </loop>
+            <loop formula="NPAR*NPARO" name="MAP" md_prefix="MAP_%04d"> <!--Warning: this condition is currently hardcoded in the interpreter -->
+                <field name="" longname="MAP" length="21" type="real"/>
+            </loop>
+        </if>
+        <if cond="INCLUC=Y">
+            <field name="URR" length="21" type="real" unit="pixel^2"/>
+            <field name="URC" length="21" type="real" unit="pixel^2"/>
+            <field name="UCC" length="21" type="real" unit="pixel^2"/>
+            <field name="UNCSR" length="1" type="integer" minval="2" maxval="9"/>
+            <loop counter="UNCSR" name="CORSR" md_prefix="CORSR_%d_">
+                <field name="UCORSR" length="21" type="real"/>
+                <field name="UTAUSR" length="21" type="real" unit="pixels"/>
+            </loop>
+            <field name="UNCSC" length="1" type="integer" minval="2" maxval="9"/>
+            <loop counter="UNCSC" name="CORSC" md_prefix="CORSC_%d_">
+                <field name="UCORSC" length="21" type="real"/>
+                <field name="UTAUSC" length="21" type="real" unit="pixels"/>
+            </loop>
+        </if>
+    </tre>
+
+    <tre name="RSMGGA" minlength="390" maxlength="99988" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="GGRSN" length="3" type="integer" minval="1" maxval="256"/>
+        <field name="GGCSN" length="3" type="integer" minval="1" maxval="256"/>
+        <field name="GGRFEP" length="21" type="real"/>
+        <field name="GGCFEP" length="21" type="real"/>
+        <field name="INTORD" length="1" type="integer" minval="0" maxval="3"/>
+        <field name="NPLN" length="3" type="integer" minval="2" maxval="999"/>
+        <field name="DELTAZ" length="21" type="real"/>
+        <field name="DELTAX" length="21" type="real"/>
+        <field name="DELTAY" length="21" type="real"/>
+        <field name="ZPLN1" length="21" type="real"/>
+        <field name="XIPLN1" length="21" type="real"/>
+        <field name="YIPLN1" length="21" type="real"/>
+        <field name="REFROW" length="9" type="integer"/>
+        <field name="REFCOL" length="9" type="integer"/>
+        <field name="TNUMRD" length="2" type="integer" minval="3" maxval="31"/>
+        <field name="TNUMCD" length="2" type="integer" minval="3" maxval="31"/>
+        <field name="FNUMRD" length="1" type="integer" minval="1" maxval="3"/>
+        <field name="FNUMCD" length="1" type="integer" minval="1" maxval="3"/>
+        <loop formula="NPLN-1" name="IG" md_prefix="IG_%03d_"> <!--Warning: this condition is currently hardcoded in the interpreter -->
+            <field name="IXO" length="4" type="integer"/>
+            <field name="IYO" length="4" type="integer"/>
+        </loop>
+        <loop counter="NPLN" name="GP" md_prefix="GP_%03d_">
+            <field name="NXPTS" length="3" type="integer" minval="2"/>
+            <field name="NYPTS" length="3" type="integer" minval="2"/>
+            <loop formula="NXPTS*NYPTS" name="GPCOORD" md_prefix="GPCOORD_%06d_"> <!--Warning: this condition is currently hardcoded in the interpreter -->
+                <field name="RCOORD" length_var="TNUMRD" type="integer"/>
+                <field name="CCOORD" length_var="TNUMCD" type="integer"/>
+            </loop>
+        </loop>
+    </tre>
+
+    <tre name="RSMGIA" length="591" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="GR0" length="21" type="real"/>
+        <field name="GRX" length="21" type="real"/>
+        <field name="GRY" length="21" type="real"/>
+        <field name="GRZ" length="21" type="real"/>
+        <field name="GRXX" length="21" type="real"/>
+        <field name="GRXY" length="21" type="real"/>
+        <field name="GRXZ" length="21" type="real"/>
+        <field name="GRYY" length="21" type="real"/>
+        <field name="GRYZ" length="21" type="real"/>
+        <field name="GRZZ" length="21" type="real"/>
+        <field name="GC0" length="21" type="real"/>
+        <field name="GCX" length="21" type="real"/>
+        <field name="GCY" length="21" type="real"/>
+        <field name="GCZ" length="21" type="real"/>
+        <field name="GCXX" length="21" type="real"/>
+        <field name="GCXY" length="21" type="real"/>
+        <field name="GCXZ" length="21" type="real"/>
+        <field name="GCYY" length="21" type="real"/>
+        <field name="GCYZ" length="21" type="real"/>
+        <field name="GCZZ" length="21" type="real"/>
+        <field name="GRNIS" length="3" type="integer"/>
+        <field name="GCNIS" length="3" type="integer"/>
+        <field name="GTNIS" length="3" type="integer"/>
+        <field name="GRSSIZ" length="21" type="real"/>
+        <field name="GCSSIZ" length="21" type="real"/>
+    </tre>
+
+    <tre name="RSMIDA" length="1628" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="ISID" length="40" type="string"/>
+        <field name="SID" length="40" type="string"/>
+        <field name="STID" length="40" type="string"/>
+        <field name="YEAR" length="4" type="integer"/>
+        <field name="MONTH" length="2" type="integer"/>
+        <field name="DAY" length="2" type="integer"/>
+        <field name="HOUR" length="2" type="integer"/>
+        <field name="MINUTE" length="2" type="integer"/>
+        <field name="SECOND" length="9" type="real"/>
+        <field name="NRG" length="8" type="integer" unit="pixels" minval="1" maxval="99999999"/>
+        <field name="NCG" length="8" type="integer" unit="pixels" minval="1" maxval="99999999"/>
+        <field name="TRG" length="21" type="real" unit="seconds"/>
+        <field name="TCG" length="21" type="real" unit="seconds"/>
+        <field name="GRNDD" length="1" type="string"/>
+        <field name="XUOR" length="21" type="real" unit="meters"/>
+        <field name="YUOR" length="21" type="real" unit="meters"/>
+        <field name="ZUOR" length="21" type="real" unit="meters"/>
+        <field name="XUXR" length="21" type="real"/>
+        <field name="XUYR" length="21" type="real"/>
+        <field name="XUZR" length="21" type="real"/>
+        <field name="YUXR" length="21" type="real"/>
+        <field name="YUYR" length="21" type="real"/>
+        <field name="YUZR" length="21" type="real"/>
+        <field name="ZUXR" length="21" type="real"/>
+        <field name="ZUYR" length="21" type="real"/>
+        <field name="ZUZR" length="21" type="real"/>
+        <field name="V1X" length="21" type="real"/>
+        <field name="V1Y" length="21" type="real"/>
+        <field name="V1Z" length="21" type="real"/>
+        <field name="V2X" length="21" type="real"/>
+        <field name="V2Y" length="21" type="real"/>
+        <field name="V2Z" length="21" type="real"/>
+        <field name="V3X" length="21" type="real"/>
+        <field name="V3Y" length="21" type="real"/>
+        <field name="V3Z" length="21" type="real"/>
+        <field name="V4X" length="21" type="real"/>
+        <field name="V4Y" length="21" type="real"/>
+        <field name="V4Z" length="21" type="real"/>
+        <field name="V5X" length="21" type="real"/>
+        <field name="V5Y" length="21" type="real"/>
+        <field name="V5Z" length="21" type="real"/>
+        <field name="V6X" length="21" type="real"/>
+        <field name="V6Y" length="21" type="real"/>
+        <field name="V6Z" length="21" type="real"/>
+        <field name="V7X" length="21" type="real"/>
+        <field name="V7Y" length="21" type="real"/>
+        <field name="V7Z" length="21" type="real"/>
+        <field name="V8X" length="21" type="real"/>
+        <field name="V8Y" length="21" type="real"/>
+        <field name="V8Z" length="21" type="real"/>
+        <field name="GRPX" length="21" type="real"/>
+        <field name="GRPY" length="21" type="real"/>
+        <field name="GRPZ" length="21" type="real"/>
+        <field name="FULLR" length="8" type="integer" unit="pixels" minval="1" maxval="99999999"/>
+        <field name="FULLC" length="8" type="integer" unit="pixels" minval="1" maxval="99999999"/>
+        <field name="MINR" length="8" type="integer" unit="pixels" minval="0" maxval="99999999"/>
+        <field name="MAXR" length="8" type="integer" unit="pixels" minval="0" maxval="99999999"/>
+        <field name="MINC" length="8" type="integer" unit="pixels" minval="0" maxval="99999999"/>
+        <field name="MAXC" length="8" type="integer" unit="pixels" minval="0" maxval="99999999"/>
+        <field name="IE0" length="21" type="real" unit="radians"/>
+        <field name="IER" length="21" type="real"/>
+        <field name="IEC" length="21" type="real"/>
+        <field name="IERR" length="21" type="real"/>
+        <field name="IERC" length="21" type="real"/>
+        <field name="IECC" length="21" type="real"/>
+        <field name="IA0" length="21" type="real" unit="radians"/>
+        <field name="IAR" length="21" type="real"/>
+        <field name="IAC" length="21" type="real"/>
+        <field name="IARR" length="21" type="real"/>
+        <field name="IARC" length="21" type="real"/>
+        <field name="IACC" length="21" type="real"/>
+        <field name="SPX" length="21" type="real"/>
+        <field name="SVX" length="21" type="real"/>
+        <field name="SAX" length="21" type="real"/>
+        <field name="SPY" length="21" type="real"/>
+        <field name="SVY" length="21" type="real"/>
+        <field name="SAY" length="21" type="real"/>
+        <field name="SPZ" length="21" type="real"/>
+        <field name="SVZ" length="21" type="real"/>
+        <field name="SAZ" length="21" type="real"/>
+    </tre>
+
+    <tre name="RSMPCA" minlength="486" maxlength="18546" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="RSN" length="3" type="integer" minval="1" maxval="256"/>
+        <field name="CSN" length="3" type="integer" minval="1" maxval="256"/>
+        <field name="RFEP" length="21" type="real"/>
+        <field name="CFEP" length="21" type="real"/>
+        <field name="RNRMO" length="21" type="real"/>
+        <field name="CNRMO" length="21" type="real"/>
+        <field name="XNRMO" length="21" type="real"/>
+        <field name="YNRMO" length="21" type="real"/>
+        <field name="ZNRMO" length="21" type="real"/>
+        <field name="RNRMSF" length="21" type="real"/>
+        <field name="CNRMSF" length="21" type="real"/>
+        <field name="XNRMSF" length="21" type="real"/>
+        <field name="YNRMSF" length="21" type="real"/>
+        <field name="ZNRMSF" length="21" type="real"/>
+        <field name="RNPWRX" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="RNPWRY" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="RNPWRZ" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="RNTRMS" length="3" type="integer" minval="1" maxval="216"/>
+        <loop counter="RNTRMS" name="RNPCF" md_prefix="RNPCF_%03d">
+            <field name="" longname="RNPCF" length="21" type="real"/>
+        </loop>
+        <field name="RDPWRX" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="RDPWRY" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="RDPWRZ" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="RDTRMS" length="3" type="integer" minval="1" maxval="216"/>
+        <loop counter="RDTRMS" name="RDPCF" md_prefix="RDPCF_%03d">
+            <field name="" longname="RDPCF" length="21" type="real"/>
+        </loop>
+        <field name="CNPWRX" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="CNPWRY" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="CNPWRZ" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="CNTRMS" length="3" type="integer" minval="1" maxval="216"/>
+        <loop counter="CNTRMS" name="CNPCF" md_prefix="CNPCF_%03d">
+            <field name="" longname="CNPCF" length="21" type="real"/>
+        </loop>
+        <field name="CDPWRX" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="CDPWRY" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="CDPWRZ" length="1" type="integer" minval="0" maxval="5"/>
+        <field name="CDTRMS" length="3" type="integer" minval="1" maxval="216"/>
+        <loop counter="CDTRMS" name="CDPCF" md_prefix="CDPCF_%03d">
+            <field name="" longname="CDPCF" length="21" type="real"/>
+        </loop>
+    </tre>
+
+    <tre name="RSMPIA" length="591" location="image">
+        <field name="IID" length="80" type="string"/>
+        <field name="EDITION" length="40" type="string"/>
+        <field name="R0" length="21" type="real"/>
+        <field name="RX" length="21" type="real"/>
+        <field name="RY" length="21" type="real"/>
+        <field name="RZ" length="21" type="real"/>
+        <field name="RXX" length="21" type="real"/>
+        <field name="RXY" length="21" type="real"/>
+        <field name="RXZ" length="21" type="real"/>
+        <field name="RYY" length="21" type="real"/>
+        <field name="RYZ" length="21" type="real"/>
+        <field name="RZZ" length="21" type="real"/>
+        <field name="C0" length="21" type="real"/>
+        <field name="CX" length="21" type="real"/>
+        <field name="CY" length="21" type="real"/>
+        <field name="CZ" length="21" type="real"/>
+        <field name="CXX" length="21" type="real"/>
+        <field name="CXY" length="21" type="real"/>
+        <field name="CXZ" length="21" type="real"/>
+        <field name="CYY" length="21" type="real"/>
+        <field name="CYZ" length="21" type="real"/>
+        <field name="CZZ" length="21" type="real"/>
+        <field name="RNIS" length="3" type="integer"/>
+        <field name="CNIS" length="3" type="integer"/>
+        <field name="TNIS" length="3" type="integer"/>
+        <field name="RSSIZ" length="21" type="real"/>
+        <field name="CSSIZ" length="21" type="real"/>
+    </tre>
+
+    <tre name="SOURCB" minlength="906" maxlength="99985" location="image">
+        <field name="IS_SCA" length="9" type="integer"/>
+        <field name="CPATCH" length="10" type="string"/>
+        <field name="NUM_SOUR" length="2" type="integer" minval="1"/>
+        <loop counter="NUM_SOUR" name="SOURCE" md_prefix="SOURCE_%02d_">
+            <field name="NUM_BP" length="2" type="integer"/>
+            <loop counter="NUM_BP" name="BP" md_prefix="BP_%02d_">
+                <field name="NUM_PTS" length="3" type="integer"/>
+                <loop counter="NUM_PTS" md_prefix="POINT_%03d_" name="POINT">
+                    <field name="LON" length="15" type="real"/>
+                    <field name="LAT" length="15" type="real"/>
+                </loop>
+            </loop>
+            <field name="PRT" length="10" type="string"/>
+            <field name="URF" length="20" type="string"/>
+            <field name="EDN" length="7" type="string"/>
+            <field name="NAM" length="20" type="string"/>
+            <field name="CDP" length="3" type="integer"/>
+            <field name="CDV" length="8" type="string"/>
+            <field name="CDV27" length="8" type="string"/>
+            <field name="SRN" length="80" type="string"/>
+            <field name="SCA" length="9" type="integer"/>
+            <field name="UNISQU" length="3" type="string"/>
+            <if cond="UNISQU!=">
+                <field name="SQU" length="10" type="integer"/>
+            </if>
+            <field name="UNIPCI" length="3" type="string"/>
+            <if cond="UNIPCI!=">
+                <field name="PCI" length="4" type="integer"/>
+            </if>
+            <field name="WPC" length="3" type="integer"/>
+            <field name="NST" length="3" type="integer"/>
+            <field name="UNIHKE" length="3" type="string"/>
+            <if cond="UNIHKE!=">
+                <field name="HKE" length="6" type="integer"/>
+                <field name="LONHKE" length="15" type="real"/>
+                <field name="LATHKE" length="15" type="real"/>
+            </if>
+            <field name="QSS" length="1" type="string"/>
+            <field name="QOD" length="1" type="string"/>
+            <if cond="QSS!=U AND QOD!=Y">                           <!--Warning: this condition is currently hardcoded in the interpreter -->
+                <field name="CDV10" length="8" type="string"/>
+            </if>
+            <field name="QLE" length="80" type="string"/>
+            <field name="CPY" length="80" type="string"/>
+            <field name="NMI" length="2" type="integer"/>
+            <loop counter="NMI" name="MI" md_prefix="MI_%02d_">
+                <field name="CDV30" length="8" type="string"/>
+                <field name="UNIRAT" length="3" type="string"/>
+                <field name="RAT" length="8" type="real"/>
+                <field name="UNIGMA" length="3" type="string"/>
+                <field name="GMA" length="8" type="real"/>
+                <field name="LONGMA" length="15" type="real"/>
+                <field name="LATGMA" length="15" type="real"/>
+                <field name="UNIGCA" length="3" type="string"/>
+                <if cond="UNIGCA!=">
+                    <field name="GCA" length="8" type="real"/>
+                </if>
+            </loop>
+            <field name="NLI" length="2" type="integer"/>
+            <loop counter="NLI" name="LI" md_prefix="LI_%02d_">
+                <field name="BAD" length="10" type="string"/>
+            </loop>
+            <field name="DAG" length="80" type="string"/>
+            <field name="DCD" length="4" type="string"/>
+            <field name="ELL" length="80" type="string"/>
+            <field name="ELC" length="3" type="string"/>
+            <field name="DVR" length="80" type="string"/>
+            <field name="VDCDVR" length="4" type="string"/>
+            <field name="SDA" length="80" type="string"/>
+            <field name="VDCSDA" length="4" type="string"/>
+            <field name="PRN" length="80" type="string"/>
+            <field name="PCO" length="2" type="string"/>
+            <field name="NUM_PRJ" length="1" type="integer"/>
+            <loop counter="NUM_PRJ" name="PRJ" md_prefix="PRJ_%d">
+                <field name="" longname="PRJ" length="15" type="real"/>
+            </loop>
+            <field name="XOR" length="15" type="integer" minval="0"/>
+            <field name="YOR" length="15" type="integer" minval="0"/>
+            <field name="GRD" length="3" type="string"/>
+            <field name="GRN" length="80" type="string"/>
+            <field name="ZNA" length="4" type="integer" minval="0"/>
+            <field name="NIN" length="2" type="integer"/>
+            <loop counter="NIN" name="IN" md_prefix="IN_%02d_">
+                <field name="INT" length="10" type="string"/>
+                <field name="INS_SCA" length="9" type="integer"/>
+                <field name="NTL" length="15" type="real"/>
+                <field name="TTL" length="15" type="real"/>
+                <field name="NVL" length="15" type="real"/>
+                <field name="TVL" length="15" type="real"/>
+                <field name="NTR" length="15" type="real"/>
+                <field name="TTR" length="15" type="real"/>
+                <field name="NVR" length="15" type="real"/>
+                <field name="TVR" length="15" type="real"/>
+                <field name="NRL" length="15" type="real"/>
+                <field name="TRL" length="15" type="real"/>
+                <field name="NSL" length="15" type="real"/>
+                <field name="TSL" length="15" type="real"/>
+                <field name="NRR" length="15" type="real"/>
+                <field name="TRR" length="15" type="real"/>
+                <field name="NSR" length="15" type="real"/>
+                <field name="TSR" length="15" type="real"/>
+            </loop>
+        </loop>
+    </tre>
+
+    <tre name="STDIDC" md_prefix="NITF_STDIDC_" length="89" location="image">
+        <field name="ACQUISITION_DATE" length="14"/>
+        <field name="MISSION" length="14"/>
+        <field name="PASS" length="2"/>
+        <field name="OP_NUM" length="3"/>
+        <field name="START_SEGMENT" length="2"/>
+        <field name="REPRO_NUM" length="2"/>
+        <field name="REPLAY_REGEN" length="3"/>
+        <field length="1"/>
+        <field name="START_COLUMN" length="3"/>
+        <field name="START_ROW" length="5"/>
+        <field name="END_SEGMENT" length="2"/>
+        <field name="END_COLUMN" length="3"/>
+        <field name="END_ROW" length="5"/>
+        <field name="COUNTRY" length="2"/>
+        <field name="WAC" length="4"/>
+        <field name="LOCATION" length="11"/>
+        <field length="5"/>
+        <field length="8"/>
+    </tre>
+
+    <tre name="USE00A" md_prefix="NITF_USE00A_" length="107" location="image">
+        <field name="ANGLE_TO_NORTH" length="3"/>
+        <field name="MEAN_GSD" length="5"/>
+        <field length="1"/>
+        <field name="DYNAMIC_RANGE" length="5"/>
+        <field length="3"/>
+        <field length="1"/>
+        <field length="3"/>
+        <field name="OBL_ANG" length="5"/>
+        <field name="ROLL_ANG" length="6"/>
+        <field length="12"/>
+        <field length="15"/>
+        <field length="4"/>
+        <field length="1"/>
+        <field length="3"/>
+        <field length="1"/>
+        <field length="1"/>
+        <field name="N_REF" length="2"/>
+        <field name="REV_NUM" length="5"/>
+        <field name="N_SEG" length="3"/>
+        <field name="MAX_LP_SEG" length="6"/>
+        <field length="6"/>
+        <field length="6"/>
+        <field name="SUN_EL" length="5"/>
+        <field name="SUN_AZ" length="5"/>
+    </tre>
+</tres>
diff --git a/data/nitf_spec.xsd b/data/nitf_spec.xsd
new file mode 100644
index 0000000..48806e6
--- /dev/null
+++ b/data/nitf_spec.xsd
@@ -0,0 +1,142 @@
+<?xml version="1.0"?>
+<!--
+/******************************************************************************
+ * $Id: nitf_spec.xsd 22867 2011-08-06 13:47:27Z rouault $
+ *
+ * Project:  NITF Library
+ * Purpose:  Schema of description of NITF TREs
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2011, 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">
+    <xs:element name="tres">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="tre" type="treType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:complexType name="treType">
+        <xs:group ref="itemType"/>
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="md_prefix" type="xs:string" use="optional"/>
+        <xs:attribute name="length" type="positiveInteger" use="optional"/>
+        <xs:attribute name="minlength" type="xs:integer" use="optional"/>
+        <xs:attribute name="maxlength" type="xs:integer" use="optional"/>
+        <xs:attribute name="location" type="xs:string" use="optional"/>
+    </xs:complexType>
+
+    <xs:group name="itemType">
+        <xs:sequence>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="field" type="fieldType">
+                    <xs:key name="att1">
+                        <xs:selector xpath="."/>
+                        <xs:field xpath="@length|@length_var"/>
+                    </xs:key>
+                </xs:element>
+                <xs:element name="loop" type="loopType">
+                    <xs:key name="att2">
+                        <xs:selector xpath="."/>
+                        <xs:field xpath="@counter|@iterations|@formula"/>
+                    </xs:key>
+                </xs:element>
+                <xs:element name="if" type="ifType"/>
+            </xs:choice>
+            <xs:element name="if_remaining_bytes" type="if_remaining_bytesType" minOccurs="0" maxOccurs="1"/>
+        </xs:sequence>
+    </xs:group>
+
+    <xs:complexType name="loopType">
+        <xs:group ref="itemType"/>
+        <xs:attribute name="name"/>
+        <!-- xs:choice -->
+            <xs:attribute name="counter" type="xs:string"/>
+            <xs:attribute name="iterations" type="positiveInteger"/>
+            <xs:attribute name="formula">
+                <xs:simpleType>
+                    <xs:restriction base="xs:string">
+                        <xs:enumeration value="(NPART+1)*(NPART)/2"/>
+                        <xs:enumeration value="(NUMOPG+1)*(NUMOPG)/2"/>
+                        <xs:enumeration value="NPAR*NPARO"/>
+                        <xs:enumeration value="NPLN-1"/>
+                        <xs:enumeration value="NXPTS*NYPTS"/>
+                    </xs:restriction>
+                </xs:simpleType>
+            </xs:attribute>
+        <!-- /xs:choice -->
+        <xs:attribute name="md_prefix" use="optional">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:pattern value="([a-z]|[A-Z]|[0-9]|_)*(%[0-9]*d)?([a-z]|[A-Z]|[0-9]|_)*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:simpleType name="positiveInteger">
+        <xs:restriction base="xs:integer">
+            <xs:minInclusive value="1"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="ifType">
+        <xs:group ref="itemType"/>
+        <xs:attribute name="cond">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:pattern value=".+[!]?=.*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="if_remaining_bytesType">
+        <xs:group ref="itemType"/>
+    </xs:complexType>
+
+    <xs:complexType name="fieldType">
+        <!-- xs:choice -->
+            <xs:attribute name="length" type="positiveInteger"/>
+            <xs:attribute name="length_var" type="xs:string"/>
+        <!-- /xs:choice -->
+        <xs:attribute name="name" type="xs:string" use="optional"/>
+        <xs:attribute name="longname" type="xs:string" use="optional"/>
+        <xs:attribute name="type" use="optional">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="string"/>
+                    <xs:enumeration value="integer"/>
+                    <xs:enumeration value="real"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="unit" type="xs:string" use="optional"/>
+        <xs:attribute name="minval" use="optional"/>
+        <xs:attribute name="maxval" use="optional"/>
+        <xs:attribute name="fixed_value" use="optional"/>
+        <!--<xs:anyAttribute/>-->
+    </xs:complexType>
+</xs:schema>
diff --git a/data/pcs.csv b/data/pcs.csv
index a131c6b..e0e5eea 100644
--- a/data/pcs.csv
+++ b/data/pcs.csv
@@ -7,7 +7,7 @@
 2005,"St. Kitts 1955 / British West Indies Grid",9001,4605,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
 2006,"St. Lucia 1955 / British West Indies Grid",9001,4606,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
 2007,"St. Vincent 45 / British West Indies Grid",9001,4607,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2008,"NAD27(CGQ77) / SCoPQ zone 2",9001,4609,17700,9807,1,0,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
+2008,"NAD27(CGQ77) / SCoPQ zone 2",9001,4609,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 2009,"NAD27(CGQ77) / SCoPQ zone 3",9001,4609,17703,9807,1,0,4499,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 2010,"NAD27(CGQ77) / SCoPQ zone 4",9001,4609,17704,9807,1,0,4499,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 2011,"NAD27(CGQ77) / SCoPQ zone 5",9001,4609,17705,9807,1,0,4499,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
@@ -64,7 +64,7 @@
 2062,"Madrid 1870 (Madrid) / Spain",9001,4903,19921,9801,1,0,4499,8801,40,9102,8802,0,9102,8805,0.9988085293,9201,8806,600000,9001,8807,600000,9001,,,,,,
 2063,"Dabola 1981 / UTM zone 28N",9001,4315,16028,9807,1,1,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2064,"Dabola 1981 / UTM zone 29N",9001,4315,16029,9807,1,1,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2065,"S-JTSK (Ferro) / Krovak",9001,4818,19952,9819,1,0,6501,8806,0,9001,8807,0,9001,8811,49.3,9110,8813,30.1717303,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
+2065,"S-JTSK (Ferro) / Krovak",9001,4818,19952,9819,1,0,6501,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
 2066,"Mount Dillon / Tobago Grid",9039,4157,19924,9806,1,0,4407,8801,11.1507843,9110,8802,-60.4109632,9110,8806,187500,9039,8807,180000,9039,,,,,,,,,
 2067,"Naparima 1955 / UTM zone 20N",9001,4158,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2068,"ELD79 / Libya zone 5",9001,4159,18240,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
@@ -80,9 +80,9 @@
 2078,"ELD79 / UTM zone 33N",9001,4159,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2079,"ELD79 / UTM zone 34N",9001,4159,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2080,"ELD79 / UTM zone 35N",9001,4159,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2081,"Chos Malal 1914 / Argentina zone 2",9001,4160,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-2082,"Pampa del Castillo / Argentina zone 2",9001,4161,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-2083,"Hito XVIII 1963 / Argentina zone 2",9001,4254,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
+2081,"Chos Malal 1914 / Argentina 2",9001,4160,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
+2082,"Pampa del Castillo / Argentina 2",9001,4161,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
+2083,"Hito XVIII 1963 / Argentina 2",9001,4254,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
 2084,"Hito XVIII 1963 / UTM zone 19S",9001,4254,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 2085,"NAD27 / Cuba Norte",9001,4267,18061,9801,1,1,4532,8801,22.21,9110,8802,-81,9110,8805,0.99993602,9201,8806,500000,9001,8807,280296.016,9001,,,,,,
 2086,"NAD27 / Cuba Sur",9001,4267,18062,9801,1,1,4532,8801,20.43,9110,8802,-76.5,9110,8805,0.99994848,9201,8806,500000,9001,8807,229126.939,9001,,,,,,
@@ -95,11 +95,11 @@
 2093,"Hanoi 1972 / GK 106 NE",9001,4147,16586,9807,1,0,4530,8801,0,9102,8802,106,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
 2094,"WGS 72BE / TM 106 NE",9001,4324,16506,9807,1,0,4400,8801,0,9102,8802,106,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2095,"Bissau / UTM zone 28N",9001,4165,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2096,"Korean 1985 / Korea East Belt",9001,4162,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-2097,"Korean 1985 / Korea Central Belt",9001,4162,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-2098,"Korean 1985 / Korea West Belt",9001,4162,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+2096,"Korean 1985 / East Belt",9001,4162,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+2097,"Korean 1985 / Central Belt",9001,4162,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+2098,"Korean 1985 / West Belt",9001,4162,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
 2099,"Qatar 1948 / Qatar Grid",9001,4286,19953,9806,1,0,4400,8801,25.22565,9110,8802,50.4541,9110,8806,100000,9001,8807,100000,9001,,,,,,,,,
-2100,"GGRS87 / Greek Grid",9001,4121,19930,9807,1,0,4400,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+2100,"GGRS87 / Greek Grid",9001,4121,19930,9807,1,0,4400,8801,0,9102,8802,24,9110,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2101,"Lake / Maracaibo Grid M1",9001,4249,18260,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,0,9001,8807,-52684.972,9001,,,,,,
 2102,"Lake / Maracaibo Grid",9001,4249,18261,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,200000,9001,8807,147315.028,9001,,,,,,
 2103,"Lake / Maracaibo Grid M3",9001,4249,18262,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,500000,9001,8807,447315.028,9001,,,,,,
@@ -935,7 +935,7 @@
 2941,"Pulkovo 1942 / CS63 zone K4",9001,4284,18448,9807,1,0,4530,8801,0.08,9110,8802,56.46,9110,8805,1,9201,8806,4300000,9001,8807,0,9001,,,,,,
 2942,"Porto Santo / UTM zone 28N",9001,4615,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2943,"Selvagem Grande / UTM zone 28N",9001,4616,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2944,"NAD83(CSRS) / SCoPQ zone 2",9001,4617,17700,9807,1,0,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
+2944,"NAD83(CSRS) / SCoPQ zone 2",9001,4617,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 2945,"NAD83(CSRS) / MTM zone 3",9001,4617,17703,9807,1,0,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 2946,"NAD83(CSRS) / MTM zone 4",9001,4617,17704,9807,1,0,4496,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 2947,"NAD83(CSRS) / MTM zone 5",9001,4617,17705,9807,1,0,4496,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
@@ -975,8 +975,8 @@
 2982,"IGN72 Grand Terre / UTM zone 58S",9001,4634,16158,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 2983,"ST87 Ouvea / UTM zone 58S",9001,4635,16158,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 2984,"RGNC 1991 / Lambert New Caledonia",9001,4645,19981,9802,1,1,4499,8821,-21.3,9110,8822,166,9110,8823,-20.4,9110,8824,-22.2,9110,8826,400000,9001,8827,300000,9001,,,
-2985,"Petrels 1972 / Terre Adelie Polar Stereographic",9001,4636,19983,9830,1,0,4492,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
-2986,"Perroud 1950 / Terre Adelie Polar Stereographic",9001,4637,19983,9830,1,0,4492,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
+2985,"Petrels 1972 / Terre Adelie Polar Stereographic",9001,4636,19983,9830,1,0,1025,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
+2986,"Perroud 1950 / Terre Adelie Polar Stereographic",9001,4637,19983,9830,1,0,1025,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
 2987,"Saint Pierre et Miquelon 1950 / UTM zone 21N",9001,4638,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 2988,"MOP78 / UTM zone 1S",9001,4639,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 2989,"RRAF 1991 / UTM zone 20N",9001,4640,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -996,19 +996,19 @@
 3003,"Monte Mario / Italy zone 1",9001,4265,18121,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,
 3004,"Monte Mario / Italy zone 2",9001,4265,18122,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,
 3005,"NAD83 / BC Albers",9001,4269,19984,9822,1,0,4400,8821,45,9102,8822,-126,9102,8823,50,9110,8824,58.3,9110,8826,1000000,9001,8827,0,9001,,,
-3006,SWEREF99 TM,9001,4619,17333,9807,1,0,4531,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3007,SWEREF99 12 00,9001,4619,17321,9807,1,0,4531,8801,0,9102,8802,12,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3008,SWEREF99 13 30,9001,4619,17322,9807,1,0,4531,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3009,SWEREF99 15 00,9001,4619,17323,9807,1,0,4531,8801,0,9102,8802,15,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3010,SWEREF99 16 30,9001,4619,17324,9807,1,0,4531,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3011,SWEREF99 18 00,9001,4619,17325,9807,1,0,4531,8801,0,9102,8802,18,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3012,SWEREF99 14 15,9001,4619,17326,9807,1,0,4531,8801,0,9110,8802,14.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3013,SWEREF99 15 45,9001,4619,17327,9807,1,0,4531,8801,0,9110,8802,15.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3014,SWEREF99 17 15,9001,4619,17328,9807,1,0,4531,8801,0,9110,8802,17.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3015,SWEREF99 18 45,9001,4619,17329,9807,1,0,4531,8801,0,9110,8802,18.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3016,SWEREF99 20 15,9001,4619,17330,9807,1,0,4531,8801,0,9110,8802,20.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3017,SWEREF99 21 45,9001,4619,17331,9807,1,0,4531,8801,0,9110,8802,21.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3018,SWEREF99 23 15,9001,4619,17332,9807,1,0,4531,8801,0,9110,8802,23.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3006,SWEREF99 TM,9001,4619,17333,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3007,SWEREF99 12 00,9001,4619,17321,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3008,SWEREF99 13 30,9001,4619,17322,9807,1,0,4500,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3009,SWEREF99 15 00,9001,4619,17323,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3010,SWEREF99 16 30,9001,4619,17324,9807,1,0,4500,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3011,SWEREF99 18 00,9001,4619,17325,9807,1,0,4500,8801,0,9102,8802,18,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3012,SWEREF99 14 15,9001,4619,17326,9807,1,0,4500,8801,0,9110,8802,14.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3013,SWEREF99 15 45,9001,4619,17327,9807,1,0,4500,8801,0,9110,8802,15.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3014,SWEREF99 17 15,9001,4619,17328,9807,1,0,4500,8801,0,9110,8802,17.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3015,SWEREF99 18 45,9001,4619,17329,9807,1,0,4500,8801,0,9110,8802,18.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3016,SWEREF99 20 15,9001,4619,17330,9807,1,0,4500,8801,0,9110,8802,20.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3017,SWEREF99 21 45,9001,4619,17331,9807,1,0,4500,8801,0,9110,8802,21.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
+3018,SWEREF99 23 15,9001,4619,17332,9807,1,0,4500,8801,0,9110,8802,23.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
 3019,RT90 7.5 gon V,9001,4124,17334,9807,1,0,4530,8801,0,9110,8802,11.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
 3020,RT90 5 gon V,9001,4124,17335,9807,1,0,4530,8801,0,9110,8802,13.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
 3021,RT90 2.5 gon V,9001,4124,19929,9807,1,0,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
@@ -1024,24 +1024,24 @@
 3031,"WGS 84 / Antarctic Polar Stereographic",9001,4326,19992,9829,1,0,4490,8806,0,9001,8807,0,9001,8832,-71,9102,8833,0,9102,,,,,,,,,
 3032,"WGS 84 / Australian Antarctic Polar Stereographic",9001,4326,19993,9829,1,0,4489,8806,6000000,9001,8807,6000000,9001,8832,-71,9102,8833,70,9102,,,,,,,,,
 3033,"WGS 84 / Australian Antarctic Lambert",9001,4326,19994,9802,1,0,4400,8821,-50,9110,8822,70,9110,8823,-68.3,9110,8824,-74.3,9110,8826,6000000,9001,8827,6000000,9001,,,
-3034,"ETRS89 / ETRS-LCC",9001,4258,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,
-3035,"ETRS89 / ETRS-LAEA",9001,4258,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,
+3034,"ETRS89 / LCC Europe",9001,4258,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,
+3035,"ETRS89 / LAEA Europe",9001,4258,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,
 3036,"Moznet / UTM zone 36S",9001,4130,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 3037,"Moznet / UTM zone 37S",9001,4130,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3038,"ETRS89 / ETRS-TM26",9001,4258,16026,9807,1,0,4500,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3039,"ETRS89 / ETRS-TM27",9001,4258,16027,9807,1,0,4500,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3040,"ETRS89 / ETRS-TM28",9001,4258,16028,9807,1,0,4500,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3041,"ETRS89 / ETRS-TM29",9001,4258,16029,9807,1,0,4500,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3042,"ETRS89 / ETRS-TM30",9001,4258,16030,9807,1,0,4500,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3043,"ETRS89 / ETRS-TM31",9001,4258,16031,9807,1,0,4500,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3044,"ETRS89 / ETRS-TM32",9001,4258,16032,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3045,"ETRS89 / ETRS-TM33",9001,4258,16033,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3046,"ETRS89 / ETRS-TM34",9001,4258,16034,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3047,"ETRS89 / ETRS-TM35",9001,4258,16035,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3048,"ETRS89 / ETRS-TM36",9001,4258,16036,9807,1,0,4500,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3049,"ETRS89 / ETRS-TM37",9001,4258,16037,9807,1,0,4500,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3050,"ETRS89 / ETRS-TM38",9001,4258,16038,9807,1,0,4500,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3051,"ETRS89 / ETRS-TM39",9001,4258,16039,9807,1,0,4500,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3038,"ETRS89 / TM26",9001,4258,16026,9807,1,0,4500,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3039,"ETRS89 / TM27",9001,4258,16027,9807,1,0,4500,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3040,"ETRS89 / TM28",9001,4258,16028,9807,1,0,4500,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3041,"ETRS89 / TM29",9001,4258,16029,9807,1,0,4500,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3042,"ETRS89 / TM30",9001,4258,16030,9807,1,0,4500,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3043,"ETRS89 / TM31",9001,4258,16031,9807,1,0,4500,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3044,"ETRS89 / TM32",9001,4258,16032,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3045,"ETRS89 / TM33",9001,4258,16033,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3046,"ETRS89 / TM34",9001,4258,16034,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3047,"ETRS89 / TM35",9001,4258,16035,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3048,"ETRS89 / TM36",9001,4258,16036,9807,1,0,4500,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3049,"ETRS89 / TM37",9001,4258,16037,9807,1,0,4500,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3050,"ETRS89 / TM38",9001,4258,16038,9807,1,0,4500,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3051,"ETRS89 / TM39",9001,4258,16039,9807,1,0,4500,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3052,"Reykjavik 1900 / Lambert 1900",9001,4657,19987,9826,1,0,4491,8801,65,9110,8802,-19.011965,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
 3053,"Hjorsey 1955 / Lambert 1955",9001,4658,19988,9826,1,0,4491,8801,65,9102,8802,-18,9102,8805,1,9201,8806,500000,9001,8807,500000,9001,,,,,,
 3054,"Hjorsey 1955 / UTM zone 26N",9001,4658,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -1057,7 +1057,7 @@
 3064,"IGM95 / UTM zone 32N",9001,4670,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3065,"IGM95 / UTM zone 33N",9001,4670,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3066,"ED50 / Jordan TM",9001,4230,19995,9807,1,0,4400,8801,0,9102,8802,37,9102,8805,0.9998,9201,8806,500000,9001,8807,-3000000,9001,,,,,,
-3067,"ETRS89 / ETRS-TM35FIN",9001,4258,16065,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3067,"ETRS89 / TM35FIN(E,N)",9001,4258,16065,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3068,"DHDN / Soldner Berlin",9001,4314,19996,9806,1,0,4531,8801,52.25071338,9110,8802,13.37379332,9110,8806,40000,9001,8807,10000,9001,,,,,,,,,
 3069,"NAD27 / Wisconsin Transverse Mercator",9001,4267,14811,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,500000,9001,8807,-4500000,9001,,,,,,
 3070,"NAD83 / Wisconsin Transverse Mercator",9001,4269,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,
@@ -1800,7 +1800,7 @@
 3826,"TWD97 / TM2 zone 121",9001,3824,3820,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,
 3827,"TWD67 / TM2 zone 119",9001,3821,3818,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,
 3828,"TWD67 / TM2 zone 121",9001,3821,3820,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,
-3829,"Hu Tzu Shan / UTM zone 51N",9001,4236,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+3829,"Hu Tzu Shan 1950 / UTM zone 51N",9001,4236,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3832,"WGS 84 / PDC Mercator",9001,4326,3831,9804,1,0,4400,8801,0,9102,8802,150,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
 3833,"Pulkovo 1942(58) / Gauss-Kruger zone 2",9001,4179,16202,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
 3834,"Pulkovo 1942(83) / Gauss-Kruger zone 2",9001,4178,16202,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
@@ -1824,6 +1824,19 @@
 3852,"RSRGD2000 / DGLC2000",9001,4764,17966,9802,1,0,4500,8821,-90,9110,8822,157,9110,8823,-76.4,9110,8824,-79.2,9110,8826,500000,9001,8827,0,9001,,,
 3854,County ST74,9001,4619,3853,9807,1,0,4531,8801,0,9110,8802,18.0328332,9110,8805,0.99999506,9201,8806,100182.7406,9001,8807,-6500620.1207,9001,,,,,,
 3857,"WGS 84 / Pseudo-Mercator",9001,4326,3856,1024,1,0,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+3873,"ETRS89 / GK19FIN",9001,4258,3860,9807,1,0,4500,8801,0,9102,8802,19,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
+3874,"ETRS89 / GK20FIN",9001,4258,3861,9807,1,0,4500,8801,0,9102,8802,20,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
+3875,"ETRS89 / GK21FIN",9001,4258,3862,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
+3876,"ETRS89 / GK22FIN",9001,4258,3863,9807,1,0,4500,8801,0,9102,8802,22,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
+3877,"ETRS89 / GK23FIN",9001,4258,3864,9807,1,0,4500,8801,0,9102,8802,23,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
+3878,"ETRS89 / GK24FIN",9001,4258,3865,9807,1,0,4500,8801,0,9102,8802,24,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,
+3879,"ETRS89 / GK25FIN",9001,4258,3866,9807,1,0,4500,8801,0,9102,8802,25,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
+3880,"ETRS89 / GK26FIN",9001,4258,3867,9807,1,0,4500,8801,0,9102,8802,26,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
+3881,"ETRS89 / GK27FIN",9001,4258,3868,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
+3882,"ETRS89 / GK28FIN",9001,4258,3869,9807,1,0,4500,8801,0,9102,8802,28,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
+3883,"ETRS89 / GK29FIN",9001,4258,3870,9807,1,0,4500,8801,0,9102,8802,29,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
+3884,"ETRS89 / GK30FIN",9001,4258,3871,9807,1,0,4500,8801,0,9102,8802,30,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
+3885,"ETRS89 / GK31FIN",9001,4258,3872,9807,1,0,4500,8801,0,9102,8802,31,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
 3890,"IGRS / UTM zone 37N",9001,3889,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3891,"IGRS / UTM zone 38N",9001,3889,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 3892,"IGRS / UTM zone 39N",9001,3889,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -1889,11 +1902,45 @@
 4094,"ETRS89 / DKTM2",9001,4258,4090,9807,1,0,4400,8801,0,9102,8802,10,9102,8805,0.99998,9201,8806,400000,9001,8807,-5000000,9001,,,,,,
 4095,"ETRS89 / DKTM3",9001,4258,4091,9807,1,0,4400,8801,0,9102,8802,11.75,9102,8805,0.99998,9201,8806,600000,9001,8807,-5000000,9001,,,,,,
 4096,"ETRS89 / DKTM4",9001,4258,4092,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,800000,9001,8807,-5000000,9001,,,,,,
+4217,"NAD83 / BLM 59N (ftUS)",9003,4269,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4399,"NAD27 / BLM 59N (ftUS)",9003,4267,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4400,"NAD27 / BLM 60N (ftUS)",9003,4267,4187,9807,1,0,4497,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4401,"NAD27 / BLM 1N (ftUS)",9003,4267,4101,9807,1,0,4497,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4402,"NAD27 / BLM 2N (ftUS)",9003,4267,4102,9807,1,0,4497,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4403,"NAD27 / BLM 3N (ftUS)",9003,4267,4103,9807,1,0,4497,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4404,"NAD27 / BLM 4N (ftUS)",9003,4267,4104,9807,1,0,4497,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4405,"NAD27 / BLM 5N (ftUS)",9003,4267,4105,9807,1,0,4497,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4406,"NAD27 / BLM 6N (ftUS)",9003,4267,4106,9807,1,0,4497,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4407,"NAD27 / BLM 7N (ftUS)",9003,4267,4107,9807,1,0,4497,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4408,"NAD27 / BLM 8N (ftUS)",9003,4267,4108,9807,1,0,4497,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4409,"NAD27 / BLM 9N (ftUS)",9003,4267,4109,9807,1,0,4497,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4410,"NAD27 / BLM 10N (ftUS)",9003,4267,4110,9807,1,0,4497,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4411,"NAD27 / BLM 11N (ftUS)",9003,4267,4111,9807,1,0,4497,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4412,"NAD27 / BLM 12N (ftUS)",9003,4267,4112,9807,1,0,4497,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4413,"NAD27 / BLM 13N (ftUS)",9003,4267,4113,9807,1,0,4497,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4414,"NAD83(HARN) / Guam Map Grid",9001,4152,4325,9807,1,0,4499,8801,13.3,9110,8802,144.45,9110,8805,1,9201,8806,100000,9001,8807,200000,9001,,,,,,
 4415,"Katanga 1955 / Katanga Lambert",9001,4695,4416,9802,1,0,4499,8821,-9,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,500000,9001,8827,500000,9001,,,
 4417,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 7",9001,4178,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
+4418,"NAD27 / BLM 18N (ftUS)",9003,4267,4118,9807,1,0,4497,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4419,"NAD27 / BLM 19N (ftUS)",9003,4267,4119,9807,1,0,4497,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4420,"NAD83 / BLM 60N (ftUS)",9003,4269,4187,9807,1,0,4497,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4421,"NAD83 / BLM 1N (ftUS)",9003,4269,4101,9807,1,0,4497,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4422,"NAD83 / BLM 2N (ftUS)",9003,4269,4102,9807,1,0,4497,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4423,"NAD83 / BLM 3N (ftUS)",9003,4269,4103,9807,1,0,4497,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4424,"NAD83 / BLM 4N (ftUS)",9003,4269,4104,9807,1,0,4497,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4425,"NAD83 / BLM 5N (ftUS)",9003,4269,4105,9807,1,0,4497,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4426,"NAD83 / BLM 6N (ftUS)",9003,4269,4106,9807,1,0,4497,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4427,"NAD83 / BLM 7N (ftUS)",9003,4269,4107,9807,1,0,4497,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4428,"NAD83 / BLM 8N (ftUS)",9003,4269,4108,9807,1,0,4497,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4429,"NAD83 / BLM 9N (ftUS)",9003,4269,4109,9807,1,0,4497,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4430,"NAD83 / BLM 10N (ftUS)",9003,4269,4110,9807,1,0,4497,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4431,"NAD83 / BLM 11N (ftUS)",9003,4269,4111,9807,1,0,4497,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4432,"NAD83 / BLM 12N (ftUS)",9003,4269,4112,9807,1,0,4497,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4433,"NAD83 / BLM 13N (ftUS)",9003,4269,4113,9807,1,0,4497,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4434,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 8",9001,4178,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
 4437,"NAD83(NSRS2007) / Puerto Rico and Virgin Is.",9001,4759,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,
+4438,"NAD83 / BLM 18N (ftUS)",9003,4269,4118,9807,1,0,4497,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4439,"NAD83 / BLM 19N (ftUS)",9003,4269,4119,9807,1,0,4497,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4455,"NAD27 / Pennsylvania South",9003,4267,4436,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,2000000,9003,8827,0,9003,,,
 4456,"NAD27 / New York Long Island",9003,4267,4454,9802,1,0,4497,8821,40.3,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,2000000,9003,8827,100000,9003,,,
 4457,"NAD83 / South Dakota North (ftUS)",9003,4269,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,
@@ -2038,6 +2085,201 @@
 4812,"New Beijing / 3-degree Gauss-Kruger CM 132E",9001,4555,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
 4822,"New Beijing / 3-degree Gauss-Kruger CM 135E",9001,4555,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
 4826,"WGS 84 / Cape Verde National",9001,4326,4825,9802,1,0,1024,8821,15.5,9110,8822,-24,9110,8823,15,9110,8824,16.4,9110,8826,161587.83,9001,8827,128511.202,9001,,,
+4839,"ETRS89 / LCC Germany (N-E)",9001,4258,4838,9802,1,0,4500,8821,51,9102,8822,10.3,9110,8823,48.4,9110,8824,53.4,9110,8826,0,9001,8827,0,9001,,,
+4855,"ETRS89 / NTM zone 5",9001,4258,4845,9807,1,1,4500,8801,0,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4856,"ETRS89 / NTM zone 6",9001,4258,4846,9807,1,1,4500,8801,0,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4857,"ETRS89 / NTM zone 7",9001,4258,4847,9807,1,1,4500,8801,0,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4858,"ETRS89 / NTM zone 8",9001,4258,4848,9807,1,1,4500,8801,0,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4859,"ETRS89 / NTM zone 9",9001,4258,4849,9807,1,1,4500,8801,0,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4860,"ETRS89 / NTM zone 10",9001,4258,4850,9807,1,1,4500,8801,0,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4861,"ETRS89 / NTM zone 11",9001,4258,4851,9807,1,1,4500,8801,0,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4862,"ETRS89 / NTM zone 12",9001,4258,4852,9807,1,1,4500,8801,0,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4863,"ETRS89 / NTM zone 13",9001,4258,4853,9807,1,1,4500,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4864,"ETRS89 / NTM zone 14",9001,4258,4854,9807,1,1,4500,8801,0,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4865,"ETRS89 / NTM zone 15",9001,4258,4841,9807,1,1,4500,8801,0,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4866,"ETRS89 / NTM zone 16",9001,4258,4842,9807,1,1,4500,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4867,"ETRS89 / NTM zone 17",9001,4258,4843,9807,1,1,4500,8801,0,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4868,"ETRS89 / NTM zone 18",9001,4258,4844,9807,1,1,4500,8801,0,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4869,"ETRS89 / NTM zone 19",9001,4258,4881,9807,1,1,4500,8801,0,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4870,"ETRS89 / NTM zone 20",9001,4258,5000,9807,1,1,4500,8801,0,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4871,"ETRS89 / NTM zone 21",9001,4258,5001,9807,1,1,4500,8801,0,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4872,"ETRS89 / NTM zone 22",9001,4258,5002,9807,1,1,4500,8801,0,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4873,"ETRS89 / NTM zone 23",9001,4258,5003,9807,1,1,4500,8801,0,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4874,"ETRS89 / NTM zone 24",9001,4258,5004,9807,1,1,4500,8801,0,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4875,"ETRS89 / NTM zone 25",9001,4258,5005,9807,1,1,4500,8801,0,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4876,"ETRS89 / NTM zone 26",9001,4258,5006,9807,1,1,4500,8801,0,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4877,"ETRS89 / NTM zone 27",9001,4258,5007,9807,1,1,4500,8801,0,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4878,"ETRS89 / NTM zone 28",9001,4258,5008,9807,1,1,4500,8801,0,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4879,"ETRS89 / NTM zone 29",9001,4258,5009,9807,1,1,4500,8801,0,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4880,"ETRS89 / NTM zone 30",9001,4258,5010,9807,1,1,4500,8801,0,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5014,"PTRA08 / UTM zone 25N",9001,5013,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+5015,"PTRA08 / UTM zone 26N",9001,5013,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+5016,"PTRA08 / UTM zone 28N",9001,5013,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+5017,"Lisbon 1890 / Portugal Bonne New",9001,4666,5019,9828,1,0,6509,8801,39.4,9110,8802,-8.0754862,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+5018,"Lisbon / Portuguese Grid New",9001,4207,5020,9807,1,0,4499,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
+5041,"WGS 84 / UPS North (E,N)",9001,4326,16061,9810,1,0,1026,8801,90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5042,"WGS 84 / UPS South (E,N)",9001,4326,16161,9810,1,0,1027,8801,-90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+5048,"ETRS89 / TM35FIN(N,E)",9001,4258,16065,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+5069,"NAD27 / Conus Albers",9001,4267,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
+5070,"NAD83 / Conus Albers",9001,4269,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
+5071,"NAD83(HARN) / Conus Albers",9001,4152,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
+5072,"NAD83(NSRS2007) / Conus Albers",9001,4759,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
+5105,"ETRS89 / NTM zone 5",9001,4258,5135,9807,1,0,4500,8801,58,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5106,"ETRS89 / NTM zone 6",9001,4258,5136,9807,1,0,4500,8801,58,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5107,"ETRS89 / NTM zone 7",9001,4258,5137,9807,1,0,4500,8801,58,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5108,"ETRS89 / NTM zone 8",9001,4258,5138,9807,1,0,4500,8801,58,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5109,"ETRS89 / NTM zone 9",9001,4258,5139,9807,1,0,4500,8801,58,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5110,"ETRS89 / NTM zone 10",9001,4258,5140,9807,1,0,4500,8801,58,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5111,"ETRS89 / NTM zone 11",9001,4258,5141,9807,1,0,4500,8801,58,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5112,"ETRS89 / NTM zone 12",9001,4258,5142,9807,1,0,4500,8801,58,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5113,"ETRS89 / NTM zone 13",9001,4258,5143,9807,1,0,4500,8801,58,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5114,"ETRS89 / NTM zone 14",9001,4258,5144,9807,1,0,4500,8801,58,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5115,"ETRS89 / NTM zone 15",9001,4258,5145,9807,1,0,4500,8801,58,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5116,"ETRS89 / NTM zone 16",9001,4258,5146,9807,1,0,4500,8801,58,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5117,"ETRS89 / NTM zone 17",9001,4258,5147,9807,1,0,4500,8801,58,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5118,"ETRS89 / NTM zone 18",9001,4258,5148,9807,1,0,4500,8801,58,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5119,"ETRS89 / NTM zone 19",9001,4258,5149,9807,1,0,4500,8801,58,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5120,"ETRS89 / NTM zone 20",9001,4258,5150,9807,1,0,4500,8801,58,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5121,"ETRS89 / NTM zone 21",9001,4258,5151,9807,1,0,4500,8801,58,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5122,"ETRS89 / NTM zone 22",9001,4258,5152,9807,1,0,4500,8801,58,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5123,"ETRS89 / NTM zone 23",9001,4258,5153,9807,1,0,4500,8801,58,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5124,"ETRS89 / NTM zone 24",9001,4258,5154,9807,1,0,4500,8801,58,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5125,"ETRS89 / NTM zone 25",9001,4258,5155,9807,1,0,4500,8801,58,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5126,"ETRS89 / NTM zone 26",9001,4258,5156,9807,1,0,4500,8801,58,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5127,"ETRS89 / NTM zone 27",9001,4258,5157,9807,1,0,4500,8801,58,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5128,"ETRS89 / NTM zone 28",9001,4258,5158,9807,1,0,4500,8801,58,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5129,"ETRS89 / NTM zone 29",9001,4258,5159,9807,1,0,4500,8801,58,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5130,"ETRS89 / NTM zone 30",9001,4258,5160,9807,1,0,4500,8801,58,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5167,"Korean 1985 / East Sea Belt",9001,4162,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5168,"Korean 1985 / Central Belt Jeju",9001,4162,5131,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
+5169,"Tokyo 1892 / Korea West Belt",9001,5132,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5170,"Tokyo 1892 / Korea Central Belt",9001,5132,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5171,"Tokyo 1892 / Korea East Belt",9001,5132,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5172,"Tokyo 1892 / Korea East Sea Belt",9001,5132,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5173,"Korean 1985 / Modified West Belt",9001,4162,5161,9807,1,0,4530,8801,38,9102,8802,125.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5174,"Korean 1985 / Modified Central Belt",9001,4162,5162,9807,1,0,4530,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5175,"Korean 1985 / Modified Central Belt Jeju",9001,4162,5163,9807,1,0,4530,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
+5176,"Korean 1985 / Modified East Belt",9001,4162,5164,9807,1,0,4530,8801,38,9102,8802,129.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5177,"Korean 1985 / Modified East Sea Belt",9001,4162,5165,9807,1,0,4530,8801,38,9102,8802,131.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5178,"Korean 1985 / Unified CS",9001,4162,5100,9807,1,0,4530,8801,38,9102,8802,127.3,9110,8805,0.9996,9201,8806,1000000,9001,8807,2000000,9001,,,,,,
+5179,"Korea 2000 / Unified CS",9001,4737,5100,9807,1,0,4530,8801,38,9102,8802,127.3,9110,8805,0.9996,9201,8806,1000000,9001,8807,2000000,9001,,,,,,
+5180,"Korea 2000 / West Belt",9001,4737,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5181,"Korea 2000 / Central Belt",9001,4737,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5182,"Korea 2000 / Central Belt Jeju",9001,4737,5131,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
+5183,"Korea 2000 / East Belt",9001,4737,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5184,"Korea 2000 / East Sea Belt",9001,4737,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5185,"Korea 2000 / West Belt 2010",9001,4737,5101,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5186,"Korea 2000 / Central Belt 2010",9001,4737,5102,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5187,"Korea 2000 / East Belt 2010",9001,4737,5103,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5188,"Korea 2000 / East Sea Belt 2010",9001,4737,5104,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5221,"S-JTSK (Ferro) / Krovak East North",9001,4818,5218,1041,1,0,4499,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
+5223,"WGS 84 / Gabon TM",9001,4326,5222,9807,1,0,4499,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,500000,9001,,,,,,
+5224,"S-JTSK/05 (Ferro) / Modified Krovak",9001,5229,5219,1042,1,0,6501,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5225,"S-JTSK/05 (Ferro) / Modified Krovak East North",9001,5229,5220,1043,1,0,4499,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5234,"Kandawala / Sri Lanka Grid",9001,4244,5231,9807,1,0,4400,8801,7.0001729,9110,8802,80.461816,9110,8805,0.9999238418,9201,8806,200000,9001,8807,200000,9001,,,,,,
+5235,"SLD99 / Sri Lanka Grid 1999",9001,5233,5232,9807,1,0,4400,8801,7.00016975,9110,8802,80.46181671,9110,8805,0.9999238418,9201,8806,500000,9001,8807,500000,9001,,,,,,
+5243,"ETRS89 / LCC Germany (E-N)",9001,4258,4838,9802,1,0,4400,8821,51,9102,8822,10.3,9110,8823,48.4,9110,8824,53.4,9110,8826,0,9001,8827,0,9001,,,
+5247,"GDBD2009 / Brunei BRSO",9001,5246,19894,9812,1,0,4400,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201
+5253,"TUREF / TM27",9001,5252,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5254,"TUREF / TM30",9001,5252,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5255,"TUREF / TM33",9001,5252,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5256,"TUREF / TM36",9001,5252,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5257,"TUREF / TM39",9001,5252,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5258,"TUREF / TM42",9001,5252,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5259,"TUREF / TM45",9001,5252,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
+5266,"DRUKREF 03 / Bhutan National Grid",9001,5264,5265,9807,1,0,4400,8801,0,9102,8802,90,9102,8805,1,9201,8806,250000,9001,8807,0,9001,,,,,,
+5269,"TUREF / 3-degree Gauss-Kruger zone 9",9001,5252,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
+5270,"TUREF / 3-degree Gauss-Kruger zone 10",9001,5252,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
+5271,"TUREF / 3-degree Gauss-Kruger zone 11",9001,5252,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
+5272,"TUREF / 3-degree Gauss-Kruger zone 12",9001,5252,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
+5273,"TUREF / 3-degree Gauss-Kruger zone 13",9001,5252,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
+5274,"TUREF / 3-degree Gauss-Kruger zone 14",9001,5252,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
+5275,"TUREF / 3-degree Gauss-Kruger zone 15",9001,5252,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
+5292,"DRUKREF 03 / Bumthang TM",9001,5264,5268,9807,1,0,4400,8801,0,9110,8802,90.44,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5293,"DRUKREF 03 / Chhukha TM",9001,5264,5276,9807,1,0,4400,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5294,"DRUKREF 03 / Dagana TM",9001,5264,5277,9807,1,0,4400,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5295,"DRUKREF 03 / Gasa TM",9001,5264,5278,9807,1,0,4400,8801,0,9110,8802,90.02,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5296,"DRUKREF 03 / Ha TM",9001,5264,5279,9807,1,0,4400,8801,0,9110,8802,90.09,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5297,"DRUKREF 03 / Lhuentse TM",9001,5264,5280,9807,1,0,4400,8801,0,9110,8802,91.08,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5298,"DRUKREF 03 / Mongar TM",9001,5264,5281,9807,1,0,4400,8801,0,9110,8802,91.14,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5299,"DRUKREF 03 / Paro TM",9001,5264,5282,9807,1,0,4400,8801,0,9110,8802,89.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5300,"DRUKREF 03 / Pemagatshel TM",9001,5264,5283,9807,1,0,4400,8801,0,9110,8802,91.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5301,"DRUKREF 03 / Punakha TM",9001,5264,5313,9807,1,0,4400,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5302,"DRUKREF 03 / Samdrup Jongkhar TM",9001,5264,5285,9807,1,0,4400,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5303,"DRUKREF 03 / Samtse TM",9001,5264,5286,9807,1,0,4400,8801,0,9110,8802,89.04,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5304,"DRUKREF 03 / Sarpang TM",9001,5264,5287,9807,1,0,4400,8801,0,9110,8802,90.16,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5305,"DRUKREF 03 / Thimphu TM",9001,5264,5312,9807,1,0,4400,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5306,"DRUKREF 03 / Trashigang TM",9001,5264,5289,9807,1,0,4400,8801,0,9110,8802,91.45,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5307,"DRUKREF 03 / Trongsa TM",9001,5264,5290,9807,1,0,4400,8801,0,9110,8802,90.3,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5308,"DRUKREF 03 / Tsirang TM",9001,5264,5284,9807,1,0,4400,8801,0,9110,8802,90.1,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5309,"DRUKREF 03 / Wangdue Phodrang TM",9001,5264,5288,9807,1,0,4400,8801,0,9110,8802,90.07,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5310,"DRUKREF 03 / Yangtse TM",9001,5264,5314,9807,1,0,4400,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5311,"DRUKREF 03 / Zhemgang TM",9001,5264,5291,9807,1,0,4400,8801,0,9110,8802,90.52,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5316,"ETRS89 / Faroe TM",9001,4258,5315,9807,1,0,4400,8801,0,9102,8802,-7,9102,8805,0.999997,9201,8806,200000,9001,8807,-6000000,9001,,,,,,
+5320,"NAD83 / Teranet Ontario Lambert",9001,4269,5319,9802,1,0,4499,8821,0,9102,8822,-84,9102,8823,44.3,9110,8824,54.3,9110,8826,1000000,9001,8827,0,9001,,,
+5321,"NAD83(CSRS) / Teranet Ontario Lambert",9001,4617,5319,9802,1,0,4499,8821,0,9102,8822,-84,9102,8823,44.3,9110,8824,54.3,9110,8826,1000000,9001,8827,0,9001,,,
+5325,"ISN2004 / Lambert 2004",9001,5324,5326,9802,1,0,4499,8821,65,9110,8822,-19,9110,8823,64.15,9110,8824,65.45,9110,8826,1700000,9001,8827,300000,9001,,,
+5329,"Segara (Jakarta) / NEIEZ",9001,4820,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
+5330,"Batavia (Jakarta) / NEIEZ",9001,4813,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
+5331,"Makassar (Jakarta) / NEIEZ",9001,4804,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
+5337,"Aratu / UTM zone 25S",9001,4208,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5343,"POSGAR 2007 / Argentina 1",9001,5340,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
+5344,"POSGAR 2007 / Argentina 2",9001,5340,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
+5345,"POSGAR 2007 / Argentina 3",9001,5340,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
+5346,"POSGAR 2007 / Argentina 4",9001,5340,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
+5347,"POSGAR 2007 / Argentina 5",9001,5340,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
+5348,"POSGAR 2007 / Argentina 6",9001,5340,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
+5349,"POSGAR 2007 / Argentina 7",9001,5340,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
+5355,"MARGEN / UTM zone 20S",9001,5354,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5356,"MARGEN / UTM zone 19S",9001,5354,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5357,"MARGEN / UTM zone 21S",9001,5354,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5361,"SIRGAS-Chile / UTM zone 19S",9001,5360,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5362,"SIRGAS-Chile / UTM zone 18S",9001,5360,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5367,"CR05 / CRTM05",9001,5365,5366,9807,1,0,4500,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
+5382,"SIRGAS-ROU98 / UTM zone 21S",9001,5381,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5383,"SIRGAS-ROU98 / UTM zone 22S",9001,5381,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5387,"Peru96 / UTM zone 18S",9001,5373,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5388,"Peru96 / UTM zone 17S",9001,5373,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+5389,"Peru96 / UTM zone 19S",9001,5373,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5396,"SIRGAS 2000 / UTM zone 26S",9001,4674,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5456,"Ocotepeque 1935 / Costa Rica Norte",9001,5451,5390,9801,1,0,4499,8801,10.28,9110,8802,-84.2,9110,8805,0.99995696,9201,8806,500000,9001,8807,271820.522,9001,,,,,,
+5457,"Ocotepeque 1935 / Costa Rica Sur",9001,5451,5394,9801,1,0,4499,8801,9,9110,8802,-83.4,9110,8805,0.99995696,9201,8806,500000,9001,8807,327987.436,9001,,,,,,
+5458,"Ocotepeque 1935 / Guatemala Norte",9001,4267,18211,9801,1,1,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,
+5459,"Ocotepeque 1935 / Guatemala Sur",9001,5451,18212,9801,1,0,4499,8801,14.54,9110,8802,-90.2,9110,8805,0.99989906,9201,8806,500000,9001,8807,325992.681,9001,,,,,,
+5460,"Ocotepeque 1935 / El Salvador Lambert",9001,5451,5399,9801,1,0,4499,8801,13.47,9110,8802,-89,9110,8805,0.99996704,9201,8806,500000,9001,8807,295809.184,9001,,,,,,
+5461,"Ocotepeque 1935 / Nicaragua Norte",9001,5451,5439,9801,1,0,4499,8801,13.52,9110,8802,-85.3,9110,8805,0.99990314,9201,8806,500000,9001,8807,359891.816,9001,,,,,,
+5462,"Ocotepeque 1935 / Nicaragua Sur",9001,5451,5444,9801,1,0,4499,8801,11.44,9110,8802,-85.3,9110,8805,0.99992228,9201,8806,500000,9001,8807,288876.327,9001,,,,,,
+5463,"SAD69 / UTM zone 17N",9001,4618,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+5466,"Sibun Gorge 1922 / Colony Grid",9001,5464,5465,9807,1,0,4499,8801,17.0340471,9110,8802,-88.3754687,9110,8805,1,9201,8806,217259.26,9005,8807,445474.83,9005,,,,,,
+5469,"Panama-Colon 1911 / Panama Lambert",9001,5467,5468,9801,1,0,4499,8801,8.25,9110,8802,-80,9110,8805,0.99989909,9201,8806,500000,9001,8807,294865.303,9001,,,,,,
+5472,"Panama-Colon 1911 / Panama Polyconic",9037,5467,5471,9818,1,0,1028,8801,8.15,9110,8802,-81,9110,8806,1000000,9037,8807,1092972.1,9037,,,,,,,,,
+5479,"RSRGD2000 / MSLC2000",9001,4764,5475,9802,1,0,4500,8821,-78,9110,8822,163,9110,8823,-76.4,9110,8824,-79.2,9110,8826,7000000,9001,8827,5000000,9001,,,
+5480,"RSRGD2000 / BCLC2000",9001,4764,5476,9802,1,0,4500,8821,-74.3,9110,8822,165,9110,8823,-73.4,9110,8824,-75.2,9110,8826,5000000,9001,8827,3000000,9001,,,
+5481,"RSRGD2000 / PCLC2000",9001,4764,5477,9802,1,0,4500,8821,-71.3,9110,8822,166,9110,8823,-70.4,9110,8824,-72.2,9110,8826,3000000,9001,8827,1000000,9001,,,
+5482,"RSRGD2000 / RSPS2000",9001,4764,5478,9810,1,0,4500,8801,-90,9102,8802,180,9102,8805,0.994,9201,8806,5000000,9001,8807,1000000,9001,,,,,,
+5490,"RGAF09 / UTM zone 20N",9001,5489,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+5513,"S-JTSK / Krovak",9001,4156,5509,9819,1,0,6501,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
+5514,"S-JTSK / Krovak East North",9001,4156,5510,1041,1,0,4499,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
+5515,"S-JTSK/05 / Modified Krovak",9001,5228,5511,1042,1,0,6501,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5516,"S-JTSK/05 / Modified Krovak East North",9001,5228,5512,1043,1,0,4499,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5518,"CI1971 / Chatham Islands Map Grid",9001,4672,5517,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,
+5519,"CI1979 / Chatham Islands Map Grid",9001,4673,5517,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,
+5520,"DHDN / 3-degree Gauss-Kruger zone 1",9001,4314,16261,9807,1,0,4530,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
+5523,"WGS 84 / Gabon TM 2011",9001,4326,5522,9807,1,0,4499,8801,0,9102,8802,11.3,9110,8805,0.9996,9201,8806,1500000,9001,8807,5500000,9001,,,,,,
+5530,"SAD69(96) / Brazil Polyconic",9001,5527,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
+5531,"SAD69(96) / UTM zone 21S",9001,5527,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5532,"SAD69(96) / UTM zone 22S",9001,4618,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5533,"SAD69(96) / UTM zone 23S",9001,5527,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5534,"SAD69(96) / UTM zone 24S",9001,5527,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5535,"SAD69(96) / UTM zone 25S",9001,5527,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5536,"Corrego Alegre 1961 / UTM zone 21S",9001,5524,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5537,"Corrego Alegre 1961 / UTM zone 22S",9001,5524,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5538,"Corrego Alegre 1961 / UTM zone 23S",9001,5524,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5539,"Corrego Alegre 1961 / UTM zone 24S",9001,5524,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5550,"PNG94 / PNGMG94 zone 54",9001,5546,5547,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+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,,,,,,
 5819,EPSG topocentric example A,9001,4979,15594,9837,1,0,4461,8834,55,9102,8835,5,9102,8836,0,9001,,,,,,,,,,,,
 5820,EPSG topocentric example B,9001,4978,15595,9836,1,0,4461,8837,3771793.97,9001,8838,140253.34,9001,8839,5124304.35,9001,,,,,,,,,,,,
 5821,EPSG vertical perspective example,9001,5819,19850,9838,1,0,4461,8834,55,9102,8835,5,9102,8836,200,9001,8840,5900,9036,,,,,,,,,
@@ -2227,7 +2469,7 @@
 22197,"Campo Inchauspe / Argentina 7",9001,4221,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
 22234,"Cape / UTM zone 34S",9001,4222,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 22235,"Cape / UTM zone 35S",9001,4222,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22236,"Cape / UTM zone 36S",9001,4222,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+22236,"Cape / UTM zone 36S",9001,4222,16136,9807,1,1,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 22275,"Cape / Lo15",9001,4222,17515,9808,1,0,6503,8801,0,9102,8802,15,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
 22277,"Cape / Lo17",9001,4222,17517,9808,1,0,6503,8801,0,9102,8802,17,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
 22279,"Cape / Lo19",9001,4222,17519,9808,1,0,6503,8801,0,9102,8802,19,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
@@ -2242,11 +2484,11 @@
 22332,"Carthage / UTM zone 32N",9001,4223,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 22391,"Carthage / Nord Tunisie",9001,4223,18181,9801,1,0,4499,8801,40,9105,8802,11,9105,8805,0.999625544,9201,8806,500000,9001,8807,300000,9001,,,,,,
 22392,"Carthage / Sud Tunisie",9001,4223,18182,9801,1,0,4499,8801,37,9105,8802,11,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,
-22521,"Corrego Alegre / UTM zone 21S",9001,4225,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22522,"Corrego Alegre / UTM zone 22S",9001,4225,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22523,"Corrego Alegre / UTM zone 23S",9001,4225,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22524,"Corrego Alegre / UTM zone 24S",9001,4225,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22525,"Corrego Alegre / UTM zone 25S",9001,4225,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+22521,"Corrego Alegre 1970-72 / UTM zone 21S",9001,4225,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+22522,"Corrego Alegre 1970-72 / UTM zone 22S",9001,4225,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+22523,"Corrego Alegre 1970-72 / UTM zone 23S",9001,4225,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+22524,"Corrego Alegre 1970-72 / UTM zone 24S",9001,4225,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+22525,"Corrego Alegre 1970-72 / UTM zone 25S",9001,4225,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 22700,"Deir ez Zor / Levant Zone",9001,4227,19940,9817,1,0,4499,8801,34.39,9110,8802,37.21,9110,8805,0.9996256,9201,8806,300000,9001,8807,300000,9001,,,,,,
 22770,"Deir ez Zor / Syria Lambert",9001,4227,19948,9801,1,0,4499,8801,34.39,9110,8802,37.21,9110,8805,0.9996256,9201,8806,300000,9001,8807,300000,9001,,,,,,
 22780,"Deir ez Zor / Levant Stereographic",9001,4227,19949,9809,1,0,4499,8801,38,9105,8802,43.5,9105,8805,0.9995341,9201,8806,0,9001,8807,0,9001,,,,,,
@@ -3040,8 +3282,8 @@
 32056,"NAD27 / Wyoming East Central",9003,4267,14902,9807,1,0,4497,8801,40.4,9110,8802,-107.2,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
 32057,"NAD27 / Wyoming West Central",9003,4267,14903,9807,1,0,4497,8801,40.4,9110,8802,-108.45,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
 32058,"NAD27 / Wyoming West",9003,4267,14904,9807,1,0,4497,8801,40.4,9110,8802,-110.05,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-32061,"NAD27 / Guatemala Norte",9001,4267,18211,9801,1,0,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,
-32062,"NAD27 / Guatemala Sur",9001,4267,18212,9801,1,0,4499,8801,14.54,9110,8802,-90.2,9110,8805,0.99989906,9201,8806,500000,9001,8807,325992.681,9001,,,,,,
+32061,"NAD27 / Guatemala Norte",9001,4267,18211,9801,1,1,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,
+32062,"NAD27 / Guatemala Sur",9001,4267,18212,9801,1,1,4499,8801,14.54,9110,8802,-90.2,9110,8805,0.99989906,9201,8806,500000,9001,8807,325992.681,9001,,,,,,
 32064,"NAD27 / BLM 14N (ftUS)",9003,4267,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 32065,"NAD27 / BLM 15N (ftUS)",9003,4267,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 32066,"NAD27 / BLM 16N (ftUS)",9003,4267,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
@@ -3115,7 +3357,7 @@
 32165,"NAD83 / BLM 15N (ftUS)",9003,4269,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 32166,"NAD83 / BLM 16N (ftUS)",9003,4269,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 32167,"NAD83 / BLM 17N (ftUS)",9003,4269,15917,9807,1,0,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32180,"NAD83 / SCoPQ zone 2",9001,4269,17700,9807,1,0,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
+32180,"NAD83 / SCoPQ zone 2",9001,4269,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 32181,"NAD83 / MTM zone 1",9001,4269,17701,9807,1,0,4496,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 32182,"NAD83 / MTM zone 2",9001,4269,17702,9807,1,0,4496,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 32183,"NAD83 / MTM zone 3",9001,4269,17703,9807,1,0,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
@@ -3436,7 +3678,7 @@
 32658,"WGS 84 / UTM zone 58N",9001,4326,16058,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 32659,"WGS 84 / UTM zone 59N",9001,4326,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 32660,"WGS 84 / UTM zone 60N",9001,4326,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32661,"WGS 84 / UPS North",9001,4326,16061,9810,1,0,4493,8801,90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+32661,"WGS 84 / UPS North (N,E)",9001,4326,16061,9810,1,0,4493,8801,90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
 32662,"WGS 84 / Plate Carree",9001,4326,19968,9823,1,1,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
 32663,"WGS 84 / World Equidistant Cylindrical",9001,4326,19846,9842,1,1,4499,8801,0,9102,8806,0,9001,8807,0,9001,8822,0,9102,,,,,,,,,
 32664,"WGS 84 / BLM 14N (ftUS)",9003,4326,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
@@ -3504,5 +3746,5 @@
 32758,"WGS 84 / UTM zone 58S",9001,4326,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 32759,"WGS 84 / UTM zone 59S",9001,4326,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 32760,"WGS 84 / UTM zone 60S",9001,4326,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32761,"WGS 84 / UPS South",9001,4326,16161,9810,1,0,4494,8801,-90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
+32761,"WGS 84 / UPS South (N,E)",9001,4326,16161,9810,1,0,4494,8801,-90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
 32766,"WGS 84 / TM 36 SE",9001,4326,16636,9807,1,0,4400,8801,0,9102,8802,36,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
diff --git a/data/pcs.override.csv b/data/pcs.override.csv
index a9b26c1..5e694fd 100644
--- a/data/pcs.override.csv
+++ b/data/pcs.override.csv
@@ -1,4 +1,4 @@
-"COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","UOM_CODE","SOURCE_GEOGCRS_CODE","COORD_OP_CODE","COORD_OP_METHOD_CODE","SHOW_CRS","DEPRECATED","PARAMETER_CODE_1","PARAMETER_VALUE_1","PARAMETER_UOM_1","PARAMETER_CODE_2","PARAMETER_VALUE_2","PARAMETER_UOM_2","PARAMETER_CODE_3","PARAMETER_VALUE_3","PARAMETER_UOM_3","PARAMETER_CODE_4","PARAMETER_VALUE_4","PARAMETER_UOM_4","PARAMETER_CODE_5","PARAMETER_VALUE_5","PARAMETER_UOM_5","PARAMETER_CODE_6","PARAMETER_VALUE_6","PARAMETER_UOM_6","PARAMETER_CODE_7","PARAMETER_VALUE_7","PARAMETER_UOM_7"
+"COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","UOM_CODE","SOURCE_GEOGCRS_CODE","COORD_OP_CODE","COORD_OP_METHOD_CODE","SHOW_CRS","DEPRECATED","COORD_SYS_CODE","PARAMETER_CODE_1","PARAMETER_VALUE_1","PARAMETER_UOM_1","PARAMETER_CODE_2","PARAMETER_VALUE_2","PARAMETER_UOM_2","PARAMETER_CODE_3","PARAMETER_VALUE_3","PARAMETER_UOM_3","PARAMETER_CODE_4","PARAMETER_VALUE_4","PARAMETER_UOM_4","PARAMETER_CODE_5","PARAMETER_VALUE_5","PARAMETER_UOM_5","PARAMETER_CODE_6","PARAMETER_VALUE_6","PARAMETER_UOM_6","PARAMETER_CODE_7","PARAMETER_VALUE_7","PARAMETER_UOM_7"
 #
 # NOTICE: The master version of this file is in the libgeotiff subversion at:
 #
@@ -10,5 +10,10 @@
 #
 # Adjust central meridian to be relative to prime meridian. 
 #
-26591,"Monte Mario (Rome) / Italy zone 1",9001,4806,18121,9807,1,0,8801,0,9102,8802,-3.45233333333333,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,
-26592,"Monte Mario (Rome) / Italy zone 2",9001,4806,18122,9807,1,0,8801,0,9102,8802,2.54766666666666,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,
+26591,"Monte Mario (Rome) / Italy zone 1",9001,4806,18121,9807,1,1,4499,8801,0,9102,8802,-3.45233333333333,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,
+26592,"Monte Mario (Rome) / Italy zone 2",9001,4806,18122,9807,1,1,4499,8801,0,9102,8802,2.54766666666666,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,
+#
+# 26799 is deprecated, because of the error in the false northing.  However,
+# we "fix" the original to reduce problems folks would otherwise encounter.
+#
+26799,"NAD27 / California zone VII",9003,4267,10408,9802,1,0,4497,8821,34.08,9110,8822,-118.2,9110,8823,34.25,9110,8824,33.52,9110,8826,4186692.58,9003,8827,4160926.74,9003,,,
diff --git a/data/projop_wparm.csv b/data/projop_wparm.csv
index 75dc292..0bd77a2 100644
--- a/data/projop_wparm.csv
+++ b/data/projop_wparm.csv
@@ -14,6 +14,19 @@
 3831,Pacific Disaster Center Mercator,9804,8801,0,9102,8802,150,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
 3853,County ST74,9807,8801,0,9110,8802,18.0328332,9110,8805,0.99999506,9201,8806,100182.7406,9001,8807,-6500620.1207,9001,,,,,,
 3856,Popular Visualisation Pseudo-Mercator,1024,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
+3860,Finland Gauss-Kruger zone 19,9807,8801,0,9102,8802,19,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
+3861,Finland Gauss-Kruger zone 20,9807,8801,0,9102,8802,20,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
+3862,Finland Gauss-Kruger zone 21,9807,8801,0,9102,8802,21,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
+3863,Finland Gauss-Kruger zone 22,9807,8801,0,9102,8802,22,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
+3864,Finland Gauss-Kruger zone 23,9807,8801,0,9102,8802,23,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
+3865,Finland Gauss-Kruger zone 24,9807,8801,0,9102,8802,24,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,
+3866,Finland Gauss-Kruger zone 25,9807,8801,0,9102,8802,25,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
+3867,Finland Gauss-Kruger zone 26,9807,8801,0,9102,8802,26,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
+3868,Finland Gauss-Kruger zone 27,9807,8801,0,9102,8802,27,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
+3869,Finland Gauss-Kruger zone 28,9807,8801,0,9102,8802,28,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
+3870,Finland Gauss-Kruger zone 29,9807,8801,0,9102,8802,29,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
+3871,Finland Gauss-Kruger zone 30,9807,8801,0,9102,8802,30,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
+3872,Finland Gauss-Kruger zone 31,9807,8801,0,9102,8802,31,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
 3897,US NSIDC Equal Area north projection,1027,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
 3898,US NSIDC Equal Area south projection,1027,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
 3899,US National Atlas Equal Area,1027,8801,45,9102,8802,-100,9102,8806,0,9001,8807,0,9001,,,,,,,,,
@@ -31,6 +44,23 @@
 4090,DKTM2,9807,8801,0,9102,8802,10,9102,8805,0.99998,9201,8806,400000,9001,8807,-5000000,9001,,,,,,
 4091,DKTM3,9807,8801,0,9102,8802,11.75,9102,8805,0.99998,9201,8806,600000,9001,8807,-5000000,9001,,,,,,
 4092,DKTM4,9807,8801,0,9102,8802,15,9102,8805,1,9201,8806,800000,9001,8807,-5000000,9001,,,,,,
+4101,"BLM zone 1N (US survey feet)",9807,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4102,"BLM zone 2N (US survey feet)",9807,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4103,"BLM zone 3N (US survey feet)",9807,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4104,"BLM zone 4N (US survey feet)",9807,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4105,"BLM zone 5N (US survey feet)",9807,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4106,"BLM zone 6N (US survey feet)",9807,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4107,"BLM zone 7N (US survey feet)",9807,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4108,"BLM zone 8N (US survey feet)",9807,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4109,"BLM zone 9N (US survey feet)",9807,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4110,"BLM zone 10N (US survey feet)",9807,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4111,"BLM zone 11N (US survey feet)",9807,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4112,"BLM zone 12N (US survey feet)",9807,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4113,"BLM zone 13N (US survey feet)",9807,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4118,"BLM zone 18N (US survey feet)",9807,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4119,"BLM zone 19N (US survey feet)",9807,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4186,"BLM zone 59N (US survey feet)",9807,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
+4187,"BLM zone 60N (US survey feet)",9807,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
 4325,Guam Map Grid,9807,8801,13.3,9110,8802,144.45,9110,8805,1,9201,8806,100000,9001,8807,200000,9001,,,,,,
 4416,Katanga Lambert,9802,8821,-9,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,500000,9001,8827,500000,9001,,,
 4436,Pennsylvania CS27 South zone,9802,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,2000000,9003,8827,0,9003,,,
@@ -38,6 +68,129 @@
 4460,Australian Centre for Remote Sensing Lambert Conformal Projection,9802,8821,-27,9102,8822,132,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,
 4648,UTM zone 32N with prefix,9807,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,32500000,9001,8807,0,9001,,,,,,
 4825,Cape Verde National,9802,8821,15.5,9110,8822,-24,9110,8823,15,9110,8824,16.4,9110,8826,161587.83,9001,8827,128511.202,9001,,,
+4838,LCC Germany,9802,8821,51,9102,8822,10.3,9110,8823,48.4,9110,8824,53.4,9110,8826,0,9001,8827,0,9001,,,
+4841,Norway TM zone 15,9807,8801,0,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4842,Norway TM zone 16,9807,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4843,Norway TM zone 17,9807,8801,0,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4844,Norway TM zone 18,9807,8801,0,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4845,Norway TM zone 5,9807,8801,0,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4846,Norway TM zone 6,9807,8801,0,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4847,Norway TM zone 7,9807,8801,0,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4848,Norway TM zone 8,9807,8801,0,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4849,Norway TM zone 9,9807,8801,0,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4850,Norway TM zone 10,9807,8801,0,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4851,Norway TM zone 11,9807,8801,0,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4852,Norway TM zone 12,9807,8801,0,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4853,Norway TM zone 13,9807,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4854,Norway TM zone 14,9807,8801,0,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+4881,Norway TM zone 19,9807,8801,0,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5000,Norway TM zone 20,9807,8801,0,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5001,Norway TM zone 21,9807,8801,0,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5002,Norway TM zone 22,9807,8801,0,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5003,Norway TM zone 23,9807,8801,0,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5004,Norway TM zone 24,9807,8801,0,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5005,Norway TM zone 25,9807,8801,0,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5006,Norway TM zone 26,9807,8801,0,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5007,Norway TM zone 27,9807,8801,0,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5008,Norway TM zone 28,9807,8801,0,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5009,Norway TM zone 29,9807,8801,0,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5010,Norway TM zone 30,9807,8801,0,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5019,Portugal Bonne New,9828,8801,39.4,9110,8802,-8.0754862,9110,8806,0,9001,8807,0,9001,,,,,,,,,
+5020,Portuguese Grid New,9807,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
+5049,Korea East Sea Belt,9807,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5068,Conus Albers,9822,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
+5100,Korea Unified Belt,9807,8801,38,9102,8802,127.3,9110,8805,0.9996,9201,8806,1000000,9001,8807,2000000,9001,,,,,,
+5101,Korea West Belt 2010,9807,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5102,Korea Central Belt 2010,9807,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5103,Korea East Belt 2010,9807,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5104,Korea East Sea Belt 2010,9807,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
+5131,Korea Central Belt Jeju,9807,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
+5135,Norway TM zone 5,9807,8801,58,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5136,Norway TM zone 6,9807,8801,58,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5137,Norway TM zone 7,9807,8801,58,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5138,Norway TM zone 8,9807,8801,58,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5139,Norway TM zone 9,9807,8801,58,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5140,Norway TM zone 10,9807,8801,58,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5141,Norway TM zone 11,9807,8801,58,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5142,Norway TM zone 12,9807,8801,58,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5143,Norway TM zone 13,9807,8801,58,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5144,Norway TM zone 14,9807,8801,58,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5145,Norway TM zone 15,9807,8801,58,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5146,Norway TM zone 16,9807,8801,58,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5147,Norway TM zone 17,9807,8801,58,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5148,Norway TM zone 18,9807,8801,58,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5149,Norway TM zone 19,9807,8801,58,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5150,Norway TM zone 20,9807,8801,58,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5151,Norway TM zone 21,9807,8801,58,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5152,Norway TM zone 22,9807,8801,58,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5153,Norway TM zone 23,9807,8801,58,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5154,Norway TM zone 24,9807,8801,58,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5155,Norway TM zone 25,9807,8801,58,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5156,Norway TM zone 26,9807,8801,58,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5157,Norway TM zone 27,9807,8801,58,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5158,Norway TM zone 28,9807,8801,58,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5159,Norway TM zone 29,9807,8801,58,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5160,Norway TM zone 30,9807,8801,58,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
+5161,Korea Modified West Belt,9807,8801,38,9102,8802,125.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5162,Korea Modified Central Belt,9807,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5163,Korea Modified Central Belt Jeju,9807,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
+5164,Korea Modified East Belt,9807,8801,38,9102,8802,129.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5165,Korea Modified East Sea Belt,9807,8801,38,9102,8802,131.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
+5218,Krovak East North,1041,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
+5219,Modified Krovak,1042,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5220,Modified Krovak East North,1043,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5222,Gabon Transverse Mercator,9807,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,500000,9001,,,,,,
+5231,Sri Lanka Grid,9807,8801,7.0001729,9110,8802,80.461816,9110,8805,0.9999238418,9201,8806,200000,9001,8807,200000,9001,,,,,,
+5232,Sri Lanka Grid 1999,9807,8801,7.00016975,9110,8802,80.46181671,9110,8805,0.9999238418,9201,8806,500000,9001,8807,500000,9001,,,,,,
+5265,Bhutan National Grid,9807,8801,0,9102,8802,90,9102,8805,1,9201,8806,250000,9001,8807,0,9001,,,,,,
+5268,Bumthang TM,9807,8801,0,9110,8802,90.44,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5276,Chhukha TM,9807,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5277,Dagana TM,9807,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5278,Gasa TM,9807,8801,0,9110,8802,90.02,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5279,Ha TM,9807,8801,0,9110,8802,90.09,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5280,Lhuentse TM,9807,8801,0,9110,8802,91.08,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5281,Mongar TM,9807,8801,0,9110,8802,91.14,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5282,Paro TM,9807,8801,0,9110,8802,89.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5283,Pemagatshel TM,9807,8801,0,9110,8802,91.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5284,Tsirang TM,9807,8801,0,9110,8802,90.1,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5285,Samdrup Jongkhar TM,9807,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5286,Samtse TM,9807,8801,0,9110,8802,89.04,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5287,Sarpang TM,9807,8801,0,9110,8802,90.16,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5288,Wangdue Phodrang TM,9807,8801,0,9110,8802,90.07,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5289,Trashigang TM,9807,8801,0,9110,8802,91.45,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5290,Trongsa TM,9807,8801,0,9110,8802,90.3,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5291,Zhemgang TM,9807,8801,0,9110,8802,90.52,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5312,Thimphu TM,9807,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5313,Punakha TM,9807,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5314,Yangtse TM,9807,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
+5315,Faroe Transverse Mercator,9807,8801,0,9102,8802,-7,9102,8805,0.999997,9201,8806,200000,9001,8807,-6000000,9001,,,,,,
+5319,Teranet Ontario Lambert,9802,8821,0,9102,8822,-84,9102,8823,44.3,9110,8824,54.3,9110,8826,1000000,9001,8827,0,9001,,,
+5326,Iceland Lambert 2004,9802,8821,65,9110,8822,-19,9110,8823,64.15,9110,8824,65.45,9110,8826,1700000,9001,8827,300000,9001,,,
+5328,"Netherlands East Indies Equatorial Zone (Jkt)",9804,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
+5366,Costa Rica TM 2005,9807,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
+5390,Costa Rica Norte,9801,8801,10.28,9110,8802,-84.2,9110,8805,0.99995696,9201,8806,500000,9001,8807,271820.522,9001,,,,,,
+5394,Costa Rica Sur,9801,8801,9,9110,8802,-83.4,9110,8805,0.99995696,9201,8806,500000,9001,8807,327987.436,9001,,,,,,
+5397,Honduras Norte,9801,8801,15.3,9110,8802,-86.1,9110,8805,0.99993273,9201,8806,500000,9001,8807,296917.439,9001,,,,,,
+5398,Honduras Sur,9801,8801,13.47,9110,8802,-86.1,9110,8805,0.9999514,9201,8806,500000,9001,8807,296215.903,9001,,,,,,
+5399,El Salvador Lambert,9801,8801,13.47,9110,8802,-89,9110,8805,0.99996704,9201,8806,500000,9001,8807,295809.184,9001,,,,,,
+5439,Nicaragua Norte,9801,8801,13.52,9110,8802,-85.3,9110,8805,0.99990314,9201,8806,500000,9001,8807,359891.816,9001,,,,,,
+5444,Nicaragua Sur,9801,8801,11.44,9110,8802,-85.3,9110,8805,0.99992228,9201,8806,500000,9001,8807,288876.327,9001,,,,,,
+5465,Belize Colony Grid,9807,8801,17.0340471,9110,8802,-88.3754687,9110,8805,1,9201,8806,217259.26,9005,8807,445474.83,9005,,,,,,
+5468,Panama Lambert,9801,8801,8.25,9110,8802,-80,9110,8805,0.99989909,9201,8806,500000,9001,8807,294865.303,9001,,,,,,
+5471,Panama Polyconic,9818,8801,8.15,9110,8802,-81,9110,8806,1000000,9037,8807,1092972.1,9037,,,,,,,,,
+5475,McMurdo Sound Lambert Conformal 2000,9802,8821,-78,9110,8822,163,9110,8823,-76.4,9110,8824,-79.2,9110,8826,7000000,9001,8827,5000000,9001,,,
+5476,Borchgrevink Coast Lambert Conformal 2000,9802,8821,-74.3,9110,8822,165,9110,8823,-73.4,9110,8824,-75.2,9110,8826,5000000,9001,8827,3000000,9001,,,
+5477,Pennell Coast Lambert Conformal 2000,9802,8821,-71.3,9110,8822,166,9110,8823,-70.4,9110,8824,-72.2,9110,8826,3000000,9001,8827,1000000,9001,,,
+5478,Ross Sea Polar Stereographic 2000,9810,8801,-90,9102,8802,180,9102,8805,0.994,9201,8806,5000000,9001,8807,1000000,9001,,,,,,
+5509,"Krovak (Greenwich)",9819,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
+5510,"Krovak East North (Greenwich)",1041,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
+5511,"Modified Krovak (Greenwich)",1042,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5512,"Modified Krovak East North (Greenwich)",1043,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
+5517,Chatham Islands Map Grid,9807,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,
+5522,Gabon Transverse Mercator 2011,9807,8801,0,9102,8802,11.3,9110,8805,0.9996,9201,8806,1500000,9001,8807,5500000,9001,,,,,,
+5547,Papua New Guinea Map Grid 1994 zone 54,9807,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5548,Papua New Guinea Map Grid 1994 zone 55,9807,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+5549,Papua New Guinea Map Grid 1994 zone 56,9807,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 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,,,,,,
@@ -1124,7 +1277,7 @@
 17625,South West African Survey Grid zone 25,9808,8801,-22,9102,8802,25,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
 17700,MTM Quebec zone 2,9807,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 17701,MTM zone 1,9807,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-17702,MTM Newfoundland zone 2,9807,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
+17702,MTM zone 2,9807,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 17703,MTM zone 3,9807,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 17704,MTM zone 4,9807,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
 17705,MTM zone 5,9807,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
@@ -1497,7 +1650,7 @@
 19891,Pahang Grid,9806,8801,3.460979712,9110,8802,102.220587634,9110,8806,-7368.228,9001,8807,6485.858,9001,,,,,,,,,
 19892,Sembilan and Melaka Grid,9806,8801,2.405645149,9110,8802,101.582965815,9110,8806,3673.785,9001,8807,-4240.573,9001,,,,,,,,,
 19893,Johor Grid,9806,8801,2.071804708,9110,8802,103.254057045,9110,8806,-14810.562,9001,8807,8758.32,9001,,,,,,,,,
-19894,East Malaysia BRSO,9812,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201
+19894,Borneo RSO,9812,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201
 19895,Peninsular RSO,9812,8806,804671,9001,8807,0,9001,8811,4,9110,8812,102.15,9110,8813,323.013286728,9110,8814,323.07483685,9110,8815,0.99984,9201
 19896,Hong Kong 1963 Grid,9806,8801,22.184368,9110,8802,114.10428,9110,8806,132033.92,9005,8807,62565.96,9005,,,,,,,,,
 19897,Statistics Canada Lambert,9802,8821,63.390675,9102,8822,-91.52,9110,8823,49,9102,8824,77,9102,8826,6200000,9001,8827,3000000,9001,,,
@@ -1531,7 +1684,7 @@
 19927,Stereo 33,9809,8801,45.54,9110,8802,25.23328772,9110,8805,0.9996667,9201,8806,500000,9001,8807,500000,9001,,,,,,
 19928,Kuwait TM,9807,8801,0,9102,8802,48,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 19929,Sweden zone 2.5 gon V,9807,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-19930,Greek Grid,9807,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
+19930,Greek Grid,9807,8801,0,9102,8802,24,9110,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 19931,Egyseges Orszagos Vetuleti,9815,8811,47.08398174,9110,8812,19.02548584,9110,8813,90,9110,8814,90,9110,8815,0.99993,9201,8816,650000,9001,8817,200000,9001
 19933,"Prince Edward Island Stereographic (ATS77)",9809,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,700000,9001,8807,400000,9001,,,,,,
 19934,Lithuania 1994,9807,8801,0,9102,8802,24,9102,8805,0.9998,9201,8806,500000,9001,8807,0,9001,,,,,,
@@ -1552,7 +1705,7 @@
 19949,Levant Stereographic,9809,8801,38,9105,8802,43.5,9105,8805,0.9995341,9201,8806,0,9001,8807,0,9001,,,,,,
 19950,Swiss Oblique Mercator 1995,9815,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,2600000,9001,8817,1200000,9001
 19951,Nakhl e Taqi Oblique Mercator,9815,8811,27.31077837,9110,8812,52.3612741,9110,8813,0.34179803,9110,8814,0.34179803,9110,8815,0.999895934,9201,8816,658377.437,9001,8817,3044969.194,9001
-19952,Krovak,9819,8806,0,9001,8807,0,9001,8811,49.3,9110,8813,30.1717303,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
+19952,Krovak,9819,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
 19953,Qatar Grid,9806,8801,25.22565,9110,8802,50.4541,9110,8806,100000,9001,8807,100000,9001,,,,,,,,,
 19954,Suriname Old TM,9807,8801,0,9110,8802,-55.41,9110,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
 19955,Suriname TM,9807,8801,0,9110,8802,-55.41,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
diff --git a/data/unit_of_measure.csv b/data/unit_of_measure.csv
index f99b5eb..f261018 100644
--- a/data/unit_of_measure.csv
+++ b/data/unit_of_measure.csv
@@ -36,7 +36,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 6415e87..41cf4f6 100644
--- a/data/vertcs.csv
+++ b/data/vertcs.csv
@@ -1,8 +1,14 @@
 "COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","DATUM_CODE","DATUM_NAME","UOM_CODE","SHOW_CRS","DEPRECATED","COORD_SYS_CODE","COORD_OP_METHOD_CODE_1","PARM_1_1"
 3855,EGM2008 geoid height,1027,EGM2008 geoid,9001,1,0,6499,9665,"egm08_25.gtx"
 3886,Fao 1979 height,1028,Fao 1979,9001,1,0,6499,,
+3900,N2000 height,1030,N2000,9001,1,0,6499,,
 4440,NZVD2009 height,1039,New Zealand Vertical Datum 2009,9001,1,0,6499,,
 4458,Dunedin-Bluff 1960 height,1040,Dunedin-Bluff 1960,9001,1,0,6499,,
+5193,Incheon height,1049,Incheon,9001,1,0,6499,,
+5195,Trieste height,1050,Trieste,9001,1,0,6499,,
+5214,Genoa height,1051,Genoa,9001,1,0,6499,,
+5237,SLVD height,1054,Sri Lanka Vertical Datum,9001,1,0,6499,,
+5317,FVR09 height,1059,Faroe Islands Vertical Reference 2009,9001,1,0,6499,,
 5600,NGPF height,5195,Nivellement General de Polynesie Francaise,9001,1,0,6499,,
 5601,IGN 1966 height,5196,IGN 1966,9001,1,0,6499,,
 5602,Moorea SAU 1981 height,5197,Moorea SAU 1981,9001,1,0,6499,,
diff --git a/doc/br/index_br.dox b/doc/br/index_br.dox
index 9e8de47..acd8059 100644
--- a/doc/br/index_br.dox
+++ b/doc/br/index_br.dox
@@ -1,129 +1,129 @@
-#ifndef DOXYGEN_SKIP                                                            
-/* $Id: index_br.dox $ */               
-Translation corresponds to index.dox "11836 2007-08-02 21:24:45Z warmerdam"
-Translator Ivan Lucena <ivan.lucena at pmldnet.com>
-#endif /* DOXYGEN_SKIP */                                                       
-
-/*! \page index_br GDAL - Biblioteca de Abstracoes de Dados Geo-Espaciais
-
-<center>
-<b>Selecione o idioma</b>: 
-<a href="index.html">[English] </a>
-<a href="index_ru.html">[Russian] </a>
-[Portuguese]
-<a href="http://softlibre.gloobe.org/doku.php?id=gdal_ogr:couteau_suisse:start">[Frances]</a>
-</center>
-
-\htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL \endlatexonly
-é uma bibliotéca para tradução de formatos de dados geográficos distribuída pela 
-<a href="http://www.osgeo.org/">Open Source Geospatial Foundation</a> sob a licença 
-<a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a> estilo
-<a href="http://www.opensource.org/"> Open Source</a>. 
-As aplicações que à utilizam acessam todos os formats 
-supportados pela biblioteca através de 
-\link gdal_datamodel_br.html um único modelo de dados abstrato\endlink.
-A bilioteca GDAL também conta com uma variadade de programas 
-<a class="el" href="gdal_utilities.html"> utilitários de linha de comando</a>
-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.7.3-News">novidades</a> descreve o 
-lançamento em Novembro de 2010 da release 1.7.3 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).
-
-Página Principal: http://www.gdal.org<br>
-Download: 
- <a href="ftp://ftp.remotesensing.org/gdal">ftp at remotesensing.org</a>,
- <a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>
-
-\section index_userdocs Documentacao para usuario
-
-<ul>
-<li> <a href="http://trac.osgeo.org/gdal/">Wiki</a> - Documentação e dicas mantidas por vários desenvolvedores e contribuidores
-<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">Downloads</a> - Programas executáveis prontos para usar
-<li> <a href="formats_list.html">Formatos Suportados</a>
-<li> <a href="gdal_utilities.html">Programs Utilitários</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">Perguntas Mais Frequentes</a>
-<li> <a href="gdal_datamodel_br.html">Modelo de dados</a> <b>(em português)</b>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">Governança e participação comunitária</a>
-<li> <a href="credits.html">Patrocinadores, Agradecimentos e Créditos</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/SoftwareUsingGdal">Software que usam GDAL</a>
-</ul>
-
-\section index_devdocs Documentacao para desenvolvedor
-
-<ul>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">Como compilar GDAL</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Downloads</a> - código fonte
-<li> <a href="hierarchy.html">Documentação de referencia da API</a>
-<li> <a href="gdal_tutorial_br.html">Tutorial da API do GDAL</a> <b>(em português)</b>
-<li> <a href="gdal_drivertut.html">Tutorial de implementação de drivers</a>
-<li> <a href="warptut.html">Tutorial de transformação geométrica</a>
-<li> <a href="ogr/osr_tutorial.html">Tutorial de Referência Espacial</a>
-<li> <a href="gdal_8h.html">GDAL API para C</a>
-<li> <a href="classGDALDataset.html">GDALDataset</a>
-<li> <a href="classGDALRasterBand.html">GDALRasterBand</a>
-<li> <a href="wince.html">GDAL para Windows CE</a>
-</ul>
-
-\section foss4g Conferencial
-\htmlonly
-<table border="0" cellspacing="4" cellpadding="4"> 
-  <tr>
-  <td>
-    <a href="http://www.foss4g2010.org/"> 
-      <img src="http://2010.foss4g.org/images/logo_125x125.jpg" alt="" border="0" width="125" height="125"> 
-    </a>
-  </td> 
-  <td><a href="http://www.foss4g2010.org">FOSS4G 2010</a> é a mais 
-    importante conferência anual de software geospatial livre, incluindo 
-    apresentações sobre GDAL/OGR, com a presença de parte 
-    da communidade de desenvolvedores do GDAL/OGR. É o principal evento 
-    para aqueles interessados em GDA/OGR e outras tecnologias FOSS geospatial 
-    relacionadas.
-  </td> 
-</table> 
-\endhtmlonly
-
-\section index_maillist Lista de discussao por correio eletronico
-
-A lista <a href="http://lists.osgeo.org/mailman/listinfo/gdal-announce">gdal-announce</a>
-é uma lista de pequeno volume de mensagens usada somente para anunciar lançamento de 
-versões e desenvolvimentos significativos.
-
-A lista <a href="mailto:gdal-dev at lists.maptools.org">gdal-dev at lists.maptools.org</a>
-pode ser usada para a discussão sobre o desenvolvimento e uso da GDAL e tecnologias relaciadas.
-A inscrição e o acesso aos arquivo da lista podem ser feitos 
-<a href="http://lists.maptools.org/mailman/listinfo/gdal-dev/"> nesta página</a>. 
-Os arquivos da lista também estão disponíveis (somente para leitura) através do
-<a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
-ou na página 
-<a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
-
-Usuários e desenvolvedores da GDAL/OGR podem constantemente ser achados no canal IRC 
-<a href="irc://irc.freenode.net/#gdal">#gdal</a> do irc.freenode.net.<p>
-
-\section index_bugs Como Reportar Problemas (Bugs)
-
-Bugs em GDAL podem ser 
-<a href="http://trac.osgeo.org/gdal/newticket">reportados</a> e também 
-<a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">listados</a> através do software Trac.<p>
-
-\section index_bindings GDAL em outras linguagens
-
-Lista de linguagens de programção supportadas por GDAL:
-
-<ul>
-<li> <a href="http://map.hut.fi/gdal-perl/">Perl</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">Python</a>
-<li> <a href="vb6_tutorial.html">VB6 Bindings</a> (sem o uso de SWIG)
-<li> <a href="http://rgdal.sourceforge.net/">GDAL interface para 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>
-
-</ul>
-
-*/
+#ifndef DOXYGEN_SKIP                                                            
+/* $Id: index_br.dox $ */               
+Translation corresponds to index.dox "11836 2007-08-02 21:24:45Z warmerdam"
+Translator Ivan Lucena <ivan.lucena at pmldnet.com>
+#endif /* DOXYGEN_SKIP */                                                       
+
+/*! \page index_br GDAL - Biblioteca de Abstracoes de Dados Geo-Espaciais
+
+<center>
+<b>Selecione o idioma</b>: 
+<a href="index.html">[English] </a>
+<a href="index_ru.html">[Russian] </a>
+[Portuguese]
+<a href="http://softlibre.gloobe.org/doku.php?id=gdal_ogr:couteau_suisse:start">[Frances]</a>
+</center>
+
+\htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL \endlatexonly
+é uma bibliotéca para tradução de formatos de dados geográficos distribuída pela 
+<a href="http://www.osgeo.org/">Open Source Geospatial Foundation</a> sob a licença 
+<a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a> estilo
+<a href="http://www.opensource.org/"> Open Source</a>. 
+As aplicações que à utilizam acessam todos os formats 
+supportados pela biblioteca através de 
+\link gdal_datamodel_br.html um único modelo de dados abstrato\endlink.
+A bilioteca GDAL também conta com uma variadade de programas 
+<a class="el" href="gdal_utilities.html"> utilitários de linha de comando</a>
+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.8.0-News">novidades</a> descreve o 
+lançamento em Janeiro de 2011 da release 1.8.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).
+
+Página Principal: http://www.gdal.org<br>
+Download: 
+ <a href="ftp://ftp.remotesensing.org/gdal">ftp at remotesensing.org</a>,
+ <a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>
+
+\section index_userdocs Documentacao para usuario
+
+<ul>
+<li> <a href="http://trac.osgeo.org/gdal/">Wiki</a> - Documentação e dicas mantidas por vários desenvolvedores e contribuidores
+<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">Downloads</a> - Programas executáveis prontos para usar
+<li> <a href="formats_list.html">Formatos Suportados</a>
+<li> <a href="gdal_utilities.html">Programs Utilitários</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">Perguntas Mais Frequentes</a>
+<li> <a href="gdal_datamodel_br.html">Modelo de dados</a> <b>(em português)</b>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">Governança e participação comunitária</a>
+<li> <a href="credits.html">Patrocinadores, Agradecimentos e Créditos</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/SoftwareUsingGdal">Software que usam GDAL</a>
+</ul>
+
+\section index_devdocs Documentacao para desenvolvedor
+
+<ul>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">Como compilar GDAL</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Downloads</a> - código fonte
+<li> <a href="hierarchy.html">Documentação de referencia da API</a>
+<li> <a href="gdal_tutorial_br.html">Tutorial da API do GDAL</a> <b>(em português)</b>
+<li> <a href="gdal_drivertut.html">Tutorial de implementação de drivers</a>
+<li> <a href="warptut.html">Tutorial de transformação geométrica</a>
+<li> <a href="ogr/osr_tutorial.html">Tutorial de Referência Espacial</a>
+<li> <a href="gdal_8h.html">GDAL API para C</a>
+<li> <a href="classGDALDataset.html">GDALDataset</a>
+<li> <a href="classGDALRasterBand.html">GDALRasterBand</a>
+<li> <a href="wince.html">GDAL para Windows CE</a>
+</ul>
+
+\section foss4g Conferencial
+\htmlonly
+<table border="0" cellspacing="4" cellpadding="4"> 
+  <tr>
+  <td>
+    <a href="http://2011.foss4g.org/"> 
+      <img src="http://wiki.osgeo.org/images/7/72/Foss4g_2011_150px.png" alt="" border="0" width="125" height="125"> 
+    </a>
+  </td> 
+  <td><a href="http://www.foss4g2010.org">FOSS4G 2011</a> é a mais 
+    importante conferência anual de software geospatial livre, incluindo 
+    apresentações sobre GDAL/OGR, com a presença de parte 
+    da communidade de desenvolvedores do GDAL/OGR. É o principal evento 
+    para aqueles interessados em GDA/OGR e outras tecnologias FOSS geospatial 
+    relacionadas.
+  </td> 
+</table> 
+\endhtmlonly
+
+\section index_maillist Lista de discussao por correio eletronico
+
+A lista <a href="http://lists.osgeo.org/mailman/listinfo/gdal-announce">gdal-announce</a>
+é uma lista de pequeno volume de mensagens usada somente para anunciar lançamento de 
+versões e desenvolvimentos significativos.
+
+A lista <a href="mailto:gdal-dev at lists.maptools.org">gdal-dev at lists.maptools.org</a>
+pode ser usada para a discussão sobre o desenvolvimento e uso da GDAL e tecnologias relaciadas.
+A inscrição e o acesso aos arquivo da lista podem ser feitos 
+<a href="http://lists.maptools.org/mailman/listinfo/gdal-dev/"> nesta página</a>. 
+Os arquivos da lista também estão disponíveis (somente para leitura) através do
+<a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
+ou na página 
+<a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
+
+Usuários e desenvolvedores da GDAL/OGR podem constantemente ser achados no canal IRC 
+<a href="irc://irc.freenode.net/#gdal">#gdal</a> do irc.freenode.net.<p>
+
+\section index_bugs Como Reportar Problemas (Bugs)
+
+Bugs em GDAL podem ser 
+<a href="http://trac.osgeo.org/gdal/newticket">reportados</a> e também 
+<a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">listados</a> através do software Trac.<p>
+
+\section index_bindings GDAL em outras linguagens
+
+Lista de linguagens de programção supportadas por GDAL:
+
+<ul>
+<li> <a href="http://map.hut.fi/gdal-perl/">Perl</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/GdalOgrInPython">Python</a>
+<li> <a href="vb6_tutorial.html">VB6 Bindings</a> (sem o uso de SWIG)
+<li> <a href="http://rgdal.sourceforge.net/">GDAL interface para 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>
+
+</ul>
+
+*/
diff --git a/doc/gdal_polygonize.dox b/doc/gdal_polygonize.dox
index 54b740f..e36adc0 100644
--- a/doc/gdal_polygonize.dox
+++ b/doc/gdal_polygonize.dox
@@ -3,14 +3,14 @@
 
 produces a polygon feature layer from a raster 
 
-\section synopsis SYNOPSIS
+\section gdal_polygonize_synopsis SYNOPSIS
 
 \verbatim
 gdal_polygonize.py [-o name=value] [-nomask] [-mask filename] raster_file [-b band]
                 [-q] [-f ogr_format] out_file [layer] [fieldname]
 \endverbatim
 
-\section description DESCRIPTION
+\section gdal_polygonize_description DESCRIPTION
 
 This utility creates vector polygons for all connected regions of pixels in
 the raster sharing a common pixel value.  Each polygon is created with an 
@@ -70,7 +70,7 @@ messages are not displayed.
 </dl>
 
 \if man
-\section author AUTHORS
+\section gdal_polygonize_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
diff --git a/doc/gdal_proximity.dox b/doc/gdal_proximity.dox
index d818554..54fa534 100755
--- a/doc/gdal_proximity.dox
+++ b/doc/gdal_proximity.dox
@@ -3,7 +3,7 @@
 
 produces a raster proximity map
 
-\section synopsis SYNOPSIS
+\section gdal_proximity_synopsis SYNOPSIS
 
 \verbatim
 gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n] 
@@ -13,7 +13,7 @@ gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n]
                   [-maxdist n] [-nodata n] [-fixed-buf-val n]
 \endverbatim
 
-\section description DESCRIPTION
+\section gdal_proximity_description DESCRIPTION
 
 The gdal_proximity.py script generates a raster proximity map indicating
 the distance from the center of each pixel to the center of the nearest 
@@ -66,7 +66,7 @@ Specify a value to be applied to all pixels that are within the -maxdist of targ
 </dl>
 
 \if man
-\section author AUTHORS
+\section gdal_proximity_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
diff --git a/doc/index.dox b/doc/index.dox
index 5974192..f9d7246 100644
--- a/doc/index.dox
+++ b/doc/index.dox
@@ -1,10 +1,10 @@
 #ifndef DOXYGEN_SKIP                                                            
-/* $Id: index.dox 21116 2010-11-11 11:52:10Z rouault $ */               
+/* $Id: index.dox 23318 2011-11-04 21:06:43Z rouault $ */               
 #endif /* DOXYGEN_SKIP */                                                       
 
 /*! \mainpage GDAL - Geospatial Data Abstraction Library
 
-<center><b>Select language</b>: [English]<a href="index_ru.html">[Russian]</a><a href="index_br.html">[Portuguese]</a><a href="http://georezo.net/wiki/main:logiciels:gdal_ogr">[French/Francais]</a></center>
+<center><b>Select language</b>: [English]<a href="index_ru.html">[Russian]</a><a href="index_br.html">[Portuguese]</a><a href="http://gdal.gloobe.org/">[French/Francais]</a></center>
 
 \htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL \endlatexonly
 is a translator library for raster geospatial data formats
@@ -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.7.3-News">NEWS</a>
-page describes the November 2010 GDAL/OGR 1.7.3 release.
+<a href="http://trac.osgeo.org/gdal/wiki/Release/1.8.1-News">NEWS</a>
+page describes the July 2011 GDAL/OGR 1.8.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,24 +59,6 @@ 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://2010.foss4g.org/"> 
-<img src="http://2010.foss4g.org/images/logo_125x125.jpg" alt="" border="0" width="125" height="125"> 
-</a></td> 
- 
-<td><a href="http://2010.foss4g.org">FOSS4G 2010</a> is the leading annual  
-conference for free and open source geospatial software.  It will include  
-workshops and 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
@@ -89,7 +71,8 @@ reviewed <a href="http://lists.osgeo.org/mailman/listinfo/gdal-dev/">on
 the web</a>.  The mailing list is also available in read-only format by NNTP at
 <a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
 and by HTTP at
-<a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
+<a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.
+Archives since 2005 are searchable on <a href="http://osgeo-org.1803224.n2.nabble.com/GDAL-Dev-f2022644.html">Nabble</a>.<p>
 
 Some GDAL/OGR users and developers can also often be found in the 
 <a href="irc://irc.freenode.net/#gdal">#gdal</a> IRC channel on irc.freenode.net.<p>
diff --git a/doc/sponsorship.dox b/doc/sponsorship.dox
index cf6bfb7..baabe5c 100644
--- a/doc/sponsorship.dox
+++ b/doc/sponsorship.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: sponsorship.dox 10411 2006-11-29 02:35:53Z fwarmerdam $ */
+/* $Id: sponsorship.dox 23132 2011-09-29 18:18:54Z warmerdam $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -82,12 +82,12 @@ and  sponsorships will be eligible as a charitable contribution for US
 taxpayers.  Appropriate receipts can be issued when needed.
 
 Organizations or individuals interested in sponsoring the GDAL/OGR project
-should contact Frank Warmerdam (warmerdam at pobox.com, +1 613 754 2041) with 
+should contact Frank Warmerdam (warmerdam at pobox.com, +1 650 701-7823) with 
 questions, or to make arrangements.  
 
 \htmlonly
 <p>
-$Id: sponsorship.dox 10411 2006-11-29 02:35:53Z fwarmerdam $
+$Id: sponsorship.dox 23132 2011-09-29 18:18:54Z warmerdam $
 </p>
 \endhtmlonly
 
diff --git a/frmts/aaigrid/aaigriddataset.cpp b/frmts/aaigrid/aaigriddataset.cpp
index 271af7c..0aefa64 100644
--- a/frmts/aaigrid/aaigriddataset.cpp
+++ b/frmts/aaigrid/aaigriddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aaigriddataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: aaigriddataset.cpp 23297 2011-10-31 11:41:52Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements Arc/Info ASCII Grid Format.
@@ -33,15 +33,22 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: aaigriddataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: aaigriddataset.cpp 23297 2011-10-31 11:41:52Z rouault $");
 
 CPL_C_START
 void    GDALRegister_AAIGrid(void);
+void    GDALRegister_GRASSASCIIGrid(void);
 CPL_C_END
 
 static CPLString OSR_GDS( char **papszNV, const char * pszField, 
                            const char *pszDefaultValue );
 
+typedef enum
+{
+    FORMAT_AAIG,
+    FORMAT_GRASSASCII
+} GridFormat;
+
 /************************************************************************/
 /* ==================================================================== */
 /*                              AAIGDataset                             */
@@ -56,13 +63,10 @@ class CPL_DLL AAIGDataset : public GDALPamDataset
     
     VSILFILE   *fp;
 
-    double      adfGeoTransform[6];
     char        **papszPrj;
     CPLString   osPrjFilename;
     char        *pszProjection;
 
-    int         bNoDataSet;
-    double      dfNoDataValue;
 
     unsigned char achReadBuf[256];
     GUIntBig    nBufferOffset;
@@ -72,15 +76,31 @@ class CPL_DLL AAIGDataset : public GDALPamDataset
     GUIntBig    Tell();
     int         Seek( GUIntBig nOffset );
 
+  protected:
+    GDALDataType eDataType;
+    double      adfGeoTransform[6];
+    int         bNoDataSet;
+    double      dfNoDataValue;
+    
+
+    virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
+
   public:
                 AAIGDataset();
                 ~AAIGDataset();
 
     virtual char **GetFileList(void);
 
+    static GDALDataset *CommonOpen( GDALOpenInfo * poOpenInfo,
+                                    GridFormat eFormat );
+
     static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
     static CPLErr       Delete( const char *pszFilename );
     static CPLErr       Remove( const char *pszFilename, int bRepError );
+    static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                                int bStrict, char ** papszOptions,
+                                GDALProgressFunc pfnProgress, void * pProgressData );
 
     virtual CPLErr GetGeoTransform( double * );
     virtual const char *GetProjectionRef(void);
@@ -88,6 +108,23 @@ class CPL_DLL AAIGDataset : public GDALPamDataset
 
 /************************************************************************/
 /* ==================================================================== */
+/*                        GRASSASCIIDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class GRASSASCIIDataset : public AAIGDataset
+{
+    virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
+
+  public:
+                GRASSASCIIDataset() : AAIGDataset() {}
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
 /*                            AAIGRasterBand                             */
 /* ==================================================================== */
 /************************************************************************/
@@ -100,7 +137,7 @@ class AAIGRasterBand : public GDALPamRasterBand
 
   public:
 
-                   AAIGRasterBand( AAIGDataset *, int, GDALDataType );
+                   AAIGRasterBand( AAIGDataset *, int );
     virtual       ~AAIGRasterBand();
 
     virtual double GetNoDataValue( int * );
@@ -112,14 +149,13 @@ class AAIGRasterBand : public GDALPamRasterBand
 /*                           AAIGRasterBand()                            */
 /************************************************************************/
 
-AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDS, int nDataStart, 
-                                GDALDataType eTypeIn )
+AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDS, int nDataStart )
 
 {
     this->poDS = poDS;
 
     nBand = 1;
-    eDataType = eTypeIn;
+    eDataType = poDS->eDataType;
 
     nBlockXSize = poDS->nRasterXSize;
     nBlockYSize = 1;
@@ -157,8 +193,8 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     AAIGDataset *poODS = (AAIGDataset *) poDS;
     int         iPixel;
 
-    if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1 
-        || nBlockXOff != 0 || panLineOffset == NULL)
+    if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1
+        || nBlockXOff != 0 || panLineOffset == NULL || poODS->fp == NULL )
         return CE_Failure;
 
     if( panLineOffset[nBlockYOff] == 0 )
@@ -286,6 +322,7 @@ AAIGDataset::AAIGDataset()
     papszPrj = NULL;
     pszProjection = CPLStrdup("");
     fp = NULL;
+    eDataType = GDT_Int32;
     bNoDataSet = FALSE;
     dfNoDataValue = -9999.0;
 
@@ -377,37 +414,16 @@ char **AAIGDataset::GetFileList()
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                            Identify()                                */
 /************************************************************************/
 
-GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
+int AAIGDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-    int i = 0;
-    int j = 0;
-    char **papszTokens = NULL;
-
-    /* Default data type */
-    GDALDataType eDataType = GDT_Int32;
-
-    const char* pszDataType = CPLGetConfigOption("AAIGRID_DATATYPE", NULL);
-    if (pszDataType != NULL)
-    {
-        eDataType = GDALGetDataTypeByName(pszDataType);
-        if (!(eDataType == GDT_Int32 || eDataType == GDT_Float32 ||
-              eDataType == GDT_Float64))
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                     "Unsupported value for AAIGRID_DATATYPE : %s", pszDataType);
-            eDataType = GDT_Int32;
-            pszDataType = NULL;
-        }
-    }
-
 /* -------------------------------------------------------------------- */
 /*      Does this look like an AI grid file?                            */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 100
+    if( poOpenInfo->nHeaderBytes < 40
         || !( EQUALN((const char *) poOpenInfo->pabyHeader,"ncols",5) ||
               EQUALN((const char *) poOpenInfo->pabyHeader,"nrows",5) ||
               EQUALN((const char *) poOpenInfo->pabyHeader,"xllcorner",9)||
@@ -417,23 +433,55 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
               EQUALN((const char *) poOpenInfo->pabyHeader,"dx",2)||
               EQUALN((const char *) poOpenInfo->pabyHeader,"dy",2)||
               EQUALN((const char *) poOpenInfo->pabyHeader,"cellsize",8)) )
-        return NULL;
+        return FALSE;
 
-    papszTokens =  
-        CSLTokenizeString2( (const char *) poOpenInfo->pabyHeader,
-                                  " \n\r\t", 0 );
-    int nTokens = CSLCount(papszTokens);
+    return TRUE;
+}
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
-    AAIGDataset         *poDS;
+/************************************************************************/
+/*                            Identify()                                */
+/************************************************************************/
 
-    poDS = new AAIGDataset();
+int GRASSASCIIDataset::Identify( GDALOpenInfo * poOpenInfo )
 
+{
 /* -------------------------------------------------------------------- */
-/*      Parse the header.                                               */
+/*      Does this look like a GRASS ASCII grid file?                    */
 /* -------------------------------------------------------------------- */
+    if( poOpenInfo->nHeaderBytes < 40
+        || !( EQUALN((const char *) poOpenInfo->pabyHeader,"north:",6) ||
+              EQUALN((const char *) poOpenInfo->pabyHeader,"south:",6) ||
+              EQUALN((const char *) poOpenInfo->pabyHeader,"east:",5)||
+              EQUALN((const char *) poOpenInfo->pabyHeader,"west:",5)||
+              EQUALN((const char *) poOpenInfo->pabyHeader,"rows:",5)||
+              EQUALN((const char *) poOpenInfo->pabyHeader,"cols:",5) ) )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+    return CommonOpen(poOpenInfo, FORMAT_AAIG);
+}
+
+/************************************************************************/
+/*                          ParseHeader()                               */
+/************************************************************************/
+
+int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
+{
+    int i, j;
+    char** papszTokens =
+        CSLTokenizeString2( pszHeader,  " \n\r\t" , 0 );
+    int nTokens = CSLCount(papszTokens);
     double dfCellDX = 0;
     double dfCellDY = 0;
 
@@ -441,48 +489,44 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
          i + 1 >= nTokens)
     {
         CSLDestroy( papszTokens );
-        delete poDS;
-        return NULL;
+        return FALSE;
     }
-    poDS->nRasterXSize = atoi(papszTokens[i + 1]);
+    nRasterXSize = atoi(papszTokens[i + 1]);
     if ( (i = CSLFindString( papszTokens, "nrows" )) < 0 ||
          i + 1 >= nTokens)
     {
         CSLDestroy( papszTokens );
-        delete poDS;
-        return NULL;
+        return FALSE;
     }
-    poDS->nRasterYSize = atoi(papszTokens[i + 1]);
+    nRasterYSize = atoi(papszTokens[i + 1]);
 
-    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
+    if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     {
-        delete poDS;
-        return NULL;
+        CSLDestroy( papszTokens );
+        return FALSE;
     }
 
     if ( (i = CSLFindString( papszTokens, "cellsize" )) < 0 )
     {
         int iDX, iDY;
-        if( (iDX = CSLFindString(papszTokens,"dx")) < 0 
+        if( (iDX = CSLFindString(papszTokens,"dx")) < 0
             || (iDY = CSLFindString(papszTokens,"dy")) < 0
             || iDX+1 >= nTokens
             || iDY+1 >= nTokens)
         {
             CSLDestroy( papszTokens );
-            delete poDS;
-            return NULL;
+            return FALSE;
         }
 
         dfCellDX = CPLAtofM( papszTokens[iDX+1] );
         dfCellDY = CPLAtofM( papszTokens[iDY+1] );
-    }    
+    }
     else
     {
         if (i + 1 >= nTokens)
         {
             CSLDestroy( papszTokens );
-            delete poDS;
-            return NULL;
+            return FALSE;
         }
         dfCellDX = dfCellDY = CPLAtofM( papszTokens[i + 1] );
     }
@@ -491,37 +535,48 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
         (j = CSLFindString( papszTokens, "yllcorner" )) >= 0 &&
         i + 1 < nTokens && j + 1 < nTokens)
     {
-        poDS->adfGeoTransform[0] = CPLAtofM( papszTokens[i + 1] );
-        poDS->adfGeoTransform[1] = dfCellDX;
-        poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
-            + poDS->nRasterYSize * dfCellDY;
-        poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = - dfCellDY;
+        adfGeoTransform[0] = CPLAtofM( papszTokens[i + 1] );
+       
+        /* Small hack to compensate from insufficient precision in cellsize */
+        /* parameter in datasets of http://ccafs-climate.org/data/A2a_2020s/hccpr_hadcm3 */
+        if ((nRasterXSize % 360) == 0 &&
+            fabs(adfGeoTransform[0] - (-180.0)) < 1e-12 &&
+            dfCellDX == dfCellDY &&
+            fabs(dfCellDX - (360.0 / nRasterXSize)) < 1e-9)
+        {
+            dfCellDX = dfCellDY = 360.0 / nRasterXSize;
+        }
+            
+        adfGeoTransform[1] = dfCellDX;
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
+            + nRasterYSize * dfCellDY;
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = - dfCellDY;
     }
     else if ((i = CSLFindString( papszTokens, "xllcenter" )) >= 0 &&
              (j = CSLFindString( papszTokens, "yllcenter" )) >= 0  &&
              i + 1 < nTokens && j + 1 < nTokens)
     {
-        poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
+        SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
 
-        poDS->adfGeoTransform[0] = CPLAtofM(papszTokens[i + 1]) - 0.5 * dfCellDX;
-        poDS->adfGeoTransform[1] = dfCellDX;
-        poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
+        adfGeoTransform[0] = CPLAtofM(papszTokens[i + 1]) - 0.5 * dfCellDX;
+        adfGeoTransform[1] = dfCellDX;
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
             - 0.5 * dfCellDY
-            + poDS->nRasterYSize * dfCellDY;
-        poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = - dfCellDY;
+            + nRasterYSize * dfCellDY;
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = - dfCellDY;
     }
     else
     {
-        poDS->adfGeoTransform[0] = 0.0;
-        poDS->adfGeoTransform[1] = dfCellDX;
-        poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = 0.0;
-        poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = - dfCellDY;
+        adfGeoTransform[0] = 0.0;
+        adfGeoTransform[1] = dfCellDX;
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = 0.0;
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = - dfCellDY;
     }
 
     if( (i = CSLFindString( papszTokens, "NODATA_value" )) >= 0 &&
@@ -529,23 +584,183 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         const char* pszNoData = papszTokens[i + 1];
 
-        poDS->bNoDataSet = TRUE;
-        poDS->dfNoDataValue = CPLAtofM(pszNoData);
+        bNoDataSet = TRUE;
+        dfNoDataValue = CPLAtofM(pszNoData);
         if( pszDataType == NULL &&
             (strchr( pszNoData, '.' ) != NULL ||
              strchr( pszNoData, ',' ) != NULL ||
-             INT_MIN > poDS->dfNoDataValue || poDS->dfNoDataValue > INT_MAX) )
+             INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
         {
             eDataType = GDT_Float32;
         }
         if( eDataType == GDT_Float32 )
         {
-            poDS->dfNoDataValue = (double) (float) poDS->dfNoDataValue;
+            dfNoDataValue = (double) (float) dfNoDataValue;
         }
     }
-    
+
     CSLDestroy( papszTokens );
 
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *GRASSASCIIDataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+    return CommonOpen(poOpenInfo, FORMAT_GRASSASCII);
+}
+
+
+/************************************************************************/
+/*                          ParseHeader()                               */
+/************************************************************************/
+
+int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
+{
+    int i;
+    char** papszTokens =
+        CSLTokenizeString2( pszHeader,  " \n\r\t:" , 0 );
+    int nTokens = CSLCount(papszTokens);
+    if ( (i = CSLFindString( papszTokens, "cols" )) < 0 ||
+         i + 1 >= nTokens)
+    {
+        CSLDestroy( papszTokens );
+        return FALSE;
+    }
+    nRasterXSize = atoi(papszTokens[i + 1]);
+    if ( (i = CSLFindString( papszTokens, "rows" )) < 0 ||
+         i + 1 >= nTokens)
+    {
+        CSLDestroy( papszTokens );
+        return FALSE;
+    }
+    nRasterYSize = atoi(papszTokens[i + 1]);
+
+    if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
+    {
+        CSLDestroy( papszTokens );
+        return FALSE;
+    }
+
+    int iNorth = CSLFindString( papszTokens, "north" );
+    int iSouth = CSLFindString( papszTokens, "south" );
+    int iEast = CSLFindString( papszTokens, "east" );
+    int iWest = CSLFindString( papszTokens, "west" );
+
+    if (iNorth == -1 || iSouth == -1 || iEast == -1 || iWest == -1 ||
+        MAX(MAX(iNorth, iSouth), MAX(iEast, iWest)) + 1 >= nTokens)
+    {
+        CSLDestroy( papszTokens );
+        return FALSE;
+    }
+
+    double dfNorth = CPLAtofM( papszTokens[iNorth + 1] );
+    double dfSouth = CPLAtofM( papszTokens[iSouth + 1] );
+    double dfEast = CPLAtofM( papszTokens[iEast + 1] );
+    double dfWest = CPLAtofM( papszTokens[iWest + 1] );
+    double dfPixelXSize = (dfEast - dfWest) / nRasterXSize;
+    double dfPixelYSize = (dfNorth - dfSouth) / nRasterYSize;
+
+    adfGeoTransform[0] = dfWest;
+    adfGeoTransform[1] = dfPixelXSize;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = dfNorth;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = - dfPixelYSize;
+
+    if( (i = CSLFindString( papszTokens, "null" )) >= 0 &&
+        i + 1 < nTokens)
+    {
+        const char* pszNoData = papszTokens[i + 1];
+
+        bNoDataSet = TRUE;
+        dfNoDataValue = CPLAtofM(pszNoData);
+        if( pszDataType == NULL &&
+            (strchr( pszNoData, '.' ) != NULL ||
+             strchr( pszNoData, ',' ) != NULL ||
+             INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
+        {
+            eDataType = GDT_Float32;
+        }
+        if( eDataType == GDT_Float32 )
+        {
+            dfNoDataValue = (double) (float) dfNoDataValue;
+        }
+    }
+
+    if( (i = CSLFindString( papszTokens, "type" )) >= 0 &&
+        i + 1 < nTokens)
+    {
+        const char* pszType = papszTokens[i + 1];
+        if (EQUAL(pszType, "int"))
+            eDataType = GDT_Int32;
+        else if (EQUAL(pszType, "float"))
+            eDataType = GDT_Float32;
+        else if (EQUAL(pszType, "double"))
+            eDataType = GDT_Float64;
+        else
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Invalid value for type parameter : %s", pszType);
+        }
+    }
+
+    CSLDestroy(papszTokens);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           CommonOpen()                               */
+/************************************************************************/
+
+GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
+                                            GridFormat eFormat )
+{
+    int i = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    AAIGDataset         *poDS;
+
+    if (eFormat == FORMAT_AAIG)
+        poDS = new AAIGDataset();
+    else
+        poDS = new GRASSASCIIDataset();
+
+
+    const char* pszDataTypeOption = (eFormat == FORMAT_AAIG) ? "AAIGRID_DATATYPE":
+                                                               "GRASSASCIIGRID_DATATYPE";
+    const char* pszDataType = CPLGetConfigOption(pszDataTypeOption, NULL);
+    if (pszDataType != NULL)
+    {
+        poDS->eDataType = GDALGetDataTypeByName(pszDataType);
+        if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 ||
+              poDS->eDataType == GDT_Float64))
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Unsupported value for %s : %s", pszDataTypeOption, pszDataType);
+            poDS->eDataType = GDT_Int32;
+            pszDataType = NULL;
+        }
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Parse the header.                                               */
+/* -------------------------------------------------------------------- */
+    if (!poDS->ParseHeader((const char *) poOpenInfo->pabyHeader, pszDataType))
+    {
+        delete poDS;
+        return NULL;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Open file with large file API.                                  */
 /* -------------------------------------------------------------------- */
@@ -597,11 +812,17 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     CPLAssert( NULL != poDS->fp );
 
-    if( pszDataType == NULL && eDataType != GDT_Float32)
+    if( pszDataType == NULL && poDS->eDataType != GDT_Float32)
     {
         /* Allocate 100K chunk + 1 extra byte for NULL character. */
         const size_t nChunkSize = 1024 * 100;
-        GByte* pabyChunk = (GByte *) CPLCalloc( nChunkSize + 1, sizeof(GByte) );
+        GByte* pabyChunk = (GByte *) VSICalloc( nChunkSize + 1, sizeof(GByte) );
+        if (pabyChunk == NULL)
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
+            delete poDS;
+            return NULL;
+        }
         pabyChunk[nChunkSize] = '\0';
 
         VSIFSeekL( poDS->fp, nStartOfData, SEEK_SET );
@@ -617,7 +838,7 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
                 GByte ch = pabyChunk[i];
                 if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E')
                 {
-                    eDataType = GDT_Float32;
+                    poDS->eDataType = GDT_Float32;
                     break;
                 }
             }
@@ -630,7 +851,7 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    AAIGRasterBand* band = new AAIGRasterBand( poDS, nStartOfData, eDataType );
+    AAIGRasterBand* band = new AAIGRasterBand( poDS, nStartOfData );
     poDS->SetBand( 1, band );
     if (band->panLineOffset == NULL)
     {
@@ -694,6 +915,11 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
@@ -719,11 +945,11 @@ const char *AAIGDataset::GetProjectionRef()
 }
 
 /************************************************************************/
-/*                        AAIGCreateCopy()                              */
+/*                          CreateCopy()                                */
 /************************************************************************/
 
-static GDALDataset *
-AAIGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
+GDALDataset * AAIGDataset::CreateCopy(
+                const char * pszFilename, GDALDataset *poSrcDS,
                 int bStrict, char ** papszOptions, 
                 GDALProgressFunc pfnProgress, void * pProgressData )
 
@@ -961,13 +1187,26 @@ AAIGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxilary pam information.         */
 /* -------------------------------------------------------------------- */
-    GDALPamDataset *poDS = (GDALPamDataset *) 
-        GDALOpen( pszFilename, GA_ReadOnly );
 
-    if( poDS )
+    /* If outputing to stdout, we can't reopen it, so we'll return */
+    /* a fake dataset to make the caller happy */
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    GDALPamDataset* poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
+    CPLPopErrorHandler();
+    if (poDS)
+    {
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+        return poDS;
+    }
 
-    return poDS;
+    CPLErrorReset();
+
+    AAIGDataset* poAAIG_DS = new AAIGDataset();
+    poAAIG_DS->nRasterXSize = nXSize;
+    poAAIG_DS->nRasterYSize = nYSize;
+    poAAIG_DS->nBands = 1;
+    poAAIG_DS->SetBand( 1, new AAIGRasterBand( poAAIG_DS, 1 ) );
+    return poAAIG_DS;
 }
 
 /************************************************************************/
@@ -1037,9 +1276,37 @@ void GDALRegister_AAIGrid()
 "</CreationOptionList>\n" );
 
         poDriver->pfnOpen = AAIGDataset::Open;
-        poDriver->pfnCreateCopy = AAIGCreateCopy;
+        poDriver->pfnIdentify = AAIGDataset::Identify;
+        poDriver->pfnCreateCopy = AAIGDataset::CreateCopy;
         
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
 }
 
+/************************************************************************/
+/*                   GDALRegister_GRASSASCIIGrid()                      */
+/************************************************************************/
+
+void GDALRegister_GRASSASCIIGrid()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "GRASSASCIIGrid" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "GRASSASCIIGrid" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "GRASS ASCII Grid" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                   "frmt_various.html#GRASSASCIIGrid" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnOpen = GRASSASCIIDataset::Open;
+        poDriver->pfnIdentify = GRASSASCIIDataset::Identify;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/frmts/adrg/srpdataset.cpp b/frmts/adrg/srpdataset.cpp
index a856b73..2886074 100644
--- a/frmts/adrg/srpdataset.cpp
+++ b/frmts/adrg/srpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: srpdataset.cpp 21640 2011-02-06 18:54:11Z warmerdam $
+ * $Id: srpdataset.cpp 23124 2011-09-27 16:55:26Z rouault $
  * Purpose:  ASRP/USRP Reader
  * Author:   Frank Warmerdam (warmerdam at pobox.com)
  *
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "iso8211.h"
 
-CPL_CVSID("$Id: srpdataset.cpp 21640 2011-02-06 18:54:11Z warmerdam $");
+CPL_CVSID("$Id: srpdataset.cpp 23124 2011-09-27 16:55:26Z rouault $");
 
 class SRPDataset : public GDALPamDataset
 {
@@ -306,7 +306,7 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
             while( nCount > 0 )
             {
-                ((GByte *) pImage)[iPixel++] = nValue;
+                ((GByte *) pImage)[iPixel++] = (GByte) nValue;
                 nCount--;
             }
         }
@@ -644,7 +644,7 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
                 {
                     return FALSE;
                 }
-                while(c ==' ' || c== '^')
+                while( c != 30 )
                 {
                     offsetInIMG ++;
                     if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
@@ -719,9 +719,9 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
                 nNSG = record->GetIntSubfield( "COL", 0, "NSG", iColor );
                 nNSB = record->GetIntSubfield( "COL", 0, "NSB", iColor );
 
-                sEntry.c1 = nNSR;
-                sEntry.c2 = nNSG;
-                sEntry.c3 = nNSB;
+                sEntry.c1 = (short) nNSR;
+                sEntry.c2 = (short) nNSG;
+                sEntry.c3 = (short) nNSB;
                 sEntry.c4 = 255;
 
                 oCT.SetColorEntry( nCCD, &sEntry );
diff --git a/frmts/aigrid/aigccitt.c b/frmts/aigrid/aigccitt.c
index 0085b93..37f770c 100644
--- a/frmts/aigrid/aigccitt.c
+++ b/frmts/aigrid/aigccitt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigccitt.c 16403 2009-02-23 21:55:44Z rouault $
+ * $Id: aigccitt.c 22640 2011-07-03 15:52:40Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Code for decoding CCITT RLE (G1) compressed data.
@@ -87,7 +87,7 @@ typedef struct {		/* state table entry */
 	GUInt32	Param;		/* unsigned 32-bit run length in bits */
 } TIFFFaxTabEnt;
 
-static const TIFFFaxTabEnt TIFFFaxMainTable[128] = {
+static const TIFFFaxTabEnt aig_TIFFFaxMainTable[128] = {
 {12,7,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},
 {2,3,0},{3,1,0},{4,3,1},{3,1,0},{5,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
 {1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{5,7,3},{3,1,0},{5,3,1},{3,1,0},
@@ -100,7 +100,7 @@ static const TIFFFaxTabEnt TIFFFaxMainTable[128] = {
 {2,3,0},{3,1,0},{4,3,1},{3,1,0},{4,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
 {1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0}
 };
-static const TIFFFaxTabEnt TIFFFaxWhiteTable[4096] = {
+static const TIFFFaxTabEnt aig_TIFFFaxWhiteTable[4096] = {
 {12,11,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
 {7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},
 {7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},
@@ -444,7 +444,7 @@ static const TIFFFaxTabEnt TIFFFaxWhiteTable[4096] = {
 {7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
 {7,5,10},{7,4,4},{7,4,2},{7,4,7}
 };
-static const TIFFFaxTabEnt TIFFFaxBlackTable[8192] = {
+static const TIFFFaxTabEnt aig_TIFFFaxBlackTable[8192] = {
 {12,11,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
 {8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
 {8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
@@ -1130,7 +1130,7 @@ static const TIFFFaxTabEnt TIFFFaxBlackTable[8192] = {
 {8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}
 };
 
-static const unsigned char TIFFBitRevTable[256] = {
+static const unsigned char aig_TIFFBitRevTable[256] = {
     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
@@ -1164,7 +1164,7 @@ static const unsigned char TIFFBitRevTable[256] = {
     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
 };
-static const unsigned char TIFFNoBitRevTable[256] = {
+static const unsigned char aig_TIFFNoBitRevTable[256] = {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
@@ -1619,7 +1619,7 @@ Fax3PrematureEOF()
 /************************************************************************/
 
 static void
-_TIFFFax3fillruns(unsigned char* buf, GUInt32* runs, GUInt32* erun, 
+aig_TIFFFax3fillruns(unsigned char* buf, GUInt32* runs, GUInt32* erun, 
                   GUInt32 lastx)
 {
 	static const unsigned char _fillmasks[] =
@@ -1753,7 +1753,7 @@ Fax3DecodeRLE(Fax3BaseState* tif, unsigned char *buf, int occ,
         do {						
             for (;;) {							 
                 for (;;) {						     
-                    LOOKUP16(12, TIFFFaxWhiteTable, eof1d);		  
+                    LOOKUP16(12, aig_TIFFFaxWhiteTable, eof1d);		  
                     switch (TabEnt->State) {				       
                       case S_EOL:					
                         EOLcnt = 1;					
@@ -1775,7 +1775,7 @@ Fax3DecodeRLE(Fax3BaseState* tif, unsigned char *buf, int occ,
                 if (a0 >= lastx)					
                     goto done1d;					
                 for (;;) {						
-                    LOOKUP16(13, TIFFFaxBlackTable, eof1d);		
+                    LOOKUP16(13, aig_TIFFFaxBlackTable, eof1d);		
                     switch (TabEnt->State) {				
                       case S_EOL:					
                         EOLcnt = 1;					
@@ -1862,7 +1862,7 @@ CPLErr DecompressCCITTRLETile( unsigned char *pabySrcData, int nSrcBytes,
     sp->subaddress = NULL;
     
     DecoderState(sp)->runs = NULL;
-    DecoderState(sp)->fill = _TIFFFax3fillruns;
+    DecoderState(sp)->fill = aig_TIFFFax3fillruns;
 
     if( sizeof(runs_buf) < (nBlockXSize * 2 + 3) )
     {
@@ -1900,7 +1900,7 @@ CPLErr DecompressCCITTRLETile( unsigned char *pabySrcData, int nSrcBytes,
     DecoderState(sp)->data = 0;
     DecoderState(sp)->EOLcnt = 0;	/* force initial scan for EOL */
 
-    DecoderState(sp)->bitmap = TIFFBitRevTable;
+    DecoderState(sp)->bitmap = aig_TIFFBitRevTable;
 
     if (DecoderState(sp)->refruns) {	/* init reference line to white */
         DecoderState(sp)->refruns[0] = (GUInt32) DecoderState(sp)->b.rowpixels;
diff --git a/frmts/aigrid/aigdataset.cpp b/frmts/aigrid/aigdataset.cpp
index 02b86b4..8e41dcc 100644
--- a/frmts/aigrid/aigdataset.cpp
+++ b/frmts/aigrid/aigdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigdataset.cpp 20504 2010-09-02 02:40:49Z warmerdam $
+ * $Id: aigdataset.cpp 22103 2011-04-02 14:51:10Z warmerdam $
  *
  * Project:  Arc/Info Binary Grid Driver
  * Purpose:  Implements GDAL interface to underlying library.
@@ -34,7 +34,7 @@
 #include "aigrid.h"
 #include "avc.h"
 
-CPL_CVSID("$Id: aigdataset.cpp 20504 2010-09-02 02:40:49Z warmerdam $");
+CPL_CVSID("$Id: aigdataset.cpp 22103 2011-04-02 14:51:10Z warmerdam $");
 
 CPL_C_START
 void	GDALRegister_AIGrid(void);
@@ -216,7 +216,10 @@ const GDALRasterAttributeTable *AIGRasterBand::GetDefaultRAT()
         poODS->bHasReadRat = TRUE;
     }
 
-    return poODS->poRAT;
+    if( poODS->poRAT )
+        return poODS->poRAT;
+    else
+        return GDALPamRasterBand::GetDefaultRAT();
 }
 
 /************************************************************************/
@@ -281,7 +284,7 @@ GDALColorInterp AIGRasterBand::GetColorInterpretation()
     if( poODS->poCT != NULL )
         return GCI_PaletteIndex;
     else
-        return GCI_Undefined;
+        return GDALPamRasterBand::GetColorInterpretation();
 }
 
 /************************************************************************/
@@ -293,7 +296,10 @@ GDALColorTable *AIGRasterBand::GetColorTable()
 {
     AIGDataset	*poODS = (AIGDataset *) poDS;
 
-    return poODS->poCT;
+    if( poODS->poCT != NULL )
+        return poODS->poCT;
+    else
+        return GDALPamRasterBand::GetColorTable();
 }
 
 /************************************************************************/
@@ -558,6 +564,29 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
     int iFile;
     int bGotOne = FALSE;
 
+    if (papszFileList == NULL)
+    {
+        /* Useful when reading from /vsicurl/ on servers that don't */
+        /* return a file list */
+        /* such as /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/NLCD/89110458 */
+        do
+        {
+            osTestName.Printf( "%s/W001001.ADF", osCoverName.c_str() );
+            if( VSIStatL( osTestName, &sStatBuf ) == 0 )
+            {
+                bGotOne = TRUE;
+                break;
+            }
+
+            osTestName.Printf( "%s/w001001.adf", osCoverName.c_str() );
+            if( VSIStatL( osTestName, &sStatBuf ) == 0 )
+            {
+                bGotOne = TRUE;
+                break;
+            }
+        } while(0);
+    }
+
     for( iFile = 0; 
          papszFileList != NULL && papszFileList[iFile] != NULL && !bGotOne;
          iFile++ )
diff --git a/frmts/aigrid/aigopen.c b/frmts/aigrid/aigopen.c
index 023aba2..83ac0d8 100644
--- a/frmts/aigrid/aigopen.c
+++ b/frmts/aigrid/aigopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigopen.c 22160 2011-04-14 18:19:58Z warmerdam $
+ * $Id: aigopen.c 22159 2011-04-14 18:18:54Z warmerdam $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file access cover API for non-GDAL use.
@@ -29,7 +29,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: aigopen.c 22160 2011-04-14 18:19:58Z warmerdam $");
+CPL_CVSID("$Id: aigopen.c 22159 2011-04-14 18:18:54Z warmerdam $");
 
 /************************************************************************/
 /*                              AIGOpen()                               */
diff --git a/frmts/aigrid/aigrid.h b/frmts/aigrid/aigrid.h
index 4e18062..db645ba 100644
--- a/frmts/aigrid/aigrid.h
+++ b/frmts/aigrid/aigrid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigrid.h 22160 2011-04-14 18:19:58Z warmerdam $
+ * $Id: aigrid.h 22159 2011-04-14 18:18:54Z warmerdam $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file access include file.
diff --git a/frmts/aigrid/aitest.c b/frmts/aigrid/aitest.c
index 67c04bf..1f36a6f 100644
--- a/frmts/aigrid/aitest.c
+++ b/frmts/aigrid/aitest.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aitest.c 22160 2011-04-14 18:19:58Z warmerdam $
+ * $Id: aitest.c 22159 2011-04-14 18:18:54Z warmerdam $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Test mainline for examining AIGrid files.
@@ -29,7 +29,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: aitest.c 22160 2011-04-14 18:19:58Z warmerdam $");
+CPL_CVSID("$Id: aitest.c 22159 2011-04-14 18:18:54Z warmerdam $");
 
 /************************************************************************/
 /*                             DumpMagic()                              */
diff --git a/frmts/aigrid/gridlib.c b/frmts/aigrid/gridlib.c
index 0d5522c..d507306 100644
--- a/frmts/aigrid/gridlib.c
+++ b/frmts/aigrid/gridlib.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gridlib.c 22160 2011-04-14 18:19:58Z warmerdam $
+ * $Id: gridlib.c 22159 2011-04-14 18:18:54Z warmerdam $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file reading code.
@@ -29,7 +29,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: gridlib.c 22160 2011-04-14 18:19:58Z warmerdam $");
+CPL_CVSID("$Id: gridlib.c 22159 2011-04-14 18:18:54Z warmerdam $");
 
 /************************************************************************/
 /*                    AIGProcessRaw32bitFloatBlock()                    */
diff --git a/frmts/blx/blxdataset.cpp b/frmts/blx/blxdataset.cpp
index 0e67b5d..af23ce0 100644
--- a/frmts/blx/blxdataset.cpp
+++ b/frmts/blx/blxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: blxdataset.cpp 20482 2010-08-28 22:30:42Z rouault $
+ * $Id: blxdataset.cpp 23619 2011-12-20 22:40:19Z rouault $
  *
  * Project:  BLX Driver
  * Purpose:  GDAL BLX support.
@@ -32,7 +32,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: blxdataset.cpp 20482 2010-08-28 22:30:42Z rouault $");
+CPL_CVSID("$Id: blxdataset.cpp 23619 2011-12-20 22:40:19Z rouault $");
 
 CPL_C_START
 #include <blx.h>
@@ -42,7 +42,7 @@ CPL_C_START
 void    GDALRegister_BLX(void);
 CPL_C_END
 
-class BLXDataset : public GDALDataset
+class BLXDataset : public GDALPamDataset
 {
     friend class BLXRasterBand;
 
@@ -62,7 +62,7 @@ class BLXDataset : public GDALDataset
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
-class BLXRasterBand : public GDALRasterBand
+class BLXRasterBand : public GDALPamRasterBand
 {
     int overviewLevel;
   public:
@@ -99,11 +99,17 @@ GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
     //      Open BLX file
     // -------------------------------------------------------------------- 
     poDS->blxcontext = blx_create_context();
-    blxopen(poDS->blxcontext, poOpenInfo->pszFilename, "rb");
-
     if(poDS->blxcontext==NULL)
-	return NULL;
-    
+    {
+        delete poDS;
+        return NULL;
+    }
+    if (blxopen(poDS->blxcontext, poOpenInfo->pszFilename, "rb") != 0)
+    {
+        delete poDS;
+        return NULL;
+    }
+
     if ((poDS->blxcontext->cell_xsize % (1 << (1+BLX_OVERVIEWLEVELS))) != 0 ||
         (poDS->blxcontext->cell_ysize % (1 << (1+BLX_OVERVIEWLEVELS))) != 0)
     {
@@ -145,6 +151,12 @@ GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
     return( poDS );
 }
 
diff --git a/frmts/bmp/bmpdataset.cpp b/frmts/bmp/bmpdataset.cpp
index b3800bf..4239066 100644
--- a/frmts/bmp/bmpdataset.cpp
+++ b/frmts/bmp/bmpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bmpdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: bmpdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  Microsoft Windows Bitmap
  * Purpose:  Read/write MS Windows Device Independent Bitmap (DIB) files
@@ -31,7 +31,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: bmpdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: bmpdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 CPL_C_START
 void    GDALRegister_BMP(void);
@@ -1040,7 +1040,7 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
 #ifdef CPL_MSB
     CPL_SWAP32PTR( &poDS->sFileHeader.iOffBits );
 #endif
-    poDS->sFileHeader.iSize = sStat.st_size;
+    poDS->sFileHeader.iSize = (GUInt32) sStat.st_size;
 
 #ifdef BMP_DEBUG
     CPLDebug( "BMP", "File size %d bytes.", poDS->sFileHeader.iSize );
diff --git a/frmts/bsb/bsbdataset.cpp b/frmts/bsb/bsbdataset.cpp
index f4d4849..2097ee6 100644
--- a/frmts/bsb/bsbdataset.cpp
+++ b/frmts/bsb/bsbdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsbdataset.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: bsbdataset.cpp 23113 2011-09-23 23:24:19Z rouault $
  *
  * Project:  BSB Reader
  * Purpose:  BSBDataset implementation for BSB format.
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: bsbdataset.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: bsbdataset.cpp 23113 2011-09-23 23:24:19Z rouault $");
 
 CPL_C_START
 void	GDALRegister_BSB(void);
@@ -61,6 +61,9 @@ class BSBDataset : public GDALPamDataset
     void        ScanForGCPs( bool isNos, const char *pszFilename );
     void        ScanForGCPsNos( const char *pszFilename );
     void        ScanForGCPsBSB();
+
+    static int IdentifyInternal( GDALOpenInfo *, bool & isNosOut );
+
   public:
                 BSBDataset();
 		~BSBDataset();
@@ -68,6 +71,7 @@ class BSBDataset : public GDALPamDataset
     BSBInfo     *psInfo;
 
     static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
 
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
@@ -416,7 +420,9 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
     if( pszKNP != NULL )
     {
         const char *pszPR = strstr(pszKNP,"PR=");
+        const char *pszGD = strstr(pszKNP,"GD=");
         const char *pszValue, *pszEnd = NULL;
+        const char *pszGEOGCS = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
         CPLString osPP;
         
         // Capture the PP string.
@@ -426,6 +432,17 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
         if( pszValue && pszEnd )
             osPP.assign(pszValue+3,pszEnd-pszValue-3);
         
+        // Look at the datum
+        if( pszGD == NULL )
+        {
+            /* no match. We'll default to EPSG:4326 */
+        }
+        else if( EQUALN(pszGD,"GD=European 1950", 16) )
+        {
+            pszGEOGCS = "GEOGCS[\"ED50\",DATUM[\"European_Datum_1950\",SPHEROID[\"International 1924\",6378388,297,AUTHORITY[\"EPSG\",\"7022\"]],TOWGS84[-87,-98,-121,0,0,0,0],AUTHORITY[\"EPSG\",\"6230\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4230\"]]";
+        }
+
+        // Look at the projection
         if( pszPR == NULL )
         {
             /* no match */
@@ -436,7 +453,8 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
             // central meridian.  This is mostly helpful to ensure 
             // that regions crossing the dateline will be contiguous 
             // in mercator.
-            osUnderlyingSRS.Printf( "PROJCS[\"Global Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.01745329251994328]],PROJECTION[\"Mercator_2SP\"],PARAMETER[\"standard_parallel_1\",0],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%d],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1]]", (int) pasGCPList[0].dfGCPX );
+            osUnderlyingSRS.Printf( "PROJCS[\"Global Mercator\",%s,PROJECTION[\"Mercator_2SP\"],PARAMETER[\"standard_parallel_1\",0],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%d],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1]]",
+                pszGEOGCS, (int) pasGCPList[0].dfGCPX );
         }
 
         else if( EQUALN(pszPR,"PR=TRANSVERSE MERCATOR", 22)
@@ -444,8 +462,8 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
         {
             
             osUnderlyingSRS.Printf( 
-                "PROJCS[\"unnamed\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]", 
-                osPP.c_str() );
+                "PROJCS[\"unnamed\",%s,PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]",
+                pszGEOGCS, osPP.c_str() );
         }
 
         else if( EQUALN(pszPR,"PR=UNIVERSAL TRANSVERSE MERCATOR", 32)
@@ -454,15 +472,15 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
             // This is not *really* UTM unless the central meridian 
             // matches a zone which it does not in some (most?) maps. 
             osUnderlyingSRS.Printf( 
-                "PROJCS[\"unnamed\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0]]", 
-                osPP.c_str() );
+                "PROJCS[\"unnamed\",%s,PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0]]", 
+                pszGEOGCS, osPP.c_str() );
         }
 
         else if( EQUALN(pszPR,"PR=POLYCONIC", 12) && osPP.size() > 0 )
         {
             osUnderlyingSRS.Printf( 
-                "PROJCS[\"unnamed\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Polyconic\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]", 
-                osPP.c_str() );
+                "PROJCS[\"unnamed\",%s,PROJECTION[\"Polyconic\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]", 
+                pszGEOGCS, osPP.c_str() );
         }
         
         else if( EQUALN(pszPR,"PR=LAMBERT CONFORMAL CONIC", 26) 
@@ -491,8 +509,8 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
 
             if( osP2.size() > 0 && osP3.size() > 0 )
                 osUnderlyingSRS.Printf( 
-                    "PROJCS[\"unnamed\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"standard_parallel_1\",%s],PARAMETER[\"standard_parallel_2\",%s],PARAMETER[\"latitude_of_origin\",0.0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0.0],PARAMETER[\"false_northing\",0.0]]",
-                    osP2.c_str(), osP3.c_str(), osPP.c_str() );
+                    "PROJCS[\"unnamed\",%s,PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"standard_parallel_1\",%s],PARAMETER[\"standard_parallel_2\",%s],PARAMETER[\"latitude_of_origin\",0.0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0.0],PARAMETER[\"false_northing\",0.0]]",
+                    pszGEOGCS, osP2.c_str(), osP3.c_str(), osPP.c_str() );
 
         }
     }
@@ -503,13 +521,13 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
 /* -------------------------------------------------------------------- */
     if( osUnderlyingSRS.length() > 0 )
     {
-        OGRSpatialReference oWGS84_SRS, oProjected_SRS;
+        OGRSpatialReference oGeog_SRS, oProjected_SRS;
         OGRCoordinateTransformation *poCT;
         
-        oWGS84_SRS.SetWellKnownGeogCS( "WGS84" );
         oProjected_SRS.SetFromUserInput( osUnderlyingSRS );
+        oGeog_SRS.CopyGeogCSFrom( &oProjected_SRS );
         
-        poCT = OGRCreateCoordinateTransformation( &oWGS84_SRS, 
+        poCT = OGRCreateCoordinateTransformation( &oGeog_SRS, 
                                                   &oProjected_SRS );
         if( poCT != NULL )
         {
@@ -680,53 +698,78 @@ void BSBDataset::ScanForGCPsBSB()
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                          IdentifyInternal()                          */
 /************************************************************************/
 
-GDALDataset *BSBDataset::Open( GDALOpenInfo * poOpenInfo )
+int BSBDataset::IdentifyInternal( GDALOpenInfo * poOpenInfo, bool& isNosOut )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Check for BSB/ keyword.                                         */
 /* -------------------------------------------------------------------- */
-    int		i;
-    bool        isNos = false;
+    int     i;
+    isNosOut = false;
 
     if( poOpenInfo->nHeaderBytes < 1000 )
         return NULL;
 
     for( i = 0; i < poOpenInfo->nHeaderBytes - 4; i++ )
     {
-        if( poOpenInfo->pabyHeader[i+0] == 'B' 
-            && poOpenInfo->pabyHeader[i+1] == 'S' 
-            && poOpenInfo->pabyHeader[i+2] == 'B' 
+        if( poOpenInfo->pabyHeader[i+0] == 'B'
+            && poOpenInfo->pabyHeader[i+1] == 'S'
+            && poOpenInfo->pabyHeader[i+2] == 'B'
             && poOpenInfo->pabyHeader[i+3] == '/' )
             break;
-        if( poOpenInfo->pabyHeader[i+0] == 'N' 
-            && poOpenInfo->pabyHeader[i+1] == 'O' 
-            && poOpenInfo->pabyHeader[i+2] == 'S' 
+        if( poOpenInfo->pabyHeader[i+0] == 'N'
+            && poOpenInfo->pabyHeader[i+1] == 'O'
+            && poOpenInfo->pabyHeader[i+2] == 'S'
             && poOpenInfo->pabyHeader[i+3] == '/' )
         {
-            isNos = true;
+            isNosOut = true;
             break;
         }
-        if( poOpenInfo->pabyHeader[i+0] == 'W' 
-            && poOpenInfo->pabyHeader[i+1] == 'X' 
-            && poOpenInfo->pabyHeader[i+2] == '\\' 
+        if( poOpenInfo->pabyHeader[i+0] == 'W'
+            && poOpenInfo->pabyHeader[i+1] == 'X'
+            && poOpenInfo->pabyHeader[i+2] == '\\'
             && poOpenInfo->pabyHeader[i+3] == '8' )
             break;
     }
 
     if( i == poOpenInfo->nHeaderBytes - 4 )
-        return NULL;
+        return FALSE;
 
     /* Additional test to avoid false positive. See #2881 */
     const char* pszRA = strstr((const char*)poOpenInfo->pabyHeader + i, "RA=");
     if (pszRA == NULL) /* This may be a NO1 file */
         pszRA = strstr((const char*)poOpenInfo->pabyHeader + i, "[JF");
     if (pszRA == NULL || pszRA - ((const char*)poOpenInfo->pabyHeader + i) > 100 )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int BSBDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    bool isNos;
+    return IdentifyInternal(poOpenInfo, isNos);
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *BSBDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    bool        isNos = false;
+    if (!IdentifyInternal(poOpenInfo, isNos))
         return NULL;
-        
+
     if( poOpenInfo->eAccess == GA_Update )
     {
         CPLError( CE_Failure, CPLE_NotSupported, 
@@ -1152,6 +1195,7 @@ void GDALRegister_BSB()
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
 #endif
         poDriver->pfnOpen = BSBDataset::Open;
+        poDriver->pfnIdentify = BSBDataset::Identify;
 #ifdef BSB_CREATE
         poDriver->pfnCreateCopy = BSBCreateCopy;
 #endif
diff --git a/frmts/ceos2/sar_ceosdataset.cpp b/frmts/ceos2/sar_ceosdataset.cpp
index 9cf2cfc..3c04883 100644
--- a/frmts/ceos2/sar_ceosdataset.cpp
+++ b/frmts/ceos2/sar_ceosdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sar_ceosdataset.cpp 22663 2011-07-07 15:08:47Z warmerdam $
+ * $Id: sar_ceosdataset.cpp 22708 2011-07-11 21:42:50Z rouault $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  GDALDataset driver for CEOS translator.
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: sar_ceosdataset.cpp 22663 2011-07-07 15:08:47Z warmerdam $");
+CPL_CVSID("$Id: sar_ceosdataset.cpp 22708 2011-07-11 21:42:50Z rouault $");
 
 CPL_C_START
 void	GDALRegister_SAR_CEOS(void);
@@ -1617,6 +1617,7 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( ProcessData( fp, __CEOS_IMAGRY_OPT_FILE, psVolume, 4, -1) != CE_None )
     {
         delete poDS;
+        VSIFCloseL(fp);
         return NULL;
     }
 
@@ -1762,6 +1763,8 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
                   "from %s.", 
                   poOpenInfo->pszFilename );
 
+        VSIFCloseL(fp);
+
         return NULL;
     }
 
@@ -2011,6 +2014,8 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
             if( fileid == __CEOS_IMAGRY_OPT_FILE && iThisRecord == 2 )
             {
                 CPLDebug( "SAR_CEOS", "Ignoring CEOS file with wrong second record sequence number - likely it has padded records." );
+                CPLFree(record);
+                CPLFree(temp_body);
                 return CE_Warning;
             }
             else
@@ -2018,6 +2023,8 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
                 CPLError( CE_Failure, CPLE_AppDefined, 
                           "Corrupt CEOS File - got record seq# %d instead of the expected %d.",
                           record->Sequence, iThisRecord );
+                CPLFree(record);
+                CPLFree(temp_body);
                 return CE_Failure;
             }
         }
diff --git a/frmts/ctg/GNUmakefile b/frmts/ctg/GNUmakefile
new file mode 100644
index 0000000..f30a1e9
--- /dev/null
+++ b/frmts/ctg/GNUmakefile
@@ -0,0 +1,15 @@
+
+include ../../GDALmake.opt
+
+OBJ	=	ctgdataset.o
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(XTRA_OPT)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o
+
+all:	$(OBJ:.o=.$(OBJ_EXT))
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/ctg/ctgdataset.cpp b/frmts/ctg/ctgdataset.cpp
new file mode 100644
index 0000000..4bc92ea
--- /dev/null
+++ b/frmts/ctg/ctgdataset.cpp
@@ -0,0 +1,610 @@
+/******************************************************************************
+ * $Id: ctgdataset.cpp 21774 2011-02-21 19:33:56Z 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
+ *
+ * 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_pam.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: ctgdataset.cpp 21774 2011-02-21 19:33:56Z rouault $");
+
+CPL_C_START
+void    GDALRegister_CTG(void);
+CPL_C_END
+
+#define HEADER_LINE_COUNT 5
+
+typedef struct
+{
+    int nCode;
+    const char* pszDesc;
+} LULCDescStruct;
+
+static const LULCDescStruct asLULCDesc[] =
+{
+    {1, "Urban or Built-Up Land" },
+    {2, "Agricultural Land" },
+    {3, "Rangeland" },
+    {4, "Forest Land" },
+    {5, "Water" },
+    {6, "Wetland" },
+    {7, "Barren Land" },
+    {8, "Tundra" },
+    {9, "Perennial Snow and Ice" },
+    {11, "Residential" },
+    {12, "Commercial Services" },
+    {13, "Industrial" },
+    {14, "Transportation, Communications" },
+    {15, "Industrial and Commercial" },
+    {16, "Mixed Urban or Built-Up Land" },
+    {17, "Other Urban or Built-Up Land" },
+    {21, "Cropland and Pasture" },
+    {22, "Orchards, Groves, Vineyards, Nurseries" },
+    {23, "Confined Feeding Operations" },
+    {24, "Other Agricultural Land" },
+    {31, "Herbaceous Rangeland" },
+    {32, "Shrub and Brush Rangeland" },
+    {33, "Mixed Rangeland" },
+    {41, "Deciduous Forest Land" },
+    {42, "Evergreen Forest Land" },
+    {43, "Mixed Forest Land" },
+    {51, "Streams and Canals" },
+    {52, "Lakes" },
+    {53, "Reservoirs" },
+    {54, "Bays and Estuaries" },
+    {61, "Forested Wetlands" },
+    {62, "Nonforested Wetlands" },
+    {71, "Dry Salt Flats" },
+    {72, "Beaches" },
+    {73, "Sandy Areas Other than Beaches" },
+    {74, "Bare Exposed Rock" },
+    {75, "Strip Mines, Quarries, and Gravel Pits" },
+    {76, "Transitional Areas" },
+    {77, "Mixed Barren Land" },
+    {81, "Shrub and Brush Tundra" },
+    {82, "Herbaceous Tundra" },
+    {83, "Bare Ground" },
+    {84, "Wet Tundra" },
+    {85, "Mixed Tundra" },
+    {91, "Perennial Snowfields" },
+    {92, "Glaciers" }
+};
+
+static const char* apszBandDescription[] =
+{
+    "Land Use and Land Cover",
+    "Political units",
+    "Census county subdivisions and SMSA tracts",
+    "Hydrologic units",
+    "Federal land ownership",
+    "State land ownership"
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              CTGDataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class CTGRasterBand;
+
+class CTGDataset : public GDALPamDataset
+{
+    friend class CTGRasterBand;
+
+    VSILFILE   *fp;
+
+    char        szField[11];
+
+    int         nNWEasting, nNWNorthing, nCellSize, nUTMZone;
+    char       *pszProjection;
+
+    int         bHasReadImagery;
+    GByte      *pabyImage;
+
+    int         ReadImagery();
+
+    static const char* ExtractField(char* szOutput, const char* pszBuffer,
+                                       int nOffset, int nLength);
+
+  public:
+                 CTGDataset();
+    virtual     ~CTGDataset();
+
+    virtual CPLErr GetGeoTransform( double * );
+    virtual const char* GetProjectionRef();
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            CTGRasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class CTGRasterBand : public GDALPamRasterBand
+{
+    friend class CTGDataset;
+
+    char** papszCategories;
+
+  public:
+
+                CTGRasterBand( CTGDataset *, int );
+               ~CTGRasterBand();
+
+    virtual CPLErr IReadBlock( int, int, void * );
+    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual char **GetCategoryNames();
+};
+
+
+/************************************************************************/
+/*                           CTGRasterBand()                            */
+/************************************************************************/
+
+CTGRasterBand::CTGRasterBand( CTGDataset *poDS, int nBand )
+
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+
+    eDataType = GDT_Int32;
+
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = poDS->GetRasterYSize();
+
+    papszCategories = NULL;
+}
+
+/************************************************************************/
+/*                          ~CTGRasterBand()                            */
+/************************************************************************/
+
+CTGRasterBand::~CTGRasterBand()
+
+{
+    CSLDestroy(papszCategories);
+}
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr CTGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                  void * pImage )
+
+{
+    CTGDataset* poGDS = (CTGDataset* ) poDS;
+
+    poGDS->ReadImagery();
+    memcpy(pImage,
+           poGDS->pabyImage + (nBand - 1) * nBlockXSize * nBlockYSize * sizeof(int),
+           nBlockXSize * nBlockYSize * sizeof(int));
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
+
+double CTGRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    if (pbSuccess)
+        *pbSuccess = TRUE;
+
+    return 0.;
+}
+
+/************************************************************************/
+/*                          GetCategoryNames()                          */
+/************************************************************************/
+
+char **CTGRasterBand::GetCategoryNames()
+{
+    if (nBand != 1)
+        return NULL;
+
+    if (papszCategories != NULL)
+        return papszCategories;
+
+    int i;
+    int nasLULCDescSize = (int)(sizeof(asLULCDesc) / sizeof(asLULCDesc[0]));
+    int nCategoriesSize = asLULCDesc[nasLULCDescSize - 1].nCode;
+    papszCategories = (char**)CPLCalloc(nCategoriesSize + 2, sizeof(char*));
+    for(i=0;i<nasLULCDescSize;i++)
+    {
+        papszCategories[asLULCDesc[i].nCode] = CPLStrdup(asLULCDesc[i].pszDesc);
+    }
+    for(i=0;i<nCategoriesSize;i++)
+    {
+        if (papszCategories[i] == NULL)
+            papszCategories[i] = CPLStrdup("");
+    }
+    papszCategories[nCategoriesSize + 1] = NULL;
+
+    return papszCategories;
+}
+
+/************************************************************************/
+/*                            ~CTGDataset()                            */
+/************************************************************************/
+
+CTGDataset::CTGDataset()
+{
+    pszProjection = NULL;
+    bHasReadImagery = FALSE;
+    pabyImage = NULL;
+    fp = NULL;
+}
+
+/************************************************************************/
+/*                            ~CTGDataset()                            */
+/************************************************************************/
+
+CTGDataset::~CTGDataset()
+
+{
+    CPLFree(pszProjection);
+    CPLFree(pabyImage);
+    if (fp != NULL)
+        VSIFCloseL(fp);
+}
+
+/************************************************************************/
+/*                              ExtractField()                          */
+/************************************************************************/
+
+const char* CTGDataset::ExtractField(char* szField, const char* pszBuffer,
+                                     int nOffset, int nLength)
+{
+    CPLAssert(nLength <= 10);
+    memcpy(szField, pszBuffer + nOffset, nLength);
+    szField[nLength] = 0;
+    return szField;
+}
+
+/************************************************************************/
+/*                            ReadImagery()                             */
+/************************************************************************/
+
+int CTGDataset::ReadImagery()
+{
+    if (bHasReadImagery)
+        return TRUE;
+
+    bHasReadImagery = TRUE;
+
+    char szLine[81];
+    char szField[11];
+    szLine[80] = 0;
+    int nLine = HEADER_LINE_COUNT;
+    VSIFSeekL(fp, nLine * 80, SEEK_SET);
+    int nCells = nRasterXSize * nRasterYSize;
+    while(VSIFReadL(szLine, 1, 80, fp) == 80)
+    {
+        int nZone = atoi(ExtractField(szField, szLine, 0, 3));
+        if (nZone != nUTMZone)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Read error at line %d, %s. Did not expected UTM zone %d",
+                     nLine, szLine, nZone);
+            return FALSE;
+        }
+        int nX = atoi(ExtractField(szField, szLine, 3, 8)) - nCellSize / 2;
+        int nY = atoi(ExtractField(szField, szLine, 11, 8)) + nCellSize / 2;
+        int nDiffX = nX - nNWEasting;
+        int nDiffY = nNWNorthing - nY;
+        if (nDiffX < 0 || (nDiffX % nCellSize) != 0 ||
+            nDiffY < 0 || (nDiffY % nCellSize) != 0)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Read error at line %d, %s. Unexpected cell coordinates",
+                     nLine, szLine);
+            return FALSE;
+        }
+        int nCellX = nDiffX / nCellSize;
+        int nCellY = nDiffY / nCellSize;
+        if (nCellX >= nRasterXSize || nCellY >= nRasterYSize)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Read error at line %d, %s. Unexpected cell coordinates",
+                     nLine, szLine);
+            return FALSE;
+        }
+        int i;
+        for(i=0;i<6;i++)
+        {
+            int nVal = atoi(ExtractField(szField, szLine, 20 + 10*i, 10));
+            if (nVal >= 2000000000)
+                nVal = 0;
+            ((int*)pabyImage)[i * nCells + nCellY * nRasterXSize + nCellX] = nVal;
+        }
+
+        nLine ++;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int CTGDataset::Identify( GDALOpenInfo * poOpenInfo )
+{
+    CPLString osFilename(poOpenInfo->pszFilename);
+
+    GDALOpenInfo* poOpenInfoToDelete = NULL;
+    /*  GZipped grid_cell.gz files are common, so automagically open them */
+    /*  if the /vsigzip/ has not been explicitely passed */
+    const char* pszFilename = CPLGetFilename(poOpenInfo->pszFilename);
+    if ((EQUAL(pszFilename, "grid_cell.gz") ||
+         EQUAL(pszFilename, "grid_cell1.gz") ||
+         EQUAL(pszFilename, "grid_cell2.gz")) &&
+        !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+    {
+        osFilename = "/vsigzip/";
+        osFilename += poOpenInfo->pszFilename;
+        poOpenInfo = poOpenInfoToDelete =
+                new GDALOpenInfo(osFilename.c_str(), GA_ReadOnly,
+                                 poOpenInfo->papszSiblingFiles);
+    }
+
+    if (poOpenInfo->nHeaderBytes < HEADER_LINE_COUNT * 80)
+    {
+        delete poOpenInfoToDelete;
+        return FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Chech that it looks roughly as a CTG dataset                    */
+/* -------------------------------------------------------------------- */
+    const char* pszData = (const char*)poOpenInfo->pabyHeader;
+    int i;
+    for(i=0;i<4 * 80;i++)
+    {
+        if (!((pszData[i] >= '0' && pszData[i] <= '9') ||
+              pszData[i] == ' ' || pszData[i] == '-'))
+        {
+            delete poOpenInfoToDelete;
+            return FALSE;
+        }
+    }
+
+    char szField[11];
+    int nRows = atoi(ExtractField(szField, pszData, 0, 10));
+    int nCols = atoi(ExtractField(szField, pszData, 20, 10));
+    int nMinColIndex = atoi(ExtractField(szField, pszData+80, 0, 5));
+    int nMinRowIndex = atoi(ExtractField(szField, pszData+80, 5, 5));
+    int nMaxColIndex = atoi(ExtractField(szField, pszData+80, 10, 5));
+    int nMaxRowIndex = atoi(ExtractField(szField, pszData+80, 15, 5));
+
+    if (nRows <= 0 || nCols <= 0 ||
+        nMinColIndex != 1 || nMinRowIndex != 1 ||
+        nMaxRowIndex != nRows || nMaxColIndex != nCols)
+    {
+        delete poOpenInfoToDelete;
+        return FALSE;
+    }
+
+    delete poOpenInfoToDelete;
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    int         i;
+
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+    CPLString osFilename(poOpenInfo->pszFilename);
+
+    /*  GZipped grid_cell.gz files are common, so automagically open them */
+    /*  if the /vsigzip/ has not been explicitely passed */
+    const char* pszFilename = CPLGetFilename(poOpenInfo->pszFilename);
+    if ((EQUAL(pszFilename, "grid_cell.gz") ||
+         EQUAL(pszFilename, "grid_cell1.gz") ||
+         EQUAL(pszFilename, "grid_cell2.gz")) &&
+        !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
+    {
+        osFilename = "/vsigzip/";
+        osFilename += poOpenInfo->pszFilename;
+    }
+
+    if (poOpenInfo->eAccess == GA_Update)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "The CTG driver does not support update access to existing"
+                  " datasets.\n" );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find dataset characteristics                                    */
+/* -------------------------------------------------------------------- */
+    VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb");
+    if (fp == NULL)
+        return NULL;
+
+    char szHeader[HEADER_LINE_COUNT * 80+1];
+    szHeader[HEADER_LINE_COUNT * 80] = 0;
+    if (VSIFReadL(szHeader, 1, HEADER_LINE_COUNT * 80, fp) != HEADER_LINE_COUNT * 80)
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    for(i=HEADER_LINE_COUNT * 80 - 1;i>=0;i--)
+    {
+        if (szHeader[i] == ' ')
+            szHeader[i] = 0;
+        else
+            break;
+    }
+
+    char szField[11];
+    int nRows = atoi(ExtractField(szField, szHeader, 0, 10));
+    int nCols = atoi(ExtractField(szField, szHeader, 20, 10));
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    CTGDataset         *poDS;
+
+    poDS = new CTGDataset();
+    poDS->fp = fp;
+    fp = NULL;
+    poDS->nRasterXSize = nCols;
+    poDS->nRasterYSize = nRows;
+
+    poDS->SetMetadataItem("TITLE", szHeader + 4 * 80);
+
+    poDS->nCellSize = atoi(ExtractField(szField, szHeader, 35, 5));
+    if (poDS->nCellSize <= 0 || poDS->nCellSize >= 10000)
+    {
+        delete poDS;
+        return NULL;
+    }
+    poDS->nNWEasting = atoi(ExtractField(szField, szHeader + 3*80, 40, 10));
+    poDS->nNWNorthing = atoi(ExtractField(szField, szHeader + 3*80, 50, 10));
+    poDS->nUTMZone = atoi(ExtractField(szField, szHeader, 50, 5));
+    if (poDS->nUTMZone <= 0 || poDS->nUTMZone > 60)
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    OGRSpatialReference oSRS;
+    oSRS.importFromEPSG(32600 + poDS->nUTMZone);
+    oSRS.exportToWkt(&poDS->pszProjection);
+
+    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
+    {
+        delete poDS;
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the imagery                                                */
+/* -------------------------------------------------------------------- */
+    GByte* pabyImage = (GByte*)VSICalloc(nCols * nRows, 6 * sizeof(int));
+    if (pabyImage == NULL)
+    {
+        delete poDS;
+        return NULL;
+    }
+    poDS->pabyImage = pabyImage;
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    poDS->nBands = 6;
+    for( i = 0; i < poDS->nBands; i++ )
+    {
+        poDS->SetBand( i+1, new CTGRasterBand( poDS, i+1 ) );
+        poDS->GetRasterBand(i+1)->SetDescription(apszBandDescription[i]);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Support overviews.                                              */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
+    return( poDS );
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr CTGDataset::GetGeoTransform( double * padfTransform )
+
+{
+    padfTransform[0] = nNWEasting - nCellSize / 2;
+    padfTransform[1] = nCellSize;
+    padfTransform[2] = 0;
+    padfTransform[3] = nNWNorthing + nCellSize / 2;
+    padfTransform[4] = 0.;
+    padfTransform[5] = -nCellSize;
+
+    return( CE_None );
+}
+
+/************************************************************************/
+/*                         GetProjectionRef()                           */
+/************************************************************************/
+
+const char* CTGDataset::GetProjectionRef()
+
+{
+    return pszProjection;
+}
+
+/************************************************************************/
+/*                         GDALRegister_CTG()                           */
+/************************************************************************/
+
+void GDALRegister_CTG()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "CTG" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "CTG" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "USGS LULC Composite Theme Grid" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                   "frmt_various.html#CTG" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnOpen = CTGDataset::Open;
+        poDriver->pfnIdentify = CTGDataset::Identify;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
+
diff --git a/frmts/ctg/makefile.vc b/frmts/ctg/makefile.vc
new file mode 100644
index 0000000..efc3d2a
--- /dev/null
+++ b/frmts/ctg/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ	=	ctgdataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/dimap/dimapdataset.cpp b/frmts/dimap/dimapdataset.cpp
index 824cc48..a85aab4 100644
--- a/frmts/dimap/dimapdataset.cpp
+++ b/frmts/dimap/dimapdataset.cpp
@@ -32,8 +32,9 @@
 #include "gdal_pam.h"
 #include "cpl_minixml.h"
 #include "ogr_spatialref.h"
+#include "gdal_proxy.h"
 
-CPL_CVSID("$Id: dimapdataset.cpp 20504 2010-09-02 02:40:49Z warmerdam $");
+CPL_CVSID("$Id: dimapdataset.cpp 23634 2011-12-22 18:50:05Z aboudreault $");
 
 CPL_C_START
 void	GDALRegister_DIMAP(void);
@@ -49,6 +50,9 @@ class DIMAPDataset : public GDALPamDataset
 {
     CPLXMLNode *psProduct;
 
+    CPLXMLNode *psProductDim; /* DIMAP2, DIM_<product_id>.XML */
+    CPLXMLNode *psProductStrip; /* DIMAP2, STRIP_<product_id>.XML */
+
     GDALDataset   *poImageDS;
 
     int           nGCPCount;
@@ -60,8 +64,19 @@ class DIMAPDataset : public GDALPamDataset
     int           bHaveGeoTransform;
     double        adfGeoTransform[6];
 
+    CPLString     osMDFilename;
+    CPLString     osImageDSFilename;
+    int           nProductVersion;
+    
     char          **papszXMLDimapMetadata;
 
+  protected:
+    virtual int         CloseDependentDatasets();
+
+    int ReadImageInformation();
+    int ReadImageInformation2(); /* DIMAP 2 */
+
+    void SetMetadata(CPLXMLNode *psProduct, const char *apszMetadataTranslation[]);
   public:
 		DIMAPDataset();
 	        ~DIMAPDataset();
@@ -82,6 +97,27 @@ class DIMAPDataset : public GDALPamDataset
 
 /************************************************************************/
 /* ==================================================================== */
+/*                        DIMAPWrapperRasterBand                        */
+/* ==================================================================== */
+/************************************************************************/
+class DIMAPWrapperRasterBand : public GDALProxyRasterBand
+{
+  GDALRasterBand* poBaseBand;
+
+  protected:
+    virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
+
+  public:
+    DIMAPWrapperRasterBand( GDALRasterBand* poBaseBand )
+        {
+            this->poBaseBand = poBaseBand;
+            eDataType = poBaseBand->GetRasterDataType();
+            poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+        }
+    ~DIMAPWrapperRasterBand() {}
+};
+/************************************************************************/
+/* ==================================================================== */
 /*				DIMAPDataset				*/
 /* ==================================================================== */
 /************************************************************************/
@@ -94,6 +130,9 @@ DIMAPDataset::DIMAPDataset()
 {
     psProduct = NULL;
 
+    psProductDim = NULL;
+    psProductStrip = NULL;
+
     nGCPCount = 0;
     pasGCPList = NULL;
     pszGCPProjection = CPLStrdup("");
@@ -101,6 +140,8 @@ DIMAPDataset::DIMAPDataset()
     poImageDS = NULL;
     bHaveGeoTransform = FALSE;
 
+    nProductVersion = 1;
+
     papszXMLDimapMetadata = NULL;
 }
 
@@ -115,6 +156,12 @@ DIMAPDataset::~DIMAPDataset()
 
     CPLDestroyXMLNode( psProduct );
 
+    if( nProductVersion == 2 )
+    {
+	CPLDestroyXMLNode( psProductDim );
+	CPLDestroyXMLNode( psProductStrip );
+    }
+
     CPLFree( pszGCPProjection );
     if( nGCPCount > 0 )
     {
@@ -122,18 +169,37 @@ DIMAPDataset::~DIMAPDataset()
         CPLFree( pasGCPList );
     }
 
+    CSLDestroy(papszXMLDimapMetadata);
+
+    CloseDependentDatasets();
+}
+
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int DIMAPDataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
     if( poImageDS != NULL )
+    {
         delete poImageDS;
-
-    CSLDestroy(papszXMLDimapMetadata);
+        poImageDS = NULL;
+        bHasDroppedRef = TRUE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Disconnect the bands so our destructor doesn't try and          */
 /*      delete them since they really belonged to poImageDS.            */
 /* -------------------------------------------------------------------- */
     int iBand;
-    for( iBand = 0; iBand < GetRasterCount(); iBand++ )
-        papoBands[iBand] = NULL;
+    for( iBand = 0; iBand < nBands; iBand++ )
+        delete papoBands[iBand];
+    nBands = 0;
+
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -214,8 +280,10 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     if( poOpenInfo->nHeaderBytes >= 100 )
     {
-        if( strstr((const char *) poOpenInfo->pabyHeader, 
-                   "<Dimap_Document" ) == NULL )
+      if( ( strstr((const char *) poOpenInfo->pabyHeader, 
+                   "<Dimap_Document" ) == NULL ) &&
+	  ( strstr((const char *) poOpenInfo->pabyHeader, 
+                   "<PHR_DIMAP_Document" ) == NULL ) )
             return FALSE;
         else
             return TRUE;
@@ -224,13 +292,23 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
     {
         VSIStatBufL sStat;
 
+	/* DIMAP file */
         CPLString osMDFilename = 
             CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
         
         if( VSIStatL( osMDFilename, &sStat ) == 0 )
             return TRUE;
         else
+	{
+	  /* DIMAP 2 file */
+	  osMDFilename = 
+            CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
+	  
+	  if( VSIStatL( osMDFilename, &sStat ) == 0 )
+            return TRUE;
+	  else
             return FALSE;
+	}
     }
 
     return FALSE;
@@ -243,6 +321,8 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
+    int nProductVersion = 1;
+
     if( !Identify( poOpenInfo ) )
         return NULL;
         
@@ -259,12 +339,19 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get the metadata filename.                                      */
 /* -------------------------------------------------------------------- */
-    CPLString osMDFilename;
+    CPLString osMDFilename, osImageDSFilename;;
 
     if( poOpenInfo->bIsDirectory )
     {
+        VSIStatBufL sStat;
+
         osMDFilename = 
             CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
+
+	/* DIMAP2 */
+	if( VSIStatL( osMDFilename, &sStat ) != 0 )
+	  osMDFilename = 
+            CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
     }
     else
         osMDFilename = poOpenInfo->pszFilename;
@@ -273,20 +360,130 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Ingest the xml file.                                            */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psProduct, *psImageAttributes;
+    CPLXMLNode *psProductDim = NULL, *psProductStrip = NULL;
+
+    float nMetadataFormatVersion;
 
     psProduct = CPLParseXMLFile( osMDFilename );
     if( psProduct == NULL )
-        return NULL;
+	  return NULL;
 
     CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
-    psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
-    if( psImageAttributes == NULL )
+    if( !psDoc )
+        psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
+
+    /* 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") );
+    if( nMetadataFormatVersion >= 2.0 )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Failed to find <Raster_Dimensions> in document." );
-        return NULL;
+      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;
+	}
+    }
+    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;
+	}
+      
+	CPLString osDIMAPFilename;
+	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 )
+            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;
+	}
     }
-
 
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
@@ -294,6 +491,39 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
     DIMAPDataset *poDS = new DIMAPDataset();
 
     poDS->psProduct = psProduct;
+    poDS->psProductDim = psProductDim;
+    poDS->psProductStrip = psProductStrip;
+    poDS->nProductVersion = nProductVersion;
+    poDS->osMDFilename = osMDFilename;
+    poDS->osImageDSFilename = osImageDSFilename;
+
+    int res = TRUE;
+    if( nProductVersion == 2 )
+	res = poDS->ReadImageInformation2();
+    else
+	res = poDS->ReadImageInformation();
+    
+    if( res == FALSE )
+    {
+	delete poDS;
+	return NULL;
+    }
+
+    return( poDS );
+}
+
+
+/************************************************************************/
+/*               ReadImageInformation() DIMAP Version 1                 */
+/************************************************************************/
+
+int DIMAPDataset::ReadImageInformation()
+{
+    CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
+    if( !psDoc )
+        psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
+
+    CPLXMLNode *psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
 
 /* -------------------------------------------------------------------- */
 /*      Get overall image information.                                  */
@@ -303,14 +533,15 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
         atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
 #endif
 
-    poDS->nRasterXSize = 
+    nRasterXSize = 
         atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
-    poDS->nRasterYSize = 
+    nRasterYSize = 
         atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
 
 /* -------------------------------------------------------------------- */
 /*      Get the name of the underlying file.                            */
 /* -------------------------------------------------------------------- */
+
     const char *pszHref = CPLGetXMLValue(
         psDoc, "Data_Access.Data_File.DATA_FILE_PATH.href", "" );
     CPLString osPath = CPLGetPath(osMDFilename);
@@ -320,21 +551,21 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try and open the file.                                          */
 /* -------------------------------------------------------------------- */
-    poDS->poImageDS = (GDALDataset *) GDALOpen( osImageFilename, GA_ReadOnly );
-    if( poDS->poImageDS == NULL )
+
+    poImageDS = (GDALDataset *) GDALOpen( osImageFilename, GA_ReadOnly );
+    if( poImageDS == NULL )
     {
-        delete poDS;
-        return NULL;
+        return FALSE;
     }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Attach the bands.                                               */
 /* -------------------------------------------------------------------- */
     int iBand;
-    CPLAssert( nBands == poDS->poImageDS->GetRasterCount() );
+    CPLAssert( nBands == poImageDS->GetRasterCount() );
 
-    for( iBand = 1; iBand <= poDS->poImageDS->GetRasterCount(); iBand++ )
-        poDS->SetBand( iBand, poDS->poImageDS->GetRasterBand( iBand ) );
+    for( iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
+        SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
 
 /* -------------------------------------------------------------------- */
 /*      Try to collect simple insertion point.                          */
@@ -344,13 +575,13 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( psGeoLoc != NULL )
     {
-        poDS->bHaveGeoTransform = TRUE;
-        poDS->adfGeoTransform[0] = atof(CPLGetXMLValue(psGeoLoc,"ULXMAP","0"));
-        poDS->adfGeoTransform[1] = atof(CPLGetXMLValue(psGeoLoc,"XDIM","0"));
-        poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = atof(CPLGetXMLValue(psGeoLoc,"ULYMAP","0"));
-        poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = -atof(CPLGetXMLValue(psGeoLoc,"YDIM","0"));
+        bHaveGeoTransform = TRUE;
+        adfGeoTransform[0] = atof(CPLGetXMLValue(psGeoLoc,"ULXMAP","0"));
+        adfGeoTransform[1] = atof(CPLGetXMLValue(psGeoLoc,"XDIM","0"));
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = atof(CPLGetXMLValue(psGeoLoc,"ULYMAP","0"));
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = -atof(CPLGetXMLValue(psGeoLoc,"YDIM","0"));
     }
 
 /* -------------------------------------------------------------------- */
@@ -363,31 +594,31 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLXMLNode *psNode;					       
 
         // count gcps.
-        poDS->nGCPCount = 0;
+        nGCPCount = 0;
         for( psNode = psGeoLoc->psChild; psNode != NULL;
              psNode = psNode->psNext )
         {
             if( EQUAL(psNode->pszValue,"Tie_Point") )
-                poDS->nGCPCount++ ;
+                nGCPCount++ ;
         }
 
-        poDS->pasGCPList = (GDAL_GCP *) 
-            CPLCalloc(sizeof(GDAL_GCP),poDS->nGCPCount);
+        pasGCPList = (GDAL_GCP *) 
+            CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
         
-        poDS->nGCPCount = 0;
+        nGCPCount = 0;
         
         for( psNode = psGeoLoc->psChild; psNode != NULL;
              psNode = psNode->psNext )
         {
             char	szID[32];
-            GDAL_GCP   *psGCP = poDS->pasGCPList + poDS->nGCPCount;
+            GDAL_GCP   *psGCP = pasGCPList + nGCPCount;
             
             if( !EQUAL(psNode->pszValue,"Tie_Point") )
                 continue;
 
-            poDS->nGCPCount++ ;
+            nGCPCount++ ;
 
-            sprintf( szID, "%d", poDS->nGCPCount );
+            sprintf( szID, "%d", nGCPCount );
             psGCP->pszId = CPLStrdup( szID );
             psGCP->pszInfo = CPLStrdup("");
             psGCP->dfGCPPixel = 
@@ -416,20 +647,30 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
         OGRSpatialReference oSRS;
         if( oSRS.SetFromUserInput( pszSRS ) == OGRERR_NONE )
         {
-            if( poDS->nGCPCount > 0 )
+            if( nGCPCount > 0 )
             {
-                CPLFree(poDS->pszGCPProjection);
-                oSRS.exportToWkt( &(poDS->pszGCPProjection) );
+                CPLFree(pszGCPProjection);
+                oSRS.exportToWkt( &(pszGCPProjection) );
             }
             else
             {
                 char *pszProjection = NULL;
                 oSRS.exportToWkt( &pszProjection );
-                poDS->osProjection = pszProjection;
+                osProjection = pszProjection;
                 CPLFree( pszProjection );
             }
         }
     }
+    else  
+    { 
+        // Check underlying raster for SRS. We have cases where 
+        // HORIZONTAL_CS_CODE is empty and the underlying raster 
+        // is georeferenced (rprinceley).
+        if ( poImageDS->GetProjectionRef() ) 
+        { 
+            osProjection = poImageDS->GetProjectionRef(); 
+        } 
+    } 
 
 /* -------------------------------------------------------------------- */
 /*      Translate other metadata of interest.                           */
@@ -444,47 +685,14 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
             NULL, NULL
         };
 
-    int iTrItem;
-    
-    for( iTrItem = 0; apszMetadataTranslation[iTrItem] != NULL; iTrItem += 2 )
-    {
-        CPLXMLNode *psParent = 
-            CPLGetXMLNode( psDoc, apszMetadataTranslation[iTrItem] );
-
-        if( psParent == NULL )
-            continue;
-
-        // hackey logic to support directly access a name/value entry
-        // or a parent element with many name/values. 
-
-        CPLXMLNode *psTarget;
-        if( psParent->psChild != NULL 
-            && psParent->psChild->eType == CXT_Text )
-            psTarget = psParent;
-        else
-            psTarget = psParent->psChild;
-
-        for( ; psTarget != NULL && psTarget != psParent; 
-             psTarget = psTarget->psNext ) 
-        {
-            if( psTarget->eType == CXT_Element
-                && psTarget->psChild != NULL
-                && psTarget->psChild->eType == CXT_Text )
-            {
-                CPLString osName = apszMetadataTranslation[iTrItem+1];
-
-                osName += psTarget->pszValue;
-                poDS->SetMetadataItem( osName, psTarget->psChild->pszValue );
-            }
-        }
-    }
+    SetMetadata(psProduct, apszMetadataTranslation);
 
 /* -------------------------------------------------------------------- */
 /*      Set Band metadata from the <Spectral_Band_Info> content         */
 /* -------------------------------------------------------------------- */
 
     CPLXMLNode *psImageInterpretationNode = 
-            CPLGetXMLNode( psDoc, "Image_Interpretation" );
+        CPLGetXMLNode( psDoc, "Image_Interpretation" );
     if (psImageInterpretationNode != NULL)
     {
         CPLXMLNode *psSpectralBandInfoNode = psImageInterpretationNode->psChild;
@@ -504,7 +712,7 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
                         {
                             nBandIndex = atoi(psTag->psChild->pszValue);
                             if (nBandIndex <= 0 ||
-                                nBandIndex > poDS->poImageDS->GetRasterCount())
+                                nBandIndex > poImageDS->GetRasterCount())
                             {
                                 CPLError(CE_Warning, CPLE_AppDefined,
                                          "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
@@ -513,8 +721,8 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
                         }
                         else if (nBandIndex >= 1)
                         {
-                            poDS->GetRasterBand(nBandIndex)->SetMetadataItem(
-                                    psTag->pszValue, psTag->psChild->pszValue);
+                            GetRasterBand(nBandIndex)->SetMetadataItem(
+                                psTag->pszValue, psTag->psChild->pszValue);
                         }
                     }
                     psTag = psTag->psNext;
@@ -527,15 +735,329 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
-    poDS->SetDescription( osMDFilename );
-    poDS->TryLoadXML();
+    SetDescription( osMDFilename );
+    TryLoadXML();
 
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, osMDFilename );
+    oOvManager.Initialize( this, osMDFilename );
 
-    return( poDS );
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*               ReadImageInformation() DIMAP Version 2                 */
+/************************************************************************/
+
+int DIMAPDataset::ReadImageInformation2()
+{
+    CPLXMLNode *psDoc = CPLGetXMLNode( psProductDim, "=Dimap_Document" );
+    if( !psDoc )
+        psDoc = CPLGetXMLNode( psProductDim, "=PHR_DIMAP_Document" );
+
+    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;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get overall image information.                                  */
+/* -------------------------------------------------------------------- */
+#ifdef DEBUG
+    int nBands = 
+        atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
+#endif
+
+    nRasterXSize = 
+        atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
+    nRasterYSize = 
+        atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
+
+/* -------------------------------------------------------------------- */
+/*      Get the name of the underlying file.                            */
+/* -------------------------------------------------------------------- */
+
+    /* 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(osMDFilename);
+	    osImageDSFilename = 
+		CPLFormFilename( osPath, pszHref, NULL );
+	}
+	else
+	{
+	    CPLError( CE_Failure, CPLE_OpenFailed, 
+		      "Failed to find <DATA_FILE_PATH> in document." );
+	    return FALSE;
+	}
+    }
+
+
+/* -------------------------------------------------------------------- */
+/*      Try and open the file.                                          */
+/* -------------------------------------------------------------------- */
+    poImageDS = (GDALDataset *) GDALOpen( osImageDSFilename, GA_ReadOnly );
+    if( poImageDS == NULL )
+    {
+        return FALSE;
+    }
+
+
+/* -------------------------------------------------------------------- */
+/*      Attach the bands.                                               */
+/* -------------------------------------------------------------------- */
+    int iBand;
+    CPLAssert( nBands == poImageDS->GetRasterCount() );
+
+    for( iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
+        SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
+
+/* -------------------------------------------------------------------- */
+/*      Try to collect simple insertion point.                          */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psGeoLoc =  
+        CPLGetXMLNode( psDoc, "Geoposition.Geoposition_Insert" );
+
+    if( psGeoLoc != NULL )
+    {
+        bHaveGeoTransform = TRUE;
+        adfGeoTransform[0] = atof(CPLGetXMLValue(psGeoLoc,"ULXMAP","0"));
+        adfGeoTransform[1] = atof(CPLGetXMLValue(psGeoLoc,"XDIM","0"));
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = atof(CPLGetXMLValue(psGeoLoc,"ULYMAP","0"));
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = -atof(CPLGetXMLValue(psGeoLoc,"YDIM","0"));
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect the CRS.  For now we look only for EPSG codes.          */
+/* -------------------------------------------------------------------- */
+    const char *pszSRS = CPLGetXMLValue( 
+        psDoc, 
+        "Coordinate_Reference_System.Projected_CRS..PROJECTED_CRS_CODE", 
+        NULL );
+
+    if( pszSRS != NULL )
+    {
+        OGRSpatialReference oSRS;
+        if( oSRS.SetFromUserInput( pszSRS ) == OGRERR_NONE )
+        {
+            if( nGCPCount > 0 )
+            {
+                CPLFree(pszGCPProjection);
+                oSRS.exportToWkt( &(pszGCPProjection) );
+            }
+            else
+            {
+                char *pszProjection = NULL;
+                oSRS.exportToWkt( &pszProjection );
+                osProjection = pszProjection;
+                CPLFree( pszProjection );
+            }
+        }
+    }
+    else  
+    { 
+        // Check underlying raster for SRS. We have cases where 
+        // HORIZONTAL_CS_CODE is empty and the underlying raster 
+        // is georeferenced (rprinceley).
+        if ( poImageDS->GetProjectionRef() ) 
+        { 
+            osProjection = poImageDS->GetProjectionRef(); 
+        } 
+    } 
+
+/* -------------------------------------------------------------------- */
+/*      Translate other metadata of interest: DIM_<product_name>.XML    */
+/* -------------------------------------------------------------------- */
+
+    static const char *apszMetadataTranslationDim[] = 
+    {
+	    "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_",
+            NULL, NULL
+        };
+
+    SetMetadata(psProductDim, apszMetadataTranslationDim);
+
+/* -------------------------------------------------------------------- */
+/*      Translate other metadata of interest: STRIP_<product_name>.XML    */
+/* -------------------------------------------------------------------- */
+
+    static const char *apszMetadataTranslationStrip[] = 
+    {
+	    "Catalog.Full_Strip.Notations.Cloud_And_Quality_Notation.Data_Strip_Notation", "CLOUDCOVER_",
+	    "Acquisition_Configuration.Platform_Configuration.Ephemeris_Configuration", "EPHEMERIS_",
+            NULL, NULL
+    };
+
+    SetMetadata(psProductStrip, apszMetadataTranslationStrip);
+
+/* -------------------------------------------------------------------- */
+/*      Set Band metadata from the <Band_Radiance> and                  */
+/*                                <Band_Spectral_Range> content         */
+/* -------------------------------------------------------------------- */
+    
+    CPLXMLNode *psImageInterpretationNode = 
+        CPLGetXMLNode( psDoc, 
+    		       "Radiometric_Data.Radiometric_Calibration.Instrument_Calibration.Band_Measurement_List" );
+    if (psImageInterpretationNode != NULL)
+    {
+        CPLXMLNode *psSpectralBandInfoNode = psImageInterpretationNode->psChild;
+        while (psSpectralBandInfoNode != NULL)
+        {
+            if (psSpectralBandInfoNode->eType == CXT_Element &&
+                (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance") ||
+		 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_";
+
+                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;
+    	}
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    SetDescription( osMDFilename );
+    TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    oOvManager.Initialize( this, osMDFilename );
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            SetMetadata()                             */
+/************************************************************************/
+
+void DIMAPDataset::SetMetadata(CPLXMLNode *psProduct, const char *apszMetadataTranslation[])
+{
+    CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
+    if( psDoc == NULL ) 
+    {
+      psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
+    }
+
+    int iTrItem;
+    
+    for( iTrItem = 0; apszMetadataTranslation[iTrItem] != NULL; iTrItem += 2 )
+    {
+        CPLXMLNode *psParent = 
+            CPLGetXMLNode( psDoc, apszMetadataTranslation[iTrItem] );
+
+        if( psParent == NULL )
+            continue;
+
+        // hackey logic to support directly access a name/value entry
+        // or a parent element with many name/values. 
+
+        CPLXMLNode *psTarget;
+        if( psParent->psChild != NULL 
+            && psParent->psChild->eType == CXT_Text )
+            psTarget = psParent;
+        else
+            psTarget = psParent->psChild;
+
+        for( ; psTarget != NULL && psTarget != psParent; 
+             psTarget = psTarget->psNext ) 
+        {
+            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 );
+			}   
+		    }
+		}
+	    } 
+	}
+    }
 }
 
 /************************************************************************/
diff --git a/frmts/dted/dted_api.c b/frmts/dted/dted_api.c
index b8eae5f..e2d1058 100644
--- a/frmts/dted/dted_api.c
+++ b/frmts/dted/dted_api.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_api.c 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: dted_api.c 22606 2011-06-28 20:31:23Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  Implementation of DTED/CDED access functions.
@@ -30,7 +30,7 @@
 #include "dted_api.h"
 
 #ifndef AVOID_CPL
-CPL_CVSID("$Id: dted_api.c 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: dted_api.c 22606 2011-06-28 20:31:23Z rouault $");
 #endif
 
 static int bWarnedTwoComplement = FALSE;
@@ -563,7 +563,6 @@ int DTEDWriteProfile( DTEDInfo * psDInfo, int nColumnOffset,
     if( VSIFSeekL( psDInfo->fp, nOffset, SEEK_SET ) != 0
         || VSIFWriteL( pabyRecord,(12+psDInfo->nYSize*2),1,psDInfo->fp ) != 1)
     {
-        CPLFree( pabyRecord );
 #ifndef AVOID_CPL
         CPLError( CE_Failure, CPLE_FileIO,
 #else
diff --git a/frmts/dted/dted_ptstream.c b/frmts/dted/dted_ptstream.c
index 2c2dfb6..f6d4f35 100644
--- a/frmts/dted/dted_ptstream.c
+++ b/frmts/dted/dted_ptstream.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_ptstream.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: dted_ptstream.c 23425 2011-11-26 19:14:25Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  DTED Point Stream Writer.
@@ -29,7 +29,7 @@
 
 #include "dted_api.h"
 
-CPL_CVSID("$Id: dted_ptstream.c 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: dted_ptstream.c 23425 2011-11-26 19:14:25Z rouault $");
 
 typedef struct {
     char     *pszFilename;
@@ -563,7 +563,7 @@ void DTEDPtStreamSetMetadata( void *hStream, DTEDMetaDataCode eCode,
 {
     DTEDPtStream *psStream = (DTEDPtStream *) hStream;
 
-    if( eCode >= 0 && eCode < DTEDMD_MAX+1 )
+    if( (int)eCode >= 0 && eCode < DTEDMD_MAX+1 )
     {
         CPLFree( psStream->apszMetadata[eCode] );
         psStream->apszMetadata[eCode] = CPLStrdup( pszValue );
diff --git a/frmts/dted/dteddataset.cpp b/frmts/dted/dteddataset.cpp
index 7be59b9..ded5849 100644
--- a/frmts/dted/dteddataset.cpp
+++ b/frmts/dted/dteddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dteddataset.cpp 20763 2010-10-04 22:04:10Z rouault $
+ * $Id: dteddataset.cpp 21837 2011-02-24 21:16:42Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  GDALDataset driver for DTED translator.
@@ -31,7 +31,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dteddataset.cpp 20763 2010-10-04 22:04:10Z rouault $");
+CPL_CVSID("$Id: dteddataset.cpp 21837 2011-02-24 21:16:42Z rouault $");
 
 CPL_C_START
 void    GDALRegister_DTED(void);
@@ -65,6 +65,7 @@ class DTEDDataset : public GDALPamDataset
     void SetFileName(const char* pszFilename);
     
     static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
 };
 
 /************************************************************************/
@@ -278,27 +279,26 @@ void DTEDDataset::SetFileName(const char* pszFilename)
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                              Identify()                              */
 /************************************************************************/
 
-GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
+int DTEDDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
     int         i;
-    DTEDInfo    *psDTED;
 
 /* -------------------------------------------------------------------- */
 /*      Does the file start with one of the possible DTED header        */
 /*      record types, and do we have a UHL marker?                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 240 )
-        return NULL;
+        return FALSE;
 
     if( !EQUALN((const char *)poOpenInfo->pabyHeader,"VOL",3)
         && !EQUALN((const char *)poOpenInfo->pabyHeader,"HDR",3)
         && !EQUALN((const char *)poOpenInfo->pabyHeader,"UHL",3) )
     {
-        return NULL;
+        return FALSE;
     }
 
     int bFoundUHL = FALSE;
@@ -310,6 +310,22 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
     if (!bFoundUHL)
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    int         i;
+    DTEDInfo    *psDTED;
+
+    if (!Identify(poOpenInfo))
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -346,7 +362,7 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    poDS->nBands = 1;;
+    poDS->nBands = 1;
     for( i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new DTEDRasterBand( poDS, i+1 ) );
 
@@ -894,6 +910,7 @@ void GDALRegister_DTED()
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = DTEDDataset::Open;
+        poDriver->pfnIdentify = DTEDDataset::Identify;
         poDriver->pfnCreateCopy = DTEDCreateCopy;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
diff --git a/frmts/e00grid/GNUmakefile b/frmts/e00grid/GNUmakefile
new file mode 100644
index 0000000..f417687
--- /dev/null
+++ b/frmts/e00grid/GNUmakefile
@@ -0,0 +1,15 @@
+
+include ../../GDALmake.opt
+
+OBJ	=	e00griddataset.o
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(XTRA_OPT)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o
+
+all:	$(OBJ:.o=.$(OBJ_EXT))
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/e00grid/e00compr.h b/frmts/e00grid/e00compr.h
new file mode 100644
index 0000000..a92bd93
--- /dev/null
+++ b/frmts/e00grid/e00compr.h
@@ -0,0 +1,181 @@
+/**********************************************************************
+ * $Id: e00compr.h,v 1.10 2009-02-24 20:03:50 aboudreault Exp $
+ *
+ * Name:     e00compr.h
+ * Project:  Compressed E00 Read/Write library
+ * Language: ANSI C
+ * Purpose:  Header file containing all definitions for the library.
+ * Author:   Daniel Morissette, dmorissette at mapgears.com
+ *
+ * $Log: e00compr.h,v $
+ * Revision 1.10  2009-02-24 20:03:50  aboudreault
+ * Added a short manual pages (#1875)
+ * Updated documentation and code examples (#247)
+ *
+ * Revision 1.9  2005-09-17 14:22:05  daniel
+ * Switch to MIT license, update refs to website and email address, and
+ * prepare for 1.0.0 release.
+ *
+ * Revision 1.8  1999/03/03 18:47:07  daniel
+ * Moved extern "C" after #include lines (form MSVC++ 6)
+ *
+ * Revision 1.7  1999/02/25 18:47:40  daniel
+ * Now use CPL for Error handling, Memory allocation, and File access.
+ *
+ * Revision 1.6  1999/01/08 17:40:33  daniel
+ * Added E00Read/WriteCallbakcOpen()
+ *
+ * Revision 1.5  1998/11/13 15:39:45  daniel
+ * Added functions for write support.
+ *
+ * Revision 1.4  1998/11/02 18:37:03  daniel
+ * New file header, and added E00ErrorReset()
+ *
+ * Revision 1.1  1998/10/29 13:26:00  daniel
+ * Initial revision
+ *
+ **********************************************************************
+ * Copyright (c) 1998-2005, Daniel Morissette
+ *
+ * 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 _E00COMPR_H_INCLUDED_
+#define _E00COMPR_H_INCLUDED_
+
+
+#include <stdio.h>
+
+#include "cpl_port.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------
+ * Current version of the library... always useful!
+ *--------------------------------------------------------------------*/
+#define E00COMPR_VERSION "1.0.0 (2005-09-17)"
+
+/*=====================================================================
+                        Data types and constants
+ =====================================================================*/
+
+#define E00_READ_BUF_SIZE   256 /* E00 lines are always 80 chars or less */
+                                /* for both compressed and uncompressed  */
+                                /* files, except the first line (the EXP)*/
+                                /* for which there is no known limit     */
+                                /* We'll assume that it can't be longer  */
+                                /* than 256 chars                        */
+
+#define E00_WRITE_BUF_SIZE  256 /* This buffer must be big enough to hold*/
+                                /* at least 2 lines of compressed output */
+                                /* (i.e. 160 chars)... but just in case  */
+                                /* compressing a line would ever result  */
+                                /* in it becoming bigger than its source */
+                                /* we'll set the size to 256 chars!      */
+
+#define E00_COMPR_NONE      0   /* Compression levels to use when writing*/
+#define E00_COMPR_PARTIAL   1
+#define E00_COMPR_FULL      2
+
+/*---------------------------------------------------------------------
+ *                          E00ReadPtr
+ *
+ * A E00ReadPtr handle is used to hold information about the compressed 
+ * file currently being read.
+ *--------------------------------------------------------------------*/
+struct _E00ReadInfo
+{
+    FILE    *fp;            /* Input file handle */
+    int     bEOF;           /* Reached EOF?      */
+    int     bIsCompressed;  /* 1 if file is compressed, 0 if not    */
+    int     nInputLineNo;
+
+    int     iInBufPtr;      /* Last character processed in szInBuf  */
+    char    szInBuf[E00_READ_BUF_SIZE]; /* compressed input buffer  */
+    char    szOutBuf[E00_READ_BUF_SIZE];/* uncompressed output buffer   */
+
+    /* pRefData, pfnReadNextLine() and pfnReadRewind() are used only
+     * when the file is opened with E00ReadCallbackOpen()
+     * (and in this case the FILE *fp defined above is not used)
+     */
+    void       * pRefData;
+    const char * (*pfnReadNextLine)(void *);
+    void         (*pfnReadRewind)(void *);
+};
+
+typedef struct _E00ReadInfo *E00ReadPtr;
+
+/*---------------------------------------------------------------------
+ *                          E00WritePtr
+ *
+ * A E00WritePtr handle is used to hold information about the 
+ * file currently being written.
+ *--------------------------------------------------------------------*/
+struct _E00WriteInfo
+{
+    FILE    *fp;            /* Output file handle */
+    int     nComprLevel;
+
+    int     nSrcLineNo;
+
+    int     iOutBufPtr;     /* Current position in szOutBuf  */
+    char    szOutBuf[E00_WRITE_BUF_SIZE]; /* compressed output buffer */
+
+    /* pRefData and pfnWriteNextLine() are used only
+     * when the file is opened with E00WriteCallbackOpen()
+     * (and in this case the FILE *fp defined above is not used)
+     */
+    void    *pRefData;
+    int     (*pfnWriteNextLine)(void *, const char *);
+};
+
+typedef struct _E00WriteInfo *E00WritePtr;
+
+
+/*=====================================================================
+                        Function prototypes
+ =====================================================================*/
+
+E00ReadPtr  E00ReadOpen(const char *pszFname);
+E00ReadPtr  E00ReadCallbackOpen(void *pRefData,
+                                const char * (*pfnReadNextLine)(void *),
+                                void (*pfnReadRewind)(void *));
+void        E00ReadClose(E00ReadPtr psInfo);
+
+const char *E00ReadNextLine(E00ReadPtr psInfo);
+void        E00ReadRewind(E00ReadPtr psInfo);
+
+E00WritePtr E00WriteOpen(const char *pszFname, int nComprLevel);
+E00WritePtr E00WriteCallbackOpen(void *pRefData,
+                                 int (*pfnWriteNextLine)(void *, const char *),
+                                 int nComprLevel);
+void        E00WriteClose(E00WritePtr psInfo);
+int         E00WriteNextLine(E00WritePtr psInfo, const char *pszLine);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _E00COMPR_H_INCLUDED_ */
diff --git a/frmts/e00grid/e00griddataset.cpp b/frmts/e00grid/e00griddataset.cpp
new file mode 100644
index 0000000..fcc8f73
--- /dev/null
+++ b/frmts/e00grid/e00griddataset.cpp
@@ -0,0 +1,924 @@
+/******************************************************************************
+ * $Id: e00griddataset.cpp 23618 2011-12-20 22:27:21Z 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
+ *
+ * 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_vsi_virtual.h"
+#include "cpl_string.h"
+#include "ogr_spatialref.h"
+#include "gdal_pam.h"
+
+/* Private import of e00read.c */
+#define E00ReadOpen         GDALE00GRIDReadOpen
+#define E00ReadCallbackOpen GDALE00GRIDReadCallbackOpen
+#define E00ReadClose        GDALE00GRIDReadClose
+#define E00ReadNextLine     GDALE00GRIDReadNextLine
+#define E00ReadRewind       GDALE00GRIDReadRewind
+#include "e00read.c"
+
+#define E00_INT_SIZE    10
+#define E00_INT14_SIZE  14
+#define E00_FLOAT_SIZE  14
+#define E00_DOUBLE_SIZE 21
+#define VALS_PER_LINE   5
+
+CPL_CVSID("$Id: e00griddataset.cpp 23618 2011-12-20 22:27:21Z rouault $");
+
+CPL_C_START
+void    GDALRegister_E00GRID(void);
+CPL_C_END
+
+/* g++ -fPIC -Wall -g frmts/e00grid/e00griddataset.cpp -shared -o gdal_E00GRID.so -Iport -Igcore -Iogr -L. -lgdal */
+
+/* Test data ; (google for "EXP  0" "GRD  2")
+
+ftp://msdis.missouri.edu/pub/dem/24k/county/
+http://dusk.geo.orst.edu/djl/samoa/data/samoa_bathy.e00
+http://dusk.geo.orst.edu/djl/samoa/FBNMS/RasterGrids-Metadata/ntae02_3m_utm.e00
+http://www.navdat.org/coverages/elevation/iddem1.e00        (int32)
+http://delta-vision.projects.atlas.ca.gov/lidar/bare_earth.grids/sac0165.e00
+http://ag.arizona.edu/SRER/maps_e00/srer_dem.e00
+http://ok.water.usgs.gov/projects/norlan/spatial/ntopo0408-10.e00 (compressed)
+http://wrri.nmsu.edu/publish/techrpt/tr322/GIS/dem.e00 (compressed)
+*/
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            E00GRIDDataset                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class E00GRIDRasterBand;
+
+class E00GRIDDataset : public GDALPamDataset
+{
+    friend class E00GRIDRasterBand;
+
+    E00ReadPtr  e00ReadPtr;
+    VSILFILE   *fp;
+    vsi_l_offset nDataStart;
+    int         nBytesEOL;
+
+    vsi_l_offset  nPosBeforeReadLine;
+    vsi_l_offset* panOffsets;
+    int         nLastYOff;
+    int         nMaxYOffset;
+
+    double      adfGeoTransform[6];
+    CPLString   osProjection;
+
+    double      dfNoData;
+
+    char**      papszPrj;
+
+    const char* ReadLine();
+
+    int         bHasReadMetadata;
+    void        ReadMetadata();
+
+    int         bHasStats;
+    double      dfMin, dfMax, dfMean, dfStddev;
+
+    static const char* ReadNextLine(void * ptr);
+    static void        Rewind(void* ptr);
+
+  public:
+                 E00GRIDDataset();
+    virtual     ~E00GRIDDataset();
+    
+    virtual CPLErr GetGeoTransform( double * );
+    virtual const char* GetProjectionRef();
+    
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          E00GRIDRasterBand                           */
+/* ==================================================================== */
+/************************************************************************/
+
+class E00GRIDRasterBand : public GDALPamRasterBand
+{
+    friend class E00GRIDDataset;
+
+  public:
+
+                E00GRIDRasterBand( E00GRIDDataset *, int, GDALDataType );
+
+    virtual CPLErr      IReadBlock( int, int, void * );
+
+    virtual double      GetNoDataValue( int *pbSuccess = NULL );
+    virtual const char *GetUnitType();
+    virtual double      GetMinimum( int *pbSuccess = NULL );
+    virtual double      GetMaximum( int *pbSuccess = NULL );
+    virtual CPLErr      GetStatistics( int bApproxOK, int bForce,
+                                       double *pdfMin, double *pdfMax,
+                                       double *pdfMean, double *padfStdDev );
+};
+
+
+/************************************************************************/
+/*                         E00GRIDRasterBand()                          */
+/************************************************************************/
+
+E00GRIDRasterBand::E00GRIDRasterBand( E00GRIDDataset *poDS, int nBand,
+                                      GDALDataType eDT )
+
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+
+    eDataType = eDT;
+
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr E00GRIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                      void * pImage )
+
+{
+    E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
+
+    char szVal[E00_FLOAT_SIZE+1];
+    szVal[E00_FLOAT_SIZE] = 0;
+
+    int i;
+    float* pafImage = (float*)pImage;
+    int* panImage = (int*)pImage;
+    const float fNoData = (const float)poGDS->dfNoData;
+
+    /* A new data line begins on a new text line. So if the xsize */
+    /* is not a multiple of VALS_PER_LINE, there are padding values */
+    /* that must be ignored */
+    const int nRoundedBlockXSize = ((nBlockXSize + VALS_PER_LINE - 1) /
+                                            VALS_PER_LINE) * VALS_PER_LINE;
+
+    if (poGDS->e00ReadPtr)
+    {
+        if (poGDS->nLastYOff < 0)
+        {
+            E00ReadRewind(poGDS->e00ReadPtr);
+            for(i=0;i<6;i++)
+                E00ReadNextLine(poGDS->e00ReadPtr);
+        }
+
+        if (nBlockYOff == poGDS->nLastYOff + 1)
+        {
+        }
+        else if (nBlockYOff <= poGDS->nMaxYOffset)
+        {
+            //CPLDebug("E00GRID", "Skip to %d from %d", nBlockYOff, poGDS->nLastYOff);
+            VSIFSeekL(poGDS->fp, poGDS->panOffsets[nBlockYOff], SEEK_SET);
+            poGDS->nPosBeforeReadLine = poGDS->panOffsets[nBlockYOff];
+            poGDS->e00ReadPtr->iInBufPtr = 0;
+            poGDS->e00ReadPtr->szInBuf[0] = '\0';
+        }
+        else if (nBlockYOff > poGDS->nLastYOff + 1)
+        {
+            //CPLDebug("E00GRID", "Forward skip to %d from %d", nBlockYOff, poGDS->nLastYOff);
+            for(i=poGDS->nLastYOff + 1; i < nBlockYOff;i++)
+                IReadBlock(0, i, pImage);
+        }
+
+        if (nBlockYOff > poGDS->nMaxYOffset)
+        {
+            poGDS->panOffsets[nBlockYOff] = poGDS->nPosBeforeReadLine +
+                                            poGDS->e00ReadPtr->iInBufPtr;
+            poGDS->nMaxYOffset = nBlockYOff;
+        }
+
+        const char* pszLine = NULL;
+        for(i=0;i<nBlockXSize;i++)
+        {
+            if ((i % VALS_PER_LINE) == 0)
+            {
+                pszLine = E00ReadNextLine(poGDS->e00ReadPtr);
+                if (pszLine == NULL || strlen(pszLine) < 5 * E00_FLOAT_SIZE)
+                    return CE_Failure;
+            }
+            if (eDataType == GDT_Float32)
+            {
+                pafImage[i] = (float) atof(pszLine + (i%VALS_PER_LINE) * E00_FLOAT_SIZE);
+                /* Workaround single vs double precision problems */
+                if (fNoData != 0 && fabs((pafImage[i] - fNoData)/fNoData) < 1e-6)
+                    pafImage[i] = fNoData;
+            }
+            else
+            {
+                panImage[i] = atoi(pszLine + (i%VALS_PER_LINE) * E00_FLOAT_SIZE);
+            }
+        }
+
+        poGDS->nLastYOff = nBlockYOff;
+
+        return CE_None;
+    }
+
+    vsi_l_offset nValsToSkip = (vsi_l_offset)nBlockYOff * nRoundedBlockXSize;
+    vsi_l_offset nLinesToSkip = nValsToSkip / VALS_PER_LINE;
+    int nBytesPerLine = VALS_PER_LINE * E00_FLOAT_SIZE + poGDS->nBytesEOL;
+    vsi_l_offset nPos = poGDS->nDataStart + nLinesToSkip * nBytesPerLine;
+    VSIFSeekL(poGDS->fp, nPos, SEEK_SET);
+
+    for(i=0;i<nBlockXSize;i++)
+    {
+        if (VSIFReadL(szVal, E00_FLOAT_SIZE, 1, poGDS->fp) != 1)
+            return CE_Failure;
+
+        if (eDataType == GDT_Float32)
+        {
+            pafImage[i] = (float) atof(szVal);
+            /* Workaround single vs double precision problems */
+            if (fNoData != 0 && fabs((pafImage[i] - fNoData)/fNoData) < 1e-6)
+                pafImage[i] = fNoData;
+        }
+        else
+        {
+            panImage[i] = atoi(szVal);
+        }
+
+        if (((i+1) % VALS_PER_LINE) == 0)
+            VSIFReadL(szVal, poGDS->nBytesEOL, 1, poGDS->fp);
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
+
+double E00GRIDRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
+
+    if (pbSuccess)
+        *pbSuccess = TRUE;
+
+    if (eDataType == GDT_Float32)
+        return (double)(float) poGDS->dfNoData;
+    else
+        return (double)(int)poGDS->dfNoData;
+}
+
+/************************************************************************/
+/*                             GetUnitType()                            */
+/************************************************************************/
+
+const char * E00GRIDRasterBand::GetUnitType()
+{
+    E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
+
+    poGDS->ReadMetadata();
+
+    if (poGDS->papszPrj == NULL)
+        return GDALPamRasterBand::GetUnitType();
+
+    char** papszIter = poGDS->papszPrj;
+    const char* pszRet = "";
+    while(*papszIter)
+    {
+        if (EQUALN(*papszIter, "Zunits", 6))
+        {
+            char** papszTokens = CSLTokenizeString(*papszIter);
+            if (CSLCount(papszTokens) == 2)
+            {
+                if (EQUAL(papszTokens[1], "FEET"))
+                    pszRet = "ft";
+                else if (EQUAL(papszTokens[1], "METERS"))
+                    pszRet = "m";
+            }
+            CSLDestroy(papszTokens);
+            break;
+        }
+        papszIter ++;
+    }
+
+    return pszRet;
+}
+
+/************************************************************************/
+/*                           GetMinimum()                               */
+/************************************************************************/
+
+double E00GRIDRasterBand::GetMinimum( int *pbSuccess )
+{
+    E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
+
+    poGDS->ReadMetadata();
+
+    if (poGDS->bHasStats)
+    {
+        if( pbSuccess != NULL )
+            *pbSuccess = TRUE;
+
+        return poGDS->dfMin;
+    }
+
+    return GDALPamRasterBand::GetMinimum( pbSuccess );
+}
+
+/************************************************************************/
+/*                           GetMaximum()                               */
+/************************************************************************/
+
+double E00GRIDRasterBand::GetMaximum( int *pbSuccess )
+{
+    E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
+
+    poGDS->ReadMetadata();
+
+    if (poGDS->bHasStats)
+    {
+        if( pbSuccess != NULL )
+            *pbSuccess = TRUE;
+
+        return poGDS->dfMax;
+    }
+
+    return GDALPamRasterBand::GetMaximum( pbSuccess );
+}
+
+/************************************************************************/
+/*                            GetStatistics()                           */
+/************************************************************************/
+
+CPLErr E00GRIDRasterBand::GetStatistics( int bApproxOK, int bForce,
+                                         double *pdfMin, double *pdfMax,
+                                         double *pdfMean, double *pdfStdDev )
+{
+    E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
+
+    poGDS->ReadMetadata();
+
+    if (poGDS->bHasStats)
+    {
+        if (pdfMin)
+            *pdfMin = poGDS->dfMin;
+        if (pdfMax)
+            *pdfMax = poGDS->dfMax;
+        if (pdfMean)
+            *pdfMean = poGDS->dfMean;
+        if (pdfStdDev)
+            *pdfStdDev = poGDS->dfStddev;
+        return CE_None;
+    }
+
+    return GDALPamRasterBand::GetStatistics(bApproxOK, bForce,
+                                            pdfMin, pdfMax,
+                                            pdfMean, pdfStdDev);
+}
+
+/************************************************************************/
+/*                           E00GRIDDataset()                           */
+/************************************************************************/
+
+E00GRIDDataset::E00GRIDDataset()
+{
+    e00ReadPtr = NULL;
+    fp = NULL;
+    nDataStart = 0;
+    nBytesEOL = 1;
+
+    nPosBeforeReadLine = 0;
+    panOffsets = NULL;
+    nLastYOff = -1;
+    nMaxYOffset = -1;
+
+    adfGeoTransform[0] = 0;
+    adfGeoTransform[1] = 1;
+    adfGeoTransform[2] = 0;
+    adfGeoTransform[3] = 0;
+    adfGeoTransform[4] = 0;
+    adfGeoTransform[5] = 1;
+
+    dfNoData = 0;
+
+    papszPrj = NULL;
+
+    bHasReadMetadata = FALSE;
+
+    bHasStats = FALSE;
+    dfMin = 0;
+    dfMax = 0;
+    dfMean = 0;
+    dfStddev = 0;
+}
+
+/************************************************************************/
+/*                           ~E00GRIDDataset()                          */
+/************************************************************************/
+
+E00GRIDDataset::~E00GRIDDataset()
+
+{
+    FlushCache();
+    if (fp)
+        VSIFCloseL(fp);
+    CSLDestroy(papszPrj);
+    E00ReadClose(e00ReadPtr);
+    CPLFree(panOffsets);
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int E00GRIDDataset::Identify( GDALOpenInfo * poOpenInfo )
+{
+    if (poOpenInfo->nHeaderBytes == 0)
+        return FALSE;
+
+    if (!(EQUALN((const char*)poOpenInfo->pabyHeader, "EXP  0", 6) ||
+          EQUALN((const char*)poOpenInfo->pabyHeader, "EXP  1", 6)))
+        return FALSE;
+
+    /* FIXME: handle GRD  3 if that ever exists ? */
+    if (strstr((const char*)poOpenInfo->pabyHeader, "GRD  2") == NULL)
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            ReadNextLine()                            */
+/************************************************************************/
+
+const char* E00GRIDDataset::ReadNextLine(void * ptr)
+{
+    E00GRIDDataset* poDS = (E00GRIDDataset*) ptr;
+    poDS->nPosBeforeReadLine = VSIFTellL(poDS->fp);
+    return CPLReadLine2L(poDS->fp, 256, NULL);
+}
+
+/************************************************************************/
+/*                                Rewind()                              */
+/************************************************************************/
+
+void E00GRIDDataset::Rewind(void * ptr)
+{
+    E00GRIDDataset* poDS = (E00GRIDDataset*) ptr;
+    VSIRewindL(poDS->fp);
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    int         i;
+    GDALDataType eDT = GDT_Float32;
+
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Find dataset characteristics                                    */
+/* -------------------------------------------------------------------- */
+    VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (fp == NULL)
+        return NULL;
+
+    if (poOpenInfo->eAccess == GA_Update)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported, 
+                  "The E00GRID driver does not support update access to existing"
+                  " datasets.\n" );
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    E00GRIDDataset         *poDS;
+
+    poDS = new E00GRIDDataset();
+    if (strstr((const char*)poOpenInfo->pabyHeader, "\r\n") != NULL)
+        poDS->nBytesEOL = 2;
+    poDS->fp = fp;
+
+    const char* pszLine;
+    /* read EXP  0 or EXP  1 line */
+    pszLine = CPLReadLine2L(fp, 81, NULL);
+    if (pszLine == NULL)
+    {
+        CPLDebug("E00GRID", "Bad 1st line");
+        delete poDS;
+        return NULL;
+    }
+    int bCompressed = EQUALN(pszLine, "EXP  1", 6);
+
+    E00ReadPtr e00ReadPtr = NULL;
+    if (bCompressed)
+    {
+        VSIRewindL(fp);
+        e00ReadPtr = E00ReadCallbackOpen(poDS,
+                                         E00GRIDDataset::ReadNextLine,
+                                         E00GRIDDataset::Rewind);
+        if (e00ReadPtr == NULL)
+        {
+            delete poDS;
+            return NULL;
+        }
+        E00ReadNextLine(e00ReadPtr);
+        poDS->e00ReadPtr = e00ReadPtr;
+    }
+
+    /* skip GRD  2 line */
+    if (e00ReadPtr)
+        pszLine = E00ReadNextLine(e00ReadPtr);
+    else
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+    if (pszLine == NULL || !EQUALN(pszLine, "GRD  2", 6))
+    {
+        CPLDebug("E00GRID", "Bad 2nd line");
+        delete poDS;
+        return NULL;
+    }
+
+    /* read ncols, nrows and nodata value */
+    if (e00ReadPtr)
+        pszLine = E00ReadNextLine(e00ReadPtr);
+    else
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+    if (pszLine == NULL || strlen(pszLine) <
+                E00_INT_SIZE+E00_INT_SIZE+2+E00_DOUBLE_SIZE)
+    {
+        CPLDebug("E00GRID", "Bad 3rd line");
+        delete poDS;
+        return NULL;
+    }
+
+    int nRasterXSize = atoi(pszLine);
+    int nRasterYSize = atoi(pszLine + E00_INT_SIZE);
+
+    if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    if (EQUALN(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 1", 2))
+        eDT = GDT_Int32;
+    else if (EQUALN(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 2", 2))
+        eDT = GDT_Float32;
+    else
+    {
+        CPLDebug("E00GRID", "Unknown data type : %s", pszLine);
+    }
+
+    double dfNoData = atof(pszLine + E00_INT_SIZE + E00_INT_SIZE + 2);
+
+    /* read pixel size */
+    if (e00ReadPtr)
+        pszLine = E00ReadNextLine(e00ReadPtr);
+    else
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+    if (pszLine == NULL || strlen(pszLine) < 2*E00_DOUBLE_SIZE)
+    {
+        CPLDebug("E00GRID", "Bad 4th line");
+        delete poDS;
+        return NULL;
+    }
+/*
+    double dfPixelX = atof(pszLine);
+    double dfPixelY = atof(pszLine + E00_DOUBLE_SIZE);
+*/
+
+    /* read xmin, ymin */
+    if (e00ReadPtr)
+        pszLine = E00ReadNextLine(e00ReadPtr);
+    else
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+    if (pszLine == NULL || strlen(pszLine) < 2*E00_DOUBLE_SIZE)
+    {
+        CPLDebug("E00GRID", "Bad 5th line");
+        delete poDS;
+        return NULL;
+    }
+    double dfMinX = atof(pszLine);
+    double dfMinY = atof(pszLine + E00_DOUBLE_SIZE);
+
+    /* read xmax, ymax */
+    if (e00ReadPtr)
+        pszLine = E00ReadNextLine(e00ReadPtr);
+    else
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+    if (pszLine == NULL || strlen(pszLine) < 2*E00_DOUBLE_SIZE)
+    {
+        CPLDebug("E00GRID", "Bad 6th line");
+        delete poDS;
+        return NULL;
+    }
+    double dfMaxX = atof(pszLine);
+    double dfMaxY = atof(pszLine + E00_DOUBLE_SIZE);
+
+    poDS->nRasterXSize = nRasterXSize;
+    poDS->nRasterYSize = nRasterYSize;
+    poDS->dfNoData = dfNoData;
+    poDS->adfGeoTransform[0] = dfMinX;
+    poDS->adfGeoTransform[1] = (dfMaxX - dfMinX) / nRasterXSize;
+    poDS->adfGeoTransform[2] = 0;
+    poDS->adfGeoTransform[3] = dfMaxY;
+    poDS->adfGeoTransform[4] = 0;
+    poDS->adfGeoTransform[5] = - (dfMaxY - dfMinY) / nRasterYSize;
+    poDS->nDataStart = VSIFTellL(fp);
+    if (bCompressed)
+    {
+        poDS->panOffsets = (vsi_l_offset*)
+                        VSIMalloc2(sizeof(vsi_l_offset), nRasterYSize);
+        if (poDS->panOffsets == NULL)
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    poDS->nBands = 1;
+    for( i = 0; i < poDS->nBands; i++ )
+        poDS->SetBand( i+1, new E00GRIDRasterBand( poDS, i+1, eDT ) );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Support overviews.                                              */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    return( poDS );
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr E00GRIDDataset::GetGeoTransform( double * padfTransform )
+
+{
+    memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
+
+    return( CE_None );
+}
+
+
+/************************************************************************/
+/*                             ReadLine()                               */
+/************************************************************************/
+
+const char* E00GRIDDataset::ReadLine()
+{
+    if (e00ReadPtr)
+        return E00ReadNextLine(e00ReadPtr);
+    else
+        return CPLReadLine2L(fp, 81, NULL);
+}
+
+/************************************************************************/
+/*                         GetProjectionRef()                           */
+/************************************************************************/
+
+const char* E00GRIDDataset::GetProjectionRef()
+
+{
+    ReadMetadata();
+    return osProjection.c_str();
+}
+
+/************************************************************************/
+/*                          ReadMetadata()                              */
+/************************************************************************/
+
+void E00GRIDDataset::ReadMetadata()
+
+{
+    if (bHasReadMetadata)
+        return;
+
+    bHasReadMetadata = TRUE;
+
+    if (e00ReadPtr == NULL)
+    {
+        int nRoundedBlockXSize = ((nRasterXSize + VALS_PER_LINE - 1) /
+                                                VALS_PER_LINE) * VALS_PER_LINE;
+        vsi_l_offset nValsToSkip =
+                               (vsi_l_offset)nRasterYSize * nRoundedBlockXSize;
+        vsi_l_offset nLinesToSkip = nValsToSkip / VALS_PER_LINE;
+        int nBytesPerLine = VALS_PER_LINE * E00_FLOAT_SIZE + nBytesEOL;
+        vsi_l_offset nPos = nDataStart + nLinesToSkip * nBytesPerLine;
+        VSIFSeekL(fp, nPos, SEEK_SET);
+    }
+    else
+    {
+        nLastYOff = -1;
+
+        const unsigned int BUFFER_SIZE = 65536;
+        const unsigned int NEEDLE_SIZE = 3*5;
+        const unsigned int nToRead = BUFFER_SIZE - NEEDLE_SIZE;
+        char* pabyBuffer = (char*)CPLCalloc(1, BUFFER_SIZE+NEEDLE_SIZE);
+        int nRead;
+        int bEOGFound = FALSE;
+
+        VSIFSeekL(fp, 0, SEEK_END);
+        vsi_l_offset nEndPos = VSIFTellL(fp);
+        if (nEndPos > BUFFER_SIZE)
+            nEndPos -= BUFFER_SIZE;
+        else
+            nEndPos = 0;
+        VSIFSeekL(fp, nEndPos, SEEK_SET);
+
+#define GOTO_NEXT_CHAR() \
+    i ++; \
+    if (pabyBuffer[i] == 13 || pabyBuffer[i] == 10) \
+    { \
+        i++; \
+        if (pabyBuffer[i] == 10) \
+            i++; \
+    } \
+
+        while ((nRead = VSIFReadL(pabyBuffer, 1, nToRead, fp)) != 0)
+        {
+            int i;
+            for(i = 0; i < nRead; i++)
+            {
+                if (pabyBuffer[i] == 'E')
+                {
+                    GOTO_NEXT_CHAR();
+                    if (pabyBuffer[i] == 'O')
+                    {
+                        GOTO_NEXT_CHAR();
+                        if (pabyBuffer[i] == 'G')
+                        {
+                            GOTO_NEXT_CHAR();
+                            if (pabyBuffer[i] == '~')
+                            {
+                                GOTO_NEXT_CHAR();
+                                if (pabyBuffer[i] == '}')
+                                {
+                                    bEOGFound = TRUE;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (bEOGFound)
+            {
+                VSIFSeekL(fp, VSIFTellL(fp) - nRead + i + 1, SEEK_SET);
+                e00ReadPtr->iInBufPtr = 0;
+                e00ReadPtr->szInBuf[0] = '\0';
+                break;
+            }
+
+            if (nEndPos == 0)
+                break;
+
+            if ((unsigned int)nRead == nToRead)
+            {
+                memmove(pabyBuffer + nToRead, pabyBuffer, NEEDLE_SIZE);
+                if (nEndPos >= (vsi_l_offset)nToRead)
+                    nEndPos -= nToRead;
+                else
+                    nEndPos = 0;
+                VSIFSeekL(fp, nEndPos, SEEK_SET);
+            }
+            else
+                break;
+        }
+        CPLFree(pabyBuffer);
+        if (!bEOGFound)
+            return;
+    }
+
+    const char* pszLine;
+    int bPRJFound = FALSE;
+    int bStatsFound = FALSE;
+    while((pszLine = ReadLine()) != NULL)
+    {
+        if (EQUALN(pszLine, "PRJ  2", 6))
+        {
+            bPRJFound = TRUE;
+            while((pszLine = ReadLine()) != NULL)
+            {
+                if (EQUAL(pszLine, "EOP"))
+                {
+                    break;
+                }
+                papszPrj = CSLAddString(papszPrj, pszLine);
+            }
+
+            OGRSpatialReference oSRS;
+            if( oSRS.importFromESRI( papszPrj ) != OGRERR_NONE )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                            "Failed to parse PRJ section, ignoring." );
+            }
+            else
+            {
+                char* pszWKT = NULL;
+                if (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE && pszWKT != NULL)
+                    osProjection = pszWKT;
+                CPLFree(pszWKT);
+            }
+            if (bStatsFound)
+                break;
+        }
+        else if (strcmp(pszLine, "STDV              8-1  254-1  15 3 60-1  -1  -1-1                   4-") == 0)
+        {
+            bStatsFound = TRUE;
+            pszLine = ReadLine();
+            if (pszLine)
+            {
+                CPLString osStats = pszLine;
+                pszLine = ReadLine();
+                if (pszLine)
+                {
+                    osStats += pszLine;
+                    char** papszTokens = CSLTokenizeString(osStats);
+                    if (CSLCount(papszTokens) == 4)
+                    {
+                        dfMin = atof(papszTokens[0]);
+                        dfMax = atof(papszTokens[1]);
+                        dfMean = atof(papszTokens[2]);
+                        dfStddev = atof(papszTokens[3]);
+                        bHasStats = TRUE;
+                    }
+                    CSLDestroy(papszTokens);
+                }
+            }
+            if (bPRJFound)
+                break;
+        }
+    }
+}
+
+/************************************************************************/
+/*                       GDALRegister_E00GRID()                         */
+/************************************************************************/
+
+void GDALRegister_E00GRID()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "E00GRID" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+        
+        poDriver->SetDescription( "E00GRID" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                   "Arc/Info Export E00 GRID" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
+                                   "frmt_various.html#E00GRID" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "e00" );
+
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnOpen = E00GRIDDataset::Open;
+        poDriver->pfnIdentify = E00GRIDDataset::Identify;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
+
diff --git a/frmts/e00grid/e00read.c b/frmts/e00grid/e00read.c
new file mode 100644
index 0000000..4a41dc4
--- /dev/null
+++ b/frmts/e00grid/e00read.c
@@ -0,0 +1,646 @@
+/**********************************************************************
+ * $Id: e00read.c,v 1.10 2009-02-24 20:03:50 aboudreault Exp $
+ *
+ * Name:     e00read.c
+ * Project:  Compressed E00 Read/Write library
+ * Language: ANSI C
+ * Purpose:  Functions to read Compressed E00 files and return a stream 
+ *           of uncompressed lines.
+ * Author:   Daniel Morissette, dmorissette at mapgears.com
+ *
+ * $Log: e00read.c,v $
+ * Revision 1.10  2009-02-24 20:03:50  aboudreault
+ * Added a short manual pages (#1875)
+ * Updated documentation and code examples (#247)
+ *
+ * Revision 1.9  2005-09-17 14:22:05  daniel
+ * Switch to MIT license, update refs to website and email address, and
+ * prepare for 1.0.0 release.
+ *
+ * Revision 1.8  1999/02/25 18:45:56  daniel
+ * Now use CPL for Error handling, Memory allocation, and File access
+ *
+ * Revision 1.7  1999/01/08 17:39:08  daniel
+ * Added E00ReadCallbackOpen()
+ *
+ * Revision 1.6  1998/11/13 16:34:08  daniel
+ * Fixed '\r' problem when reading E00 files from a PC under Unix
+ *
+ * Revision 1.5  1998/11/13 15:48:08  daniel
+ * Simplified the decoding of the compression codes for numbers
+ * (use a logical rule instead of going case by case)
+ *
+ * Revision 1.4  1998/11/02 18:34:29  daniel
+ * Added E00ErrorReset() calls.  Replace "EXP  1" by "EXP  0" on read.
+ *
+ * Revision 1.1  1998/10/29 13:26:00  daniel
+ * Initial revision
+ *
+ **********************************************************************
+ * Copyright (c) 1998-2005, Daniel Morissette
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "e00compr.h"
+
+static void _ReadNextSourceLine(E00ReadPtr psInfo);
+static const char *_UncompressNextLine(E00ReadPtr psInfo);
+
+/**********************************************************************
+ *                          _E00ReadTestOpen()
+ *
+ * Given a pre-initialized E00ReadPtr, this function will make sure
+ * that the file is really a E00 file, and also establish if it is
+ * compressed or not... setting the structure members by the same way.
+ *
+ * Returns NULL (and destroys the E00ReadPtr) if the file does not
+ * appear to be a valid E00 file.
+ **********************************************************************/
+static E00ReadPtr  _E00ReadTestOpen(E00ReadPtr psInfo)
+{
+
+    /* Check that the file is in E00 format.
+     */
+    _ReadNextSourceLine(psInfo);
+    if (!psInfo->bEOF && strncmp(psInfo->szInBuf, "EXP ", 4) == 0)
+    {
+        /* We should be in presence of a valid E00 file... 
+         * Is the file compressed or not?
+         *
+         * Note: we cannot really rely on the number that follows the EXP to
+         * establish if the file is compressed since we sometimes encounter
+         * uncompressed files that start with a "EXP 1" line!!!
+         *
+         * The best test is to read the first non-empty line: if the file is
+         * compressed, the first line of data should be 79 or 80 characters 
+         * long and contain several '~' characters.
+         */
+        do
+        {
+            _ReadNextSourceLine(psInfo);
+        }while(!psInfo->bEOF && 
+               (psInfo->szInBuf[0] == '\0' || isspace(psInfo->szInBuf[0])) );
+
+         if (!psInfo->bEOF && 
+             (strlen(psInfo->szInBuf)==79 || strlen(psInfo->szInBuf)==80) &&
+             strchr(psInfo->szInBuf, '~') != NULL )
+             psInfo->bIsCompressed = 1;
+
+         /* Move the Read ptr ready to read at the beginning of the file
+          */
+         E00ReadRewind(psInfo);
+    }
+    else
+    {
+        CPLFree(psInfo);
+        psInfo = NULL;
+    }
+
+    return psInfo;
+}
+
+/**********************************************************************
+ *                          E00ReadOpen()
+ *
+ * Try to open a E00 file given its filename and return a E00ReadPtr handle.
+ *
+ * Returns NULL if the file could not be opened or if it does not 
+ * appear to be a valid E00 file.
+ **********************************************************************/
+E00ReadPtr  E00ReadOpen(const char *pszFname)
+{
+    E00ReadPtr  psInfo = NULL;
+    FILE        *fp;
+
+    CPLErrorReset();
+
+    /* Open the file 
+     */
+    fp = VSIFOpen(pszFname, "rt");
+    if (fp == NULL)
+    {
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Failed to open %s: %s", pszFname, strerror(errno));
+        return NULL;
+    }
+
+    /* File was succesfully opened, allocate and initialize a 
+     * E00ReadPtr handle and check that the file is valid.
+     */
+    psInfo = (E00ReadPtr)CPLCalloc(1, sizeof(struct _E00ReadInfo));
+
+    psInfo->fp = fp;
+
+    psInfo = _E00ReadTestOpen(psInfo);
+
+    if (psInfo == NULL)
+    {
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "%s is not a valid E00 file.", pszFname);
+    }
+
+    return psInfo;
+}
+
+/**********************************************************************
+ *                          E00ReadCallbackOpen()
+ *
+ * This is an alternative to E00ReadOpen() for cases where you want to
+ * do all the file management yourself.  You open/close the file yourself
+ * and provide 2 callback functions: to read from the file and rewind the
+ * file pointer.  pRefData is your handle on the physical file and can
+ * be whatever you want... it is not used by the library, it will be
+ * passed directly to your 2 callback functions when they are called.
+ *
+ * The callback functions must have the following C prototype:
+ *
+ *   const char *myReadNextLine(void *pRefData);
+ *   void        myReadRewind(void *pRefData);
+ *
+ *   myReadNextLine() should return a reference to its own internal 
+ *   buffer, or NULL if an error happens or EOF is reached.
+ *
+ * E00ReadCallbackOpen() returns a E00ReadPtr handle or NULL if the file
+ * does not appear to be a valid E00 file.
+ **********************************************************************/
+E00ReadPtr  E00ReadCallbackOpen(void *pRefData,
+                                const char * (*pfnReadNextLine)(void *),
+                                void (*pfnReadRewind)(void *))
+{
+    E00ReadPtr  psInfo = NULL;
+
+    CPLErrorReset();
+
+    /* Make sure we received valid function pointers
+     */
+    if (pfnReadNextLine == NULL || pfnReadRewind == NULL)
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "Invalid function pointers!");
+        return NULL;
+    }
+
+    /* Allocate and initialize a 
+     * E00ReadPtr handle and check that the file is valid.
+     */
+    psInfo = (E00ReadPtr)CPLCalloc(1, sizeof(struct _E00ReadInfo));
+
+    psInfo->pRefData = pRefData;
+    psInfo->pfnReadNextLine = pfnReadNextLine;
+    psInfo->pfnReadRewind = pfnReadRewind;
+
+    psInfo = _E00ReadTestOpen(psInfo);
+
+    if (psInfo == NULL)
+    {
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "This is not a valid E00 file.");
+    }
+
+    return psInfo;
+}
+
+/**********************************************************************
+ *                          E00ReadClose()
+ *
+ * Close input file and release any memory used by the E00ReadPtr.
+ **********************************************************************/
+void    E00ReadClose(E00ReadPtr psInfo)
+{
+    CPLErrorReset();
+
+    if (psInfo)
+    {
+        if (psInfo->fp)
+            VSIFClose(psInfo->fp);
+        CPLFree(psInfo);
+    }
+}
+
+/**********************************************************************
+ *                          E00ReadRewind()
+ *
+ * Rewind the E00ReadPtr.  Allows to start another read pass on the 
+ * input file.
+ **********************************************************************/
+void    E00ReadRewind(E00ReadPtr psInfo)
+{
+    CPLErrorReset();
+
+    psInfo->szInBuf[0] = psInfo->szOutBuf[0] = '\0';
+    psInfo->iInBufPtr = 0;
+
+    psInfo->nInputLineNo = 0;
+
+    if (psInfo->pfnReadRewind == NULL)
+        VSIRewind(psInfo->fp);
+    else
+        psInfo->pfnReadRewind(psInfo->pRefData);
+
+    psInfo->bEOF = 0;
+}
+
+/**********************************************************************
+ *                          E00ReadNextLine()
+ *
+ * Return the next line of input from the E00 file or NULL if we reached EOF.
+ *
+ * Returns a reference to an internal buffer whose contents will be valid
+ * only until the next call to this function.
+ **********************************************************************/
+const char *E00ReadNextLine(E00ReadPtr psInfo)
+{
+    const char *pszLine = NULL;
+    char *pszPtr;
+
+    CPLErrorReset();
+
+    if (psInfo && !psInfo->bEOF)
+    {
+        if (!psInfo->bIsCompressed)
+        {
+            /* Uncompressed file... return line directly. 
+             */
+            _ReadNextSourceLine(psInfo);
+            pszLine = psInfo->szInBuf;
+        }
+        else if (psInfo->bIsCompressed && psInfo->nInputLineNo == 0)
+        {
+            /* Header line in a compressed file... return line 
+             * after replacing "EXP  1" with "EXP  0".  E00ReadOpen()
+             * has already verified that this line starts with "EXP "
+             */
+            _ReadNextSourceLine(psInfo);
+            if ( (pszPtr = strstr(psInfo->szInBuf, " 1")) != NULL)
+                pszPtr[1] = '0';
+            pszLine = psInfo->szInBuf;
+        }
+        else
+        {
+            if (psInfo->nInputLineNo == 1)
+            {
+                /* We just read the header line... reload the input buffer
+                 */
+                _ReadNextSourceLine(psInfo);
+            }
+
+            /* Uncompress the next line of input and return it 
+             */
+            pszLine = _UncompressNextLine(psInfo);
+        }
+
+        /* If we just reached EOF then make sure we don't add an extra
+         * empty line at the end of the uncompressed oputput.
+         */
+        if (psInfo->bEOF && strlen(pszLine) == 0)
+            pszLine = NULL;
+    }
+
+    return pszLine;
+}
+
+/**********************************************************************
+ *                          _ReadNextSourceLine()
+ *
+ * Loads the next line from the source file in psInfo.
+ *
+ * psInfo->bEOF should be checked after this call.
+ **********************************************************************/
+static void _ReadNextSourceLine(E00ReadPtr psInfo)
+{
+    if (!psInfo->bEOF)
+    {
+        psInfo->iInBufPtr = 0;
+        psInfo->szInBuf[0] = '\0';
+
+        /* Read either using fgets() or psInfo->pfnReadNextLine() 
+         * depending on the way the file was opened...
+         */
+        if (psInfo->pfnReadNextLine == NULL)
+        {
+            if (VSIFGets(psInfo->szInBuf,E00_READ_BUF_SIZE,psInfo->fp) == NULL)
+            {
+                /* We reached EOF
+                 */
+                psInfo->bEOF = 1;
+            }
+        }
+        else
+        {
+            const char *pszLine;
+            pszLine = psInfo->pfnReadNextLine(psInfo->pRefData);
+            if (pszLine)
+            {
+                strncpy(psInfo->szInBuf, pszLine, E00_READ_BUF_SIZE);
+            }
+            else
+            {
+                /* We reached EOF
+                 */
+                psInfo->bEOF = 1;
+            }
+        }
+
+        if (!psInfo->bEOF)
+        {
+            /* A new line was succesfully read.  Remove trailing '\n' if any.
+             * (Note: For Unix systems, we also have to check for '\r')
+             */
+            int nLen;
+            nLen = strlen(psInfo->szInBuf);
+            while(nLen > 0 && (psInfo->szInBuf[nLen-1] == '\n' ||
+                               psInfo->szInBuf[nLen-1] == '\r'   ) )
+            {
+                nLen--;
+                psInfo->szInBuf[nLen] = '\0';
+            }
+
+            psInfo->nInputLineNo++;
+        }
+    }
+}
+
+
+/**********************************************************************
+ *                          _GetNextSourceChar()
+ *
+ * Returns the next char from the source file input buffer... and 
+ * reload the input buffer when necessary... this function makes the
+ * whole input file appear as one huge null-terminated string with
+ * no line delimiters.
+ *
+ * Will return '\0' when EOF is reached.
+ **********************************************************************/
+static char _GetNextSourceChar(E00ReadPtr psInfo)
+{
+    char c = '\0';
+
+    if (!psInfo->bEOF)
+    {
+        if (psInfo->szInBuf[psInfo->iInBufPtr] == '\0')
+        {
+            _ReadNextSourceLine(psInfo);
+            c = _GetNextSourceChar(psInfo);
+        }
+        else
+        {
+            c = psInfo->szInBuf[psInfo->iInBufPtr++];
+        }
+    }
+
+    return c;
+}
+
+/**********************************************************************
+ *                          _UngetSourceChar()
+ *
+ * Reverse the effect of the previous call to _GetNextSourceChar() by
+ * moving the input buffer pointer back 1 character.
+ *
+ * This function can be called only once per call to _GetNextSourceChar()
+ * (i.e. you cannot unget more than one character) otherwise the pointer
+ * could move before the beginning of the input buffer.
+ **********************************************************************/
+static void _UngetSourceChar(E00ReadPtr psInfo)
+{
+    if (psInfo->iInBufPtr > 0)
+        psInfo->iInBufPtr--;
+    else
+    {
+        /* This error can happen only if _UngetSourceChar() is called
+         * twice in a row (which should never happen!).
+         */
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                 "UNEXPECTED INTERNAL ERROR: _UngetSourceChar() "
+                      "failed while reading line %d.", psInfo->nInputLineNo);
+    }
+}
+
+/**********************************************************************
+ *                          _UncompressNextLine()
+ *
+ * Uncompress one line of input and return a reference to an internal
+ * buffer containing the uncompressed output.
+ **********************************************************************/
+static const char *_UncompressNextLine(E00ReadPtr psInfo)
+{
+    char    c;
+    int     bEOL = 0;   /* Set to 1 when End of Line reached */
+    int     iOutBufPtr = 0, i, n;
+    int     iDecimalPoint, bOddNumDigits, iCurDigit;
+    char    *pszExp;
+    int     bPreviousCodeWasNumeric = 0;
+
+    while(!bEOL && (c=_GetNextSourceChar(psInfo)) != '\0')
+    {
+        if (c != '~')
+        {
+            /* Normal character... just copy it 
+             */
+            psInfo->szOutBuf[iOutBufPtr++] = c;
+            bPreviousCodeWasNumeric = 0;
+        }
+        else /* c == '~' */
+        {
+            /* ========================================================
+             * Found an encoded sequence.
+             * =======================================================*/
+            c = _GetNextSourceChar(psInfo);
+
+            /* --------------------------------------------------------
+             * Compression level 1: only spaces, '~' and '\n' are encoded
+             * -------------------------------------------------------*/
+            if (c == ' ')
+            {
+                /* "~ " followed by number of spaces
+                 */
+                c = _GetNextSourceChar(psInfo);
+                n = c - ' ';
+                for(i=0; i<n; i++)
+                    psInfo->szOutBuf[iOutBufPtr++] = ' ';
+                bPreviousCodeWasNumeric = 0;
+            }
+            else if (c == '}')
+            {
+                /* "~}" == '\n'
+                 */
+                bEOL = 1;
+                bPreviousCodeWasNumeric = 0;
+            }
+            else if (bPreviousCodeWasNumeric)
+            {
+                /* If the previous code was numeric, then the only valid code
+                 * sequences are the ones above: "~ " and "~}".  If we end up
+                 * here, it is because the number was followed by a '~' but
+                 * this '~' was not a code, it only marked the end of a 
+                 * number that was not followed by any space.
+                 *
+                 * We should simply ignore the '~' and return the character
+                 * that follows it directly.
+                 */
+                psInfo->szOutBuf[iOutBufPtr++] = c;
+                bPreviousCodeWasNumeric = 0;
+            }
+            else if (c == '~' || c == '-')
+            {
+                /* "~~" and "~-" are simple escape sequences for '~' and '-'
+                 */
+                psInfo->szOutBuf[iOutBufPtr++] = c;
+            }
+            /* --------------------------------------------------------
+             * Compression level 2: numeric values are encoded.
+             *
+             * All codes for this level are in the form "~ c0 c1 c2 ... cn"
+             * where:
+             *
+             *  ~             marks the beginning of a new code sequence
+             *
+             *  c0            is a single character code defining the format
+             *                of the number (decimal position, exponent, 
+             *                and even or odd number of digits)
+             *
+             *  c1 c2 ... cn  each of these characters represent a pair of 
+             *                digits of the encoded value with '!' == 00
+             *                values 92..99 are encoded on 2 chars that
+             *                must be added to each other 
+             *                (i.e. 92 == }!, 93 == }", ...)
+             *
+             *  The sequence ends with a ' ' or a '~' character
+             * -------------------------------------------------------*/
+            else if (c >= '!' && c <= 'z')
+            {
+                /* The format code defines 3 characteristics of the final number:
+                 * - Presence of a decimal point and its position
+                 * - Presence of an exponent, and its sign
+                 * - Odd or even number of digits
+                 */
+                n = c - '!';
+                iDecimalPoint = n % 15; /* 0 = no decimal point         */
+                bOddNumDigits = n / 45; /* 0 = even num.digits, 1 = odd */
+                n = n / 15;
+                if ( n % 3 == 1 )
+                    pszExp = "E+";
+                else if (n % 3 == 2 )
+                    pszExp = "E-";
+                else 
+                    pszExp = NULL;
+
+                /* Decode the c1 c2 ... cn value and apply the format.
+                 * Read characters until we encounter a ' ' or a '~'
+                 */
+                iCurDigit = 0;
+                while((c=_GetNextSourceChar(psInfo)) != '\0' && 
+                      c != ' ' && c != '~')
+                {
+                    n = c - '!';
+                    if (n == 92 && (c=_GetNextSourceChar(psInfo)) != '\0')
+                        n += c - '!';
+
+                    psInfo->szOutBuf[iOutBufPtr++] = '0' + n/10;
+
+                    if (++iCurDigit == iDecimalPoint)
+                        psInfo->szOutBuf[iOutBufPtr++] = '.';
+
+                    psInfo->szOutBuf[iOutBufPtr++] = '0' + n%10;
+
+                    if (++iCurDigit == iDecimalPoint)
+                        psInfo->szOutBuf[iOutBufPtr++] = '.';
+                }
+
+                if (c == '~' || c == ' ')
+                {
+                    bPreviousCodeWasNumeric = 1;
+                    _UngetSourceChar(psInfo);
+                }
+
+                /* If odd number of digits, then flush the last one
+                 */
+                if (bOddNumDigits)
+                    iOutBufPtr--;
+
+                /* Insert the exponent string before the 2 last digits
+                 * (we assume the exponent string is 2 chars. long)
+                 */
+                if (pszExp)
+                {
+                    for(i=0; i<2;i++)
+                    {
+                        psInfo->szOutBuf[iOutBufPtr] = 
+                                   psInfo->szOutBuf[iOutBufPtr-2];
+                        psInfo->szOutBuf[iOutBufPtr-2] = pszExp[i];
+                        iOutBufPtr++;
+                    }
+                }
+            }
+            else
+            {
+                /* Unsupported code sequence... this is a possibility
+                 * given the fact that this library was written by 
+                 * reverse-engineering the format!
+                 *
+                 * Send an error to the user and abort.
+                 *
+                 * If this error ever happens, and you are convinced that
+                 * the input file is not corrupted, then please report it to
+                 * me at dmorissette at mapgears.com, quoting the section of the input
+                 * file that produced it, and I'll do my best to add support
+                 * for this code sequence.
+                 */
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Unexpected code \"~%c\" encountered in line %d.",
+                          c, psInfo->nInputLineNo);
+    
+                /* Force the program to abort by simulating a EOF 
+                 */
+                psInfo->bEOF = 1;
+                bEOL = 1;
+            }
+
+        }/* if c == '~' */
+
+        /* E00 lines should NEVER be longer than 80 chars.  if we passed
+         * that limit, then the input file is likely corrupt.
+         */
+         if (iOutBufPtr > 80)
+         {
+            CPLError(CE_Failure, CPLE_FileIO,
+                      "Uncompressed line longer than 80 chars. "
+                      "Input file possibly corrupt around line %d.",
+                      psInfo->nInputLineNo);
+            /* Force the program to abort by simulating a EOF 
+             */
+            psInfo->bEOF = 1;
+            bEOL = 1;
+         }
+
+    }/* while !EOL */
+
+    psInfo->szOutBuf[iOutBufPtr++] = '\0';
+
+    return psInfo->szOutBuf;
+}
+
+
diff --git a/frmts/e00grid/makefile.vc b/frmts/e00grid/makefile.vc
new file mode 100644
index 0000000..a65cdc8
--- /dev/null
+++ b/frmts/e00grid/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ	=	e00griddataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/ecw/GNUmakefile b/frmts/ecw/GNUmakefile
index b46890c..fd1a79e 100644
--- a/frmts/ecw/GNUmakefile
+++ b/frmts/ecw/GNUmakefile
@@ -1,7 +1,7 @@
 
 include ../../GDALmake.opt
 
-OBJ	=	ecwdataset.o ecwcreatecopy.o jp2userbox.o
+OBJ	=	ecwdataset.o ecwcreatecopy.o jp2userbox.o ecwasyncreader.o
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) -DFRMT_ecw $(CPPFLAGS) $(EXTRA_CFLAGS)
 PLUGIN_SO =	gdal_ECW_JP2ECW.so
@@ -13,6 +13,8 @@ clean:
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 
+$(OBJ) $(O_OBJ):	gdal_ecw.h
+
 plugin: $(PLUGIN_SO)
 
 $(PLUGIN_SO):	$(OBJ)
diff --git a/frmts/ecw/ecwasyncreader.cpp b/frmts/ecw/ecwasyncreader.cpp
new file mode 100755
index 0000000..a8541ff
--- /dev/null
+++ b/frmts/ecw/ecwasyncreader.cpp
@@ -0,0 +1,383 @@
+/******************************************************************************
+ * $Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $
+ *
+ * Project:  GDAL 
+ * Purpose:  ECWAsyncReader implementation
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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 "gdal_ecw.h"
+
+CPL_CVSID("$Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $");
+
+#if defined(FRMT_ecw) && (ECWSDK_VERSION >= 40)
+
+/************************************************************************/
+/*                          BeginAsyncReader()                          */
+/************************************************************************/
+
+GDALAsyncReader* 
+ECWDataset::BeginAsyncReader( int nXOff, int nYOff, int nXSize, int nYSize, 
+                              void *pBuf, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              int nBandCount, int* panBandMap,
+                              int nPixelSpace, int nLineSpace, int nBandSpace,
+                              char **papszOptions)
+
+{
+/* -------------------------------------------------------------------- */
+/*      Provide default packing if needed.                              */
+/* -------------------------------------------------------------------- */
+    if( nPixelSpace == 0 )
+        nPixelSpace = GDALGetDataTypeSize(eBufType) / 8;
+    if( nLineSpace == 0 )
+        nLineSpace = nPixelSpace * nBufXSize;
+    if( nBandSpace == 0 )
+        nBandSpace = nLineSpace * nBufYSize;
+    
+/* -------------------------------------------------------------------- */
+/*      We should do a bit of validation first - perhaps add later.     */
+/* -------------------------------------------------------------------- */
+    
+/* -------------------------------------------------------------------- */
+/*      Create the corresponding async reader.                          */
+/* -------------------------------------------------------------------- */
+    ECWAsyncReader *poReader = new ECWAsyncReader();
+
+    poReader->poDS = this;
+
+    poReader->nXOff = nXOff;
+    poReader->nYOff = nYOff;
+    poReader->nXSize = nXSize;
+    poReader->nYSize = nYSize;
+
+    poReader->pBuf = pBuf;
+    poReader->nBufXSize = nBufXSize;
+    poReader->nBufYSize = nBufYSize;
+    poReader->eBufType = eBufType;
+    poReader->nBandCount = nBandCount;
+    poReader->panBandMap = (int *) CPLCalloc(sizeof(int),nBandCount);
+    memcpy( poReader->panBandMap, panBandMap, sizeof(int) * nBandCount );
+
+    poReader->nPixelSpace = nPixelSpace;
+    poReader->nLineSpace = nLineSpace;
+    poReader->nBandSpace = nBandSpace;
+
+/* -------------------------------------------------------------------- */
+/*      Create a new view for this request.                             */
+/* -------------------------------------------------------------------- */
+    poReader->poFileView = OpenFileView( GetDescription(), true, 
+                                         poReader->bUsingCustomStream );
+
+    if( poReader->poFileView == NULL )
+    {
+        delete poReader;
+        return NULL;
+    }
+
+    poReader->poFileView->SetClientData( poReader );
+    poReader->poFileView->SetRefreshCallback( ECWAsyncReader::RefreshCB );
+
+/* -------------------------------------------------------------------- */
+/*      Issue a corresponding SetView command.                          */
+/* -------------------------------------------------------------------- */
+    std::vector<UINT32> anBandIndices;
+    int   i;
+    NCSError     eNCSErr;
+    CNCSError    oErr;
+    
+    for( i = 0; i < nBandCount; i++ )
+        anBandIndices.push_back( panBandMap[i] - 1 );
+
+    oErr = poReader->poFileView->SetView( nBandCount, &(anBandIndices[0]),
+                                          nXOff, nYOff, 
+                                          nXOff + nXSize - 1, 
+                                          nYOff + nYSize - 1,
+                                          nBufXSize, nBufYSize );
+    eNCSErr = oErr.GetErrorNumber();
+    
+    if( eNCSErr != NCS_SUCCESS )
+    {
+        delete poReader;
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "%s", NCSGetErrorText(eNCSErr) );
+        
+        return NULL;
+    }
+
+    return poReader;
+}
+
+/************************************************************************/
+/*                           EndAsyncReader()                           */
+/************************************************************************/
+void ECWDataset::EndAsyncReader(GDALAsyncReader *poReader)
+
+{
+    delete poReader;
+}
+
+/************************************************************************/
+/*                           ECWAsyncReader()                           */
+/************************************************************************/
+
+ECWAsyncReader::ECWAsyncReader()
+
+{
+    hMutex = CPLCreateMutex();
+    CPLReleaseMutex( hMutex );
+
+    poFileView = NULL;
+    bUpdateReady = FALSE;
+    bComplete = FALSE;
+}
+
+/************************************************************************/
+/*                          ~ECWAsyncReader()                           */
+/************************************************************************/
+
+ECWAsyncReader::~ECWAsyncReader()
+
+{
+    {
+        CPLMutexHolderD( &hMutex );
+
+        // cancel? 
+
+        delete poFileView;
+        // we should also consider cleaning up the io stream if needed.
+    }
+
+    CPLDestroyMutex( hMutex );
+    hMutex = NULL;
+}
+
+/************************************************************************/
+/*                             RefreshCB()                              */
+/*                                                                      */
+/*      This static method is called by the ECW SDK to notify us        */
+/*      that there is new data ready to refresh from.  We just mark     */
+/*      the async reader as ready for an update.  We fetch the data     */
+/*      and push into into the buffer the application uses.  We lock    */
+/*      this async reader's mutex for this whole operation to avoid     */
+/*      a conflict with the main application.                           */
+/************************************************************************/
+
+NCSEcwReadStatus ECWAsyncReader::RefreshCB( NCSFileView *pFileView )
+
+{
+    NCSFileViewSetInfo *psVSI = NULL;
+
+    NCScbmGetViewInfo( pFileView, &psVSI );
+    if( psVSI != NULL )
+    {
+        CPLDebug( "ECW", "RefreshCB(): BlockCounts=%d/%d/%d/%d", 
+                  psVSI->nBlocksAvailableAtSetView,
+                  psVSI->nBlocksAvailable,
+                  psVSI->nMissedBlocksDuringRead,
+                  psVSI->nBlocksInView );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Identify the reader we are responding on behalf of.             */
+/* -------------------------------------------------------------------- */
+    CNCSJP2FileView *poFileView = (CNCSJP2FileView *) pFileView;
+    ECWAsyncReader *poReader = (ECWAsyncReader *)poFileView->GetClientData();
+    
+/* -------------------------------------------------------------------- */
+/*      Acquire the async reader mutex.  Currently we make no           */
+/*      arrangements for failure to acquire it.                         */
+/* -------------------------------------------------------------------- */
+    CPLMutexHolderD( &(poReader->hMutex) );
+
+/* -------------------------------------------------------------------- */
+/*      Mark the buffer as updated unless we are already complete.      */
+/*      It seems the Update callback keeps getting called even when     */
+/*      no new data has arrived after completion so we don't want to    */
+/*      trigger new work elsewhere in that case.                        */
+/*                                                                      */
+/*      Also record whether we are now complete.                        */
+/* -------------------------------------------------------------------- */
+    if( !poReader->bComplete )
+        poReader->bUpdateReady = TRUE;
+
+    if( psVSI->nBlocksAvailable == psVSI->nBlocksInView )
+        poReader->bComplete = TRUE;
+
+    return NCSECW_READ_OK;
+}
+
+/************************************************************************/
+/*                            ReadToBuffer()                            */
+/************************************************************************/
+NCSEcwReadStatus ECWAsyncReader::ReadToBuffer()
+{
+/* -------------------------------------------------------------------- */
+/*      Setup working scanline, and the pointers into it.               */
+/*                                                                      */
+/*      Should we try and optimize some cases that we could read        */
+/*      directly into the application buffer?  Perhaps in the           */
+/*      future.                                                         */
+/* -------------------------------------------------------------------- */
+    ECWDataset *poECWDS = (ECWDataset *) poDS;
+    int i;
+    int nDataTypeSize = (GDALGetDataTypeSize(poECWDS->eRasterDataType) / 8);
+    GByte *pabyBILScanline = (GByte *) 
+        CPLMalloc(nBufXSize * nDataTypeSize * nBandCount);
+    GByte **papabyBIL = (GByte**)CPLMalloc(nBandCount*sizeof(void*));
+
+    for( i = 0; i < nBandCount; i++ )
+        papabyBIL[i] = pabyBILScanline 
+            + i * nBufXSize * nDataTypeSize;
+
+/* -------------------------------------------------------------------- */
+/*      Read back the imagery into the buffer.                          */
+/* -------------------------------------------------------------------- */ 
+    for( int iScanline = 0; iScanline < nBufYSize; iScanline++ )
+    {
+        NCSEcwReadStatus  eRStatus;
+
+        eRStatus = 
+            poFileView->ReadLineBIL( poECWDS->eNCSRequestDataType, 
+                                               (UINT16) nBandCount,
+                                               (void **) papabyBIL );
+        if( eRStatus != NCSECW_READ_OK )
+        {
+            CPLFree( papabyBIL );
+            CPLFree( pabyBILScanline );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "NCScbmReadViewLineBIL failed." );
+            return eRStatus;
+        }
+
+        for( i = 0; i < nBandCount; i++ )
+        {
+            GDALCopyWords( 
+                pabyBILScanline + i * nDataTypeSize * nBufXSize,
+                poECWDS->eRasterDataType, nDataTypeSize, 
+                ((GByte *) pBuf) 
+                + nLineSpace * iScanline 
+                + nBandSpace * i, 
+                eBufType, 
+                nPixelSpace, 
+                nBufXSize );
+        }
+    }
+
+    CPLFree( pabyBILScanline );
+    CPLFree( papabyBIL );
+
+    return NCSECW_READ_OK;
+}
+
+/************************************************************************/
+/*                        GetNextUpdatedRegion()                        */
+/************************************************************************/
+
+GDALAsyncStatusType 
+ECWAsyncReader::GetNextUpdatedRegion( double dfTimeout,
+                                      int* pnXBufOff, int* pnYBufOff,
+                                      int* pnXBufSize, int* pnYBufSize )
+
+{
+    CPLDebug( "ECW", "GetNextUpdatedRegion()" );
+
+/* -------------------------------------------------------------------- */
+/*      We always mark the whole raster as updated since the ECW SDK    */
+/*      does not have a concept of partial update notifications.        */
+/* -------------------------------------------------------------------- */
+    *pnXBufOff = 0;
+    *pnYBufOff = 0;
+    *pnXBufSize = nBufXSize;
+    *pnYBufSize = nBufYSize;
+
+    if( bComplete && !bUpdateReady )
+    {
+        CPLDebug( "ECW", "return GARIO_COMPLETE" );
+        return GARIO_COMPLETE;
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      Wait till our timeout, or until we are notified there is        */
+/*      data ready.  We are trusting the CPLSleep() to be pretty        */
+/*      accurate instead of keeping track of time elapsed ourselves     */
+/*      - this is not necessarily a good approach.                      */
+/* -------------------------------------------------------------------- */
+    if( dfTimeout < 0.0 )
+        dfTimeout = 100000.0;
+    
+    while( !bUpdateReady && dfTimeout > 0.0 )
+    {
+        CPLSleep( MIN(0.1, dfTimeout) );
+        dfTimeout -= 0.1;
+        CPLDebug( "ECW", "wait..." );
+    }
+
+    if( !bUpdateReady )
+    {
+        CPLDebug( "ECW", "return GARIO_PENDING" );
+        return GARIO_PENDING;
+    }
+
+    bUpdateReady = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Acquire Mutex                                                   */
+/* -------------------------------------------------------------------- */
+    if( !CPLAcquireMutex( hMutex, dfTimeout ) )
+    {
+        CPLDebug( "ECW", "return GARIO_PENDING" );
+        return GARIO_PENDING;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Actually decode the imagery into our buffer.                    */
+/* -------------------------------------------------------------------- */
+    NCSEcwReadStatus  eRStatus = ReadToBuffer();
+
+    if( eRStatus != NCSECW_READ_OK )
+    {
+        CPLReleaseMutex( hMutex );
+        return GARIO_ERROR;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Return indication of complete or just buffer updateded.         */
+/* -------------------------------------------------------------------- */
+
+    if( bComplete && !bUpdateReady )
+    {
+        CPLReleaseMutex( hMutex );
+        CPLDebug( "ECW", "return GARIO_COMPLETE" );
+        return GARIO_COMPLETE;
+    }
+    else
+    {
+        CPLReleaseMutex( hMutex );
+        CPLDebug( "ECW", "return GARIO_UPDATE" );
+        return GARIO_UPDATE;
+    }
+}
+
+#endif /* def FRMT_ecw */
diff --git a/frmts/ecw/ecwcreatecopy.cpp b/frmts/ecw/ecwcreatecopy.cpp
index 924e7b1..2687f1d 100644
--- a/frmts/ecw/ecwcreatecopy.cpp
+++ b/frmts/ecw/ecwcreatecopy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ecwcreatecopy.cpp 21492 2011-01-14 04:54:09Z warmerdam $
+ * $Id: ecwcreatecopy.cpp 23601 2011-12-19 20:04:51Z rouault $
  *
  * Project:  GDAL ECW Driver
  * Purpose:  ECW CreateCopy method implementation.
@@ -27,19 +27,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+#include "gdal_ecw.h"
 #include "ogr_spatialref.h"
-#include "cpl_string.h"
-#include "cpl_conv.h"
-#include "vsiiostream.h"
-#include "jp2userbox.h"
-#include "gdaljp2metadata.h"
 
-CPL_CVSID("$Id: ecwcreatecopy.cpp 21492 2011-01-14 04:54:09Z warmerdam $");
-
-void ECWInitialize( void );
-
-GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo);
+CPL_CVSID("$Id: ecwcreatecopy.cpp 23601 2011-12-19 20:04:51Z rouault $");
 
 #if defined(FRMT_ecw) && defined(HAVE_COMPRESS)
 
@@ -130,6 +121,7 @@ CPLErr GDALECWCompressor::CloseDown()
     CPLFree( sFileInfo.pBands );
 
     Close( true );
+    m_OStream.Close();
 
     return CE_None;
 }
@@ -356,7 +348,7 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox( const char *pszWKT,
     poAssoc->m_OwnedBoxes.push_back( poLabel );
 
     poGMLData = new JP2UserBox();
-    poGMLData->m_nTBox = 'xml ';
+    poGMLData->m_nTBox = 'xml '; /* Is it correct on a big-endian host ? Does ECW work on big-endian hosts ;-) */
     poGMLData->SetData( strlen( szDoc ), (unsigned char *) szDoc );
     poAssoc->m_OtherBoxes.push_back( poGMLData );
     poAssoc->m_OwnedBoxes.push_back( poGMLData );
@@ -375,7 +367,7 @@ CPLErr  GDALECWCompressor::PrepareCoverageBox( const char *pszWKT,
         poAssoc->m_OwnedBoxes.push_back( poLabel );
 
         poGMLData = new JP2UserBox();
-        poGMLData->m_nTBox = 'xml ';
+        poGMLData->m_nTBox = 'xml '; /* Is it correct on a big-endian host ? Does ECW work on big-endian hosts ;-) */
         poGMLData->SetData( strlen(pszDictBox), 
                             (unsigned char *) pszDictBox );
         poAssoc->m_OtherBoxes.push_back( poGMLData );
@@ -405,6 +397,7 @@ CPLErr GDALECWCompressor::WriteJP2Box( GDALJP2Box * poBox )
 
     poECWBox = new JP2UserBox();
     memcpy( &(poECWBox->m_nTBox), poBox->GetType(), 4 );
+    CPL_MSBPTR32( &(poECWBox->m_nTBox) );
 
     poECWBox->SetData( (int) poBox->GetDataLength(), 
                        poBox->GetWritableData() );
@@ -421,90 +414,6 @@ CPLErr GDALECWCompressor::WriteJP2Box( GDALJP2Box * poBox )
     return CE_None;
 }
 
-/************************************************************************/
-/*                        ECWTranslateFromWKT()                         */
-/************************************************************************/
-
-static int ECWTranslateFromWKT( const char *pszWKT, 
-                                char *pszProjection,
-                                int nProjectionLen,
-                                char *pszDatum,
-                                int nDatumLen)
-
-{
-    OGRSpatialReference oSRS;
-    char *pszWKTIn = (char *) pszWKT;
-
-    strcpy( pszProjection, "RAW" );
-    strcpy( pszDatum, "RAW" );
-
-    if( pszWKT == NULL || strlen(pszWKT) == 0 )
-        return FALSE;
-    
-    oSRS.importFromWkt( &pszWKTIn );
-    
-    if( oSRS.IsLocal() )
-        return TRUE;
-
-/* -------------------------------------------------------------------- */
-/*      Do we have an overall EPSG number for this coordinate system?   */
-/* -------------------------------------------------------------------- */
-    const char *pszAuthorityCode = NULL;
-    const char *pszAuthorityName = NULL;
-    UINT32 nEPSGCode = 0;
-
-    if( oSRS.IsProjected() )
-    {
-        pszAuthorityCode =  oSRS.GetAuthorityCode( "PROJCS" );
-        pszAuthorityName =  oSRS.GetAuthorityName( "PROJCS" );
-    }
-    else if( oSRS.IsGeographic() )
-    {
-        pszAuthorityCode =  oSRS.GetAuthorityCode( "GEOGCS" );
-        pszAuthorityName =  oSRS.GetAuthorityName( "GEOGCS" );
-    }
-
-    if( pszAuthorityName != NULL && EQUAL(pszAuthorityName,"EPSG") 
-        && pszAuthorityCode != NULL && atoi(pszAuthorityCode) > 0 )
-        nEPSGCode = (UINT32) atoi(pszAuthorityCode);
-
-    if( nEPSGCode != 0 )
-    {
-        char *pszEPSGProj = NULL, *pszEPSGDatum = NULL;
-        CNCSError oErr;
-
-        oErr = 
-            CNCSJP2FileView::GetProjectionAndDatum( atoi(pszAuthorityCode), 
-                                                 &pszEPSGProj, &pszEPSGDatum );
-
-        CPLDebug( "ECW", "GetGDTProjDat(%d) = %s/%s", 
-                  atoi(pszAuthorityCode), pszEPSGProj, pszEPSGDatum );
-
-        if( oErr.GetErrorNumber() == NCS_SUCCESS
-            && pszEPSGProj != NULL && pszEPSGDatum != NULL )
-        {
-            strncpy( pszProjection, pszEPSGProj, nProjectionLen );
-            strncpy( pszDatum, pszEPSGDatum, nDatumLen );
-            pszProjection[nProjectionLen - 1] = 0;
-            pszDatum[nDatumLen - 1] = 0;
-            NCSFree( pszEPSGProj );
-            NCSFree( pszEPSGDatum );
-            return TRUE;
-        }
-
-        NCSFree( pszEPSGProj );
-        NCSFree( pszEPSGDatum );
-
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Fallback to translating based on the ecw_cs.wkt file, and       */
-/*      various jiffy rules.                                            */
-/* -------------------------------------------------------------------- */
-    char szUnits[32];
-
-    return oSRS.exportToERM( pszProjection, pszDatum, szUnits ) == OGRERR_NONE;
-}
 
 /************************************************************************/
 /*                             Initialize()                             */
@@ -522,6 +431,34 @@ CPLErr GDALECWCompressor::Initialize(
 
 {
 /* -------------------------------------------------------------------- */
+/*      For 4.x and beyond you need a license key to compress data.     */
+/*      Check for it as a configuration option or a creation option.    */
+/* -------------------------------------------------------------------- */
+#if ECWSDK_VERSION >= 40 
+    const char* pszECWKey = CSLFetchNameValue( papszOptions, "ECW_ENCODE_KEY");
+    if( pszECWKey == NULL )
+        pszECWKey = CPLGetConfigOption( "ECW_ENCODE_KEY", NULL );
+    
+    const char* pszECWCompany = 
+        CSLFetchNameValue( papszOptions, "ECW_ENCODE_COMPANY");
+    if( pszECWCompany == NULL )
+        pszECWCompany = CPLGetConfigOption( "ECW_ENCODE_COMPANY", NULL );
+    
+    if( pszECWKey && pszECWCompany)
+    {
+        CPLDebug( "ECW", "SetOEMKey(%s,%s)", pszECWCompany, pszECWKey );
+        CNCSFile::SetOEMKey( (char *) pszECWCompany, (char *)pszECWKey );
+    }
+    else if( pszECWKey || pszECWCompany )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Only one of ECW_ENCODE_KEY and ECW_ENCODE_COMPANY were provided.\nBoth are required." );
+        return CE_Failure;
+    }
+
+#endif /* ECWSDK_VERSION >= 40 */
+
+/* -------------------------------------------------------------------- */
 /*      Do some rudimentary checking in input.                          */
 /* -------------------------------------------------------------------- */
     if( nBands == 0 )
@@ -546,12 +483,16 @@ CPLErr GDALECWCompressor::Initialize(
     {
         fTargetCompression = (float) 
             atof(CSLFetchNameValue(papszOptions, "TARGET"));
-        
-        if( fTargetCompression < 0.0 || fTargetCompression > 99.0 )
+
+        /* The max allowed value should be 100 - 100 / 65535 = 99.9984740978 */
+        /* so that nCompressionRate fits on a uint16 (see below) */
+        /* No need to be so pedantic, so we will limit to 99.99 % */
+        /* (compression rate = 10 000) */
+        if( fTargetCompression < 0.0 || fTargetCompression > 99.99 )
         {
             CPLError( CE_Failure, CPLE_NotSupported, 
                       "TARGET compression of %.3f invalid, should be a\n"
-                      "value between 0 and 99 percent.\n", 
+                      "value between 0 and 99.99 percent.\n",
                       (double) fTargetCompression );
             return CE_Failure;
         }
@@ -795,6 +736,7 @@ CPLErr GDALECWCompressor::Initialize(
 /* -------------------------------------------------------------------- */
     char szProjection[128];
     char szDatum[128];
+    char szUnits[128];
 
     strcpy( szProjection, "RAW" );
     strcpy( szDatum, "RAW" );
@@ -814,16 +756,23 @@ CPLErr GDALECWCompressor::Initialize(
             strcpy( szProjection, "GEODETIC" );
     }
 
+    const char* pszUnits = CSLFetchNameValue(papszOptions, "UNITS");
+    if( pszUnits != NULL )
+    {
+        psClient->eCellSizeUnits = ECWTranslateToCellSizeUnits(pszUnits);
+    }
+
     if( EQUAL(szProjection,"RAW") && pszWKT != NULL )
     {
-        ECWTranslateFromWKT( pszWKT, szProjection, sizeof(szProjection), szDatum, sizeof(szDatum) );
+        ECWTranslateFromWKT( pszWKT, szProjection, sizeof(szProjection), szDatum, sizeof(szDatum), szUnits );
+        psClient->eCellSizeUnits = ECWTranslateToCellSizeUnits(szUnits);
     }
 
     psClient->szDatum = szDatum;
     psClient->szProjection = szProjection;
 
-    CPLDebug( "ECW", "Writing with PROJ=%s, DATUM=%s", 
-              szProjection, szDatum );
+    CPLDebug( "ECW", "Writing with PROJ=%s, DATUM=%s, UNITS=%s", 
+              szProjection, szDatum, ECWTranslateFromCellSizeUnits(psClient->eCellSizeUnits) );
 
 /* -------------------------------------------------------------------- */
 /*      Setup GML and GeoTIFF information.                              */
@@ -840,46 +789,23 @@ CPLErr GDALECWCompressor::Initialize(
         WriteJP2Box( oJP2MD.CreateJP2GeoTIFF() );
 
 /* -------------------------------------------------------------------- */
-/*      Handle special case of a JPEG2000 data stream in another file.  */
+/*      We handle all jpeg2000 files via the VSIIOStream, but ECW       */
+/*      files cannot be done this way for some reason.                  */
 /* -------------------------------------------------------------------- */
     VSILFILE *fpVSIL = NULL;
 
-    if( EQUALN(pszFilename,"J2K_SUBFILE:",12) )
+    if( bIsJPEG2000 )
     {
-        int  subfile_offset=-1, subfile_size=-1;
-        const char *real_filename = NULL;
-
-        if( sscanf( pszFilename, "J2K_SUBFILE:%d,%d", 
-                    &subfile_offset, &subfile_size ) != 2 )
-        {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to parse J2K_SUBFILE specification." );
-            return CE_Failure;
-        }
-
-        real_filename = strstr(pszFilename,",");
-        if( real_filename != NULL )
-            real_filename = strstr(real_filename+1,",");
-        if( real_filename != NULL )
-            real_filename++;
-        else
-        {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to parse J2K_SUBFILE specification." );
-            return CE_Failure;
-        }
-
-        fpVSIL = VSIFOpenL( real_filename, "rb+" );
+        fpVSIL = VSIFOpenL( pszFilename, "wb+" );
         if( fpVSIL == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed, 
-                      "Failed to open %s.",  real_filename );
+                      "Failed to open %s.", pszFilename );
             return CE_Failure;
         }
 
-        m_OStream.Access( fpVSIL, TRUE, real_filename,
-                          subfile_offset, subfile_size );
-    }
+        m_OStream.Access( fpVSIL, TRUE, pszFilename, 0, -1 );
+    }    
 
 /* -------------------------------------------------------------------- */
 /*      Check if we can enable large files.  This option should only    */
@@ -950,34 +876,6 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     ECWInitialize();
 
 /* -------------------------------------------------------------------- */
-/*      For 4.x and beyond you need a license key to compress data.     */
-/*      Check for it as a configuration option or a creation option.    */
-/* -------------------------------------------------------------------- */
-#if ECWSDK_VERSION >= 40 
-    const char* pszECWKey = CSLFetchNameValue( papszOptions, "ECW_ENCODE_KEY");
-    if( pszECWKey == NULL )
-        pszECWKey = CPLGetConfigOption( "ECW_ENCODE_KEY", NULL );
-    
-    const char* pszECWCompany = 
-        CSLFetchNameValue( papszOptions, "ECW_ENCODE_COMPANY");
-    if( pszECWCompany == NULL )
-        pszECWCompany = CPLGetConfigOption( "ECW_ENCODE_COMPANY", NULL );
-    
-    if( pszECWKey && pszECWCompany)
-    {
-        CPLDebug( "ECW", "SetOEMKey(%s,%s)", pszECWCompany, pszECWKey );
-        CNCSFile::SetOEMKey( (char *) pszECWCompany, (char *)pszECWKey );
-    }
-    else if( pszECWKey || pszECWCompany )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Only one of ECW_ENCODE_KEY and ECW_ENCODE_COMPANY were provided.\nBoth are required." );
-        return NULL;
-    }
-
-#endif /* ECWSDK_VERSION >= 40
-
-/* -------------------------------------------------------------------- */
 /*      Get various values from the source dataset.                     */
 /* -------------------------------------------------------------------- */
     int  nBands = poSrcDS->GetRasterCount();
@@ -1038,6 +936,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Setup the compressor.                                           */
 /* -------------------------------------------------------------------- */
     GDALECWCompressor         oCompressor;
+    CNCSError oErr;
 
     oCompressor.pfnProgress = pfnProgress;
     oCompressor.pProgressData = pProgressData;
@@ -1058,7 +957,17 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Start the compression.                                          */
 /* -------------------------------------------------------------------- */
-    oCompressor.Write();
+    oErr = oCompressor.Write();
+
+    if( oErr.GetErrorNumber() != NCS_SUCCESS )
+    {
+        char* pszErrorMessage = oErr.GetErrorMessage();
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "%s", pszErrorMessage );
+        NCSFree(pszErrorMessage);
+        
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup, and return read-only handle.                           */
@@ -1310,6 +1219,8 @@ ECWWriteDataset::ECWWriteDataset( const char *pszFilename,
     pabyBILBuffer = NULL;
     nLoadedLine = -1;
 
+    eAccess = GA_Update;
+
     this->bIsJPEG2000 = bIsJPEG2000;
     this->eDataType = eType;
     this->papszOptions = CSLDuplicate( papszOptions );
diff --git a/frmts/ecw/ecwdataset.cpp b/frmts/ecw/ecwdataset.cpp
index 8a635b4..1e620d1 100644
--- a/frmts/ecw/ecwdataset.cpp
+++ b/frmts/ecw/ecwdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ecwdataset.cpp 22589 2011-06-25 21:02:42Z rouault $
+ * $Id: ecwdataset.cpp 23321 2011-11-05 13:20:20Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  ECW (ERDAS Wavelet Compression Format) Driver
@@ -27,18 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "gdaljp2metadata.h"
-#include "ogr_spatialref.h"
-#include "cpl_string.h"
-#include "cpl_conv.h"
-#include "vsiiostream.h"
-#include "cpl_multiproc.h"
+#include "gdal_ecw.h"
 #include "cpl_minixml.h"
+#include "ogr_spatialref.h"
 #include "ogr_api.h"
 #include "ogr_geometry.h"
 
-CPL_CVSID("$Id: ecwdataset.cpp 22589 2011-06-25 21:02:42Z rouault $");
+CPL_CVSID("$Id: ecwdataset.cpp 23321 2011-11-05 13:20:20Z rouault $");
 
 #undef NOISY_DEBUG
 
@@ -56,122 +51,6 @@ void ECWInitialize( void );
 GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo);
 
 /************************************************************************/
-/* ==================================================================== */
-/*				ECWDataset				*/
-/* ==================================================================== */
-/************************************************************************/
-
-class ECWRasterBand;
-
-class CPL_DLL ECWDataset : public GDALPamDataset
-{
-    friend class ECWRasterBand;
-
-    CNCSJP2FileView *poFileView;
-    NCSFileViewFileInfoEx *psFileInfo;
-
-    GDALDataType eRasterDataType;
-    NCSEcwCellType eNCSRequestDataType;
-
-    int         bUsingCustomStream;
-
-    // Current view window. 
-    int         bWinActive;
-    int         nWinXOff, nWinYOff, nWinXSize, nWinYSize;
-    int         nWinBufXSize, nWinBufYSize;
-    int         nWinBandCount;
-    int         *panWinBandList;
-    int         nWinBufLoaded;
-    void        **papCurLineBuf;
-
-    int         bGeoTransformValid;
-    double      adfGeoTransform[6];
-    char        *pszProjection;
-    int         nGCPCount;
-    GDAL_GCP    *pasGCPList;
-
-    char        **papszGMLMetadata;
-
-    void        ECW2WKTProjection();
-
-    void        CleanupWindow();
-    int         TryWinRasterIO( GDALRWFlag, int, int, int, int,
-                                GByte *, int, int, GDALDataType,
-                                int, int *, int, int, int );
-    CPLErr      LoadNextLine();
-
-  public:
-		ECWDataset(int bIsJPEG2000);
-		~ECWDataset();
-                
-    static GDALDataset *Open( GDALOpenInfo *, int bIsJPEG2000 );
-    static int          IdentifyJPEG2000( GDALOpenInfo * poOpenInfo );
-    static GDALDataset *OpenJPEG2000( GDALOpenInfo * );
-    static int          IdentifyECW( GDALOpenInfo * poOpenInfo );
-    static GDALDataset *OpenECW( GDALOpenInfo * );
-
-    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                              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      **GetMetadata( const char * pszDomain = "" );
-
-    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
-                               GDALDataType eDT, 
-                               int nBandCount, int *panBandList,
-                               char **papszOptions );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            ECWRasterBand                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class ECWRasterBand : public GDALPamRasterBand
-{
-    friend class ECWDataset;
-    
-    // NOTE: poDS may be altered for NITF/JPEG2000 files!
-    ECWDataset     *poGDS;
-
-    GDALColorInterp         eBandInterp;
-
-    int                          iOverview; // -1 for base. 
-
-    std::vector<ECWRasterBand*>  apoOverviews;
-
-    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                              void *, int, int, GDALDataType,
-                              int, int );
-
-  public:
-
-                   ECWRasterBand( ECWDataset *, int, int = -1 );
-                   ~ECWRasterBand();
-
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual int    HasArbitraryOverviews() { return apoOverviews.size() == 0; }
-    virtual int    GetOverviewCount() { return apoOverviews.size(); }
-    virtual GDALRasterBand *GetOverview(int);
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-
-    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
-                               GDALDataType eDT, char **papszOptions );
-};
-
-/************************************************************************/
 /*                           ECWRasterBand()                            */
 /************************************************************************/
 
@@ -255,6 +134,11 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDS, int nBand, int iOverview )
             apoOverviews.push_back( new ECWRasterBand( poDS, nBand, i ) );
         }
     }
+
+    if( (poDS->psFileInfo->pBands[nBand-1].nBits % 8) != 0 )
+        SetMetadataItem("NBITS",
+                        CPLString().Printf("%d",poDS->psFileInfo->pBands[nBand-1].nBits),
+                        "IMAGE_STRUCTURE" );
 }
 
 /************************************************************************/
@@ -578,6 +462,7 @@ CPLErr ECWRasterBand::IReadBlock( int, int nBlockYOff, void * pImage )
 ECWDataset::ECWDataset(int bIsJPEG2000)
 
 {
+    this->bIsJPEG2000 = bIsJPEG2000;
     bUsingCustomStream = FALSE;
     pszProjection = NULL;
     poFileView = NULL;
@@ -595,6 +480,13 @@ ECWDataset::ECWDataset(int bIsJPEG2000)
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+
+    bHdrDirty = FALSE;
+    bGeoTransformChanged = FALSE;
+    bProjectionChanged = FALSE;
+    bProjCodeChanged = FALSE;
+    bDatumCodeChanged = FALSE;
+    bUnitsCodeChanged = FALSE;
     
     poDriver = (GDALDriver*) GDALGetDriverByName( bIsJPEG2000 ? "JP2ECW" : "ECW" );
 }
@@ -608,14 +500,6 @@ ECWDataset::~ECWDataset()
 {
     FlushCache();
     CleanupWindow();
-    CPLFree( pszProjection );
-    CSLDestroy( papszGMLMetadata );
-
-    if( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Release / dereference iostream.                                 */
@@ -642,6 +526,235 @@ ECWDataset::~ECWDataset()
                 delete poUnderlyingIOStream;
         }
     }
+
+    /* WriteHeader() must be called after closing the file handle to work */
+    /* on Windows */
+    if( bHdrDirty )
+        WriteHeader();
+
+    CPLFree( pszProjection );
+    CSLDestroy( papszGMLMetadata );
+
+    if( nGCPCount > 0 )
+    {
+        GDALDeinitGCPs( nGCPCount, pasGCPList );
+        CPLFree( pasGCPList );
+    }
+}
+
+/************************************************************************/
+/*                             AdviseRead()                             */
+/************************************************************************/
+
+CPLErr ECWDataset::SetGeoTransform( double * padfGeoTransform )
+{
+    if ( bIsJPEG2000 || eAccess == GA_ReadOnly )
+        return GDALPamDataset::SetGeoTransform(padfGeoTransform);
+
+    if ( !bGeoTransformValid ||
+        adfGeoTransform[0] != padfGeoTransform[0] ||
+        adfGeoTransform[1] != padfGeoTransform[1] ||
+        adfGeoTransform[2] != padfGeoTransform[2] ||
+        adfGeoTransform[3] != padfGeoTransform[3] ||
+        adfGeoTransform[4] != padfGeoTransform[4] ||
+        adfGeoTransform[5] != padfGeoTransform[5] )
+    {
+        memcpy(adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
+        bGeoTransformValid = TRUE;
+        bHdrDirty = TRUE;
+        bGeoTransformChanged = TRUE;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            SetProjection()                           */
+/************************************************************************/
+
+CPLErr ECWDataset::SetProjection( const char* pszProjectionIn )
+{
+    if ( bIsJPEG2000 || eAccess == GA_ReadOnly )
+        return GDALPamDataset::SetProjection(pszProjectionIn);
+
+    if ( !( (pszProjection == NULL && pszProjectionIn == NULL) ||
+            (pszProjection != NULL && pszProjectionIn != NULL &&
+             strcmp(pszProjection, pszProjectionIn) == 0) ) )
+    {
+        CPLFree(pszProjection);
+        pszProjection = pszProjectionIn ? CPLStrdup(pszProjectionIn) : NULL;
+        bHdrDirty = TRUE;
+        bProjectionChanged = TRUE;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            SetMetadataItem()                         */
+/************************************************************************/
+
+CPLErr ECWDataset::SetMetadataItem( const char * pszName,
+                                    const char * pszValue,
+                                    const char * pszDomain )
+{
+    if ( !bIsJPEG2000 && eAccess == GA_Update &&
+         (pszDomain == NULL || EQUAL(pszDomain, "") ||
+          (pszDomain != NULL && EQUAL(pszDomain, "ECW"))) &&
+         pszName != NULL &&
+         (strcmp(pszName, "PROJ") == 0 || strcmp( pszName, "DATUM") == 0 ||
+          strcmp( pszName, "UNITS") == 0 ) )
+    {
+        CPLString osNewVal = pszValue ? pszValue : "";
+        if (osNewVal.size() > 31)
+            osNewVal.resize(31);
+        if (strcmp(pszName, "PROJ") == 0)
+        {
+            bProjCodeChanged = (osNewVal != m_osProjCode);
+            m_osProjCode = osNewVal;
+            bHdrDirty |= bProjCodeChanged;
+        }
+        else if (strcmp( pszName, "DATUM") == 0)
+        {
+            bDatumCodeChanged |= (osNewVal != m_osDatumCode);
+            m_osDatumCode = osNewVal;
+            bHdrDirty |= bDatumCodeChanged;
+        }
+        else 
+        {
+            bUnitsCodeChanged |= (osNewVal != m_osUnitsCode);
+            m_osUnitsCode = osNewVal;
+            bHdrDirty |= bUnitsCodeChanged;
+        }
+        return CE_None;
+    }
+    else
+        return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
+}
+
+/************************************************************************/
+/*                              SetMetadata()                           */
+/************************************************************************/
+
+CPLErr ECWDataset::SetMetadata( char ** papszMetadata,
+                                const char * pszDomain )
+{
+    if ( (pszDomain == NULL || EQUAL(pszDomain, "") || EQUAL(pszDomain, "ECW")) &&
+          (CSLFetchNameValue(papszMetadata, "PROJ") != NULL ||
+           CSLFetchNameValue(papszMetadata, "DATUM") != NULL ||
+           CSLFetchNameValue(papszMetadata, "UNITS") != NULL) )
+    {
+        CPLStringList osNewMetadata;
+        char** papszIter = papszMetadata;
+        while(*papszIter)
+        {
+            if (strncmp(*papszIter, "PROJ=", 5) == 0 ||
+                strncmp(*papszIter, "DATUM=", 6) == 0 ||
+                strncmp(*papszIter, "UNITS=", 6) == 0)
+            {
+                char* pszKey = NULL;
+                const char* pszValue = CPLParseNameValue(*papszIter, &pszKey );
+                SetMetadataItem(pszKey, pszValue, pszDomain);
+                CPLFree(pszKey);
+            }
+            else
+                osNewMetadata.AddString(*papszIter);
+            papszIter ++;
+        }
+        if (osNewMetadata.size() != 0)
+            return GDALPamDataset::SetMetadata(osNewMetadata.List(), pszDomain);
+        else
+            return CE_None;
+    }
+    else
+        return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
+}
+
+/************************************************************************/
+/*                             WriteHeader()                            */
+/************************************************************************/
+
+void ECWDataset::WriteHeader()
+{
+    if (!bHdrDirty)
+        return;
+
+    CPLAssert(eAccess == GA_Update);
+    CPLAssert(!bIsJPEG2000);
+
+    bHdrDirty = FALSE;
+
+    NCSEcwEditInfo *psEditInfo = NULL;
+    NCSError eErr;
+
+    /* Load original header info */
+    eErr = NCSEcwEditReadInfo((char*) GetDescription(), &psEditInfo);
+    if (eErr != NCS_SUCCESS)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "NCSEcwEditReadInfo() failed");
+        return;
+    }
+
+    /* To avoid potential cross-heap issues, we keep the original */
+    /* strings, and restore them before freeing the structure */
+    char* pszOriginalCode = psEditInfo->szDatum;
+    char* pszOriginalProj = psEditInfo->szProjection;
+
+    /* Alter the structure with user modified information */
+    char szProjCode[32], szDatumCode[32], szUnits[32];
+    if (bProjectionChanged)
+    {
+        if (ECWTranslateFromWKT( pszProjection, szProjCode, sizeof(szProjCode),
+                                 szDatumCode, sizeof(szDatumCode), szUnits ) )
+        {
+            psEditInfo->szDatum = szDatumCode;
+            psEditInfo->szProjection = szProjCode;
+            psEditInfo->eCellSizeUnits = ECWTranslateToCellSizeUnits(szUnits);
+            CPLDebug("ECW", "Rewrite DATUM : %s", psEditInfo->szDatum);
+            CPLDebug("ECW", "Rewrite PROJ : %s", psEditInfo->szProjection);
+            CPLDebug("ECW", "Rewrite UNITS : %s",
+                     ECWTranslateFromCellSizeUnits(psEditInfo->eCellSizeUnits));
+        }
+    }
+
+    if (bDatumCodeChanged)
+    {
+        psEditInfo->szDatum = (char*) ((m_osDatumCode.size()) ? m_osDatumCode.c_str() : "RAW");
+        CPLDebug("ECW", "Rewrite DATUM : %s", psEditInfo->szDatum);
+    }
+    if (bProjCodeChanged)
+    {
+        psEditInfo->szProjection = (char*) ((m_osProjCode.size()) ? m_osProjCode.c_str() : "RAW");
+        CPLDebug("ECW", "Rewrite PROJ : %s", psEditInfo->szProjection);
+    }
+    if (bUnitsCodeChanged)
+    {
+        psEditInfo->eCellSizeUnits = ECWTranslateToCellSizeUnits(m_osUnitsCode.c_str());
+        CPLDebug("ECW", "Rewrite UNITS : %s",
+                 ECWTranslateFromCellSizeUnits(psEditInfo->eCellSizeUnits));
+    }
+
+    if (bGeoTransformChanged)
+    {
+        psEditInfo->fOriginX = adfGeoTransform[0];
+        psEditInfo->fCellIncrementX = adfGeoTransform[1];
+        psEditInfo->fOriginY = adfGeoTransform[3];
+        psEditInfo->fCellIncrementY = adfGeoTransform[5];
+        CPLDebug("ECW", "Rewrite Geotransform");
+    }
+
+    /* Write modified header info */
+    eErr = NCSEcwEditWriteInfo((char*) GetDescription(), psEditInfo, NULL, NULL, NULL);
+    if (eErr != NCS_SUCCESS)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "NCSEcwEditWriteInfo() failed");
+    }
+
+    /* Restore original pointers before free'ing */
+    psEditInfo->szDatum = pszOriginalCode;
+    psEditInfo->szProjection = pszOriginalProj;
+
+    NCSEcwEditFreeInfo(psEditInfo);
 }
 
 /************************************************************************/
@@ -1095,7 +1208,8 @@ int ECWDataset::IdentifyECW( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"ecw")
          || poOpenInfo->nHeaderBytes == 0)
-        && !EQUALN(poOpenInfo->pszFilename,"ecwp:",5) )
+        && !EQUALN(poOpenInfo->pszFilename,"ecwp:",5)
+        && !EQUALN(poOpenInfo->pszFilename,"ecwps:",5) )
         return FALSE;
 
     return TRUE;
@@ -1115,218 +1229,174 @@ GDALDataset *ECWDataset::OpenECW( GDALOpenInfo * poOpenInfo )
 
     return Open( poOpenInfo, FALSE );
 }
-    
+
 /************************************************************************/
-/*                                Open()                                */
+/*                            OpenFileView()                            */
 /************************************************************************/
 
-GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
+CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
+                                           bool bProgressive,
+                                           int &bUsingCustomStream )
 
 {
+/* -------------------------------------------------------------------- */
+/*      First we try to open it as a normal CNCSFile, letting the       */
+/*      ECW SDK manage the IO itself.   This will only work for real    */
+/*      files, and ecwp: or ecwps: sources.                             */
+/* -------------------------------------------------------------------- */
     CNCSJP2FileView *poFileView = NULL;
     NCSError         eErr;
     CNCSError        oErr;
-    int              i;
-    VSILFILE        *fpVSIL = NULL;
-    VSIIOStream *poIOStream = NULL;
-    int              bUsingCustomStream = FALSE;
-
-    ECWInitialize();
 
-/* -------------------------------------------------------------------- */
-/*      This will disable automatic conversion of YCbCr to RGB by       */
-/*      the toolkit.                                                    */
-/* -------------------------------------------------------------------- */
-    if( !CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ) )
-        NCSecwSetConfig(NCSCFG_JP2_MANAGE_ICC, FALSE);
+    bUsingCustomStream = FALSE;
+    poFileView = new CNCSFile();
+    oErr = poFileView->Open( (char *) pszDatasetName, bProgressive );
+    eErr = oErr.GetErrorNumber();
 
 /* -------------------------------------------------------------------- */
-/*      Handle special case of a JPEG2000 data stream in another file.  */
+/*      If that did not work, trying opening as a virtual file.         */
 /* -------------------------------------------------------------------- */
-    int bIsVirtualFile = FALSE;
-try_again:
-    if( EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12) ||
-        bIsVirtualFile )
+    if( eErr != NCS_SUCCESS )
     {
-        GIntBig            subfile_offset=-1, subfile_size=-1;
-        const char *real_filename = NULL;
+        CPLDebug( "ECW", 
+                  "NCScbmOpenFileView(%s): eErr=%d, will try VSIL stream.", 
+                  pszDatasetName, (int) eErr );
 
-          if (EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12))
-          {
-            char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 12, ",", 0);
-            if (CSLCount(papszTokens) >= 2)
-            {
-                subfile_offset = CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
-                subfile_size = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
-            }
-            else
-            {
-                CPLError( CE_Failure, CPLE_OpenFailed, 
-                            "Failed to parse J2K_SUBFILE specification." );
-                CSLDestroy(papszTokens);
-                return NULL;
-            }
-            CSLDestroy(papszTokens);
+        delete poFileView;
 
-            real_filename = strstr(poOpenInfo->pszFilename,",");
-            if( real_filename != NULL )
-                real_filename = strstr(real_filename+1,",");
-            if( real_filename != NULL )
-                real_filename++;
-            else
-            {
-                CPLError( CE_Failure, CPLE_OpenFailed, 
-                            "Failed to parse J2K_SUBFILE specification." );
-                return NULL;
-            }
+        VSILFILE *fpVSIL = VSIFOpenL( pszDatasetName, "rb" );
+        if( fpVSIL == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed, 
+                      "Failed to open %s.", pszDatasetName );
+            return NULL;
+        }
 
-          }
-          else
-          {
-              real_filename = poOpenInfo->pszFilename;
-              subfile_offset = 0;
-          }
-
-          fpVSIL = VSIFOpenL( real_filename, "rb" );
-          if( fpVSIL == NULL )
-          {
-              CPLError( CE_Failure, CPLE_OpenFailed, 
-                        "Failed to open %s.",  real_filename );
-              return NULL;
-          }
-
-          if( hECWDatasetMutex == NULL )
-          {
-              hECWDatasetMutex = CPLCreateMutex();
-          }
-          else if( !CPLAcquireMutex( hECWDatasetMutex, 60.0 ) )
-          {
-              CPLDebug( "ECW", "Failed to acquire mutex in 60s." );
-          }
-          else
-          {
-              CPLDebug( "ECW", "Got mutex." );
-          }
-          poIOStream = new VSIIOStream();
-          poIOStream->Access( fpVSIL, FALSE, real_filename,
-                              subfile_offset, subfile_size );
-
-          poFileView = new CNCSJP2FileView();
-          oErr = poFileView->Open( poIOStream, false );
-
-          // The CNCSJP2FileView (poFileView) object may not use the iostream 
-          // (poIOStream) passed to the CNCSJP2FileView::Open() method if an 
-          // iostream is already available to the ECW JPEG 2000 SDK for a given
-          // file.  Consequently, if the iostream passed to 
-          // CNCSJP2FileView::Open() does not become the underlying iostream 
-          // of the CNCSJP2FileView object, then it should be deleted.
-          //
-          // In addition, the underlying iostream of the CNCSJP2FileView object
-          // should not be deleted until all CNCSJP2FileView objects using the 
-          // underlying iostream are deleted. Consequently, each time a 
-          // CNCSJP2FileView object is created, the nFileViewCount attribute 
-          // of the underlying VSIIOStream object must be incremented for use 
-          // in the ECWDataset destructor.
+        if( hECWDatasetMutex == NULL )
+        {
+            hECWDatasetMutex = CPLCreateMutex();
+        }
+        else if( !CPLAcquireMutex( hECWDatasetMutex, 60.0 ) )
+        {
+            CPLDebug( "ECW", "Failed to acquire mutex in 60s." );
+        }
+        else
+        {
+            CPLDebug( "ECW", "Got mutex." );
+        }
+        VSIIOStream *poIOStream = new VSIIOStream();
+        poIOStream->Access( fpVSIL, FALSE, pszDatasetName, 0, -1 );
+
+        poFileView = new CNCSJP2FileView();
+        oErr = poFileView->Open( poIOStream, bProgressive );
+
+        // The CNCSJP2FileView (poFileView) object may not use the iostream 
+        // (poIOStream) passed to the CNCSJP2FileView::Open() method if an 
+        // iostream is already available to the ECW JPEG 2000 SDK for a given
+        // file.  Consequently, if the iostream passed to 
+        // CNCSJP2FileView::Open() does not become the underlying iostream 
+        // of the CNCSJP2FileView object, then it should be deleted.
+        //
+        // In addition, the underlying iostream of the CNCSJP2FileView object
+        // should not be deleted until all CNCSJP2FileView objects using the 
+        // underlying iostream are deleted. Consequently, each time a 
+        // CNCSJP2FileView object is created, the nFileViewCount attribute 
+        // of the underlying VSIIOStream object must be incremented for use 
+        // in the ECWDataset destructor.
 		  
-          VSIIOStream * poUnderlyingIOStream = 
-              ((VSIIOStream *)(poFileView->GetStream()));
-
-          if ( poUnderlyingIOStream )
-              poUnderlyingIOStream->nFileViewCount++;
-
-          if ( poIOStream != poUnderlyingIOStream ) 
-          {
-              delete poIOStream;
-          }
-          else
-          {
-              bUsingCustomStream = TRUE;
-          }
-
-          CPLReleaseMutex( hECWDatasetMutex );
-
-          if( oErr.GetErrorNumber() != NCS_SUCCESS )
-          {
-              if (poFileView)
-                  delete poFileView;
-
-              char* pszErrorMessage = oErr.GetErrorMessage();
-              CPLError( CE_Failure, CPLE_AppDefined, 
-                        "%s", pszErrorMessage );
-              NCSFree(pszErrorMessage);
-
-              return NULL;
-          }
-    }
+        VSIIOStream * poUnderlyingIOStream = 
+            ((VSIIOStream *)(poFileView->GetStream()));
 
-/* -------------------------------------------------------------------- */
-/*      This has to either be a file on disk ending in .ecw or a        */
-/*      ecwp: protocol url.                                             */
-/* -------------------------------------------------------------------- */
-    else if( poOpenInfo->nHeaderBytes >= 16 
-        && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
-                    sizeof(jpc_header) ) == 0
-            || memcmp( poOpenInfo->pabyHeader, jp2_header, 
-                    sizeof(jp2_header) ) == 0) )
-    {
-        /* accept JPEG2000 files */
+        if ( poUnderlyingIOStream )
+            poUnderlyingIOStream->nFileViewCount++;
+
+        if ( poIOStream != poUnderlyingIOStream ) 
+        {
+            delete poIOStream;
+        }
+        else
+        {
+            bUsingCustomStream = TRUE;
+        }
+
+        CPLReleaseMutex( hECWDatasetMutex );
+
+        if( oErr.GetErrorNumber() != NCS_SUCCESS )
+        {
+            if (poFileView)
+                delete poFileView;
+
+            char* pszErrorMessage = oErr.GetErrorMessage();
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "%s", pszErrorMessage );
+            NCSFree(pszErrorMessage);
+
+            return NULL;
+        }
     }
-    else if( (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"ecw")
-              || poOpenInfo->nHeaderBytes == 0)
-             && !EQUALN(poOpenInfo->pszFilename,"ecwp:",5) )
-        return( NULL );
     
+    return poFileView;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
+
+{
+    CNCSJP2FileView *poFileView = NULL;
+    int              i;
+    int              bUsingCustomStream = FALSE;
+    CPLString        osFilename = poOpenInfo->pszFilename;
+
+    ECWInitialize();
+
 /* -------------------------------------------------------------------- */
-/*      Open the client interface.                                      */
+/*      If we get a J2K_SUBFILE style name, convert it into the         */
+/*      corresponding /vsisubfile/ path.                                */
+/*                                                                      */
+/*      From: J2K_SUBFILE:offset,size,filename                           */
+/*      To: /vsisubfile/offset_size,filename                            */
 /* -------------------------------------------------------------------- */
-    if( poFileView == NULL )
+    if (EQUALN(osFilename,"J2K_SUBFILE:",12))
     {
-        poFileView = new CNCSFile();
-        oErr = poFileView->Open( (char *) poOpenInfo->pszFilename, FALSE );
-        eErr = oErr.GetErrorNumber();
-        CPLDebug( "ECW", "NCScbmOpenFileView(%s): eErr = %d", 
-                  poOpenInfo->pszFilename, (int) eErr );
-        if( eErr != NCS_SUCCESS )
+        char** papszTokens = CSLTokenizeString2(osFilename.c_str()+12, ",", 0);
+        if (CSLCount(papszTokens) >= 2)
         {
-            delete poFileView;
-
-            /* If the file is not a 'real' file but recognized as a */
-            /* virtual file by the VSIL API, try again by using a */
-            /* VSIIOStream object, like in the J2K_SUBFILE case */
-            VSIStatBuf sBuf;
-            VSIStatBufL sBufL;
-            if (!bIsVirtualFile &&
-                VSIStat(poOpenInfo->pszFilename, &sBuf) != 0 &&
-                VSIStatL(poOpenInfo->pszFilename, &sBufL) == 0)
-            {
-                bIsVirtualFile = TRUE;
-                goto try_again;
-            }
-
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "%s", NCSGetErrorText(eErr) );
+            osFilename.Printf( "/vsisubfile/%s_%s,%s",
+                               papszTokens[0], papszTokens[1], papszTokens[2]);
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed, 
+                      "Failed to parse J2K_SUBFILE specification." );
+            CSLDestroy(papszTokens);
             return NULL;
         }
+        CSLDestroy(papszTokens);
     }
 
-    if( poOpenInfo->eAccess == GA_Update )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "The ECW driver does not support update access to existing"
-                  " datasets.\n" );
+/* -------------------------------------------------------------------- */
+/*      Open the client interface.                                      */
+/* -------------------------------------------------------------------- */
+    poFileView = OpenFileView( osFilename, false, bUsingCustomStream );
+    if( poFileView == NULL )
         return NULL;
-    }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
     ECWDataset  *poDS;
 
     poDS = new ECWDataset(bIsJPEG2000);
-
     poDS->poFileView = poFileView;
+    poDS->eAccess = poOpenInfo->eAccess;
 
-    if( fpVSIL != NULL )
+    // Disable .aux.xml writing for subfiles and such.  Unfortunately
+    // this will also disable it in some cases where it might be 
+    // applicable. 
+    if( bUsingCustomStream )
         poDS->nPamFlags |= GPF_DISABLED;
 
     poDS->bUsingCustomStream = bUsingCustomStream;
@@ -1407,18 +1477,28 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Look for supporting coordinate system information.              */
 /* -------------------------------------------------------------------- */
-    GDALJP2Metadata oJP2Geo;
-
-    if( bIsJPEG2000 && oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
+    if( bIsJPEG2000 )
     {
-        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;
+        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");
+        }
     }
     else
     {
@@ -1429,35 +1509,23 @@ try_again:
 /*      Check for world file for ecw files.                             */
 /* -------------------------------------------------------------------- */
     if( !poDS->bGeoTransformValid 
-        && EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"ecw") )
+        && EQUAL(CPLGetExtension(osFilename),"ecw") )
     {
         poDS->bGeoTransformValid |= 
-            GDALReadWorldFile( poOpenInfo->pszFilename, ".eww", 
+            GDALReadWorldFile( osFilename, ".eww", 
                                poDS->adfGeoTransform )
-            || GDALReadWorldFile( poOpenInfo->pszFilename, ".ecww", 
+            || GDALReadWorldFile( osFilename, ".ecww", 
                                   poDS->adfGeoTransform )
-            || GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
+            || GDALReadWorldFile( osFilename, ".wld", 
                                   poDS->adfGeoTransform );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->SetDescription( osFilename );
     poDS->TryLoadXML();
     
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->eAccess == GA_Update )
-    {
-        delete poDS;
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "The ECW driver does not support update access to existing"
-                  " datasets.\n" );
-        return NULL;
-    }
-    
     return( poDS );
 }
 
@@ -1540,13 +1608,40 @@ CPLErr ECWDataset::GetGeoTransform( double * padfTransform )
 }
 
 /************************************************************************/
+/*                           GetMetadataItem()                          */
+/************************************************************************/
+
+const char *ECWDataset::GetMetadataItem( const char * pszName,
+                                         const char * pszDomain )
+{
+    if (!bIsJPEG2000 && pszDomain != NULL && EQUAL(pszDomain, "ECW") && pszName != NULL)
+    {
+        if (EQUAL(pszName, "PROJ"))
+            return m_osProjCode.size() ? m_osProjCode.c_str() : "RAW";
+        if (EQUAL(pszName, "DATUM"))
+            return m_osDatumCode.size() ? m_osDatumCode.c_str() : "RAW";
+        if (EQUAL(pszName, "UNITS"))
+            return m_osUnitsCode.size() ? m_osUnitsCode.c_str() : "METERS";
+    }
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
 
 char **ECWDataset::GetMetadata( const char *pszDomain )
 
 {
-    if( pszDomain == NULL || !EQUAL(pszDomain,"GML") )
+    if( !bIsJPEG2000 && pszDomain != NULL && EQUAL(pszDomain, "ECW") )
+    {
+        oECWMetadataList.Clear();
+        oECWMetadataList.AddString(CPLSPrintf("%s=%s", "PROJ", GetMetadataItem("PROJ", "ECW")));
+        oECWMetadataList.AddString(CPLSPrintf("%s=%s", "DATUM", GetMetadataItem("DATUM", "ECW")));
+        oECWMetadataList.AddString(CPLSPrintf("%s=%s", "UNITS", GetMetadataItem("UNITS", "ECW")));
+        return oECWMetadataList.List();
+    }
+    else if( pszDomain == NULL || !EQUAL(pszDomain,"GML") )
         return GDALPamDataset::GetMetadata( pszDomain );
     else
         return papszGMLMetadata;
@@ -1599,8 +1694,11 @@ void ECWDataset::ECW2WKTProjection()
 /* -------------------------------------------------------------------- */
 /*      do we have projection and datum?                                */
 /* -------------------------------------------------------------------- */
-    CPLDebug( "ECW", "projection=%s, datum=%s",
-              psFileInfo->szProjection, psFileInfo->szDatum );
+    CPLString osUnits = ECWTranslateFromCellSizeUnits(psFileInfo->eCellSizeUnits);
+
+    CPLDebug( "ECW", "projection=%s, datum=%s, units=%s",
+              psFileInfo->szProjection, psFileInfo->szDatum,
+              osUnits.c_str());
 
     if( EQUAL(psFileInfo->szProjection,"RAW") )
         return;
@@ -1609,17 +1707,151 @@ void ECWDataset::ECW2WKTProjection()
 /*      Set projection if we have it.                                   */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS;
-    CPLString osUnits = "METERS";
 
-    if( psFileInfo->eCellSizeUnits == ECW_CELL_UNITS_FEET )
-        osUnits = "FEET";
+    /* For backward-compatible with previous behaviour. Should we only */
+    /* restrict to those 2 values ? */
+    if (psFileInfo->eCellSizeUnits != ECW_CELL_UNITS_METERS &&
+        psFileInfo->eCellSizeUnits != ECW_CELL_UNITS_FEET)
+        osUnits = ECWTranslateFromCellSizeUnits(ECW_CELL_UNITS_METERS);
 
+    m_osDatumCode = psFileInfo->szDatum;
+    m_osProjCode = psFileInfo->szProjection;
+    m_osUnitsCode = osUnits;
     if( oSRS.importFromERM( psFileInfo->szProjection, 
                             psFileInfo->szDatum, 
-                            osUnits ) != OGRERR_NONE )
-        return;
+                            osUnits ) == OGRERR_NONE )
+    {
+        oSRS.exportToWkt( &pszProjection );
+    }
 
-    oSRS.exportToWkt( &pszProjection );
+    CPLErrorReset(); /* see #4187 */
+}
+
+/************************************************************************/
+/*                        ECWTranslateFromWKT()                         */
+/************************************************************************/
+
+int ECWTranslateFromWKT( const char *pszWKT,
+                         char *pszProjection,
+                         int nProjectionLen,
+                         char *pszDatum,
+                         int nDatumLen,
+                         char *pszUnits)
+
+{
+    OGRSpatialReference oSRS;
+    char *pszWKTIn = (char *) pszWKT;
+
+    strcpy( pszProjection, "RAW" );
+    strcpy( pszDatum, "RAW" );
+    strcpy( pszUnits, "METERS" );
+
+    if( pszWKT == NULL || strlen(pszWKT) == 0 )
+        return FALSE;
+    
+    oSRS.importFromWkt( &pszWKTIn );
+    
+    if( oSRS.IsLocal() )
+        return TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Do we have an overall EPSG number for this coordinate system?   */
+/* -------------------------------------------------------------------- */
+    const char *pszAuthorityCode = NULL;
+    const char *pszAuthorityName = NULL;
+    UINT32 nEPSGCode = 0;
+
+    if( oSRS.IsProjected() )
+    {
+        pszAuthorityCode =  oSRS.GetAuthorityCode( "PROJCS" );
+        pszAuthorityName =  oSRS.GetAuthorityName( "PROJCS" );
+    }
+    else if( oSRS.IsGeographic() )
+    {
+        pszAuthorityCode =  oSRS.GetAuthorityCode( "GEOGCS" );
+        pszAuthorityName =  oSRS.GetAuthorityName( "GEOGCS" );
+    }
+
+    if( pszAuthorityName != NULL && EQUAL(pszAuthorityName,"EPSG") 
+        && pszAuthorityCode != NULL && atoi(pszAuthorityCode) > 0 )
+        nEPSGCode = (UINT32) atoi(pszAuthorityCode);
+
+    if( nEPSGCode != 0 )
+    {
+        char *pszEPSGProj = NULL, *pszEPSGDatum = NULL;
+        CNCSError oErr;
+
+        oErr = 
+            CNCSJP2FileView::GetProjectionAndDatum( atoi(pszAuthorityCode), 
+                                                 &pszEPSGProj, &pszEPSGDatum );
+
+        CPLDebug( "ECW", "GetGDTProjDat(%d) = %s/%s", 
+                  atoi(pszAuthorityCode), pszEPSGProj, pszEPSGDatum );
+
+        if( oErr.GetErrorNumber() == NCS_SUCCESS
+            && pszEPSGProj != NULL && pszEPSGDatum != NULL )
+        {
+            strncpy( pszProjection, pszEPSGProj, nProjectionLen );
+            strncpy( pszDatum, pszEPSGDatum, nDatumLen );
+            pszProjection[nProjectionLen - 1] = 0;
+            pszDatum[nDatumLen - 1] = 0;
+            NCSFree( pszEPSGProj );
+            NCSFree( pszEPSGDatum );
+            return TRUE;
+        }
+
+        NCSFree( pszEPSGProj );
+        NCSFree( pszEPSGDatum );
+
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Fallback to translating based on the ecw_cs.wkt file, and       */
+/*      various jiffy rules.                                            */
+/* -------------------------------------------------------------------- */
+
+    return oSRS.exportToERM( pszProjection, pszDatum, pszUnits ) == OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                    ECWTranslateToCellSizeUnits()                     */
+/************************************************************************/
+
+CellSizeUnits ECWTranslateToCellSizeUnits(const char* pszUnits)
+{
+    if (EQUAL(pszUnits, "METERS"))
+        return ECW_CELL_UNITS_METERS;
+    else if (EQUAL(pszUnits, "DEGREES"))
+        return ECW_CELL_UNITS_DEGREES;
+    else if (EQUAL(pszUnits, "FEET"))
+        return ECW_CELL_UNITS_FEET;
+    else if (EQUAL(pszUnits, "UNKNOWN"))
+        return ECW_CELL_UNITS_UNKNOWN;
+    else if (EQUAL(pszUnits, "INVALID"))
+        return ECW_CELL_UNITS_INVALID;
+    else
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "Unrecognized value for UNITS : %s", pszUnits);
+        return ECW_CELL_UNITS_INVALID;
+    }
+}
+
+/************************************************************************/
+/*                     ECWTranslateFromCellSizeUnits()                  */
+/************************************************************************/
+
+const char* ECWTranslateFromCellSizeUnits(CellSizeUnits eUnits)
+{
+    if (eUnits == ECW_CELL_UNITS_METERS)
+        return "METERS";
+    else if (eUnits == ECW_CELL_UNITS_DEGREES)
+        return "DEGREES";
+    else if (eUnits == ECW_CELL_UNITS_FEET)
+        return "FEET";
+    else if (eUnits == ECW_CELL_UNITS_UNKNOWN)
+        return "UNKNOWN";
+    else
+        return "INVALID";
 }
 
 #endif /* def FRMT_ecw */
@@ -1644,12 +1876,19 @@ void ECWInitialize()
     bNCSInitialized = TRUE;
 
 /* -------------------------------------------------------------------- */
+/*      This will disable automatic conversion of YCbCr to RGB by       */
+/*      the toolkit.                                                    */
+/* -------------------------------------------------------------------- */
+    if( !CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ) )
+        NCSecwSetConfig(NCSCFG_JP2_MANAGE_ICC, FALSE);
+
+/* -------------------------------------------------------------------- */
 /*      Initialize cache memory limit.  Default is apparently 1/4 RAM.  */
 /* -------------------------------------------------------------------- */
     const char *pszEcwCacheSize = 
         CPLGetConfigOption("GDAL_ECW_CACHE_MAXMEM",NULL);
     if( pszEcwCacheSize == NULL )
-        CPLGetConfigOption("ECW_CACHE_MAXMEM",NULL);
+        pszEcwCacheSize = CPLGetConfigOption("ECW_CACHE_MAXMEM",NULL);
 
     if( pszEcwCacheSize != NULL )
         NCSecwSetConfig(NCSCFG_CACHE_MAXMEM, (UINT32) atoi(pszEcwCacheSize) );
@@ -1676,6 +1915,18 @@ void ECWInitialize()
 /* -------------------------------------------------------------------- */
 /*      Various other configuration items.                              */
 /* -------------------------------------------------------------------- */
+    pszOpt = CPLGetConfigOption( "ECWP_BLOCKING_TIME_MS", NULL );
+    if( pszOpt )
+        NCSecwSetConfig( NCSCFG_BLOCKING_TIME_MS, 
+                         (NCSTimeStampMs) atoi(pszOpt) );
+
+    // I believe 10s means we wait for complete data back from
+    // ECWP almost all the time which is good for our blocking model.
+    pszOpt = CPLGetConfigOption( "ECWP_REFRESH_TIME_MS", "10000" );
+    if( pszOpt )
+        NCSecwSetConfig( NCSCFG_REFRESH_TIME_MS, 
+                         (NCSTimeStampMs) atoi(pszOpt) );
+
     pszOpt = CPLGetConfigOption( "ECW_TEXTURE_DITHER", NULL );
     if( pszOpt )
         NCSecwSetConfig( NCSCFG_TEXTURE_DITHER, 
@@ -1691,12 +1942,12 @@ void ECWInitialize()
     if( pszOpt )
         NCSecwSetConfig( NCSCFG_CACHE_MAXOPEN, (UINT32) atoi(pszOpt) );
 
+#if ECWSDK_VERSION >= 40
     pszOpt = CPLGetConfigOption( "ECW_AUTOGEN_J2I", NULL );
     if( pszOpt )
-        NCSecwSetConfig( NCSCFG_FORCE_FILE_REOPEN, 
+        NCSecwSetConfig( NCSCFG_JP2_AUTOGEN_J2I, 
                          (BOOLEAN) CSLTestBoolean( pszOpt ) );
 
-#if ECWSDK_VERSION >= 40
     pszOpt = CPLGetConfigOption( "ECW_OPTIMIZE_USE_NEAREST_NEIGHBOUR", NULL );
     if( pszOpt )
         NCSecwSetConfig( NCSCFG_OPTIMIZE_USE_NEAREST_NEIGHBOUR, 
@@ -1790,6 +2041,10 @@ void GDALRegister_ECW()
 #endif
 
 "</CreationOptionList>" );
+#else
+        /* In read-only mode, we support VirtualIO. This is not the case */
+        /* for ECWCreateCopyECW() */
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 #endif
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
@@ -1850,6 +2105,7 @@ void GDALRegister_JP2ECW()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_jp2ecw.html" );
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
         
         poDriver->pfnIdentify = ECWDataset::IdentifyJPEG2000;
         poDriver->pfnOpen = ECWDataset::OpenJPEG2000;
@@ -1863,6 +2119,10 @@ void GDALRegister_JP2ECW()
 "   <Option name='TARGET' type='float' description='Compression Percentage' />"
 "   <Option name='PROJ' type='string' description='ECW Projection Name'/>"
 "   <Option name='DATUM' type='string' description='ECW Datum Name' />"
+"   <Option name='UNITS' type='string-select' description='ECW Projection Units'>"
+"       <Value>METERS</Value>"
+"       <Value>FEET</Value>"
+"   </Option>"
 
 #if ECWSDK_VERSION < 40
 "   <Option name='LARGE_OK' type='boolean' description='Enable compressing 500+MB files'/>"
@@ -1903,7 +2163,3 @@ void GDALRegister_JP2ECW()
     }
 #endif /* def FRMT_ecw */
 }
-
-
-
-
diff --git a/frmts/ecw/frmt_ecw.html b/frmts/ecw/frmt_ecw.html
index 2ca9cab..b92b5f2 100644
--- a/frmts/ecw/frmt_ecw.html
+++ b/frmts/ecw/frmt_ecw.html
@@ -15,6 +15,30 @@ but in some cases coordinate systems may not translate.<p>
 Support for the ECW driver in GDAL is optional, and requires linking
 in external ECW SDK libraries provided by ERDAS.<p>
 
+In addition to ECW files, this driver also supports access to network
+image services using the "ECWP" protocol.  Use the full ecwp:// url of 
+the service as the dataset name.  When built with SDK 4.1 or newer it
+is also possible to take advantage of 
+<a href="http://trac.osgeo.org/gdal/wiki/rfc24_progressive_data_support">
+RFC 24</a> style asynchronous access to ECWP services.<p>
+
+Starting with GDAL 1.9.0, XMP metadata can be extracted from JPEG2000 files, and will be
+stored as XML raw content in the xml:XMP metadata domain.<p>
+
+<h2>ECW metadata domain / Georeferencing update</h2>
+
+(Starting with GDAL 1.9.0)<p>
+
+The PROJ, DATUM and UNITS found in the ECW header are
+reported in the ECW metadata domain. They can also be set with the SetMetadataItem()
+method, in order to update the header information of an existing ECW file,
+opened in update mode, without modifying the imagery.<p>
+
+The geotransform and projection can also be modified with the SetGeoTransform()
+and SetProjection() methods. If the projection is set with SetProjection() and
+the PROJ, DATUM or UNITS with SetMetadataItem(), the later values will override the values
+built from the projection string.<p>
+
 <h2>Creation Issues</h2>
 
 The ECW 4.x SDK from ERDAS is only free for image decompression.  To 
@@ -47,6 +71,9 @@ Common examples are NUTM11, or GEODETIC.<p>
 <li> <b>DATUM=name</b>: Name of the ECW datum string to use. 
 Common examples are WGS84 or NAD83.<p>
 
+<li> <b>UNITS=name</b>: (GDAL >= 1.9.0) Name of the ECW projection units to use :
+METERS (default) or FEET (us-foot).<p>
+
 <li> <b>LARGE_OK=YES</b>: When built with the ECW 3.x SDK this option can be 
 set to allow compressing files larger than 500MB.  It is the users 
 responsibility to ensure that the licensing requirments for large file 
@@ -86,6 +113,15 @@ ECWP results.  If unset ECWP caching will not be enabled.<p>
 number of megabytes of space in the ECWP_CACHE_LOCATION to be used for 
 caching ECWP results.<p>
 
+<li> <b>ECWP_BLOCKING_TIME_MS</b>: time an ecwp:// blocking read will wait
+before returning - default 10000 ms.<p>
+
+<li> <b>ECWP_REFRESH_TIME_MS</b>: time delay between blocks arriving and the 
+next refresh callback - default 10000 ms.  For the purposes of GDAL this is
+the amount of time the driver will wait for more data on an ecwp connection 
+for which the final result has not yet been returned.  If set small then 
+RasterIO() requests will often produce low resolution results.<p>
+
 <li> <b>ECW_TEXTURE_DITHER=TRUE/FALSE</b>: This may be set to FALSE to disable
 dithering when decompressing ECW files.  Defaults to TRUE.<p>
 
@@ -105,13 +141,12 @@ in an error.<p>
 in the creation options, may also be set as configuration options. See above.
 <p>
 
-
 </ul>
 
 <h2>See Also:</h2>
 
 <ul>
-<li> Implemented as <tt>gdal/frmts/ecw/ecwdataset.cpp</tt>.
+<li> Implemented in <tt>gdal/frmts/ecw</tt>.
 
 <li> ECW SDK available at <a href="http://www.erdas.com/products/ERDASECWJPEG2000SDK/Details.aspx">erdas.com</a>.
 
diff --git a/frmts/ecw/gdal_ecw.h b/frmts/ecw/gdal_ecw.h
new file mode 100755
index 0000000..be9c97c
--- /dev/null
+++ b/frmts/ecw/gdal_ecw.h
@@ -0,0 +1,499 @@
+/******************************************************************************
+ * $Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $
+ *
+ * Project:  GDAL 
+ * Purpose:  ECW (ERDAS Wavelet Compression Format) Driver Definitions
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2001-2011, 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 GDAL_ECW_H_INCLUDED
+#define GDAL_ECW_H_INCLUDED
+
+#include "gdal_pam.h"
+#include "gdal_frmts.h"
+#include "gdaljp2metadata.h"
+#include "cpl_string.h"
+#include "cpl_conv.h"
+#include "cpl_multiproc.h"
+#include "cpl_vsi.h"
+
+#undef NOISY_DEBUG
+
+#ifdef FRMT_ecw
+
+// The following is needed on 4.x+ to enable rw support.
+#if defined(HAVE_COMPRESS)
+#  define ECW_COMPRESS_RW_SDK_VERSION
+#endif
+
+#if defined(_MSC_VER)
+#  pragma warning(disable:4800)
+#endif
+
+#include <NCSECWClient.h>
+#include <NCSECWCompressClient.h>
+#include <NCSErrors.h>
+#include <NCSFile.h>
+#include <NCSJP2FileView.h>
+
+/* By default, assume 3.3 SDK Version. */
+#if !defined(ECWSDK_VERSION)
+#  define ECWSDK_VERSION 33
+#endif
+
+#if ECWSDK_VERSION < 40
+
+#if !defined(NO_COMPRESS)
+#  define HAVE_COMPRESS
+#endif
+
+#  include <NCSJP2File.h>
+#else
+#  include <ECWJP2BuildNumber.h>
+#  include <HeaderEditor.h>
+#  define NCS_FASTCALL
+#endif
+
+#ifndef NCSFILEBASE_H
+#  include <NCSJP2FileView.h>
+#else
+#  undef  CNCSJP2FileView
+#  define CNCSJP2FileView	  CNCSFile
+#endif
+
+void ECWInitialize( void );
+GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo);
+
+#ifdef HAVE_COMPRESS
+GDALDataset *
+ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS, 
+                 int bStrict, char ** papszOptions, 
+                 GDALProgressFunc pfnProgress, void * pProgressData );
+GDALDataset *
+ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS, 
+                 int bStrict, char ** papszOptions, 
+                 GDALProgressFunc pfnProgress, void * pProgressData );
+
+GDALDataset *
+ECWCreateECW( const char * pszFilename, int nXSize, int nYSize, int nBands, 
+              GDALDataType eType, char **papszOptions );
+GDALDataset *
+ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands, 
+                  GDALDataType eType, char **papszOptions );
+#endif
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             JP2Userbox                               */
+/* ==================================================================== */
+/************************************************************************/
+#ifdef HAVE_COMPRESS
+class JP2UserBox : public CNCSJP2Box {
+
+private:
+    int           nDataLength;
+    unsigned char *pabyData;
+
+public:
+    JP2UserBox();
+
+    virtual ~JP2UserBox();
+
+#if ECWSDK_VERSION >= 40
+    virtual CNCSError Parse( NCS::JP2::CFile &JP2File, 
+                             NCS::CIOStream &Stream);
+    virtual CNCSError UnParse( NCS::JP2::CFile &JP2File, 
+								NCS::CIOStream &Stream);
+#else        
+    virtual CNCSError Parse(class CNCSJP2File &JP2File, 
+                            CNCSJPCIOStream &Stream);
+    virtual CNCSError UnParse(class CNCSJP2File &JP2File, 
+                              CNCSJPCIOStream &Stream);
+#endif
+    virtual void UpdateXLBox(void);
+
+    void    SetData( int nDataLength, const unsigned char *pabyDataIn );
+    
+    int     GetDataLength() { return nDataLength; }
+    unsigned char *GetData() { return pabyData; }
+};
+#endif /* def HAVE_COMPRESS */
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             VSIIOStream                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class VSIIOStream : public CNCSJPCIOStream
+
+{
+  public:
+    
+    INT64    startOfJPData;
+    INT64    lengthOfJPData;
+    VSILFILE    *fpVSIL;
+    int      bWritable;
+	int      nFileViewCount;
+    char     *pszFilename;
+
+    VSIIOStream() {
+        nFileViewCount = 0;
+        startOfJPData = 0;
+        lengthOfJPData = -1;
+        fpVSIL = NULL;
+    }
+    virtual ~VSIIOStream() {
+        Close();
+    }
+
+    virtual CNCSError Close() {
+        CNCSError oErr = CNCSJPCIOStream::Close();
+        if( fpVSIL != NULL )
+        {
+            VSIFCloseL( fpVSIL );
+            fpVSIL = NULL;
+        }
+        return oErr;
+    }        
+        
+#if ECWSDK_VERSION >= 40
+    virtual NCS::CIOStream *Clone() { return NULL; }
+#endif /* ECWSDK_VERSION >= 4 */
+
+    virtual CNCSError Access( VSILFILE *fpVSILIn, BOOLEAN bWrite,
+                              const char *pszFilename, 
+                              INT64 start, INT64 size = -1) {
+
+        fpVSIL = fpVSILIn;
+        startOfJPData = start;
+        lengthOfJPData = size;
+        bWritable = bWrite;
+        VSIFSeekL(fpVSIL, startOfJPData, SEEK_SET);
+
+        // the filename is used to establish where to put temporary files.
+        // if it does not have a path to a real directory, we will 
+        // substitute something. 
+        CPLString osFilenameUsed = pszFilename;
+        CPLString osPath = CPLGetPath( pszFilename );
+        struct stat sStatBuf;
+        if( osPath != "" && stat( osPath, &sStatBuf ) != 0 )
+        {
+            osFilenameUsed = CPLGenerateTempFilename( NULL );
+            // try to preserve the extension.
+            if( strlen(CPLGetExtension(pszFilename)) > 0 )
+            {
+                osFilenameUsed += ".";
+                osFilenameUsed += CPLGetExtension(pszFilename);
+            }
+            CPLDebug( "ECW", "Using filename '%s' for temporary directory determination purposes.", osFilenameUsed.c_str() );
+        }
+        return(CNCSJPCIOStream::Open((char *)osFilenameUsed.c_str(), 
+                                     (bool) bWrite));
+    }
+
+    virtual bool NCS_FASTCALL Seek() {
+        return(true);
+    }
+    
+    virtual bool NCS_FASTCALL Seek(INT64 offset, Origin origin = CURRENT) {
+        bool success = false;
+        switch(origin) {
+            case START:
+              success = (0 == VSIFSeekL(fpVSIL, offset+startOfJPData, SEEK_SET));
+              break;
+
+            case CURRENT:
+              success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_CUR));
+              break;
+                
+            case END:
+              success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_END));
+              break;
+        }
+        if( !success )
+            CPLDebug( "ECW", "VSIIOStream::Seek(%d,%d) failed.", 
+                      (int) offset, (int) origin );
+        return(success);
+    }
+
+    virtual INT64 NCS_FASTCALL Tell() {
+        return VSIFTellL( fpVSIL ) - startOfJPData;
+    }
+
+    virtual INT64 NCS_FASTCALL Size() {
+        if( lengthOfJPData != -1 )
+            return lengthOfJPData;
+        else
+        {
+            INT64 curPos = Tell(), size;
+
+            Seek( 0, END );
+            size = Tell();
+            Seek( curPos, START );
+
+            return size;
+        }
+    }
+
+    virtual bool NCS_FASTCALL Read(void* buffer, UINT32 count) {
+        if( count == 0 )
+            return true;
+
+//        return(1 == VSIFReadL( buffer, count, 1, fpVSIL ) );
+
+        // The following is a hack 
+        if( VSIFReadL( buffer, count, 1, fpVSIL ) != 1 )
+        {
+            CPLDebug( "VSIIOSTREAM",
+                      "Read(%d) failed @ " CPL_FRMT_GIB ", ignoring failure.",
+                      count, (VSIFTellL( fpVSIL ) - startOfJPData) );
+        }
+        
+        return true;
+    }
+
+    virtual bool NCS_FASTCALL Write(void* buffer, UINT32 count) {
+        if( count == 0 )
+            return true;
+        if( 1 != VSIFWriteL(buffer, count, 1, fpVSIL) )
+        {
+            CPLDebug( "ECW", "VSIIOStream::Write(%d) failed.", 
+                      (int) count );
+            return false;
+        }
+        else 
+            return true;
+    }
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ECWAsyncReader                            */
+/* ==================================================================== */
+/************************************************************************/
+class ECWDataset;
+
+#if ECWSDK_VERSION >= 40
+
+class ECWAsyncReader : public GDALAsyncReader
+{
+private:
+    CNCSJP2FileView *poFileView;
+    void            *hMutex;
+    int              bUsingCustomStream;
+
+    int              bUpdateReady;
+    int              bComplete;
+
+    static NCSEcwReadStatus RefreshCB( NCSFileView * );
+    NCSEcwReadStatus ReadToBuffer();
+    
+public:
+    ECWAsyncReader();
+    virtual ~ECWAsyncReader();
+    virtual GDALAsyncStatusType GetNextUpdatedRegion(double dfTimeout,
+                                                     int* pnXBufOff,
+                                                     int* pnYBufOff,
+                                                     int* pnXBufSize,
+                                                     int* pnYBufSize);
+
+    friend class ECWDataset;
+};
+#endif /* ECWSDK_VERSION >= 40 */
+
+/************************************************************************/
+/* ==================================================================== */
+/*				ECWDataset				*/
+/* ==================================================================== */
+/************************************************************************/
+
+class ECWRasterBand;
+
+class CPL_DLL ECWDataset : public GDALPamDataset
+{
+    friend class ECWRasterBand;
+    friend class ECWAsyncReader;
+
+    int         bIsJPEG2000;
+
+    CNCSJP2FileView *poFileView;
+    NCSFileViewFileInfoEx *psFileInfo;
+
+    GDALDataType eRasterDataType;
+    NCSEcwCellType eNCSRequestDataType;
+
+    int         bUsingCustomStream;
+
+    // Current view window. 
+    int         bWinActive;
+    int         nWinXOff, nWinYOff, nWinXSize, nWinYSize;
+    int         nWinBufXSize, nWinBufYSize;
+    int         nWinBandCount;
+    int         *panWinBandList;
+    int         nWinBufLoaded;
+    void        **papCurLineBuf;
+
+    int         bGeoTransformValid;
+    double      adfGeoTransform[6];
+    char        *pszProjection;
+    int         nGCPCount;
+    GDAL_GCP    *pasGCPList;
+
+    char        **papszGMLMetadata;
+
+    void        ECW2WKTProjection();
+
+    void        CleanupWindow();
+    int         TryWinRasterIO( GDALRWFlag, int, int, int, int,
+                                GByte *, int, int, GDALDataType,
+                                int, int *, int, int, int );
+    CPLErr      LoadNextLine();
+
+    static CNCSJP2FileView    *OpenFileView( const char *pszDatasetName,
+                                             bool bProgressive,
+                                             int &bUsingCustomStream );
+
+    int         bHdrDirty;
+    CPLString   m_osDatumCode;
+    CPLString   m_osProjCode;
+    CPLString   m_osUnitsCode;
+    int         bGeoTransformChanged;
+    int         bProjectionChanged;
+    int         bProjCodeChanged;
+    int         bDatumCodeChanged;
+    int         bUnitsCodeChanged;
+    void        WriteHeader();
+
+    CPLStringList oECWMetadataList;
+
+  public:
+		ECWDataset(int bIsJPEG2000);
+		~ECWDataset();
+                
+    static GDALDataset *Open( GDALOpenInfo *, int bIsJPEG2000 );
+    static int          IdentifyJPEG2000( GDALOpenInfo * poOpenInfo );
+    static GDALDataset *OpenJPEG2000( GDALOpenInfo * );
+    static int          IdentifyECW( GDALOpenInfo * poOpenInfo );
+    static GDALDataset *OpenECW( GDALOpenInfo * );
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              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 const char *GetMetadataItem( const char * pszName,
+                                     const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" );
+
+    virtual CPLErr SetGeoTransform( double * padfGeoTransform );
+    virtual CPLErr SetProjection( const char* pszProjection );
+    virtual CPLErr SetMetadataItem( const char * pszName,
+                                 const char * pszValue,
+                                 const char * pszDomain = "" );
+    virtual CPLErr SetMetadata( char ** papszMetadata,
+                             const char * pszDomain = "" );
+
+    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
+                               int nBufXSize, int nBufYSize, 
+                               GDALDataType eDT, 
+                               int nBandCount, int *panBandList,
+                               char **papszOptions );
+
+    // progressive methods
+#if ECWSDK_VERSION >= 40
+    virtual GDALAsyncReader* BeginAsyncReader( int nXOff, int nYOff,
+                                               int nXSize, int nYSize, 
+                                               void *pBuf,
+                                               int nBufXSize, int nBufYSize,
+                                               GDALDataType eBufType,
+                                               int nBandCount, int* panBandMap,
+                                               int nPixelSpace, int nLineSpace,
+                                               int nBandSpace,
+                                               char **papszOptions);
+
+    virtual void EndAsyncReader(GDALAsyncReader *);
+#endif /* ECWSDK_VERSION > 40 */
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ECWRasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class ECWRasterBand : public GDALPamRasterBand
+{
+    friend class ECWDataset;
+    
+    // NOTE: poDS may be altered for NITF/JPEG2000 files!
+    ECWDataset     *poGDS;
+
+    GDALColorInterp         eBandInterp;
+
+    int                          iOverview; // -1 for base. 
+
+    std::vector<ECWRasterBand*>  apoOverviews;
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              int, int );
+
+  public:
+
+                   ECWRasterBand( ECWDataset *, int, int = -1 );
+                   ~ECWRasterBand();
+
+    virtual CPLErr IReadBlock( int, int, void * );
+    virtual int    HasArbitraryOverviews() { return apoOverviews.size() == 0; }
+    virtual int    GetOverviewCount() { return apoOverviews.size(); }
+    virtual GDALRasterBand *GetOverview(int);
+
+    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr SetColorInterpretation( GDALColorInterp );
+
+    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
+                               int nBufXSize, int nBufYSize, 
+                               GDALDataType eDT, char **papszOptions );
+};
+
+int ECWTranslateFromWKT( const char *pszWKT,
+                         char *pszProjection,
+                         int nProjectionLen,
+                         char *pszDatum,
+                         int nDatumLen,
+                         char *pszUnits);
+
+CellSizeUnits ECWTranslateToCellSizeUnits(const char* pszUnits);
+const char* ECWTranslateFromCellSizeUnits(CellSizeUnits eUnits);
+
+#endif /* def FRMT_ecw */
+
+#endif /* ndef GDAL_ECW_H_INCLUDED */
diff --git a/frmts/ecw/jp2userbox.cpp b/frmts/ecw/jp2userbox.cpp
index a0605c3..a160771 100644
--- a/frmts/ecw/jp2userbox.cpp
+++ b/frmts/ecw/jp2userbox.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jp2userbox.cpp 21325 2010-12-28 23:44:31Z warmerdam $
+ * $Id: jp2userbox.cpp 21514 2011-01-16 23:49:42Z warmerdam $
  *
  * Project:  GDAL ECW Driver
  * Purpose:  JP2UserBox implementation - arbitrary box read/write.
@@ -27,9 +27,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "jp2userbox.h"
+#include "gdal_ecw.h"
 
-CPL_CVSID("$Id: jp2userbox.cpp 21325 2010-12-28 23:44:31Z warmerdam $");
+CPL_CVSID("$Id: jp2userbox.cpp 21514 2011-01-16 23:49:42Z warmerdam $");
 
 #if defined(HAVE_COMPRESS)
 
diff --git a/frmts/ecw/makefile.vc b/frmts/ecw/makefile.vc
index e093400..3d69077 100644
--- a/frmts/ecw/makefile.vc
+++ b/frmts/ecw/makefile.vc
@@ -2,7 +2,8 @@
 EXTRAFLAGS = 	$(ECWFLAGS) -DFRMT_ecw 
 
 
-OBJ	=	ecwdataset.obj ecwcreatecopy.obj jp2userbox.obj
+OBJ	=	ecwdataset.obj ecwcreatecopy.obj jp2userbox.obj \
+		ecwasyncreader.obj
 
 PLUGIN_DLL =	gdal_ECW_JP2ECW.dll
 
@@ -17,6 +18,8 @@ EXTRAFLAGS = $(EXTRAFLAGS) -D_WIN32_WINNT=0x0500
 default:	$(OBJ)
 	$(INSTALL) *.obj ..\o
 
+$(OBJ):	gdal_ecw.h
+
 all:	default testecw.exe
 
 clean:
diff --git a/frmts/elas/elasdataset.cpp b/frmts/elas/elasdataset.cpp
index 848d730..13b704a 100644
--- a/frmts/elas/elasdataset.cpp
+++ b/frmts/elas/elasdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: elasdataset.cpp 16396 2009-02-22 20:49:52Z rouault $
+ * $Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $
  *
  * Project:  ELAS Translator
  * Purpose:  Complete implementation of ELAS translator module for GDAL.
@@ -29,7 +29,7 @@
 
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: elasdataset.cpp 16396 2009-02-22 20:49:52Z rouault $");
+CPL_CVSID("$Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $");
 
 CPL_C_START
 void	GDALRegister_ELAS(void);
@@ -81,7 +81,7 @@ class ELASDataset : public GDALPamDataset
 {
     friend class ELASRasterBand;
 
-    FILE	*fp;
+    VSILFILE	*fp;
 
     ELASHeader  sHeader;
     int		bHeaderModified;
@@ -101,6 +101,7 @@ class ELASDataset : public GDALPamDataset
     virtual CPLErr SetGeoTransform( double * );
 
     static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
@@ -170,8 +171,8 @@ CPLErr ELASRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      created file, and that the file hasn't been extended yet.       */
 /*      Just read as zeros.                                             */
 /* -------------------------------------------------------------------- */
-    if( VSIFSeek( poGDS->fp, nOffset, SEEK_SET ) != 0 
-        || VSIFRead( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
+    if( VSIFSeekL( poGDS->fp, nOffset, SEEK_SET ) != 0
+        || VSIFReadL( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Seek or read of %d bytes at %ld failed.\n",
@@ -201,8 +202,8 @@ CPLErr ELASRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
     nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
     
-    if( VSIFSeek( poGDS->fp, nOffset, SEEK_SET ) != 0
-        || VSIFWrite( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
+    if( VSIFSeekL( poGDS->fp, nOffset, SEEK_SET ) != 0
+        || VSIFWriteL( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Seek or write of %d bytes at %ld failed.\n",
@@ -246,8 +247,11 @@ ELASDataset::~ELASDataset()
 {
     FlushCache();
 
-    VSIFClose( fp );
-    fp = NULL;
+    if( fp != NULL )
+    {
+        VSIFCloseL( fp );
+        fp = NULL;
+    }
 }
 
 /************************************************************************/
@@ -263,33 +267,45 @@ void ELASDataset::FlushCache()
 
     if( bHeaderModified )
     {
-        VSIFSeek( fp, 0, SEEK_SET );
-        VSIFWrite( &sHeader, 1024, 1, fp );
+        VSIFSeekL( fp, 0, SEEK_SET );
+        VSIFWriteL( &sHeader, 1024, 1, fp );
         bHeaderModified = FALSE;
     }
 }
 
-
 /************************************************************************/
-/*                                Open()                                */
+/*                              Identify()                               */
 /************************************************************************/
 
-GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
+int ELASDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/    
+/*  First we check to see if the file has the expected header           */
+/*  bytes.                                                               */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 256 )
-        return NULL;
+        return FALSE;
 
     if( CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+0))) != 1024
         || CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+28))) != 4321 )
     {
-        return NULL;
+        return FALSE;
     }
 
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if( !Identify(poOpenInfo) )
+        return NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
@@ -303,12 +319,13 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS = new ELASDataset();
 
-    poDS->fp = VSIFOpen( poOpenInfo->pszFilename, pszAccess );
+    poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, pszAccess );
     if( poDS->fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Attempt to open `%s' with acces `%s' failed.\n",
                   poOpenInfo->pszFilename, pszAccess );
+        delete poDS;
         return NULL;
     }
 
@@ -318,7 +335,7 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Read the header information.                                    */
 /* -------------------------------------------------------------------- */
     poDS->bHeaderModified = FALSE;
-    if( VSIFRead( &(poDS->sHeader), 1024, 1, poDS->fp ) != 1 )
+    if( VSIFReadL( &(poDS->sHeader), 1024, 1, poDS->fp ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Attempt to read 1024 byte header filed on file %s\n",
@@ -432,6 +449,11 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
@@ -653,8 +675,11 @@ void GDALRegister_ELAS()
                                    "ELAS" );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
                                    "Byte Float32 Float64" );
-        
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = ELASDataset::Open;
+        poDriver->pfnIdentify = ELASDataset::Identify;
         poDriver->pfnCreate = ELASDataset::Create;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
diff --git a/frmts/envisat/EnvisatFile.c b/frmts/envisat/EnvisatFile.c
index 492c325..125b355 100644
--- a/frmts/envisat/EnvisatFile.c
+++ b/frmts/envisat/EnvisatFile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: EnvisatFile.c 20600 2010-09-12 22:56:55Z rouault $
+ * $Id: EnvisatFile.c 22619 2011-06-29 20:54:01Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -32,7 +32,7 @@
 #  include "cpl_conv.h"
 #  include "EnvisatFile.h"
 
-CPL_CVSID("$Id: EnvisatFile.c 20600 2010-09-12 22:56:55Z rouault $");
+CPL_CVSID("$Id: EnvisatFile.c 22619 2011-06-29 20:54:01Z rouault $");
 
 #else
 #  include "APP/app.h"
@@ -1213,7 +1213,8 @@ int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
      * be 28 characters, I try to pad more than this incase the specification
      * is changed. 
      */
-    strcpy( padded_ds_name, ds_name );
+    strncpy( padded_ds_name, ds_name, sizeof(padded_ds_name) );
+    padded_ds_name[sizeof(padded_ds_name)-1] = 0;
     for( i = strlen(padded_ds_name); i < sizeof(padded_ds_name)-1; i++ )
     {
         padded_ds_name[i] = ' ';
diff --git a/frmts/envisat/GNUmakefile b/frmts/envisat/GNUmakefile
index ccc0555..839fce0 100644
--- a/frmts/envisat/GNUmakefile
+++ b/frmts/envisat/GNUmakefile
@@ -1,5 +1,5 @@
 
-OBJ	=	EnvisatFile.o envisatdataset.o
+OBJ	=	EnvisatFile.o records.o envisatdataset.o
 
 include ../../GDALmake.opt
 
diff --git a/frmts/envisat/envisatdataset.cpp b/frmts/envisat/envisatdataset.cpp
index a4a69a0..94fadcf 100644
--- a/frmts/envisat/envisatdataset.cpp
+++ b/frmts/envisat/envisatdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envisatdataset.cpp 22404 2011-05-19 15:16:06Z warmerdam $
+ * $Id: envisatdataset.cpp 22870 2011-08-06 19:07:45Z antonio $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Reader for ENVISAT format image data.
@@ -29,12 +29,13 @@
 
 #include "rawdataset.h"
 #include "cpl_string.h"
-#include "ogr_srs_api.h"					       
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: envisatdataset.cpp 22404 2011-05-19 15:16:06Z warmerdam $");
+CPL_CVSID("$Id: envisatdataset.cpp 22870 2011-08-06 19:07:45Z antonio $");
 
 CPL_C_START
 #include "EnvisatFile.h"
+#include "records.h"
 CPL_C_END
 
 CPL_C_START
@@ -43,6 +44,113 @@ CPL_C_END
 
 /************************************************************************/
 /* ==================================================================== */
+/*                        MerisL2FlagBand                         */
+/* ==================================================================== */
+/************************************************************************/
+class MerisL2FlagBand : public GDALPamRasterBand
+{
+  public:
+    MerisL2FlagBand( GDALDataset *, int, FILE*, off_t, off_t );
+    virtual ~MerisL2FlagBand();
+    virtual CPLErr IReadBlock( int, int, void * );
+
+  private:
+    off_t nImgOffset;
+    off_t nPrefixBytes;
+    size_t nBytePerPixel;
+    size_t nRecordSize;
+    size_t nDataSize;
+    GByte *pReadBuf;
+    FILE *fpImage;
+};
+
+/************************************************************************/
+/*                        MerisL2FlagBand()                       */
+/************************************************************************/
+MerisL2FlagBand::MerisL2FlagBand( GDALDataset *poDS, int nBand,
+                                  FILE* fpImage, off_t nImgOffset,
+                                  off_t nPrefixBytes )
+{
+    this->poDS = (GDALDataset *) poDS;
+    this->nBand = nBand;
+
+    this->fpImage = fpImage;
+    this->nImgOffset = nImgOffset;
+    this->nPrefixBytes = nPrefixBytes;
+
+    eDataType = GDT_UInt32;
+
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+    nBytePerPixel = 3;
+
+    nDataSize = nBlockXSize * nBytePerPixel;
+    nRecordSize = nPrefixBytes + nDataSize;
+
+    pReadBuf = (GByte *) CPLMalloc( nRecordSize );
+}
+
+
+/************************************************************************/
+/*                        ~MerisL2FlagBand()                       */
+/************************************************************************/
+MerisL2FlagBand::~MerisL2FlagBand()
+{
+    CPLFree( pReadBuf );
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+CPLErr MerisL2FlagBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                    void * pImage )
+{
+    CPLAssert( nBlockXOff == 0 );
+    CPLAssert( pReadBuf != NULL );
+
+    off_t nOffset = nImgOffset + nPrefixBytes +
+                    nBlockYOff * nBlockYSize * nRecordSize;
+
+    if ( VSIFSeek( fpImage, nOffset, SEEK_SET ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Seek to %d for scanline %d failed.\n",
+                  (int)nOffset, nBlockYOff );
+        return CE_Failure;
+    }
+
+    if ( VSIFRead( pReadBuf, 1, nDataSize, fpImage ) != nDataSize )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Read of %d bytes for scanline %d failed.\n",
+                  (int)nDataSize, nBlockYOff );
+        return CE_Failure;
+    }
+
+    unsigned iImg, iBuf;
+    for( iImg = 0, iBuf = 0;
+         iImg < nBlockXSize * sizeof(GDT_UInt32);
+         iImg += sizeof(GDT_UInt32), iBuf += nBytePerPixel )
+    {
+#ifdef CPL_LSB
+        ((GByte*) pImage)[iImg] = pReadBuf[iBuf + 2];
+        ((GByte*) pImage)[iImg + 1] = pReadBuf[iBuf + 1];
+        ((GByte*) pImage)[iImg + 2] = pReadBuf[iBuf];
+        ((GByte*) pImage)[iImg + 3] = 0;
+#else
+        ((GByte*) pImage)[iImg] = 0;
+        ((GByte*) pImage)[iImg + 1] = pReadBuf[iBuf];
+        ((GByte*) pImage)[iImg + 2] = pReadBuf[iBuf + 1];
+        ((GByte*) pImage)[iImg + 3] = pReadBuf[iBuf + 2];
+#endif
+    }
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/* ==================================================================== */
 /*				EnvisatDataset				*/
 /* ==================================================================== */
 /************************************************************************/
@@ -56,17 +164,18 @@ class EnvisatDataset : public RawDataset
     GDAL_GCP    *pasGCPList;
 
     char        **papszTempMD;
-    
+
     void        ScanForGCPs_ASAR();
     void        ScanForGCPs_MERIS();
 
     void	CollectMetadata( EnvisatFile_HeaderFlag );
     void        CollectDSDMetadata();
+    void        CollectADSMetadata();
 
   public:
     		EnvisatDataset();
     	        ~EnvisatDataset();
-    
+
     virtual int    GetGCPCount();
     virtual const char *GetGCPProjection();
     virtual const GDAL_GCP *GetGCPs();
@@ -164,13 +273,13 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 /* -------------------------------------------------------------------- */
 /*      Do we have a meaningful geolocation grid?                       */
 /* -------------------------------------------------------------------- */
-    nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile, 
+    nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
                                                  "GEOLOCATION GRID ADS" );
     if( nDatasetIndex == -1 )
         return;
 
-    if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex, 
-                                    NULL, NULL, NULL, NULL, NULL, 
+    if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex,
+                                    NULL, NULL, NULL, NULL, NULL,
                                     &nNumDSR, &nDSRSize ) != SUCCESS )
         return;
 
@@ -189,7 +298,7 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 
     for( iRecord = 0; iRecord < nNumDSR; iRecord++ )
     {
-        if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex, 
+        if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex,
                                            iRecord, abyRecord ) != SUCCESS )
             continue;
 
@@ -198,8 +307,8 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 
         if((iRecord>1) && (int(pasGCPList[nGCPCount-1].dfGCPLine+0.5) > nRange))
         {
-            int delta = pasGCPList[nGCPCount-1].dfGCPLine -
-                        pasGCPList[nGCPCount-12].dfGCPLine;
+            int delta = (int) (pasGCPList[nGCPCount-1].dfGCPLine -
+                               pasGCPList[nGCPCount-12].dfGCPLine);
             nRange = int(pasGCPList[nGCPCount-1].dfGCPLine+0.5) + delta;
             nRangeOffset = nRange-1;
         }
@@ -211,7 +320,7 @@ void EnvisatDataset::ScanForGCPs_ASAR()
             GDALInitGCPs( 1, pasGCPList + nGCPCount );
 
             CPLFree( pasGCPList[nGCPCount].pszId );
-            
+
             sprintf( szId, "%d", nGCPCount+1 );
             pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
 
@@ -228,7 +337,7 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 
             pasGCPList[nGCPCount].dfGCPLine = nRange - 0.5;
             pasGCPList[nGCPCount].dfGCPPixel = nSample - 0.5;
-            
+
             nGCPCount++;
         }
     }
@@ -246,7 +355,7 @@ void EnvisatDataset::ScanForGCPs_ASAR()
         GDALInitGCPs( 1, pasGCPList + nGCPCount );
 
         CPLFree( pasGCPList[nGCPCount].pszId );
-            
+
         sprintf( szId, "%d", nGCPCount+1 );
         pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
 
@@ -263,7 +372,7 @@ void EnvisatDataset::ScanForGCPs_ASAR()
 
         pasGCPList[nGCPCount].dfGCPLine = nRange - 0.5;
         pasGCPList[nGCPCount].dfGCPPixel = nSample - 0.5;
-            
+
         nGCPCount++;
     }
 }
@@ -282,13 +391,13 @@ void EnvisatDataset::ScanForGCPs_MERIS()
 /*      DS_TYPE=A and a name containing "geolocation" or "tie           */
 /*      points".                                                        */
 /* -------------------------------------------------------------------- */
-    nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile, 
+    nDatasetIndex = EnvisatFile_GetDatasetIndex( hEnvisatFile,
                                                  "Tie points ADS" );
     if( nDatasetIndex == -1 )
         return;
 
-    if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex, 
-                                    NULL, NULL, NULL, NULL, NULL, 
+    if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nDatasetIndex,
+                                    NULL, NULL, NULL, NULL, NULL,
                                     &nNumDSR, &nDSRSize ) != SUCCESS )
         return;
 
@@ -304,23 +413,23 @@ void EnvisatDataset::ScanForGCPs_MERIS()
     if( nNumDSR == 0 )
         return;
 
-    nLinesPerTiePoint = 
-        EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, 
+    nLinesPerTiePoint =
+        EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
                                       "LINES_PER_TIE_PT", 0 );
     nSamplesPerTiePoint =
-        EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH, 
+        EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
                                       "SAMPLES_PER_TIE_PT", 0 );
 
     if( nLinesPerTiePoint == 0 || nSamplesPerTiePoint == 0 )
         return;
 
-    nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1) 
+    nTPPerLine = (GetRasterXSize() + nSamplesPerTiePoint - 1)
         / nSamplesPerTiePoint;
 
-    if( (GetRasterYSize() + nLinesPerTiePoint - 1) 
+    if( (GetRasterYSize() + nLinesPerTiePoint - 1)
         / nLinesPerTiePoint != nTPPerColumn )
     {
-        CPLDebug( "EnvisatDataset", "Got %d instead of %d nTPPerColumn.", 
+        CPLDebug( "EnvisatDataset", "Got %d instead of %d nTPPerColumn.",
                   (GetRasterYSize()+nLinesPerTiePoint-1)/nLinesPerTiePoint,
                   nTPPerColumn );
         return;
@@ -328,8 +437,8 @@ void EnvisatDataset::ScanForGCPs_MERIS()
 
     if( 50*nTPPerLine + 13 != nDSRSize )
     {
-        CPLDebug( "EnvisatDataset", 
-                  "DSRSize=%d instead of expected %d for tiepoints ADS.", 
+        CPLDebug( "EnvisatDataset",
+                  "DSRSize=%d instead of expected %d for tiepoints ADS.",
                   nDSRSize, 50*nTPPerLine + 13 );
         return;
     }
@@ -342,12 +451,12 @@ void EnvisatDataset::ScanForGCPs_MERIS()
     GUInt32 	unValue;
 
     nGCPCount = 0;
-    pasGCPList = (GDAL_GCP *) 
+    pasGCPList = (GDAL_GCP *)
         CPLCalloc(sizeof(GDAL_GCP),nNumDSR * nTPPerLine);
 
     for( iRecord = 0; iRecord < nNumDSR; iRecord++ )
     {
-        if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex, 
+        if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDatasetIndex,
                                            iRecord, pabyRecord ) != SUCCESS )
             continue;
 
@@ -360,23 +469,23 @@ void EnvisatDataset::ScanForGCPs_MERIS()
             GDALInitGCPs( 1, pasGCPList + nGCPCount );
 
             CPLFree( pasGCPList[nGCPCount].pszId );
-            
+
             sprintf( szId, "%d", nGCPCount+1 );
             pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
 
             memcpy( &unValue, pabyRecord + 13 + nTPPerLine*4 + iGCP*4, 4 );
-            pasGCPList[nGCPCount].dfGCPX = 
+            pasGCPList[nGCPCount].dfGCPX =
                 ((int)CPL_MSBWORD32(unValue))*0.000001;
 
             memcpy( &unValue, pabyRecord + 13 + iGCP*4, 4 );
-            pasGCPList[nGCPCount].dfGCPY = 
+            pasGCPList[nGCPCount].dfGCPY =
                 ((int)CPL_MSBWORD32(unValue))*0.000001;
 
             pasGCPList[nGCPCount].dfGCPZ = 0.0;
 
             pasGCPList[nGCPCount].dfGCPLine = iRecord*nLinesPerTiePoint + 0.5;
             pasGCPList[nGCPCount].dfGCPPixel = iGCP*nSamplesPerTiePoint + 0.5;
-            
+
             nGCPCount++;
         }
     }
@@ -400,6 +509,7 @@ char **EnvisatDataset::GetMetadata( const char * pszDomain )
     int         i, nRecord = -1;
 
     strncpy( szDSName, pszDomain+11, sizeof(szDSName) );
+    szDSName[sizeof(szDSName)-1] = 0;
     for( i = 0; i < (int) sizeof(szDSName)-1; i++ )
     {
         if( szDSName[i] == '-' )
@@ -434,8 +544,8 @@ char **EnvisatDataset::GetMetadata( const char * pszDomain )
     char  *pszRecord;
 
     pszRecord = (char *) CPLMalloc(nDSRSize+1);
-    
-    if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDSIndex, nRecord, 
+
+    if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDSIndex, nRecord,
                                        pszRecord ) == FAILURE )
     {
         CPLFree( pszRecord );
@@ -450,7 +560,7 @@ char **EnvisatDataset::GetMetadata( const char * pszDomain )
 
     CSLDestroy( papszTempMD );
 
-    pszEscapedRecord = CPLEscapeString( pszRecord, nDSRSize, 
+    pszEscapedRecord = CPLEscapeString( pszRecord, nDSRSize,
                                         CPLES_BackslashQuotable );
     papszTempMD = CSLSetNameValue( NULL, "EscapedRecord", pszEscapedRecord );
     CPLFree( pszEscapedRecord );
@@ -479,24 +589,24 @@ void EnvisatDataset::CollectDSDMetadata()
     char	*pszDSName, *pszFilename;
     int		iDSD;
 
-    for( iDSD = 0; 
-         EnvisatFile_GetDatasetInfo( hEnvisatFile, iDSD, &pszDSName, NULL, 
+    for( iDSD = 0;
+         EnvisatFile_GetDatasetInfo( hEnvisatFile, iDSD, &pszDSName, NULL,
                              &pszFilename, NULL, NULL, NULL, NULL ) == SUCCESS;
          iDSD++ )
     {
-        if( pszFilename == NULL 
-            || strlen(pszFilename) == 0 
+        if( pszFilename == NULL
+            || strlen(pszFilename) == 0
             || EQUALN(pszFilename,"NOT USED",8)
             || EQUALN(pszFilename,"        ",8))
             continue;
 
         char	szKey[128], szTrimmedName[128];
         int	i;
-        
+
         strcpy( szKey, "DS_" );
         strcat( szKey, pszDSName );
 
-        // strip trailing spaces. 
+        // strip trailing spaces.
         for( i = strlen(szKey)-1; i && szKey[i] == ' '; i-- )
             szKey[i] = '\0';
 
@@ -518,6 +628,95 @@ void EnvisatDataset::CollectDSDMetadata()
 }
 
 /************************************************************************/
+/*                         CollectADSMetadata()                         */
+/*                                                                      */
+/*      Collect metadata from envisat ADS and GADS.                     */
+/************************************************************************/
+
+void EnvisatDataset::CollectADSMetadata()
+{
+    int nDSIndex, nNumDsr, nDSRSize;
+    int nRecord;
+    const char *pszDSName, *pszDSType, *pszDSFilename;
+    const char *pszProduct;
+    char *pszRecord;
+    char szPrefix[128], szKey[128], szValue[1024];
+    int i;
+    CPLErr ret;
+    const EnvisatRecordDescr *pRecordDescr = NULL;
+    const EnvisatFieldDescr *pField;
+
+    pszProduct = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH,
+                                                  "PRODUCT", "" );
+
+    for( nDSIndex = 0;
+         EnvisatFile_GetDatasetInfo( hEnvisatFile, nDSIndex,
+                                     (char **) &pszDSName,
+                                     (char **) &pszDSType,
+                                     (char **) &pszDSFilename,
+                                     NULL, NULL,
+                                     &nNumDsr, &nDSRSize ) == SUCCESS;
+         ++nDSIndex )
+    {
+        if( EQUALN(pszDSFilename,"NOT USED",8) || (nNumDsr <= 0) )
+            continue;
+        if( !EQUAL(pszDSType,"A") && !EQUAL(pszDSType,"G") )
+            continue;
+
+        for ( nRecord = 0; nRecord < nNumDsr; ++nRecord )
+        {
+            strncpy( szPrefix, pszDSName, sizeof(szPrefix) - 1);
+            szPrefix[sizeof(szPrefix) - 1] = '\0';
+
+            // strip trailing spaces
+            for( i = strlen(szPrefix)-1; i && szPrefix[i] == ' '; --i )
+                szPrefix[i] = '\0';
+
+            // convert spaces into underscores
+            for( i = 0; szPrefix[i] != '\0'; i++ )
+            {
+                if( szPrefix[i] == ' ' )
+                    szPrefix[i] = '_';
+            }
+
+            pszRecord = (char *) CPLMalloc(nDSRSize+1);
+
+            if( EnvisatFile_ReadDatasetRecord( hEnvisatFile, nDSIndex, nRecord,
+                                               pszRecord ) == FAILURE )
+            {
+                CPLFree( pszRecord );
+                return;
+            }
+
+            pRecordDescr = EnvisatFile_GetRecordDescriptor(pszProduct, pszDSName);
+            if (pRecordDescr)
+            {
+                pField = pRecordDescr->pFields;
+                while ( pField && pField->szName )
+                {
+                    ret = EnvisatFile_GetFieldAsString(pszRecord, nDSRSize,
+                                           pField, szValue);
+                    if ( ret == CE_None )
+                    {
+                        if (nNumDsr == 1)
+                            sprintf(szKey, "%s_%s", szPrefix, pField->szName);
+                        else
+                            // sprintf(szKey, "%s_%02d_%s", szPrefix, nRecord,
+                            sprintf(szKey, "%s_%d_%s", szPrefix, nRecord,
+                                    pField->szName);
+                        SetMetadataItem(szKey, szValue, "RECORDS");
+                    }
+                    // silently ignore conversion errors
+
+                    ++pField;
+                }
+            }
+            CPLFree( pszRecord );
+        }
+    }
+}
+
+/************************************************************************/
 /*                          CollectMetadata()                           */
 /*                                                                      */
 /*      Collect metadata from the SPH or MPH header fields.             */
@@ -527,7 +726,7 @@ void EnvisatDataset::CollectMetadata( EnvisatFile_HeaderFlag  eMPHOrSPH )
 
 {
     int		iKey;
-    
+
     for( iKey = 0; TRUE; iKey++ )
     {
         const char *pszValue, *pszKey;
@@ -568,7 +767,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
     EnvisatFile	*hEnvisatFile;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Check the header.                                               */
 /* -------------------------------------------------------------------- */
@@ -583,7 +782,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     int		ds_index;
 
-    if( EnvisatFile_Open( &hEnvisatFile, poOpenInfo->pszFilename, "r" ) 
+    if( EnvisatFile_Open( &hEnvisatFile, poOpenInfo->pszFilename, "r" )
         == FAILURE )
         return NULL;
 
@@ -596,12 +795,12 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 
     for( ds_index = 0; TRUE; ds_index++ )
     {
-        if( EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index, 
-                                        NULL, &pszDSType, NULL, 
-                                        &ds_offset, NULL, 
+        if( EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
+                                        NULL, &pszDSType, NULL,
+                                        &ds_offset, NULL,
                                         &num_dsr, &dsr_size ) == FAILURE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to find \"MDS1\" measurement datatset in Envisat file." );
             EnvisatFile_Close( hEnvisatFile );
             return NULL;
@@ -611,14 +810,14 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
         if( EQUAL(pszDSType,"M") )
             break;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
         EnvisatFile_Close( hEnvisatFile );
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The ENVISAT driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
@@ -639,8 +838,8 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
     GDALDataType eDataType;
     int          nPrefixBytes;
 
-    EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index, 
-                                NULL, NULL, NULL, &ds_offset, NULL, 
+    EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
+                                NULL, NULL, NULL, &ds_offset, NULL,
                                 &num_dsr, &dsr_size );
 
     poDS->nRasterXSize = EnvisatFile_GetKeyValueAsInt( hEnvisatFile, SPH,
@@ -650,9 +849,9 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 
     pszProduct = EnvisatFile_GetKeyValueAsString( hEnvisatFile, MPH,
                                                   "PRODUCT", "" );
-    pszDataType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH, 
+    pszDataType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH,
                                                    "DATA_TYPE", "" );
-    pszSampleType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH, 
+    pszSampleType = EnvisatFile_GetKeyValueAsString( hEnvisatFile, SPH,
                                                      "SAMPLE_TYPE", "" );
     if( EQUAL(pszDataType,"FLT32") && EQUALN(pszSampleType,"COMPLEX",7))
         eDataType = GDT_CFloat32;
@@ -686,13 +885,13 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
             eDataType = GDT_Byte;
     }
 
-#ifdef CPL_LSB 
+#ifdef CPL_LSB
     bNative = FALSE;
 #else
     bNative = TRUE;
 #endif
 
-    nPrefixBytes = dsr_size - 
+    nPrefixBytes = dsr_size -
         ((GDALGetDataTypeSize(eDataType) / 8) * poDS->nRasterXSize);
 
 /* -------------------------------------------------------------------- */
@@ -700,7 +899,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poDS->nRasterXSize < 1 || poDS->nRasterYSize < 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to determine organization of dataset.  It would\n"
                   "appear this is an Envisat dataset, but an unsupported\n"
                   "data product.  Unable to utilize." );
@@ -721,37 +920,129 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Scan for all datasets matching the reference dataset.           */
 /* -------------------------------------------------------------------- */
-    int	num_dsr2, dsr_size2, iBand = 0;
+    int num_dsr2, dsr_size2, iBand = 0;
     const char *pszDSName;
+    char szBandName[128];
+    bool bMiltiChannel;
 
-    for( ds_index = 0; 
-         EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index, 
-                                     (char **) &pszDSName, NULL, NULL, 
-                                     &ds_offset, NULL, 
+    for( ds_index = 0;
+         EnvisatFile_GetDatasetInfo( hEnvisatFile, ds_index,
+                                     (char **) &pszDSName, NULL, NULL,
+                                     &ds_offset, NULL,
                                      &num_dsr2, &dsr_size2 ) == SUCCESS;
          ds_index++ )
     {
-        if( EQUAL(pszDSType,"M") 
-            && num_dsr2 == num_dsr && dsr_size2 == dsr_size )
+        if( !EQUAL(pszDSType,"M") || num_dsr2 != num_dsr )
+            continue;
+
+        if( EQUALN(pszProduct,"MER",3) && (pszProduct[8] == '2') &&
+            ( (strstr(pszDSName, "MDS(16)") != NULL) ||
+              (strstr(pszDSName, "MDS(19)") != NULL)) )
+            bMiltiChannel = true;
+        else
+            bMiltiChannel = false;
+
+        if( (dsr_size2 == dsr_size) && !bMiltiChannel )
         {
             poDS->SetBand( iBand+1,
                        new RawRasterBand( poDS, iBand+1, poDS->fpImage,
                                           ds_offset + nPrefixBytes,
-                                          GDALGetDataTypeSize(eDataType) / 8, 
-                                          dsr_size, 
+                                          GDALGetDataTypeSize(eDataType) / 8,
+                                          dsr_size,
                                           eDataType, bNative ) );
             iBand++;
 
             poDS->GetRasterBand(iBand)->SetDescription( pszDSName );
         }
+/* -------------------------------------------------------------------- */
+/*       Handle MERIS Level 2 datasets with data type different from    */
+/*       the one declared in the SPH                                    */
+/* -------------------------------------------------------------------- */
+        else if( EQUALN(pszProduct,"MER",3) &&
+                 (strstr(pszDSName, "Flags") != NULL) )
+        {
+            if (pszProduct[8] == '1')
+            {
+                // Flags
+                poDS->SetBand( iBand+1,
+                           new RawRasterBand( poDS, iBand+1, poDS->fpImage,
+                                              ds_offset + nPrefixBytes, 3,
+                                              dsr_size, GDT_Byte, bNative ) );
+                iBand++;
+
+                poDS->GetRasterBand(iBand)->SetDescription( pszDSName );
+
+                // Detector indices
+                poDS->SetBand( iBand+1,
+                           new RawRasterBand( poDS, iBand+1, poDS->fpImage,
+                                              ds_offset + nPrefixBytes + 1,
+                                              3, dsr_size, GDT_Int16,
+                                              bNative ) );
+                iBand++;
+
+                const char *pszSuffix = strstr( pszDSName, "MDS" );
+                if ( pszSuffix != NULL)
+                    sprintf( szBandName, "Detector index %s", pszSuffix );
+                else
+                    sprintf( szBandName, "Detector index" );
+                poDS->GetRasterBand(iBand)->SetDescription( szBandName );
+            }
+            else if ( (pszProduct[8] == '2') &&
+                      (dsr_size2 >= 3 * poDS->nRasterXSize ) )
+            {
+                int nFlagPrefixBytes = dsr_size2 - 3 * poDS->nRasterXSize;
+
+                poDS->SetBand( iBand+1,
+                       new MerisL2FlagBand( poDS, iBand+1, poDS->fpImage,
+                                            ds_offset, nFlagPrefixBytes ) );
+                iBand++;
+
+                poDS->GetRasterBand(iBand)->SetDescription( pszDSName );
+            }
+        }
+        else if( EQUALN(pszProduct,"MER",3) && (pszProduct[8] == '2') )
+        {
+            int nPrefixBytes2, nSubBands, nSubBandIdx, nSubBandOffset;
+
+            int nPixelSize = 1;
+            GDALDataType eDataType2 = GDT_Byte;
+
+            nSubBands = dsr_size2 / poDS->nRasterXSize;
+            if( (nSubBands < 1) || (nSubBands > 3) )
+                nSubBands = 0;
+
+            nPrefixBytes2 = dsr_size2 -
+                (nSubBands * nPixelSize * poDS->nRasterXSize);
+
+            for (nSubBandIdx = 0; nSubBandIdx < nSubBands; ++nSubBandIdx)
+            {
+                nSubBandOffset =
+                    ds_offset + nPrefixBytes2 + nSubBandIdx * nPixelSize;
+                poDS->SetBand( iBand+1,
+                        new RawRasterBand( poDS, iBand+1, poDS->fpImage,
+                                           nSubBandOffset,
+                                           nPixelSize * nSubBands,
+                                           dsr_size2, eDataType2, bNative ) );
+                iBand++;
+
+                if (nSubBands > 1)
+                {
+                    sprintf( szBandName, "%s (%d)", pszDSName, nSubBandIdx );
+                    poDS->GetRasterBand(iBand)->SetDescription( szBandName );
+                }
+                else
+                    poDS->GetRasterBand(iBand)->SetDescription( pszDSName );
+            }
+        }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Collect metadata.                                               */
 /* -------------------------------------------------------------------- */
     poDS->CollectMetadata( MPH );
     poDS->CollectMetadata( SPH );
     poDS->CollectDSDMetadata();
+    poDS->CollectADSMetadata();
 
     if( EQUALN(pszProduct,"MER",3) )
         poDS->ScanForGCPs_MERIS();
@@ -784,11 +1075,11 @@ void GDALRegister_Envisat()
     if( GDALGetDriverByName( "ESAT" ) == NULL )
     {
         poDriver = new GDALDriver();
-        
+
         poDriver->SetDescription( "ESAT" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                    "Envisat Image Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                    "frmt_various.html#Envisat" );
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "n1" );
 
diff --git a/frmts/envisat/makefile.vc b/frmts/envisat/makefile.vc
index 843378b..75cc756 100644
--- a/frmts/envisat/makefile.vc
+++ b/frmts/envisat/makefile.vc
@@ -1,5 +1,5 @@
 
-OBJ	=	envisatdataset.obj EnvisatFile.obj
+OBJ	=	envisatdataset.obj EnvisatFile.obj records.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/envisat/records.c b/frmts/envisat/records.c
new file mode 100644
index 0000000..9e19d27
--- /dev/null
+++ b/frmts/envisat/records.c
@@ -0,0 +1,1409 @@
+/******************************************************************************
+ * $Id: records.c 22499 2011-06-04 14:45:17Z rouault $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  Low Level Envisat file access (read/write) API.
+ * Author:   Antonio Valentino <antonio.valentino at tiscali.it>
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Antonio Valentino
+ *
+ * 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 "records.h"
+
+CPL_CVSID("$Id: records.c 22499 2011-06-04 14:45:17Z rouault $");
+
+/* --- ASAR record descriptors --------------------------------------------- */
+static const EnvisatFieldDescr ASAR_ANTENNA_ELEV_PATT_ADSR[] = {
+    {"ZERO_DOPPLER_TIME",                                  0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"BEAM_ID",                                           13, EDT_Char,        3},
+    {"ELEVATION_PATTERN.SLANT_RANGE_TIME",                16, EDT_Float32,    11},
+    {"ELEVATION_PATTERN.ELEVATION_ANGLES",                60, EDT_Float32,    11},
+    {"ELEVATION_PATTERN.ANTENNA_PATTERN",                104, EDT_Float32,    11},
+    /*{"SPARE_1",                                        148, EDT_UByte,      14},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_CHIRP_PARAMS_ADSR[] = {
+    {"ZERO_DOPPLER_TIME",                                  0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"BEAM_ID",                                           13, EDT_Char,        3},
+    {"POLAR",                                             16, EDT_Char,        3},
+    {"CHIRP_WIDTH",                                       19, EDT_Float32,     1},
+    {"CHIRP_SIDELOBE",                                    23, EDT_Float32,     1},
+    {"CHIRP_ISLR",                                        27, EDT_Float32,     1},
+    {"CHIRP_PEAK_LOC",                                    31, EDT_Float32,     1},
+    {"CHIRP_POWER",                                       35, EDT_Float32,     1},
+    {"ELEV_CORR_FACTOR",                                  39, EDT_Float32,     1},
+    /*{"SPARE_1",                                         43, EDT_UByte,      16},*/
+    {"CAL_PULSE_INFO.1.MAX_CAL",                          59, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.1.AVG_CAL",                          71, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.1.AVG_VAL_1A",                       83, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.1.PHS_CAL",                          87, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.2.MAX_CAL",                         103, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.2.AVG_CAL",                         115, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.2.AVG_VAL_1A",                      127, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.2.PHS_CAL",                         131, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.3.MAX_CAL",                         147, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.3.AVG_CAL",                         159, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.3.AVG_VAL_1A",                      171, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.3.PHS_CAL",                         175, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.4.MAX_CAL",                         191, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.4.AVG_CAL",                         203, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.4.AVG_VAL_1A",                      215, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.4.PHS_CAL",                         219, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.5.MAX_CAL",                         235, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.5.AVG_CAL",                         247, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.5.AVG_VAL_1A",                      259, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.5.PHS_CAL",                         263, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.6.MAX_CAL",                         279, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.6.AVG_CAL",                         291, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.6.AVG_VAL_1A",                      303, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.6.PHS_CAL",                         307, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.7.MAX_CAL",                         323, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.7.AVG_CAL",                         335, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.7.AVG_VAL_1A",                      347, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.7.PHS_CAL",                         351, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.8.MAX_CAL",                         367, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.8.AVG_CAL",                         379, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.8.AVG_VAL_1A",                      391, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.8.PHS_CAL",                         395, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.9.MAX_CAL",                         411, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.9.AVG_CAL",                         423, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.9.AVG_VAL_1A",                      435, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.9.PHS_CAL",                         439, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.10.MAX_CAL",                        455, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.10.AVG_CAL",                        467, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.10.AVG_VAL_1A",                     479, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.10.PHS_CAL",                        483, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.11.MAX_CAL",                        499, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.11.AVG_CAL",                        511, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.11.AVG_VAL_1A",                     523, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.11.PHS_CAL",                        527, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.12.MAX_CAL",                        543, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.12.AVG_CAL",                        555, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.12.AVG_VAL_1A",                     567, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.12.PHS_CAL",                        571, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.13.MAX_CAL",                        587, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.13.AVG_CAL",                        599, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.13.AVG_VAL_1A",                     611, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.13.PHS_CAL",                        615, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.14.MAX_CAL",                        631, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.14.AVG_CAL",                        643, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.14.AVG_VAL_1A",                     655, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.14.PHS_CAL",                        659, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.15.MAX_CAL",                        675, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.15.AVG_CAL",                        687, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.15.AVG_VAL_1A",                     699, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.15.PHS_CAL",                        703, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.16.MAX_CAL",                        719, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.16.AVG_CAL",                        731, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.16.AVG_VAL_1A",                     743, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.16.PHS_CAL",                        747, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.17.MAX_CAL",                        763, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.17.AVG_CAL",                        775, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.17.AVG_VAL_1A",                     787, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.17.PHS_CAL",                        791, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.18.MAX_CAL",                        807, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.18.AVG_CAL",                        819, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.18.AVG_VAL_1A",                     831, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.18.PHS_CAL",                        835, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.19.MAX_CAL",                        851, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.19.AVG_CAL",                        863, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.19.AVG_VAL_1A",                     875, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.19.PHS_CAL",                        879, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.20.MAX_CAL",                        895, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.20.AVG_CAL",                        907, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.20.AVG_VAL_1A",                     919, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.20.PHS_CAL",                        923, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.21.MAX_CAL",                        939, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.21.AVG_CAL",                        951, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.21.AVG_VAL_1A",                     963, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.21.PHS_CAL",                        967, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.22.MAX_CAL",                        983, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.22.AVG_CAL",                        995, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.22.AVG_VAL_1A",                    1007, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.22.PHS_CAL",                       1011, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.23.MAX_CAL",                       1027, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.23.AVG_CAL",                       1039, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.23.AVG_VAL_1A",                    1051, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.23.PHS_CAL",                       1055, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.24.MAX_CAL",                       1071, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.24.AVG_CAL",                       1083, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.24.AVG_VAL_1A",                    1095, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.24.PHS_CAL",                       1099, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.25.MAX_CAL",                       1115, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.25.AVG_CAL",                       1127, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.25.AVG_VAL_1A",                    1139, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.25.PHS_CAL",                       1143, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.26.MAX_CAL",                       1159, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.26.AVG_CAL",                       1171, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.26.AVG_VAL_1A",                    1183, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.26.PHS_CAL",                       1187, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.27.MAX_CAL",                       1203, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.27.AVG_CAL",                       1215, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.27.AVG_VAL_1A",                    1227, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.27.PHS_CAL",                       1231, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.28.MAX_CAL",                       1247, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.28.AVG_CAL",                       1259, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.28.AVG_VAL_1A",                    1271, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.28.PHS_CAL",                       1275, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.29.MAX_CAL",                       1291, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.29.AVG_CAL",                       1303, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.29.AVG_VAL_1A",                    1315, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.29.PHS_CAL",                       1319, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.30.MAX_CAL",                       1335, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.30.AVG_CAL",                       1347, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.30.AVG_VAL_1A",                    1359, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.30.PHS_CAL",                       1363, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.31.MAX_CAL",                       1379, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.31.AVG_CAL",                       1391, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.31.AVG_VAL_1A",                    1403, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.31.PHS_CAL",                       1407, EDT_Float32,     4},
+    {"CAL_PULSE_INFO.32.MAX_CAL",                       1423, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.32.AVG_CAL",                       1435, EDT_Float32,     3},
+    {"CAL_PULSE_INFO.32.AVG_VAL_1A",                    1447, EDT_Float32,     1},
+    {"CAL_PULSE_INFO.32.PHS_CAL",                       1451, EDT_Float32,     4},
+    /*{"SPARE_2",                                       1467, EDT_UByte,      16},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_DOP_CENTROID_COEFFS_ADSR[] = {
+    {"ZERO_DOPPLER_TIME",                                  0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"SLANT_RANGE_TIME",                                  13, EDT_Float32,     1},
+    {"DOP_COEF",                                          17, EDT_Float32,     5},
+    {"DOP_CONF",                                          37, EDT_Float32,     1},
+    {"DOP_CONF_BELOW_THRESH_FLAG",                        41, EDT_UByte,       1},
+    {"DELTA_DOPP_COEFF",                                  42, EDT_Int16,       5},
+    /*{"SPARE_1",                                         52, EDT_UByte,       3},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_GEOLOCATION_GRID_ADSR[] = {
+    {"FIRST_ZERO_DOPPLER_TIME",                            0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"LINE_NUM",                                          13, EDT_UInt32,      1},
+    {"NUM_LINES",                                         17, EDT_UInt32,      1},
+    {"SUB_SAT_TRACK",                                     21, EDT_Float32,     1},
+    {"FIRST_LINE_TIE_POINTS.SAMP_NUMBERS",                25, EDT_UInt32,     11},
+    {"FIRST_LINE_TIE_POINTS.SLANT_RANGE_TIMES",           69, EDT_Float32,    11},
+    {"FIRST_LINE_TIE_POINTS.ANGLES",                     113, EDT_Float32,    11},
+    {"FIRST_LINE_TIE_POINTS.LATS",                       157, EDT_Int32,      11},
+    {"FIRST_LINE_TIE_POINTS.LONGS",                      201, EDT_Int32,      11},
+    /*{"SPARE_1",                                        245, EDT_UByte,      22},*/
+    {"LAST_ZERO_DOPPLER_TIME",                           267, EDT_MJD,         1},
+    {"LAST_LINE_TIE_POINTS.SAMP_NUMBERS",                279, EDT_UInt32,     11},
+    {"LAST_LINE_TIE_POINTS.SLANT_RANGE_TIMES",           323, EDT_Float32,    11},
+    {"LAST_LINE_TIE_POINTS.ANGLES",                      367, EDT_Float32,    11},
+    {"LAST_LINE_TIE_POINTS.LATS",                        411, EDT_Int32,      11},
+    {"LAST_LINE_TIE_POINTS.LONGS",                       455, EDT_Int32,      11},
+    /*{"SPARE_2",                                        499, EDT_UByte,      22},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_MAIN_PROCESSING_PARAMS_ADSR[] = {
+    {"FIRST_ZERO_DOPPLER_TIME",                            0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"LAST_ZERO_DOPPLER_TIME",                            13, EDT_MJD,         1},
+    {"WORK_ORDER_ID",                                     25, EDT_Char,       12},
+    {"TIME_DIFF",                                         37, EDT_Float32,     1},
+    {"SWATH_ID",                                          41, EDT_Char,        3},
+    {"RANGE_SPACING",                                     44, EDT_Float32,     1},
+    {"AZIMUTH_SPACING",                                   48, EDT_Float32,     1},
+    {"LINE_TIME_INTERVAL",                                52, EDT_Float32,     1},
+    {"NUM_OUTPUT_LINES",                                  56, EDT_UInt32,      1},
+    {"NUM_SAMPLES_PER_LINE",                              60, EDT_UInt32,      1},
+    {"DATA_TYPE",                                         64, EDT_Char,        5},
+    /*{"SPARE_1",                                         69, EDT_UByte,      51},*/
+    {"DATA_ANALYSIS_FLAG",                               120, EDT_UByte,       1},
+    {"ANT_ELEV_CORR_FLAG",                               121, EDT_UByte,       1},
+    {"CHIRP_EXTRACT_FLAG",                               122, EDT_UByte,       1},
+    {"SRGR_FLAG",                                        123, EDT_UByte,       1},
+    {"DOP_CEN_FLAG",                                     124, EDT_UByte,       1},
+    {"DOP_AMB_FLAG",                                     125, EDT_UByte,       1},
+    {"RANGE_SPREAD_COMP_FLAG",                           126, EDT_UByte,       1},
+    {"DETECTED_FLAG",                                    127, EDT_UByte,       1},
+    {"LOOK_SUM_FLAG",                                    128, EDT_UByte,       1},
+    {"RMS_EQUAL_FLAG",                                   129, EDT_UByte,       1},
+    {"ANT_SCAL_FLAG",                                    130, EDT_UByte,       1},
+    {"VGA_COM_ECHO_FLAG",                                131, EDT_UByte,       1},
+    {"VGA_COM_PULSE_2_FLAG",                             132, EDT_UByte,       1},
+    {"VGA_COM_PULSE_ZERO_FLAG",                          133, EDT_UByte,       1},
+    {"INV_FILT_COMP_FLAG",                               134, EDT_UByte,       1},
+    /*{"SPARE_2",                                        135, EDT_UByte,       6},*/
+    {"RAW_DATA_ANALYSIS.1.NUM_GAPS",                     141, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.NUM_MISSING_LINES",            145, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.RANGE_SAMP_SKIP",              149, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.RANGE_LINES_SKIP",             153, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.CALC_I_BIAS",                  157, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_Q_BIAS",                  161, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_I_STD_DEV",               165, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_Q_STD_DEV",               169, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_GAIN",                    173, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_QUAD",                    177, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.I_BIAS_MAX",                   181, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.I_BIAS_MIN",                   185, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.Q_BIAS_MAX",                   189, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.Q_BIAS_MIN",                   193, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.GAIN_MIN",                     197, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.GAIN_MAX",                     201, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.QUAD_MIN",                     205, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.QUAD_MAX",                     209, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.I_BIAS_FLAG",                  213, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.Q_BIAS_FLAG",                  214, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.GAIN_FLAG",                    215, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.QUAD_FLAG",                    216, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.USED_I_BIAS",                  217, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.USED_Q_BIAS",                  221, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.USED_GAIN",                    225, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.USED_QUAD",                    229, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.NUM_GAPS",                     233, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.NUM_MISSING_LINES",            237, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.RANGE_SAMP_SKIP",              241, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.RANGE_LINES_SKIP",             245, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.CALC_I_BIAS",                  249, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_Q_BIAS",                  253, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_I_STD_DEV",               257, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_Q_STD_DEV",               261, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_GAIN",                    265, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_QUAD",                    269, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.I_BIAS_MAX",                   273, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.I_BIAS_MIN",                   277, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.Q_BIAS_MAX",                   281, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.Q_BIAS_MIN",                   285, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.GAIN_MIN",                     289, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.GAIN_MAX",                     293, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.QUAD_MIN",                     297, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.QUAD_MAX",                     301, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.I_BIAS_FLAG",                  305, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.Q_BIAS_FLAG",                  306, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.GAIN_FLAG",                    307, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.QUAD_FLAG",                    308, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.USED_I_BIAS",                  309, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.USED_Q_BIAS",                  313, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.USED_GAIN",                    317, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.USED_QUAD",                    321, EDT_Float32,     1},
+    /*{"SPARE_3",                                        325, EDT_UByte,      32},*/
+    {"START_TIME.1.FIRST_OBT",                           357, EDT_UInt32,      2},
+    {"START_TIME.1.FIRST_MJD",                           365, EDT_MJD,         1},
+    {"START_TIME.2.FIRST_OBT",                           377, EDT_UInt32,      2},
+    {"START_TIME.2.FIRST_MJD",                           385, EDT_MJD,         1},
+    {"PARAMETER_CODES.FIRST_SWST_CODE",                  397, EDT_UInt16,      5},
+    {"PARAMETER_CODES.LAST_SWST_CODE",                   407, EDT_UInt16,      5},
+    {"PARAMETER_CODES.PRI_CODE",                         417, EDT_UInt16,      5},
+    {"PARAMETER_CODES.TX_PULSE_LEN_CODE",                427, EDT_UInt16,      5},
+    {"PARAMETER_CODES.TX_BW_CODE",                       437, EDT_UInt16,      5},
+    {"PARAMETER_CODES.ECHO_WIN_LEN_CODE",                447, EDT_UInt16,      5},
+    {"PARAMETER_CODES.UP_CODE",                          457, EDT_UInt16,      5},
+    {"PARAMETER_CODES.DOWN_CODE",                        467, EDT_UInt16,      5},
+    {"PARAMETER_CODES.RESAMP_CODE",                      477, EDT_UInt16,      5},
+    {"PARAMETER_CODES.BEAM_ADJ_CODE",                    487, EDT_UInt16,      5},
+    {"PARAMETER_CODES.BEAM_SET_NUM_CODE",                497, EDT_UInt16,      5},
+    {"PARAMETER_CODES.TX_MONITOR_CODE",                  507, EDT_UInt16,      5},
+    /*{"SPARE_4",                                        517, EDT_UByte,      60},*/
+    {"ERROR_COUNTERS.NUM_ERR_SWST",                      577, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_PRI",                       581, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_TX_PULSE_LEN",              585, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_TX_PULSE_BW",               589, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_ECHO_WIN_LEN",              593, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_UP",                        597, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_DOWN",                      601, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_RESAMP",                    605, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_BEAM_ADJ",                  609, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_BEAM_SET_NUM",              613, EDT_UInt32,      1},
+    /*{"SPARE_5",                                        617, EDT_UByte,      26},*/
+    {"IMAGE_PARAMETERS.FIRST_SWST_VALUE",                643, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.LAST_SWST_VALUE",                 663, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.SWST_CHANGES",                    683, EDT_UInt32,      5},
+    {"IMAGE_PARAMETERS.PRF_VALUE",                       703, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.TX_PULSE_LEN_VALUE",              723, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.TX_PULSE_BW_VALUE",               743, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.ECHO_WIN_LEN_VALUE",              763, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.UP_VALUE",                        783, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.DOWN_VALUE",                      803, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.RESAMP_VALUE",                    823, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.BEAM_ADJ_VALUE",                  843, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.BEAM_SET_VALUE",                  863, EDT_UInt16,      5},
+    {"IMAGE_PARAMETERS.TX_MONITOR_VALUE",                873, EDT_Float32,     5},
+    /*{"SPARE_6",                                        893, EDT_UByte,      82},*/
+    {"FIRST_PROC_RANGE_SAMP",                            975, EDT_UInt32,      1},
+    {"RANGE_REF",                                        979, EDT_Float32,     1},
+    {"RANGE_SAMP_RATE",                                  983, EDT_Float32,     1},
+    {"RADAR_FREQ",                                       987, EDT_Float32,     1},
+    {"NUM_LOOKS_RANGE",                                  991, EDT_UInt16,      1},
+    {"FILTER_WINDOW",                                    993, EDT_Char,        7},
+    {"WINDOW_COEF_RANGE",                               1000, EDT_Float32,     1},
+    {"BANDWIDTH.LOOK_BW_RANGE",                         1004, EDT_Float32,     5},
+    {"BANDWIDTH.TOT_BW_RANGE",                          1024, EDT_Float32,     5},
+    {"NOMINAL_CHIRP.1.NOM_CHIRP_AMP",                   1044, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.1.NOM_CHIRP_PHS",                   1060, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.2.NOM_CHIRP_AMP",                   1076, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.2.NOM_CHIRP_PHS",                   1092, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.3.NOM_CHIRP_AMP",                   1108, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.3.NOM_CHIRP_PHS",                   1124, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.4.NOM_CHIRP_AMP",                   1140, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.4.NOM_CHIRP_PHS",                   1156, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.5.NOM_CHIRP_AMP",                   1172, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.5.NOM_CHIRP_PHS",                   1188, EDT_Float32,     4},
+    /*{"SPARE_7",                                       1204, EDT_UByte,      60},*/
+    {"NUM_LINES_PROC",                                  1264, EDT_UInt32,      1},
+    {"NUM_LOOK_AZ",                                     1268, EDT_UInt16,      1},
+    {"LOOK_BW_AZ",                                      1270, EDT_Float32,     1},
+    {"TO_BW_AZ",                                        1274, EDT_Float32,     1},
+    {"FILTER_AZ",                                       1278, EDT_Char,        7},
+    {"FILTER_COEF_AZ",                                  1285, EDT_Float32,     1},
+    {"AZ_FM_RATE",                                      1289, EDT_Float32,     3},
+    {"AX_FM_ORIGIN",                                    1301, EDT_Float32,     1},
+    {"DOP_AMB_CONF",                                    1305, EDT_Float32,     1},
+    /*{"SPARE_8",                                       1309, EDT_UByte,      68},*/
+    {"CALIBRATION_FACTORS.1.PROC_SCALING_FACT",         1377, EDT_Float32,     1},
+    {"CALIBRATION_FACTORS.1.EXT_CAL_FACT",              1381, EDT_Float32,     1},
+    {"CALIBRATION_FACTORS.2.PROC_SCALING_FACT",         1385, EDT_Float32,     1},
+    {"CALIBRATION_FACTORS.2.EXT_CAL_FACT",              1389, EDT_Float32,     1},
+    {"NOISE_ESTIMATION.NOISE_POWER_CORR",               1393, EDT_Float32,     5},
+    {"NOISE_ESTIMATION.NUM_NOISE_LINES",                1413, EDT_UInt32,      5},
+    /*{"SPARE_9",                                       1433, EDT_UByte,      76},*/
+    {"OUTPUT_STATISTICS.1.OUT_MEAN",                    1509, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.1.OUT_IMAG_MEAN",               1513, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.1.OUT_STD_DEV",                 1517, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.1.OUT_IMAG_STD_DEV",            1521, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_MEAN",                    1525, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_IMAG_MEAN",               1529, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_STD_DEV",                 1533, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_IMAG_STD_DEV",            1537, EDT_Float32,     1},
+    /*{"SPARE_10",                                      1541, EDT_UByte,      52},*/
+    {"ECHO_COMP",                                       1593, EDT_Char,        4},
+    {"ECHO_COMP_RATIO",                                 1597, EDT_Char,        3},
+    {"INIT_CAL_COMP",                                   1600, EDT_Char,        4},
+    {"INIT_CAL_RATIO",                                  1604, EDT_Char,        3},
+    {"PER_CAL_COMP",                                    1607, EDT_Char,        4},
+    {"PER_CAL_RATIO",                                   1611, EDT_Char,        3},
+    {"NOISE_COMP",                                      1614, EDT_Char,        4},
+    {"NOISE_COMP_RATIO",                                1618, EDT_Char,        3},
+    /*{"SPARE_11",                                      1621, EDT_UByte,      64},*/
+    {"BEAM_MERGE_SL_RANGE",                             1685, EDT_UInt32,      4},
+    {"BEAM_MERGE_ALG_PARAM",                            1701, EDT_Float32,     4},
+    {"LINES_PER_BURST",                                 1717, EDT_UInt32,      5},
+    /*{"SPARE_12",                                      1737, EDT_UByte,      28},*/
+    {"ORBIT_STATE_VECTORS.1.STATE_VECT_TIME_1",         1765, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.1.X_POS_1",                   1777, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Y_POS_1",                   1781, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Z_POS_1",                   1785, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.X_VEL_1",                   1789, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Y_VEL_1",                   1793, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Z_VEL_1",                   1797, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.STATE_VECT_TIME_1",         1801, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.2.X_POS_1",                   1813, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Y_POS_1",                   1817, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Z_POS_1",                   1821, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.X_VEL_1",                   1825, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Y_VEL_1",                   1829, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Z_VEL_1",                   1833, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.STATE_VECT_TIME_1",         1837, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.3.X_POS_1",                   1849, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Y_POS_1",                   1853, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Z_POS_1",                   1857, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.X_VEL_1",                   1861, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Y_VEL_1",                   1865, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Z_VEL_1",                   1869, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.STATE_VECT_TIME_1",         1873, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.4.X_POS_1",                   1885, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Y_POS_1",                   1889, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Z_POS_1",                   1893, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.X_VEL_1",                   1897, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Y_VEL_1",                   1901, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Z_VEL_1",                   1905, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.STATE_VECT_TIME_1",         1909, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.5.X_POS_1",                   1921, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Y_POS_1",                   1925, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Z_POS_1",                   1929, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.X_VEL_1",                   1933, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Y_VEL_1",                   1937, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Z_VEL_1",                   1941, EDT_Int32,       1},
+    /*{"SPARE_13",                                      1945, EDT_UByte,      64},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_MAP_PROJECTION_GADS[] = {
+    {"MAP_DESCRIPTOR",                                     0, EDT_Char,       32},
+    {"SAMPLES",                                           32, EDT_UInt32,      1},
+    {"LINES",                                             36, EDT_UInt32,      1},
+    {"SAMPLE_SPACING",                                    40, EDT_Float32,     1},
+    {"LINE_SPACING",                                      44, EDT_Float32,     1},
+    {"ORIENTATION",                                       48, EDT_Float32,     1},
+    /*{"SPARE_1",                                         52, EDT_UByte,      40},*/
+    {"HEADING",                                           92, EDT_Float32,     1},
+    {"ELLIPSOID_NAME",                                    96, EDT_Char,       32},
+    {"SEMI_MAJOR",                                       128, EDT_Float32,     1},
+    {"SEMI_MINOR",                                       132, EDT_Float32,     1},
+    {"SHIFT_DX",                                         136, EDT_Float32,     1},
+    {"SHIFT_DY",                                         140, EDT_Float32,     1},
+    {"SHIFT_DZ",                                         144, EDT_Float32,     1},
+    {"AVG_HEIGHT",                                       148, EDT_Float32,     1},
+    /*{"SPARE_2",                                        152, EDT_UByte,      12},*/
+    {"PROJECTION_DESCRIPTION",                           164, EDT_Char,       32},
+    {"UTM_DESCRIPTOR",                                   196, EDT_Char,       32},
+    {"UTM_ZONE",                                         228, EDT_Char,        4},
+    {"UTM_ORIGIN_EASTING",                               232, EDT_Float32,     1},
+    {"UTM_ORIGIN_NORTHING",                              236, EDT_Float32,     1},
+    {"UTM_CENTER_LONG",                                  240, EDT_Int32,       1},
+    {"UTM_CENTER_LAT",                                   244, EDT_Int32,       1},
+    {"UTM_PARA1",                                        248, EDT_Float32,     1},
+    {"UTM_PARA2",                                        252, EDT_Float32,     1},
+    {"UTM_SCALE",                                        256, EDT_Float32,     1},
+    {"UPS_DESCRIPTOR",                                   260, EDT_Char,       32},
+    {"UPS_CENTER_LONG",                                  292, EDT_Int32,       1},
+    {"UPS_CENTER_LAT",                                   296, EDT_Int32,       1},
+    {"UPS_SCALE",                                        300, EDT_Float32,     1},
+    {"NSP_DESCRIPTOR",                                   304, EDT_Char,       32},
+    {"ORIGIN_EASTING",                                   336, EDT_Float32,     1},
+    {"ORIGIN_NORTHING",                                  340, EDT_Float32,     1},
+    {"CENTER_LONG",                                      344, EDT_Int32,       1},
+    {"CENTER_LAT",                                       348, EDT_Int32,       1},
+    {"STANDARD_PARALLEL_PARAMETERS.PARA1",               352, EDT_Float32,     1},
+    {"STANDARD_PARALLEL_PARAMETERS.PARA2",               356, EDT_Float32,     1},
+    {"STANDARD_PARALLEL_PARAMETERS.PARA3",               360, EDT_Float32,     1},
+    {"STANDARD_PARALLEL_PARAMETERS.PARA4",               364, EDT_Float32,     1},
+    {"CENTRAL_MERIDIAN_PARAMETERS.CENTRAL_M1",           368, EDT_Float32,     1},
+    {"CENTRAL_MERIDIAN_PARAMETERS.CENTRAL_M2",           372, EDT_Float32,     1},
+    {"CENTRAL_MERIDIAN_PARAMETERS.CENTRAL_M3",           376, EDT_Float32,     1},
+    /*{"PROJECTION_PARAMETERS.SPARE_3",                  380, EDT_UByte,      16},*/
+    {"POSITION_NORTHINGS_EASTINGS.TL_NORTHING",          396, EDT_Float32,     1},
+    {"POSITION_NORTHINGS_EASTINGS.TL_EASTING",           400, EDT_Float32,     1},
+    {"POSITION_NORTHINGS_EASTINGS.TR_NORTHING",          404, EDT_Float32,     1},
+    {"POSITION_NORTHINGS_EASTINGS.TR_EASTING",           408, EDT_Float32,     1},
+    {"POSITION_NORTHINGS_EASTINGS.BR_NORTHING",          412, EDT_Float32,     1},
+    {"POSITION_NORTHINGS_EASTINGS.BR_EASTING",           416, EDT_Float32,     1},
+    {"POSITION_NORTHINGS_EASTINGS.BL_NORTHING",          420, EDT_Float32,     1},
+    {"POSITION_NORTHINGS_EASTINGS.BL_EASTING",           424, EDT_Float32,     1},
+    {"POSITION_LAT_LONG.TL_LAT",                         428, EDT_Int32,       1},
+    {"POSITION_LAT_LONG.TL_LONG",                        432, EDT_Int32,       1},
+    {"POSITION_LAT_LONG.TR_LAT",                         436, EDT_Int32,       1},
+    {"POSITION_LAT_LONG.TR_LONG",                        440, EDT_Int32,       1},
+    {"POSITION_LAT_LONG.BR_LAT",                         444, EDT_Int32,       1},
+    {"POSITION_LAT_LONG.BR_LONG",                        448, EDT_Int32,       1},
+    {"POSITION_LAT_LONG.BL_LAT",                         452, EDT_Int32,       1},
+    {"POSITION_LAT_LONG.BL_LONG",                        456, EDT_Int32,       1},
+    /*{"SPARE_4",                                        460, EDT_UByte,      32},*/
+    {"IMAGE_TO_MAP_COEFS",                               492, EDT_Float32,     8},
+    {"MAP_TO_IMAGE_COEFS",                               524, EDT_Float32,     8},
+    /*{"SPARE_5",                                        556, EDT_UByte,      35},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_SQ_ADSR[] = {
+    {"ZERO_DOPPLER_TIME",                                  0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"INPUT_MEAN_FLAG",                                   13, EDT_UByte,       1},
+    {"INPUT_STD_DEV_FLAG",                                14, EDT_UByte,       1},
+    {"INPUT_GAPS_FLAG",                                   15, EDT_UByte,       1},
+    {"INPUT_MISSING_LINES_FLAG",                          16, EDT_UByte,       1},
+    {"DOP_CEN_FLAG",                                      17, EDT_UByte,       1},
+    {"DOP_AMB_FLAG",                                      18, EDT_UByte,       1},
+    {"OUTPUT_MEAN_FLAG",                                  19, EDT_UByte,       1},
+    {"OUTPUT_STD_DEV_FLAG",                               20, EDT_UByte,       1},
+    {"CHIRP_FLAG",                                        21, EDT_UByte,       1},
+    {"MISSING_DATA_SETS_FLAG",                            22, EDT_UByte,       1},
+    {"INVALID_DOWNLINK_FLAG",                             23, EDT_UByte,       1},
+    /*{"SPARE_1",                                         24, EDT_UByte,       7},*/
+    {"THRESH_CHIRP_BROADENING",                           31, EDT_Float32,     1},
+    {"THRESH_CHIRP_SIDELOBE",                             35, EDT_Float32,     1},
+    {"THRESH_CHIRP_ISLR",                                 39, EDT_Float32,     1},
+    {"THRESH_INPUT_MEAN",                                 43, EDT_Float32,     1},
+    {"EXP_INPUT_MEAN",                                    47, EDT_Float32,     1},
+    {"THRESH_INPUT_STD_DEV",                              51, EDT_Float32,     1},
+    {"EXP_INPUT_STD_DEV",                                 55, EDT_Float32,     1},
+    {"THRESH_DOP_CEN",                                    59, EDT_Float32,     1},
+    {"THRESH_DOP_AMB",                                    63, EDT_Float32,     1},
+    {"THRESH_OUTPUT_MEAN",                                67, EDT_Float32,     1},
+    {"EXP_OUTPUT_MEAN",                                   71, EDT_Float32,     1},
+    {"THRESH_OUTPUT_STD_DEV",                             75, EDT_Float32,     1},
+    {"EXP_OUTPUT_STD_DEV",                                79, EDT_Float32,     1},
+    {"THRESH_INPUT_MISSING_LINES",                        83, EDT_Float32,     1},
+    {"THRESH_INPUT_GAPS",                                 87, EDT_Float32,     1},
+    {"LINES_PER_GAPS",                                    91, EDT_UInt32,      1},
+    /*{"SPARE_2",                                         95, EDT_UByte,      15},*/
+    {"INPUT_MEAN",                                       110, EDT_Float32,     2},
+    {"INPUT_STD_DEV",                                    118, EDT_Float32,     2},
+    {"NUM_GAPS",                                         126, EDT_Float32,     1},
+    {"NUM_MISSING_LINES",                                130, EDT_Float32,     1},
+    {"OUTPUT_MEAN",                                      134, EDT_Float32,     2},
+    {"OUTPUT_STD_DEV",                                   142, EDT_Float32,     2},
+    {"TOT_ERRORS",                                       150, EDT_UInt32,      1},
+    /*{"SPARE_3",                                        154, EDT_UByte,      16},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_SR_GR_ADSR[] = {
+    {"ZERO_DOPPLER_TIME",                                  0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"SLANT_RANGE_TIME",                                  13, EDT_Float32,     1},
+    {"GROUND_RANGE_ORIGIN",                               17, EDT_Float32,     1},
+    {"SRGR_COEFF",                                        21, EDT_Float32,     5},
+    /*{"SPARE_1",                                         41, EDT_UByte,      14},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_GEOLOCATION_ADSR[] = {
+    {"ZERO_DOPPLER_TIME",                                  0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"CENTER_LAT",                                        13, EDT_Int32,       1},
+    {"CENTER_LONG",                                       17, EDT_Int32,       1},
+    /*{"SPARE_1",                                         21, EDT_UByte,       4},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_PROCESSING_PARAMS_ADSR[] = {
+    {"FIRST_ZERO_DOPPLER_TIME",                            0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"LAST_ZERO_DOPPLER_TIME",                            13, EDT_MJD,         1},
+    {"WORK_ORDER_ID",                                     25, EDT_Char,       12},
+    {"TIME_DIFF",                                         37, EDT_Float32,     1},
+    {"SWATH_ID",                                          41, EDT_Char,        3},
+    {"RANGE_SPACING",                                     44, EDT_Float32,     1},
+    {"AZIMUTH_SPACING",                                   48, EDT_Float32,     1},
+    {"LINE_TIME_INTERVAL",                                52, EDT_Float32,     1},
+    {"NUM_OUTPUT_LINES",                                  56, EDT_UInt32,      1},
+    {"NUM_SAMPLES_PER_LINE",                              60, EDT_UInt32,      1},
+    {"DATA_TYPE",                                         64, EDT_Char,        5},
+    /*{"SPARE_1",                                         69, EDT_UByte,      51},*/
+    {"DATA_ANALYSIS_FLAG",                               120, EDT_UByte,       1},
+    {"ANT_ELEV_CORR_FLAG",                               121, EDT_UByte,       1},
+    {"CHIRP_EXTRACT_FLAG",                               122, EDT_UByte,       1},
+    {"SRGR_FLAG",                                        123, EDT_UByte,       1},
+    {"DOP_CEN_FLAG",                                     124, EDT_UByte,       1},
+    {"DOP_AMB_FLAG",                                     125, EDT_UByte,       1},
+    {"RANGE_SPREAD_COMP_FLAG",                           126, EDT_UByte,       1},
+    {"DETECTED_FLAG",                                    127, EDT_UByte,       1},
+    {"LOOK_SUM_FLAG",                                    128, EDT_UByte,       1},
+    {"RMS_EQUAL_FLAG",                                   129, EDT_UByte,       1},
+    {"ANT_SCAL_FLAG",                                    130, EDT_UByte,       1},
+    /*{"SPARE_2",                                        131, EDT_UByte,      10},*/
+    {"RAW_DATA_ANALYSIS.1.NUM_GAPS",                     141, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.NUM_MISSING_LINES",            145, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.RANGE_SAMP_SKIP",              149, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.RANGE_LINES_SKIP",             153, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.1.CALC_I_BIAS",                  157, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_Q_BIAS",                  161, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_I_STD_DEV",               165, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_Q_STD_DEV",               169, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_GAIN",                    173, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.CALC_QUAD",                    177, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.I_BIAS_MAX",                   181, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.I_BIAS_MIN",                   185, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.Q_BIAS_MAX",                   189, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.Q_BIAS_MIN",                   193, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.GAIN_MIN",                     197, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.GAIN_MAX",                     201, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.QUAD_MIN",                     205, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.QUAD_MAX",                     209, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.I_BIAS_FLAG",                  213, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.Q_BIAS_FLAG",                  214, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.GAIN_FLAG",                    215, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.QUAD_FLAG",                    216, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.1.USED_I_BIAS",                  217, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.USED_Q_BIAS",                  221, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.USED_GAIN",                    225, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.1.USED_QUAD",                    229, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.NUM_GAPS",                     233, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.NUM_MISSING_LINES",            237, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.RANGE_SAMP_SKIP",              241, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.RANGE_LINES_SKIP",             245, EDT_UInt32,      1},
+    {"RAW_DATA_ANALYSIS.2.CALC_I_BIAS",                  249, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_Q_BIAS",                  253, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_I_STD_DEV",               257, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_Q_STD_DEV",               261, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_GAIN",                    265, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.CALC_QUAD",                    269, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.I_BIAS_MAX",                   273, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.I_BIAS_MIN",                   277, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.Q_BIAS_MAX",                   281, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.Q_BIAS_MIN",                   285, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.GAIN_MIN",                     289, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.GAIN_MAX",                     293, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.QUAD_MIN",                     297, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.QUAD_MAX",                     301, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.I_BIAS_FLAG",                  305, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.Q_BIAS_FLAG",                  306, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.GAIN_FLAG",                    307, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.QUAD_FLAG",                    308, EDT_UByte,       1},
+    {"RAW_DATA_ANALYSIS.2.USED_I_BIAS",                  309, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.USED_Q_BIAS",                  313, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.USED_GAIN",                    317, EDT_Float32,     1},
+    {"RAW_DATA_ANALYSIS.2.USED_QUAD",                    321, EDT_Float32,     1},
+    /*{"SPARE_3",                                        325, EDT_UByte,      32},*/
+    {"START_TIME.1.FIRST_OBT",                           357, EDT_UInt32,      2},
+    {"START_TIME.1.FIRST_MJD",                           365, EDT_MJD,         1},
+    {"START_TIME.2.FIRST_OBT",                           377, EDT_UInt32,      2},
+    {"START_TIME.2.FIRST_MJD",                           385, EDT_MJD,         1},
+    {"PARAMETER_CODES.SWST_CODE",                        397, EDT_UInt16,      5},
+    {"PARAMETER_CODES.LAST_SWST_CODE",                   407, EDT_UInt16,      5},
+    {"PARAMETER_CODES.PRI_CODE",                         417, EDT_UInt16,      5},
+    {"PARAMETER_CODES.TX_PULSE_LEN_CODE",                427, EDT_UInt16,      5},
+    {"PARAMETER_CODES.TX_BW_CODE",                       437, EDT_UInt16,      5},
+    {"PARAMETER_CODES.ECHO_WIN_LEN_CODE",                447, EDT_UInt16,      5},
+    {"PARAMETER_CODES.UP_CODE",                          457, EDT_UInt16,      5},
+    {"PARAMETER_CODES.DOWN_CODE",                        467, EDT_UInt16,      5},
+    {"PARAMETER_CODES.RESAMP_CODE",                      477, EDT_UInt16,      5},
+    {"PARAMETER_CODES.BEAM_ADJ_CODE",                    487, EDT_UInt16,      5},
+    {"PARAMETER_CODES.BEAM_SET_NUM_CODE",                497, EDT_UInt16,      5},
+    {"PARAMETER_CODES.TX_MONITOR_CODE",                  507, EDT_UInt16,      5},
+    /*{"SPARE_4",                                        517, EDT_UByte,      60},*/
+    {"ERROR_COUNTERS.NUM_ERR_SWST",                      577, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_PRI",                       581, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_TX_PULSE_LEN",              585, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_TX_PULSE_BW",               589, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_ECHO_WIN_LEN",              593, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_UP",                        597, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_DOWN",                      601, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_RESAMP",                    605, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_BEAM_ADJ",                  609, EDT_UInt32,      1},
+    {"ERROR_COUNTERS.NUM_ERR_BEAM_SET_NUM",              613, EDT_UInt32,      1},
+    /*{"SPARE_5",                                        617, EDT_UByte,      26},*/
+    {"IMAGE_PARAMETERS.SWST_VALUE",                      643, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.LAST_SWST_VALUE",                 663, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.SWST_CHANGES",                    683, EDT_UInt32,      5},
+    {"IMAGE_PARAMETERS.PRF_VALUE",                       703, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.TX_PULSE_LEN_VALUE",              723, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.TX_PULSE_BW_VALUE",               743, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.ECHO_WIN_LEN_VALUE",              763, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.UP_VALUE",                        783, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.DOWN_VALUE",                      803, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.RESAMP_VALUE",                    823, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.BEAM_ADJ_VALUE",                  843, EDT_Float32,     5},
+    {"IMAGE_PARAMETERS.BEAM_SET_VALUE",                  863, EDT_UInt16,      5},
+    {"IMAGE_PARAMETERS.TX_MONITOR_VALUE",                873, EDT_Float32,     5},
+    /*{"SPARE_6",                                        893, EDT_UByte,      82},*/
+    {"FIRST_PROC_RANGE_SAMP",                            975, EDT_UInt32,      1},
+    {"RANGE_REF",                                        979, EDT_Float32,     1},
+    {"RANGE_SAMP_RATE",                                  983, EDT_Float32,     1},
+    {"RADAR_FREQ",                                       987, EDT_Float32,     1},
+    {"NUM_LOOKS_RANGE",                                  991, EDT_UInt16,      1},
+    {"FILTER_RANGE",                                     993, EDT_Char,        7},
+    {"FILTER_COEF_RANGE",                               1000, EDT_Float32,     1},
+    {"BANDWIDTH.LOOK_BW_RANGE",                         1004, EDT_Float32,     5},
+    {"BANDWIDTH.TOT_BW_RANGE",                          1024, EDT_Float32,     5},
+    {"NOMINAL_CHIRP.1.NOM_CHIRP_AMP",                   1044, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.1.NOM_CHIRP_PHS",                   1060, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.2.NOM_CHIRP_AMP",                   1076, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.2.NOM_CHIRP_PHS",                   1092, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.3.NOM_CHIRP_AMP",                   1108, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.3.NOM_CHIRP_PHS",                   1124, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.4.NOM_CHIRP_AMP",                   1140, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.4.NOM_CHIRP_PHS",                   1156, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.5.NOM_CHIRP_AMP",                   1172, EDT_Float32,     4},
+    {"NOMINAL_CHIRP.5.NOM_CHIRP_PHS",                   1188, EDT_Float32,     4},
+    /*{"SPARE_7",                                       1204, EDT_UByte,      60},*/
+    {"NUM_LINES_PROC",                                  1264, EDT_UInt32,      1},
+    {"NUM_LOOK_AZ",                                     1268, EDT_UInt16,      1},
+    {"LOOK_BW_AZ",                                      1270, EDT_Float32,     1},
+    {"TO_BW_AZ",                                        1274, EDT_Float32,     1},
+    {"FILTER_AZ",                                       1278, EDT_Char,        7},
+    {"FILTER_COEF_AZ",                                  1285, EDT_Float32,     1},
+    {"AZ_FM_RATE",                                      1289, EDT_Float32,     3},
+    {"AX_FM_ORIGIN",                                    1301, EDT_Float32,     1},
+    {"DOP_AMB_CONF",                                    1305, EDT_Float32,     1},
+    /*{"SPARE_8",                                       1309, EDT_UByte,      68},*/
+    {"CALIBRATION_FACTORS.1.PROC_SCALING_FACT",         1377, EDT_Float32,     1},
+    {"CALIBRATION_FACTORS.1.EXT_CAL_FACT",              1381, EDT_Float32,     1},
+    {"CALIBRATION_FACTORS.2.PROC_SCALING_FACT",         1385, EDT_Float32,     1},
+    {"CALIBRATION_FACTORS.2.EXT_CAL_FACT",              1389, EDT_Float32,     1},
+    {"NOISE_ESTIMATION.NOISE_POWER_CORR",               1393, EDT_Float32,     5},
+    {"NOISE_ESTIMATION.NUM_NOISE_LINES",                1413, EDT_UInt32,      5},
+    /*{"SPARE_9",                                       1433, EDT_UByte,      76},*/
+    {"OUTPUT_STATISTICS.1.OUT_MEAN",                    1509, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.1.OUT_IMAG_MEAN",               1513, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.1.OUT_STD_DEV",                 1517, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.1.OUT_IMAG_STD_DEV",            1521, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_MEAN",                    1525, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_IMAG_MEAN",               1529, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_STD_DEV",                 1533, EDT_Float32,     1},
+    {"OUTPUT_STATISTICS.2.OUT_IMAG_STD_DEV",            1537, EDT_Float32,     1},
+    /*{"SPARE_10",                                      1541, EDT_UByte,      52},*/
+    {"ECHO_COMP",                                       1593, EDT_Char,        4},
+    {"ECHO_COMP_RATIO",                                 1597, EDT_Char,        3},
+    {"INIT_CAL_COMP",                                   1600, EDT_Char,        4},
+    {"INIT_CAL_RATIO",                                  1604, EDT_Char,        3},
+    {"PER_CAL_COMP",                                    1607, EDT_Char,        4},
+    {"PER_CAL_RATIO",                                   1611, EDT_Char,        3},
+    {"NOISE_COMP",                                      1614, EDT_Char,        4},
+    {"NOISE_COMP_RATIO",                                1618, EDT_Char,        3},
+    /*{"SPARE_11",                                      1621, EDT_UByte,      64},*/
+    {"BEAM_OVERLAP",                                    1685, EDT_UInt32,      4},
+    {"LINES_PER_BURST",                                 1701, EDT_UInt32,      5},
+    /*{"SPARE_12",                                      1721, EDT_UByte,      44},*/
+    {"ORBIT_STATE_VECTORS.1.STATE_VECT_TIME_1",         1765, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.1.X_POS_1",                   1777, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Y_POS_1",                   1781, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Z_POS_1",                   1785, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.X_VEL_1",                   1789, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Y_VEL_1",                   1793, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.1.Z_VEL_1",                   1797, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.STATE_VECT_TIME_1",         1801, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.2.X_POS_1",                   1813, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Y_POS_1",                   1817, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Z_POS_1",                   1821, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.X_VEL_1",                   1825, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Y_VEL_1",                   1829, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.2.Z_VEL_1",                   1833, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.STATE_VECT_TIME_1",         1837, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.3.X_POS_1",                   1849, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Y_POS_1",                   1853, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Z_POS_1",                   1857, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.X_VEL_1",                   1861, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Y_VEL_1",                   1865, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.3.Z_VEL_1",                   1869, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.STATE_VECT_TIME_1",         1873, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.4.X_POS_1",                   1885, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Y_POS_1",                   1889, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Z_POS_1",                   1893, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.X_VEL_1",                   1897, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Y_VEL_1",                   1901, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.4.Z_VEL_1",                   1905, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.STATE_VECT_TIME_1",         1909, EDT_MJD,         1},
+    {"ORBIT_STATE_VECTORS.5.X_POS_1",                   1921, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Y_POS_1",                   1925, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Z_POS_1",                   1929, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.X_VEL_1",                   1933, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Y_VEL_1",                   1937, EDT_Int32,       1},
+    {"ORBIT_STATE_VECTORS.5.Z_VEL_1",                   1941, EDT_Int32,       1},
+    /*{"SPARE_13",                                      1945, EDT_UByte,      64},*/
+    {"SLANT_RANGE_TIME",                                2009, EDT_Float32,     1},
+    {"DOP_COEF",                                        2013, EDT_Float32,     5},
+    {"DOP_CONF",                                        2033, EDT_Float32,     1},
+    /*{"SPARE_14",                                      2037, EDT_UByte,      14},*/
+    {"CHIRP_WIDTH",                                     2051, EDT_Float32,     1},
+    {"CHIRP_SIDELOBE",                                  2055, EDT_Float32,     1},
+    {"CHIRP_ISLR",                                      2059, EDT_Float32,     1},
+    {"CHIRP_PEAK_LOC",                                  2063, EDT_Float32,     1},
+    {"CHIRP_POWER",                                     2067, EDT_Float32,     1},
+    {"ELEV_CORR_FACTOR",                                2071, EDT_Float32,     1},
+    /*{"SPARE_15",                                      2075, EDT_UByte,      16},*/
+    {"CAL_INFO.1.MAX_CAL",                              2091, EDT_Float32,     3},
+    {"CAL_INFO.1.AVG_CAL",                              2103, EDT_Float32,     3},
+    {"CAL_INFO.1.AVG_VAL_1A",                           2115, EDT_Float32,     1},
+    {"CAL_INFO.1.PHS_CAL",                              2119, EDT_Float32,     4},
+    {"CAL_INFO.2.MAX_CAL",                              2135, EDT_Float32,     3},
+    {"CAL_INFO.2.AVG_CAL",                              2147, EDT_Float32,     3},
+    {"CAL_INFO.2.AVG_VAL_1A",                           2159, EDT_Float32,     1},
+    {"CAL_INFO.2.PHS_CAL",                              2163, EDT_Float32,     4},
+    {"CAL_INFO.3.MAX_CAL",                              2179, EDT_Float32,     3},
+    {"CAL_INFO.3.AVG_CAL",                              2191, EDT_Float32,     3},
+    {"CAL_INFO.3.AVG_VAL_1A",                           2203, EDT_Float32,     1},
+    {"CAL_INFO.3.PHS_CAL",                              2207, EDT_Float32,     4},
+    {"CAL_INFO.4.MAX_CAL",                              2223, EDT_Float32,     3},
+    {"CAL_INFO.4.AVG_CAL",                              2235, EDT_Float32,     3},
+    {"CAL_INFO.4.AVG_VAL_1A",                           2247, EDT_Float32,     1},
+    {"CAL_INFO.4.PHS_CAL",                              2251, EDT_Float32,     4},
+    {"CAL_INFO.5.MAX_CAL",                              2267, EDT_Float32,     3},
+    {"CAL_INFO.5.AVG_CAL",                              2279, EDT_Float32,     3},
+    {"CAL_INFO.5.AVG_VAL_1A",                           2291, EDT_Float32,     1},
+    {"CAL_INFO.5.PHS_CAL",                              2295, EDT_Float32,     4},
+    {"CAL_INFO.6.MAX_CAL",                              2311, EDT_Float32,     3},
+    {"CAL_INFO.6.AVG_CAL",                              2323, EDT_Float32,     3},
+    {"CAL_INFO.6.AVG_VAL_1A",                           2335, EDT_Float32,     1},
+    {"CAL_INFO.6.PHS_CAL",                              2339, EDT_Float32,     4},
+    {"CAL_INFO.7.MAX_CAL",                              2355, EDT_Float32,     3},
+    {"CAL_INFO.7.AVG_CAL",                              2367, EDT_Float32,     3},
+    {"CAL_INFO.7.AVG_VAL_1A",                           2379, EDT_Float32,     1},
+    {"CAL_INFO.7.PHS_CAL",                              2383, EDT_Float32,     4},
+    {"CAL_INFO.8.MAX_CAL",                              2399, EDT_Float32,     3},
+    {"CAL_INFO.8.AVG_CAL",                              2411, EDT_Float32,     3},
+    {"CAL_INFO.8.AVG_VAL_1A",                           2423, EDT_Float32,     1},
+    {"CAL_INFO.8.PHS_CAL",                              2427, EDT_Float32,     4},
+    {"CAL_INFO.9.MAX_CAL",                              2443, EDT_Float32,     3},
+    {"CAL_INFO.9.AVG_CAL",                              2455, EDT_Float32,     3},
+    {"CAL_INFO.9.AVG_VAL_1A",                           2467, EDT_Float32,     1},
+    {"CAL_INFO.9.PHS_CAL",                              2471, EDT_Float32,     4},
+    {"CAL_INFO.10.MAX_CAL",                             2487, EDT_Float32,     3},
+    {"CAL_INFO.10.AVG_CAL",                             2499, EDT_Float32,     3},
+    {"CAL_INFO.10.AVG_VAL_1A",                          2511, EDT_Float32,     1},
+    {"CAL_INFO.10.PHS_CAL",                             2515, EDT_Float32,     4},
+    {"CAL_INFO.11.MAX_CAL",                             2531, EDT_Float32,     3},
+    {"CAL_INFO.11.AVG_CAL",                             2543, EDT_Float32,     3},
+    {"CAL_INFO.11.AVG_VAL_1A",                          2555, EDT_Float32,     1},
+    {"CAL_INFO.11.PHS_CAL",                             2559, EDT_Float32,     4},
+    {"CAL_INFO.12.MAX_CAL",                             2575, EDT_Float32,     3},
+    {"CAL_INFO.12.AVG_CAL",                             2587, EDT_Float32,     3},
+    {"CAL_INFO.12.AVG_VAL_1A",                          2599, EDT_Float32,     1},
+    {"CAL_INFO.12.PHS_CAL",                             2603, EDT_Float32,     4},
+    {"CAL_INFO.13.MAX_CAL",                             2619, EDT_Float32,     3},
+    {"CAL_INFO.13.AVG_CAL",                             2631, EDT_Float32,     3},
+    {"CAL_INFO.13.AVG_VAL_1A",                          2643, EDT_Float32,     1},
+    {"CAL_INFO.13.PHS_CAL",                             2647, EDT_Float32,     4},
+    {"CAL_INFO.14.MAX_CAL",                             2663, EDT_Float32,     3},
+    {"CAL_INFO.14.AVG_CAL",                             2675, EDT_Float32,     3},
+    {"CAL_INFO.14.AVG_VAL_1A",                          2687, EDT_Float32,     1},
+    {"CAL_INFO.14.PHS_CAL",                             2691, EDT_Float32,     4},
+    {"CAL_INFO.15.MAX_CAL",                             2707, EDT_Float32,     3},
+    {"CAL_INFO.15.AVG_CAL",                             2719, EDT_Float32,     3},
+    {"CAL_INFO.15.AVG_VAL_1A",                          2731, EDT_Float32,     1},
+    {"CAL_INFO.15.PHS_CAL",                             2735, EDT_Float32,     4},
+    {"CAL_INFO.16.MAX_CAL",                             2751, EDT_Float32,     3},
+    {"CAL_INFO.16.AVG_CAL",                             2763, EDT_Float32,     3},
+    {"CAL_INFO.16.AVG_VAL_1A",                          2775, EDT_Float32,     1},
+    {"CAL_INFO.16.PHS_CAL",                             2779, EDT_Float32,     4},
+    {"CAL_INFO.17.MAX_CAL",                             2795, EDT_Float32,     3},
+    {"CAL_INFO.17.AVG_CAL",                             2807, EDT_Float32,     3},
+    {"CAL_INFO.17.AVG_VAL_1A",                          2819, EDT_Float32,     1},
+    {"CAL_INFO.17.PHS_CAL",                             2823, EDT_Float32,     4},
+    {"CAL_INFO.18.MAX_CAL",                             2839, EDT_Float32,     3},
+    {"CAL_INFO.18.AVG_CAL",                             2851, EDT_Float32,     3},
+    {"CAL_INFO.18.AVG_VAL_1A",                          2863, EDT_Float32,     1},
+    {"CAL_INFO.18.PHS_CAL",                             2867, EDT_Float32,     4},
+    {"CAL_INFO.19.MAX_CAL",                             2883, EDT_Float32,     3},
+    {"CAL_INFO.19.AVG_CAL",                             2895, EDT_Float32,     3},
+    {"CAL_INFO.19.AVG_VAL_1A",                          2907, EDT_Float32,     1},
+    {"CAL_INFO.19.PHS_CAL",                             2911, EDT_Float32,     4},
+    {"CAL_INFO.20.MAX_CAL",                             2927, EDT_Float32,     3},
+    {"CAL_INFO.20.AVG_CAL",                             2939, EDT_Float32,     3},
+    {"CAL_INFO.20.AVG_VAL_1A",                          2951, EDT_Float32,     1},
+    {"CAL_INFO.20.PHS_CAL",                             2955, EDT_Float32,     4},
+    {"CAL_INFO.21.MAX_CAL",                             2971, EDT_Float32,     3},
+    {"CAL_INFO.21.AVG_CAL",                             2983, EDT_Float32,     3},
+    {"CAL_INFO.21.AVG_VAL_1A",                          2995, EDT_Float32,     1},
+    {"CAL_INFO.21.PHS_CAL",                             2999, EDT_Float32,     4},
+    {"CAL_INFO.22.MAX_CAL",                             3015, EDT_Float32,     3},
+    {"CAL_INFO.22.AVG_CAL",                             3027, EDT_Float32,     3},
+    {"CAL_INFO.22.AVG_VAL_1A",                          3039, EDT_Float32,     1},
+    {"CAL_INFO.22.PHS_CAL",                             3043, EDT_Float32,     4},
+    {"CAL_INFO.23.MAX_CAL",                             3059, EDT_Float32,     3},
+    {"CAL_INFO.23.AVG_CAL",                             3071, EDT_Float32,     3},
+    {"CAL_INFO.23.AVG_VAL_1A",                          3083, EDT_Float32,     1},
+    {"CAL_INFO.23.PHS_CAL",                             3087, EDT_Float32,     4},
+    {"CAL_INFO.24.MAX_CAL",                             3103, EDT_Float32,     3},
+    {"CAL_INFO.24.AVG_CAL",                             3115, EDT_Float32,     3},
+    {"CAL_INFO.24.AVG_VAL_1A",                          3127, EDT_Float32,     1},
+    {"CAL_INFO.24.PHS_CAL",                             3131, EDT_Float32,     4},
+    {"CAL_INFO.25.MAX_CAL",                             3147, EDT_Float32,     3},
+    {"CAL_INFO.25.AVG_CAL",                             3159, EDT_Float32,     3},
+    {"CAL_INFO.25.AVG_VAL_1A",                          3171, EDT_Float32,     1},
+    {"CAL_INFO.25.PHS_CAL",                             3175, EDT_Float32,     4},
+    {"CAL_INFO.26.MAX_CAL",                             3191, EDT_Float32,     3},
+    {"CAL_INFO.26.AVG_CAL",                             3203, EDT_Float32,     3},
+    {"CAL_INFO.26.AVG_VAL_1A",                          3215, EDT_Float32,     1},
+    {"CAL_INFO.26.PHS_CAL",                             3219, EDT_Float32,     4},
+    {"CAL_INFO.27.MAX_CAL",                             3235, EDT_Float32,     3},
+    {"CAL_INFO.27.AVG_CAL",                             3247, EDT_Float32,     3},
+    {"CAL_INFO.27.AVG_VAL_1A",                          3259, EDT_Float32,     1},
+    {"CAL_INFO.27.PHS_CAL",                             3263, EDT_Float32,     4},
+    {"CAL_INFO.28.MAX_CAL",                             3279, EDT_Float32,     3},
+    {"CAL_INFO.28.AVG_CAL",                             3291, EDT_Float32,     3},
+    {"CAL_INFO.28.AVG_VAL_1A",                          3303, EDT_Float32,     1},
+    {"CAL_INFO.28.PHS_CAL",                             3307, EDT_Float32,     4},
+    {"CAL_INFO.29.MAX_CAL",                             3323, EDT_Float32,     3},
+    {"CAL_INFO.29.AVG_CAL",                             3335, EDT_Float32,     3},
+    {"CAL_INFO.29.AVG_VAL_1A",                          3347, EDT_Float32,     1},
+    {"CAL_INFO.29.PHS_CAL",                             3351, EDT_Float32,     4},
+    {"CAL_INFO.30.MAX_CAL",                             3367, EDT_Float32,     3},
+    {"CAL_INFO.30.AVG_CAL",                             3379, EDT_Float32,     3},
+    {"CAL_INFO.30.AVG_VAL_1A",                          3391, EDT_Float32,     1},
+    {"CAL_INFO.30.PHS_CAL",                             3395, EDT_Float32,     4},
+    {"CAL_INFO.31.MAX_CAL",                             3411, EDT_Float32,     3},
+    {"CAL_INFO.31.AVG_CAL",                             3423, EDT_Float32,     3},
+    {"CAL_INFO.31.AVG_VAL_1A",                          3435, EDT_Float32,     1},
+    {"CAL_INFO.31.PHS_CAL",                             3439, EDT_Float32,     4},
+    {"CAL_INFO.32.MAX_CAL",                             3455, EDT_Float32,     3},
+    {"CAL_INFO.32.AVG_CAL",                             3467, EDT_Float32,     3},
+    {"CAL_INFO.32.AVG_VAL_1A",                          3479, EDT_Float32,     1},
+    {"CAL_INFO.32.PHS_CAL",                             3483, EDT_Float32,     4},
+    /*{"SPARE_16",                                      3499, EDT_UByte,      16},*/
+    {"FIRST_LINE_TIME",                                 3515, EDT_MJD,         1},
+    {"FIRST_LINE_TIE_POINTS.RANGE_SAMP_NUMS_FIRST",     3527, EDT_UInt32,      3},
+    {"FIRST_LINE_TIE_POINTS.SLANT_RANGE_TIMES_FIRST",   3539, EDT_Float32,     3},
+    {"FIRST_LINE_TIE_POINTS.INC_ANGLES_FIRST",          3551, EDT_Float32,     3},
+    {"FIRST_LINE_TIE_POINTS.LATS_FIRST",                3563, EDT_Int32,       3},
+    {"FIRST_LINE_TIE_POINTS.LONGS_FIRST",               3575, EDT_Int32,       3},
+    {"MID_LINE_TIME",                                   3587, EDT_MJD,         1},
+    {"MID_RANGE_LINE_NUMS",                             3599, EDT_UInt32,      1},
+    {"MID_LINE_TIE_POINTS.RANGE_SAMP_NUMS_MID",         3603, EDT_UInt32,      3},
+    {"MID_LINE_TIE_POINTS.SLANT_RANGE_TIMES_MID",       3615, EDT_Float32,     3},
+    {"MID_LINE_TIE_POINTS.INC_ANGLES_MID",              3627, EDT_Float32,     3},
+    {"MID_LINE_TIE_POINTS.LATS_MID",                    3639, EDT_Int32,       3},
+    {"MID_LINE_TIE_POINTS.LONGS_MID",                   3651, EDT_Int32,       3},
+    {"LAST_LINE_TIME",                                  3663, EDT_MJD,         1},
+    {"LAST_LINE_NUM",                                   3675, EDT_UInt32,      1},
+    {"LAST_LINE_TIE_POINTS.RANGE_SAMP_NUMS_LAST",       3679, EDT_UInt32,      3},
+    {"LAST_LINE_TIE_POINTS.SLANT_RANGE_TIMES_LAST",     3691, EDT_Float32,     3},
+    {"LAST_LINE_TIE_POINTS.INC_ANGLES_LAST",            3703, EDT_Float32,     3},
+    {"LAST_LINE_TIE_POINTS.LATS_LAST",                  3715, EDT_Int32,       3},
+    {"LAST_LINE_TIE_POINTS.LONGS_LAST",                 3727, EDT_Int32,       3},
+    {"SWST_OFFSET",                                     3739, EDT_Float32,     1},
+    {"GROUND_RANGE_BIAS",                               3743, EDT_Float32,     1},
+    {"ELEV_ANGLE_BIAS",                                 3747, EDT_Float32,     1},
+    {"IMAGETTE_RANGE_LEN",                              3751, EDT_Float32,     1},
+    {"IMAGETTE_AZ_LEN",                                 3755, EDT_Float32,     1},
+    {"IMAGETTE_RANGE_RES",                              3759, EDT_Float32,     1},
+    {"GROUND_RES",                                      3763, EDT_Float32,     1},
+    {"IMAGETTE_AZ_RES",                                 3767, EDT_Float32,     1},
+    {"PLATFORM_ALT",                                    3771, EDT_Float32,     1},
+    {"PLATFORM_VEL",                                    3775, EDT_Float32,     1},
+    {"SLANT_RANGE",                                     3779, EDT_Float32,     1},
+    {"CW_DRIFT",                                        3783, EDT_Float32,     1},
+    {"WAVE_SUBCYCLE",                                   3787, EDT_UInt16,      1},
+    {"EARTH_RADIUS",                                    3789, EDT_Float32,     1},
+    {"SAT_HEIGHT",                                      3793, EDT_Float32,     1},
+    {"FIRST_SAMPLE_SLANT_RANGE",                        3797, EDT_Float32,     1},
+    /*{"SPARE_17",                                      3801, EDT_UByte,      12},*/
+    {"ELEVATION_PATTERN.SLANT_RANGE_TIME",              3813, EDT_Float32,    11},
+    {"ELEVATION_PATTERN.ELEVATION_ANGLES",              3857, EDT_Float32,    11},
+    {"ELEVATION_PATTERN.ANTENNA_PATTERN",               3901, EDT_Float32,    11},
+    /*{"SPARE_18",                                      3945, EDT_UByte,      14},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr ASAR_WAVE_SQ_ADSR[] = {
+    {"ZERO_DOPPLER_TIME",                                  0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"INPUT_MEAN_FLAG",                                   13, EDT_UByte,       1},
+    {"INPUT_STD_DEV_FLAG",                                14, EDT_UByte,       1},
+    {"INPUT_GAPS_FLAG",                                   15, EDT_UByte,       1},
+    {"INPUT_MISSING_LINES_FLAG",                          16, EDT_UByte,       1},
+    {"DOP_CEN_FLAG",                                      17, EDT_UByte,       1},
+    {"DOP_AMB_FLAG",                                      18, EDT_UByte,       1},
+    {"OUTPUT_MEAN_FLAG",                                  19, EDT_UByte,       1},
+    {"OUTPUT_STD_DEV_FLAG",                               20, EDT_UByte,       1},
+    {"CHIRP_FLAG",                                        21, EDT_UByte,       1},
+    {"MISSING_DATA_SETS_FLAG",                            22, EDT_UByte,       1},
+    {"INVALID_DOWNLINK_FLAG",                             23, EDT_UByte,       1},
+    /*{"SPARE_1",                                         24, EDT_UByte,       7},*/
+    {"THRESH_CHIRP_BROADENING",                           31, EDT_Float32,     1},
+    {"THRESH_CHIRP_SIDELOBE",                             35, EDT_Float32,     1},
+    {"THRESH_CHIRP_ISLR",                                 39, EDT_Float32,     1},
+    {"THRESH_INPUT_MEAN",                                 43, EDT_Float32,     1},
+    {"EXP_INPUT_MEAN",                                    47, EDT_Float32,     1},
+    {"THRESH_INPUT_STD_DEV",                              51, EDT_Float32,     1},
+    {"EXP_INPUT_STD_DEV",                                 55, EDT_Float32,     1},
+    {"THRESH_DOP_CEN",                                    59, EDT_Float32,     1},
+    {"THRESH_DOP_AMB",                                    63, EDT_Float32,     1},
+    {"THRESH_OUTPUT_MEAN",                                67, EDT_Float32,     1},
+    {"EXP_OUTPUT_MEAN",                                   71, EDT_Float32,     1},
+    {"THRESH_OUTPUT_STD_DEV",                             75, EDT_Float32,     1},
+    {"EXP_OUTPUT_STD_DEV",                                79, EDT_Float32,     1},
+    {"THRESH_INPUT_MISSING_LINES",                        83, EDT_Float32,     1},
+    {"THRESH_INPUT_GAPS",                                 87, EDT_Float32,     1},
+    {"LINES_PER_GAPS",                                    91, EDT_UInt32,      1},
+    /*{"SPARE_2",                                         95, EDT_UByte,      15},*/
+    {"INPUT_MEAN",                                       110, EDT_Float32,     2},
+    {"INPUT_STD_DEV",                                    118, EDT_Float32,     2},
+    {"NUM_GAPS",                                         126, EDT_Float32,     1},
+    {"NUM_MISSING_LINES",                                130, EDT_Float32,     1},
+    {"OUTPUT_MEAN",                                      134, EDT_Float32,     2},
+    {"OUTPUT_STD_DEV",                                   142, EDT_Float32,     2},
+    {"TOT_ERRORS",                                       150, EDT_UInt32,      1},
+    /*{"SPARE_3",                                        154, EDT_UByte,      16},*/
+    {"LAND_FLAG",                                        170, EDT_UByte,       1},
+    {"LOOK_CONF_FLAG",                                   171, EDT_UByte,       1},
+    {"INTER_LOOK_CONF_FLAG",                             172, EDT_UByte,       1},
+    {"AZ_CUTOFF_FLAG",                                   173, EDT_UByte,       1},
+    {"AZ_CUTOFF_ITERATION_FLAG",                         174, EDT_UByte,       1},
+    {"PHASE_FLAG",                                       175, EDT_UByte,       1},
+    /*{"SPARE_4",                                        176, EDT_UByte,       4},*/
+    {"LOOK_CONF_THRESH",                                 180, EDT_Float32,     2},
+    {"INTER_LOOK_CONF_THRESH",                           188, EDT_Float32,     1},
+    {"AZ_CUTOFF_THRESH",                                 192, EDT_Float32,     1},
+    {"AZ_CUTOFF_ITERATIONS_THRESH",                      196, EDT_UInt32,      1},
+    {"PHASE_PEAK_THRESH",                                200, EDT_Float32,     1},
+    {"PHASE_CROSS_THRESH",                               204, EDT_Float32,     1},
+    /*{"SPARE_5",                                        208, EDT_UByte,      12},*/
+    {"LOOK_CONF",                                        220, EDT_Float32,     1},
+    {"INTER_LOOK_CONF",                                  224, EDT_Float32,     1},
+    {"AZ_CUTOFF",                                        228, EDT_Float32,     1},
+    {"PHASE_PEAK_CONF",                                  232, EDT_Float32,     1},
+    {"PHASE_CROSS_CONF",                                 236, EDT_Float32,     1},
+    /*{"SPARE_6",                                        240, EDT_UByte,      12},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+/* --- MERIS record descriptors -------------------------------------------- */
+static const EnvisatFieldDescr MERIS_1P_QUALITY_ADSR[] = {
+    {"DSR_TIME",                                           0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"RANGE_FLAG",                                        13, EDT_UInt16,      5},
+    {"RANGE_BLIND_FLAG",                                  23, EDT_UInt16,      5},
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr MERIS_1P_SCALING_FACTOR_GADS[] = {
+    {"SCALING_FACTOR_ALT",                                 0, EDT_Float32,     1},
+    {"SCALING_FACTOR_ROUGH",                               4, EDT_Float32,     1},
+    {"SCALING_FACTOR_ZON_WIND",                            8, EDT_Float32,     1},
+    {"SCALING_FACTOR_MERR_WIND",                          12, EDT_Float32,     1},
+    {"SCALING_FACTOR_ATM_PRES",                           16, EDT_Float32,     1},
+    {"SCALING_FACTOR_OZONE",                              20, EDT_Float32,     1},
+    {"SCALING_FACTOR_REL_HUM",                            24, EDT_Float32,     1},
+    {"SCALING_FACTOR_RAD",                                28, EDT_Float32,    15},
+    {"GAIN_SETTINGS",                                     88, EDT_UByte,      80},
+    {"SAMPLING_RATE",                                    168, EDT_UInt32,      1},
+    {"SUN_SPECTRAL_FLUX",                                172, EDT_Float32,    15},
+    /*{"SPARE_1",                                        232, EDT_UByte,      60},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr MERIS_2P_QUALITY_ADSR[] = {
+    {"DSR_TIME",                                           0, EDT_MJD,         1},
+    {"ATTACH_FLAG",                                       12, EDT_UByte,       1},
+    {"PERC_WATER_ABS_AERO",                               13, EDT_UByte,       1},
+    {"PERC_WATER",                                        14, EDT_UByte,       1},
+    {"PERC_DDV_LAND",                                     15, EDT_UByte,       1},
+    {"PERC_LAND",                                         16, EDT_UByte,       1},
+    {"PERC_CLOUD",                                        17, EDT_UByte,       1},
+    {"PERC_LOW_POLY_PRESS",                               18, EDT_UByte,       1},
+    {"PERC_LOW_NEURAL_PRESS",                             19, EDT_UByte,       1},
+    {"PERC_OUT_RAN_INP_WVAPOUR",                          20, EDT_UByte,       1},
+    {"PER_OUT_RAN_OUTP_WVAPOUR",                          21, EDT_UByte,       1},
+    {"PERC_OUT_RANGE_INP_CL",                             22, EDT_UByte,       1},
+    {"PERC_OUT_RAN_OUTP_CL",                              23, EDT_UByte,       1},
+    {"PERC_IN_RAN_INP_LAND",                              24, EDT_UByte,       1},
+    {"PERC_OUT_RAN_OUTP_LAND",                            25, EDT_UByte,       1},
+    {"PERC_OUT_RAN_INP_OCEAN",                            26, EDT_UByte,       1},
+    {"PERC_OUT_RAN_OUTP_OCEAN",                           27, EDT_UByte,       1},
+    {"PERC_OUT_RAN_INP_CASE1",                            28, EDT_UByte,       1},
+    {"PERC_OUT_RAN_OUTP_CASE1",                           29, EDT_UByte,       1},
+    {"PERC_OUT_RAN_INP_CASE2",                            30, EDT_UByte,       1},
+    {"PERC_OUT_RAN_OUTP_CASE2",                           31, EDT_UByte,       1},
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr MERIS_2P_SCALING_FACTOR_GADS[] = {
+    {"SCALING_FACTOR_ALT",                                 0, EDT_Float32,     1},
+    {"SCALING_FACTOR_ROUGH",                               4, EDT_Float32,     1},
+    {"SCALING_FACTOR_ZON_WIND",                            8, EDT_Float32,     1},
+    {"SCALING_FACTOR_MERR_WIND",                          12, EDT_Float32,     1},
+    {"SCALING_FACTOR_ATM_PRES",                           16, EDT_Float32,     1},
+    {"SCALING_FACTOR_OZONE",                              20, EDT_Float32,     1},
+    {"SCALING_FACTOR_REL_HUMID",                          24, EDT_Float32,     1},
+    {"SCALING_FACTOR_REFLEC",                             28, EDT_Float32,    13},
+    {"SCALING_FACTOR_ALGAL_PIG_IND",                      80, EDT_Float32,     1},
+    {"SCALING_FACTOR_YELLOW_SUBS",                        84, EDT_Float32,     1},
+    {"SCALING_FACTOR_SUSP_SED",                           88, EDT_Float32,     1},
+    {"SCALING_FACTOR_AERO_EPSILON",                       92, EDT_Float32,     1},
+    {"SCALING_FACTOR_AER_OPT_THICK",                      96, EDT_Float32,     1},
+    {"SCALING_FACTOR_CL_OPT_THICK",                      100, EDT_Float32,     1},
+    {"SCALING_FACTOR_SURF_PRES",                         104, EDT_Float32,     1},
+    {"SCALING_FACTOR_WVAPOUR",                           108, EDT_Float32,     1},
+    {"SCALING_FACTOR_PHOTOSYN_RAD",                      112, EDT_Float32,     1},
+    {"SCALING_FACTOR_TOA_VEG",                           116, EDT_Float32,     1},
+    {"SCALING_FACTOR_BOA_VEG",                           120, EDT_Float32,     1},
+    {"SCALING_FACTOR_CLOUD_ALBEDO",                      124, EDT_Float32,     1},
+    {"SCALING_FACTOR_CLOUD_TOP_PRESS",                   128, EDT_Float32,     1},
+    {"OFF_REFLEC",                                       132, EDT_Float32,    13},
+    {"OFFSET_ALGAL",                                     184, EDT_Float32,     1},
+    {"OFFSET_YELLOW_SUBS",                               188, EDT_Float32,     1},
+    {"OFFSET_TOTAL_SUSP",                                192, EDT_Float32,     1},
+    {"OFFSET_AERO_EPSILON",                              196, EDT_Float32,     1},
+    {"OFFSET_AER_OPT_THICK",                             200, EDT_Float32,     1},
+    {"OFFSET_CL_OPT_THICK",                              204, EDT_Float32,     1},
+    {"OFFSET_SURF_PRES",                                 208, EDT_Float32,     1},
+    {"OFFSET_WVAPOUR",                                   212, EDT_Float32,     1},
+    {"OFFSET_PHOTOSYN_RAD",                              216, EDT_Float32,     1},
+    {"OFFSET_TOA_VEG",                                   220, EDT_Float32,     1},
+    {"OFFSET_BOA_VEG",                                   224, EDT_Float32,     1},
+    {"OFFSET_CLOUD_ALBEDO",                              228, EDT_Float32,     1},
+    {"OFFSET_CLOUD_TOP_PRESS",                           232, EDT_Float32,     1},
+    {"GAIN_SETTINGS",                                    236, EDT_UByte,      80},
+    {"SAMPLING_RATE",                                    316, EDT_UInt32,      1},
+    {"SUN_SPECTRAL_FLUX",                                320, EDT_Float32,    15},
+    {"SCALING_FACTOR_RECT_REFL_NIR",                     380, EDT_Float32,     1},
+    {"OFFSET_RECT_REFL_NIR",                             384, EDT_Float32,     1},
+    {"SCALING_FACTOR_RECT_REFL_RED",                     388, EDT_Float32,     1},
+    {"OFFSET_RECT_REFL_RED",                             392, EDT_Float32,     1},
+    /*{"SPARE_1",                                        396, EDT_UByte,      44},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr MERIS_2P_C_SCALING_FACTOR_GADS[] = {
+    {"SCALING_FACTOR_CLOUD_OPT_THICK",                     0, EDT_Float32,     1},
+    {"SCALING_FACTOR_CLOUD_TOP_PRESS",                     4, EDT_Float32,     1},
+    {"SCALING_FACTOR_WVAPOUR",                             8, EDT_Float32,     1},
+    {"OFFSET_CL_OPT_THICK",                               12, EDT_Float32,     1},
+    {"OFFSET_CLOUD_TOP_PRESS",                            16, EDT_Float32,     1},
+    {"OFFSET_WVAPOUR",                                    20, EDT_Float32,     1},
+    /*{"SPARE_1",                                         24, EDT_UByte,      52},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+static const EnvisatFieldDescr MERIS_2P_V_SCALING_FACTOR_GADS[] = {
+    {"SCALING_FACTOR_TOA_VEGETATION_INDEX",                0, EDT_Float32,     1},
+    {"SCALING_FACTOR_BOA_VEGETATION_INDEX",                4, EDT_Float32,     1},
+    {"OFFSET_TOA_VEGETAYION_INDEX",                        8, EDT_Float32,     1},
+    {"OFFSET_BOA_VEGETAYION_INDEX",                       12, EDT_Float32,     1},
+    /*{"SPARE_1",                                         16, EDT_UByte,      60},*/
+    {NULL,                                                 0, EDT_Unknown,     0}
+};
+
+
+static const EnvisatRecordDescr aASAR_Records[] =  {
+    {"MDS1 ANTENNA ELEV PATT ADS", ASAR_ANTENNA_ELEV_PATT_ADSR},
+    {"MDS2 ANTENNA ELEV PATT ADS", ASAR_ANTENNA_ELEV_PATT_ADSR},
+    {"CHIRP PARAMS ADS", ASAR_CHIRP_PARAMS_ADSR},
+    {"DOP CENTROID COEFFS ADS", ASAR_DOP_CENTROID_COEFFS_ADSR},
+    /*{"GEOLOCATION GRID ADS", ASAR_GEOLOCATION_GRID_ADSR},*/
+    {"MAIN PROCESSING PARAMS ADS", ASAR_MAIN_PROCESSING_PARAMS_ADSR},
+    {"MAP PROJECTION GADS", ASAR_MAP_PROJECTION_GADS},
+    {"MDS1 SQ ADS", ASAR_SQ_ADSR},
+    {"MDS2 SQ ADS", ASAR_SQ_ADSR},
+    {"SR GR ADS", ASAR_SR_GR_ADSR},
+    /* WAVE */
+    /*{"GEOLOCATION ADS", ASAR_GEOLOCATION_ADSR},*/
+    {"PROCESSING PARAMS ADS", ASAR_PROCESSING_PARAMS_ADSR},
+    {"SQ ADS", ASAR_WAVE_SQ_ADSR},
+    {NULL, NULL}
+};
+
+static const EnvisatRecordDescr aMERIS_1P_Records[] =  {
+    {"Quality ADS", MERIS_1P_QUALITY_ADSR},
+    {"Scaling Factor GADS", MERIS_1P_SCALING_FACTOR_GADS},
+    {NULL, NULL}
+};
+
+static const EnvisatRecordDescr aMERIS_2P_Records[] =  {
+    {"Quality ADS", MERIS_2P_QUALITY_ADSR},
+    {"Scaling Factor GADS", MERIS_2P_SCALING_FACTOR_GADS},
+    {NULL, NULL}
+};
+
+static const EnvisatRecordDescr aMERIS_2P_C_Records[] =  {
+    {"Quality ADS", MERIS_2P_QUALITY_ADSR},
+    {"Scaling Factor GADS", MERIS_2P_C_SCALING_FACTOR_GADS},
+    {NULL, NULL}
+};
+
+static const EnvisatRecordDescr aMERIS_2P_V_Records[] =  {
+    {"Quality ADS", MERIS_2P_QUALITY_ADSR},
+    {"Scaling Factor GADS", MERIS_2P_V_SCALING_FACTOR_GADS},
+    {NULL, NULL}
+};
+
+const EnvisatRecordDescr* EnvisatFile_GetRecordDescriptor(
+                        const char* pszProduct, const char* pszDataset)
+{
+    const EnvisatRecordDescr *paRecords = NULL;
+    const EnvisatRecordDescr *pRecordDescr = NULL;
+    int nLen;
+
+    if( EQUALN(pszProduct,"ASA",3) )
+        paRecords = aASAR_Records;
+    else if( EQUALN(pszProduct,"MER",3) )
+    {
+        if ( EQUALN(pszProduct + 6,"C_2P",4) )
+            paRecords = aMERIS_2P_C_Records;
+        else if ( EQUALN(pszProduct + 6,"V_2P",4) )
+            paRecords = aMERIS_2P_V_Records;
+        else if ( EQUALN(pszProduct + 8,"1P",2) )
+            paRecords = aMERIS_1P_Records;
+        else if ( EQUALN(pszProduct + 8,"2P",2) )
+            paRecords = aMERIS_2P_Records;
+        else
+            return NULL;
+    }
+    else if( EQUALN(pszProduct,"SAR",3) )
+        /* ERS products in ENVISAT format have the same records of ASAR ones */
+        paRecords = aASAR_Records;
+    else
+        return NULL;
+
+    /* strip trailing spaces */
+    for( nLen = strlen(pszDataset); nLen && pszDataset[nLen-1] == ' '; --nLen );
+
+    pRecordDescr = paRecords;
+    while ( pRecordDescr->szName != NULL )
+    {
+        if ( EQUALN(pRecordDescr->szName, pszDataset, nLen) )
+            return pRecordDescr;
+        else
+            ++pRecordDescr;
+    }
+
+    return NULL;
+}
+
+CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
+                        const EnvisatFieldDescr* pField, char *szBuf)
+{
+    int i, nOffset = 0;
+    const void *pData;
+
+    if ( pField->nOffset >= nRecLen )
+    {
+        CPLDebug( "EnvisatDataset",
+                  "Field offset (%d) is greater than the record length (%d).",
+                  pField->nOffset, nRecLen );
+
+        return CE_Failure;
+    }
+
+    pData = (GByte*)pRecord + pField->nOffset;
+
+    szBuf[0] = '\0';
+
+    switch (pField->eType)
+    {
+        case EDT_Char:
+            memcpy((void*)szBuf, pData, pField->nCount);
+            szBuf[pField->nCount] = '\0';
+            break;
+        case EDT_UByte:
+        case EDT_SByte:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "%d",
+                                   ((const char*)pData)[i]);
+            }
+            break;
+        case EDT_Int16:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "%d",
+                                   CPL_MSBWORD16(((const GInt16*)pData)[i]));
+            }
+            break;
+        case EDT_UInt16:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "%d",
+                                   CPL_MSBWORD16(((const GUInt16*)pData)[i]));
+            }
+            break;
+        case EDT_Int32:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "%d",
+                                   CPL_MSBWORD32(((const GInt32*)pData)[i]));
+            }
+            break;
+        case EDT_UInt32:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "%d",
+                                   CPL_MSBWORD32(((const GUInt32*)pData)[i]));
+            }
+            break;
+        case EDT_Float32:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                float fValue = ((const float*)pData)[i];
+#ifdef CPL_LSB
+                CPL_SWAP32PTR( &fValue );
+#endif
+
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "%f", fValue);
+            }
+            break;
+        case EDT_Float64:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                double dfValue = ((const double*)pData)[i];
+#ifdef CPL_LSB
+                CPL_SWAPDOUBLE( &dfValue );
+#endif
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "%f", dfValue);
+            }
+            break;
+/*
+        case EDT_CInt16:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "(%d, %d)",
+                                CPL_MSBWORD16(((const GInt16*)pData)[2 * i]),
+                                CPL_MSBWORD16(((const GInt16*)pData)[2 * i+1]));
+            }
+            break;
+        case EDT_CInt32:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "(%d, %d)",
+                                CPL_MSBWORD32(((const GInt32*)pData)[2 * i]),
+                                CPL_MSBWORD32(((const GInt32*)pData)[2 * i+1]));
+            }
+            break;
+        case EDT_CFloat32:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                float fReal = ((const float*)pData)[2 * i];
+                float fImag = ((const float*)pData)[2 * i + 1];
+#ifdef CPL_LSB
+                CPL_SWAP32PTR( &fReal );
+                CPL_SWAP32PTR( &fImag );
+#endif
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "(%f, %f)", fReal, fImag);
+            }
+            break;
+        case EDT_CFloat64:
+            for (i = 0; i < pField->nCount; ++i)
+            {
+                double dfReal = ((const double*)pData)[2 * i];
+                double dfImag = ((const double*)pData)[2 * i + 1];
+#ifdef CPL_LSB
+                CPL_SWAPDOUBLE( &dfReal );
+                CPL_SWAPDOUBLE( &dfImag );
+#endif
+                if (i > 0)
+                    szBuf[nOffset++] = ' ';
+                nOffset += sprintf(szBuf + nOffset, "(%f, %f)", dfReal, dfImag);
+            }
+            break;
+*/
+        case EDT_MJD:
+            CPLAssert(pField->nCount == 1);
+            {
+                GInt32 days;
+                GUInt32 seconds, microseconds;
+
+                days = CPL_MSBWORD32(((const GInt32*)pData)[0]);
+                seconds = CPL_MSBWORD32(((const GUInt32*)pData)[1]);
+                microseconds = CPL_MSBWORD32(((const GUInt32*)pData)[2]);
+
+                sprintf(szBuf, "%d, %d, %d", days, seconds, microseconds);
+            }
+            break;
+        default:
+            CPLDebug( "EnvisatDataset",
+                      "Unabe to convert '%s' field to string: "
+                      "unsecpected data type '%d'.",
+                      pField->szName, pField->eType );
+            return CE_Failure;
+    }
+
+    return CE_None;
+}
diff --git a/frmts/envisat/records.h b/frmts/envisat/records.h
new file mode 100644
index 0000000..4eb8ae2
--- /dev/null
+++ b/frmts/envisat/records.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * $Id: records.h 22488 2011-06-02 17:04:47Z rouault $
+ *
+ * Project:  APP ENVISAT Support
+ * Purpose:  Low Level Envisat file access (read/write) API.
+ * Author:   Antonio Valentino <antonio.valentino at tiscali.it>
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Antonio Valentino
+ *
+ * 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 __RECORDS_H__
+#define __RECORDS_H__
+
+#include "gdal.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#define MJD_FIELD_SIZE 12
+
+/*! Field data types */
+typedef enum {
+    /*! Unknown or unspecified type */      EDT_Unknown = GDT_Unknown,
+    /*! Eight bit unsigned integer */       EDT_UByte = GDT_Byte,
+    /*! Eight bit signed integer */         EDT_SByte = GDT_TypeCount + 0,
+    /*! Sixteen bit unsigned integer */     EDT_UInt16 = GDT_UInt16,
+    /*! Sixteen bit signed integer */       EDT_Int16 = GDT_Int16,
+    /*! Thirty two bit unsigned integer */  EDT_UInt32 = GDT_UInt32,
+    /*! Thirty two bit signed integer */    EDT_Int32 = GDT_Int32,
+    /*! Thirty two bit floating point */    EDT_Float32 = GDT_Float32,
+    /*! Sixty four bit floating point */    EDT_Float64 = GDT_Float64,
+    /*! Complex Int16 */                    EDT_CInt16 = GDT_CInt16,
+    /*! Complex Int32 */                    EDT_CInt32 = GDT_CInt32,
+    /*! Complex Float32 */                  EDT_CFloat32 = GDT_CFloat32,
+    /*! Complex Float64 */                  EDT_CFloat64 = GDT_CFloat64,
+    /*! Modified Julian Dated */            EDT_MJD = GDT_TypeCount + 1,
+    /*! ASCII characters */                 EDT_Char = GDT_TypeCount + 2,
+    EDT_TypeCount = GDT_TypeCount + 3       /* maximum type # + 1 */
+} EnvisatDataType;
+
+typedef struct {
+    const char* szName;
+    const int nOffset;
+    const EnvisatDataType eType;
+    const int nCount;
+} EnvisatFieldDescr;
+
+typedef struct {
+    const char* szName;
+    const EnvisatFieldDescr *pFields;
+} EnvisatRecordDescr;
+
+const EnvisatRecordDescr* EnvisatFile_GetRecordDescriptor(const char* pszProduct,
+                                              const char* pszDataset);
+
+CPLErr EnvisatFile_GetFieldAsString(const void*, int, const EnvisatFieldDescr*, char*);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __RECORDS_H__ */
diff --git a/frmts/epsilon/epsilondataset.cpp b/frmts/epsilon/epsilondataset.cpp
index b12928a..de5f124 100644
--- a/frmts/epsilon/epsilondataset.cpp
+++ b/frmts/epsilon/epsilondataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: epsilondataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: epsilondataset.cpp 22363 2011-05-12 18:26:19Z rouault $
  *
  * Project:  GDAL Epsilon driver
  * Purpose:  Implement GDAL Epsilon support using Epsilon library
@@ -30,7 +30,7 @@
 #include "epsilon.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: epsilondataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: epsilondataset.cpp 22363 2011-05-12 18:26:19Z rouault $");
 
 #define RASTERLITE_WAVELET_HEADER "StartWaveletsImage$$"
 #define RASTERLITE_WAVELET_FOOTER "$$EndWaveletsImage"
@@ -48,6 +48,13 @@ typedef struct
     vsi_l_offset offset;
 } BlockDesc;
 
+#ifdef I_WANT_COMPATIBILITY_WITH_EPSILON_0_8_1
+#define GET_FIELD(hdr, field) \
+    (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.field : hdr.tc.field
+#else
+#define GET_FIELD(hdr, field) \
+    (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.hdr_data.gs.field : hdr.hdr_data.tc.field
+#endif
 
 /************************************************************************/
 /* ==================================================================== */
@@ -237,8 +244,8 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
         return CE_Failure;
     }
     
-    int w = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.w : hdr.tc.w;
-    int h = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.h : hdr.tc.h;
+    int w = GET_FIELD(hdr, w);
+    int h = GET_FIELD(hdr, h);
     int i;
 
     if (poGDS->nBands == 1)
@@ -505,12 +512,12 @@ int EpsilonDataset::ScanBlocks(int* pnBands)
             continue;
         }
         
-        int W = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.W : hdr.tc.W;
-        int H = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.H : hdr.tc.H;
-        int x = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.x : hdr.tc.x;
-        int y = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.y : hdr.tc.y;
-        int w = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.w : hdr.tc.w;
-        int h = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.h : hdr.tc.h;
+        int W = GET_FIELD(hdr, W);
+        int H = GET_FIELD(hdr, H);
+        int x = GET_FIELD(hdr, x);
+        int y = GET_FIELD(hdr, y);
+        int w = GET_FIELD(hdr, w);
+        int h = GET_FIELD(hdr, h);
 
         //CPLDebug("EPSILON", "W=%d,H=%d,x=%d,y=%d,w=%d,h=%d,offset=" CPL_FRMT_GUIB,
         //                    W, H, x, y, w, h, nStartBlockFileOff);
@@ -1012,8 +1019,8 @@ void GDALRegister_EPSILON()
 "   <Option name='FILTER' type='string-select' description='Filter ID' default='daub97lift'>"
 "%s"
 "   </Option>"
-"   <Option name='BLOCKXSIZE' type='int' description='Tile Width. Between 32 and 1024' default=256/>"
-"   <Option name='BLOCKYSIZE' type='int' description='Tile Height. Between 32 and 1024' default=256/>"
+"   <Option name='BLOCKXSIZE' type='int' description='Tile Width. Between 32 and 1024' default='256'/>"
+"   <Option name='BLOCKYSIZE' type='int' description='Tile Height. Between 32 and 1024' default='256'/>"
 "   <Option name='MODE' type='string-select' default='OTLPF'>"
 "       <Value>NORMAL</Value>"
 "       <Value>OTLPF</Value>"
diff --git a/frmts/epsilon/frmt_epsilon.html b/frmts/epsilon/frmt_epsilon.html
index 96cefdb..d8dd6ce 100644
--- a/frmts/epsilon/frmt_epsilon.html
+++ b/frmts/epsilon/frmt_epsilon.html
@@ -9,9 +9,10 @@
 
 <h1>Epsilon - Wavelet compressed images</h1>
 
-<p>Starting with GDAL 1.7.0, GDAL can read and write wavelet-compressed images through the Epsilon library.</p>
+<p>Starting with GDAL 1.7.0, GDAL can read and write wavelet-compressed images through the Epsilon library.
+Starting with GDAL 1.9.0, epsilon 0.9.1 is required.</p>
 
-<p>The driver rely on the Open Source EPSILON library (GPL licenced). In its current state, the
+<p>The driver rely on the Open Source EPSILON library (dual LGPL/GPL licence v3). In its current state, the
    driver will only be able to read images with regular internal tiling.</p>
 
 <p>The EPSILON driver only supports 1 band (grayscale) and 3 bands (RGB) images</p>
diff --git a/frmts/ers/ersdataset.cpp b/frmts/ers/ersdataset.cpp
index f51723b..3cc2777 100644
--- a/frmts/ers/ersdataset.cpp
+++ b/frmts/ers/ersdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ersdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ersdataset.cpp 23029 2011-09-03 10:15:51Z rouault $
  *
  * Project:  ERMapper .ers Driver
  * Purpose:  Implementation of .ers driver.
@@ -32,11 +32,11 @@
 #include "cpl_string.h"
 #include "ershdrnode.h"
 
-CPL_CVSID("$Id: ersdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ersdataset.cpp 23029 2011-09-03 10:15:51Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				ERSDataset				*/
+/*                              ERSDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -44,6 +44,8 @@ class ERSRasterBand;
 
 class ERSDataset : public RawDataset
 {
+    friend class ERSRasterBand;
+
     VSILFILE	*fpImage;	// image data file.
     GDALDataset *poDepFile;
 
@@ -63,6 +65,22 @@ class ERSDataset : public RawDataset
     char          *pszGCPProjection;
 
     void          ReadGCPs();
+
+    int         bHasNoDataValue;
+    double      dfNoDataValue;
+
+    CPLString      osProj;
+    CPLString      osDatum;
+    CPLString      osUnits;
+    void           WriteProjectionInfo(const char* pszProj,
+                                       const char* pszDatum,
+                                       const char* pszUnits);
+
+    CPLStringList oERSMetadataList;
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
   public:
     		ERSDataset();
 	       ~ERSDataset();
@@ -80,19 +98,18 @@ class ERSDataset : public RawDataset
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
                             const char *pszGCPProjection );
 
+    virtual const char *GetMetadataItem( const char * pszName,
+                                     const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" );
+
     static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
 };
 
 /************************************************************************/
-/* ==================================================================== */
-/*				ERSDataset				*/
-/* ==================================================================== */
-/************************************************************************/
-
-/************************************************************************/
 /*                            ERSDataset()                             */
 /************************************************************************/
 
@@ -114,6 +131,9 @@ ERSDataset::ERSDataset()
     nGCPCount = 0;
     pasGCPList = NULL;
     pszGCPProjection = CPLStrdup("");
+
+    bHasNoDataValue = FALSE;
+    dfNoDataValue = 0.0;
 }
 
 /************************************************************************/
@@ -130,15 +150,7 @@ ERSDataset::~ERSDataset()
         VSIFCloseL( fpImage );
     }
 
-    if( poDepFile != NULL )
-    {
-        int iBand;
-
-        for( iBand = 0; iBand < nBands; iBand++ )
-            papoBands[iBand] = NULL;
-
-        GDALClose( (GDALDatasetH) poDepFile );
-    }
+    CloseDependentDatasets();
 
     CPLFree( pszProjection );
 
@@ -154,6 +166,31 @@ ERSDataset::~ERSDataset()
 }
 
 /************************************************************************/
+/*                      CloseDependentDatasets()                        */
+/************************************************************************/
+
+int ERSDataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = RawDataset::CloseDependentDatasets();
+
+    if( poDepFile != NULL )
+    {
+        int iBand;
+
+        bHasDroppedRef = TRUE;
+
+        for( iBand = 0; iBand < nBands; iBand++ )
+            papoBands[iBand] = NULL;
+        nBands = 0;
+
+        GDALClose( (GDALDatasetH) poDepFile );
+        poDepFile = NULL;
+    }
+
+    return bHasDroppedRef;
+}
+
+/************************************************************************/
 /*                             FlushCache()                             */
 /************************************************************************/
 
@@ -182,6 +219,47 @@ void ERSDataset::FlushCache()
 }
 
 /************************************************************************/
+/*                           GetMetadataItem()                          */
+/************************************************************************/
+
+const char *ERSDataset::GetMetadataItem( const char * pszName,
+                                         const char * pszDomain )
+{
+    if (pszDomain != NULL && EQUAL(pszDomain, "ERS") && pszName != NULL)
+    {
+        if (EQUAL(pszName, "PROJ"))
+            return osProj.size() ? osProj.c_str() : NULL;
+        if (EQUAL(pszName, "DATUM"))
+            return osDatum.size() ? osDatum.c_str() : NULL;
+        if (EQUAL(pszName, "UNITS"))
+            return osUnits.size() ? osUnits.c_str() : NULL;
+    }
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **ERSDataset::GetMetadata( const char *pszDomain )
+
+{
+    if( pszDomain != NULL && EQUAL(pszDomain, "ERS") )
+    {
+        oERSMetadataList.Clear();
+        if (osProj.size())
+            oERSMetadataList.AddString(CPLSPrintf("%s=%s", "PROJ", osProj.c_str()));
+        if (osDatum.size())
+            oERSMetadataList.AddString(CPLSPrintf("%s=%s", "DATUM", osDatum.c_str()));
+        if (osUnits.size())
+            oERSMetadataList.AddString(CPLSPrintf("%s=%s", "UNITS", osUnits.c_str()));
+        return oERSMetadataList.List();
+    }
+    else
+        return GDALPamDataset::GetMetadata( pszDomain );
+}
+
+/************************************************************************/
 /*                            GetGCPCount()                             */
 /************************************************************************/
 
@@ -260,15 +338,21 @@ CPLErr ERSDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
     char szERSProj[32], szERSDatum[32], szERSUnits[32];
 
     oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
-    
+
+    /* Write the above computed values, unless they have been overriden by */
+    /* the creation options PROJ, DATUM or UNITS */
+
     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Datum", 
-                   CPLString().Printf( "\"%s\"", szERSDatum ) );
+                   CPLString().Printf( "\"%s\"",
+                        (osDatum.size()) ? osDatum.c_str() : szERSDatum ) );
     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Projection", 
-                   CPLString().Printf( "\"%s\"", szERSProj ) );
+                   CPLString().Printf( "\"%s\"",
+                        (osProj.size()) ? osProj.c_str() : szERSProj ) );
     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.CoordinateType", 
                    CPLString().Printf( "EN" ) );
     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Units", 
-                   CPLString().Printf( "\"%s\"", szERSUnits ) );
+                   CPLString().Printf( "\"%s\"",
+                        (osUnits.size()) ? osUnits.c_str() : szERSUnits ) );
     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Rotation", 
                    "0:0:0.0" );
 
@@ -337,16 +421,33 @@ CPLErr ERSDataset::SetProjection( const char *pszSRS )
     char szERSProj[32], szERSDatum[32], szERSUnits[32];
 
     oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
-    
+
+    /* Write the above computed values, unless they have been overriden by */
+    /* the creation options PROJ, DATUM or UNITS */
+    WriteProjectionInfo( (osProj.size()) ? osProj.c_str() : szERSProj,
+                         (osDatum.size()) ? osDatum.c_str() : szERSDatum,
+                         (osUnits.size()) ? osUnits.c_str() : szERSUnits );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                         WriteProjectionInfo()                        */
+/************************************************************************/
+
+void ERSDataset::WriteProjectionInfo(const char* pszProj,
+                                     const char* pszDatum,
+                                     const char* pszUnits)
+{
     bHDRDirty = TRUE;
     poHeader->Set( "CoordinateSpace.Datum", 
-                   CPLString().Printf( "\"%s\"", szERSDatum ) );
+                   CPLString().Printf( "\"%s\"", pszDatum ) );
     poHeader->Set( "CoordinateSpace.Projection", 
-                   CPLString().Printf( "\"%s\"", szERSProj ) );
+                   CPLString().Printf( "\"%s\"", pszProj ) );
     poHeader->Set( "CoordinateSpace.CoordinateType", 
                    CPLString().Printf( "EN" ) );
     poHeader->Set( "CoordinateSpace.Units", 
-                   CPLString().Printf( "\"%s\"", szERSUnits ) );
+                   CPLString().Printf( "\"%s\"", pszUnits ) );
     poHeader->Set( "CoordinateSpace.Rotation", 
                    "0:0:0.0" );
 
@@ -389,8 +490,6 @@ CPLErr ERSDataset::SetProjection( const char *pszSRS )
             poHeader->papszItemValue[i-1] = pszTemp;
         }
     }
-    
-    return CE_None;
 }
 
 /************************************************************************/
@@ -459,6 +558,7 @@ static double ERSDMS2Dec( const char *pszDMS )
 
     if( CSLCount(papszTokens) != 3 )
     {
+        CSLDestroy(papszTokens);
         return CPLAtof( pszDMS );
     }
     else
@@ -536,7 +636,8 @@ void ERSDataset::ReadGCPs()
         nItemsPerLine = 8;
     else if( nItemCount < 14 )
     {
-        CPLAssert( FALSE );
+        CPLDebug("ERS", "Invalid item count for ControlPoints");
+        CSLDestroy( papszTokens );
         return;
     }
     else if( EQUAL(papszTokens[8],"Yes") || EQUAL(papszTokens[8],"No") )
@@ -545,7 +646,8 @@ void ERSDataset::ReadGCPs()
         nItemsPerLine = 8;
     else
     {
-        CPLAssert( FALSE );
+        CPLDebug("ERS", "Invalid format for ControlPoints");
+        CSLDestroy( papszTokens );
         return;
     }
 
@@ -581,24 +683,93 @@ void ERSDataset::ReadGCPs()
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS;
 
-    CPLString osProjection = poHeader->Find( 
-        "RasterInfo.WarpControl.CoordinateSpace.Projection", "RAW" );
-    CPLString osDatum = poHeader->Find( 
-        "RasterInfo.WarpControl.CoordinateSpace.Datum", "WGS84" );
-    CPLString osUnits = poHeader->Find( 
-        "RasterInfo.WarpControl.CoordinateSpace.Units", "METERS" );
+    osProj = poHeader->Find( "RasterInfo.WarpControl.CoordinateSpace.Projection", "" );
+    osDatum = poHeader->Find( "RasterInfo.WarpControl.CoordinateSpace.Datum", "" );
+    osUnits = poHeader->Find( "RasterInfo.WarpControl.CoordinateSpace.Units", "" );
 
-    oSRS.importFromERM( osProjection, osDatum, osUnits );
+    oSRS.importFromERM( osProj.size() ? osProj : "RAW",
+                        osDatum.size() ? osDatum : "WGS84",
+                        osUnits.size() ? osUnits : "METERS" );
 
     CPLFree( pszGCPProjection );
     oSRS.exportToWkt( &pszGCPProjection );
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/* ==================================================================== */
+/*                             ERSRasterBand                            */
+/* ==================================================================== */
 /************************************************************************/
 
-GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
+class ERSRasterBand : public RawRasterBand
+{
+    public:
+
+                 ERSRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
+                                vsi_l_offset nImgOffset, int nPixelOffset,
+                                int nLineOffset,
+                                GDALDataType eDataType, int bNativeOrder,
+                                int bIsVSIL = FALSE, int bOwnsFP = FALSE );
+
+    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr SetNoDataValue( double );
+};
+
+/************************************************************************/
+/*                           ERSRasterBand()                            */
+/************************************************************************/
+
+ERSRasterBand::ERSRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
+                                vsi_l_offset nImgOffset, int nPixelOffset,
+                                int nLineOffset,
+                                GDALDataType eDataType, int bNativeOrder,
+                                int bIsVSIL, int bOwnsFP ) :
+    RawRasterBand(poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
+                  nLineOffset, eDataType, bNativeOrder, bIsVSIL, bOwnsFP)
+{
+}
+
+/************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
+
+double ERSRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    ERSDataset* poGDS = (ERSDataset*) poDS;
+    if (poGDS->bHasNoDataValue)
+    {
+        if (pbSuccess)
+            *pbSuccess = TRUE;
+        return poGDS->dfNoDataValue;
+    }
+
+    return RawRasterBand::GetNoDataValue(pbSuccess);
+}
+
+/************************************************************************/
+/*                           SetNoDataValue()                           */
+/************************************************************************/
+
+CPLErr ERSRasterBand::SetNoDataValue( double dfNoDataValue )
+{
+    ERSDataset* poGDS = (ERSDataset*) poDS;
+    if (!poGDS->bHasNoDataValue || poGDS->dfNoDataValue != dfNoDataValue)
+    {
+        poGDS->bHasNoDataValue = TRUE;
+        poGDS->dfNoDataValue = dfNoDataValue;
+
+        poGDS->bHDRDirty = TRUE;
+        poGDS->poHeader->Set( "RasterInfo.NullCellValue",
+                    CPLString().Printf( "%.16g", dfNoDataValue) );
+    }
+    return CE_None;
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int ERSDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
 /* -------------------------------------------------------------------- */
@@ -607,17 +778,30 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes > 15
         && EQUALN((const char *) poOpenInfo->pabyHeader,"Algorithm Begin",15) )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "%s appears to be an algorithm ERS file, which is not currently supported.", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "%s appears to be an algorithm ERS file, which is not currently supported.",
                   poOpenInfo->pszFilename );
-        return NULL;
+        return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      We assume the user selects the .ers file.                       */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 15 
+    if( poOpenInfo->nHeaderBytes < 15
         || !EQUALN((const char *) poOpenInfo->pabyHeader,"DatasetHeader ",14) )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if( !Identify( poOpenInfo ) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -795,7 +979,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
                 // Assume pixel interleaved.
                 poDS->SetBand( 
                     iBand+1, 
-                    new RawRasterBand( poDS, iBand+1, poDS->fpImage,
+                    new ERSRasterBand( poDS, iBand+1, poDS->fpImage,
                                        nHeaderOffset 
                                        + iWordSize * iBand * poDS->nRasterXSize,
                                        iWordSize,
@@ -857,12 +1041,13 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS;
 
-    CPLString osProjection = poHeader->Find( "CoordinateSpace.Projection", 
-                                             "RAW" );
-    CPLString osDatum = poHeader->Find( "CoordinateSpace.Datum", "WGS84" );
-    CPLString osUnits = poHeader->Find( "CoordinateSpace.Units", "METERS" );
+    poDS->osProj = poHeader->Find( "CoordinateSpace.Projection", "" );
+    poDS->osDatum = poHeader->Find( "CoordinateSpace.Datum", "" );
+    poDS->osUnits = poHeader->Find( "CoordinateSpace.Units", "" );
 
-    oSRS.importFromERM( osProjection, osDatum, osUnits );
+    oSRS.importFromERM( poDS->osProj.size() ? poDS->osProj : "RAW",
+                        poDS->osDatum.size() ? poDS->osDatum : "WGS84",
+                        poDS->osUnits.size() ? poDS->osUnits : "METERS" );
 
     CPLFree( poDS->pszProjection );
     oSRS.exportToWkt( &(poDS->pszProjection) );
@@ -870,20 +1055,19 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Look for the geotransform.                                      */
 /* -------------------------------------------------------------------- */
-    if( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", NULL )
-        && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
+    if( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", NULL ) )
     {
         poDS->bGotTransform = TRUE;
         poDS->adfGeoTransform[0] = CPLAtof( 
             poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", "" ));
         poDS->adfGeoTransform[1] = CPLAtof( 
-            poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
+            poHeader->Find( "RasterInfo.CellInfo.Xdimension", "1.0" ));
         poDS->adfGeoTransform[2] = 0.0;
         poDS->adfGeoTransform[3] = CPLAtof( 
             poHeader->Find( "RasterInfo.RegistrationCoord.Northings", "" ));
         poDS->adfGeoTransform[4] = 0.0;
         poDS->adfGeoTransform[5] = -CPLAtof( 
-            poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
+            poHeader->Find( "RasterInfo.CellInfo.Ydimension", "1.0" ));
     }
     else if( poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", NULL )
              && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
@@ -922,13 +1106,18 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poHeader->Find( "RasterInfo.NullCellValue", NULL ) )
     {
-        CPLPushErrorHandler( CPLQuietErrorHandler );
+        poDS->bHasNoDataValue = TRUE;
+        poDS->dfNoDataValue = CPLAtofM(poHeader->Find( "RasterInfo.NullCellValue" ));
 
-        for( iBand = 1; iBand <= poDS->nBands; iBand++ )
-            poDS->GetRasterBand(iBand)->SetNoDataValue(
-                CPLAtofM(poHeader->Find( "RasterInfo.NullCellValue" )) );
-        
-        CPLPopErrorHandler();
+        if (poDS->poDepFile != NULL)
+        {
+            CPLPushErrorHandler( CPLQuietErrorHandler );
+
+            for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+                poDS->GetRasterBand(iBand)->SetNoDataValue(poDS->dfNoDataValue);
+
+            CPLPopErrorHandler();
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1179,7 +1368,32 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Reopen.                                                         */
 /* -------------------------------------------------------------------- */
-    return (GDALDataset *) GDALOpen( osErsFile, GA_Update );
+    GDALOpenInfo oOpenInfo( osErsFile, GA_Update );
+    ERSDataset* poDS = (ERSDataset*) Open( &oOpenInfo );
+    if (poDS == NULL)
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Fetch DATUM, PROJ and UNITS creation option                     */
+/* -------------------------------------------------------------------- */
+    const char *pszDatum = CSLFetchNameValue( papszOptions, "DATUM" );
+    if (pszDatum)
+        poDS->osDatum = pszDatum;
+    const char *pszProj = CSLFetchNameValue( papszOptions, "PROJ" );
+    if (pszProj)
+        poDS->osProj = pszProj;
+    const char *pszUnits = CSLFetchNameValue( papszOptions, "UNITS" );
+    if (pszUnits)
+        poDS->osUnits = pszUnits;
+
+    if (pszDatum || pszProj || pszUnits)
+    {
+        poDS->WriteProjectionInfo(pszProj ? pszProj : "RAW",
+                                  pszDatum ? pszDatum : "RAW",
+                                  pszUnits ? pszUnits : "METERS");
+    }
+    
+    return poDS;
 }
 
 /************************************************************************/
@@ -1206,9 +1420,18 @@ void GDALRegister_ERS()
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
 "<CreationOptionList>"
 "   <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
+"   <Option name='PROJ' type='string' description='ERS Projection Name'/>"
+"   <Option name='DATUM' type='string' description='ERS Datum Name' />"
+"   <Option name='UNITS' type='string-select' description='ERS Projection Units'>"
+"       <Value>METERS</Value>"
+"       <Value>FEET</Value>"
+"   </Option>"
 "</CreationOptionList>" );
 
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = ERSDataset::Open;
+        poDriver->pfnIdentify = ERSDataset::Identify;
         poDriver->pfnCreate = ERSDataset::Create;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
diff --git a/frmts/ers/ershdrnode.cpp b/frmts/ers/ershdrnode.cpp
index a54fc64..5aab4d1 100644
--- a/frmts/ers/ershdrnode.cpp
+++ b/frmts/ers/ershdrnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ershdrnode.cpp 21815 2011-02-23 22:56:54Z warmerdam $
+ * $Id: ershdrnode.cpp 21814 2011-02-23 22:55:14Z warmerdam $
  *
  * Project:  ERMapper .ers Driver
  * Purpose:  Implementation of ERSHdrNode class for parsing/accessing .ers hdr.
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "ershdrnode.h"
 
-CPL_CVSID("$Id: ershdrnode.cpp 21815 2011-02-23 22:56:54Z warmerdam $");
+CPL_CVSID("$Id: ershdrnode.cpp 21814 2011-02-23 22:55:14Z warmerdam $");
 
 
 /************************************************************************/
diff --git a/frmts/ers/frmt_ers.html b/frmts/ers/frmt_ers.html
index 2ea83bb..3100f6b 100644
--- a/frmts/ers/frmt_ers.html
+++ b/frmts/ers/frmt_ers.html
@@ -11,8 +11,29 @@ GDAL supports reading and writing raster files with .ers header files, with some
 limitations.  The .ers ascii format is used by ERMapper for labelling raw 
 data files, as well as for providing extended metadata, and georeferencing 
 for some other file formats.  The .ERS format, or variants are also used to
-hold descriptions of ERMapper algorithms, but these are not supported by GDAL.
-<p>
+hold descriptions of ERMapper algorithms, but these are not supported by GDAL.<p>
+
+Starting with GDAL 1.9.0, the PROJ, DATUM and UNITS values found in the ERS header are reported
+in the ERS metadata domain.<p>
+
+<h2>Creation Issues</h2>
+
+Creation Options:<p>
+
+<ul>
+
+<li> <b>PIXELTYPE=value</b>:.By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte<p>
+
+<li> <b>PROJ=name</b>: (GDAL >= 1.9.0) Name of the ERS projection string to use.
+Common examples are NUTM11, or GEODETIC. If defined, this will override the value computed by SetProjection() or SetGCPs().<p>
+
+<li> <b>DATUM=name</b>: (GDAL >= 1.9.0) Name of the ERS datum string to use.
+Common examples are WGS84 or NAD83. If defined, this will override the value computed by SetProjection() or SetGCPs().<p>
+
+<li> <b>UNITS=name</b>: (GDAL >= 1.9.0) Name of the ERS projection units to use :
+METERS (default) or FEET (us-foot). If defined, this will override the value computed by SetProjection() or SetGCPs().<p>
+
+</ul>
 
 <h2>See Also:</h2>
 
diff --git a/frmts/fit/fitdataset.cpp b/frmts/fit/fitdataset.cpp
index 0543ad1..7233af3 100644
--- a/frmts/fit/fitdataset.cpp
+++ b/frmts/fit/fitdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fitdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -32,7 +32,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: fitdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: fitdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
  
@@ -1065,6 +1065,11 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return guard.take();
 }
 
diff --git a/frmts/fits/fitsdataset.cpp b/frmts/fits/fitsdataset.cpp
index d7f4323..2d9bc0d 100644
--- a/frmts/fits/fitsdataset.cpp
+++ b/frmts/fits/fitsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fitsdataset.cpp 21104 2010-11-08 22:17:58Z rouault $
+ * $Id: fitsdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  FITS Driver
  * Purpose:  Implement FITS raster read/write support
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include <string.h>
 
-CPL_CVSID("$Id: fitsdataset.cpp 21104 2010-11-08 22:17:58Z rouault $");
+CPL_CVSID("$Id: fitsdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 #include <fitsio.h>
@@ -508,6 +508,11 @@ GDALDataset* FITSDataset::Open(GDALOpenInfo* poOpenInfo) {
       dataset->SetDescription( poOpenInfo->pszFilename );
       dataset->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+      dataset->oOvManager.Initialize( dataset, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
       return dataset;
   }
 }
diff --git a/frmts/formats_list.html b/frmts/formats_list.html
index f1fc471..d71e758 100644
--- a/frmts/formats_list.html
+++ b/frmts/formats_list.html
@@ -27,6 +27,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#ACE2">ACE2</a>
+</td><td> ACE2
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#ADRG">ADRG/ARC Digitilized Raster Graphics (.gen/.thf)</a>
 </td><td> ADRG
 </td><td> Yes
@@ -123,6 +131,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#CTG">USGS LULC Composite Theme Grid</a>
+</td><td> CTG
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#DIMAP">Spot DIMAP (metadata.dim)</a>
 </td><td> DIMAP
 </td><td> No
@@ -171,6 +187,22 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#E00GRID">Arc/Info Export E00 GRID</a>
+</td><td> E00GRID
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
+<tr><td> <a href="frmt_various.html#ECRGTOC">ECRG Table Of Contents (TOC.xml)</a>
+</td><td> ECRGTOC
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_ecw.html">ERDAS Compressed Wavelets (.ecw)</a>
 </td><td> ECW
 </td><td> Yes
@@ -323,6 +355,14 @@
 </td><td> No, needs libgrass
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#GRASSASCIIGrid">GRASS ASCII Grid</a>
+</td><td> GRASSASCIIGrid
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#GSAG">Golden Software ASCII Grid</a>
 </td><td> GSAG
 </td><td> Yes
@@ -355,6 +395,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_gta.html">Generic Tagged Arrays (.gta)</a>
+</td><td> GTA
+</td><td> Yes
+</td><td> Yes
+</td><td>
+</td><td> No, needs libgta
+</td></tr>
+
 <tr><td> <a href="frmt_gtiff.html">TIFF / BigTIFF / GeoTIFF (.tif)</a>
 </td><td> GTiff
 </td><td> Yes
@@ -435,15 +483,15 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> USGS Astrogeology ISIS cube (Version 2)
+<tr><td> <a href="frmt_isis2.html">USGS Astrogeology ISIS cube (Version 2)</a>
 </td><td> ISIS2
-</td><td> No
+</td><td> Yes
 </td><td> Yes
 </td><td> --
 </td><td> Yes
 </td></tr>
 
-<tr><td> USGS Astrogeology ISIS cube (Version 3)
+<tr><td> <a href="frmt_isis3.html">USGS Astrogeology ISIS cube (Version 3)</a>
 </td><td> ISIS3
 </td><td> No
 </td><td> Yes
@@ -523,6 +571,22 @@
 </td><td> No, needs OpenJPEG library (v2)
 </td></tr>
 
+<tr><td> <a href="frmt_jpipkak.html">JPIP (based on Kakadu)</a>
+</td><td> JPIPKAK
+</td><td> No
+</td><td> Yes
+</td><td>
+</td><td> No, needs Kakadu library
+</td></tr>
+
+<tr><td> KMLSUPEROVERLAY
+</td><td> KMLSUPEROVERLAY
+</td><td> Yes
+</td><td> Yes
+</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
@@ -627,7 +691,15 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="frmt_nitf.html">NITF</a>
+<tr><td> <a href="frmt_ngsgeoid.html">NOAA NGS Geoid Height Grids</a>
+</td><td> NGSGEOID
+</td><td> No
+</td><td> Yes
+</td><td>
+</td><td> Yes
+</td></tr>
+
+<tr><td> <a href="frmt_nitf.html">NITF (.ntf, .nsf, .gn?, .hr?, .ja?, .jg?, .jn?, .lf?, .on?, .tl?, .tp?, etc.)</a>
 </td><td> NITF
 </td><td> Yes
 </td><td> Yes
@@ -712,10 +784,10 @@
 </td><td> No
 </td><td> Yes
 </td><td> --
-</td><td> No, needs libpoppler
+</td><td> No, needs libpoppler or libpodofo
 </td></tr>
 
-<tr><td> NASA Planetary Data System
+<tr><td> <a href="frmt_pds.html">NASA Planetary Data System</a>
 </td><td> PDS
 </td><td> No
 </td><td> Yes
@@ -787,7 +859,7 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="frmt_various.html#RPFTOC">Raster Product Format/RPF (a.toc)</a>
+<tr><td> <a href="frmt_various.html#RPFTOC">Raster Product Format/RPF (CADRG, CIB)</a>
 </td><td> RPFTOC
 </td><td> No
 </td><td> Yes
@@ -851,6 +923,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#SNODAS">Snow Data Assimilation System</a>
+</td><td> SNODAS
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#SRP">Standard Raster Product (ASRP/USRP)</a>
 </td><td> SRP
 </td><td> No
@@ -875,14 +955,6 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> Terralib
-</td><td> Terralib
-</td><td> No
-</td><td> Yes
-</td><td> --
-</td><td> No, needs Terralib
-</td></tr>
-
 <tr><td> EarthWatch/DigitalGlobe .TIL
 </td><td> TIL
 </td><td> No
@@ -915,7 +987,7 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="frmt_wcs.html">OGC Web Coverage Server</a>
+<tr><td> <a href="frmt_wcs.html">OGC Web Coverage Service</a>
 </td><td> WCS
 </td><td> No
 </td><td> Yes
@@ -923,7 +995,15 @@
 </td><td> No, needs libcurl
 </td></tr>
 
-<tr><td> <a href="frmt_wms.html">OGC Web Map Server</a>
+<tr><td> <a href="frmt_webp.html">WEBP</a>
+</td><td> WEBP
+</td><td> Yes
+</td><td> No
+</td><td> --
+</td><td> No, needs libwebp
+</td></tr>
+
+<tr><td> <a href="frmt_wms.html">OGC Web Map Service</a>
 </td><td> WMS
 </td><td> No
 </td><td> Yes
@@ -947,6 +1027,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#ZMap">ZMap Plus Grid</a>
+</td><td> ZMap
+</td><td> Yes
+</td><td> Yes
+</td><td> 
+</td><td> Yes
+</td></tr>
+
 </table>
 
 <p>
@@ -963,7 +1051,7 @@
 </p>
 
 <p>
-$Id: formats_list.html 21404 2011-01-05 01:20:33Z warmerdam $
+$Id: formats_list.html 23473 2011-12-05 22:17:02Z rouault $
 </p>
 
 </body>
diff --git a/frmts/frmt_various.html b/frmts/frmt_various.html
index 477d410..f9e300d 100644
--- a/frmts/frmt_various.html
+++ b/frmts/frmt_various.html
@@ -54,6 +54,20 @@ for Arc/Info Binary Grid format.</p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="ACE2">ACE2 -- ACE2</a></h2>
+
+<p>(GDAL >= 1.9.0)</p>
+
+<p>This is a conveniency driver to read ACE2 DEMs. Those files contain raw binary data. The
+georeferencing is entirely determined by the filename. Quality, source and confidence
+layers are of Int16 type, whereas elevation data is returned as Float32.</p>
+
+<p><a href="http://tethys.eaprs.cse.dmu.ac.uk/ACE2/shared/overview">ACE2 product overview</a></p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/raw/ace2dataset.cpp</tt>.</p>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="ADRG">ADRG/ARC Digitized Raster Graphics (.gen/.thf)</a></h2>
 <p>Supported by GDAL for read access. Creation is possible, but it must be
 considered as experimental and a means of testing read access (although files created
@@ -160,6 +174,45 @@ SAR CEOS data products.</p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="CTG">CTG -- USGS LULC Composite Theme Grid</a></h2>
+
+<p>(GDAL >= 1.9.0)</p>
+
+<p>
+This driver can read USGS Land Use and Land Cover (LULC) grids encoded in the
+Character Composite Theme Grid (CTG) format. Each file is reported as a 6-band
+dataset of type Int32. The meaning of each band is the following one :
+<ol>
+<li>Land Use and Land Cover Code</li>
+<li>Political units Code</li>
+<li>Census county subdivisions and SMSA tracts Code</li>
+<li>Hydrologic units Code</li>
+<li>Federal land ownership Code</li>
+<li>State land ownership Code</li>
+</ol>
+</p>
+<p>Those files are typically named grid_cell.gz, grid_cell1.gz or grid_cell2.gz
+on the USGS site.</p>
+<p>
+<ul>
+<li>
+<a href="http://edc2.usgs.gov/geodata/LULC/LULCDataUsersGuide.pdf">
+Land Use and Land Cover Digital Data (Data Users Guide 4)</a> - PDF version from USGS
+</li>
+<li>
+<a href="http://www.vterrain.org/Culture/LULC/Data_Users_Guide_4.html">
+Land Use and Land Cover Digital Data (Data Users Guide 4)</a> - HTML version converted by Ben Discoe
+</li>
+<li>
+<a href="http://edcftp.cr.usgs.gov/pub/data/LULC">USGS LULC data at 250K and 100K</a>
+</li>
+</ul>
+</p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/ctg/ctgdataset.cpp</tt>.</p>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="DIMAP">DIMAP -- Spot DIMAP</a></h2>
 
 <p>This is a read-only read for Spot DIMAP described images.  To use, select
@@ -216,6 +269,19 @@ USGS DOQ Standards</a></p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="E00GRID">E00GRID -- Arc/Info Export E00 GRID</a></h2>
+
+<p>(GDAL >= 1.9.0)</p>
+
+<p>GDAL supports reading DEMs/rasters exported as E00 Grids.</p>
+
+<p>The driver has been tested against datasets such as the one available on
+<a href="ftp://msdis.missouri.edu/pub/dem/24k/county/">ftp://msdis.missouri.edu/pub/dem/24k/county/</a></p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/e00grid/e00griddataset.cpp</tt>.</p>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="EHdr">EHdr -- ESRI .hdr Labelled</a></h2>
 
 <p>GDAL supports reading and writing the ESRI .hdr labelling format,
@@ -262,6 +328,34 @@ of pixel types.</p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="ECRGTOC">ECRG Table Of Contents (TOC.xml)</a></h2>
+
+Starting with GDAL 1.9.0
+
+<p>This is a read-only reader for ECRG (Enhanced Compressed Raster Graphic) products,
+that uses the table of content file, TOC.xml, and exposes it as a virtual dataset whose
+coverage is the set of ECRG frames contained in the table of content.</p>
+<p>The driver will report a different subdataset for each subdataset found in the TOC.xml
+file.</p>
+
+<p>Result of a gdalinfo on a TOC.xml file.</p>
+<pre>
+Subdatasets:
+  SUBDATASET_1_NAME=ECRG_TOC_ENTRY:ECRG:FalconView:ECRG_Sample/EPF/TOC.xml
+  SUBDATASET_1_DESC=ECRG:FalconView
+</pre>
+
+<p>See Also:</p>
+
+<ul>
+<li> <a href="frmt_nitf.html">NITF driver</a> : format of the ECRG frames</li>
+<li> <a href="http://www.everyspec.com/MIL-PRF/MIL-PRF+%28030000+-+79999%29/MIL-PRF-32283_26022/">MIL-PRF-32283</a> : specification of ECRG products</li>
+</ul>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/nitf/ecrgtocdataset.cpp</tt></p>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="EIR">EIR -- Erdas Imagine Raw</a></h2>
 
 <p>GDAL supports the Erdas Imagine Raw format for read access including 1, 2, 4, 8,
@@ -328,6 +422,10 @@ generally giving a good coverage of the dataset.  The GCPs are in WGS84.</p>
 <p>Virtually all key/value pairs from the MPH and SPH (primary and secondary
 headers) are copied through as dataset level metadata. </p>
 
+<p>ASAR and MERIS parameters contained in the ADS and GADS records (excluded
+geolocation ones) can be retrieved as key/value pairs using the "RECORDS"
+metadata domain.</p>
+
 <p>NOTE: Implemented as <tt>gdal/frmts/envisat/envisatdataset.cpp</tt>.</p>
 
 <p>See Also: <a href="http://envisat.esa.int/dataproducts/">
@@ -390,6 +488,23 @@ when provided. </p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="GRASSASCIIGrid">GRASSASCIIGrid -- GRASS ASCII Grid</a></h2>
+
+<p> (GDAL >= 1.9.0)</p>
+
+<p>Supports reading GRASS ASCII grid format (similar to Arc/Info ASCIIGRID command).</p>
+
+<p>By default, the datatype returned for GRASS ASCII grid datasets by GDAL is autodetected,
+and set to Float32 for grid with floating point values or Int32 otherwise. This is
+done by analysing the format of the null value and the first 100k bytes of data of the
+grid. You can also explictely specify the datatype by setting the
+GRASSASCIIGRID_DATATYPE configuration option (Int32, Float32 and Float64 values are
+supported currently)</p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/aaigrid/aaigriddataset.cpp</tt>.</p>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="GSAG">GSAG -- Golden Software ASCII Grid File Format</a></h2>
 
 <p>This is the ASCII-based (human-readable) version of one of the raster formats
@@ -508,8 +623,10 @@ Institute (GSI) Web Site.</a></p>
 
 <h2><a name="LAN">LAN -- Erdas 7.x .LAN and .GIS</a></h2>
 
-<p>GDAL supports reading Erdas 7.x .LAN and .GIS raster files.  Currently 
-4bit, 8bit and 16bit pixel data types are supported.  </p>
+<p>GDAL supports reading and writing
+Erdas 7.x .LAN and .GIS raster files.  Currently 
+4bit, 8bit and 16bit pixel data types are supported for reading
+and 8bit and 16bit for writing.  </p>
 
 <p>GDAL does read the map extents (geotransform) from LAN/GIS files, and 
 attempts to read the coordinate system informaton.  However, this format
@@ -753,6 +870,9 @@ various image types, and will preserve transparency/nodata values.
 Georeferencing .wld files are written if option WORLDFILE setted.  All
 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>
+
 <p>Creation Options:</p>
 
 <ul>
@@ -798,8 +918,9 @@ software which is not liberal to this value.</li>
 
 <h2><a name="RPFTOC">Raster Product Format/RPF (a.toc)</a></h2>
 
-<p>This is a read-only reader for RPF products, like CADRG or CIB, that use the table of
-content file - A.TOC - from a RPF exchange.</p>
+<p>This is a read-only reader for RPF products, like CADRG or CIB, that uses the table of
+content file - A.TOC - from a RPF exchange, and exposes it as a virtual dataset whose
+coverage is the set of frames contained in the table of content.</p>
 <p>The driver will report a different subdataset for each subdataset found in the A.TOC
 file.</p>
 
@@ -819,7 +940,7 @@ Subdatasets:
 </pre>
 
 
-<p>In some situations, NITF tiles inside a subdataset don't share the same palettes.
+<p>In some situations, <a href="frmt_nitf.html">NITF</a> tiles inside a subdataset don't share the same palettes.
 The RPFTOC driver will do its best to remap palettes to the reported palette by gdalinfo (which
 is the palette of the first tile of the subdataset).
 In situations where it wouldn't give a good result, you can try to set the RPFTOC_FORCE_RGBA
@@ -839,14 +960,10 @@ as the list of the NITF tiles of the subdataset.</p>
 
 <ul>
 <li> <a href="frmt_ogdi.html">OGDI Bridge</a> : the RPFTOC driver gives an equivalent
-     functionnality to the RPF driver from the OGDI library. </li>
-<li> <a href="RPF">MIL-PRF-89038</a> : specifications of RPF, CADRG, CIB</li>
+     functionnality (without external dependency) to the RPF driver from the OGDI library. </li>
+<li> <a href="http://www.everyspec.com/MIL-PRF/MIL-PRF+%28080000+-+99999%29/MIL-PRF-89038_25371/">MIL-PRF-89038</a> : specification of RPF, CADRG, CIB products</li>
 </ul>
 
-
-<p>This driver gives an equivalent functionnality to the RPF driver from the
-OGDI library, that can be accessed through the  <a href="frmt_ogdi.html">OGDI Bridge</a></p>
-
 <p>NOTE: Implemented as <tt>gdal/frmts/nitf/rpftocdataset.cpp</tt></p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
@@ -975,6 +1092,19 @@ created files are always RLE compressed..</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/sgi/sgidataset.cpp</tt>.</p>
 
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<h2><a name="SNODAS">SNODAS -- Snow Data Assimilation System</a></h2>
+
+<p>(GDAL >= 1.9.0)</p>
+
+<p>This is a conveniency driver to read Snow Data Assimilation System data.
+Those files contain Int16 raw binary data. The file to provide to GDAL is the .Hdr file.</p>
+
+<p><a href="http://nsidc.org/data/docs/noaa/g02158_snodas_snow_cover_model/index.html">Snow Data Assimilation System (SNODAS) Data Products at NSIDC</a></p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/raw/snodasdataset.cpp</tt>.</p>
+
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
@@ -1076,13 +1206,37 @@ to about 70 colors automatically.</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/gff/gff_dataset.cpp</tt>.</p>
 
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<h2><a name="ZMap">ZMap -- ZMap Plus Grid</a></h2>
+
+<p>(GDAL >= 1.9.0)</p>
+
+<p>
+Supported for read access and creation.
+This format is an ASCII interchange format for gridded data
+in an ASCII line format for transport and storage. It is commonly used
+in applications in the Oil and Gas Exploration field.</p>
+
+<p>By default, files are interpreted and written according to the PIXEL_IS_AREA convention.
+If you define the ZMAP_PIXEL_IS_POINT configuration option to TRUE, the PIXEL_IS_POINT
+convention will be followed to interprete/write the file (the georeferenced values in the header
+of the file will then be considered as the coordinate of the center of the pixels). Note that in that case,
+GDAL will report the extent with its usual PIXEL_IS_AREA convention (the coordinates of the topleft corner
+as reported by GDAL will be a half-pixel at the top and left of the values that appear in the file).</p>
+
+<p>Informal specification given in this <a href="http://lists.osgeo.org/pipermail/gdal-dev/2011-June/029173.html">GDAL-dev mailing list thread</a></p>
+
+<p>NOTE: Implemented as <tt>gdal/frmts/zmap/zmapdataset.cpp</tt>.</p>
+
+
 <hr>
 <p>
 <a href="formats_list.html">Full list of GDAL Raster Formats</a>
 </p>
 
 <p>
-$Id: frmt_various.html 21225 2010-12-09 19:49:33Z warmerdam $
+$Id: frmt_various.html 22861 2011-08-04 20:13:27Z rouault $
 </p>
 
 </body>
diff --git a/frmts/gdalallregister.cpp b/frmts/gdalallregister.cpp
index 78aa08f..140f9f1 100644
--- a/frmts/gdalallregister.cpp
+++ b/frmts/gdalallregister.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalallregister.cpp 21249 2010-12-13 23:43:02Z rouault $
+ * $Id: gdalallregister.cpp 23473 2011-12-05 22:17:02Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALAllRegister(), primary format registration.
@@ -30,7 +30,7 @@
 #include "gdal_priv.h"
 #include "gdal_frmts.h"
 
-CPL_CVSID("$Id: gdalallregister.cpp 21249 2010-12-13 23:43:02Z rouault $");
+CPL_CVSID("$Id: gdalallregister.cpp 23473 2011-12-05 22:17:02Z rouault $");
 
 #ifdef notdef
 // we may have a use for this some day
@@ -90,6 +90,7 @@ void CPL_STDCALL GDALAllRegister()
 #ifdef FRMT_nitf
     GDALRegister_NITF();
     GDALRegister_RPFTOC();
+    GDALRegister_ECRGTOC();
 #endif
 
 #ifdef FRMT_hfa
@@ -123,6 +124,7 @@ void CPL_STDCALL GDALAllRegister()
 
 #ifdef FRMT_aaigrid
     GDALRegister_AAIGrid();
+    GDALRegister_GRASSASCIIGrid();
 #endif
 
 #ifdef FRMT_sdts
@@ -141,6 +143,10 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_PNG();
 #endif
 
+#ifdef FRMT_gta
+    GDALRegister_GTA();
+#endif
+
 #ifdef FRMT_jpeg
     GDALRegister_JPEG();
 #endif
@@ -382,6 +388,8 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_GTX();
     GDALRegister_LOSLAS();
     GDALRegister_NTv2();
+    GDALRegister_ACE2();
+    GDALRegister_SNODAS();
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -480,6 +488,27 @@ void CPL_STDCALL GDALAllRegister()
 #ifdef FRMT_ozi
     GDALRegister_OZI();
 #endif
+
+#ifdef FRMT_ctg
+    GDALRegister_CTG();
+#endif
+
+#ifdef FRMT_e00grid
+    GDALRegister_E00GRID();
+#endif
+
+#ifdef FRMT_webp
+    GDALRegister_WEBP();
+#endif
+
+#ifdef FRMT_zmap
+    GDALRegister_ZMap();
+#endif
+
+#ifdef FRMT_ngsgeoid
+    GDALRegister_NGSGEOID();
+#endif
+
 /* -------------------------------------------------------------------- */
 /*      Deregister any drivers explicitly marked as supressed by the    */
 /*      GDAL_SKIP environment variable.                                 */
diff --git a/frmts/georaster/georaster_dataset.cpp b/frmts/georaster/georaster_dataset.cpp
index ebc35f4..70f4371 100644
--- a/frmts/georaster/georaster_dataset.cpp
+++ b/frmts/georaster/georaster_dataset.cpp
@@ -503,7 +503,7 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
     }
     else
     {
-        if( EQUAL( poGRW->sCompressionType.c_str(), "NONE" ) &&
+        if( ! EQUAL( poGRW->sCompressionType.c_str(), "NONE" ) &&
           ( nBands == 3 || nBands == 4 ) )
         {
             poGRW->nBandBlockSize = nBands;
@@ -516,6 +516,16 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
       poGRW->sInterleaving = "BIP";
     }
 
+    if( EQUALN( poGRW->sCompressionType.c_str(), "JPEG", 4 ) )
+    {
+        if( ! EQUAL( poGRW->sInterleaving.c_str(), "BIP" ) )
+        {
+            CPLError( CE_Warning, CPLE_IllegalArg, 
+                "compress=JPEG assumes interleave=BIP" );
+            poGRW->sInterleaving = "BIP";
+        }
+    }
+
     pszFetched = CSLFetchNameValue( papszOptions, "BLOCKING" );
 
     if( pszFetched )
@@ -620,19 +630,8 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         }
     }
 
-    if( EQUALN( poGRW->sCompressionType.c_str(), "DEFLATE", 4 ) )
+    if( EQUAL( poGRW->sCompressionType.c_str(), "DEFLATE" ) )
     {
-        if( poGRW->nBandBlockSize != 1 && 
-            EQUAL( poGRW->sInterleaving, "BIP" ) == false )
-        {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
-                "(COMPRESS=%s) and BLOCKBSIZE > 1 must select "
-                "INTERLEAVE as PIXEL (BIP).",
-                poGRW->sCompressionType.c_str() );
-            delete poGRD;
-            return NULL;
-        }
-
         if( ( poGRW->nColumnBlockSize * 
               poGRW->nRowBlockSize *
               poGRW->nBandBlockSize *
diff --git a/frmts/georaster/georaster_wrapper.cpp b/frmts/georaster/georaster_wrapper.cpp
index df5d760..fed4f3d 100644
--- a/frmts/georaster/georaster_wrapper.cpp
+++ b/frmts/georaster/georaster_wrapper.cpp
@@ -140,6 +140,11 @@ GeoRasterWrapper::~GeoRasterWrapper()
     {
         jpeg_destroy_compress( &sCInfo );
     }
+
+    if( poConnection )
+    {
+        delete poConnection;
+    }
 }
 
 //  ---------------------------------------------------------------------------
@@ -646,14 +651,12 @@ bool GeoRasterWrapper::Create( char* pszDescription,
 
         if( pszInsert )
         {
-            if( ! EQUALN( pszInsert, "VALUES", 6 ) )
+            sValues = pszInsert;
+
+            if( pszInsert[0] == '(' && sValues.ifind( "VALUES" ) == std::string::npos )
             {
                 sValues = CPLSPrintf( "VALUES %s", pszInsert );
             }
-            else
-            {
-                sValues = pszInsert;
-            }
         }
         else
         {
@@ -1278,10 +1281,10 @@ void GeoRasterWrapper::GetRasterInfo( void )
     //  -------------------------------------------------------------------
 
     anULTCoordinate[0] = atoi(CPLGetXMLValue( 
-            phMetadata, "rasterInfo.ULTCoordinate.row", "0"));
+            phMetadata, "rasterInfo.ULTCoordinate.column", "0"));
 
     anULTCoordinate[1] = atoi(CPLGetXMLValue( 
-            phMetadata, "rasterInfo.ULTCoordinate.column", "0"));
+            phMetadata, "rasterInfo.ULTCoordinate.row", "0"));
 
     anULTCoordinate[2] = atoi(CPLGetXMLValue( 
             phMetadata, "rasterInfo.ULTCoordinate.band", "0"));
@@ -1348,6 +1351,11 @@ void GeoRasterWrapper::GetRasterInfo( void )
                             "rasterInfo.compression.quality", "75" ) );
     }
 
+    if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
+    {
+        sInterleaving = "BIP";
+    }
+
     //  -------------------------------------------------------------------
     //  Get default RGB Bands
     //  -------------------------------------------------------------------
@@ -2564,14 +2572,14 @@ char* GeoRasterWrapper::GetVAT( int nBand )
 
 bool GeoRasterWrapper::FlushMetadata()
 {
-    if( ! bFlushMetadata )
+    if( bFlushBlock )
     {
-        return true;
+        FlushBlock( nCacheBlockId );
     }
 
-    if( bFlushBlock ) // Flush the block in cache
+    if( ! bFlushMetadata )
     {
-        FlushBlock( nCacheBlockId );
+        return true;
     }
 
     bFlushMetadata = false;
diff --git a/frmts/georaster/oci_wrapper.cpp b/frmts/georaster/oci_wrapper.cpp
index 76c1c4d..95e7406 100644
--- a/frmts/georaster/oci_wrapper.cpp
+++ b/frmts/georaster/oci_wrapper.cpp
@@ -1646,7 +1646,7 @@ const char* OWParseSDO_GEOR_INIT( const char* pszInsert, int nField )
         *pszIn = (char) toupper( *pszIn );
     }
 
-    char* pszStart = strstr( szUpcase, "SDO_GEOR.INIT" ) + strlen("SDO_GEOR.");
+    char* pszStart = strstr( szUpcase, "SDO_GEOR.INIT" );
 
     if( pszStart == NULL )
     {
@@ -1660,6 +1660,8 @@ const char* OWParseSDO_GEOR_INIT( const char* pszInsert, int nField )
         return "";
     }
 
+    pszStart += strlen("SDO_GEOR.");
+
     pszEnd++;
 
     int nLength = pszEnd - pszStart + 1;
diff --git a/frmts/gif/GNUmakefile b/frmts/gif/GNUmakefile
index 813c68b..8fd8ff9 100644
--- a/frmts/gif/GNUmakefile
+++ b/frmts/gif/GNUmakefile
@@ -5,9 +5,9 @@ ifeq ($(GIF_SETTING),internal)
 XTRA_OPT =	-Igiflib
 OBJ	=	egif_lib.o dgif_lib.o gifalloc.o gif_err.o gif_hash.o \
 		\
-		gifdataset.o biggifdataset.o
+		gifdataset.o biggifdataset.o gifabstractdataset.o
 else
-OBJ	=	gifdataset.o biggifdataset.o
+OBJ	=	gifdataset.o biggifdataset.o gifabstractdataset.o
 endif
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(XTRA_OPT)
diff --git a/frmts/gif/biggifdataset.cpp b/frmts/gif/biggifdataset.cpp
index a4127bc..e3029e5 100644
--- a/frmts/gif/biggifdataset.cpp
+++ b/frmts/gif/biggifdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: biggifdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: biggifdataset.cpp 22684 2011-07-10 19:30:49Z rouault $
  *
  * Project:  BIGGIF Driver
  * Purpose:  Implement GDAL support for reading large GIF files in a 
@@ -31,12 +31,9 @@
 
 #include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: biggifdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
-
-CPL_C_START
-#include "gif_lib.h"
-CPL_C_END
+CPL_CVSID("$Id: biggifdataset.cpp 22684 2011-07-10 19:30:49Z rouault $");
 
 CPL_C_START
 void	GDALRegister_BIGGIF(void);
@@ -49,35 +46,30 @@ static int VSIGIFReadFunc( GifFileType *, GifByteType *, int);
 
 /************************************************************************/
 /* ==================================================================== */
-/*				BIGGIFDataset				*/
+/*                          BIGGIFDataset                               */
 /* ==================================================================== */
 /************************************************************************/
 
 class BIGGifRasterBand;
 
-class BIGGIFDataset : public GDALPamDataset
+class BIGGIFDataset : public GIFAbstractDataset
 {
     friend class BIGGifRasterBand;
 
-    VSILFILE *fp;
-
-    GifFileType *hGifFile;
     int         nLastLineRead;
 
-    int	   bGeoTransformValid;
-    double adfGeoTransform[6];
-
     GDALDataset *poWorkDS;
 
     CPLErr       ReOpen();
 
+  protected:
+    virtual int         CloseDependentDatasets();
+
   public:
                  BIGGIFDataset();
                  ~BIGGIFDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
     static GDALDataset *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
 };
 
 /************************************************************************/
@@ -289,15 +281,6 @@ GDALColorTable *BIGGifRasterBand::GetColorTable()
 BIGGIFDataset::BIGGIFDataset()
 
 {
-    hGifFile = NULL;
-    fp = 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;
     nLastLineRead = -1;
     poWorkDS = NULL;
 }
@@ -310,54 +293,34 @@ BIGGIFDataset::~BIGGIFDataset()
 
 {
     FlushCache();
-    if( hGifFile )
-        DGifCloseFile( hGifFile );
-    if( fp != NULL )
-        VSIFCloseL( fp );
 
-    if( poWorkDS != NULL )
-    {
-        CPLString osTempFilename = poWorkDS->GetDescription();
-
-        GDALClose( (GDALDatasetH) poWorkDS );
-        poWorkDS = NULL;
-
-        GDALDriver *poGTiff = (GDALDriver *) GDALGetDriverByName( "GTiff" );
-        poGTiff->Delete( osTempFilename );
-    }
+    CloseDependentDatasets();
 }
 
 /************************************************************************/
-/*                          GetGeoTransform()                           */
+/*                      CloseDependentDatasets()                        */
 /************************************************************************/
 
-CPLErr BIGGIFDataset::GetGeoTransform( double * padfTransform )
-
+int BIGGIFDataset::CloseDependentDatasets()
 {
-    if( bGeoTransformValid )
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
+    if( poWorkDS != NULL )
     {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-        return CE_None;
-    }
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-}
+        bHasDroppedRef = TRUE;
 
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
+        CPLString osTempFilename = poWorkDS->GetDescription();
 
-int BIGGIFDataset::Identify( GDALOpenInfo * poOpenInfo )
+        GDALClose( (GDALDatasetH) poWorkDS );
+        poWorkDS = NULL;
 
-{
-    if( poOpenInfo->nHeaderBytes < 8 )
-        return FALSE;
+        GDALDriver *poGTiff = (GDALDriver *) GDALGetDriverByName( "GTiff" );
+        poGTiff->Delete( osTempFilename );
 
-    if( strncmp((const char *) poOpenInfo->pabyHeader, "GIF87a",5) != 0
-        && strncmp((const char *) poOpenInfo->pabyHeader, "GIF89a",5) != 0 )
-        return FALSE;
+        poWorkDS = NULL;
+    }
 
-    return TRUE;
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -424,7 +387,22 @@ CPLErr BIGGIFDataset::ReOpen()
 
     while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR
            && RecordType != TERMINATE_RECORD_TYPE
-           && RecordType != IMAGE_DESC_RECORD_TYPE ) {}
+           && RecordType != IMAGE_DESC_RECORD_TYPE )
+    {
+        /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
+        if (RecordType == EXTENSION_RECORD_TYPE)
+        {
+            int nFunction;
+            GifByteType *pExtData;
+            if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
+                break;
+            while (pExtData != NULL)
+            {
+                if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
+                    break;
+            }
+        }
+    }
 
     if( RecordType != IMAGE_DESC_RECORD_TYPE )
     {
@@ -507,13 +485,9 @@ GDALDataset *BIGGIFDataset::Open( GDALOpenInfo * poOpenInfo )
                                          poDS->hGifFile->SBackGroundColor ));
 
 /* -------------------------------------------------------------------- */
-/*      Check for world file.                                           */
+/*      Check for georeferencing.                                       */
 /* -------------------------------------------------------------------- */
-    poDS->bGeoTransformValid = 
-        GDALReadWorldFile( poOpenInfo->pszFilename, NULL, 
-                           poDS->adfGeoTransform )
-        || GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
-                              poDS->adfGeoTransform );
+    poDS->DetectGeoreferencing(poOpenInfo);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -566,7 +540,7 @@ void GDALRegister_BIGGIF()
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = BIGGIFDataset::Open;
-        poDriver->pfnIdentify = BIGGIFDataset::Identify;
+        poDriver->pfnIdentify = GIFAbstractDataset::Identify;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/gif/frmt_gif.html b/frmts/gif/frmt_gif.html
index 1979cad..fdb0e30 100644
--- a/frmts/gif/frmt_gif.html
+++ b/frmts/gif/frmt_gif.html
@@ -18,6 +18,9 @@ be returned as the NoData value for the band.<p>
 If an ESRI world file exists with the .gfw, .gifw or .wld extension, it will be read and
 used to establish the geotransform for the image.<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>Creation Issues</h2>
 
 GIF files can only be created as 1 8bit band using the "CreateCopy" mechanism.
diff --git a/frmts/gif/gifabstractdataset.cpp b/frmts/gif/gifabstractdataset.cpp
new file mode 100644
index 0000000..43ac269
--- /dev/null
+++ b/frmts/gif/gifabstractdataset.cpp
@@ -0,0 +1,354 @@
+/******************************************************************************
+ * $Id: gifabstractdataset.cpp 22685 2011-07-10 19:31:35Z 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>
+ *
+ * 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 "gifabstractdataset.h"
+
+CPL_CVSID("$Id: gifabstractdataset.cpp 22685 2011-07-10 19:31:35Z rouault $");
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         GIFAbstractDataset                           */
+/* ==================================================================== */
+/************************************************************************/
+
+
+/************************************************************************/
+/*                         GIFAbstractDataset()                         */
+/************************************************************************/
+
+GIFAbstractDataset::GIFAbstractDataset()
+
+{
+    hGifFile = NULL;
+    fp = NULL;
+
+    pszProjection = 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;
+
+    nGCPCount = 0;
+    pasGCPList = NULL;
+
+    bHasReadXMPMetadata = FALSE;
+}
+
+/************************************************************************/
+/*                        ~GIFAbstractDataset()                         */
+/************************************************************************/
+
+GIFAbstractDataset::~GIFAbstractDataset()
+
+{
+    FlushCache();
+
+    if ( pszProjection )
+        CPLFree( pszProjection );
+
+    if ( nGCPCount > 0 )
+    {
+        GDALDeinitGCPs( nGCPCount, pasGCPList );
+        CPLFree( pasGCPList );
+    }
+
+    if( hGifFile )
+        DGifCloseFile( hGifFile );
+
+    if( fp != NULL )
+        VSIFCloseL( fp );
+}
+
+
+/************************************************************************/
+/*                       GIFCollectXMPMetadata()                        */
+/************************************************************************/
+
+/* See §2.1.2 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
+
+static CPLString GIFCollectXMPMetadata(VSILFILE* fp)
+
+{
+    CPLString osXMP;
+
+    /* Save current position to avoid disturbing GIF stream decoding */
+    vsi_l_offset nCurOffset = VSIFTellL(fp);
+
+    char abyBuffer[2048+1];
+
+    VSIFSeekL( fp, 0, SEEK_SET );
+
+    /* Loop over file */
+
+    int iStartSearchOffset = 1024;
+    while(TRUE)
+    {
+        int nRead = VSIFReadL( abyBuffer + 1024, 1, 1024, fp );
+        if (nRead <= 0)
+            break;
+        abyBuffer[1024 + nRead] = 0;
+
+        int i;
+        int iFoundOffset = -1;
+        for(i=iStartSearchOffset;i<1024+nRead - 14;i++)
+        {
+            if (memcmp(abyBuffer + i, "\x21\xff\x0bXMP DataXMP", 14) == 0)
+            {
+                iFoundOffset = i + 14;
+                break;
+            }
+        }
+
+        iStartSearchOffset = 0;
+
+        if (iFoundOffset >= 0)
+        {
+            int nSize = 1024 + nRead - iFoundOffset;
+            char* pszXMP = (char*)VSIMalloc(nSize + 1);
+            if (pszXMP == NULL)
+                break;
+
+            pszXMP[nSize] = 0;
+            memcpy(pszXMP, abyBuffer + iFoundOffset, nSize);
+
+            /* Read from file until we find a NUL character */
+            int nLen = (int)strlen(pszXMP);
+            while(nLen == nSize)
+            {
+                char* pszNewXMP = (char*)VSIRealloc(pszXMP, nSize + 1024 + 1);
+                if (pszNewXMP == NULL)
+                    break;
+                pszXMP = pszNewXMP;
+
+                nRead = VSIFReadL( pszXMP + nSize, 1, 1024, fp );
+                if (nRead <= 0)
+                    break;
+
+                pszXMP[nSize + nRead] = 0;
+                nLen += (int)strlen(pszXMP + nSize);
+                nSize += nRead;
+            }
+
+            if (nLen > 256 && pszXMP[nLen - 1] == '\x01' &&
+                pszXMP[nLen - 2] == '\x02' && pszXMP[nLen - 255] == '\xff' &&
+                pszXMP[nLen - 256] == '\x01')
+            {
+                pszXMP[nLen - 256] = 0;
+
+                osXMP = pszXMP;
+            }
+
+            VSIFree(pszXMP);
+
+            break;
+        }
+
+        if (nRead != 1024)
+            break;
+
+        memcpy(abyBuffer, abyBuffer + 1024, 1024);
+    }
+
+    VSIFSeekL( fp, nCurOffset, SEEK_SET );
+
+    return osXMP;
+}
+
+/************************************************************************/
+/*                       CollectXMPMetadata()                           */
+/************************************************************************/
+
+void GIFAbstractDataset::CollectXMPMetadata()
+
+{
+    if (fp == NULL || bHasReadXMPMetadata)
+        return;
+
+    CPLString osXMP = GIFCollectXMPMetadata(fp);
+    if (osXMP.size())
+    {
+        /* Avoid setting the PAM dirty bit just for that */
+        int nOldPamFlags = nPamFlags;
+
+        char *apszMDList[2];
+        apszMDList[0] = (char*) osXMP.c_str();
+        apszMDList[1] = NULL;
+        SetMetadata(apszMDList, "xml:XMP");
+
+        nPamFlags = nOldPamFlags;
+    }
+
+    bHasReadXMPMetadata = TRUE;
+}
+
+/************************************************************************/
+/*                           GetMetadata()                              */
+/************************************************************************/
+
+char  **GIFAbstractDataset::GetMetadata( const char * pszDomain )
+{
+    if (fp == NULL)
+        return NULL;
+    if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
+        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        CollectXMPMetadata();
+    return GDALPamDataset::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                       GetMetadataItem()                              */
+/************************************************************************/
+
+const char *GIFAbstractDataset::GetMetadataItem( const char * pszName,
+                                         const char * pszDomain )
+{
+    if (fp == NULL)
+        return NULL;
+    if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
+        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        CollectXMPMetadata();
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                        GetProjectionRef()                            */
+/************************************************************************/
+
+const char *GIFAbstractDataset::GetProjectionRef()
+
+{
+    if ( pszProjection && bGeoTransformValid )
+        return pszProjection;
+    else
+        return GDALPamDataset::GetProjectionRef();
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr GIFAbstractDataset::GetGeoTransform( double * padfTransform )
+
+{
+    if( bGeoTransformValid )
+    {
+        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
+        return CE_None;
+    }
+    else
+        return GDALPamDataset::GetGeoTransform( padfTransform );
+}
+
+/************************************************************************/
+/*                            GetGCPCount()                             */
+/************************************************************************/
+
+int GIFAbstractDataset::GetGCPCount()
+
+{
+    if (nGCPCount > 0)
+        return nGCPCount;
+    else
+        return GDALPamDataset::GetGCPCount();
+}
+
+/************************************************************************/
+/*                          GetGCPProjection()                          */
+/************************************************************************/
+
+const char *GIFAbstractDataset::GetGCPProjection()
+
+{
+    if ( pszProjection && nGCPCount > 0 )
+        return pszProjection;
+    else
+        return GDALPamDataset::GetGCPProjection();
+}
+
+/************************************************************************/
+/*                               GetGCPs()                              */
+/************************************************************************/
+
+const GDAL_GCP *GIFAbstractDataset::GetGCPs()
+
+{
+    if (nGCPCount > 0)
+        return pasGCPList;
+    else
+        return GDALPamDataset::GetGCPs();
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int GIFAbstractDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    if( poOpenInfo->nHeaderBytes < 8 )
+        return FALSE;
+
+    if( strncmp((const char *) poOpenInfo->pabyHeader, "GIF87a",5) != 0
+        && strncmp((const char *) poOpenInfo->pabyHeader, "GIF89a",5) != 0 )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         DetectGeoreferencing()                       */
+/************************************************************************/
+
+void GIFAbstractDataset::DetectGeoreferencing( GDALOpenInfo * poOpenInfo )
+{
+    bGeoTransformValid =
+        GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
+                           adfGeoTransform );
+    if ( !bGeoTransformValid )
+    {
+        bGeoTransformValid =
+            GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
+                               adfGeoTransform );
+
+        if ( !bGeoTransformValid )
+        {
+            int bOziFileOK =
+                GDALReadOziMapFile( poOpenInfo->pszFilename,
+                                    adfGeoTransform,
+                                    &pszProjection,
+                                    &nGCPCount, &pasGCPList );
+
+            if ( bOziFileOK && nGCPCount == 0 )
+                 bGeoTransformValid = TRUE;
+        }
+    }
+}
diff --git a/frmts/gif/gifabstractdataset.h b/frmts/gif/gifabstractdataset.h
new file mode 100644
index 0000000..2be97fb
--- /dev/null
+++ b/frmts/gif/gifabstractdataset.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ * $Id: gifabstractdataset.h 22685 2011-07-10 19:31:35Z 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>
+ *
+ * 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 _GIFABSTRACTDATASET_H_INCLUDED
+#define _GIFABSTRACTDATASET_H_INCLUDED
+
+#include "gdal_pam.h"
+
+CPL_C_START
+#include "gif_lib.h"
+CPL_C_END
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        GIFAbstractDataset                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class GIFAbstractDataset : public GDALPamDataset
+{
+  protected:
+    VSILFILE        *fp;
+
+    GifFileType *hGifFile;
+
+    char        *pszProjection;
+    int         bGeoTransformValid;
+    double      adfGeoTransform[6];
+
+    int         nGCPCount;
+    GDAL_GCP    *pasGCPList;
+
+    int         bHasReadXMPMetadata;
+    void        CollectXMPMetadata();
+
+    void        DetectGeoreferencing( GDALOpenInfo * poOpenInfo );
+
+  public:
+                 GIFAbstractDataset();
+                 ~GIFAbstractDataset();
+
+    virtual const char *GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * );
+    virtual int    GetGCPCount();
+    virtual const char *GetGCPProjection();
+    virtual const GDAL_GCP *GetGCPs();
+
+    virtual char  **GetMetadata( const char * pszDomain = "" );
+    virtual const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain = "" );
+
+    static int          Identify( GDALOpenInfo * );
+};
+
+
+#endif
diff --git a/frmts/gif/gifdataset.cpp b/frmts/gif/gifdataset.cpp
index bd01a0c..c89f34c 100644
--- a/frmts/gif/gifdataset.cpp
+++ b/frmts/gif/gifdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gifdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gifdataset.cpp 23621 2011-12-20 23:26:56Z rouault $
  *
  * Project:  GIF Driver
  * Purpose:  Implement GDAL GIF Support using libungif code.  
@@ -29,12 +29,9 @@
 
 #include "gdal_pam.h"
 #include "cpl_string.h"
+#include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
-
-CPL_C_START
-#include "gif_lib.h"
-CPL_C_END
+CPL_CVSID("$Id: gifdataset.cpp 23621 2011-12-20 23:26:56Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GIF(void);
@@ -51,38 +48,27 @@ static int VSIGIFWriteFunc( GifFileType *, const GifByteType *, int );
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GIFDataset				*/
+/*	                            GIFDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
 class GIFRasterBand;
 
-class GIFDataset : public GDALPamDataset
+class GIFDataset : public GIFAbstractDataset
 {
     friend class GIFRasterBand;
 
-    VSILFILE        *fp;
-
-    GifFileType *hGifFile;
-
-    char        *pszProjection;
-    int	        bGeoTransformValid;
-    double      adfGeoTransform[6];
-
-    int         nGCPCount;
-    GDAL_GCP	*pasGCPList;
-
   public:
                  GIFDataset();
-                 ~GIFDataset();
 
-    virtual const char *GetProjectionRef();
-    virtual CPLErr GetGeoTransform( double * );
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
     static GDALDataset *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
+
+    static GDALDataset* CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
+
 };
 
 /************************************************************************/
@@ -133,6 +119,13 @@ GIFRasterBand::GIFRasterBand( GIFDataset *poDS, int nBand,
 
     psImage = psSavedImage;
 
+    poColorTable = NULL;
+    panInterlaceMap = NULL;
+    nTransparentColor = 0;
+
+    if (psImage == NULL)
+        return;
+
 /* -------------------------------------------------------------------- */
 /*      Setup interlacing map if required.                              */
 /* -------------------------------------------------------------------- */
@@ -237,6 +230,12 @@ CPLErr GIFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 {
     CPLAssert( nBlockXOff == 0 );
 
+    if (psImage == NULL)
+    {
+        memset(pImage, 0, nBlockXSize);
+        return CE_None;
+    }
+
     if( panInterlaceMap != NULL )
         nBlockYOff = panInterlaceMap[nBlockYOff];
 
@@ -291,132 +290,7 @@ double GIFRasterBand::GetNoDataValue( int *pbSuccess )
 /************************************************************************/
 
 GIFDataset::GIFDataset()
-
-{
-    hGifFile = NULL;
-    fp = NULL;
-
-    pszProjection = 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;
-
-    nGCPCount = 0;
-    pasGCPList = NULL;
-}
-
-/************************************************************************/
-/*                           ~GIFDataset()                            */
-/************************************************************************/
-
-GIFDataset::~GIFDataset()
-
-{
-    FlushCache();
-
-    if ( pszProjection )
-        CPLFree( pszProjection );
-
-    if ( nGCPCount > 0 )
-    {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
-    }
-
-    if( hGifFile )
-        DGifCloseFile( hGifFile );
-
-    if( fp != NULL )
-        VSIFCloseL( fp );
-}
-
-/************************************************************************/
-/*                        GetProjectionRef()                            */
-/************************************************************************/
-
-const char *GIFDataset::GetProjectionRef()
-
 {
-    if ( pszProjection && bGeoTransformValid )
-        return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr GIFDataset::GetGeoTransform( double * padfTransform )
-
-{
-    if( bGeoTransformValid )
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-        return CE_None;
-    }
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
-}
-
-/************************************************************************/
-/*                            GetGCPCount()                             */
-/************************************************************************/
-
-int GIFDataset::GetGCPCount()
-
-{
-    if (nGCPCount > 0)
-        return nGCPCount;
-    else
-        return GDALPamDataset::GetGCPCount();
-}
-
-/************************************************************************/
-/*                          GetGCPProjection()                          */
-/************************************************************************/
-
-const char *GIFDataset::GetGCPProjection()
-
-{
-    if ( pszProjection && nGCPCount > 0 )
-        return pszProjection;
-    else
-        return GDALPamDataset::GetGCPProjection();
-}
-
-/************************************************************************/
-/*                               GetGCPs()                              */
-/************************************************************************/
-
-const GDAL_GCP *GIFDataset::GetGCPs()
-
-{
-    if (nGCPCount > 0)
-        return pasGCPList;
-    else
-        return GDALPamDataset::GetGCPs();
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-int GIFDataset::Identify( GDALOpenInfo * poOpenInfo )
-
-{
-    if( poOpenInfo->nHeaderBytes < 8 )
-        return FALSE;
-
-    if( strncmp((const char *) poOpenInfo->pabyHeader, "GIF87a",5) != 0
-        && strncmp((const char *) poOpenInfo->pabyHeader, "GIF89a",5) != 0 )
-        return FALSE;
-
-    return TRUE;
 }
 
 /************************************************************************/
@@ -470,7 +344,22 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR
         && RecordType != TERMINATE_RECORD_TYPE
-        && RecordType != IMAGE_DESC_RECORD_TYPE ) {}
+        && RecordType != IMAGE_DESC_RECORD_TYPE )
+    {
+        /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
+        if (RecordType == EXTENSION_RECORD_TYPE)
+        {
+            int nFunction;
+            GifByteType *pExtData;
+            if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
+                break;
+            while (pExtData != NULL)
+            {
+                if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
+                    break;
+            }
+        }
+    }
 
     if( RecordType == IMAGE_DESC_RECORD_TYPE  &&
         DGifGetImageDesc(hGifFile) != GIF_ERROR)
@@ -505,7 +394,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     nGifErr = DGifSlurp( hGifFile );
 
-    if( nGifErr != GIF_OK )
+    if( nGifErr != GIF_OK || hGifFile->SavedImages == NULL )
     {
         VSIFCloseL( fp );
         DGifCloseFile(hGifFile);
@@ -562,29 +451,9 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Check for world file.                                           */
+/*      Check for georeferencing.                                       */
 /* -------------------------------------------------------------------- */
-    poDS->bGeoTransformValid = 
-        GDALReadWorldFile( poOpenInfo->pszFilename, NULL, 
-                           poDS->adfGeoTransform );
-    if ( !poDS->bGeoTransformValid )
-    {
-        poDS->bGeoTransformValid =
-            GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
-                               poDS->adfGeoTransform );
-
-        if ( !poDS->bGeoTransformValid )
-        {
-            int bOziFileOK = 
-                GDALReadOziMapFile( poOpenInfo->pszFilename,
-                                    poDS->adfGeoTransform, 
-                                    &poDS->pszProjection,
-                                    &poDS->nGCPCount, &poDS->pasGCPList );
-
-            if ( bOziFileOK && poDS->nGCPCount == 0 )
-                 poDS->bGeoTransformValid = TRUE;
-        }
-    }
+    poDS->DetectGeoreferencing(poOpenInfo);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -601,11 +470,11 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
-/*                           GIFCreateCopy()                            */
+/*                             CreateCopy()                             */
 /************************************************************************/
 
-static GDALDataset *
-GIFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
+GDALDataset *
+GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
                int bStrict, char ** papszOptions, 
                GDALProgressFunc pfnProgress, void * pProgressData )
 
@@ -657,7 +526,7 @@ GIFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     GifFileType *hGifFile;
     VSILFILE *fp;
 
-    fp = VSIFOpenL( pszFilename, "w" );
+    fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
@@ -848,23 +717,6 @@ GIFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
     hGifFile = NULL;
 
-    /* This is a hack to write a GIF89a instead of GIF87a */
-    /* (we have to, since we are using graphical extension block) */
-    /* EGifSpew would write GIF89a when it detects an extension block if we were using it */
-    /* As we don't, we could have used EGifSetGifVersion instead, but the version of libungif */
-    /* in GDAL has a bug : it writes on read-only memory ! */
-    /* (this is a well-known problem. Just google for "EGifSetGifVersion segfault") */
-    /* Most readers don't even care if it is GIF87a or GIF89a, but it is */
-    /* better to write the right version */
-
-    VSIFSeekL(fp, 0, SEEK_SET);
-    if (VSIFWriteL("GIF89a", 1, 6, fp) != 6)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Error writing gif file." );
-        goto error;
-    }
-
     VSIFCloseL( fp );
     fp = NULL;
 
@@ -882,13 +734,28 @@ GIFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxilary pam information.         */
 /* -------------------------------------------------------------------- */
-    poDS = (GDALPamDataset *) 
-        GDALOpen( pszFilename, GA_ReadOnly );
 
-    if( poDS )
+    /* If outputing to stdout, we can't reopen it, so we'll return */
+    /* a fake dataset to make the caller happy */
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
+    CPLPopErrorHandler();
+    if (poDS)
+    {
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
-
-    return poDS;
+        return poDS;
+    }
+    else
+    {
+        CPLErrorReset();
+
+        GIFDataset* poGIF_DS = new GIFDataset();
+        poGIF_DS->nRasterXSize = nXSize;
+        poGIF_DS->nRasterYSize = nYSize;
+        for(int i=0;i<nBands;i++)
+            poGIF_DS->SetBand( i+1, new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) );
+        return poGIF_DS;
+    }
 
 error:
     if (hGifFile)
@@ -924,8 +791,25 @@ static int VSIGIFWriteFunc( GifFileType *psGFile,
                             const GifByteType *pabyBuffer, int nBytesToWrite )
 
 {
-    return VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite, 
-                       (VSILFILE *) psGFile->UserData );
+    VSILFILE* fp = (VSILFILE *) psGFile->UserData;
+    if ( VSIFTellL(fp) == 0 && nBytesToWrite >= 6 &&
+         memcmp(pabyBuffer, "GIF87a", 6) == 0 )
+    {
+        /* This is a hack to write a GIF89a instead of GIF87a */
+        /* (we have to, since we are using graphical extension block) */
+        /* EGifSpew would write GIF89a when it detects an extension block if we were using it */
+        /* As we don't, we could have used EGifSetGifVersion instead, but the version of libungif */
+        /* in GDAL has a bug : it writes on read-only memory ! */
+        /* (this is a well-known problem. Just google for "EGifSetGifVersion segfault") */
+        /* Most readers don't even care if it is GIF87a or GIF89a, but it is */
+        /* better to write the right version */
+
+        int nRet = VSIFWriteL("GIF89a", 1, 6, fp);
+        nRet += VSIFWriteL( (char *) pabyBuffer + 6, 1, nBytesToWrite - 6, fp );
+        return nRet;
+    }
+    else
+        return VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite, fp );
 }
 
 /************************************************************************/
@@ -960,8 +844,8 @@ void GDALRegister_GIF()
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = GIFDataset::Open;
-        poDriver->pfnCreateCopy = GIFCreateCopy;
-        poDriver->pfnIdentify = GIFDataset::Identify;
+        poDriver->pfnCreateCopy = GIFDataset::CreateCopy;
+        poDriver->pfnIdentify = GIFAbstractDataset::Identify;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/gif/giflib/makefile.vc b/frmts/gif/giflib/makefile.vc
index 59103d1..0f36be0 100644
--- a/frmts/gif/giflib/makefile.vc
+++ b/frmts/gif/giflib/makefile.vc
@@ -6,6 +6,8 @@ GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
+EXTRAFLAGS =	$(SOFTWARNFLAGS)
+
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\..\o
 
diff --git a/frmts/gif/makefile.vc b/frmts/gif/makefile.vc
index da83f3b..7ed85c8 100644
--- a/frmts/gif/makefile.vc
+++ b/frmts/gif/makefile.vc
@@ -1,6 +1,6 @@
 
 OBJ	=	\
-	gifdataset.obj biggifdataset.obj
+	gifdataset.obj biggifdataset.obj gifabstractdataset.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/grib/degrib18/degrib/degrib1.cpp b/frmts/grib/degrib18/degrib/degrib1.cpp
index 0134d34..759caee 100644
--- a/frmts/grib/degrib18/degrib/degrib1.cpp
+++ b/frmts/grib/degrib18/degrib/degrib1.cpp
@@ -1797,6 +1797,11 @@ int ReadGrib1Record (DataSource &fp, sChar f_unit, double **Grib_Data,
       *grib_DataLen = meta->gds.numPts;
       *Grib_Data = (double *) realloc ((void *) (*Grib_Data),
                                        (*grib_DataLen) * sizeof (double));
+      if (!(*Grib_Data))
+      {
+        *grib_DataLen = 0;
+        return -1;
+      }
    }
    grib_Data = *Grib_Data;
 
diff --git a/frmts/grib/degrib18/degrib/makefile.vc b/frmts/grib/degrib18/degrib/makefile.vc
index 137b8f9..b96a23a 100644
--- a/frmts/grib/degrib18/degrib/makefile.vc
+++ b/frmts/grib/degrib18/degrib/makefile.vc
@@ -1,6 +1,6 @@
 OBJ = clock.obj degrib1.obj degrib2.obj inventory.obj metaname.obj myerror.obj tdlpack.obj filedatasource.obj memorydatasource.obj grib1tab.obj myutil.obj metaparse.obj weather.obj metaprint.obj engribapi.obj grib2api.obj myassert.obj scan.obj memendian.obj fileendian.obj
 
-EXTRAFLAGS = -I ../g2clib-1.0.4
+EXTRAFLAGS = -I ../g2clib-1.0.4 $(SOFTWARNFLAGS)
 
 GDAL_ROOT       =       ..\..\..\..
 
diff --git a/frmts/grib/degrib18/degrib/memorydatasource.cpp b/frmts/grib/degrib18/degrib/memorydatasource.cpp
index 3a844c7..7b21bca 100644
--- a/frmts/grib/degrib18/degrib/memorydatasource.cpp
+++ b/frmts/grib/degrib18/degrib/memorydatasource.cpp
@@ -1,5 +1,6 @@
 #include "memorydatasource.h"
 #include <memory.h>
+#include <string.h>
 
 MemoryDataSource::MemoryDataSource(unsigned char * block, long length)
 : seekPos(0)
diff --git a/frmts/grib/degrib18/degrib/metaname.cpp b/frmts/grib/degrib18/degrib/metaname.cpp
index 321b6da..a566210 100644
--- a/frmts/grib/degrib18/degrib/metaname.cpp
+++ b/frmts/grib/degrib18/degrib/metaname.cpp
@@ -2459,8 +2459,8 @@ void ParseLevelName (unsigned short int center, unsigned short int subcenter,
                      char **longLevelName)
 {
    int f_reserved;
-   char valBuff[20];
-   char sndBuff[20];
+   char valBuff[512];
+   char sndBuff[512];
    GRIB2SurfTable surf = Table45Index (surfType, &f_reserved, center,
                                        subcenter);
 
diff --git a/frmts/grib/degrib18/degrib/myutil.c b/frmts/grib/degrib18/degrib/myutil.c
index 88d58ac..a9f20a4 100644
--- a/frmts/grib/degrib18/degrib/myutil.c
+++ b/frmts/grib/degrib18/degrib/myutil.c
@@ -21,6 +21,20 @@
 #include "myutil.h"
 #include "myassert.h"
 
+/* Android compat */
+#ifndef S_IREAD
+#define S_IREAD S_IRUSR
+#endif
+
+#ifndef S_IWRITE
+#define S_IWRITE S_IWUSR
+#endif
+
+#ifndef S_IEXEC
+#define S_IEXEC S_IXUSR
+#endif
+/* End of Android compat */
+
 #ifdef MEMWATCH
 #include "memwatch.h"
 #endif
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp b/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
index 703fabb..6cdd095 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
+++ b/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
@@ -1,3 +1,5 @@
+#include <cpl_port.h>
+
 #include "grib2.h"
 
 #include <stdio.h>
@@ -12,8 +14,6 @@
 /* ==================================================================== */
 /* -------------------------------------------------------------------- */
 
-#include <cpl_port.h>
-
 #ifdef HAVE_JASPER
 #include <jasper/jasper.h>
 #define JAS_1_700_2
@@ -85,20 +85,9 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
                     osFileName, (unsigned char*)injpc, bufsize, 
                     FALSE ) ); // TRUE to let vsi delete the buffer when done
 
-/* -------------------------------------------------------------------- */
-/*      Currently the JP2ECW driver doesn't support /vsimem and         */
-/*      other virtual files *unless* we force processing to go          */
-/*      through J2K_SUBFILE.  Grr.  It would be ideal to fix this in    */
-/*      the ECW driver eventually.                                      */
-/* -------------------------------------------------------------------- */
-    CPLString osSubfileName;
-
-    osSubfileName.Printf( "J2K_SUBFILE:%d,%d,%s", 
-                          0, bufsize, osFileName.c_str() );
-
     // Open memory buffer for reading 
     GDALDataset* poJ2KDataset = (GDALDataset *)
-        GDALOpen( osSubfileName, GA_ReadOnly );
+        GDALOpen( osFileName, GA_ReadOnly );
  
     if( poJ2KDataset == NULL )
     {
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc b/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc
index 27f44c1..43be202 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc
+++ b/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc
@@ -2,7 +2,7 @@ OBJ = gridtemplates.obj drstemplates.obj pdstemplates.obj gbits.obj g2_free.obj
 	dec_jpeg2000.obj jpcunpack.obj jpcpack.obj enc_jpeg2000.obj
 	
 
-EXTRAFLAGS = -I ../../../png/libpng -I ../../../zlib -DUSE_PNG
+EXTRAFLAGS = -I ../../../png/libpng -I ../../../zlib -DUSE_PNG $(SOFTWARNFLAGS)
 
 GDAL_ROOT       =       ..\..\..\..
 
diff --git a/frmts/grib/frmt_grib.html b/frmts/grib/frmt_grib.html
index 1e964bc..28ec9c3 100644
--- a/frmts/grib/frmt_grib.html
+++ b/frmts/grib/frmt_grib.html
@@ -49,6 +49,17 @@ as metadata like this:
     GRIB_PDS_TEMPLATE_NUMBERS=3 5 2 0 105 0 0 0 1 0 0 0 1 100 0 0 1 134 160 255 0 0 0 0 0
 </pre>
 
+<h2>Configuration options</h2>
+
+<p>
+
+This paragraph lists the configuration options that can be set to alter the default behaviour of the GRIB driver.
+
+<ul>
+<li>GRIB_NORMALIZE_UNITS : (GDAL >= 1.9.0) Can be set to NO to avoid gdal to normalize units to metric.</li>
+</ul>
+</p>
+
 <h2>Known issues:</h2>
 
 The library that GDAL uses to read GRIB files is known to be not thread-safe, so you should avoid
diff --git a/frmts/grib/gribdataset.cpp b/frmts/grib/gribdataset.cpp
index ead069a..e2fcb78 100644
--- a/frmts/grib/gribdataset.cpp
+++ b/frmts/grib/gribdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gribdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gribdataset.cpp 23302 2011-11-02 16:07:04Z aboudreault $
  *
  * Project:  GRIB Driver
  * Purpose:  GDALDataset driver for GRIB translator for read support
@@ -40,7 +40,7 @@
 
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gribdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: gribdataset.cpp 23302 2011-11-02 16:07:04Z aboudreault $");
 
 CPL_C_START
 void	GDALRegister_GRIB(void);
@@ -238,7 +238,7 @@ CPLErr GRIBRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 
 {
-    if (!m_Grib_Data)
+    if( !m_Grib_Data )
     {
         GRIBDataset *poGDS = (GRIBDataset *) poDS;
 
@@ -246,6 +246,11 @@ CPLErr GRIBRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         // we don't seem to have any way to detect errors in this!
         ReadGribData(grib_fp, start, subgNum, &m_Grib_Data, &m_Grib_MetaData);
+        if( !m_Grib_Data )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Out of memory." );
+            return CE_Failure;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Check that this band matches the dataset as a whole, size       */
@@ -325,6 +330,9 @@ 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 ) )
+        f_unit = 0; /* do not normalize units to metric */
 
     /* Read GRIB message from file position "start". */
     fp.DataSourceFseek(start, SEEK_SET);
@@ -546,7 +554,7 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
             double * data = NULL;
             grib_MetaData* metaData;
             GRIBRasterBand::ReadGribData(grib_fp, 0, Inv[i].subgNum, &data, &metaData);
-            if (metaData->gds.Nx < 1 || metaData->gds.Ny < 1 )
+            if (data == 0 || metaData->gds.Nx < 1 || metaData->gds.Ny < 1)
             {
                 CPLError( CE_Failure, CPLE_OpenFailed, 
                           "%s is a grib file, but no raster dataset was successfully identified.",
@@ -577,6 +585,11 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
@@ -707,12 +720,36 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
         rMinX = meta->gds.lon1; // longitude in degrees, to be transformed to meters (or degrees in case of latlon)
         rMaxY = meta->gds.lat1; // latitude in degrees, to be transformed to meters 
 
-        if (meta->gds.scan == GRIB2BIT_2) // Y is minY, GDAL wants maxY
-            rMaxY += (meta->gds.Ny - 1) * meta->gds.Dy; // -1 because we GDAL needs the coordinates of the centre of the pixel
-        rPixelSizeX = meta->gds.Dx;
-        rPixelSizeY = meta->gds.Dy;
+        double rMinY = meta->gds.lat2;
+        if (meta->gds.lat2 > rMaxY)
+        {
+          rMaxY = meta->gds.lat2;
+          rMinY = meta->gds.lat1;
+        }
+
+        if (meta->gds.lon1 > meta->gds.lon2)
+          rPixelSizeX = (360.0 - (meta->gds.lon1 - meta->gds.lon2)) / (meta->gds.Nx - 1);
+        else
+          rPixelSizeX = (meta->gds.lon2 - meta->gds.lon1) / (meta->gds.Nx - 1);
+
+        rPixelSizeY = (rMaxY - rMinY) / (meta->gds.Ny - 1);
+
+        // Do some sanity checks for cases that can't be handled by the above
+        // pixel size corrections. GRIB1 has a minimum precision of 0.001
+        // for latitudes and longitudes, so we'll allow a bit higher than that.
+        if (rPixelSizeX < 0 || fabs(rPixelSizeX - meta->gds.Dx) > 0.002)
+          rPixelSizeX = meta->gds.Dx;
+
+        if (rPixelSizeY < 0 || fabs(rPixelSizeY - meta->gds.Dy) > 0.002)
+          rPixelSizeY = meta->gds.Dy;
     }
 
+    // http://gdal.org/gdal_datamodel.html :
+    //   we need the top left corner of the top left pixel.
+    //   At the moment we have the center of the pixel.
+    rMinX-=rPixelSizeX/2;
+    rMaxY+=rPixelSizeY/2;
+
     adfGeoTransform[0] = rMinX;
     adfGeoTransform[3] = rMaxY;
     adfGeoTransform[1] = rPixelSizeX;
diff --git a/frmts/gsg/gs7bgdataset.cpp b/frmts/gsg/gs7bgdataset.cpp
index b8d188b..a02334e 100644
--- a/frmts/gsg/gs7bgdataset.cpp
+++ b/frmts/gsg/gs7bgdataset.cpp
@@ -1,5 +1,5 @@
 /****************************************************************************
- * $Id: gs7bgdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gs7bgdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Surfer 7 Binary Grid Format.
@@ -59,7 +59,7 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gs7bgdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: gs7bgdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GS7BG(void);
@@ -134,7 +134,7 @@ class GS7BGRasterBand : public GDALPamRasterBand
 GS7BGRasterBand::GS7BGRasterBand( GS7BGDataset *poDS, int nBand )
 {
     this->poDS = poDS;
-    nBand = nBand;
+    this->nBand = nBand;
 
     eDataType = GDT_Float64;
 
@@ -503,8 +503,7 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    poDS->nData_Position =  VSIFTellL(poDS->fp);
-
+    poDS->nData_Position =  (size_t) VSIFTellL(poDS->fp);
 
     /* --------------------------------------------------------------------*/
     /*      Initialize any PAM information.                                */
@@ -512,6 +511,11 @@ GDALDataset *GS7BGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return poDS;
 }
 
@@ -580,6 +584,7 @@ void GDALRegister_GS7BG()
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
             "Byte Int16 UInt16 Float32 Float64" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = GS7BGDataset::Open;
 
diff --git a/frmts/gsg/gsagdataset.cpp b/frmts/gsg/gsagdataset.cpp
index b75f856..645f1c6 100644
--- a/frmts/gsg/gsagdataset.cpp
+++ b/frmts/gsg/gsagdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gsagdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gsagdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software ASCII Grid Format.
@@ -49,7 +49,7 @@
 # define INT_MAX 2147483647
 #endif /* INT_MAX */
 
-CPL_CVSID("$Id: gsagdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: gsagdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GSAG(void);
@@ -171,7 +171,7 @@ GSAGRasterBand::GSAGRasterBand( GSAGDataset *poDS, int nBand,
 
 {
     this->poDS = poDS;
-    nBand = nBand;
+    this->nBand = nBand;
     
     eDataType = GDT_Float64;
 
@@ -335,8 +335,8 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( (nBlockYOff > 0) && ( panLineOffset[nBlockYOff-1] != 0 ) )
     {
 	assert(panLineOffset[nBlockYOff-1] > panLineOffset[nBlockYOff]);
-	nLineBufSize = panLineOffset[nBlockYOff-1]
-            - panLineOffset[nBlockYOff] + 1;
+	nLineBufSize = (size_t) (panLineOffset[nBlockYOff-1]
+                                 - panLineOffset[nBlockYOff] + 1);
     }
     else
     {
@@ -626,8 +626,8 @@ CPLErr GSAGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     CPLString sOut = ssOutBuf.str();
     if( sOut.length() != panLineOffset[nBlockYOff+1]-panLineOffset[nBlockYOff] )
     {
-	int nShiftSize = sOut.length() - (panLineOffset[nBlockYOff+1]
-					  - panLineOffset[nBlockYOff]);
+	int nShiftSize = (int) (sOut.length() - (panLineOffset[nBlockYOff+1]
+                                                 - panLineOffset[nBlockYOff]));
 	if( nBlockYOff != poGDS->nRasterYSize
 	    && GSAGDataset::ShiftFileContents( poGDS->fp,
 					       panLineOffset[nBlockYOff+1],
@@ -1048,6 +1048,11 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 
 error:
@@ -1309,7 +1314,10 @@ CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
 	nRead = VSIFReadL( (void *)(pabyBuffer+nOverlap), 1,
 			   nBufferSize - nOverlap, fp );
 
-	bEOF = VSIFEofL( fp );
+        if( VSIFEofL( fp ) )
+            bEOF = true;
+        else 
+            bEOF = false;
 
 	if( nRead == 0 && !bEOF )
 	{
@@ -1440,7 +1448,7 @@ CPLErr GSAGDataset::UpdateHeader()
     CPLString sOut = ssOutBuf.str();
     if( sOut.length() != poBand->panLineOffset[0] )
     {
-	int nShiftSize = sOut.length() - poBand->panLineOffset[0];
+	int nShiftSize = (int) (sOut.length() - poBand->panLineOffset[0]);
 	if( ShiftFileContents( fp, poBand->panLineOffset[0], nShiftSize,
 			       szEOL ) != CE_None )
 	{
@@ -1830,6 +1838,7 @@ void GDALRegister_GSAG()
 	poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
 				   "Byte Int16 UInt16 Int32 UInt32 "
 				   "Float32 Float64" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
     poDriver->pfnOpen = GSAGDataset::Open;
 	poDriver->pfnCreateCopy = GSAGDataset::CreateCopy;
diff --git a/frmts/gsg/gsbgdataset.cpp b/frmts/gsg/gsbgdataset.cpp
index 624f287..013de4f 100644
--- a/frmts/gsg/gsbgdataset.cpp
+++ b/frmts/gsg/gsbgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gsbgdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gsbgdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Binary Grid Format.
@@ -60,7 +60,7 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gsbgdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: gsbgdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 void	GDALRegister_GSBG(void);
@@ -162,7 +162,7 @@ GSBGRasterBand::GSBGRasterBand( GSBGDataset *poDS, int nBand ) :
 
 {
     this->poDS = poDS;
-    nBand = nBand;
+    this->nBand = nBand;
     
     eDataType = GDT_Float32;
 
@@ -451,7 +451,8 @@ CPLErr GSBGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( bHeaderNeedsUpdate && dfMaxZ > dfMinZ )
     {
 	CPLErr eErr = poGDS->WriteHeader( poGDS->fp,
-					  nRasterXSize, nRasterYSize,
+					  (GInt16) nRasterXSize, 
+                                          (GInt16) nRasterYSize,
 					  dfMinX, dfMaxX,
 					  dfMinY, dfMaxY,
 					  dfMinZ, dfMaxZ );
@@ -657,6 +658,11 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return poDS;
 }
 
@@ -739,7 +745,9 @@ CPLErr GSBGDataset::SetGeoTransform( double *padfGeoTransform )
         padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3];
     double dfMaxY = padfGeoTransform[3] + padfGeoTransform[5] / 2;
 
-    eErr = WriteHeader( fp, poGRB->nRasterXSize, poGRB->nRasterYSize,
+    eErr = WriteHeader( fp, 
+                        (GInt16) poGRB->nRasterXSize, 
+                        (GInt16) poGRB->nRasterYSize,
 			dfMinX, dfMaxX, dfMinY, dfMaxY,
 			poGRB->dfMinZ, poGRB->dfMaxZ );
 
@@ -900,8 +908,8 @@ GDALDataset *GSBGDataset::Create( const char * pszFilename,
                   pszFilename );
         return NULL;
     }
-
-    CPLErr eErr = WriteHeader( fp, nXSize, nYSize,
+    
+    CPLErr eErr = WriteHeader( fp, (GInt16) nXSize, (GInt16) nYSize,
 			       0.0, nXSize, 0.0, nYSize, 0.0, 0.0 );
     if( eErr != CE_None )
     {
@@ -994,8 +1002,8 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
         return NULL;
     }
 
-    GInt16  nXSize = poSrcBand->GetXSize();
-    GInt16  nYSize = poSrcBand->GetYSize();
+    GInt16  nXSize = (GInt16) poSrcBand->GetXSize();
+    GInt16  nYSize = (GInt16) poSrcBand->GetYSize();
     double  adfGeoTransform[6];
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
@@ -1026,7 +1034,7 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
     }
 
     int     bSrcHasNDValue;
-    float   fSrcNoDataValue = poSrcBand->GetNoDataValue( &bSrcHasNDValue );
+    float   fSrcNoDataValue = (float) poSrcBand->GetNoDataValue( &bSrcHasNDValue );
     double  dfMinZ = DBL_MAX;
     double  dfMaxZ = -DBL_MAX;
     for( GInt16 iRow = nYSize - 1; iRow >= 0; iRow-- )
@@ -1226,6 +1234,7 @@ void GDALRegister_GSBG()
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
 	poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
 				   "Byte Int16 UInt16 Float32" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = GSBGDataset::Open;
 	poDriver->pfnCreate = GSBGDataset::Create;
diff --git a/frmts/gta/GNUmakefile b/frmts/gta/GNUmakefile
new file mode 100644
index 0000000..cb16a5d
--- /dev/null
+++ b/frmts/gta/GNUmakefile
@@ -0,0 +1,13 @@
+
+include ../../GDALmake.opt
+
+OBJ	=	gtadataset.o
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/gta/frmt_gta.html b/frmts/gta/frmt_gta.html
new file mode 100644
index 0000000..cdfae7b
--- /dev/null
+++ b/frmts/gta/frmt_gta.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>GTA - Generic Tagged Arrays</title>
+</head>
+
+<body>
+
+<h1>GTA - Generic Tagged Arrays</h1>
+
+<p>Starting with GDAL 1.9.0, GDAL can read and write GTA data files through the libgta library.</p>
+
+<p>GTA is a file format that can store any kind of multidimensional array data, allows generic manipulations of array data, and
+allows easy conversion to and from other file formats.</p>
+
+<h2>Creation options</h2>
+
+<ul>
+<li><p><b>COMPRESS=method</b> Set the GTA compression method: NONE (default) or one of BZIP2, XZ, ZLIB,
+ZLIB1, ZLIB2, ZLIB3, ZLIB4, ZLIB5, ZLIB6, ZLIB7, ZLIB8, ZLIB9. <p></li>
+</ul>
+
+<p>See Also:</p>
+
+<ul>
+<li><a href="http://gta.nongnu.org">GTA home page</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/gta/gtadataset.cpp b/frmts/gta/gtadataset.cpp
new file mode 100644
index 0000000..eb49a92
--- /dev/null
+++ b/frmts/gta/gtadataset.cpp
@@ -0,0 +1,1733 @@
+/******************************************************************************
+ * $Id: gtadataset.cpp 23475 2011-12-05 22:44:57Z rouault $
+ *
+ * Project:  GTA read/write Driver
+ * Purpose:  GDAL bindings over GTA library.
+ * Author:   Martin Lambers, marlam at marlam.de
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, 2011, Martin Lambers <marlam at marlam.de>
+ *
+ * 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.
+ ****************************************************************************/
+
+/*
+ * This driver supports reading and writing GTAs (Generic Tagged Arrays). See
+ * http://www.nongnu.org/gta/ for details on this format.
+ *
+ * Supported Features:
+ * - CreateCopy().
+ * - GTA compression can be set.
+ * - Raster data is updatable for uncompressed GTAs.
+ * - All input/output is routed through the VSIF*L functions
+ *   (GDAL_DCAP_VIRTUALIO is set to "YES").
+ * - All kinds of metadata are supported (see tag list below).
+ *
+ * Limitations:
+ * - Only uncompressed GTAs can be updated.
+ * - Only raster data updates are possible; metadata cannot be changed.
+ * - Color palettes are not supported.
+ * - CInt16 is stored as gta::cfloat32, and CInt32 as gta::cfloat64.
+ * - GDAL metadata is assumed to be in UTF-8 encoding, so that no conversion is
+ *   necessary to store it in GTA tags. I'm not sure that this is correct, but
+ *   since some metadata might not be representable in the local encoding (e.g.
+ *   a chinese description in latin1), using UTF-8 seems reasonable.
+ *
+ * The following could be implemented, but currently is not:
+ * - Allow metadata updates by using a special GDAL/METADATA_BUFFER tag that
+ *   contains a number of spaces as a placeholder for additional metadata, so
+ *   that the header size on disk can be kept constant.
+ * - Implement Create().
+ * - Implement AddBand() for uncompressed GTAs. But this would be inefficient:
+ *   the old data would need to be copied to a temporary file, and then copied
+ *   back while extending it with the new band.
+ * - When strict conversion is requested, store CInt16 in 2 x gta::int16 and
+ *   CInt32 in 2 x gta::int32, and mark these components with special flags so
+ *   that this is reverted when opening the GTA.
+ * - Support color palettes by storing the palette in special tags.
+ *
+ * This driver supports the following standard GTA tags:
+ * DESCRIPTION
+ * INTERPRETATION
+ * NO_DATA_VALUE
+ * MIN_VALUE
+ * MAX_VALUE
+ * UNIT
+ *
+ * Additionally, the following tags are used for GDAL-specific metadata:
+ * GDAL/PROJECTION      (WKT)
+ * GDAL/GEO_TRANSFORM   (6 doubles)
+ * GDAL/OFFSET          (1 double)
+ * GDAL/SCALE           (1 double)
+ * GDAL/GCP_PROJECTION  (WKT)
+ * GDAL/GCP_COUNT       (1 int > 0)
+ * GDAL/GCP%d           (5 doubles)
+ * GDAL/GCP%d_INFO      (String)
+ * GDAL/CATEGORY_COUNT  (1 int > 0)
+ * GDAL/CATEGORY%d      (String)
+ * GDAL/META/DEFAULT/%s (String)
+ * GDAL/META/RCP/%s     (String)
+ */
+
+#include <limits.h>
+#include "cpl_port.h" // for snprintf for MSVC
+#include <gta/gta.hpp>
+#include "gdal_pam.h"
+
+CPL_CVSID("$Id: gtadataset.cpp 23475 2011-12-05 22:44:57Z rouault $");
+
+CPL_C_START
+void    GDALRegister_GTA(void);
+CPL_C_END
+
+
+/************************************************************************/
+/* Helper functions                                                     */
+/************************************************************************/
+
+static void ScanDoubles( const char *pszString, double *padfDoubles, int nCount )
+
+{
+    char *pszRemainingString = (char *)pszString;
+    for( int i = 0; i < nCount; i++ )
+    {
+        padfDoubles[i] = 0.0;   // fallback value
+        padfDoubles[i] = CPLStrtod( pszRemainingString, &pszRemainingString );
+    }
+}
+
+static CPLString PrintDoubles( const double *padfDoubles, int nCount )
+
+{
+    CPLString oString;
+    for( int i = 0; i < nCount; i++ )
+    {
+        oString.FormatC( padfDoubles[i], "%.16g" );
+        if( i < nCount - 1)
+        {
+            oString += ' ';
+        }
+    }
+    return oString;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/* GTA custom IO class using GDAL's IO abstraction layer                */
+/* ==================================================================== */
+/************************************************************************/
+
+class GTAIO : public gta::custom_io
+{
+  private:
+    VSILFILE *fp;
+
+  public:
+    GTAIO( ) throw ()
+        : fp( NULL )
+    {
+    }
+    ~GTAIO( )
+    {
+        close( );
+    }
+
+    int open( const char *pszFilename, const char *pszMode )
+    {
+        fp = VSIFOpenL( pszFilename, pszMode );
+        return ( fp == NULL ? -1 : 0 );
+    }
+
+    void close( )
+    {
+        if( fp != NULL )
+        {
+            VSIFCloseL( fp );
+            fp = NULL;
+        }
+    }
+
+    vsi_l_offset tell( )
+    {
+        return VSIFTellL( fp );
+    }
+
+    virtual size_t read(void *buffer, size_t size, bool *error) throw ()
+    {
+        size_t s;
+        s = VSIFReadL( buffer, 1, size, fp );
+        if( s != size )
+        {
+            errno = EIO;
+            *error = true;
+        }
+        return size;
+    }
+
+    virtual size_t write(const void *buffer, size_t size, bool *error) throw ()
+    {
+        size_t s;
+        s = VSIFWriteL( buffer, 1, size, fp );
+        if( s != size )
+        {
+            errno = EIO;
+            *error = true;
+        }
+        return size;
+    }
+
+    virtual bool seekable() throw ()
+    {
+        return true;
+    }
+
+    virtual void seek(intmax_t offset, int whence, bool *error) throw ()
+    {
+        int r;
+        r = VSIFSeekL( fp, offset, whence );
+        if( r != 0 )
+        {
+            errno = EIO;
+            *error = true;
+        }
+    }
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              GTADataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class GTARasterBand;
+
+class GTADataset : public GDALPamDataset
+{
+    friend class GTARasterBand;
+
+  private:
+    // GTA input/output via VSIF*L functions
+    GTAIO       oGTAIO;
+    // GTA information
+    gta::header oHeader;
+    vsi_l_offset DataOffset;
+    // Metadata
+    bool        bHaveGeoTransform;
+    double      adfGeoTransform[6];
+    int         nGCPs;
+    char        *pszGCPProjection;
+    GDAL_GCP    *pasGCPs;
+    // Cached data block for block-based input/output
+    int         nLastBlockXOff, nLastBlockYOff;
+    void        *pBlock;
+
+    // Block-based input/output of all bands at once. This is used
+    // by the GTARasterBand input/output functions.
+    CPLErr      ReadBlock( int, int );
+    CPLErr      WriteBlock( );
+
+  public:
+                GTADataset();
+                ~GTADataset();
+
+    static GDALDataset *Open( GDALOpenInfo * );
+
+    CPLErr      GetGeoTransform( double * padfTransform );
+    CPLErr      SetGeoTransform( double * padfTransform );
+
+    const char *GetProjectionRef( );
+    CPLErr      SetProjection( const char *pszProjection );
+
+    int         GetGCPCount( );
+    const char *GetGCPProjection( );
+    const GDAL_GCP *GetGCPs( );
+    CPLErr      SetGCPs( int, const GDAL_GCP *, const char * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            GTARasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class GTARasterBand : public GDALPamRasterBand
+{
+    friend class GTADataset;
+  private:
+    // Size of the component represented by this band
+    size_t      sComponentSize;
+    // Offset of the component represented by this band inside a GTA element
+    size_t      sComponentOffset;
+    // StringList for category names
+    char      **papszCategoryNames;
+    // StringList for metadata
+    char      **papszMetaData;
+
+  public:
+                GTARasterBand( GTADataset *, int );
+                ~GTARasterBand( );
+
+    CPLErr      IReadBlock( int, int, void * );
+    CPLErr      IWriteBlock( int, int, void * );
+
+    char      **GetCategoryNames( );
+    CPLErr      SetCategoryNames( char ** );
+
+    double      GetMinimum( int * );
+    double      GetMaximum( int * );
+
+    double      GetNoDataValue( int * );
+    CPLErr      SetNoDataValue( double );
+    double      GetOffset( int * );
+    CPLErr      SetOffset( double );
+    double      GetScale( int * );
+    CPLErr      SetScale( double );
+    const char *GetUnitType( );
+    CPLErr      SetUnitType( const char * );
+    GDALColorInterp GetColorInterpretation( );
+    CPLErr      SetColorInterpretation( GDALColorInterp );
+};
+
+/************************************************************************/
+/*                           GTARasterBand()                            */
+/************************************************************************/
+
+GTARasterBand::GTARasterBand( GTADataset *poDS, int nBand )
+
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+
+    // Data type
+    switch( poDS->oHeader.component_type( nBand-1 ) )
+    {
+    case gta::int8:
+        eDataType = GDT_Byte;
+        SetMetadataItem("PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE");
+        break;
+    case gta::uint8:
+        eDataType = GDT_Byte;
+        break;
+    case gta::int16:
+        eDataType = GDT_Int16;
+        break;
+    case gta::uint16:
+        eDataType = GDT_UInt16;
+        break;
+    case gta::int32:
+        eDataType = GDT_Int32;
+        break;
+    case gta::uint32:
+        eDataType = GDT_UInt32;
+        break;
+    case gta::float32:
+        eDataType = GDT_Float32;
+        break;
+    case gta::float64:
+        eDataType = GDT_Float64;
+        break;
+    case gta::cfloat32:
+        eDataType = GDT_CFloat32;
+        break;
+    case gta::cfloat64:
+        eDataType = GDT_CFloat64;
+        break;
+    default:
+        // cannot happen because we checked this in GTADataset::Open()
+        break;
+    }
+
+    // Block size
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+
+    // Component information
+    sComponentSize = poDS->oHeader.component_size( nBand-1 );
+    sComponentOffset = 0;
+    for( int i = 0; i < nBand-1; i++ )
+    {
+        sComponentOffset += poDS->oHeader.component_size( i );
+    }
+
+    // Metadata
+    papszCategoryNames = NULL;
+    papszMetaData = NULL;
+    if( poDS->oHeader.component_taglist( nBand-1 ).get( "DESCRIPTION" ) )
+    {
+        SetDescription( poDS->oHeader.component_taglist( nBand-1 ).get( "DESCRIPTION" ) );
+    }
+    for( uintmax_t i = 0; i < poDS->oHeader.component_taglist( nBand-1 ).tags(); i++)
+    {
+        const char *pszTagName = poDS->oHeader.component_taglist( nBand-1 ).name( i );
+        if( strncmp( pszTagName, "GDAL/META/", 10 ) == 0 )
+        {
+            const char *pDomainEnd = strchr( pszTagName + 10, '/' );
+            if( pDomainEnd && pDomainEnd - (pszTagName + 10) > 0 )
+            {
+                char *pszDomain = (char *)VSIMalloc( pDomainEnd - (pszTagName + 10) + 1 );
+                if( !pszDomain )
+                {
+                    continue;
+                }
+                int j;
+                for( j = 0; j < pDomainEnd - (pszTagName + 10); j++ )
+                {
+                    pszDomain[j] = pszTagName[10 + j];
+                }
+                pszDomain[j] = '\0';
+                const char *pszName = pszTagName + 10 + j + 1;
+                const char *pszValue = poDS->oHeader.component_taglist( nBand-1 ).value( i );
+                SetMetadataItem( pszName, pszValue,
+                        strcmp( pszDomain, "DEFAULT" ) == 0 ? NULL : pszDomain );
+                VSIFree( pszDomain );
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                           ~GTARasterBand()                           */
+/************************************************************************/
+
+GTARasterBand::~GTARasterBand( )
+
+{
+    CSLDestroy( papszCategoryNames );
+    CSLDestroy( papszMetaData );
+}
+
+/************************************************************************/
+/*                             GetCategoryNames()                       */
+/************************************************************************/
+
+char **GTARasterBand::GetCategoryNames( )
+
+{
+    if( !papszCategoryNames )
+    {
+        GTADataset *poGDS = (GTADataset *) poDS;
+        const char *pszCatCount = poGDS->oHeader.component_taglist( nBand-1 ).get( "GDAL/CATEGORY_COUNT" );
+        int nCatCount = 0;
+        if( pszCatCount )
+        {
+            nCatCount = atoi( pszCatCount );
+        }
+        if( nCatCount > 0 )
+        {
+            for( int i = 0; i < nCatCount; i++ )
+            {
+                const char *pszCatName = poGDS->oHeader.component_taglist( nBand-1 ).get(
+                        CPLSPrintf( "GDAL/CATEGORY%d", i ) );
+                papszCategoryNames = CSLAddString( papszCategoryNames, pszCatName ? pszCatName : "" );
+            }
+        }
+    }
+    return papszCategoryNames;
+}
+
+/************************************************************************/
+/*                             SetCategoryName()                        */
+/************************************************************************/
+
+CPLErr GTARasterBand::SetCategoryNames( char ** )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double GTARasterBand::GetMinimum( int *pbSuccess )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+    const char *pszValue = poGDS->oHeader.component_taglist( nBand-1 ).get( "MIN_VALUE" );
+    if( pszValue )
+    {
+        if( pbSuccess )
+            *pbSuccess = true;
+        return CPLAtof( pszValue );
+    }
+    else
+    {
+        return GDALRasterBand::GetMinimum( pbSuccess );
+    }
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double GTARasterBand::GetMaximum( int *pbSuccess  )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+    const char *pszValue = poGDS->oHeader.component_taglist( nBand-1 ).get( "MAX_VALUE" );
+    if( pszValue )
+    {
+        if( pbSuccess )
+            *pbSuccess = true;
+        return CPLAtof( pszValue );
+    }
+    else
+    {
+        return GDALRasterBand::GetMaximum( pbSuccess );
+    }
+}
+
+/************************************************************************/
+/*                             GetNoDataValue()                         */
+/************************************************************************/
+
+double GTARasterBand::GetNoDataValue( int *pbSuccess )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+    const char *pszValue = poGDS->oHeader.component_taglist( nBand-1 ).get( "NO_DATA_VALUE" );
+    if( pszValue )
+    {
+        if( pbSuccess )
+            *pbSuccess = true;
+        return CPLAtof( pszValue );
+    }
+    else
+    {
+        return GDALRasterBand::GetNoDataValue( pbSuccess );
+    }
+}
+
+/************************************************************************/
+/*                             SetNoDataValue()                         */
+/************************************************************************/
+
+CPLErr GTARasterBand::SetNoDataValue( double )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                             GetOffset()                              */
+/************************************************************************/
+
+double GTARasterBand::GetOffset( int *pbSuccess )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+    const char *pszValue = poGDS->oHeader.component_taglist( nBand-1 ).get( "GDAL/OFFSET" );
+    if( pszValue )
+    {
+        if( pbSuccess )
+            *pbSuccess = true;
+        return CPLAtof( pszValue );
+    }
+    else
+    {
+        return GDALRasterBand::GetOffset( pbSuccess );
+    }
+}
+
+/************************************************************************/
+/*                             SetOffset()                              */
+/************************************************************************/
+
+CPLErr GTARasterBand::SetOffset( double )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                             GetScale()                               */
+/************************************************************************/
+
+double GTARasterBand::GetScale( int *pbSuccess )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+    const char *pszValue = poGDS->oHeader.component_taglist( nBand-1 ).get( "GDAL/SCALE" );
+    if( pszValue )
+    {
+        if( pbSuccess )
+            *pbSuccess = true;
+        return CPLAtof( pszValue );
+    }
+    else
+    {
+        return GDALRasterBand::GetScale( pbSuccess );
+    }
+}
+
+/************************************************************************/
+/*                             SetScale()                               */
+/************************************************************************/
+
+CPLErr GTARasterBand::SetScale( double )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                             GetUnitType()                            */
+/************************************************************************/
+
+const char *GTARasterBand::GetUnitType( )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+    const char *pszValue = poGDS->oHeader.component_taglist( nBand-1 ).get( "UNIT" );
+    return pszValue ? pszValue : "";
+}
+
+/************************************************************************/
+/*                             SetUnitType()                            */
+/************************************************************************/
+
+CPLErr GTARasterBand::SetUnitType( const char * )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                             GetColorInterpretation()                 */
+/************************************************************************/
+
+GDALColorInterp GTARasterBand::GetColorInterpretation( )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+    const char *pszColorInterpretation =
+        poGDS->oHeader.component_taglist( nBand-1 ).get(
+                "INTERPRETATION" );
+    if( pszColorInterpretation )
+    {
+        if( EQUAL( pszColorInterpretation, "GRAY" ) )
+            return GCI_GrayIndex ;
+        else if ( EQUAL( pszColorInterpretation, "RED" ) )
+            return GCI_RedBand ;
+        else if ( EQUAL( pszColorInterpretation, "GREEN" ) )
+            return GCI_GreenBand ;
+        else if ( EQUAL( pszColorInterpretation, "BLUE" ) )
+            return GCI_BlueBand ;
+        else if ( EQUAL( pszColorInterpretation, "ALPHA" ) )
+            return GCI_AlphaBand ;
+        else if ( EQUAL( pszColorInterpretation, "HSL/H" ) )
+            return GCI_HueBand ;
+        else if ( EQUAL( pszColorInterpretation, "HSL/S" ) )
+            return GCI_SaturationBand ;
+        else if ( EQUAL( pszColorInterpretation, "HSL/L" ) )
+            return GCI_LightnessBand ;
+        else if ( EQUAL( pszColorInterpretation, "CMYK/C" ) )
+            return GCI_CyanBand ;
+        else if ( EQUAL( pszColorInterpretation, "CMYK/M" ) )
+            return GCI_MagentaBand ;
+        else if ( EQUAL( pszColorInterpretation, "CMYK/Y" ) )
+            return GCI_YellowBand ;
+        else if ( EQUAL( pszColorInterpretation, "CMYK/K" ) )
+            return GCI_BlackBand ;
+        else if ( EQUAL( pszColorInterpretation, "YCBCR/Y" ) )
+            return GCI_YCbCr_YBand;
+        else if ( EQUAL( pszColorInterpretation, "YCBCR/CB" ) )
+            return GCI_YCbCr_CbBand;
+        else if ( EQUAL( pszColorInterpretation, "YCBCR/CR" ) )
+            return GCI_YCbCr_CrBand;
+    }
+    return GCI_Undefined;
+}
+
+/************************************************************************/
+/*                             SetColorInterpretation()                 */
+/************************************************************************/
+
+CPLErr GTARasterBand::SetColorInterpretation( GDALColorInterp )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr GTARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                  void * pImage )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+
+    // Read and cache block containing all bands at once
+    if( poGDS->ReadBlock( nBlockXOff, nBlockYOff ) != CE_None )
+    {
+        return CE_Failure;
+    }
+
+    char *pBlock = (char *)poGDS->pBlock;
+    if( poGDS->oHeader.compression() != gta::none )
+    {
+        // pBlock contains the complete data set. Add the offset into the
+        // requested block. This assumes that nBlockYSize == 1 and
+        // nBlockXSize == nRasterXSize.
+        pBlock += nBlockYOff * nBlockXSize * poGDS->oHeader.element_size();
+    }
+
+    // Copy the data for this band from the cached block
+    for( int i = 0; i < nBlockXSize; i++ )
+    {
+        char *pSrc = pBlock + i * poGDS->oHeader.element_size() + sComponentOffset;
+        char *pDst = (char *) pImage + i * sComponentSize;
+        memcpy( (void *) pDst, (void *) pSrc, sComponentSize );
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                             IWriteBlock()                            */
+/************************************************************************/
+
+CPLErr GTARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
+                                  void * pImage )
+
+{
+    GTADataset *poGDS = (GTADataset *) poDS;
+
+    if( poGDS->oHeader.compression() != gta::none )
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                "The GTA driver cannot update compressed GTAs.\n" );
+        return CE_Failure;
+    }
+
+    // Read and cache block containing all bands at once
+    if( poGDS->ReadBlock( nBlockXOff, nBlockYOff ) != CE_None )
+    {
+        return CE_Failure;
+    }
+    char *pBlock = (char *)poGDS->pBlock;
+
+    // Copy the data for this band into the cached block
+    for( int i = 0; i < nBlockXSize; i++ )
+    {
+        char *pSrc = (char *) pImage + i * sComponentSize;
+        char *pDst = pBlock + i * poGDS->oHeader.element_size() + sComponentOffset;
+        memcpy( (void *) pDst, (void *) pSrc, sComponentSize );
+    }
+
+    // Write the block that conatins all bands at once
+    if( poGDS->WriteBlock( ) != CE_None )
+    {
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              GTADataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                            GTADataset()                              */
+/************************************************************************/
+
+GTADataset::GTADataset()
+
+{
+    // Initialize Metadata
+    bHaveGeoTransform = false;
+    nGCPs = 0;
+    pszGCPProjection = NULL;
+    pasGCPs = NULL;
+    // Initialize block-based input/output
+    nLastBlockXOff = -1;
+    nLastBlockYOff = -1;
+    pBlock = NULL;
+}
+
+/************************************************************************/
+/*                            ~GTADataset()                             */
+/************************************************************************/
+
+GTADataset::~GTADataset()
+
+{
+    FlushCache();
+    VSIFree( pszGCPProjection );
+    for( int i = 0; i < nGCPs; i++ )
+    {
+        VSIFree( pasGCPs[i].pszId );
+        VSIFree( pasGCPs[i].pszInfo );
+    }
+    VSIFree( pasGCPs );
+    VSIFree( pBlock );
+}
+
+/************************************************************************/
+/*                             ReadBlock()                              */
+/************************************************************************/
+
+CPLErr GTADataset::ReadBlock( int nBlockXOff, int nBlockYOff )
+
+{
+    /* Compressed data sets must be read into memory completely.
+     * Uncompressed data sets are read block-wise. */
+
+    if( oHeader.compression() != gta::none )
+    {
+        if( pBlock == NULL )
+        {
+            if( oHeader.data_size() > (size_t)(-1)
+                    || ( pBlock = VSIMalloc( oHeader.data_size() ) ) == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                        "Cannot allocate buffer for the complete data set.\n"
+                        "Try to uncompress the data set to allow block-wise "
+                        "reading.\n" );
+                return CE_Failure;
+            }
+
+            try
+            {
+                oHeader.read_data( oGTAIO, pBlock );
+            }
+            catch( gta::exception &e )
+            {
+                CPLError( CE_Failure, CPLE_FileIO, "GTA error: %s\n", e.what() );
+                return CE_Failure;
+            }
+        }
+    }
+    else
+    {
+        // This has to be the same as in the RasterBand constructor!
+        int nBlockXSize = GetRasterXSize();
+        int nBlockYSize = 1;
+
+        if( nLastBlockXOff == nBlockXOff && nLastBlockYOff == nBlockYOff )
+            return CE_None;
+
+        if( pBlock == NULL )
+        {
+            pBlock = VSIMalloc2( oHeader.element_size(), nBlockXSize );
+            if( pBlock == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                        "Cannot allocate scanline buffer" );
+                return CE_Failure;
+            }
+        }
+
+        try
+        {
+            uintmax_t lo[2] = { nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize};
+            uintmax_t hi[2] = { lo[0] + nBlockXSize - 1, lo[1] + nBlockYSize - 1 };
+            oHeader.read_block( oGTAIO, DataOffset, lo, hi, pBlock );
+        }
+        catch( gta::exception &e )
+        {
+            CPLError( CE_Failure, CPLE_FileIO, "GTA error: %s\n", e.what() );
+            return CE_Failure;
+        }
+
+        nLastBlockXOff = nBlockXOff;
+        nLastBlockYOff = nBlockYOff;
+    }
+    return CE_None;
+}
+
+/************************************************************************/
+/*                             WriteBlock()                             */
+/************************************************************************/
+
+CPLErr GTADataset::WriteBlock( )
+
+{
+    // This has to be the same as in the RasterBand constructor!
+    int nBlockXSize = GetRasterXSize();
+    int nBlockYSize = 1;
+
+    // Write the block (nLastBlockXOff, nLastBlockYOff) stored in pBlock.
+    try
+    {
+        uintmax_t lo[2] = { nLastBlockXOff * nBlockXSize, nLastBlockYOff * nBlockYSize};
+        uintmax_t hi[2] = { lo[0] + nBlockXSize - 1, lo[1] + nBlockYSize - 1 };
+        oHeader.write_block( oGTAIO, DataOffset, lo, hi, pBlock );
+    }
+    catch( gta::exception &e )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "GTA error: %s\n", e.what() );
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr GTADataset::GetGeoTransform( double * padfTransform )
+
+{
+    if( bHaveGeoTransform )
+    {
+        memcpy( padfTransform, adfGeoTransform, 6*sizeof(double) );
+        return CE_None;
+    }
+    else
+    {
+        return CE_Failure;
+    }
+}
+
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr GTADataset::SetGeoTransform( double * )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *GTADataset::GetProjectionRef()
+
+{
+    const char *p = oHeader.global_taglist().get("GDAL/PROJECTION");
+    return ( p ? p : "" );
+}
+
+/************************************************************************/
+/*                          SetProjection()                             */
+/************************************************************************/
+
+CPLErr GTADataset::SetProjection( const char * )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                          GetGCPCount()                               */
+/************************************************************************/
+
+int GTADataset::GetGCPCount( )
+
+{
+    return nGCPs;
+}
+
+/************************************************************************/
+/*                          GetGCPProjection()                          */
+/************************************************************************/
+
+const char * GTADataset::GetGCPProjection( )
+
+{
+    return pszGCPProjection ? pszGCPProjection : "";
+}
+
+/************************************************************************/
+/*                          GetGCPs()                                   */
+/************************************************************************/
+
+const GDAL_GCP * GTADataset::GetGCPs( )
+
+{
+    return pasGCPs;
+}
+
+/************************************************************************/
+/*                          SetGCPs()                                   */
+/************************************************************************/
+
+CPLErr GTADataset::SetGCPs( int, const GDAL_GCP *, const char * )
+
+{
+    CPLError( CE_Warning, CPLE_NotSupported,
+            "The GTA driver does not support metadata updates.\n" );
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if( poOpenInfo->nHeaderBytes < 5 )
+        return NULL;
+
+    if( !EQUALN((char *)poOpenInfo->pabyHeader,"GTA",3) )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    GTADataset  *poDS;
+
+    poDS = new GTADataset();
+
+    if( poDS->oGTAIO.open( poOpenInfo->pszFilename,
+            poOpenInfo->eAccess == GA_Update ? "r+" : "r" ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "Cannot open file.\n" );
+        delete poDS;
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the header.                                                */
+/* -------------------------------------------------------------------- */
+
+    try
+    {
+        poDS->oHeader.read_from( poDS->oGTAIO );
+    }
+    catch( gta::exception &e )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, "GTA error: %s\n", e.what() );
+        delete poDS;
+        return NULL;
+    }
+    poDS->DataOffset = poDS->oGTAIO.tell();
+    poDS->eAccess = poOpenInfo->eAccess;
+
+    if( poDS->oHeader.compression() != gta::none
+            && poOpenInfo->eAccess == GA_Update )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "The GTA driver does not support update access to compressed "
+                  "data sets.\nUncompress the data set first.\n" );
+        delete poDS;
+        return NULL;
+    }
+
+    if( poDS->oHeader.dimensions() != 2 )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                "The GTA driver does not support GTAs with %s than 2 "
+                "dimensions.\n",
+                poDS->oHeader.dimensions() < 2 ? "less" : "more" );
+        delete poDS;
+        return NULL;
+    }
+
+    // We know the dimensions are > 0 (guaranteed by libgta), but they may be
+    // unrepresentable in GDAL.
+    if( poDS->oHeader.dimension_size(0) > INT_MAX
+            || poDS->oHeader.dimension_size(1) > INT_MAX )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                "The GTA driver does not support the size of this data set.\n" );
+        delete poDS;
+        return NULL;
+    }
+    poDS->nRasterXSize = poDS->oHeader.dimension_size(0);
+    poDS->nRasterYSize = poDS->oHeader.dimension_size(1);
+
+    // Check the number of bands (called components in GTA)
+    if( poDS->oHeader.components() > INT_MAX-1
+            || poDS->oHeader.element_size() > ((size_t)-1) )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                "The GTA driver does not support the number or size of bands "
+                "in this data set.\n" );
+        delete poDS;
+        return NULL;
+    }
+    poDS->nBands = poDS->oHeader.components();
+
+    // Check the data types (called component types in GTA)
+    for( int iBand = 0; iBand < poDS->nBands; iBand++ )
+    {
+        if( poDS->oHeader.component_type(iBand) != gta::uint8
+                && poDS->oHeader.component_type(iBand) != gta::int8
+                && poDS->oHeader.component_type(iBand) != gta::uint16
+                && poDS->oHeader.component_type(iBand) != gta::int16
+                && poDS->oHeader.component_type(iBand) != gta::uint32
+                && poDS->oHeader.component_type(iBand) != gta::int32
+                && poDS->oHeader.component_type(iBand) != gta::float32
+                && poDS->oHeader.component_type(iBand) != gta::float64
+                && poDS->oHeader.component_type(iBand) != gta::cfloat32
+                && poDS->oHeader.component_type(iBand) != gta::cfloat64 )
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                    "The GTA driver does not support some of the data types "
+                    "used in this data set.\n" );
+            delete poDS;
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read and set meta information.                                  */
+/* -------------------------------------------------------------------- */
+
+    if( poDS->oHeader.global_taglist().get("GDAL/GEO_TRANSFORM") )
+    {
+        poDS->bHaveGeoTransform = true;
+        ScanDoubles( poDS->oHeader.global_taglist().get( "GDAL/GEO_TRANSFORM" ),
+                poDS->adfGeoTransform, 6 );
+    }
+    else
+    {
+        poDS->bHaveGeoTransform = false;
+    }
+
+    if( poDS->oHeader.global_taglist().get("GDAL/GCP_PROJECTION") )
+    {
+        poDS->pszGCPProjection = VSIStrdup( poDS->oHeader.global_taglist().get("GDAL/GCP_PROJECTION") );
+    }
+    if( poDS->oHeader.global_taglist().get("GDAL/GCP_COUNT") )
+    {
+        poDS->nGCPs = atoi( poDS->oHeader.global_taglist().get("GDAL/GCP_COUNT") );
+        if( poDS->nGCPs < 1 )
+        {
+            poDS->nGCPs = 0;
+        }
+        else
+        {
+            poDS->pasGCPs = (GDAL_GCP *)VSIMalloc2( poDS->nGCPs, sizeof(GDAL_GCP) );
+            if( poDS->pasGCPs == NULL )
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate GCP list" );
+                delete poDS;
+                return NULL;
+            }
+            for( int i = 0; i < poDS->nGCPs; i++ )
+            {
+                poDS->pasGCPs[i].pszInfo = NULL;
+                poDS->pasGCPs[i].dfGCPPixel = 0.0;
+                poDS->pasGCPs[i].dfGCPLine = 0.0;
+                poDS->pasGCPs[i].dfGCPX = 0.0;
+                poDS->pasGCPs[i].dfGCPY = 0.0;
+                poDS->pasGCPs[i].dfGCPZ = 0.0;
+                poDS->pasGCPs[i].pszId = VSIStrdup( CPLSPrintf( "%d", i ) );
+                char pszGCPTagName[64];
+                char pszGCPInfoTagName[64];
+                strcpy( pszGCPTagName, CPLSPrintf( "GDAL/GCP%d", i ) );
+                strcpy( pszGCPInfoTagName, CPLSPrintf( "GDAL/GCP%d_INFO", i ) );
+                if( poDS->oHeader.global_taglist().get(pszGCPInfoTagName) )
+                {
+                    poDS->pasGCPs[i].pszInfo = VSIStrdup( poDS->oHeader.global_taglist().get(pszGCPInfoTagName) );
+                }
+                else
+                {
+                    poDS->pasGCPs[i].pszInfo = VSIStrdup( "" );
+                }
+                if( poDS->oHeader.global_taglist().get(pszGCPTagName) )
+                {
+                    double adfTempDoubles[5];
+                    ScanDoubles( poDS->oHeader.global_taglist().get(pszGCPTagName), adfTempDoubles, 5 );
+                    poDS->pasGCPs[i].dfGCPPixel = adfTempDoubles[0];
+                    poDS->pasGCPs[i].dfGCPLine = adfTempDoubles[1];
+                    poDS->pasGCPs[i].dfGCPX = adfTempDoubles[2];
+                    poDS->pasGCPs[i].dfGCPY = adfTempDoubles[3];
+                    poDS->pasGCPs[i].dfGCPZ = adfTempDoubles[4];
+                }
+            }
+        }
+    }
+
+    if( poDS->oHeader.global_taglist().get("DESCRIPTION") )
+    {
+        poDS->SetDescription( poDS->oHeader.global_taglist().get("DESCRIPTION") );
+    }
+    for( uintmax_t i = 0; i < poDS->oHeader.global_taglist().tags(); i++)
+    {
+        const char *pszTagName = poDS->oHeader.global_taglist().name( i );
+        if( strncmp( pszTagName, "GDAL/META/", 10 ) == 0 )
+        {
+            const char *pDomainEnd = strchr( pszTagName + 10, '/' );
+            if( pDomainEnd && pDomainEnd - (pszTagName + 10) > 0 )
+            {
+                char *pszDomain = (char *)VSIMalloc( pDomainEnd - (pszTagName + 10) + 1 );
+                if( !pszDomain )
+                {
+                    CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate metadata buffer" );
+                    delete poDS;
+                    return NULL;
+                }
+                int j;
+                for( j = 0; j < pDomainEnd - (pszTagName + 10); j++ )
+                {
+                    pszDomain[j] = pszTagName[10 + j];
+                }
+                pszDomain[j] = '\0';
+                const char *pszName = pszTagName + 10 + j + 1;
+                const char *pszValue = poDS->oHeader.global_taglist().value( i );
+                poDS->SetMetadataItem( pszName, pszValue,
+                        strcmp( pszDomain, "DEFAULT" ) == 0 ? NULL : pszDomain );
+                VSIFree( pszDomain );
+            }
+        }
+    }
+
+    if( poDS->nBands > 0 )
+    {
+        poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+    }
+    if( poDS->oHeader.compression() == gta::bzip2 )
+        poDS->SetMetadataItem( "COMPRESSION", "BZIP2", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::xz )
+        poDS->SetMetadataItem( "COMPRESSION", "XZ", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib1 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB1", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib2 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB2", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib3 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB3", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib4 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB4", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib5 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB5", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib6 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB6", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib7 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB7", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib8 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB8", "IMAGE_STRUCTURE" );
+    else if( poDS->oHeader.compression() == gta::zlib9 )
+        poDS->SetMetadataItem( "COMPRESSION", "ZLIB9", "IMAGE_STRUCTURE" );
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < poDS->nBands; iBand++ )
+    {
+        poDS->SetBand( iBand+1, new GTARasterBand( poDS, iBand+1 ) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
+    return( poDS );
+}
+
+/************************************************************************/
+/*                             CreateCopy()                             */
+/************************************************************************/
+
+static GDALDataset*
+GTACreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                int bStrict, char ** papszOptions,
+                GDALProgressFunc pfnProgress, void * pProgressData )
+
+{
+    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create a GTA header                                             */
+/* -------------------------------------------------------------------- */
+
+    gta::compression eGTACompression = gta::none;
+    const char *pszCompressionValue = CSLFetchNameValue( papszOptions,
+            "COMPRESS" );
+    if( pszCompressionValue != NULL )
+    {
+        if( EQUAL( pszCompressionValue, "NONE" ) )
+            eGTACompression = gta::none;
+        else if( EQUAL( pszCompressionValue, "BZIP2" ) )
+            eGTACompression = gta::bzip2;
+        else if( EQUAL( pszCompressionValue, "XZ" ) )
+            eGTACompression = gta::xz;
+        else if( EQUAL( pszCompressionValue, "ZLIB" ))
+            eGTACompression = gta::zlib;
+        else if( EQUAL( pszCompressionValue, "ZLIB1" ))
+            eGTACompression = gta::zlib1;
+        else if( EQUAL( pszCompressionValue, "ZLIB2" ))
+            eGTACompression = gta::zlib2;
+        else if( EQUAL( pszCompressionValue, "ZLIB3" ))
+            eGTACompression = gta::zlib3;
+        else if( EQUAL( pszCompressionValue, "ZLIB4" ))
+            eGTACompression = gta::zlib4;
+        else if( EQUAL( pszCompressionValue, "ZLIB5" ))
+            eGTACompression = gta::zlib5;
+        else if( EQUAL( pszCompressionValue, "ZLIB6" ))
+            eGTACompression = gta::zlib6;
+        else if( EQUAL( pszCompressionValue, "ZLIB7" ))
+            eGTACompression = gta::zlib7;
+        else if( EQUAL( pszCompressionValue, "ZLIB8" ))
+            eGTACompression = gta::zlib8;
+        else if( EQUAL( pszCompressionValue, "ZLIB9" ))
+            eGTACompression = gta::zlib9;
+        else
+            CPLError( CE_Warning, CPLE_IllegalArg,
+                      "COMPRESS=%s value not recognised, ignoring.",
+                      pszCompressionValue );
+    }
+
+    gta::type *peGTATypes = (gta::type *)VSIMalloc2( poSrcDS->GetRasterCount(), sizeof(gta::type) );
+    if( peGTATypes == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate GTA type list" );
+        return NULL;
+    }
+    for( int i = 0; i < poSrcDS->GetRasterCount(); i++ )
+    {
+        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( i+1 );
+        if( poSrcBand->GetColorInterpretation() == GCI_PaletteIndex )
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                    "The GTA driver does not support color palettes.\n" );
+            VSIFree( peGTATypes );
+            return NULL;
+        }
+        GDALDataType eDT = poSrcBand->GetRasterDataType();
+        switch( eDT )
+        {
+        case GDT_Byte:
+        {
+            const char *pszPixelType = poSrcBand->GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
+            if (pszPixelType && EQUAL(pszPixelType, "SIGNEDBYTE"))
+                peGTATypes[i] = gta::int8;
+            else
+                peGTATypes[i] = gta::uint8;
+            break;
+        }
+        case GDT_UInt16:
+            peGTATypes[i] = gta::uint16;
+            break;
+        case GDT_Int16:
+            peGTATypes[i] = gta::int16;
+            break;
+        case GDT_UInt32:
+            peGTATypes[i] = gta::uint32;
+            break;
+        case GDT_Int32:
+            peGTATypes[i] = gta::int32;
+            break;
+        case GDT_Float32:
+            peGTATypes[i] = gta::float32;
+            break;
+        case GDT_Float64:
+            peGTATypes[i] = gta::float64;
+            break;
+        case GDT_CInt16:
+            if( bStrict )
+            {
+                CPLError( CE_Failure, CPLE_NotSupported,
+                        "The GTA driver does not support the CInt16 data "
+                        "type.\n"
+                        "(If no strict copy is required, the driver can "
+                        "use CFloat32 instead.)\n" );
+                VSIFree( peGTATypes );
+                return NULL;
+            }
+            peGTATypes[i] = gta::cfloat32;
+            break;
+        case GDT_CInt32:
+            if( bStrict )
+            {
+                CPLError( CE_Failure, CPLE_NotSupported,
+                        "The GTA driver does not support the CInt32 data "
+                        "type.\n"
+                        "(If no strict copy is required, the driver can "
+                        "use CFloat64 instead.)\n" );
+                VSIFree( peGTATypes );
+                return NULL;
+            }
+            peGTATypes[i] = gta::cfloat64;
+            break;
+        case GDT_CFloat32:
+            peGTATypes[i] = gta::cfloat32;
+            break;
+        case GDT_CFloat64:
+            peGTATypes[i] = gta::cfloat64;
+            break;
+        default:
+            CPLError( CE_Failure, CPLE_NotSupported,
+                    "The GTA driver does not support source data sets using "
+                    "unknown data types.\n");
+            VSIFree( peGTATypes );
+            return NULL;
+        }
+    }
+
+    gta::header oHeader;
+    try
+    {
+        oHeader.set_compression( eGTACompression );
+        oHeader.set_dimensions( poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize() );
+        oHeader.set_components( poSrcDS->GetRasterCount(), peGTATypes );
+        const char *pszDescription = poSrcDS->GetDescription();
+        // Metadata from GDALMajorObject
+        if( pszDescription && pszDescription[0] != '\0' )
+        {
+            oHeader.global_taglist().set( "DESCRIPTION", pszDescription );
+        }
+        const char *papszMetadataDomains[] = { NULL /* default */, "RPC" };
+        size_t nMetadataDomains = sizeof( papszMetadataDomains ) / sizeof( papszMetadataDomains[0] );
+        for( size_t iDomain = 0; iDomain < nMetadataDomains; iDomain++ )
+        {
+            char **papszMetadata = poSrcDS->GetMetadata( papszMetadataDomains[iDomain] );
+            if( papszMetadata )
+            {
+                for( int i = 0; papszMetadata[i]; i++ )
+                {
+                    char *pEqualSign = strchr( papszMetadata[i], '=' );
+                    if( pEqualSign && pEqualSign - papszMetadata[i] > 0 )
+                    {
+                        *pEqualSign = '\0';
+                        oHeader.global_taglist().set(
+                                CPLSPrintf( "GDAL/META/%s/%s",
+                                    papszMetadataDomains[iDomain] ? papszMetadataDomains[iDomain] : "DEFAULT",
+                                    papszMetadata[i] ),
+                                pEqualSign + 1 );
+                        *pEqualSign = '=';
+                    }
+                }
+            }
+        }
+        // Projection and transformation
+        const char *pszWKT = poSrcDS->GetProjectionRef();
+        if( pszWKT && pszWKT[0] != '\0' )
+        {
+            oHeader.global_taglist().set( "GDAL/PROJECTION", pszWKT );
+        }
+        double adfTransform[6];
+        if( poSrcDS->GetGeoTransform( adfTransform ) == CE_None )
+        {
+            oHeader.global_taglist().set( "GDAL/GEO_TRANSFORM",
+                    PrintDoubles( adfTransform, 6 ).c_str() );
+        }
+        // GCPs
+        if( poSrcDS->GetGCPCount() > 0 )
+        {
+            oHeader.global_taglist().set( "GDAL/GCP_COUNT", CPLSPrintf( "%d", poSrcDS->GetGCPCount() ) );
+            oHeader.global_taglist().set( "GDAL/GCP_PROJECTION", poSrcDS->GetGCPProjection() );
+            const GDAL_GCP *pasGCPs = poSrcDS->GetGCPs();
+            for( int i = 0; i < poSrcDS->GetGCPCount(); i++ )
+            {
+                char pszGCPTagName[64];
+                char pszGCPInfoTagName[64];
+                strcpy( pszGCPTagName, CPLSPrintf( "GDAL/GCP%d", i ) );
+                strcpy( pszGCPInfoTagName, CPLSPrintf( "GDAL/GCP%d_INFO", i ) );
+                if( pasGCPs[i].pszInfo && pasGCPs[i].pszInfo[0] != '\0' )
+                {
+                    oHeader.global_taglist().set( pszGCPInfoTagName, pasGCPs[i].pszInfo );
+                }
+                double adfTempDoubles[5];
+                adfTempDoubles[0] = pasGCPs[i].dfGCPPixel;
+                adfTempDoubles[1] = pasGCPs[i].dfGCPLine;
+                adfTempDoubles[2] = pasGCPs[i].dfGCPX;
+                adfTempDoubles[3] = pasGCPs[i].dfGCPY;
+                adfTempDoubles[4] = pasGCPs[i].dfGCPZ;
+                oHeader.global_taglist().set( pszGCPTagName, PrintDoubles( adfTempDoubles, 5 ).c_str() );
+            }
+        }
+        // Now the bands
+        for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
+        {
+            GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
+            // Metadata from GDALMajorObject
+            const char *pszBandDescription = poSrcBand->GetDescription();
+            if( pszBandDescription && pszBandDescription[0] != '\0' )
+            {
+                oHeader.component_taglist( iBand ).set( "DESCRIPTION", pszBandDescription );
+            }
+            for( size_t iDomain = 0; iDomain < nMetadataDomains; iDomain++ )
+            {
+                char **papszBandMetadata = poSrcBand->GetMetadata( papszMetadataDomains[iDomain] );
+                if( papszBandMetadata )
+                {
+                    for( int i = 0; papszBandMetadata[i]; i++ )
+                    {
+                        char *pEqualSign = strchr( papszBandMetadata[i], '=' );
+                        if( pEqualSign && pEqualSign - papszBandMetadata[i] > 0 )
+                        {
+                            *pEqualSign = '\0';
+                            oHeader.component_taglist( iBand ).set(
+                                    CPLSPrintf( "GDAL/META/%s/%s",
+                                        papszMetadataDomains[iDomain] ? papszMetadataDomains[iDomain] : "DEFAULT",
+                                        papszBandMetadata[i] ),
+                                    pEqualSign + 1 );
+                            *pEqualSign = '=';
+                        }
+                    }
+                }
+            }
+            // Category names
+            char **papszCategoryNames = poSrcBand->GetCategoryNames( );
+            if( papszCategoryNames )
+            {
+                int i;
+                for( i = 0; papszCategoryNames[i]; i++ )
+                {
+                    oHeader.component_taglist( iBand ).set(
+                            CPLSPrintf( "GDAL/CATEGORY%d", i ),
+                            papszCategoryNames[i] );
+                }
+                oHeader.component_taglist( iBand ).set(
+                        "GDAL/CATEGORY_COUNT", CPLSPrintf( "%d", i ) );
+            }
+            // No data value
+            int bHaveNoDataValue;
+            double dfNoDataValue;
+            dfNoDataValue = poSrcBand->GetNoDataValue( &bHaveNoDataValue );
+            if( bHaveNoDataValue )
+                oHeader.component_taglist( iBand ).set( "NO_DATA_VALUE",
+                        PrintDoubles( &dfNoDataValue, 1 ).c_str() );
+            // Min/max values
+            int bHaveMinValue;
+            double dfMinValue;
+            dfMinValue = poSrcBand->GetMinimum( &bHaveMinValue );
+            if( bHaveMinValue )
+                oHeader.component_taglist( iBand ).set( "MIN_VALUE",
+                        PrintDoubles( &dfMinValue, 1 ).c_str() );
+            int bHaveMaxValue;
+            double dfMaxValue;
+            dfMaxValue = poSrcBand->GetMaximum( &bHaveMaxValue );
+            if( bHaveMaxValue )
+                oHeader.component_taglist( iBand ).set( "MAX_VALUE",
+                        PrintDoubles( &dfMaxValue, 1 ).c_str() );
+            // Offset/scale values
+            int bHaveOffsetValue;
+            double dfOffsetValue;
+            dfOffsetValue = poSrcBand->GetOffset( &bHaveOffsetValue );
+            if( bHaveOffsetValue )
+                oHeader.component_taglist( iBand ).set( "GDAL/OFFSET",
+                        PrintDoubles( &dfOffsetValue, 1 ).c_str() );
+            int bHaveScaleValue;
+            double dfScaleValue;
+            dfScaleValue = poSrcBand->GetScale( &bHaveScaleValue );
+            if( bHaveScaleValue )
+                oHeader.component_taglist( iBand ).set( "GDAL/SCALE",
+                        PrintDoubles( &dfScaleValue, 1 ).c_str() );
+            // Unit
+            const char *pszUnit = poSrcBand->GetUnitType( );
+            if( pszUnit != NULL && pszUnit[0] != '\0' )
+                oHeader.component_taglist( iBand ).set( "UNIT", pszUnit );
+            // Color interpretation
+            GDALColorInterp eCI = poSrcBand->GetColorInterpretation();
+            if( eCI == GCI_GrayIndex )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "GRAY" );
+            else if( eCI == GCI_RedBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "RED" );
+            else if( eCI == GCI_GreenBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "GREEN" );
+            else if( eCI == GCI_BlueBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "BLUE" );
+            else if( eCI == GCI_AlphaBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "ALPHA" );
+            else if( eCI == GCI_HueBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "HSL/H" );
+            else if( eCI == GCI_SaturationBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "HSL/S" );
+            else if( eCI == GCI_LightnessBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "HSL/L" );
+            else if( eCI == GCI_CyanBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "CMYK/C" );
+            else if( eCI == GCI_MagentaBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "CMYK/M" );
+            else if( eCI == GCI_YellowBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "CMYK/Y" );
+            else if( eCI == GCI_BlackBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "CMYK/K" );
+            else if( eCI == GCI_YCbCr_YBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "YCBCR/Y" );
+            else if( eCI == GCI_YCbCr_CbBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "YCBCR/CB" );
+            else if( eCI == GCI_YCbCr_CrBand )
+                oHeader.component_taglist( iBand ).set( "INTERPRETATION", "YCBCR/CR" );
+        }
+    }
+    catch( gta::exception &e )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported, "GTA error: %s\n", e.what() );
+        VSIFree( peGTATypes );
+        return NULL;
+    }
+    VSIFree( peGTATypes );
+
+/* -------------------------------------------------------------------- */
+/*      Write header and data to the file                               */
+/* -------------------------------------------------------------------- */
+
+    GTAIO oGTAIO;
+    if( oGTAIO.open( pszFilename, "w" ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                "Cannot create GTA file %s.\n", pszFilename );
+        return NULL;
+    }
+
+    void *pLine = VSIMalloc2( oHeader.element_size(), oHeader.dimension_size(0) );
+    if( pLine == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate scanline buffer.\n" );
+        VSIFree( pLine );
+        return NULL;
+    }
+
+    try
+    {
+        // Write header
+        oHeader.write_to( oGTAIO );
+        // Write data line by line
+        gta::io_state oGTAIOState;
+        for( int iLine = 0; iLine < poSrcDS->GetRasterYSize(); iLine++ )
+        {
+            size_t nComponentOffset = 0;
+            for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
+            {
+                GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
+                GDALDataType eDT = poSrcBand->GetRasterDataType();
+                if( eDT == GDT_CInt16 )
+                {
+                    eDT = GDT_CFloat32;
+                }
+                else if( eDT == GDT_CInt32 )
+                {
+                    eDT = GDT_CFloat64;
+                }
+                char *pDst = (char *)pLine + nComponentOffset;
+                CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, iLine,
+                        poSrcDS->GetRasterXSize(), 1,
+                        pDst, poSrcDS->GetRasterXSize(), 1, eDT,
+                        oHeader.element_size(), 0 );
+                if( eErr != CE_None )
+                {
+                    CPLError( CE_Failure, CPLE_FileIO, "Cannot read source data set.\n" );
+                    VSIFree( pLine );
+                    return NULL;
+                }
+                nComponentOffset += oHeader.component_size( iBand );
+            }
+            oHeader.write_elements( oGTAIOState, oGTAIO, poSrcDS->GetRasterXSize(), pLine );
+            if( !pfnProgress( (iLine+1) / (double) poSrcDS->GetRasterYSize(),
+                        NULL, pProgressData ) )
+            {
+                CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" );
+                VSIFree( pLine );
+                return NULL;
+            }
+        }
+    }
+    catch( gta::exception &e )
+    {
+        CPLError( CE_Failure, CPLE_FileIO, "GTA write error: %s\n", e.what() );
+        VSIFree( pLine );
+        return NULL;
+    }
+    VSIFree( pLine );
+
+    oGTAIO.close();
+
+/* -------------------------------------------------------------------- */
+/*      Re-open dataset, and copy any auxilary pam information.         */
+/* -------------------------------------------------------------------- */
+
+    GTADataset *poDS = (GTADataset *) GDALOpen( pszFilename,
+            eGTACompression == gta::none ? GA_Update : GA_ReadOnly );
+
+    if( poDS )
+        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                          GDALRegister_GTA()                          */
+/************************************************************************/
+
+void GDALRegister_GTA()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "GTA" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "GTA" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                "Generic Tagged Arrays (.gta)" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                "frmt_gta.html" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gta" );
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                "Byte UInt16 Int16 UInt32 Int32 Float32 Float64 "
+                "CInt16 CInt32 CFloat32 CFloat64" );
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                "<CreationOptionList>"
+                "  <Option name='COMPRESS' type='string-select'>"
+                "    <Value>NONE</Value>"
+                "    <Value>BZIP2</Value>"
+                "    <Value>XZ</Value>"
+                "    <Value>ZLIB</Value>"
+                "    <Value>ZLIB1</Value>"
+                "    <Value>ZLIB2</Value>"
+                "    <Value>ZLIB3</Value>"
+                "    <Value>ZLIB4</Value>"
+                "    <Value>ZLIB5</Value>"
+                "    <Value>ZLIB6</Value>"
+                "    <Value>ZLIB7</Value>"
+                "    <Value>ZLIB8</Value>"
+                "    <Value>ZLIB9</Value>"
+                "  </Option>"
+                "</CreationOptionList>" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnOpen = GTADataset::Open;
+        poDriver->pfnCreateCopy = GTACreateCopy;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/frmts/gta/makefile.vc b/frmts/gta/makefile.vc
new file mode 100644
index 0000000..442ad12
--- /dev/null
+++ b/frmts/gta/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	gtadataset.obj
+
+EXTRAFLAGS 	= 	$(GTA_CFLAGS) 
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/gtiff/GNUmakefile b/frmts/gtiff/GNUmakefile
index a303cc7..8367131 100644
--- a/frmts/gtiff/GNUmakefile
+++ b/frmts/gtiff/GNUmakefile
@@ -9,11 +9,17 @@ SUBLIBS 	=
 ifeq ($(TIFF_SETTING),internal)
 SUBLIBS	:= lib-tiff $(SUBLIBS) 
 TIFF_OPTS	:=	-Ilibtiff $(TIFF_OPTS)
+ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
+TIFF_OPTS	:=	-DRENAME_INTERNAL_LIBTIFF_SYMBOLS $(TIFF_OPTS)
+endif
 endif
 
 ifeq ($(GEOTIFF_SETTING),internal)
 SUBLIBS	:= lib-geotiff $(SUBLIBS) 
 TIFF_OPTS	:=	-Ilibgeotiff $(TIFF_OPTS)
+ifeq ($(RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS),yes)
+TIFF_OPTS	:=	-DRENAME_INTERNAL_LIBGEOTIFF_SYMBOLS $(TIFF_OPTS)
+endif
 endif
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(GEOTIFF_INCLUDE) $(TIFF_OPTS) $(CPPFLAGS)
diff --git a/frmts/gtiff/frmt_gtiff.html b/frmts/gtiff/frmt_gtiff.html
index 9d332ca..78b18f5 100644
--- a/frmts/gtiff/frmt_gtiff.html
+++ b/frmts/gtiff/frmt_gtiff.html
@@ -52,7 +52,7 @@ For more details, see the <a href="http://trac.osgeo.org/gdal/wiki/rfc22_rpc">RP
 If .RPB or _RPC.TXT files are found, they will be used to read the RPCs, even if the <i>RPCCoefficientTag</i> tag is set.
 </p>
 
-<h2>Internal nodata masks</h2>
+<h2><a name="internal_mask">Internal nodata masks</a></h2>
 
 <p>(from GDAL 1.6.0)</p>
 
@@ -80,7 +80,7 @@ value for unmasked pixels is 255) unless the GDAL_TIFF_INTERNAL_MASK_TO_8BIT
 configuration option is set to NO. This does not affect the way the mask band is
 written (it is always 1-bit).</p>
 
-<h2>Overviews</h2>
+<h2><a name="overviews"Overviews</a></h2>
 
 <p>The GeoTIFF driver supports reading, creation and update of internal overviews.
 Internal overviews can be created on GeoTIFF files opened in update mode
@@ -126,6 +126,9 @@ or GeoTIFF profile are used, those non standard metadata items are stored into a
 <p>The value of GDALMD_AREA_OR_POINT ("AREA_OR_POINT") metadata item is stored in the GeoTIFF key
 RasterPixelIsPoint for GDALGeoTIFF or GeoTIFF profiles.</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>Nodata value</h2>
 
 <p>GDAL stores band nodata value in the non standard TIFFTAG_GDAL_NODATA ASCII tag (code 42113) for
@@ -232,7 +235,9 @@ used. Primarily intended for debugging & test purposes</p>
 
 <li><p><b>COPY_SRC_OVERVIEWS=[YES/NO]</b>: (GDAL >= 1.8.0, CreateCopy() only) By setting this to YES (default is NO), the potential existing overviews
 of the source dataset will be copied to the target dataset without being recomputed. If overviews of mask band
-also exist, provided that the GDAL_TIFF_INTERNAL_MASK configuration option is set to YES, they will also be copied.</p></li>
+also exist, provided that the GDAL_TIFF_INTERNAL_MASK configuration option is set to YES, they will also be copied.
+Note that this creation option will have <a href="http://trac.osgeo.org/gdal/ticket/3917">no effect</a> if general options
+(i.e. options which are not creation options) of gdal_translate are used.</p></li>
 
 </ul>
 
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index 69d23cf..0ed2ed6 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff.cpp 22461 2011-05-29 18:40:33Z rouault $
+ * $Id: geotiff.cpp 23561 2011-12-13 05:47:58Z warmerdam $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -30,6 +30,9 @@
 /* If we use sunpro compiler on linux. Weird idea indeed ! */
 #if defined(__SUNPRO_CC) && defined(__linux__)
 #define _GNU_SOURCE
+#elif defined(__GNUC__) && !defined(_GNU_SOURCE)
+/* Required to use RTLD_DEFAULT of dlfcn.h */
+#define _GNU_SOURCE
 #endif
 
 #include "gdal_pam.h"
@@ -49,7 +52,7 @@
 #include "tifvsi.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: geotiff.cpp 22461 2011-05-29 18:40:33Z rouault $");
+CPL_CVSID("$Id: geotiff.cpp 23561 2011-12-13 05:47:58Z warmerdam $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -227,6 +230,9 @@ class GTiffDataset : public GDALPamDataset
     GTiffDataset **ppoActiveDSRef;
     GTiffDataset *poActiveDS; /* only used in actual base */
 
+    int         bScanDeferred;
+    void        ScanDirectories();
+
     toff_t      nDirOffset;
     int		bBase;
     int         bCloseTIFFHandle; /* usefull for closing TIFF handle opened by GTIFF_DIR: */
@@ -256,6 +262,9 @@ class GTiffDataset : public GDALPamDataset
     int         bLookedForProjection;
 
     void        LookForProjection();
+#ifdef ESRI_BUILD
+    void        AdjustLinearUnit( short UOMLength );
+#endif
 
     double	adfGeoTransform[6];
     int		bGeoTransformValid;
@@ -324,11 +333,15 @@ class GTiffDataset : public GDALPamDataset
     int           bClipWarn;
 
     CPLString     osRPBFile;
-    int           FindRPBFile(char** papszSiblingFiles);
+    int           FindRPBFile();
     CPLString     osRPCFile;
-    int           FindRPCFile(char** papszSiblingFiles);
+    int           FindRPCFile();
     CPLString     osIMDFile;
-    int           FindIMDFile(char** papszSiblingFiles);
+    int           FindIMDFile();
+    int           bHasSearchedRPC;
+    void          LoadRPCRPB();
+    int           bHasSearchedIMD;
+    void          LoadIMD();
 
     int           bHasWarnedDisableAggressiveBandCaching;
 
@@ -347,6 +360,18 @@ class GTiffDataset : public GDALPamDataset
     CPLErr        CreateInternalMaskOverviews(int nOvrBlockXSize,
                                               int nOvrBlockYSize);
 
+    int           bIsFinalized;
+    int           Finalize();
+
+    int           bIgnoreReadErrors;
+
+    CPLString     osWldFilename;
+
+    int           bDirectIO;
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
   public:
                  GTiffDataset();
                  ~GTiffDataset();
@@ -420,6 +445,9 @@ void    GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
 
     GTiffDataset* poDS = (GTiffDataset*)hGTIFFDS;
     poDS->nJpegQuality = nJpegQuality;
+
+    poDS->ScanDirectories();
+
     int i;
     for(i=0;i<poDS->nOverviewCount;i++)
         poDS->papoOverviewDS[i]->nJpegQuality = nJpegQuality;
@@ -442,6 +470,12 @@ class GTiffRasterBand : public GDALPamRasterBand
     double             dfScale;
     CPLString          osUnitType;
 
+    CPLErr DirectIO( GDALRWFlag eRWFlag,
+                                  int nXOff, int nYOff, int nXSize, int nYSize,
+                                  void * pData, int nBufXSize, int nBufYSize,
+                                  GDALDataType eBufType,
+                                  int nPixelSpace, int nLineSpace );
+
 protected:
     GTiffDataset       *poGDS;
     GDALMultiDomainMetadata oGTiffMDMD;
@@ -450,6 +484,7 @@ protected:
     double             dfNoDataValue;
 
     void NullBlock( void *pData );
+    CPLErr FillCacheForOtherBands( int nBlockXOff, int nBlockYOff );
 
 public:
                    GTiffRasterBand( GTiffDataset *, int );
@@ -557,6 +592,8 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
 /* -------------------------------------------------------------------- */
 /*      Try to work out band color interpretation.                      */
 /* -------------------------------------------------------------------- */
+    int bLookForExtraSamples = FALSE;
+
     if( poDS->poColorTable != NULL && nBand == 1 ) 
         eBandInterp = GCI_PaletteIndex;
     else if( poDS->nPhotometric == PHOTOMETRIC_RGB 
@@ -572,22 +609,7 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
         else if( nBand == 3 )
             eBandInterp = GCI_BlueBand;
         else
-        {
-            uint16 *v;
-            uint16 count = 0;
-
-            if( TIFFGetField( poDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v) )
-            {
-                if( nBand - 3 <= count && v[nBand-4] == EXTRASAMPLE_ASSOCALPHA )
-                    eBandInterp = GCI_AlphaBand;
-                else
-                    eBandInterp = GCI_Undefined;
-            }
-            else if( nBand == 4 )
-                eBandInterp = GCI_AlphaBand;
-            else
-                eBandInterp = GCI_Undefined;
-        }
+            bLookForExtraSamples = TRUE;
     }
     else if( poDS->nPhotometric == PHOTOMETRIC_YCBCR )
     {
@@ -598,22 +620,7 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
         else if( nBand == 3 )
             eBandInterp = GCI_YCbCr_CrBand;
         else
-        {
-            uint16 *v;
-            uint16 count = 0;
-
-            if( TIFFGetField( poDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v) )
-            {
-                if( nBand - 3 <= count && v[nBand-4] == EXTRASAMPLE_ASSOCALPHA )
-                    eBandInterp = GCI_AlphaBand;
-                else
-                    eBandInterp = GCI_Undefined;
-            }
-            else if( nBand == 4 )
-                eBandInterp = GCI_AlphaBand;
-            else
-                eBandInterp = GCI_Undefined;
-        }
+            bLookForExtraSamples = TRUE;
     }
     else if( poDS->nPhotometric == PHOTOMETRIC_SEPARATED )
     {
@@ -623,12 +630,17 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
             eBandInterp = GCI_MagentaBand;
         else if( nBand == 3 )
             eBandInterp = GCI_YellowBand;
-        else
+        else if( nBand == 4 )
             eBandInterp = GCI_BlackBand;
+        else
+            bLookForExtraSamples = TRUE;
     }
     else if( poDS->nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1 )
         eBandInterp = GCI_GrayIndex;
     else
+        bLookForExtraSamples = TRUE;
+        
+    if( bLookForExtraSamples )
     {
         uint16 *v;
         uint16 count = 0;
@@ -639,7 +651,8 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
             nBaseSamples = poDS->nSamplesPerPixel - count;
 
             if( nBand > nBaseSamples 
-                && v[nBand-nBaseSamples-1] == EXTRASAMPLE_ASSOCALPHA )
+                && (v[nBand-nBaseSamples-1] == EXTRASAMPLE_ASSOCALPHA
+                    || v[nBand-nBaseSamples-1] == EXTRASAMPLE_UNASSALPHA) )
                 eBandInterp = GCI_AlphaBand;
             else
                 eBandInterp = GCI_Undefined;
@@ -659,6 +672,167 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDS, int nBand )
 }
 
 /************************************************************************/
+/*                           DirectIO()                                 */
+/************************************************************************/
+
+/* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
+/* block reading. Restricted to simple TIFF configurations (single-band, un-tiled, */
+/* uncompressed data, standard data types). Particularly usefull to extract */
+/* sub-windows of data on a large /vsicurl dataset). */
+
+CPLErr GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
+                                  int nXOff, int nYOff, int nXSize, int nYSize,
+                                  void * pData, int nBufXSize, int nBufYSize,
+                                  GDALDataType eBufType,
+                                  int nPixelSpace, int nLineSpace )
+{
+    if( !(eRWFlag == GF_Read && poGDS->nBands == 1 &&
+          poGDS->nCompression == COMPRESSION_NONE &&
+          (poGDS->nBitsPerSample == 8 || (poGDS->nBitsPerSample == 16) ||
+           poGDS->nBitsPerSample == 32 || poGDS->nBitsPerSample == 64) &&
+          poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
+          !TIFFIsTiled( poGDS->hTIFF )) )
+    {
+        return CE_Failure;
+    }
+
+/* ==================================================================== */
+/*      Do we have overviews that would be appropriate to satisfy       */
+/*      this request?                                                   */
+/* ==================================================================== */
+    if( (nBufXSize < nXSize || nBufYSize < nYSize)
+        && GetOverviewCount() > 0 && eRWFlag == GF_Read )
+    {
+        int         nOverview;
+
+        nOverview =
+            GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
+                                        nBufXSize, nBufYSize);
+        if (nOverview >= 0)
+        {
+            GDALRasterBand* poOverviewBand = GetOverview(nOverview);
+            if (poOverviewBand == NULL)
+                return CE_Failure;
+
+            return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                            pData, nBufXSize, nBufYSize, eBufType,
+                                            nPixelSpace, nLineSpace );
+        }
+    }
+
+    /* 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 CE_Failure;
+    }
+
+    int iLine;
+    int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
+    int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
+    void** ppData = (void**) VSIMalloc(nReqYSize * sizeof(void*));
+    vsi_l_offset* panOffsets = (vsi_l_offset*)
+                            VSIMalloc(nReqYSize * sizeof(vsi_l_offset));
+    size_t* panSizes = (size_t*) VSIMalloc(nReqYSize * sizeof(size_t));
+    int eDTSize = GDALGetDataTypeSize(eDataType) / 8;
+    void* pTmpBuffer = NULL;
+    CPLErr eErr = CE_None;
+
+    if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
+        eErr = CE_Failure;
+    else if (nXSize != nBufXSize || nYSize != nBufYSize ||
+             eBufType != eDataType ||
+             nPixelSpace != GDALGetDataTypeSize(eBufType) / 8)
+    {
+        /* We need a temporary buffer for over-sampling/sub-sampling */
+        /* and/or data type conversion */
+        pTmpBuffer = VSIMalloc(nReqXSize * nReqYSize * eDTSize);
+        if (pTmpBuffer == NULL)
+            eErr = CE_Failure;
+    }
+
+    /* Prepare data extraction */
+    for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
+    {
+        if (pTmpBuffer == NULL)
+            ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
+        else
+            ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * eDTSize;
+        int nSrcLine;
+        if (nBufYSize < nYSize) /* Sub-sampling in y */
+            nSrcLine = nYOff + (int)((iLine + 0.5) * nYSize / nBufYSize);
+        else
+            nSrcLine = nYOff + iLine;
+        panOffsets[iLine] = panTIFFOffsets[nSrcLine / nBlockYSize];
+        if (panOffsets[iLine] == 0) /* We don't support sparse files */
+            eErr = CE_Failure;
+
+        panOffsets[iLine] += (nXOff + (nSrcLine % nBlockYSize) * nBlockXSize) * eDTSize;
+        panSizes[iLine] = nReqXSize * eDTSize;
+    }
+
+    /* Extract data from the file */
+    if (eErr == CE_None)
+    {
+        VSILFILE* fp = (VSILFILE*) TIFFClientdata( poGDS->hTIFF );
+        int nRet = VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
+        if (nRet != 0)
+            eErr = CE_Failure;
+    }
+
+    /* Byte-swap if necessary */
+    if (eErr == CE_None && TIFFIsByteSwapped(poGDS->hTIFF))
+    {
+        for(iLine=0;iLine<nReqYSize;iLine++)
+        {
+            GDALSwapWords( ppData[iLine], eDTSize, nReqXSize, eDTSize);
+        }
+    }
+
+    /* Over-sampling/sub-sampling and/or data type conversion */
+    if (eErr == CE_None && pTmpBuffer != NULL)
+    {
+        for(int iY=0;iY<nBufYSize;iY++)
+        {
+            int iSrcY = (nBufYSize <= nYSize) ? iY :
+                            (int)((iY + 0.5) * nYSize / nBufYSize);
+            if (nBufXSize == nXSize)
+            {
+                GDALCopyWords( ppData[iSrcY], eDataType, eDTSize,
+                                ((GByte*)pData) + iY * nLineSpace,
+                                eBufType, nPixelSpace,
+                                nReqXSize);
+            }
+            else
+            {
+                for(int iX=0;iX<nBufXSize;iX++)
+                {
+                    int iSrcX = (nBufXSize == nXSize) ? iX :
+                                    (int)((iX+0.5) * nXSize / nBufXSize);
+                    GDALCopyWords( ((GByte*)ppData[iSrcY]) + iSrcX * eDTSize,
+                                    eDataType, 0,
+                                    ((GByte*)pData) + iX * nPixelSpace + iY * nLineSpace,
+                                    eBufType, 0, 1);
+                }
+            }
+        }
+    }
+
+    /* Cleanup */
+    CPLFree(pTmpBuffer);
+    CPLFree(ppData);
+    CPLFree(panOffsets);
+    CPLFree(panSizes);
+
+    return eErr;
+}
+
+/************************************************************************/
 /*                            IRasterIO()                               */
 /************************************************************************/
 
@@ -670,6 +844,19 @@ CPLErr GTiffRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 {
     CPLErr eErr;
 
+    //CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)",
+    //         nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize);
+
+    if (poGDS->bDirectIO)
+    {
+        eErr = DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                        pData, nBufXSize, nBufYSize, eBufType,
+                        nPixelSpace, nLineSpace);
+
+        if (eErr == CE_None)
+            return eErr;
+    }
+
     if (poGDS->nBands != 1 &&
         poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
         eRWFlag == GF_Read &&
@@ -769,7 +956,8 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         if( TIFFIsTiled( poGDS->hTIFF ) )
         {
             if( TIFFReadEncodedTile( poGDS->hTIFF, nBlockId, pImage,
-                                     nBlockReqSize ) == -1 )
+                                     nBlockReqSize ) == -1
+                && !poGDS->bIgnoreReadErrors )
             {
                 memset( pImage, 0, nBlockBufSize );
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -781,12 +969,13 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         else
         {
             if( TIFFReadEncodedStrip( poGDS->hTIFF, nBlockId, pImage,
-                                      nBlockReqSize ) == -1 )
+                                      nBlockReqSize ) == -1
+                && !poGDS->bIgnoreReadErrors )
             {
                 memset( pImage, 0, nBlockBufSize );
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "TIFFReadEncodedStrip() failed.\n" );
-                
+                        "TIFFReadEncodedStrip() failed.\n" );
+
                 eErr = CE_Failure;
             }
         }
@@ -930,6 +1119,21 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         }
     }
 
+    if (eErr == CE_None)
+        eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
+
+    return eErr;
+}
+
+
+/************************************************************************/
+/*                       FillCacheForOtherBands()                       */
+/************************************************************************/
+
+CPLErr GTiffRasterBand::FillCacheForOtherBands( int nBlockXOff, int nBlockYOff )
+
+{
+    CPLErr eErr = CE_None;
 /* -------------------------------------------------------------------- */
 /*      In the fairly common case of pixel interleaved 8bit data        */
 /*      that is multi-band, lets push the rest of the data into the     */
@@ -946,7 +1150,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      If there are many bands and the block cache size is not big     */
 /*      enough to accomodate the size of all the blocks, don't enter    */
 /* -------------------------------------------------------------------- */
-    if( poGDS->nBands != 1 && eErr == CE_None && !poGDS->bLoadingOtherBands &&
+    if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands &&
         nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) < GDALGetCacheMax64() / poGDS->nBands)
     {
         int iOtherBand;
@@ -1530,7 +1734,14 @@ void GTiffRasterBand::NullBlock( void *pData )
     double dfNoData = GetNoDataValue( &bNoDataSet );
     if( !bNoDataSet )
     {
+#ifdef ESRI_BUILD
+        if ( poGDS->nBitsPerSample >= 2 )
+            memset( pData, 0, nWords*nChunkSize );
+        else
+            memset( pData, 1, nWords*nChunkSize );
+#else
         memset( pData, 0, nWords*nChunkSize );
+#endif
     }
     else
     {
@@ -1547,6 +1758,8 @@ void GTiffRasterBand::NullBlock( void *pData )
 int GTiffRasterBand::GetOverviewCount()
 
 {
+    poGDS->ScanDirectories();
+
     if( poGDS->nOverviewCount > 0 )
         return poGDS->nOverviewCount;
     else
@@ -1560,6 +1773,8 @@ int GTiffRasterBand::GetOverviewCount()
 GDALRasterBand *GTiffRasterBand::GetOverview( int i )
 
 {
+    poGDS->ScanDirectories();
+
     if( poGDS->nOverviewCount > 0 )
     {
         if( i < 0 || i >= poGDS->nOverviewCount )
@@ -1577,6 +1792,8 @@ GDALRasterBand *GTiffRasterBand::GetOverview( int i )
 
 int GTiffRasterBand::GetMaskFlags()
 {
+    poGDS->ScanDirectories();
+
     if( poGDS->poMaskDS != NULL )
     {
         if( poGDS->poMaskDS->GetRasterCount() == 1)
@@ -1598,6 +1815,8 @@ int GTiffRasterBand::GetMaskFlags()
 
 GDALRasterBand *GTiffRasterBand::GetMaskBand()
 {
+    poGDS->ScanDirectories();
+
     if( poGDS->poMaskDS != NULL )
     {
         if( poGDS->poMaskDS->GetRasterCount() == 1)
@@ -1699,7 +1918,8 @@ CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         if( TIFFReadScanline( poGDS->hTIFF,
                               poGDS->pabyBlockBuf ? poGDS->pabyBlockBuf : pImage,
                               ++poGDS->nLastLineRead,
-                              (poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE) ? nBand-1 : 0 ) == -1 )
+                              (poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE) ? (uint16) (nBand-1) : 0 ) == -1
+            && !poGDS->bIgnoreReadErrors )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadScanline() failed." );
@@ -1823,7 +2043,8 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
             if( TIFFReadRGBATile(poGDS->hTIFF, 
                                  nBlockXOff * nBlockXSize, 
                                  nBlockYOff * nBlockYSize,
-                                 (uint32 *) poGDS->pabyBlockBuf) == -1 )
+                                 (uint32 *) poGDS->pabyBlockBuf) == -1
+                && !poGDS->bIgnoreReadErrors )
             {
                 /* Once TIFFError() is properly hooked, this can go away */
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -1838,7 +2059,8 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
         {
             if( TIFFReadRGBAStrip(poGDS->hTIFF, 
                                   nBlockId * nBlockYSize,
-                                  (uint32 *) poGDS->pabyBlockBuf) == -1 )
+                                  (uint32 *) poGDS->pabyBlockBuf) == -1
+                && !poGDS->bIgnoreReadErrors )
             {
                 /* Once TIFFError() is properly hooked, this can go away */
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -1882,6 +2104,9 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
                        nBlockXSize );
     }
 
+    if (eErr == CE_None)
+        eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
+
     return eErr;
 }
 
@@ -2530,6 +2755,9 @@ GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDS, int nBand )
         poColorTable = poDS->poColorTable->Clone();
     else
     {
+#ifdef ESRI_BUILD
+        poColorTable = NULL;
+#else
         GDALColorEntry	oWhite, oBlack;
 
         oWhite.c1 = 255;
@@ -2554,6 +2782,7 @@ GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDS, int nBand )
             poColorTable->SetColorEntry( 0, &oBlack );
             poColorTable->SetColorEntry( 1, &oWhite );
         }
+#endif /* not defined ESRI_BUILD */
     }
 }
 
@@ -2659,7 +2888,8 @@ CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     while( poGDS->nLastLineRead < nBlockYOff )
     {
-        if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf, ++poGDS->nLastLineRead, 0 ) == -1 )
+        if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf, ++poGDS->nLastLineRead, 0 ) == -1
+            && !poGDS->bIgnoreReadErrors )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadScanline() failed." );
@@ -2775,6 +3005,16 @@ GTiffDataset::GTiffDataset()
     bPromoteTo8Bits = FALSE;
 
     bDebugDontWriteBlocks = CSLTestBoolean(CPLGetConfigOption("GTIFF_DONT_WRITE_BLOCKS", "NO"));
+
+    bIsFinalized = FALSE;
+    bIgnoreReadErrors = CSLTestBoolean(CPLGetConfigOption("GTIFF_IGNORE_READ_ERRORS", "NO"));
+
+    bHasSearchedRPC = FALSE;
+    bHasSearchedIMD = FALSE;
+
+    bScanDeferred = TRUE;
+
+    bDirectIO = CSLTestBoolean(CPLGetConfigOption("GTIFF_DIRECT_IO", "NO"));
 }
 
 /************************************************************************/
@@ -2784,6 +3024,20 @@ GTiffDataset::GTiffDataset()
 GTiffDataset::~GTiffDataset()
 
 {
+    Finalize();
+}
+
+/************************************************************************/
+/*                             Finalize()                               */
+/************************************************************************/
+
+int GTiffDataset::Finalize()
+{
+    if (bIsFinalized)
+        return FALSE;
+
+    int bHasDroppedRef = FALSE;
+
     Crystalize();
 
 /* -------------------------------------------------------------------- */
@@ -2837,41 +3091,76 @@ GTiffDataset::~GTiffDataset()
         for( int i = 0; i < nOverviewCount; i++ )
         {
             delete papoOverviewDS[i];
+            bHasDroppedRef = TRUE;
         }
+        nOverviewCount = 0;
     }
 
     /* If we are a mask dataset, we can have overviews, but we don't */
     /* own them. We can only free the array, not the overviews themselves */
     CPLFree( papoOverviewDS );
+    papoOverviewDS = NULL;
 
     /* poMaskDS is owned by the main image and the overviews */
     /* so because of the latter case, we can delete it even if */
     /* we are not the base image */
     if (poMaskDS)
+    {
         delete poMaskDS;
+        poMaskDS = NULL;
+        bHasDroppedRef = TRUE;
+    }
 
     if( poColorTable != NULL )
         delete poColorTable;
+    poColorTable = NULL;
 
     if( bBase || bCloseTIFFHandle )
     {
         XTIFFClose( hTIFF );
+        hTIFF = NULL;
     }
 
     if( nGCPCount > 0 )
     {
         GDALDeinitGCPs( nGCPCount, pasGCPList );
         CPLFree( pasGCPList );
+        pasGCPList = NULL;
+        nGCPCount = 0;
     }
 
     CPLFree( pszProjection );
+    pszProjection = NULL;
 
     CSLDestroy( papszCreationOptions );
+    papszCreationOptions = NULL;
 
     CPLFree(pabyTempWriteBuffer);
+    pabyTempWriteBuffer = NULL;
 
     if( *ppoActiveDSRef == this )
         *ppoActiveDSRef = NULL;
+    ppoActiveDSRef = NULL;
+
+    bIsFinalized = TRUE;
+
+    return bHasDroppedRef;
+}
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int GTiffDataset::CloseDependentDatasets()
+{
+    if (!bBase)
+        return FALSE;
+
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
+    bHasDroppedRef |= Finalize();
+
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -3253,7 +3542,8 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
     if( TIFFIsTiled( hTIFF ) )
     {
         if( TIFFReadEncodedTile(hTIFF, nBlockId, pabyBlockBuf,
-                                nBlockReqSize) == -1 )
+                                nBlockReqSize) == -1
+            && !bIgnoreReadErrors )
         {
             /* Once TIFFError() is properly hooked, this can go away */
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -3267,7 +3557,8 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
     else
     {
         if( TIFFReadEncodedStrip(hTIFF, nBlockId, pabyBlockBuf,
-                                 nBlockReqSize) == -1 )
+                                 nBlockReqSize) == -1
+            && !bIgnoreReadErrors )
         {
             /* Once TIFFError() is properly hooked, this can go away */
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -3371,6 +3662,9 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
 void GTiffDataset::FlushCache()
 
 {
+    if (bIsFinalized)
+        return;
+
     GDALPamDataset::FlushCache();
 
     if( bLoadedBlockDirty && nLoadedBlock != -1 )
@@ -3502,6 +3796,8 @@ CPLErr GTiffDataset::CleanOverviews()
 {
     CPLAssert( bBase );
 
+    ScanDirectories();
+
     FlushDirectory();
     *ppoActiveDSRef = NULL;
 
@@ -3535,7 +3831,7 @@ CPLErr GTiffDataset::CleanOverviews()
             {
                 CPLDebug( "GTiff", "%d -> %d", 
                           (int) anOvDirOffsets[i], iThisOffset );
-                anOvDirIndexes.push_back( iThisOffset );
+                anOvDirIndexes.push_back( (uint16) iThisOffset );
             }
         }
         
@@ -3593,6 +3889,7 @@ CPLErr GTiffDataset::RegisterNewOverviewDataset(toff_t nOverviewOffset)
     if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nOverviewOffset, FALSE,
                             GA_Update ) != CE_None )
     {
+        delete poODS;
         return CE_Failure;
     }
     else
@@ -3616,6 +3913,8 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
     CPLAssert(poSrcDS->GetRasterCount() != 0);
     CPLAssert(nOverviewCount == 0);
 
+    ScanDirectories();
+
 /* -------------------------------------------------------------------- */
 /*      Move to the directory for this dataset.                         */
 /* -------------------------------------------------------------------- */
@@ -3752,6 +4051,9 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
                                                  int nOvrBlockYSize)
 {
     GTiffDataset *poODS;
+
+    ScanDirectories();
+
 /* -------------------------------------------------------------------- */
 /*      Create overviews for the mask.                                  */
 /* -------------------------------------------------------------------- */
@@ -3831,6 +4133,9 @@ CPLErr GTiffDataset::IBuildOverviews(
     CPLErr       eErr = CE_None;
     int          i;
     GTiffDataset *poODS;
+    int          bUseGenericHandling = FALSE;
+
+    ScanDirectories();
 
 /* -------------------------------------------------------------------- */
 /*      If RRD or external OVR overviews requested, then invoke         */
@@ -3839,9 +4144,7 @@ CPLErr GTiffDataset::IBuildOverviews(
     if( CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" )) 
         || CSLTestBoolean(CPLGetConfigOption( "TIFF_USE_OVR", "NO" )) )
     {
-        return GDALDataset::IBuildOverviews( 
-            pszResampling, nOverviews, panOverviewList, 
-            nBands, panBandList, pfnProgress, pProgressData );
+        bUseGenericHandling = TRUE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -3854,8 +4157,20 @@ CPLErr GTiffDataset::IBuildOverviews(
                   "File open for read-only accessing, "
                   "creating overviews externally." );
 
-        return GDALDataset::IBuildOverviews( 
-            pszResampling, nOverviews, panOverviewList, 
+        bUseGenericHandling = TRUE;
+    }
+
+    if( bUseGenericHandling )
+    {
+        if (nOverviewCount != 0)
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Cannot add external overviews when there are already internal overviews");
+            return CE_Failure;
+        }
+
+        return GDALDataset::IBuildOverviews(
+            pszResampling, nOverviews, panOverviewList,
             nBands, panBandList, pfnProgress, pProgressData );
     }
 
@@ -4259,7 +4574,7 @@ void GTiffDataset::WriteGeoTIFFInfo()
 /* -------------------------------------------------------------------- */
     if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
         || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
-        || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0 )
+        || adfGeoTransform[4] != 0.0 || ABS(adfGeoTransform[5]) != 1.0 )
     {
         bNeedsRewrite = TRUE;
 
@@ -4277,48 +4592,48 @@ void GTiffDataset::WriteGeoTIFFInfo()
 /*      Write the transform.  If we have a normal north-up image we     */
 /*      use the tiepoint plus pixelscale otherwise we use a matrix.     */
 /* -------------------------------------------------------------------- */
-	if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 
-            && adfGeoTransform[5] < 0.0 )
-	{
-	    double	adfPixelScale[3], adfTiePoints[6];
+        if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
+                && adfGeoTransform[5] < 0.0 )
+        {
+            double	adfPixelScale[3], adfTiePoints[6];
 
-	    adfPixelScale[0] = adfGeoTransform[1];
-	    adfPixelScale[1] = fabs(adfGeoTransform[5]);
-	    adfPixelScale[2] = 0.0;
+            adfPixelScale[0] = adfGeoTransform[1];
+            adfPixelScale[1] = fabs(adfGeoTransform[5]);
+            adfPixelScale[2] = 0.0;
 
             if( !EQUAL(osProfile,"BASELINE") )
                 TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
-	    
-	    adfTiePoints[0] = 0.0;
-	    adfTiePoints[1] = 0.0;
-	    adfTiePoints[2] = 0.0;
-	    adfTiePoints[3] = adfGeoTransform[0];
-	    adfTiePoints[4] = adfGeoTransform[3];
-	    adfTiePoints[5] = 0.0;
+
+            adfTiePoints[0] = 0.0;
+            adfTiePoints[1] = 0.0;
+            adfTiePoints[2] = 0.0;
+            adfTiePoints[3] = adfGeoTransform[0];
+            adfTiePoints[4] = adfGeoTransform[3];
+            adfTiePoints[5] = 0.0;
 
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
                 adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
                 adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
             }
-	    
+
             if( !EQUAL(osProfile,"BASELINE") )
                 TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
-	}
-	else
-	{
-	    double	adfMatrix[16];
-	    
-	    memset(adfMatrix,0,sizeof(double) * 16);
-	    
-	    adfMatrix[0] = adfGeoTransform[1];
-	    adfMatrix[1] = adfGeoTransform[2];
-	    adfMatrix[3] = adfGeoTransform[0];
-	    adfMatrix[4] = adfGeoTransform[4];
-	    adfMatrix[5] = adfGeoTransform[5];
-	    adfMatrix[7] = adfGeoTransform[3];
-	    adfMatrix[15] = 1.0;
-	    
+        }
+        else
+        {
+            double	adfMatrix[16];
+
+            memset(adfMatrix,0,sizeof(double) * 16);
+
+            adfMatrix[0] = adfGeoTransform[1];
+            adfMatrix[1] = adfGeoTransform[2];
+            adfMatrix[3] = adfGeoTransform[0];
+            adfMatrix[4] = adfGeoTransform[4];
+            adfMatrix[5] = adfGeoTransform[5];
+            adfMatrix[7] = adfGeoTransform[3];
+            adfMatrix[15] = 1.0;
+
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
                 adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
@@ -4327,7 +4642,7 @@ void GTiffDataset::WriteGeoTIFFInfo()
 
             if( !EQUAL(osProfile,"BASELINE") )
                 TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
-	}
+        }
 
         // Do we need a world file?
         if( CSLFetchBoolean( papszCreationOptions, "TFW", FALSE ) )
@@ -4337,34 +4652,35 @@ void GTiffDataset::WriteGeoTIFFInfo()
     }
     else if( GetGCPCount() > 0 )
     {
-	double	*padfTiePoints;
-	int		iGCP;
+        double	*padfTiePoints;
+        int		iGCP;
+
         bNeedsRewrite = TRUE;
-	
-	padfTiePoints = (double *) 
-	    CPLMalloc( 6 * sizeof(double) * GetGCPCount() );
 
-	for( iGCP = 0; iGCP < GetGCPCount(); iGCP++ )
-	{
+        padfTiePoints = (double *)
+            CPLMalloc( 6 * sizeof(double) * GetGCPCount() );
 
-	    padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
-	    padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine;
-	    padfTiePoints[iGCP*6+2] = 0;
-	    padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX;
-	    padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY;
-	    padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ;
+        for( iGCP = 0; iGCP < GetGCPCount(); iGCP++ )
+        {
+
+            padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
+            padfTiePoints[iGCP*6+1] = pasGCPList[iGCP].dfGCPLine;
+            padfTiePoints[iGCP*6+2] = 0;
+            padfTiePoints[iGCP*6+3] = pasGCPList[iGCP].dfGCPX;
+            padfTiePoints[iGCP*6+4] = pasGCPList[iGCP].dfGCPY;
+            padfTiePoints[iGCP*6+5] = pasGCPList[iGCP].dfGCPZ;
 
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
                 padfTiePoints[iGCP*6+0] += 0.5;
                 padfTiePoints[iGCP*6+1] += 0.5;
             }
-	}
+        }
 
         if( !EQUAL(osProfile,"BASELINE") )
             TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 
                           6 * GetGCPCount(), padfTiePoints );
-	CPLFree( padfTiePoints );
+        CPLFree( padfTiePoints );
     }
 
 /* -------------------------------------------------------------------- */
@@ -4541,11 +4857,15 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
                 else if( EQUAL(pszItemName,"TIFFTAG_COPYRIGHT") )
                     TIFFSetField( hTIFF, TIFFTAG_COPYRIGHT, pszItemValue );
                 else if( EQUAL(pszItemName,"TIFFTAG_XRESOLUTION") )
-                    TIFFSetField( hTIFF, TIFFTAG_XRESOLUTION, atof(pszItemValue) );
+                    TIFFSetField( hTIFF, TIFFTAG_XRESOLUTION, CPLAtof(pszItemValue) );
                 else if( EQUAL(pszItemName,"TIFFTAG_YRESOLUTION") )
-                    TIFFSetField( hTIFF, TIFFTAG_YRESOLUTION, atof(pszItemValue) );
+                    TIFFSetField( hTIFF, TIFFTAG_YRESOLUTION, CPLAtof(pszItemValue) );
                 else if( EQUAL(pszItemName,"TIFFTAG_RESOLUTIONUNIT") )
                     TIFFSetField( hTIFF, TIFFTAG_RESOLUTIONUNIT, atoi(pszItemValue) );
+                else if( EQUAL(pszItemName,"TIFFTAG_MINSAMPLEVALUE") )
+                    TIFFSetField( hTIFF, TIFFTAG_MINSAMPLEVALUE, atoi(pszItemValue) );
+                else if( EQUAL(pszItemName,"TIFFTAG_MAXSAMPLEVALUE") )
+                    TIFFSetField( hTIFF, TIFFTAG_MAXSAMPLEVALUE, atoi(pszItemValue) );
                 else
                     CPLError(CE_Warning, CPLE_NotSupported,
                              "%s metadata item is unhandled and will not be written",
@@ -4801,16 +5121,8 @@ void GTiffDataset::PushMetadataToPam()
 /* -------------------------------------------------------------------- */
         if( poBand != NULL )
         {
-            int bSuccess;
-            double dfOffset = poBand->GetOffset( &bSuccess );
-            double dfScale = poBand->GetScale();
-
-            if( bSuccess )
-            {
-                poBand->GDALPamRasterBand::SetScale( dfScale );
-                poBand->GDALPamRasterBand::SetOffset( dfOffset );
-            }
-
+            poBand->GDALPamRasterBand::SetOffset( poBand->GetOffset() );
+            poBand->GDALPamRasterBand::SetScale( poBand->GetScale() );
             poBand->GDALPamRasterBand::SetUnitType( poBand->GetUnitType() );
         }
     }
@@ -5171,7 +5483,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
-    poDS->TryLoadXML();
+    poDS->TryLoadXML( poOpenInfo->papszSiblingFiles);
     poDS->ApplyPamInfo();
 
     int i;
@@ -5199,7 +5511,7 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, pszFilename );
+    poDS->oOvManager.Initialize( poDS, pszFilename, poOpenInfo->papszSiblingFiles );
     
     return poDS;
 }
@@ -5260,6 +5572,11 @@ void GTiffDataset::LookForProjection()
         // Is this a pixel-is-point dataset?
         short nRasterType;
 
+        // check the tif linear unit and the CS linear unit 
+#ifdef ESRI_BUILD
+        AdjustLinearUnit(sGTIFDefn.UOMLength); 
+#endif
+
         if( GTIFKeyGet(hGTIF, GTRasterTypeGeoKey, &nRasterType, 
                        0, 1 ) == 1 )
         {
@@ -5281,6 +5598,47 @@ void GTiffDataset::LookForProjection()
 }
 
 /************************************************************************/
+/*                          AdjustLinearUnit()                          */
+/*                                                                      */
+/*      The following code is only used in ESRI Builds and there is     */
+/*      outstanding discussion on whether it is even appropriate        */
+/*      then.                                                           */
+/************************************************************************/
+#ifdef ESRI_BUILD
+
+void GTiffDataset::AdjustLinearUnit(short UOMLength)
+{
+    if (!pszProjection || strlen(pszProjection) == 0)
+        return;
+    if( UOMLength == 9001)
+    {
+        char* pstr = strstr(pszProjection, "PARAMETER");
+        if (!pstr)
+            return;
+        pstr = strstr(pstr, "UNIT[");
+        if (!pstr)
+            return;
+        pstr = strchr(pstr, ',') + 1;
+        if (!pstr)
+            return;
+        char* pstr1 = strchr(pstr, ']');
+        if (!pstr1 || pstr1 - pstr >= 128)
+            return;
+        char csUnitStr[128];
+        strncpy(csUnitStr, pstr, pstr1-pstr);
+        csUnitStr[pstr1-pstr] = '\0';
+        double csUnit = CPLAtof(csUnitStr);
+        if(fabs(csUnit - 1.0) > 0.000001)
+        {
+            for(long i=0; i<6; i++)
+                adfGeoTransform[i] /= csUnit;
+        }
+    }
+}
+
+#endif /* def ESRI_BUILD */
+
+/************************************************************************/
 /*                            ApplyPamInfo()                            */
 /*                                                                      */
 /*      PAM Information, if available, overrides the GeoTIFF            */
@@ -5335,21 +5693,21 @@ void GTiffDataset::ApplyPamInfo()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Copy any PAM metadata into our GeoTIFF context, but with the    */
-/*      GeoTIFF context overriding the PAM info.                        */
+/*      Copy any PAM metadata into our GeoTIFF context, and with        */
+/*      the PAM info overriding the GeoTIFF context.                    */
 /* -------------------------------------------------------------------- */
     char **papszPamDomains = oMDMD.GetDomainList();
 
     for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
     {
         const char *pszDomain = papszPamDomains[iDomain];
-        char **papszGT_MD = oGTiffMDMD.GetMetadata( pszDomain );
-        char **papszPAM_MD = CSLDuplicate(oMDMD.GetMetadata( pszDomain ));
+        char **papszGT_MD = CSLDuplicate(oGTiffMDMD.GetMetadata( pszDomain ));
+        char **papszPAM_MD = oMDMD.GetMetadata( pszDomain );
 
-        papszPAM_MD = CSLMerge( papszPAM_MD, papszGT_MD );
+        papszGT_MD = CSLMerge( papszGT_MD, papszPAM_MD );
 
-        oGTiffMDMD.SetMetadata( papszPAM_MD, pszDomain );
-        CSLDestroy( papszPAM_MD );
+        oGTiffMDMD.SetMetadata( papszGT_MD, pszDomain );
+        CSLDestroy( papszGT_MD );
     }
 
     for( int i = 1; i <= GetRasterCount(); i++)
@@ -5360,13 +5718,13 @@ void GTiffDataset::ApplyPamInfo()
         for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
         {
             const char *pszDomain = papszPamDomains[iDomain];
-            char **papszGT_MD = poBand->oGTiffMDMD.GetMetadata( pszDomain );
-            char **papszPAM_MD = CSLDuplicate(poBand->oMDMD.GetMetadata( pszDomain ));
+            char **papszGT_MD = CSLDuplicate(poBand->oGTiffMDMD.GetMetadata( pszDomain ));
+            char **papszPAM_MD = poBand->oMDMD.GetMetadata( pszDomain );
 
-            papszPAM_MD = CSLMerge( papszPAM_MD, papszGT_MD );
+            papszGT_MD = CSLMerge( papszGT_MD, papszPAM_MD );
 
-            poBand->oGTiffMDMD.SetMetadata( papszPAM_MD, pszDomain );
-            CSLDestroy( papszPAM_MD );
+            poBand->oGTiffMDMD.SetMetadata( papszGT_MD, pszDomain );
+            CSLDestroy( papszGT_MD );
         }
     }
 }
@@ -5898,24 +6256,35 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
         else
         {
-            bGeoTransformValid = 
-                GDALReadWorldFile( osFilename, NULL, adfGeoTransform );
+            char* pszWldFilename = NULL;
+
+            bGeoTransformValid =
+                GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
+                                    papszSiblingFiles, &pszWldFilename);
 
             if( !bGeoTransformValid )
             {
-                bGeoTransformValid = 
-                    GDALReadWorldFile( osFilename, "wld", adfGeoTransform );
+                bGeoTransformValid =
+                    GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
+                                        papszSiblingFiles, &pszWldFilename);
             }
 
             if( !bGeoTransformValid )
             {
-                int bTabFileOK = 
-                    GDALReadTabFile( osFilename, adfGeoTransform, 
-                                     &pszTabWKT, &nGCPCount, &pasGCPList );
+                int bTabFileOK =
+                    GDALReadTabFile2( osFilename, adfGeoTransform,
+                                      &pszTabWKT, &nGCPCount, &pasGCPList,
+                                      papszSiblingFiles, &pszWldFilename );
 
                 if( bTabFileOK && nGCPCount == 0 )
                     bGeoTransformValid = TRUE;
             }
+
+            if (pszWldFilename)
+            {
+                osWldFilename = pszWldFilename;
+                CPLFree(pszWldFilename);
+            }
         }
 
 /* -------------------------------------------------------------------- */
@@ -6031,6 +6400,25 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         SetMetadataItem( "TIFFTAG_RESOLUTIONUNIT", szWorkMDI );
     }
 
+    int nTagSize;
+    void* pData;
+    if( TIFFGetField( hTIFF, TIFFTAG_XMLPACKET, &nTagSize, &pData ) )
+    {
+        char* pszXMP = (char*)VSIMalloc(nTagSize + 1);
+        if (pszXMP)
+        {
+            memcpy(pszXMP, pData, nTagSize);
+            pszXMP[nTagSize] = '\0';
+
+            char *apszMDList[2];
+            apszMDList[0] = pszXMP;
+            apszMDList[1] = NULL;
+            SetMetadata(apszMDList, "xml:XMP");
+
+            CPLFree(pszXMP);
+        }
+    }
+
     if( nCompression == COMPRESSION_NONE )
         /* no compression tag */;
     else if( nCompression == COMPRESSION_CCITTRLE )
@@ -6180,44 +6568,6 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     bMetadataChanged = FALSE;
 
 /* -------------------------------------------------------------------- */
-/*      Check for RPC metadata in an RPB or _rpc.txt file.              */
-/* -------------------------------------------------------------------- */
-    if( bBaseIn )
-    {
-        char **papszRPCMD = NULL;
-        /* Read Digital Globe .RPB file */
-        if (FindRPBFile(papszSiblingFiles))
-            papszRPCMD = GDALLoadRPBFile( osRPBFile.c_str(), NULL );
-        /* Read GeoEye _rpc.txt file */
-        if(papszRPCMD == NULL && FindRPCFile(papszSiblingFiles))
-            papszRPCMD = GDALLoadRPCFile( osRPCFile.c_str(), NULL );
-
-        if( papszRPCMD != NULL )
-        {
-            oGTiffMDMD.SetMetadata( papszRPCMD, "RPC" );
-            CSLDestroy( papszRPCMD );
-            bMetadataChanged = FALSE;
-        }
-        else
-            ReadRPCTag();
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Check for RPC metadata in an RPB file.                          */
-/* -------------------------------------------------------------------- */
-    if( bBaseIn && FindIMDFile(papszSiblingFiles) )
-    {
-        char **papszIMDMD = GDALLoadIMDFile( osIMDFile.c_str(), NULL );
-
-        if( papszIMDMD != NULL )
-        {
-            oGTiffMDMD.SetMetadata( papszIMDMD, "IMD" );
-            CSLDestroy( papszIMDMD );
-            bMetadataChanged = FALSE;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Check for NODATA                                                */
 /* -------------------------------------------------------------------- */
     if( TIFFGetField( hTIFF, TIFFTAG_GDAL_NODATA, &pszText ) )
@@ -6232,185 +6582,219 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
     if( bBase )
     {
-        char **papszSubdatasets = NULL;
-        int  iDirIndex = 0;
+        //ScanDirectories();
+    }
 
-        FlushDirectory();  
-        while( !TIFFLastDirectory( hTIFF ) 
-               && (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
-        {
-            toff_t	nThisDir = TIFFCurrentDirOffset(hTIFF);
-            uint32	nSubType = 0;
+    return( CE_None );
+}
+
+/************************************************************************/
+/*                          ScanDirectories()                           */
+/*                                                                      */
+/*      Scan through all the directories finding overviews, masks       */
+/*      and subdatasets.                                                */
+/************************************************************************/
+
+void GTiffDataset::ScanDirectories()
+
+{
+/* -------------------------------------------------------------------- */
+/*      We only scan once.  We do not scan for non-base datasets.       */
+/* -------------------------------------------------------------------- */
+    if( !bScanDeferred )
+        return;
+
+    bScanDeferred = FALSE;
+
+    if( !bBase )
+        return;
+
+    if( TIFFLastDirectory( hTIFF ) )
+        return;
+
+    CPLDebug( "GTiff", "ScanDirectories()" );
 
-            *ppoActiveDSRef = NULL; // our directory no longer matches this ds
+/* ==================================================================== */
+/*      Scan all directories.                                           */
+/* ==================================================================== */
+    char **papszSubdatasets = NULL;
+    int  iDirIndex = 0;
+
+    FlushDirectory();  
+    while( !TIFFLastDirectory( hTIFF ) 
+           && (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
+    {
+        toff_t	nThisDir = TIFFCurrentDirOffset(hTIFF);
+        uint32	nSubType = 0;
+
+        *ppoActiveDSRef = NULL; // our directory no longer matches this ds
             
-            iDirIndex++;
+        iDirIndex++;
 
-            if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
-                nSubType = 0;
+        if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
+            nSubType = 0;
 
-            /* Embedded overview of the main image */
-            if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
-                (nSubType & FILETYPE_MASK) == 0 &&
-                iDirIndex != 1 )
-            {
-                GTiffDataset	*poODS;
+        /* Embedded overview of the main image */
+        if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
+            (nSubType & FILETYPE_MASK) == 0 &&
+            iDirIndex != 1 )
+        {
+            GTiffDataset	*poODS;
                 
-                poODS = new GTiffDataset();
-                if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE, 
-                                       eAccess ) != CE_None 
-                    || poODS->GetRasterCount() != GetRasterCount() )
-                {
-                    delete poODS;
-                }
-                else
-                {
-                    CPLDebug( "GTiff", "Opened %dx%d overview.\n", 
-                              poODS->GetRasterXSize(), poODS->GetRasterYSize());
-                    nOverviewCount++;
-                    papoOverviewDS = (GTiffDataset **)
-                        CPLRealloc(papoOverviewDS, 
-                                   nOverviewCount * (sizeof(void*)));
-                    papoOverviewDS[nOverviewCount-1] = poODS;
-                    poODS->poBaseDS = this;
-                }
+            poODS = new GTiffDataset();
+            if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE, 
+                                   eAccess ) != CE_None 
+                || poODS->GetRasterCount() != GetRasterCount() )
+            {
+                delete poODS;
             }
-            
-            /* Embedded mask of the main image */
-            else if ((nSubType & FILETYPE_MASK) != 0 &&
-                     (nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
-                     poMaskDS == NULL )
+            else
             {
-                poMaskDS = new GTiffDataset();
+                CPLDebug( "GTiff", "Opened %dx%d overview.\n", 
+                          poODS->GetRasterXSize(), poODS->GetRasterYSize());
+                nOverviewCount++;
+                papoOverviewDS = (GTiffDataset **)
+                    CPLRealloc(papoOverviewDS, 
+                               nOverviewCount * (sizeof(void*)));
+                papoOverviewDS[nOverviewCount-1] = poODS;
+                poODS->poBaseDS = this;
+            }
+        }
+            
+        /* Embedded mask of the main image */
+        else if ((nSubType & FILETYPE_MASK) != 0 &&
+                 (nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
+                 poMaskDS == NULL )
+        {
+            poMaskDS = new GTiffDataset();
                 
-                /* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
-                   Here we support either 1 or 8 bit per sample
-                   and we support either 1 sample per pixel or as many samples as in the main image
-                   We don't check the value of the PhotometricInterpretation tag, which should be
-                   set to "Transparency mask" (4) according to the specification (page 36)
-                   ... But the TIFF6 specification allows image masks to have a higher resolution than
-                   the main image, what we don't support here
-                */
-
-                if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, 
-                                          FALSE, eAccess ) != CE_None 
-                    || poMaskDS->GetRasterCount() == 0
-                    || !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
-                    || poMaskDS->GetRasterXSize() != GetRasterXSize()
-                    || poMaskDS->GetRasterYSize() != GetRasterYSize()
-                    || poMaskDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
-                {
-                    delete poMaskDS;
-                    poMaskDS = NULL;
-                }
-                else
-                {
-                    CPLDebug( "GTiff", "Opened band mask.\n");
-                    poMaskDS->poBaseDS = this;
+            /* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
+               Here we support either 1 or 8 bit per sample
+               and we support either 1 sample per pixel or as many samples as in the main image
+               We don't check the value of the PhotometricInterpretation tag, which should be
+               set to "Transparency mask" (4) according to the specification (page 36)
+               ... But the TIFF6 specification allows image masks to have a higher resolution than
+               the main image, what we don't support here
+            */
+
+            if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, 
+                                      FALSE, eAccess ) != CE_None 
+                || poMaskDS->GetRasterCount() == 0
+                || !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
+                || poMaskDS->GetRasterXSize() != GetRasterXSize()
+                || poMaskDS->GetRasterYSize() != GetRasterYSize()
+                || poMaskDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
+            {
+                delete poMaskDS;
+                poMaskDS = NULL;
+            }
+            else
+            {
+                CPLDebug( "GTiff", "Opened band mask.\n");
+                poMaskDS->poBaseDS = this;
                     
-                    poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
-                }
+                poMaskDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
             }
+        }
             
-            /* Embedded mask of an overview */
-            /* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
-            else if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
-                     (nSubType & FILETYPE_MASK) != 0)
+        /* Embedded mask of an overview */
+        /* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
+        else if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
+                 (nSubType & FILETYPE_MASK) != 0)
+        {
+            GTiffDataset* poDS = new GTiffDataset();
+            if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE, 
+                                  eAccess ) != CE_None
+                || poDS->GetRasterCount() == 0
+                || poDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
             {
-                GTiffDataset* poDS = new GTiffDataset();
-                if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE, 
-                                      eAccess ) != CE_None
-                    || poDS->GetRasterCount() == 0
-                    || poDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
-                {
-                    delete poDS;
-                }
-                else
+                delete poDS;
+            }
+            else
+            {
+                int i;
+                for(i=0;i<nOverviewCount;i++)
                 {
-                    int i;
-                    for(i=0;i<nOverviewCount;i++)
+                    if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS == NULL &&
+                        poDS->GetRasterXSize() == papoOverviewDS[i]->GetRasterXSize() &&
+                        poDS->GetRasterYSize() == papoOverviewDS[i]->GetRasterYSize() &&
+                        (poDS->GetRasterCount() == 1 || poDS->GetRasterCount() == GetRasterCount()))
                     {
-                        if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS == NULL &&
-                            poDS->GetRasterXSize() == papoOverviewDS[i]->GetRasterXSize() &&
-                            poDS->GetRasterYSize() == papoOverviewDS[i]->GetRasterYSize() &&
-                            (poDS->GetRasterCount() == 1 || poDS->GetRasterCount() == GetRasterCount()))
-                        {
-                            CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
-                                      poDS->GetRasterXSize(), poDS->GetRasterYSize());
-                            ((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
-                            poDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
-                            poDS->poBaseDS = this;
-                            break;
-                        }
-                    }
-                    if (i == nOverviewCount)
-                    {
-                        delete poDS;
+                        CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
+                                  poDS->GetRasterXSize(), poDS->GetRasterYSize());
+                        ((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
+                        poDS->bPromoteTo8Bits = CSLTestBoolean(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+                        poDS->poBaseDS = this;
+                        break;
                     }
                 }
+                if (i == nOverviewCount)
+                {
+                    delete poDS;
+                }
             }
-            else if( nSubType == 0 ) {
-                CPLString osName, osDesc;
-                uint32	nXSize, nYSize;
-                uint16  nSPP;
-
-                TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
-                TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
-                if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
-                    nSPP = 1;
-
-                osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s", 
-                               iDirIndex, iDirIndex, osFilename.c_str() );
-                osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)", 
-                               iDirIndex, iDirIndex, 
-                               (int)nXSize, (int)nYSize, nSPP );
-
-                papszSubdatasets = 
-                    CSLAddString( papszSubdatasets, osName );
-                papszSubdatasets = 
-                    CSLAddString( papszSubdatasets, osDesc );
-            }
+        }
+        else if( nSubType == 0 || nSubType == FILETYPE_PAGE ) {
+            CPLString osName, osDesc;
+            uint32	nXSize, nYSize;
+            uint16  nSPP;
+
+            TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
+            TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
+            if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
+                nSPP = 1;
+
+            osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s", 
+                           iDirIndex, iDirIndex, osFilename.c_str() );
+            osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)", 
+                           iDirIndex, iDirIndex, 
+                           (int)nXSize, (int)nYSize, nSPP );
 
-            // Make sure we are stepping from the expected directory regardless
-            // of churn done processing the above.
-            if( TIFFCurrentDirOffset(hTIFF) != nThisDir )
-                TIFFSetSubDirectory( hTIFF, nThisDir );
-            *ppoActiveDSRef = NULL;
+            papszSubdatasets = 
+                CSLAddString( papszSubdatasets, osName );
+            papszSubdatasets = 
+                CSLAddString( papszSubdatasets, osDesc );
         }
 
-        /* If we have a mask for the main image, loop over the overviews, and if they */
-        /* have a mask, let's set this mask as an overview of the main mask... */
-        if (poMaskDS != NULL)
+        // Make sure we are stepping from the expected directory regardless
+        // of churn done processing the above.
+        if( TIFFCurrentDirOffset(hTIFF) != nThisDir )
+            TIFFSetSubDirectory( hTIFF, nThisDir );
+        *ppoActiveDSRef = NULL;
+    }
+
+    /* If we have a mask for the main image, loop over the overviews, and if they */
+    /* have a mask, let's set this mask as an overview of the main mask... */
+    if (poMaskDS != NULL)
+    {
+        int i;
+        for(i=0;i<nOverviewCount;i++)
         {
-            int i;
-            for(i=0;i<nOverviewCount;i++)
+            if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
             {
-                if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
-                {
-                    poMaskDS->nOverviewCount++;
-                    poMaskDS->papoOverviewDS = (GTiffDataset **)
-                        CPLRealloc(poMaskDS->papoOverviewDS, 
-                                poMaskDS->nOverviewCount * (sizeof(void*)));
-                    poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
-                            ((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
-                }
+                poMaskDS->nOverviewCount++;
+                poMaskDS->papoOverviewDS = (GTiffDataset **)
+                    CPLRealloc(poMaskDS->papoOverviewDS, 
+                               poMaskDS->nOverviewCount * (sizeof(void*)));
+                poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
+                    ((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
             }
         }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Only keep track of subdatasets if we have more than one         */
 /*      subdataset (pair).                                              */
 /* -------------------------------------------------------------------- */
-        if( CSLCount(papszSubdatasets) > 2 )
-        {
-            oGTiffMDMD.SetMetadata( papszSubdatasets, "SUBDATASETS" );
-        }
-        CSLDestroy( papszSubdatasets );
+    if( CSLCount(papszSubdatasets) > 2 )
+    {
+        oGTiffMDMD.SetMetadata( papszSubdatasets, "SUBDATASETS" );
     }
-
-    return( CE_None );
+    CSLDestroy( papszSubdatasets );
+    
 }
 
+
 static int GTiffGetLZMAPreset(char** papszOptions)
 {
     int nLZMAPreset = -1;
@@ -6484,7 +6868,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     TIFF		*hTIFF;
     int                 nBlockXSize = 0, nBlockYSize = 0;
     int                 bTiled = FALSE;
-    uint16              nCompression = COMPRESSION_NONE;
+    int                 nCompression = COMPRESSION_NONE;
     int                 nPredictor = PREDICTOR_NONE, nJpegQuality = -1, nZLevel = -1,
                         nLZMAPreset = -1;
     uint16              nSampleFormat;
@@ -7745,13 +8129,20 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
          nBand <= MIN(poDS->GetRasterCount(), poSrcDS->GetRasterCount()) ;
          nBand++ )
     {
-        char **papszSRC_MD = poSrcDS->GetRasterBand(nBand)->GetMetadata();
-        char **papszDST_MD = CSLDuplicate(poDS->GetRasterBand(nBand)->GetMetadata());
+        GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(nBand);
+        GDALRasterBand* poDstBand = poDS->GetRasterBand(nBand);
+        char **papszSRC_MD = poSrcBand->GetMetadata();
+        char **papszDST_MD = CSLDuplicate(poDstBand->GetMetadata());
 
         papszDST_MD = CSLMerge( papszDST_MD, papszSRC_MD );
 
-        poDS->GetRasterBand(nBand)->SetMetadata( papszDST_MD );
+        poDstBand->SetMetadata( papszDST_MD );
         CSLDestroy( papszDST_MD );
+
+        char** papszCatNames;
+        papszCatNames = poSrcBand->GetCategoryNames();
+        if (NULL != papszCatNames)
+            poDstBand->SetCategoryNames( papszCatNames );
     }
 
     hTIFF = (TIFF*) poDS->GetInternalHandle(NULL);
@@ -7958,7 +8349,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                         }
                     }
                     if (eErr == CE_None &&
-                        TIFFWriteScanline( hTIFF, pabyScanline, j, iBand - 1) == -1)
+                        TIFFWriteScanline( hTIFF, pabyScanline, j, (uint16) (iBand-1)) == -1)
                     {
                         CPLError( CE_Failure, CPLE_AppDefined,
                                   "TIFFWriteScanline() failed." );
@@ -8066,6 +8457,7 @@ CPLErr GTiffDataset::SetProjection( const char * pszNewProjection )
         && !EQUALN(pszNewProjection,"PROJCS",6)
         && !EQUALN(pszNewProjection,"LOCAL_CS",8)
         && !EQUALN(pszNewProjection,"COMPD_CS",8)
+        && !EQUALN(pszNewProjection,"GEOCCS",6)
         && !EQUAL(pszNewProjection,"") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -8203,6 +8595,15 @@ char **GTiffDataset::GetMetadata( const char * pszDomain )
     if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
         return GDALPamDataset::GetMetadata( pszDomain );
 
+    else if( pszDomain != NULL && EQUAL(pszDomain,"RPC") )
+        LoadRPCRPB();
+
+    else if( pszDomain != NULL && EQUAL(pszDomain,"IMD") )
+        LoadIMD();
+    
+    else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+        ScanDirectories();
+
     /* FIXME ? Should we call LookForProjection() to load GDALMD_AREA_OR_POINT ? */
     /* This can impact performances */
 
@@ -8247,7 +8648,16 @@ const char *GTiffDataset::GetMetadataItem( const char * pszName,
     if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
         return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
 
-    if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
+    else if( pszDomain != NULL && EQUAL(pszDomain,"RPC") )
+        LoadRPCRPB();
+
+    else if( pszDomain != NULL && EQUAL(pszDomain,"IMD") )
+        LoadIMD();
+
+    else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+        ScanDirectories();
+
+    else if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
         pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
     {
         LookForProjection();
@@ -8293,43 +8703,31 @@ void *GTiffDataset::GetInternalHandle( const char * /* pszHandleName */ )
 /*                           FindRPBFile()                             */
 /************************************************************************/
 
-int GTiffDataset::FindRPBFile(char** papszSiblingFiles)
+int GTiffDataset::FindRPBFile()
 {
-    CPLString osTarget = CPLResetExtension( osFilename, "RPB" );
+    osRPBFile = GDALFindAssociatedFile( osFilename, "RPB", 
+                                        oOvManager.GetSiblingFiles(), 0 );
 
-    if( papszSiblingFiles == NULL )
-    {
-        VSIStatBufL sStatBuf;
-
-        if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
-        {
-            osTarget = CPLResetExtension( osFilename, "rpb" );
+    return osRPBFile != "";
+}
 
-            if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
-                return FALSE;
-        }
-    }
-    else
-    {
-        int iSibling = CSLFindString( papszSiblingFiles, 
-                                      CPLGetFilename(osTarget) );
-        if( iSibling < 0 )
-            return FALSE;
+/************************************************************************/
+/*                           FindIMDFile()                             */
+/************************************************************************/
 
-        osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
-        osTarget += papszSiblingFiles[iSibling];
-    }
+int GTiffDataset::FindIMDFile()
+{
+    osIMDFile = GDALFindAssociatedFile( osFilename, "IMD", 
+                                        oOvManager.GetSiblingFiles(), 0 );
 
-    osRPBFile = osTarget;
-    return TRUE;
+    return osIMDFile != "";
 }
 
-
 /************************************************************************/
 /*                           FindRPCFile()                             */
 /************************************************************************/
 
-int GTiffDataset::FindRPCFile(char** papszSiblingFiles)
+int GTiffDataset::FindRPCFile()
 {
     CPLString osSrcPath = osFilename;
     CPLString soPt(".");
@@ -8339,6 +8737,7 @@ int GTiffDataset::FindRPCFile(char** papszSiblingFiles)
     osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.txt");
     CPLString osTarget = osSrcPath; 
 
+    char** papszSiblingFiles = oOvManager.GetSiblingFiles();
     if( papszSiblingFiles == NULL )
     {
         VSIStatBufL sStatBuf;
@@ -8378,38 +8777,55 @@ int GTiffDataset::FindRPCFile(char** papszSiblingFiles)
 }
 
 /************************************************************************/
-/*                           FindIMDFile()                             */
+/*                            LoadRPCRPB()                              */
 /************************************************************************/
 
-int GTiffDataset::FindIMDFile(char** papszSiblingFiles)
+void GTiffDataset::LoadRPCRPB()
 {
-    CPLString osTarget = CPLResetExtension( osFilename, "IMD" );
+    if (bHasSearchedRPC)
+        return;
 
-    if( papszSiblingFiles == NULL )
-    {
-        VSIStatBufL sStatBuf;
+    bHasSearchedRPC = TRUE;
 
-        if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
-        {
-            osTarget = CPLResetExtension( osFilename, "imd" );
+    char **papszRPCMD = NULL;
+    /* Read Digital Globe .RPB file */
+    if (FindRPBFile())
+        papszRPCMD = GDALLoadRPBFile( osRPBFile.c_str(), NULL );
 
-            if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
-                return FALSE;
-        }
+    /* Read GeoEye _rpc.txt file */
+    if(papszRPCMD == NULL && FindRPCFile())
+        papszRPCMD = GDALLoadRPCFile( osRPCFile.c_str(), NULL );
+
+    if( papszRPCMD != NULL )
+    {
+        oGTiffMDMD.SetMetadata( papszRPCMD, "RPC" );
+        CSLDestroy( papszRPCMD );
     }
     else
+        ReadRPCTag();
+}
+
+/************************************************************************/
+/*                              LoadIMD()                               */
+/************************************************************************/
+
+void GTiffDataset::LoadIMD()
+{
+    if (bHasSearchedIMD)
+        return;
+
+    bHasSearchedIMD = TRUE;
+
+    if (FindIMDFile())
     {
-        int iSibling = CSLFindString( papszSiblingFiles, 
-                                      CPLGetFilename(osTarget) );
-        if( iSibling < 0 )
-            return FALSE;
+        char **papszIMDMD = GDALLoadIMDFile( osIMDFile.c_str(), NULL );
 
-        osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
-        osTarget += papszSiblingFiles[iSibling];
+        if( papszIMDMD != NULL )
+        {
+            oGTiffMDMD.SetMetadata( papszIMDMD, "IMD" );
+            CSLDestroy( papszIMDMD );
+        }
     }
-
-    osIMDFile = osTarget;
-    return TRUE;
 }
 
 /************************************************************************/
@@ -8421,6 +8837,9 @@ char **GTiffDataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
 
+    LoadRPCRPB();
+    LoadIMD();
+
     if (osIMDFile.size() != 0)
         papszFileList = CSLAddString( papszFileList, osIMDFile );
     if (osRPBFile.size() != 0)
@@ -8428,6 +8847,12 @@ char **GTiffDataset::GetFileList()
     if (osRPCFile.size() != 0)
         papszFileList = CSLAddString( papszFileList, osRPCFile );
 
+    if (osWldFilename.size() != 0 &&
+        CSLFindString(papszFileList, osWldFilename) == -1)
+    {
+        papszFileList = CSLAddString( papszFileList, osWldFilename );
+    }
+
     return papszFileList;
 }
 
@@ -8437,6 +8862,8 @@ char **GTiffDataset::GetFileList()
 
 CPLErr GTiffDataset::CreateMaskBand(int nFlags)
 {
+    ScanDirectories();
+
     if (poMaskDS != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -8536,6 +8963,8 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlags)
 
 CPLErr GTiffRasterBand::CreateMaskBand(int nFlags)
 {
+    poGDS->ScanDirectories();
+
     if (poGDS->poMaskDS != NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -8592,16 +9021,23 @@ GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
 {
     char	*pszModFmt;
 
-    if( strstr(fmt,"unknown field") != NULL )
+    if( strstr(fmt,"nknown field") != NULL )
         return;
 
     pszModFmt = PrepareTIFFErrorFormat( module, fmt );
-    CPLErrorV( CE_Warning, CPLE_AppDefined, pszModFmt, ap );
+    if( strstr(fmt, "does not end in null byte") != NULL )
+    {
+        CPLString osMsg;
+        osMsg.vPrintf(pszModFmt, ap);
+        CPLDebug( "GTiff", "%s", osMsg.c_str() );
+    }
+    else
+        CPLErrorV( CE_Warning, CPLE_AppDefined, pszModFmt, ap );
     CPLFree( pszModFmt );
 }
 
 /************************************************************************/
-/*                        GTiffWarningHandler()                         */
+/*                         GTiffErrorHandler()                          */
 /************************************************************************/
 void
 GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
@@ -8672,7 +9108,7 @@ int GTiffOneTimeInit()
     /* by the following code - is "-ltiff -lgdal". "-lgdal -ltiff" works for the */
     /* GTiff driver but probably breaks the application that believes it uses libtiff 3.X */
     /* but we cannot detect that... */
-#ifdef BIGTIFF_SUPPORT
+#if defined(BIGTIFF_SUPPORT) && !defined(RENAME_INTERNAL_LIBTIFF_SYMBOLS)
 #if defined(HAVE_DLFCN_H) && !defined(WIN32)
     const char* (*pfnVersion)(void);
     pfnVersion = (const char* (*)(void)) dlsym(RTLD_DEFAULT, "TIFFGetVersion");
@@ -8707,7 +9143,6 @@ int GTiffOneTimeInit()
 void GDALDeregister_GTiff( GDALDriver * )
 
 {
-    CPLDebug( "GDAL", "GDALDeregister_GTiff() called." );
     CSVDeaccess( NULL );
 
 #if defined(LIBGEOTIFF_VERSION) && LIBGEOTIFF_VERSION > 1150
@@ -8719,7 +9154,7 @@ void GDALDeregister_GTiff( GDALDriver * )
 /*                   GTIFFGetCompressionMethod()                        */
 /************************************************************************/
 
-int     GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
+int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
 {
     int nCompression = COMPRESSION_NONE;
     if( EQUAL( pszValue, "NONE" ) )
@@ -8749,7 +9184,7 @@ int     GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableN
 
 #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
     if (nCompression != COMPRESSION_NONE &&
-        !TIFFIsCODECConfigured(nCompression))
+        !TIFFIsCODECConfigured((uint16) nCompression))
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "Cannot create TIFF file due to missing codec for %s.", pszValue );
diff --git a/frmts/gtiff/gt_citation.cpp b/frmts/gtiff/gt_citation.cpp
index d1c313a..1f44ef5 100644
--- a/frmts/gtiff/gt_citation.cpp
+++ b/frmts/gtiff/gt_citation.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_citation.cpp 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: gt_citation.cpp 23433 2011-11-27 19:49:54Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -34,133 +34,187 @@
 #include "geovalues.h"
 #include "gt_citation.h"
 
-CPL_CVSID("$Id: gt_citation.cpp 21102 2010-11-08 20:47:38Z rouault $");
+CPL_CVSID("$Id: gt_citation.cpp 23433 2011-11-27 19:49:54Z rouault $");
 
-#define nCitationNameTypes 9
-typedef enum 
-{
-  CitCsName = 0,
-  CitPcsName = 1,
-  CitProjectionName = 2,
-  CitLUnitsName = 3,
-  CitGcsName = 4,
-  CitDatumName = 5,
-  CitEllipsoidName = 6,
-  CitPrimemName = 7,
-  CitAUnitsName = 8
-} CitationNameType;
-
-char* ImagineCitationTranslation(const char* psCitation, geokey_t keyID);
-char** CitationStringParse(const char* psCitation);
+static const char *apszUnitMap[] = {
+    "meters", "1.0",
+    "meter", "1.0",
+    "m", "1.0",
+    "centimeters", "0.01",
+    "centimeter", "0.01",
+    "cm", "0.01", 
+    "millimeters", "0.001",
+    "millimeter", "0.001",
+    "mm", "0.001",
+    "kilometers", "1000.0",
+    "kilometer", "1000.0",
+    "km", "1000.0",
+    "us_survey_feet", "0.3048006096012192",
+    "us_survey_foot", "0.3048006096012192",
+    "feet", "0.3048006096012192", 
+    "foot", "0.3048006096012192",
+    "ft", "0.3048006096012192",
+    "international_feet", "0.3048",
+    "international_foot", "0.3048",
+    "inches", "0.0254000508001",
+    "inch", "0.0254000508001",
+    "in", "0.0254000508001",
+    "yards", "0.9144",
+    "yard", "0.9144",
+    "yd", "0.9144",
+    "miles", "1304.544",
+    "mile", "1304.544",
+    "mi", "1304.544",
+    "modified_american_feet", "0.3048122530",
+    "modified_american_foot", "0.3048122530",
+    "clarke_feet", "0.3047972651",
+    "clarke_foot", "0.3047972651",
+    "indian_feet", "0.3047995142",
+    "indian_foot", "0.3047995142",
+    "Yard_Indian", "0.9143985307444408", 
+    "Foot_Clarke", "0.304797265",
+    "Foot_Gold_Coast", "0.3047997101815088",
+    "Link_Clarke", "0.2011661949", 
+    "Yard_Sears", "0.9143984146160287", 
+    "50_Kilometers", "50000.0", 
+    "150_Kilometers", "150000.0", 
+    NULL, NULL
+};
 
 /************************************************************************/
 /*                     ImagineCitationTranslation()                     */
 /*                                                                      */
 /*      Translate ERDAS Imagine GeoTif citation                         */
 /************************************************************************/
-char* ImagineCitationTranslation(const char* psCitation, geokey_t keyID)
+char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
 {
+    static const char *keyNames[] = {
+        "NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL
+    };
+
     char* ret = NULL;
+    int i;
     if(!psCitation)
         return ret;
     if(EQUALN(psCitation, "IMAGINE GeoTIFF Support", strlen("IMAGINE GeoTIFF Support")))
     {
-        CPLString osName;
-
         // this is a handle IMAGING style citation
-        const char* p = NULL;
+        char name[256];
+        name[0] = '\0';
+        char* p = NULL;
+        char* p1 = NULL;
+
         p = strchr(psCitation, '$');
+        if( p && strchr(p, '\n') )
+            p = strchr(p, '\n') + 1;
         if(p)
-            p = strchr(p, '\n');
-        if(p)
-            p++;
-        const char* p1 = NULL;
-        if(p)
-            p1 = strchr(p, '\n');
+        {
+            p1 = p + strlen(p);
+            char *p2 = strchr(p, '\n');
+            if(p2)
+                p1 = MIN(p1, p2);
+            p2 = strchr(p, '\0');
+            if(p2)
+                p1 = MIN(p1, p2);
+            for(i=0; keyNames[i]!=NULL; i++)
+            {
+                p2 = strstr(p, keyNames[i]);
+                if(p2)
+                    p1 = MIN(p1, p2);
+            }
+        }
+
+        // PCS name, GCS name and PRJ name
         if(p && p1)
         {
             switch (keyID)
             {
               case PCSCitationGeoKey:
-                osName = "PCS Name = ";
+                if(strstr(psCitation, "Projection = "))
+                    strcpy(name, "PRJ Name = ");
+                else
+                    strcpy(name, "PCS Name = ");
                 break;
               case GTCitationGeoKey:
-                osName = "CS Name = ";
+                strcpy(name, "PCS Name = ");
                 break;
               case GeogCitationGeoKey:
                 if(!strstr(p, "Unable to"))
-                    osName = "GCS Name = ";
+                    strcpy(name, "GCS Name = ");
                 break;
               default:
                 break;
             }
-            if(strlen(osName)>0)
+            if(strlen(name)>0)
             {
-                osName.append(p, p1-p);
-                osName += "|";
+                char* p2;
+                if((p2 = strstr(psCitation, "Projection Name = ")) != 0)
+                    p = p2 + strlen("Projection Name = ");
+                if((p2 = strstr(psCitation, "Projection = ")) != 0)
+                    p = p2 + strlen("Projection = ");
+                if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
+                    p1 --;
+                p2 = p1 - 1;
+                while( p2>0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                    p2--;
+                if(p2 != p1 - 1)
+                    p1 = p2;
+                if(p1 >= p)
+                {
+                    strncat(name, p, p1-p+1);
+                    strcat(name, "|");
+                    name[strlen(name)] = '\0';
+                }
             }
         }
-        p = strstr(psCitation, "Projection Name = ");
-        if(p)
-        {
-            p += strlen("Projection Name = ");
-            p1 = strchr(p, '\n');
-            if(!p1)
-                p1 = strchr(p, '\0');
-        }
-        if(p && p1)
-        {
-            osName.append(p, p1-p);
-            osName += "|";
-        }
-        p = strstr(psCitation, "Datum = ");
-        if(p)
-        {
-            p += strlen("Datum = ");
-            p1 = strchr(p, '\n');
-            if(!p1)
-                p1 = strchr(p, '\0');
-        }
-        if(p && p1)
-        {
-            osName += "Datum = ";
-            osName.append(p, p1-p);
-            osName += "|";
-        }
-        p = strstr(psCitation, "Ellipsoid = ");
-        if(p)
-        {
-            p += strlen("Ellipsoid = ");
-            p1 = strchr(p, '\n');
-            if(!p1)
-                p1 = strchr(p, '\0');
-        }
-        if(p && p1)
-        {
-            osName += "Ellipsoid = ";
-            osName.append(p, p1-p);
-            osName += "|";
-        }
-        p = strstr(psCitation, "Units = ");
-        if(p)
-        {
-            p += strlen("Units = ");
-            p1 = strchr(p, '\n');
-            if(!p1)
-                p1 = strchr(p, '\0');
-        }
-        if(p && p1)
-        {
-            osName += "LUnits = ";
-            osName.append(p, p1-p);
-            osName += "|";
-        }
-        if(strlen(osName) > 0)
+
+        // All other parameters
+        for(i=0; keyNames[i]!=NULL; i++)
         {
-            ret = CPLStrdup(osName);
+            p = strstr(psCitation, keyNames[i]);
+            if(p)
+            {
+                p += strlen(keyNames[i]);
+                p1 = p + strlen(p);
+                char *p2 = strchr(p, '\n');
+                if(p2)
+                    p1 = MIN(p1, p2);
+                p2 = strchr(p, '\0');
+                if(p2)
+                    p1 = MIN(p1, p2);
+                for(int j=0; keyNames[j]!=NULL; j++)
+                {
+                    p2 = strstr(p, keyNames[j]);
+                    if(p2)
+                        p1 = MIN(p1, p2);
+                }
+            }
+            if(p && p1 && p1>p)
+            {
+                if(EQUAL(keyNames[i], "Units = "))
+                    strcat(name, "LUnits = ");
+                else
+                    strcat(name, keyNames[i]);
+                if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
+                    p1 --;
+                char* p2 = p1 - 1;
+                while( p2>0 && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                    p2--;
+                if(p2 != p1 - 1)
+                    p1 = p2;
+                if(p1 >= p)
+                {
+                    strncat(name, p, p1-p+1);
+                    strcat(name, "|");
+                    name[strlen(name)] = '\0';
+                }
+            }
         }
+        if(strlen(name) > 0)
+            ret = CPLStrdup(name);
     }
     return ret;
+
 }
 
 /************************************************************************/
@@ -168,81 +222,81 @@ char* ImagineCitationTranslation(const char* psCitation, geokey_t keyID)
 /*                                                                      */
 /*      Parse a Citation string                                         */
 /************************************************************************/
-char** CitationStringParse(const char* psCitation)
+
+char** CitationStringParse(char* psCitation, geokey_t keyID)
 {
     char ** ret = NULL;
     if(!psCitation)
         return ret;
 
     ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes); 
-    const char* pDelimit = NULL;
-    const char* pStr = psCitation;
-    CPLString osName;
-    int nCitationLen = strlen(psCitation);
+    char* pDelimit = NULL;
+    char* pStr = psCitation;
+    char name[512];
+    int nameSet = FALSE;
+    int nameLen = strlen(psCitation);
     OGRBoolean nameFound = FALSE;
-    while((pStr-psCitation+1)< nCitationLen)
+    while((pStr-psCitation+1)< nameLen)
     {
         if( (pDelimit = strstr(pStr, "|")) != NULL )
         {
-            osName = "";
-            osName.append(pStr, pDelimit-pStr);
+            strncpy( name, pStr, pDelimit-pStr );
+            name[pDelimit-pStr] = '\0';
             pStr = pDelimit+1;
+            nameSet = TRUE;
         }
         else
         {
-            osName = pStr;
+            strcpy (name, pStr);
             pStr += strlen(pStr);
+            nameSet = TRUE;
         }
-        const char* name = osName.c_str();
         if( strstr(name, "PCS Name = ") )
         {
-            if (!ret[CitPcsName])
-                ret[CitPcsName] = CPLStrdup(name+strlen("PCS Name = "));
+            ret[CitPcsName] = CPLStrdup(name+strlen("PCS Name = "));
             nameFound = TRUE;
         }
-        if(strstr(name, "Projection Name = "))
+        if(strstr(name, "PRJ Name = "))
         {
-            if (!ret[CitProjectionName])
-                ret[CitProjectionName] = CPLStrdup(name+strlen("Projection Name = "));
+            ret[CitProjectionName] = CPLStrdup(name+strlen("PRJ Name = "));
             nameFound = TRUE;
         }
         if(strstr(name, "LUnits = "))
         {
-            if (!ret[CitLUnitsName])
-                ret[CitLUnitsName] = CPLStrdup(name+strlen("LUnits = "));
+            ret[CitLUnitsName] = CPLStrdup(name+strlen("LUnits = "));
             nameFound = TRUE;
         }
         if(strstr(name, "GCS Name = "))
         {
-            if (!ret[CitGcsName])
-                ret[CitGcsName] = CPLStrdup(name+strlen("GCS Name = "));
+            ret[CitGcsName] = CPLStrdup(name+strlen("GCS Name = "));
             nameFound = TRUE;
         }
         if(strstr(name, "Datum = "))
         {
-            if (!ret[CitDatumName])
-                ret[CitDatumName] = CPLStrdup(name+strlen("Datum = "));
+            ret[CitDatumName] = CPLStrdup(name+strlen("Datum = "));
             nameFound = TRUE;
         }
         if(strstr(name, "Ellipsoid = "))
         {
-            if (!ret[CitEllipsoidName])
-                ret[CitEllipsoidName] = CPLStrdup(name+strlen("Ellipsoid = "));
+            ret[CitEllipsoidName] = CPLStrdup(name+strlen("Ellipsoid = "));
             nameFound = TRUE;
         }
         if(strstr(name, "Primem = "))
         {
-            if (!ret[CitPrimemName])
-                ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));
+            ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));    
             nameFound = TRUE;
         }
         if(strstr(name, "AUnits = "))
         {
-            if (!ret[CitAUnitsName])
-                ret[CitAUnitsName] = CPLStrdup(name+strlen("AUnits = "));
+            ret[CitAUnitsName] = CPLStrdup(name+strlen("AUnits = "));
             nameFound = TRUE;
         }
     }
+    if( !nameFound && keyID == GeogCitationGeoKey && nameSet )
+    {
+        ret[CitGcsName] = CPLStrdup(name);
+        nameFound = TRUE;
+    }
     if(!nameFound)
     {
         CPLFree( ret );
@@ -251,6 +305,7 @@ char** CitationStringParse(const char* psCitation)
     return ret;
 }
 
+
 /************************************************************************/
 /*                       SetLinearUnitCitation()                        */
 /*                                                                      */
@@ -369,7 +424,14 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
                             geokey_t geoKey,  OGRSpatialReference*	poSRS, OGRBoolean* linearUnitIsSet)
 {
     OGRBoolean ret = FALSE;
-    *linearUnitIsSet = FALSE;
+    char* lUnitName = NULL;
+    
+    poSRS->GetLinearUnits( &lUnitName );
+    if(!lUnitName || strlen(lUnitName) == 0  || EQUAL(lUnitName, "unknown"))
+        *linearUnitIsSet = FALSE;
+    else
+        *linearUnitIsSet = TRUE;
+
     char* imgCTName = ImagineCitationTranslation(szCTString, geoKey);
     if(imgCTName)
     {
@@ -377,7 +439,7 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
         szCTString[nCTStringLen-1] = '\0';
         CPLFree( imgCTName );
     }
-    char** ctNames = CitationStringParse(szCTString);
+    char** ctNames = CitationStringParse(szCTString, geoKey);
     if(ctNames)
     {
         if( poSRS->GetRoot() == NULL)
@@ -387,33 +449,47 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
             poSRS->SetNode( "PROJCS", ctNames[CitPcsName] );
             ret = TRUE;
         }
-        else if(geoKey != GTCitationGeoKey) 
-        {
-            char    szPCSName[128];
-            if( GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 0, sizeof(szPCSName) ) )
-            {
-                poSRS->SetNode( "PROJCS", szPCSName );
-                ret = TRUE;
-            }
-        }
-    
         if(ctNames[CitProjectionName])
             poSRS->SetProjection( ctNames[CitProjectionName] );
 
         if(ctNames[CitLUnitsName])
         {
-            double unitSize;
-            if (GTIFKeyGet(hGTIF, ProjLinearUnitSizeGeoKey, &unitSize, 0,
-                           sizeof(unitSize) ))
+            double unitSize = 0.0;
+            int size = strlen(ctNames[CitLUnitsName]);
+            if(strchr(ctNames[CitLUnitsName], '\0'))
+                size -= 1;
+            for( int i = 0; apszUnitMap[i] != NULL; i += 2 )
             {
-                poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
-                *linearUnitIsSet = TRUE;
+                if( EQUALN(apszUnitMap[i], ctNames[CitLUnitsName], size) )
+                {
+                    unitSize = atof(apszUnitMap[i+1]);
+                    break;
+                }
             }
+            if( unitSize == 0.0 )
+                GTIFKeyGet(hGTIF, ProjLinearUnitSizeGeoKey, &unitSize, 0,
+                           sizeof(unitSize) );
+            poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
+            *linearUnitIsSet = TRUE;
         }
         for(int i= 0; i<nCitationNameTypes; i++) 
             CPLFree( ctNames[i] );
         CPLFree( ctNames );
     }
+
+    /* if no "PCS Name = " (from Erdas) in GTCitationGeoKey */
+    if(geoKey == GTCitationGeoKey)
+    {
+        if(strlen(szCTString) > 0 && !strstr(szCTString, "PCS Name = "))
+        {
+            const char* pszProjCS = poSRS->GetAttrValue( "PROJCS" );
+            if((!(pszProjCS && strlen(pszProjCS) > 0) && !strstr(szCTString, "Projected Coordinates"))
+               ||(pszProjCS && strstr(pszProjCS, "unnamed")))
+                poSRS->SetNode( "PROJCS", szCTString );
+            ret = TRUE;
+        }
+    }
+
     return ret;
 }
 
@@ -440,7 +516,7 @@ void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
         szGCSName[nGCSName-1] = '\0';
         CPLFree( imgCTName );
     }
-    char** ctNames = CitationStringParse(szGCSName);
+    char** ctNames = CitationStringParse(szGCSName, geoKey);
     if(ctNames)
     {
         if(ctNames[CitGcsName])
@@ -466,3 +542,211 @@ void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
 }
 
 
+/************************************************************************/
+/*               CheckCitationKeyForStatePlaneUTM()                     */
+/*                                                                      */
+/*      Handle state plane and UTM in citation key                      */
+/************************************************************************/
+OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet)
+{
+    if( !hGTIF || !psDefn || !poSRS )
+        return FALSE;
+    char  szCTString[512];
+    szCTString[0] = '\0';
+
+    /* Check units */
+    char units[32];
+    units[0] = '\0';
+
+    OGRBoolean hasUnits = FALSE;
+    if( GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
+    {
+        CPLString osLCCT = szCTString;
+
+        osLCCT.tolower();
+
+        if( strstr(osLCCT,"us") && strstr(osLCCT,"survey")
+            && (strstr(osLCCT,"feet") || strstr(osLCCT,"foot")) )
+            strcpy(units, "us_survey_feet");
+        else if(strstr(osLCCT, "linear_feet")  
+                || strstr(osLCCT, "linear_foot") 
+                || strstr(osLCCT, "international"))
+            strcpy(units, "international_feet");
+        else if( strstr(osLCCT,"meter") )
+            strcpy(units, "meters");
+
+        if (strlen(units) > 0)
+            hasUnits = TRUE;
+
+        if( strstr( szCTString, "Projection Name = ") && strstr( szCTString, "_StatePlane_"))
+        {
+            const char *pStr = strstr( szCTString, "Projection Name = ") + strlen("Projection Name = ");
+            const char* pReturn = strchr( pStr, '\n');
+            char CSName[128];
+            strncpy(CSName, pStr, pReturn-pStr);
+            CSName[pReturn-pStr] = '\0';
+            if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName) == OGRERR_NONE )
+            {
+                // for some erdas citation keys, the state plane CS name is incomplete, the unit check is necessary.
+                OGRBoolean done = FALSE;
+                if (hasUnits)
+                {
+                    OGR_SRSNode *poUnit = poSRS->GetAttrNode( "PROJCS|UNIT" );
+      
+                    if( poUnit != NULL && poUnit->GetChildCount() >= 2 )
+                    {
+                        CPLString unitName = poUnit->GetChild(0)->GetValue();
+                        unitName.tolower();
+
+                        if (strstr(units, "us_survey_feet"))
+                        {              
+                            if (strstr(unitName, "us_survey_feet") || strstr(unitName, "foot_us") )
+                                done = TRUE;
+                        }
+                        else if (strstr(units, "international_feet"))
+                        {
+                            if (strstr(unitName, "feet") || strstr(unitName, "foot"))
+                                done = TRUE;
+                        }
+                        else if (strstr(units, "meters"))
+                        {
+                            if (strstr(unitName, "meter") )
+                                done = TRUE;
+                        }
+                    }
+                }
+                if (done)
+                    return TRUE;
+            }
+        }
+    }
+    if( !hasUnits )
+    {
+        char	*pszUnitsName = NULL;
+        GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
+        if( pszUnitsName && strlen(pszUnitsName) > 0 )
+        {
+            CPLString osLCCT = pszUnitsName;
+            GTIFFreeMemory( pszUnitsName );
+            osLCCT.tolower();
+
+            if( strstr(osLCCT, "us") && strstr(osLCCT, "survey")
+                && (strstr(osLCCT, "feet") || strstr(osLCCT, "foot")))
+                strcpy(units, "us_survey_feet");
+            else if(strstr(osLCCT, "feet") || strstr(osLCCT, "foot"))
+                strcpy(units, "international_feet");
+            else if(strstr(osLCCT, "meter"))
+                strcpy(units, "meters");
+            hasUnits = TRUE;
+        }
+    }
+
+    if (strlen(units) == 0)
+        strcpy(units, "meters");
+
+    /* check PCSCitationGeoKey if it exists */
+    szCTString[0] = '\0';
+    if( hGTIF && GTIFKeyGet( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )  
+    {
+        /* For tif created by LEICA(ERDAS), ESRI state plane pe string was used and */
+        /* the state plane zone is given in PCSCitation. Therefore try Esri pe string first. */
+        SetCitationToSRS(hGTIF, szCTString, strlen(szCTString), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
+        const char *pcsName = poSRS->GetAttrValue("PROJCS");
+        const char *pStr = NULL;
+        if( (pcsName && (pStr = strstr(pcsName, "State Plane Zone ")) != NULL)
+            || (pStr = strstr(szCTString, "State Plane Zone ")) != NULL )
+        {
+            pStr += strlen("State Plane Zone ");
+            int statePlaneZone = abs(atoi(pStr));
+            char nad[32];
+            strcpy(nad, "HARN");
+            if( strstr(szCTString, "NAD83") || strstr(szCTString, "NAD = 83") )
+                strcpy(nad, "NAD83");
+            else if( strstr(szCTString, "NAD27") || strstr(szCTString, "NAD = 27") )
+                strcpy(nad, "NAD27");
+            if( poSRS->ImportFromESRIStatePlaneWKT(statePlaneZone, (const char*)nad, (const char*)units, psDefn->PCS) == OGRERR_NONE )
+                return TRUE;
+        }
+        else if( pcsName && (pStr = strstr(pcsName, "UTM Zone ")) != NULL )
+            CheckUTM( psDefn, szCTString );
+    }
+
+    /* check state plane again to see if a pe string is available */
+    if( psDefn->PCS != KvUserDefined )
+    {
+        if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, (const char*)units, psDefn->PCS) == OGRERR_NONE )
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                               CheckUTM()                             */
+/*                                                                      */
+/*        Check utm proj code by its name.                              */
+/************************************************************************/
+void CheckUTM( GTIFDefn * psDefn, char * pszCtString )
+{
+    if(!psDefn || !pszCtString)
+        return;
+
+    static const char *apszUtmProjCode[] = {
+        "PSAD56", "17N", "16017",
+        "PSAD56", "18N", "16018",
+        "PSAD56", "19N", "16019",
+        "PSAD56", "20N", "16020",
+        "PSAD56", "21N", "16021",
+        "PSAD56", "17S", "16117",
+        "PSAD56", "18S", "16118",
+        "PSAD56", "19S", "16119",
+        "PSAD56", "20S", "16120",
+        "PSAD56", "21S", "16121",
+        "PSAD56", "22S", "16122",
+        NULL, NULL, NULL};
+
+    char* p = strstr(pszCtString, "Datum = ");
+    char datumName[128];
+    if(p)
+    {
+        p += strlen("Datum = ");
+        char* p1 = strchr(p, '|');
+        if(p1)
+        {
+            strncpy(datumName, p, (p1-p));
+            datumName[p1-p] = '\0';
+        }
+        else
+            strcpy(datumName, p);
+    }
+
+    char utmName[64];
+    p = strstr(pszCtString, "UTM Zone ");
+    if(p)
+    {
+        p += strlen("UTM Zone ");
+        char* p1 = strchr(p, '|');
+        if(p1)
+        {
+            strncpy(utmName, p, (p1-p));
+            utmName[p1-p] = '\0';
+        }
+        else
+            strcpy(utmName, p);
+    }
+
+    for(int i=0; apszUtmProjCode[i]!=NULL; i += 3)
+    {
+        if(EQUALN(utmName, apszUtmProjCode[i+1], strlen(apszUtmProjCode[i+1])) &&
+           EQUAL(datumName, apszUtmProjCode[i]) )
+        {
+            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 e1c6119..5aa5b25 100644
--- a/frmts/gtiff/gt_citation.h
+++ b/frmts/gtiff/gt_citation.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_citation.h 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: gt_citation.h 21929 2011-03-11 03:58:42Z warmerdam $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -35,16 +35,38 @@
 #include "geo_normalize.h"
 #include "ogr_spatialref.h"
 
+char* ImagineCitationTranslation(char* psCitation, geokey_t keyID);
+char** CitationStringParse(char* psCitation, geokey_t keyID);
+
+#define nCitationNameTypes 9
+typedef enum 
+{
+  CitCsName = 0,
+  CitPcsName = 1,
+  CitProjectionName = 2,
+  CitLUnitsName = 3,
+  CitGcsName = 4,
+  CitDatumName = 5,
+  CitEllipsoidName = 6,
+  CitPrimemName = 7,
+  CitAUnitsName = 8
+} CitationNameType;
+
+OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet);
+//char* ImagineCitationTranslation(char* psCitation, geokey_t keyID);
+//char** CitationStringParse(char* psCitation, geokey_t keyID);
 void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName);
 void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid);
 OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
                             geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet);
 void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
-                           geokey_t geoKey,
-                          char  **ppszGeogName,
-                          char  **ppszDatumName,
-                          char  **ppszPMName,
-                          char  **ppszSpheroidName,
-                          char  **ppszAngularUnits);
+                           geokey_t geoKey, 
+                          char	**ppszGeogName,
+                          char	**ppszDatumName,
+                          char	**ppszPMName,
+                          char	**ppszSpheroidName,
+                          char	**ppszAngularUnits);
+void CheckUTM( GTIFDefn * psDefn, char * pszCtString );
+
 
 #endif // GT_CITATION_H_INCLUDED
diff --git a/frmts/gtiff/gt_overview.cpp b/frmts/gtiff/gt_overview.cpp
index c6b1ead..5d8a3b1 100644
--- a/frmts/gtiff/gt_overview.cpp
+++ b/frmts/gtiff/gt_overview.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_overview.cpp 21103 2010-11-08 20:49:08Z rouault $
+ * $Id: gt_overview.cpp 23497 2011-12-08 20:50:57Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Code to build overviews of external databases as a TIFF file. 
@@ -31,11 +31,12 @@
 #include "gdal_priv.h"
 #define CPL_SERV_H_INCLUDED
 
+#include "tifvsi.h"
 #include "xtiffio.h"
 #include "gt_overview.h"
 #include "gtiff.h"
 
-CPL_CVSID("$Id: gt_overview.cpp 21103 2010-11-08 20:49:08Z rouault $");
+CPL_CVSID("$Id: gt_overview.cpp 23497 2011-12-08 20:50:57Z rouault $");
 
 /************************************************************************/
 /*                         GTIFFWriteDirectory()                        */
@@ -335,8 +336,18 @@ GTIFFBuildOverviews( const char * pszFilename,
             return CE_Failure;
     }
     
-    if( nCompression == COMPRESSION_JPEG && nBitsPerPixel == 16 )
+    if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 )
+    {  
+        if( nBitsPerPixel > 16 )
+        {
+            CPLError( CE_Failure, CPLE_NotSupported, 
+                      "GTIFFBuildOverviews() doesn't support building"
+                      " JPEG compressed overviews of nBitsPerPixel > 16." );
+            return CE_Failure;
+        }
+
         nBitsPerPixel = 12;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the planar configuration to use.                     */
@@ -550,13 +561,13 @@ GTIFFBuildOverviews( const char * pszFilename,
         if( bCreateBigTIFF )
             CPLDebug( "GTiff", "File being created as a BigTIFF." );
 
-        hOTIFF = XTIFFOpen( pszFilename, (bCreateBigTIFF) ? "w+8" : "w+" );
+        hOTIFF = VSI_TIFFOpen( pszFilename, (bCreateBigTIFF) ? "w+8" : "w+" );
         if( hOTIFF == NULL )
         {
             if( CPLGetLastErrorNo() == 0 )
                 CPLError( CE_Failure, CPLE_OpenFailed,
                           "Attempt to create new tiff file `%s'\n"
-                          "failed in XTIFFOpen().\n",
+                          "failed in VSI_TIFFOpen().\n",
                           pszFilename );
 
             return CE_Failure;
@@ -567,13 +578,13 @@ GTIFFBuildOverviews( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     else 
     {
-        hOTIFF = XTIFFOpen( pszFilename, "r+" );
+        hOTIFF = VSI_TIFFOpen( pszFilename, "r+" );
         if( hOTIFF == NULL )
         {
             if( CPLGetLastErrorNo() == 0 )
                 CPLError( CE_Failure, CPLE_OpenFailed,
                           "Attempt to create new tiff file `%s'\n"
-                          "failed in XTIFFOpen().\n",
+                          "failed in VSI_TIFFOpen().\n",
                           pszFilename );
 
             return CE_Failure;
diff --git a/frmts/gtiff/gt_wkt_srs.cpp b/frmts/gtiff/gt_wkt_srs.cpp
index 54f233f..a7d4bde 100644
--- a/frmts/gtiff/gt_wkt_srs.cpp
+++ b/frmts/gtiff/gt_wkt_srs.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.cpp 22365 2011-05-12 18:42:44Z warmerdam $
+ * $Id: gt_wkt_srs.cpp 23272 2011-10-23 19:37:12Z etourigny $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements translation between GeoTIFF normalized projection
@@ -44,7 +44,7 @@
 #include "gt_wkt_srs_for_gdal.h"
 #include "gt_citation.h"
 
-CPL_CVSID("$Id: gt_wkt_srs.cpp 22365 2011-05-12 18:42:44Z warmerdam $")
+CPL_CVSID("$Id: gt_wkt_srs.cpp 23272 2011-10-23 19:37:12Z etourigny $")
 
 #define ProjLinearUnitsInterpCorrectGeoKey   3059
 
@@ -62,6 +62,11 @@ typedef struct _VSILFILE VSILFILE;
 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,
@@ -72,6 +77,9 @@ 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 */
@@ -208,11 +216,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: 22365 $ $Date: 2011-05-12 11:42:44 -0700 (Thu, 12 May 2011) $\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: 23272 $ $Date: 2011-10-23 12:37:12 -0700 (Sun, 23 Oct 2011) $\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: 22365 $ $Date: 2011-05-12 11:42:44 -0700 (Thu, 12 May 2011) $\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: 23272 $ $Date: 2011-10-23 12:37:12 -0700 (Sun, 23 Oct 2011) $\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: 22365 $ $Date: 2011-05-12 11:42:44 -0700 (Thu, 12 May 2011) $\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: 23272 $ $Date: 2011-10-23 12:37:12 -0700 (Sun, 23 Oct 2011) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
  
 */
 
@@ -272,7 +280,8 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /*      Handle non-standard coordinate systems as LOCAL_CS.             */
 /* -------------------------------------------------------------------- */
     if( psDefn->Model != ModelTypeProjected 
-        && psDefn->Model != ModelTypeGeographic )
+        && psDefn->Model != ModelTypeGeographic 
+        && psDefn->Model != ModelTypeGeocentric )
     {
         char	*pszWKT;
         char    szPeStr[2400];
@@ -281,48 +290,78 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         if( GTIFKeyGet( hGTIF, PCSCitationGeoKey, szPeStr, 0, sizeof(szPeStr) ) &&
             strstr(szPeStr, "ESRI PE String = " ) )
         {
-          pszWKT = CPLStrdup( szPeStr + strlen("ESRI PE String = ") );
-          return pszWKT;
+            pszWKT = CPLStrdup( szPeStr + strlen("ESRI PE String = ") );
+            return pszWKT;
         }
         else
         {
-          char	*pszUnitsName = NULL;
-          char    szPCSName[300];
-          int     nKeyCount = 0;
-          int     anVersion[3];
-
-          if( hGTIF != NULL )
-              GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount );
-
-          if( nKeyCount > 0 ) // Use LOCAL_CS if we have any geokeys at all.
-          {
-              // Handle citation.
-              strcpy( szPCSName, "unnamed" );
-              if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 
-                               0, sizeof(szPCSName) ) )
-                  GTIFKeyGet( hGTIF, GeogCitationGeoKey, szPCSName, 
-                              0, sizeof(szPCSName) );
-
-              GTIFCleanupImagineNames( szPCSName );
-              oSRS.SetLocalCS( szPCSName );
-
-              // Handle units
-              GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
+            char	*pszUnitsName = NULL;
+            char    szPCSName[300];
+            int     nKeyCount = 0;
+            int     anVersion[3];
+
+            if( hGTIF != NULL )
+                GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount );
+
+            if( nKeyCount > 0 ) // Use LOCAL_CS if we have any geokeys at all.
+            {
+                // Handle citation.
+                strcpy( szPCSName, "unnamed" );
+                if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szPCSName, 
+                                 0, sizeof(szPCSName) ) )
+                    GTIFKeyGet( hGTIF, GeogCitationGeoKey, szPCSName, 
+                                0, sizeof(szPCSName) );
+
+                GTIFCleanupImagineNames( szPCSName );
+                oSRS.SetLocalCS( szPCSName );
+
+                // Handle units
+                GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
               
-              if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
-              {
-                  oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
-                  oSRS.SetAuthority( "LOCAL_CS|UNIT", "EPSG", psDefn->UOMLength);
-              }
-              else
-                  oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
+                if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
+                {
+                    oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
+                    oSRS.SetAuthority( "LOCAL_CS|UNIT", "EPSG", psDefn->UOMLength);
+                }
+                else
+                    oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
 
-              GTIFFreeMemory( pszUnitsName );
-          }
-          oSRS.exportToWkt( &pszWKT );
+                GTIFFreeMemory( pszUnitsName );
+            }
+            oSRS.exportToWkt( &pszWKT );
 
-          return pszWKT;
-       }
+            return pszWKT;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle Geocentric coordinate systems.                           */
+/* -------------------------------------------------------------------- */
+    if( psDefn->Model == ModelTypeGeocentric )
+    {
+        char    szName[300];
+
+        strcpy( szName, "unnamed" );
+        if( !GTIFKeyGet( hGTIF, GTCitationGeoKey, szName, 
+                         0, sizeof(szName) ) )
+            GTIFKeyGet( hGTIF, GeogCitationGeoKey, szName, 
+                        0, sizeof(szName) );
+
+        oSRS.SetGeocCS( szName );
+
+        char	*pszUnitsName = NULL;
+          
+        GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
+        
+        if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
+        {
+            oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
+            oSRS.SetAuthority( "GEOCCS|UNIT", "EPSG", psDefn->UOMLength );
+        }
+        else
+            oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
+
+        GTIFFreeMemory( pszUnitsName );
     }
     
 /* -------------------------------------------------------------------- */
@@ -428,24 +467,39 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
         }
         else if(hGTIF && GTIFKeyGet( hGTIF, PCSCitationGeoKey, szCTString, 0, 
-                       sizeof(szCTString)) )  
+                                     sizeof(szCTString)) )  
         {
             if (!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
-                             PCSCitationGeoKey, &oSRS, &linearUnitIsSet))
-              oSRS.SetNode("PROJCS",szCTString);
+                                  PCSCitationGeoKey, &oSRS, &linearUnitIsSet))
+                oSRS.SetNode("PROJCS",szCTString);
         }
         else
         {
-          if( hGTIF )
-          {
-            GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) );
-            if(!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
-                                 GTCitationGeoKey, &oSRS, &linearUnitIsSet))
-              oSRS.SetNode( "PROJCS", szCTString );
-          }
-          else
-            oSRS.SetNode( "PROJCS", szCTString );
+            if( hGTIF )
+            {
+                GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) );
+                if(!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
+                                     GTCitationGeoKey, &oSRS, &linearUnitIsSet))
+                    oSRS.SetNode( "PROJCS", szCTString );
+            }
+            else
+                oSRS.SetNode( "PROJCS", szCTString );
+        }
+
+        /* Handle ESRI/Erdas style state plane and UTM in citation key */
+        if( CheckCitationKeyForStatePlaneUTM(hGTIF, psDefn, &oSRS, &linearUnitIsSet) )
+        {
+            char	*pszWKT;
+            oSRS.morphFromESRI();
+            oSRS.FixupOrdering();
+            if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
+                return pszWKT;
         }
+
+        /* Handle ESRI PE string in citation */
+        szCTString[0] = '\0';
+        if( hGTIF && GTIFKeyGet( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
+            SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString), GTCitationGeoKey, &oSRS, &linearUnitIsSet);
     }
     
 /* ==================================================================== */
@@ -476,18 +530,18 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         
     if( !pszDatumName )
     {
-      GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
-      GTIFToCPLRecycleString( &pszDatumName );
+        GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
+        GTIFToCPLRecycleString( &pszDatumName );
     }
     if( !pszSpheroidName )
     {
-      GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
-      GTIFToCPLRecycleString( &pszSpheroidName );
+        GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
+        GTIFToCPLRecycleString( &pszSpheroidName );
     }
     else
     {
-      GTIFKeyGet(hGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 );
-      GTIFKeyGet(hGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening, 0, 1 );
+        GTIFKeyGet(hGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 );
+        GTIFKeyGet(hGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening, 0, 1 );
     }
     if( !pszPMName )
     {
@@ -495,20 +549,20 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         GTIFToCPLRecycleString( &pszPMName );
     }
     else
-      GTIFKeyGet(hGTIF, GeogPrimeMeridianLongGeoKey, &(psDefn->PMLongToGreenwich), 0, 1 );
+        GTIFKeyGet(hGTIF, GeogPrimeMeridianLongGeoKey, &(psDefn->PMLongToGreenwich), 0, 1 );
     
     if( !pszAngularUnits )
     {
-      GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
-      if( pszAngularUnits == NULL )
-          pszAngularUnits = CPLStrdup("unknown");
-      else
-          GTIFToCPLRecycleString( &pszAngularUnits );
+        GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
+        if( pszAngularUnits == NULL )
+            pszAngularUnits = CPLStrdup("unknown");
+        else
+            GTIFToCPLRecycleString( &pszAngularUnits );
     }
     else
     {
-      GTIFKeyGet(hGTIF, GeogAngularUnitSizeGeoKey, &(psDefn->UOMAngleInDegrees), 0, 1 );
-      aUnitGot = TRUE;
+        GTIFKeyGet(hGTIF, GeogAngularUnitSizeGeoKey, &(psDefn->UOMAngleInDegrees), 0, 1 );
+        aUnitGot = TRUE;
     }
 
     if( pszDatumName != NULL )
@@ -522,35 +576,35 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         dfInvFlattening = SRS_WGS84_INVFLATTENING;
     }
     else if( dfInvFlattening == 0.0 && ((psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
-             || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 ) )
+                                        || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 ) )
     {
-          dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0);
+        dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0);
 
-          /* Take official inverse flattening definition in the WGS84 case */
-          if (dfSemiMajor == SRS_WGS84_SEMIMAJOR &&
-              fabs(dfInvFlattening - SRS_WGS84_INVFLATTENING) < 1e-10)
-              dfInvFlattening = SRS_WGS84_INVFLATTENING;
+        /* Take official inverse flattening definition in the WGS84 case */
+        if (fabs(dfSemiMajor-SRS_WGS84_SEMIMAJOR) < 1e-10 &&
+            fabs(dfInvFlattening - SRS_WGS84_INVFLATTENING) < 1e-10)
+            dfInvFlattening = SRS_WGS84_INVFLATTENING;
     }
     if(!pszGeogName || strlen(pszGeogName) == 0)
     {
         CPLFree(pszGeogName);
-        pszGeogName = CPLStrdup( pszDatumName );
+        pszGeogName = CPLStrdup( pszDatumName ? pszDatumName : "unknown" );
     }
 
     if(aUnitGot)
-      oSRS.SetGeogCS( pszGeogName, pszDatumName, 
-                      pszSpheroidName, dfSemiMajor, dfInvFlattening,
-                      pszPMName,
-                      psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
-                      pszAngularUnits,
-                      psDefn->UOMAngleInDegrees );
+        oSRS.SetGeogCS( pszGeogName, pszDatumName, 
+                        pszSpheroidName, dfSemiMajor, dfInvFlattening,
+                        pszPMName,
+                        psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
+                        pszAngularUnits,
+                        psDefn->UOMAngleInDegrees );
     else
-      oSRS.SetGeogCS( pszGeogName, pszDatumName, 
-                      pszSpheroidName, dfSemiMajor, dfInvFlattening,
-                      pszPMName,
-                      psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
-                      pszAngularUnits,
-                      psDefn->UOMAngleInDegrees * 0.0174532925199433 );
+        oSRS.SetGeogCS( pszGeogName, pszDatumName, 
+                        pszSpheroidName, dfSemiMajor, dfInvFlattening,
+                        pszPMName,
+                        psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
+                        pszAngularUnits,
+                        psDefn->UOMAngleInDegrees * 0.0174532925199433 );
 
     if( psDefn->GCS != KvUserDefined && psDefn->GCS > 0 )
         oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS );
@@ -566,6 +620,17 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     CPLFree( pszSpheroidName );
     CPLFree( pszPMName );
     CPLFree( pszAngularUnits );
+
+#if LIBGEOTIFF_VERSION >= 1310
+    if( psDefn->TOWGS84Count > 0 )
+        oSRS.SetTOWGS84( psDefn->TOWGS84[0],
+                         psDefn->TOWGS84[1],
+                         psDefn->TOWGS84[2],
+                         psDefn->TOWGS84[3],
+                         psDefn->TOWGS84[4],
+                         psDefn->TOWGS84[5],
+                         psDefn->TOWGS84[6] );
+#endif
         
 /* ==================================================================== */
 /*      Handle projection parameters.                                   */
@@ -588,17 +653,17 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
         if(!aUnitGot)
         {
-          adfParm[0] *= psDefn->UOMAngleInDegrees;
-          adfParm[1] *= psDefn->UOMAngleInDegrees;
-          adfParm[2] *= psDefn->UOMAngleInDegrees;
-          adfParm[3] *= psDefn->UOMAngleInDegrees; 
+            adfParm[0] *= psDefn->UOMAngleInDegrees;
+            adfParm[1] *= psDefn->UOMAngleInDegrees;
+            adfParm[2] *= psDefn->UOMAngleInDegrees;
+            adfParm[3] *= psDefn->UOMAngleInDegrees; 
         }
         int unitCode = 0;
         GTIFKeyGet(hGTIF, ProjLinearUnitsGeoKey, &unitCode, 0, 1  );
         if(unitCode != KvUserDefined)
         {
-          adfParm[5] /= psDefn->UOMLengthInMeters;
-          adfParm[6] /= psDefn->UOMLengthInMeters;
+            adfParm[5] /= psDefn->UOMLengthInMeters;
+            adfParm[6] /= psDefn->UOMLengthInMeters;
         }
         
 /* -------------------------------------------------------------------- */
@@ -626,7 +691,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator. 
             {
                 oSRS.SetExtension( "PROJCS", "PROJ4",  
-                                    "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" ); 
+                                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" ); 
             }
             break;
 
@@ -637,7 +702,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             break;
 
           case CT_Stereographic:
-            oSRS.SetOS( adfParm[0], adfParm[1],
+            oSRS.SetStereographic( adfParm[0], adfParm[1],
                         adfParm[4],
                         adfParm[5], adfParm[6] );
             break;
@@ -744,27 +809,31 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             oSRS.SetCEA( adfParm[0], adfParm[1],
                          adfParm[5], adfParm[6] );
             break;
+          default:
+            if( oSRS.IsProjected() )
+                oSRS.GetRoot()->SetValue( "LOCAL_CS" );
+            break;
         }
 
 /* -------------------------------------------------------------------- */
 /*      Set projection units.                                           */
 /* -------------------------------------------------------------------- */
-       if(!linearUnitIsSet)
-       {
-          char	*pszUnitsName = NULL;
+        if(!linearUnitIsSet)
+        {
+            char	*pszUnitsName = NULL;
           
-          GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
+            GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
 
-          if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
-          {
-              oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
-              oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
-          }
-          else
-              oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
+            if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
+            {
+                oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
+                oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
+            }
+            else
+                oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
 
-          GTIFFreeMemory( pszUnitsName );
-       }
+            GTIFFreeMemory( pszUnitsName );
+        }
     }
 
 /* ==================================================================== */
@@ -865,7 +934,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                                         szSearchKey, CC_Integer, 
                                         "datum_code" );
                 if( pszValue != NULL )
-                    verticalDatum = atoi(pszValue);
+                    verticalDatum = (short) atoi(pszValue);
             }
 
             if( EQUAL(citation,"unknown") )
@@ -892,7 +961,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                                             pszValue, CC_Integer, 
                                             "uom_code" );
                     if( pszValue != NULL )
-                        verticalUnits = atoi(pszValue);
+                        verticalUnits = (short) atoi(pszValue);
                 }                
             }
         }
@@ -937,7 +1006,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             ->AddChild( new OGR_SRSNode( pszVDatumType ) );
         if( verticalDatum > 0 && verticalDatum != KvUserDefined )
             oSRS.SetAuthority( "COMPD_CS|VERT_CS|VERT_DATUM", "EPSG", 
-                                  verticalDatum );
+                               verticalDatum );
     
 /* -------------------------------------------------------------------- */
 /*      Set the vertical units.                                         */
@@ -961,12 +1030,14 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
             // Value
             double dfFactorB, dfFactorC;
-            dfFactorB = atof(CSVGetField( pszFilename, 
-                                          "uom_code", szSearchKey, CC_Integer,
-                                          "factor_b" ));
-            dfFactorC = atof(CSVGetField( pszFilename, 
-                                          "uom_code", szSearchKey, CC_Integer,
-                                          "factor_b" ));
+            dfFactorB = GTIFAtof(
+                CSVGetField( pszFilename, 
+                             "uom_code", szSearchKey, CC_Integer,
+                             "factor_b" ));
+            dfFactorC = GTIFAtof(
+                CSVGetField( pszFilename, 
+                             "uom_code", szSearchKey, CC_Integer,
+                             "factor_b" ));
             if( dfFactorB != 0.0 && dfFactorC != 0.0 )
                 sprintf( szInMeters, "%.16g", dfFactorB / dfFactorC );
             else
@@ -1029,7 +1100,7 @@ static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
         || EQUAL(pszOGCName,"North_American_Datum_1927") )
         return Datum_North_American_Datum_1927;
     else if( EQUAL(pszOGCName,"NAD83") 
-        || EQUAL(pszOGCName,"North_American_Datum_1983") )
+             || EQUAL(pszOGCName,"North_American_Datum_1983") )
         return Datum_North_American_Datum_1983;
     else if( EQUAL(pszOGCName,"WGS84") || EQUAL(pszOGCName,"WGS_1984")
              || EQUAL(pszOGCName,"WGS 84"))
@@ -1167,13 +1238,13 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
     if( (pszLinearUOMName != NULL
          && EQUAL(pszLinearUOMName,SRS_UL_FOOT))
-        || dfLinearUOM == atof(SRS_UL_FOOT_CONV) )
+        || fabs(dfLinearUOM-GTIFAtof(SRS_UL_FOOT_CONV)) < 0.0000001 )
         nUOMLengthCode = 9002; /* international foot */
     else if( (pszLinearUOMName != NULL
               && EQUAL(pszLinearUOMName,SRS_UL_US_FOOT))
-             || ABS(dfLinearUOM-atof(SRS_UL_US_FOOT_CONV)) < 0.0000001 )
+             || ABS(dfLinearUOM-GTIFAtof(SRS_UL_US_FOOT_CONV)) < 0.0000001 )
         nUOMLengthCode = 9003; /* us survey foot */
-    else if( dfLinearUOM != 1.0 )
+    else if( fabs(dfLinearUOM-1.0) > 0.00000001 )
         nUOMLengthCode = KvUserDefined;
 
 /* -------------------------------------------------------------------- */
@@ -1191,13 +1262,19 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /*      Handle the projection transformation.                           */
 /* -------------------------------------------------------------------- */
     const char *pszProjection = poSRS->GetAttrValue( "PROJECTION" );
-
+    int bWritePEString = FALSE;
+    
     if( nPCS != KvUserDefined )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
         GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, nPCS );
     }
+    else if( poSRS->IsGeocentric() )
+    {
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1, 
+                   ModelTypeGeocentric );
+    }
     else if( pszProjection == NULL )
     {
         if( poSRS->IsGeographic() )
@@ -1207,15 +1284,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     }
     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_AlbersEqualArea );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_AlbersEqualArea );
 
         GTIFKeySet(psGTIF, ProjStdParallelGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
@@ -1240,7 +1317,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     {
         int		bNorth, nZone, nProjection;
 
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
 
         nZone = poSRS->GetUTMZone( &bNorth );
@@ -1285,15 +1362,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_TransverseMercator );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_TransverseMercator );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1313,15 +1390,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_TransvMercator_SouthOriented );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_TransvMercator_SouthOriented );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1343,15 +1420,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
              || EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
 
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Mercator );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Mercator );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1371,15 +1448,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_ObliqueStereographic );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_ObliqueStereographic );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1399,15 +1476,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Stereographic );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Stereographic );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1427,15 +1504,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_PolarStereographic );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_PolarStereographic );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1455,15 +1532,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_ObliqueMercator );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_ObliqueMercator );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
@@ -1489,15 +1566,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_CassiniSoldner );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_CassiniSoldner );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1514,15 +1591,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_EquidistantConic );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_EquidistantConic );
 
         GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
@@ -1545,15 +1622,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Polyconic );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Polyconic );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1573,15 +1650,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_AzimuthalEquidistant );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_AzimuthalEquidistant );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
@@ -1598,15 +1675,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_MillerCylindrical );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_MillerCylindrical );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
@@ -1623,15 +1700,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Equirectangular );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Equirectangular );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1651,15 +1728,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Gnomonic );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Gnomonic );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1676,15 +1753,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_LambertAzimEqualArea );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_LambertAzimEqualArea );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
@@ -1701,15 +1778,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Orthographic );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Orthographic );
 
         GTIFKeySet(psGTIF, ProjCenterLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1726,15 +1803,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_NewZealandMapGrid );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_NewZealandMapGrid );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1751,15 +1828,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Robinson );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Robinson );
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
@@ -1773,15 +1850,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_Sinusoidal );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_Sinusoidal );
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 ) );
@@ -1795,15 +1872,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_VanDerGrinten );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_VanDerGrinten );
 
         GTIFKeySet(psGTIF, ProjCenterLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
@@ -1817,15 +1894,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_AlbersEqualArea );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_AlbersEqualArea );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0 ) );
@@ -1848,15 +1925,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_LambertConfConic_2SP );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_LambertConfConic_2SP );
 
         GTIFKeySet(psGTIF, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1879,15 +1956,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
     
     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_LambertConfConic_1SP );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_LambertConfConic_1SP );
 
         GTIFKeySet(psGTIF, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) );
@@ -1907,15 +1984,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 
     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
     {
-	GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
-	GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
-	GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
+        GTIFKeySet(psGTIF, ProjectionGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-	GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
-		   CT_CylindricalEqualArea );
+        GTIFKeySet(psGTIF, ProjCoordTransGeoKey, TYPE_SHORT, 1, 
+                   CT_CylindricalEqualArea );
 
         GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
@@ -1929,9 +2006,20 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-    
+
     else
     {
+        bWritePEString = TRUE;
+    }
+
+    // Note that VERTCS is an ESRI "spelling" of VERT_CS so we assume if
+    // we find it that we should try to treat this as a PE string.
+    bWritePEString |= (poSRS->GetAttrValue("VERTCS") != NULL);
+
+    if( bWritePEString 
+        && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
+                                              "YES") ) )
+    {
         /* Anyhing we can't map, we store as an ESRI PE string with a citation key */
         char *pszPEString = NULL;
         poSRS->morphToESRI();
@@ -1939,12 +2027,12 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
         int peStrLen = strlen(pszPEString);
         if(peStrLen > 0)
         {
-            char *outPeStr = new char[peStrLen + strlen("ESRI PE String = ")+1];
+            char *outPeStr = (char *) CPLMalloc( peStrLen + strlen("ESRI PE String = ")+1 );
             strcpy(outPeStr, "ESRI PE String = "); 
             strcat(outPeStr, pszPEString); 
             GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, outPeStr ); 
             peStrStored = TRUE;
-            delete[] outPeStr; 
+            CPLFree( outPeStr );
         }
         if(pszPEString)
             CPLFree( pszPEString );
@@ -1973,7 +2061,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /* -------------------------------------------------------------------- */
 /*      Write linear units information.                                 */
 /* -------------------------------------------------------------------- */
-    if( !poSRS->IsGeographic() )
+    if( poSRS->IsGeocentric() )
+    {
+        GTIFKeySet(psGTIF, GeogLinearUnitsGeoKey, TYPE_SHORT, 1, 
+                   nUOMLengthCode );
+        if( nUOMLengthCode == KvUserDefined )
+            GTIFKeySet( psGTIF, GeogLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
+                        dfLinearUOM);
+    }
+    else if( !poSRS->IsGeographic() )
     {
         GTIFKeySet(psGTIF, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
                    nUOMLengthCode );
@@ -1982,8 +2078,15 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
                         dfLinearUOM);
 
         /* if linear units name is available and user defined, store it as citation */
-        if(!peStrStored && nUOMLengthCode == KvUserDefined && pszLinearUOMName && strlen(pszLinearUOMName)>0)
+        if(!peStrStored 
+           && nUOMLengthCode == KvUserDefined 
+           && pszLinearUOMName 
+           && strlen(pszLinearUOMName)>0
+           && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
+                                                 "YES") ) )
+        {
             SetLinearUnitCitation(psGTIF, pszLinearUOMName);
+        }
     }
     
 /* -------------------------------------------------------------------- */
@@ -2010,7 +2113,7 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 /* -------------------------------------------------------------------- */
     if( poSRS->GetRoot() != NULL
         && poSRS->GetRoot()->GetChild(0) != NULL 
-        && (poSRS->IsProjected() || poSRS->IsLocal()) )
+        && (poSRS->IsProjected() || poSRS->IsLocal() || poSRS->IsGeocentric()) )
     {
         GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0, 
                     poSRS->GetRoot()->GetChild(0)->GetValue() );
@@ -2101,11 +2204,40 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
                         dfSemiMajor );
 
-        if( nGCS == KvUserDefined )
+        if( nGCS == KvUserDefined 
+            && CSLTestBoolean( CPLGetConfigOption("GTIFF_ESRI_CITATION",
+                                                  "YES") ) )
             SetGeogCSCitation(psGTIF, poSRS, angUnitName, nDatum, nSpheroid);
     }
 
 /* -------------------------------------------------------------------- */
+/*      Do we have TOWGS84 parameters?                                  */
+/* -------------------------------------------------------------------- */
+
+#if LIBGEOTIFF_VERSION >= 1310
+    double adfTOWGS84[7];
+
+    if( poSRS->GetTOWGS84( adfTOWGS84 ) == OGRERR_NONE )
+    {
+        if( adfTOWGS84[3] == 0.0 && adfTOWGS84[4] == 0.0
+            && adfTOWGS84[5] == 0.0 && adfTOWGS84[6] == 0.0 )
+        {
+            if( nGCS == GCS_WGS_84 && adfTOWGS84[0] == 0.0
+                && adfTOWGS84[1] == 0.0 && adfTOWGS84[2] == 0.0 )
+            {
+                ; /* do nothing */
+            }
+            else
+                GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 3,
+                            adfTOWGS84 );
+        }
+        else
+            GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 7, 
+                        adfTOWGS84 );
+    }
+#endif
+
+/* -------------------------------------------------------------------- */
 /*      Do we have vertical datum information to set?                   */
 /* -------------------------------------------------------------------- */
     if( poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) != NULL )
@@ -2222,7 +2354,7 @@ CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
     }
 
     else if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
-            && nCount >= 6 )
+             && nCount >= 6 )
     {
         *pnGCPCount = nCount / 6;
         *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),*pnGCPCount);
diff --git a/frmts/gtiff/gt_wkt_srs.h b/frmts/gtiff/gt_wkt_srs.h
index 5b9eee4..38f6e78 100644
--- a/frmts/gtiff/gt_wkt_srs.h
+++ b/frmts/gtiff/gt_wkt_srs.h
@@ -1,15 +1,15 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.h 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: gt_wkt_srs.h 21929 2011-03-11 03:58:42Z warmerdam $
  *
  * 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.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
+ * Author:   Even Rouault
  *
  ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2010, Even Rouault
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,6 +41,6 @@
 CPL_C_START
 char CPL_DLL *  GTIFGetOGISDefn( GTIF *, GTIFDefn * );
 int  CPL_DLL   GTIFSetFromOGISDefn( GTIF *, const char * );
-CPL_C_END;
+CPL_C_END
 
 #endif // GT_WKT_SRS_H_INCLUDED
diff --git a/frmts/gtiff/gt_wkt_srs_for_gdal.h b/frmts/gtiff/gt_wkt_srs_for_gdal.h
index 8a860e6..b12f8fd 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 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: gt_wkt_srs_for_gdal.h 21595 2011-01-28 04:21:40Z warmerdam $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Read/Write in-memory GeoTIFF file
- * Author:   Frank Warmerdam, warmerdam at pobox.com
+ * Author:   Even Rouault
  *
  ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2010, Even Rouault
  *
  * 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/libgeotiff/GNUmakefile b/frmts/gtiff/libgeotiff/GNUmakefile
index a6fabbe..dcca749 100644
--- a/frmts/gtiff/libgeotiff/GNUmakefile
+++ b/frmts/gtiff/libgeotiff/GNUmakefile
@@ -23,6 +23,12 @@ ALL_C_FLAGS	=	$(CPPFLAGS) $(CFLAGS)
 
 ifeq ($(TIFF_SETTING),internal)
 ALL_C_FLAGS	:=	-I../libtiff $(ALL_C_FLAGS)
+ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
+ALL_C_FLAGS	:=	-DRENAME_INTERNAL_LIBTIFF_SYMBOLS $(ALL_C_FLAGS)
+endif
+ifeq ($(RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS),yes)
+ALL_C_FLAGS	:=	-DRENAME_INTERNAL_LIBGEOTIFF_SYMBOLS $(ALL_C_FLAGS)
+endif
 endif
 
 
diff --git a/frmts/gtiff/libgeotiff/cpl_serv.h b/frmts/gtiff/libgeotiff/cpl_serv.h
index f903029..3fe8dd5 100644
--- a/frmts/gtiff/libgeotiff/cpl_serv.h
+++ b/frmts/gtiff/libgeotiff/cpl_serv.h
@@ -39,6 +39,8 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
+#define GTIFAtof CPLAtof
+#define GTIFStrtod CPLStrtod
 /*
  * Define an auxiliary symbol to help us to find when the internal cpl_serv.h
  * is used instead of the external one from the geotiff package.
diff --git a/frmts/gtiff/libgeotiff/dump_symbols.sh b/frmts/gtiff/libgeotiff/dump_symbols.sh
new file mode 100755
index 0000000..a717a7c
--- /dev/null
+++ b/frmts/gtiff/libgeotiff/dump_symbols.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# GDAL specific script to extract exported libtiff symbols that can be renamed
+# to keep them internal to GDAL as much as possible
+
+gcc *.c -fPIC -shared -o libgeotiff.so -I. -I../../../port
+
+OUT_FILE=gdal_libgeotiff_symbol_rename.h
+
+rm $OUT_FILE 2>/dev/null
+
+echo "/* This is a generated file by dump_symbols.h. *DO NOT EDIT MANUALLY !* */" >> $OUT_FILE
+
+symbol_list=$(objdump -t libgeotiff.so  | grep .text | awk '{print $6}' | grep -v .text | grep -v __do_global | grep -v __bss_start | grep -v _edata | grep -v _end | grep -v _fini | grep -v _init | sort)
+for symbol in $symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+rodata_symbol_list=$(objdump -t libgeotiff.so  | grep "\.rodata" |  awk '{print $6}' | grep -v "\.")
+for symbol in $data_symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+data_symbol_list=$(objdump -t libgeotiff.so  | grep "\.data" |  awk '{print $6}' | grep -v "\.")
+for symbol in $data_symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+bss_symbol_list=$(objdump -t libgeotiff.so  | grep "\.bss" |  awk '{print $6}' | grep -v "\.")
+for symbol in $bss_symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+rm libgeotiff.so
diff --git a/frmts/gtiff/libgeotiff/gdal_libgeotiff_symbol_rename.h b/frmts/gtiff/libgeotiff/gdal_libgeotiff_symbol_rename.h
new file mode 100644
index 0000000..e8dbb2c
--- /dev/null
+++ b/frmts/gtiff/libgeotiff/gdal_libgeotiff_symbol_rename.h
@@ -0,0 +1,114 @@
+/* This is a generated file by dump_symbols.h. *DO NOT EDIT MANUALLY !* */
+#define call_gmon_start gdal_call_gmon_start
+#define DefaultPrint gdal_DefaultPrint
+#define DefaultRead gdal_DefaultRead
+#define EPSGProjMethodToCTProjMethod gdal_EPSGProjMethodToCTProjMethod
+#define FindCode gdal_FindCode
+#define FindName gdal_FindName
+#define frame_dummy gdal_frame_dummy
+#define GTIFAngleStringToDD gdal_GTIFAngleStringToDD
+#define GTIFAngleToDD gdal_GTIFAngleToDD
+#define _GTIFcalloc gdal__GTIFcalloc
+#define GTIFDeaccessCSV gdal_GTIFDeaccessCSV
+#define GTIFDecToDMS gdal_GTIFDecToDMS
+#define GTIFDirectoryInfo gdal_GTIFDirectoryInfo
+#define GTIFFetchProjParms gdal_GTIFFetchProjParms
+#define GTIFFree gdal_GTIFFree
+#define _GTIFFree gdal__GTIFFree
+#define GTIFFreeMemory gdal_GTIFFreeMemory
+#define GTIFGetDatumInfo gdal_GTIFGetDatumInfo
+#define GTIFGetDefn gdal_GTIFGetDefn
+#define GTIFGetEllipsoidInfo gdal_GTIFGetEllipsoidInfo
+#define _GTIFGetField gdal__GTIFGetField
+#define _GTIFGetField gdal__GTIFGetField
+#define GTIFGetGCSInfo gdal_GTIFGetGCSInfo
+#define GTIFGetPCSInfo gdal_GTIFGetPCSInfo
+#define GTIFGetPMInfo gdal_GTIFGetPMInfo
+#define GTIFGetProj4Defn gdal_GTIFGetProj4Defn
+#define GTIFGetProjTRFInfo gdal_GTIFGetProjTRFInfo
+#define GTIFGetUOMAngleInfo gdal_GTIFGetUOMAngleInfo
+#define GTIFGetUOMLengthInfo gdal_GTIFGetUOMLengthInfo
+#define GTIFImageToPCS gdal_GTIFImageToPCS
+#define GTIFImport gdal_GTIFImport
+#define GTIFKeyCode gdal_GTIFKeyCode
+#define GTIFKeyGet gdal_GTIFKeyGet
+#define GTIFKeyInfo gdal_GTIFKeyInfo
+#define GTIFKeyName gdal_GTIFKeyName
+#define GTIFKeySet gdal_GTIFKeySet
+#define GTIFMapSysToPCS gdal_GTIFMapSysToPCS
+#define GTIFMapSysToProj gdal_GTIFMapSysToProj
+#define _GTIFmemcpy gdal__GTIFmemcpy
+#define GTIFNew gdal_GTIFNew
+#define GTIFNewSimpleTags gdal_GTIFNewSimpleTags
+#define GTIFNewWithMethods gdal_GTIFNewWithMethods
+#define GTIFPCSToImage gdal_GTIFPCSToImage
+#define GTIFPCSToMapSys gdal_GTIFPCSToMapSys
+#define GTIFPrint gdal_GTIFPrint
+#define GTIFPrintDefn gdal_GTIFPrintDefn
+#define GTIFProj4FromLatLong gdal_GTIFProj4FromLatLong
+#define GTIFProj4ToLatLong gdal_GTIFProj4ToLatLong
+#define GTIFProjToMapSys gdal_GTIFProjToMapSys
+#define _GTIFrealloc gdal__GTIFrealloc
+#define _GTIFSetDefaultTIFF gdal__GTIFSetDefaultTIFF
+#define _GTIFSetField gdal__GTIFSetField
+#define _GTIFSetField gdal__GTIFSetField
+#define GTIFSetFromProj4 gdal_GTIFSetFromProj4
+#define GTIFSetSimpleTagsMethods gdal_GTIFSetSimpleTagsMethods
+#define GTIFTagCode gdal_GTIFTagCode
+#define GTIFTagName gdal_GTIFTagName
+#define _GTIFTagType gdal__GTIFTagType
+#define _GTIFTagType gdal__GTIFTagType
+#define GTIFTiepointTranslate gdal_GTIFTiepointTranslate
+#define GTIFTypeCode gdal_GTIFTypeCode
+#define GTIFTypeName gdal_GTIFTypeName
+#define GTIFValueCode gdal_GTIFValueCode
+#define GTIFValueName gdal_GTIFValueName
+#define GTIFWriteKeys gdal_GTIFWriteKeys
+#define inv_geotransform gdal_inv_geotransform
+#define OSRFreeStringList gdal_OSRFreeStringList
+#define OSR_GDV gdal_OSR_GDV
+#define OSR_GSV gdal_OSR_GSV
+#define OSRProj4Tokenize gdal_OSRProj4Tokenize
+#define PrintGeoTags gdal_PrintGeoTags
+#define PrintKey gdal_PrintKey
+#define PrintTag gdal_PrintTag
+#define ReadKey gdal_ReadKey
+#define ReadKey gdal_ReadKey
+#define ReadTag gdal_ReadTag
+#define SetGTParmIds gdal_SetGTParmIds
+#define SortKeys gdal_SortKeys
+#define ST_Create gdal_ST_Create
+#define ST_Destroy gdal_ST_Destroy
+#define ST_GetKey gdal_ST_GetKey
+#define StringError gdal_StringError
+#define ST_SetKey gdal_ST_SetKey
+#define ST_TagType gdal_ST_TagType
+#define ST_TypeSize gdal_ST_TypeSize
+#define WriteKey gdal_WriteKey
+#define XTIFFClientOpen gdal_XTIFFClientOpen
+#define XTIFFClose gdal_XTIFFClose
+#define _XTIFFDefaultDirectory gdal__XTIFFDefaultDirectory
+#define XTIFFFdOpen gdal_XTIFFFdOpen
+#define XTIFFInitialize gdal_XTIFFInitialize
+#define _XTIFFLocalDefaultDirectory gdal__XTIFFLocalDefaultDirectory
+#define XTIFFOpen gdal_XTIFFOpen
+#define StatePlaneTable gdal_StatePlaneTable
+#define _keyInfo gdal__keyInfo
+#define _csdefaultValue gdal__csdefaultValue
+#define _modeltypeValue gdal__modeltypeValue
+#define _rastertypeValue gdal__rastertypeValue
+#define _geounitsValue gdal__geounitsValue
+#define _geographicValue gdal__geographicValue
+#define _geodeticdatumValue gdal__geodeticdatumValue
+#define _ellipsoidValue gdal__ellipsoidValue
+#define _primemeridianValue gdal__primemeridianValue
+#define _pcstypeValue gdal__pcstypeValue
+#define _projectionValue gdal__projectionValue
+#define _coordtransValue gdal__coordtransValue
+#define _vertcstypeValue gdal__vertcstypeValue
+#define _vdatumValue gdal__vdatumValue
+#define _formatInfo gdal__formatInfo
+#define _tagInfo gdal__tagInfo
+#define xtiffFieldInfo gdal_xtiffFieldInfo
+#define _gtiff_size gdal__gtiff_size
+#define _ParentExtender gdal__ParentExtender
diff --git a/frmts/gtiff/libgeotiff/geo_config.h b/frmts/gtiff/libgeotiff/geo_config.h
index 3a19fb4..a749082 100644
--- a/frmts/gtiff/libgeotiff/geo_config.h
+++ b/frmts/gtiff/libgeotiff/geo_config.h
@@ -4,4 +4,12 @@
 
 #include "cpl_config.h"
 
+#ifdef RENAME_INTERNAL_LIBTIFF_SYMBOLS
+#include "gdal_libtiff_symbol_rename.h"
+#endif
+
+#ifdef RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
+#include "gdal_libgeotiff_symbol_rename.h"
+#endif
+
 #endif /* ndef GEO_CONFIG_H */
diff --git a/frmts/gtiff/libgeotiff/geo_new.c b/frmts/gtiff/libgeotiff/geo_new.c
index fc9548a..f8bb0e1 100644
--- a/frmts/gtiff/libgeotiff/geo_new.c
+++ b/frmts/gtiff/libgeotiff/geo_new.c
@@ -160,7 +160,11 @@ GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
     else
     {
         /* last NULL doesn't count; "|" used for delimiter */
-        --tempData.tk_asciiParamsLength;
+        if( tempData.tk_asciiParamsLength > 0 
+            && tempData.tk_asciiParams[tempData.tk_asciiParamsLength-1] == '\0')
+        {
+            --tempData.tk_asciiParamsLength;
+        }
     }
 
     /* allocate space for GeoKey array and its index */
diff --git a/frmts/gtiff/libgeotiff/geo_normalize.c b/frmts/gtiff/libgeotiff/geo_normalize.c
index 3254bd8..9bb24bc 100644
--- a/frmts/gtiff/libgeotiff/geo_normalize.c
+++ b/frmts/gtiff/libgeotiff/geo_normalize.c
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: geo_normalize.c 1685 2009-11-11 17:08:09Z warmerdam $
+ * $Id: geo_normalize.c 2037 2011-05-24 01:45:24Z warmerdam $
  *
  * Project:  libgeotiff
  * Purpose:  Code to normalize PCS and other composite codes in a GeoTIFF file.
- * Author:   Frank Warmerdam, warmerda at home.com
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
@@ -67,6 +67,11 @@
 #define EPSGSphericalOriginLong  8829
 #define EPSGInitialLongitude     8830
 #define EPSGZoneWidth            8831
+#define EPSGLatOfStdParallel     8832
+#define EPSGOriginLong           8833
+#define EPSGTopocentricOriginLat 8834
+#define EPSGTopocentricOriginLong 8835
+#define EPSGTopocentricOriginHeight 8836
 
 /************************************************************************/
 /*                           GTIFGetPCSInfo()                           */
@@ -109,13 +114,13 @@ int GTIFGetPCSInfo( int nPCSCode, char **ppszEPSGName,
             }
 
             if (pnProjOp)
-                *pnProjOp = ((Proj == MapSys_UTM_North) ? Proj_UTM_zone_1N - 1 : Proj_UTM_zone_1S - 1) + nZone;
+                *pnProjOp = (short) (((Proj == MapSys_UTM_North) ? Proj_UTM_zone_1N - 1 : Proj_UTM_zone_1S - 1) + nZone);
 
             if (pnUOMLengthCode)
                 *pnUOMLengthCode = 9001; /* Linear_Meter */
 
             if (pnGeogCS)
-                *pnGeogCS = nDatum;
+                *pnGeogCS = (short) nDatum;
 
             return TRUE;
         }
@@ -279,7 +284,7 @@ double GTIFAngleStringToDD( const char * pszAngle, int nUOMAngle )
                     szSeconds[1] = '0';
                     szSeconds[2] = '\0';
                 }
-                dfAngle += atof(szSeconds) / 3600.0;
+                dfAngle += GTIFAtof(szSeconds) / 3600.0;
             }
         }
 
@@ -288,26 +293,26 @@ double GTIFAngleStringToDD( const char * pszAngle, int nUOMAngle )
     }
     else if( nUOMAngle == 9105 || nUOMAngle == 9106 )	/* grad */
     {
-        dfAngle = 180 * (atof(pszAngle ) / 200);
-    } 
+        dfAngle = 180 * (GTIFAtof(pszAngle ) / 200);
+    }
     else if( nUOMAngle == 9101 )			/* radians */
     {
-        dfAngle = 180 * (atof(pszAngle ) / PI);
+        dfAngle = 180 * (GTIFAtof(pszAngle ) / PI);
     }
     else if( nUOMAngle == 9103 )			/* arc-minute */
     {
-        dfAngle = atof(pszAngle) / 60;
+        dfAngle = GTIFAtof(pszAngle) / 60;
     }
     else if( nUOMAngle == 9104 )			/* arc-second */
     {
-        dfAngle = atof(pszAngle) / 3600;
+        dfAngle = GTIFAtof(pszAngle) / 3600;
     }
     else /* decimal degrees ... some cases missing but seeminly never used */
     {
         CPLAssert( nUOMAngle == 9102 || nUOMAngle == KvUserDefined
                    || nUOMAngle == 0 );
         
-        dfAngle = atof(pszAngle );
+        dfAngle = GTIFAtof(pszAngle );
     }
 
     return( dfAngle );
@@ -325,7 +330,7 @@ int GTIFGetGCSInfo( int nGCSCode, char ** ppszName,
 
 {
     char	szSearchKey[24];
-    int		nDatum, nPM, nUOMAngle;
+    int		nDatum=0, nPM, nUOMAngle;
     const char *pszFilename;
 
 /* -------------------------------------------------------------------- */
@@ -452,14 +457,14 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
 
 {
     char	szSearchKey[24];
-    double	dfSemiMajor, dfToMeters = 1.0;
+    double	dfSemiMajor=0.0, dfToMeters = 1.0;
     int		nUOMLength;
     const char* pszFilename;
 
 /* -------------------------------------------------------------------- */
 /*      Try some well known ellipsoids.                                 */
 /* -------------------------------------------------------------------- */
-    double     dfInvFlattening, dfSemiMinor;
+    double     dfInvFlattening=0.0, dfSemiMinor=0.0;
     const char *pszName = NULL;
     
     if( nEllipseCode == Ellipse_Clarke_1866 )
@@ -513,7 +518,7 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
     pszFilename = CSVFilename("ellipsoid.csv" );
 
     dfSemiMajor =
-        atof(CSVGetField( pszFilename,
+        GTIFAtof(CSVGetField( pszFilename,
                           "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                           "SEMI_MAJOR_AXIS" ) );
 
@@ -542,7 +547,7 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
     if( pdfSemiMinor != NULL )
     {
         *pdfSemiMinor =
-            atof(CSVGetField( pszFilename,
+            GTIFAtof(CSVGetField( pszFilename,
                               "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                               "SEMI_MINOR_AXIS" )) * dfToMeters;
 
@@ -551,7 +556,7 @@ int GTIFGetEllipsoidInfo( int nEllipseCode, char ** ppszName,
             double	dfInvFlattening;
             
             dfInvFlattening = 
-                atof(CSVGetField( pszFilename,
+                GTIFAtof(CSVGetField( pszFilename,
                                   "ELLIPSOID_CODE", szSearchKey, CC_Integer,
                                   "INV_FLATTENING" ));
             *pdfSemiMinor = dfSemiMajor * (1 - 1.0/dfInvFlattening);
@@ -645,7 +650,7 @@ int GTIFGetDatumInfo( int nDatumCode, char ** ppszName, short * pnEllipsoid )
 
 {
     char	szSearchKey[24];
-    int		nEllipsoid;
+    int		nEllipsoid = 0;
     const char *pszFilename;
     FILE       *fp;
     const char *pszName = NULL;
@@ -817,9 +822,9 @@ int GTIFGetUOMLengthInfo( int nUOMLengthCode,
         iBFactorField = CSVGetFileFieldId( pszFilename, "FACTOR_B" );
         iCFactorField = CSVGetFileFieldId( pszFilename, "FACTOR_C" );
 
-        if( atof(CSLGetField(papszUnitsRecord, iCFactorField)) > 0.0 )
-            *pdfInMeters = atof(CSLGetField(papszUnitsRecord, iBFactorField))
-                / atof(CSLGetField(papszUnitsRecord, iCFactorField));
+        if( GTIFAtof(CSLGetField(papszUnitsRecord, iCFactorField)) > 0.0 )
+            *pdfInMeters = GTIFAtof(CSLGetField(papszUnitsRecord, iBFactorField))
+                / GTIFAtof(CSLGetField(papszUnitsRecord, iCFactorField));
         else
             *pdfInMeters = 0.0;
     }
@@ -919,12 +924,12 @@ int GTIFGetUOMAngleInfo( int nUOMAngleCode,
         double dfFactorB, dfFactorC, dfInRadians;
         
         dfFactorB = 
-            atof(CSVGetField( pszFilename,
+            GTIFAtof(CSVGetField( pszFilename,
                               "UOM_CODE", szSearchKey, CC_Integer,
                               "FACTOR_B" ));
         
         dfFactorC = 
-            atof(CSVGetField( pszFilename,
+            GTIFAtof(CSVGetField( pszFilename,
                               "UOM_CODE", szSearchKey, CC_Integer,
                               "FACTOR_C" ));
 
@@ -1006,6 +1011,7 @@ static int EPSGProjMethodToCTProjMethod( int nEPSG )
         return( CT_ObliqueStereographic );
 
       case 9810:
+        /* case 9829: variant B not quite the same */ 
         return( CT_PolarStereographic );
 
       case 9811:
@@ -1027,10 +1033,14 @@ static int EPSGProjMethodToCTProjMethod( int nEPSG )
         return( KvUserDefined );
 
       case 9820:
+      case 1027:
         return( CT_LambertAzimEqualArea );
 
       case 9822:
         return( CT_AlbersEqualArea );
+
+      case 9834:
+        return( CT_CylindricalEqualArea );
     }
 
     return( KvUserDefined );
@@ -1090,8 +1100,8 @@ static int SetGTParmIds( int nCTProjection,
         panEPSGCodes[2] = EPSGAzimuth;
         panEPSGCodes[3] = EPSGAngleRectifiedToSkewedGrid;
         panEPSGCodes[4] = EPSGInitialLineScaleFactor;
-        panEPSGCodes[5] = EPSGProjCenterEasting;
-        panEPSGCodes[6] = EPSGProjCenterNorthing;
+        panEPSGCodes[5] = EPSGProjCenterEasting; /* EPSG proj method 9812 uses EPSGFalseEasting, but 9815 uses EPSGProjCenterEasting */
+        panEPSGCodes[6] = EPSGProjCenterNorthing; /* EPSG proj method 9812 uses EPSGFalseNorthing, but 9815 uses EPSGProjCenterNorthing */
         return TRUE;
 
       case CT_ObliqueMercator_Laborde:
@@ -1182,6 +1192,18 @@ static int SetGTParmIds( int nCTProjection,
         panEPSGCodes[6] = EPSGFalseNorthing;
         return TRUE;
 
+      case CT_CylindricalEqualArea:
+        panProjParmId[0] = ProjStdParallel1GeoKey;
+        panProjParmId[1] = ProjNatOriginLongGeoKey;
+        panProjParmId[5] = ProjFalseEastingGeoKey;
+        panProjParmId[6] = ProjFalseNorthingGeoKey;
+
+        panEPSGCodes[0] = EPSGStdParallel1Lat;
+        panEPSGCodes[1] = EPSGFalseOriginLong;
+        panEPSGCodes[5] = EPSGFalseOriginEasting;
+        panEPSGCodes[6] = EPSGFalseOriginNorthing;
+        return TRUE;
+
       default:
         return( FALSE );
     }
@@ -1316,7 +1338,29 @@ int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
 
         /* not found, accept the default */
         if( iEPSG == 7 )
-            continue;
+        {
+            /* for CT_ObliqueMercator try alternate parameter codes first */
+            /* because EPSG proj method 9812 uses EPSGFalseXXXXX, but 9815 uses EPSGProjCenterXXXXX */
+            if ( nCTProjMethod == CT_ObliqueMercator && nEPSGCode == EPSGProjCenterEasting )
+                nEPSGCode = EPSGFalseEasting;
+            else if ( nCTProjMethod == CT_ObliqueMercator && nEPSGCode == EPSGProjCenterNorthing )
+                nEPSGCode = EPSGFalseNorthing;
+            else
+                continue;
+                
+            for( iEPSG = 0; iEPSG < 7; iEPSG++ )
+            {
+                sprintf( szParamCodeID, "PARAMETER_CODE_%d", iEPSG+1 );
+
+                if( atoi(CSVGetField( pszFilename,
+                                      "COORD_OP_CODE", szTRFCode, CC_Integer, 
+                                      szParamCodeID )) == nEPSGCode )
+                    break;
+            }
+            
+            if( iEPSG == 7 )
+                continue;
+        }
 
         /* Get the value, and UOM */
         sprintf( szParamUOMID, "PARAMETER_UOM_%d", iEPSG+1 );
@@ -1338,10 +1382,10 @@ int GTIFGetProjTRFInfo( /* COORD_OP_CODE from coordinate_operation.csv */
 
             if( !GTIFGetUOMLengthInfo( nUOM, NULL, &dfInMeters ) )
                 dfInMeters = 1.0;
-            adfProjParms[i] = atof(pszValue) * dfInMeters;
+            adfProjParms[i] = GTIFAtof(pszValue) * dfInMeters;
         }
         else
-            adfProjParms[i] = atof(pszValue);
+            adfProjParms[i] = GTIFAtof(pszValue);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2022,6 +2066,8 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
     psDefn->SemiMinor = 0.0;
     psDefn->PM = KvUserDefined;
     psDefn->PMLongToGreenwich = 0.0;
+    psDefn->TOWGS84Count = 0;
+    memset( psDefn->TOWGS84, 0, sizeof(psDefn->TOWGS84) );
 
     psDefn->ProjCode = KvUserDefined;
     psDefn->Projection = KvUserDefined;
@@ -2211,6 +2257,12 @@ int GTIFGetDefn( GTIF * psGTIF, GTIFDefn * psDefn )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Get the TOWGS84 parameters.                                     */
+/* -------------------------------------------------------------------- */
+    psDefn->TOWGS84Count = 
+        GTIFKeyGet(psGTIF, GeogTOWGS84GeoKey, &(psDefn->TOWGS84), 0, 7 );
+
+/* -------------------------------------------------------------------- */
 /*      Have the projection units of measure been overridden?  We       */
 /*      should likely be doing something about angular units too,       */
 /*      but these are very rarely not decimal degrees for actual        */
@@ -2478,6 +2530,25 @@ void GTIFPrintDefn( GTIFDefn * psDefn, FILE * fp )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Report TOWGS84 parameters.                                      */
+/* -------------------------------------------------------------------- */
+    if( psDefn->TOWGS84Count > 0 )
+    {
+        int i;
+
+        fprintf( fp, "TOWGS84: " );
+        
+        for( i = 0; i < psDefn->TOWGS84Count; i++ )
+        {
+            if( i > 0 )
+                fprintf( fp, "," );
+            fprintf( fp, "%g", psDefn->TOWGS84[i] );
+        }
+
+        fprintf( fp, "\n" );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Report the projection units of measure (currently just          */
 /*      linear).                                                        */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/gtiff/libgeotiff/geo_normalize.h b/frmts/gtiff/libgeotiff/geo_normalize.h
index cf72729..bfaf983 100644
--- a/frmts/gtiff/libgeotiff/geo_normalize.h
+++ b/frmts/gtiff/libgeotiff/geo_normalize.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geo_normalize.h 1641 2009-09-24 19:35:59Z warmerdam $
+ * $Id: geo_normalize.h 1983 2011-03-10 02:10:00Z warmerdam $
  *
  * Project:  libgeotiff
  * Purpose:  Include file related to geo_normalize.c containing Code to
@@ -95,6 +95,12 @@ typedef struct {
     /** The length of the semi minor ellipse axis in meters. */
     double	SemiMinor;
 
+    /** TOWGS84 transformation values (0/3/7) */
+    short       TOWGS84Count;
+
+    /** TOWGS84 transformation values */
+    double      TOWGS84[7];
+
     /** Projection id from ProjectionGeoKey.  For example Proj_UTM_11S. */
     short	ProjCode;
 
diff --git a/frmts/gtiff/libgeotiff/geo_print.c b/frmts/gtiff/libgeotiff/geo_print.c
index 0eb7245..9b22db5 100644
--- a/frmts/gtiff/libgeotiff/geo_print.c
+++ b/frmts/gtiff/libgeotiff/geo_print.c
@@ -121,6 +121,9 @@ static void PrintTag(int tag, int nrows, double *dptr, int ncols,
 		{
 			sprintf(message,FMT_DOUBLE,*data++);
 			print(message,aux);
+
+                        if( j < ncols-1 )
+                            print(" ",aux);
 		}
 		print("\n",aux);
 	}
@@ -263,10 +266,10 @@ int GTIFImport(GTIF *gtif, GTIFReadMethod scan,void *aux)
     scan(message,aux);
     if (strncmp(message,FMT_GEOTIFF,8)) return 0; 
     scan(message,aux);
-    if (!sscanf(message,FMT_VERSION,&gtif->gt_version)) return 0;
+    if (!sscanf(message,FMT_VERSION,(short int*)&gtif->gt_version)) return 0;
     scan(message,aux);
-    if (sscanf(message,FMT_REV,&gtif->gt_rev_major,
-               &gtif->gt_rev_minor) !=2) return 0;
+    if (sscanf(message,FMT_REV,(short int*)&gtif->gt_rev_major,
+               (short int*)&gtif->gt_rev_minor) !=2) return 0;
 
     scan(message,aux);
     if (strncmp(message,FMT_TAGS,8)) return 0;
diff --git a/frmts/gtiff/libgeotiff/geo_simpletags.c b/frmts/gtiff/libgeotiff/geo_simpletags.c
index 513f560..e001782 100644
--- a/frmts/gtiff/libgeotiff/geo_simpletags.c
+++ b/frmts/gtiff/libgeotiff/geo_simpletags.c
@@ -199,7 +199,7 @@ int ST_SetKey( ST_TIFF *st, int tag, int count, int st_type, void *data )
 /* -------------------------------------------------------------------- */
     if (count == 0 && st_type == STT_ASCII ) 
     {
-        count = strlen((char*)data);
+        count = strlen((char*)data)+1;
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/frmts/gtiff/libgeotiff/geo_simpletags.h b/frmts/gtiff/libgeotiff/geo_simpletags.h
index cc52272..666578e 100644
--- a/frmts/gtiff/libgeotiff/geo_simpletags.h
+++ b/frmts/gtiff/libgeotiff/geo_simpletags.h
@@ -31,7 +31,6 @@
 #define __geo_simpletags_h_
 
 #include "geotiff.h"
-#include "cpl_serv.h"
 
 #if defined(__cplusplus)
 extern "C" {
diff --git a/frmts/gtiff/libgeotiff/geokeys.inc b/frmts/gtiff/libgeotiff/geokeys.inc
index 286c23c..03be6e0 100644
--- a/frmts/gtiff/libgeotiff/geokeys.inc
+++ b/frmts/gtiff/libgeotiff/geokeys.inc
@@ -31,6 +31,7 @@ ValuePair(  GeogSemiMinorAxisGeoKey,	2058) /* GeogLinearUnits           */
 ValuePair(  GeogInvFlatteningGeoKey,	2059) /* ratio                     */
 ValuePair(  GeogAzimuthUnitsGeoKey,	2060) /* Section 6.3.1.4 Codes     */
 ValuePair(  GeogPrimeMeridianLongGeoKey,	2061) /* GeoAngularUnit            */
+ValuePair(  GeogTOWGS84GeoKey,          2062) /* 2011 - proposed addition  */
 
 /* 6.2.3 Projected CS Parameter Keys */
 /*    Several keys have been renamed,*/
diff --git a/frmts/gtiff/libgeotiff/geotiff.h b/frmts/gtiff/libgeotiff/geotiff.h
index 6c283e6..6c51d41 100644
--- a/frmts/gtiff/libgeotiff/geotiff.h
+++ b/frmts/gtiff/libgeotiff/geotiff.h
@@ -30,7 +30,7 @@
  */
 #define GvCurrentVersion   1
 
-#define LIBGEOTIFF_VERSION 1390
+#define LIBGEOTIFF_VERSION 1400
 
 #include "geo_config.h"
 #include "geokeys.h"
diff --git a/frmts/gtiff/libgeotiff/geotiff_proj4.c b/frmts/gtiff/libgeotiff/geotiff_proj4.c
index 20bb8f1..47e4597 100644
--- a/frmts/gtiff/libgeotiff/geotiff_proj4.c
+++ b/frmts/gtiff/libgeotiff/geotiff_proj4.c
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: geotiff_proj4.c 1670 2009-10-09 16:29:38Z hobu $
+ * $Id: geotiff_proj4.c 1979 2011-02-24 22:17:39Z warmerdam $
  *
  * Project:  libgeotiff
  * Purpose:  Code to convert a normalized GeoTIFF definition into a PROJ.4
  *           (OGDI) compatible projection string.
- * Author:   Frank Warmerdam, warmerda at home.com
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
@@ -115,7 +115,7 @@ static char **OSRProj4Tokenize( const char *pszFull )
 static const char *OSR_GSV( char **papszNV, const char * pszField )
 
 {
-    int field_len = strlen(pszField);
+    size_t field_len = strlen(pszField);
     int i;
     
     if( !papszNV )
@@ -157,7 +157,7 @@ static double OSR_GDV( char **papszNV, const char * pszField,
     if( pszValue == NULL )
         return dfDefaultValue;
     else
-        return atof(pszValue);
+        return GTIFAtof(pszValue);
 }
 
 /************************************************************************/
@@ -811,7 +811,7 @@ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 )
             GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, 
                         KvUserDefined );
             GTIFKeySet( gtif, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, 
-                        atof(value) );
+                        GTIFAtof(value) );
         }
     }
     else if( EQUAL(value,"meter") || EQUAL(value,"m") )
@@ -1299,7 +1299,7 @@ char * GTIFGetProj4Defn( GTIFDefn * psDefn )
     return( strdup( szProjection ) );
 }
 
-#if !defined(HAVE_LIBPROJ) || !defined(HAVE_PROJECTS_H)
+#if !defined(HAVE_LIBPROJ)
 
 int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
                         double *padfX, double *padfY )
@@ -1330,11 +1330,7 @@ int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
 }
 #else
 
-#include "projects.h"
-
-#ifdef USE_PROJUV
-#  define UV projUV
-#endif
+#include "proj_api.h"
 
 /************************************************************************/
 /*                        GTIFProj4FromLatLong()                        */
@@ -1348,7 +1344,7 @@ int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
 
 {
     char	*pszProjection, **papszArgs;
-    PJ		*psPJ;
+    projPJ	*psPJ;
     int		i;
     
 /* -------------------------------------------------------------------- */
@@ -1380,7 +1376,7 @@ int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints,
 /* -------------------------------------------------------------------- */
     for( i = 0; i < nPoints; i++ )
     {
-        UV	sUV;
+        projUV	sUV;
 
         sUV.u = padfX[i] * DEG_TO_RAD;
         sUV.v = padfY[i] * DEG_TO_RAD;
@@ -1408,7 +1404,7 @@ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
 
 {
     char	*pszProjection, **papszArgs;
-    PJ		*psPJ;
+    projPJ	*psPJ;
     int		i;
     
 /* -------------------------------------------------------------------- */
@@ -1440,7 +1436,7 @@ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
 /* -------------------------------------------------------------------- */
     for( i = 0; i < nPoints; i++ )
     {
-        UV	sUV;
+        projUV	sUV;
 
         sUV.u = padfX[i];
         sUV.v = padfY[i];
@@ -1456,5 +1452,5 @@ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints,
     return TRUE;
 }
 
-#endif /* has projects.h and -lproj */
+#endif /* has proj_api.h and -lproj */
 
diff --git a/frmts/gtiff/libtiff/GNUmakefile b/frmts/gtiff/libtiff/GNUmakefile
index 8a09cbb..d4ae920 100644
--- a/frmts/gtiff/libtiff/GNUmakefile
+++ b/frmts/gtiff/libtiff/GNUmakefile
@@ -51,6 +51,10 @@ else
 XTRA_OPT = 
 endif
 
+ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
+ALL_C_FLAGS 	:=	$(ALL_C_FLAGS) -DRENAME_INTERNAL_LIBTIFF_SYMBOLS
+endif
+
 ifneq ($(LIBZ_SETTING),no)
 ALL_C_FLAGS 	:=	$(ALL_C_FLAGS) -DPIXARLOG_SUPPORT -DZIP_SUPPORT $(XTRA_OPT)
 endif
@@ -65,7 +69,7 @@ endif
 
 ifeq ($(JPEG12_ENABLED),yes)
 ALL_C_FLAGS	:=      $(ALL_C_FLAGS) -DJPEG_DUAL_MODE_8_12
-EXTRA_DEP	=	libjpeg12src	
+EXTRA_DEP	=	libjpeg12src
 endif
 
 ifeq ($(LIBLZMA_SETTING),yes)
@@ -96,6 +100,13 @@ import:
 
 install-obj:	$(EXTRA_DEP) $(O_OBJ:.o=.$(OBJ_EXT))
 
+ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
+../../o/tif_jpeg.$(OBJ_EXT) : tif_jpeg.c t4.h tif_config.h tif_dir.h tif_fax3.h tif_predict.h tiff.h tiffconf.h tiffio.h tiffiop.h tiffvers.h uvcode.h
+	sed "s/defined(TIFFInitJPEG)/0/" < tif_jpeg.c > tmp_tif_jpeg.c
+	$(CC) -c -I../../port $(ALL_C_FLAGS) tmp_tif_jpeg.c -o $@
+	rm tmp_tif_jpeg.c
+endif
+
 ../../o/%.$(OBJ_EXT):	%.c t4.h tif_config.h tif_dir.h tif_fax3.h tif_predict.h tiff.h tiffconf.h tiffio.h tiffiop.h tiffvers.h uvcode.h
 	$(CC) -c -I../../port $(ALL_C_FLAGS) $< -o $@
 
diff --git a/frmts/gtiff/libtiff/dump_symbols.sh b/frmts/gtiff/libtiff/dump_symbols.sh
new file mode 100755
index 0000000..36b0795
--- /dev/null
+++ b/frmts/gtiff/libtiff/dump_symbols.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+# GDAL specific script to extract exported libtiff symbols that can be renamed
+# to keep them internal to GDAL as much as possible
+
+gcc *.c -fPIC -shared -o libtiff.so -I. -I../../../port  -DPIXARLOG_SUPPORT -DZIP_SUPPORT -DOJPEG_SUPPORT -DLZMA_SUPPORT
+
+OUT_FILE=gdal_libtiff_symbol_rename.h
+
+rm $OUT_FILE 2>/dev/null
+
+echo "/* This is a generated file by dump_symbols.h. *DO NOT EDIT MANUALLY !* */" >> $OUT_FILE
+
+# We exclude the TIFFSwab functions for renaming since tif_swab.c uses ifdef to determine if the symbols must be defined
+symbol_list=$(objdump -t libtiff.so  | grep .text | awk '{print $6}' | grep -v .text | grep -v TIFFInit | grep -v TIFFSwab | grep -v __do_global | grep -v __bss_start | grep -v _edata | grep -v _end | grep -v _fini | grep -v _init | sort)
+for symbol in $symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+rodata_symbol_list=$(objdump -t libtiff.so  | grep "\.rodata" |  awk '{print $6}' | grep -v "\.")
+for symbol in $rodata_symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+data_symbol_list=$(objdump -t libtiff.so  | grep "\.data" |  awk '{print $6}' | grep -v "\.")
+for symbol in $data_symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+bss_symbol_list=$(objdump -t libtiff.so  | grep "\.bss" |  awk '{print $6}' | grep -v "\.")
+for symbol in $bss_symbol_list
+do
+    echo "#define $symbol gdal_$symbol" >> $OUT_FILE
+done
+
+rm libtiff.so
+
+# Was excluded by grep -v TIFFInit
+echo "#define TIFFInitDumpMode gdal_TIFFInitDumpMode" >> $OUT_FILE
+
+# Pasted and adapter from tif_codec.c
+echo "#define TIFFReInitJPEG_12 gdal_TIFFReInitJPEG_12" >> $OUT_FILE
+echo "#ifdef LZW_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitLZW gdal_TIFFInitLZW" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef PACKBITS_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitPackBits gdal_TIFFInitPackBits" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef THUNDER_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitThunderScan gdal_TIFFInitThunderScan" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef NEXT_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitNeXT gdal_TIFFInitNeXT" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef JPEG_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitJPEG gdal_TIFFInitJPEG" >> $OUT_FILE
+# Manually added
+echo "#define TIFFInitJPEG_12 gdal_TIFFInitJPEG_12" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef OJPEG_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitOJPEG gdal_TIFFInitOJPEG" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef CCITT_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitCCITTRLE gdal_TIFFInitCCITTRLE" >> $OUT_FILE
+echo "#define TIFFInitCCITTRLEW gdal_TIFFInitCCITTRLEW" >> $OUT_FILE
+echo "#define TIFFInitCCITTFax3 gdal_TIFFInitCCITTFax3" >> $OUT_FILE
+echo "#define TIFFInitCCITTFax4 gdal_TIFFInitCCITTFax4" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef JBIG_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitJBIG gdal_TIFFInitJBIG" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef ZIP_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitZIP gdal_TIFFInitZIP" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef PIXARLOG_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitPixarLog gdal_TIFFInitPixarLog" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef LOGLUV_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitSGILog gdal_TIFFInitSGILog" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
+echo "#ifdef LZMA_SUPPORT" >> $OUT_FILE
+echo "#define TIFFInitLZMA gdal_TIFFInitLZMA" >> $OUT_FILE
+echo "#endif" >> $OUT_FILE
diff --git a/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
new file mode 100644
index 0000000..80920f2
--- /dev/null
+++ b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
@@ -0,0 +1,736 @@
+/* This is a generated file by dump_symbols.h. *DO NOT EDIT MANUALLY !* */
+#define buildMap gdal_buildMap
+#define BuildMapBitdepth16To8 gdal_BuildMapBitdepth16To8
+#define BuildMapUaToAa gdal_BuildMapUaToAa
+#define call_gmon_start gdal_call_gmon_start
+#define checkcmap gdal_checkcmap
+#define CheckDirCount gdal_CheckDirCount
+#define checkInkNamesString gdal_checkInkNamesString
+#define ChopUpSingleUncompressedStrip gdal_ChopUpSingleUncompressedStrip
+#define cl_hash gdal_cl_hash
+#define codeLoop gdal_codeLoop
+#define cvtcmap gdal_cvtcmap
+#define DumpFixupTags gdal_DumpFixupTags
+#define DumpModeDecode gdal_DumpModeDecode
+#define DumpModeEncode gdal_DumpModeEncode
+#define DumpModeSeek gdal_DumpModeSeek
+#define EstimateStripByteCounts gdal_EstimateStripByteCounts
+#define Fax3BadLength gdal_Fax3BadLength
+#define Fax3Cleanup gdal_Fax3Cleanup
+#define Fax3Close gdal_Fax3Close
+#define Fax3Decode1D gdal_Fax3Decode1D
+#define Fax3Decode2D gdal_Fax3Decode2D
+#define Fax3DecodeRLE gdal_Fax3DecodeRLE
+#define Fax3Encode gdal_Fax3Encode
+#define Fax3Encode1DRow gdal_Fax3Encode1DRow
+#define Fax3Encode2DRow gdal_Fax3Encode2DRow
+#define Fax3Extension gdal_Fax3Extension
+#define Fax3FixupTags gdal_Fax3FixupTags
+#define Fax3PostEncode gdal_Fax3PostEncode
+#define Fax3PreDecode gdal_Fax3PreDecode
+#define Fax3PreEncode gdal_Fax3PreEncode
+#define Fax3PrematureEOF gdal_Fax3PrematureEOF
+#define Fax3PrintDir gdal_Fax3PrintDir
+#define Fax3PutBits gdal_Fax3PutBits
+#define Fax3PutEOL gdal_Fax3PutEOL
+#define Fax3SetupState gdal_Fax3SetupState
+#define Fax3Unexpected gdal_Fax3Unexpected
+#define Fax3VGetField gdal_Fax3VGetField
+#define Fax3VSetField gdal_Fax3VSetField
+#define Fax4Decode gdal_Fax4Decode
+#define Fax4Encode gdal_Fax4Encode
+#define Fax4PostEncode gdal_Fax4PostEncode
+#define find0span gdal_find0span
+#define find1span gdal_find1span
+#define fpAcc gdal_fpAcc
+#define fpDiff gdal_fpDiff
+#define frame_dummy gdal_frame_dummy
+#define gtStripContig gdal_gtStripContig
+#define gtStripSeparate gdal_gtStripSeparate
+#define gtTileContig gdal_gtTileContig
+#define gtTileSeparate gdal_gtTileSeparate
+#define horAcc16 gdal_horAcc16
+#define horAcc32 gdal_horAcc32
+#define horAcc8 gdal_horAcc8
+#define horDiff16 gdal_horDiff16
+#define horDiff32 gdal_horDiff32
+#define horDiff8 gdal_horDiff8
+#define horizontalAccumulate11 gdal_horizontalAccumulate11
+#define horizontalAccumulate12 gdal_horizontalAccumulate12
+#define horizontalAccumulate16 gdal_horizontalAccumulate16
+#define horizontalAccumulate8 gdal_horizontalAccumulate8
+#define horizontalAccumulate8abgr gdal_horizontalAccumulate8abgr
+#define horizontalAccumulateF gdal_horizontalAccumulateF
+#define horizontalDifference16 gdal_horizontalDifference16
+#define horizontalDifference8 gdal_horizontalDifference8
+#define horizontalDifferenceF gdal_horizontalDifferenceF
+#define InitCCITTFax3 gdal_InitCCITTFax3
+#define initCIELabConversion gdal_initCIELabConversion
+#define initYCbCrConversion gdal_initYCbCrConversion
+#define isCCITTCompression gdal_isCCITTCompression
+#define jpeg_create_decompress_encap gdal_jpeg_create_decompress_encap
+#define jpeg_encap_unwind gdal_jpeg_encap_unwind
+#define jpeg_read_header_encap gdal_jpeg_read_header_encap
+#define jpeg_read_raw_data_encap gdal_jpeg_read_raw_data_encap
+#define jpeg_read_scanlines_encap gdal_jpeg_read_scanlines_encap
+#define jpeg_start_decompress_encap gdal_jpeg_start_decompress_encap
+#define L16fromY gdal_L16fromY
+#define L16toGry gdal_L16toGry
+#define L16toY gdal_L16toY
+#define LogL10fromY gdal_LogL10fromY
+#define LogL10toY gdal_LogL10toY
+#define LogL16Decode gdal_LogL16Decode
+#define LogL16Encode gdal_LogL16Encode
+#define LogL16fromY gdal_LogL16fromY
+#define LogL16GuessDataFmt gdal_LogL16GuessDataFmt
+#define LogL16InitState gdal_LogL16InitState
+#define LogL16toY gdal_LogL16toY
+#define LogLuv24fromXYZ gdal_LogLuv24fromXYZ
+#define LogLuv24toXYZ gdal_LogLuv24toXYZ
+#define LogLuv32fromXYZ gdal_LogLuv32fromXYZ
+#define LogLuv32toXYZ gdal_LogLuv32toXYZ
+#define LogLuvCleanup gdal_LogLuvCleanup
+#define LogLuvClose gdal_LogLuvClose
+#define LogLuvDecode24 gdal_LogLuvDecode24
+#define LogLuvDecode32 gdal_LogLuvDecode32
+#define LogLuvDecodeStrip gdal_LogLuvDecodeStrip
+#define LogLuvDecodeTile gdal_LogLuvDecodeTile
+#define LogLuvEncode24 gdal_LogLuvEncode24
+#define LogLuvEncode32 gdal_LogLuvEncode32
+#define LogLuvEncodeStrip gdal_LogLuvEncodeStrip
+#define LogLuvEncodeTile gdal_LogLuvEncodeTile
+#define LogLuvFixupTags gdal_LogLuvFixupTags
+#define LogLuvGuessDataFmt gdal_LogLuvGuessDataFmt
+#define LogLuvInitState gdal_LogLuvInitState
+#define _logLuvNop gdal__logLuvNop
+#define LogLuvSetupDecode gdal_LogLuvSetupDecode
+#define LogLuvSetupEncode gdal_LogLuvSetupEncode
+#define LogLuvVGetField gdal_LogLuvVGetField
+#define LogLuvVSetField gdal_LogLuvVSetField
+#define Luv24fromLuv48 gdal_Luv24fromLuv48
+#define Luv24fromXYZ gdal_Luv24fromXYZ
+#define Luv24toLuv48 gdal_Luv24toLuv48
+#define Luv24toRGB gdal_Luv24toRGB
+#define Luv24toXYZ gdal_Luv24toXYZ
+#define Luv32fromLuv48 gdal_Luv32fromLuv48
+#define Luv32fromXYZ gdal_Luv32fromXYZ
+#define Luv32toLuv48 gdal_Luv32toLuv48
+#define Luv32toRGB gdal_Luv32toRGB
+#define Luv32toXYZ gdal_Luv32toXYZ
+#define LZMACleanup gdal_LZMACleanup
+#define LZMADecode gdal_LZMADecode
+#define LZMAEncode gdal_LZMAEncode
+#define LZMAFixupTags gdal_LZMAFixupTags
+#define LZMAPostEncode gdal_LZMAPostEncode
+#define LZMAPreDecode gdal_LZMAPreDecode
+#define LZMAPreEncode gdal_LZMAPreEncode
+#define LZMASetupDecode gdal_LZMASetupDecode
+#define LZMASetupEncode gdal_LZMASetupEncode
+#define LZMAStrerror gdal_LZMAStrerror
+#define LZMAVGetField gdal_LZMAVGetField
+#define LZMAVSetField gdal_LZMAVSetField
+#define LZWCleanup gdal_LZWCleanup
+#define LZWDecode gdal_LZWDecode
+#define LZWDecodeCompat gdal_LZWDecodeCompat
+#define LZWEncode gdal_LZWEncode
+#define LZWFixupTags gdal_LZWFixupTags
+#define LZWPostEncode gdal_LZWPostEncode
+#define LZWPreDecode gdal_LZWPreDecode
+#define LZWPreEncode gdal_LZWPreEncode
+#define LZWSetupDecode gdal_LZWSetupDecode
+#define LZWSetupEncode gdal_LZWSetupEncode
+#define makebwmap gdal_makebwmap
+#define makecmap gdal_makecmap
+#define MissingRequired gdal_MissingRequired
+#define multiply_ms gdal_multiply_ms
+#define multiply_ms gdal_multiply_ms
+#define NeXTDecode gdal_NeXTDecode
+#define _notConfigured gdal__notConfigured
+#define NotConfigured gdal_NotConfigured
+#define OJPEGCleanup gdal_OJPEGCleanup
+#define OJPEGDecode gdal_OJPEGDecode
+#define OJPEGDecodeRaw gdal_OJPEGDecodeRaw
+#define OJPEGDecodeScanlines gdal_OJPEGDecodeScanlines
+#define OJPEGEncode gdal_OJPEGEncode
+#define OJPEGFixupTags gdal_OJPEGFixupTags
+#define OJPEGLibjpegJpegErrorMgrErrorExit gdal_OJPEGLibjpegJpegErrorMgrErrorExit
+#define OJPEGLibjpegJpegErrorMgrOutputMessage gdal_OJPEGLibjpegJpegErrorMgrOutputMessage
+#define OJPEGLibjpegJpegSourceMgrFillInputBuffer gdal_OJPEGLibjpegJpegSourceMgrFillInputBuffer
+#define OJPEGLibjpegJpegSourceMgrInitSource gdal_OJPEGLibjpegJpegSourceMgrInitSource
+#define OJPEGLibjpegJpegSourceMgrResyncToRestart gdal_OJPEGLibjpegJpegSourceMgrResyncToRestart
+#define OJPEGLibjpegJpegSourceMgrSkipInputData gdal_OJPEGLibjpegJpegSourceMgrSkipInputData
+#define OJPEGLibjpegJpegSourceMgrTermSource gdal_OJPEGLibjpegJpegSourceMgrTermSource
+#define OJPEGLibjpegSessionAbort gdal_OJPEGLibjpegSessionAbort
+#define OJPEGPostDecode gdal_OJPEGPostDecode
+#define OJPEGPostEncode gdal_OJPEGPostEncode
+#define OJPEGPreDecode gdal_OJPEGPreDecode
+#define OJPEGPreDecodeSkipRaw gdal_OJPEGPreDecodeSkipRaw
+#define OJPEGPreDecodeSkipScanlines gdal_OJPEGPreDecodeSkipScanlines
+#define OJPEGPreEncode gdal_OJPEGPreEncode
+#define OJPEGPrintDir gdal_OJPEGPrintDir
+#define OJPEGReadBlock gdal_OJPEGReadBlock
+#define OJPEGReadBufferFill gdal_OJPEGReadBufferFill
+#define OJPEGReadByte gdal_OJPEGReadByte
+#define OJPEGReadByteAdvance gdal_OJPEGReadByteAdvance
+#define OJPEGReadBytePeek gdal_OJPEGReadBytePeek
+#define OJPEGReadHeaderInfo gdal_OJPEGReadHeaderInfo
+#define OJPEGReadHeaderInfoSec gdal_OJPEGReadHeaderInfoSec
+#define OJPEGReadHeaderInfoSecStreamDht gdal_OJPEGReadHeaderInfoSecStreamDht
+#define OJPEGReadHeaderInfoSecStreamDqt gdal_OJPEGReadHeaderInfoSecStreamDqt
+#define OJPEGReadHeaderInfoSecStreamDri gdal_OJPEGReadHeaderInfoSecStreamDri
+#define OJPEGReadHeaderInfoSecStreamSof gdal_OJPEGReadHeaderInfoSecStreamSof
+#define OJPEGReadHeaderInfoSecStreamSos gdal_OJPEGReadHeaderInfoSecStreamSos
+#define OJPEGReadHeaderInfoSecTablesAcTable gdal_OJPEGReadHeaderInfoSecTablesAcTable
+#define OJPEGReadHeaderInfoSecTablesDcTable gdal_OJPEGReadHeaderInfoSecTablesDcTable
+#define OJPEGReadHeaderInfoSecTablesQTable gdal_OJPEGReadHeaderInfoSecTablesQTable
+#define OJPEGReadSecondarySos gdal_OJPEGReadSecondarySos
+#define OJPEGReadSkip gdal_OJPEGReadSkip
+#define OJPEGReadWord gdal_OJPEGReadWord
+#define OJPEGSetupDecode gdal_OJPEGSetupDecode
+#define OJPEGSetupEncode gdal_OJPEGSetupEncode
+#define OJPEGSubsamplingCorrect gdal_OJPEGSubsamplingCorrect
+#define OJPEGVGetField gdal_OJPEGVGetField
+#define OJPEGVSetField gdal_OJPEGVSetField
+#define OJPEGWriteHeaderInfo gdal_OJPEGWriteHeaderInfo
+#define OJPEGWriteStream gdal_OJPEGWriteStream
+#define OJPEGWriteStreamAcTable gdal_OJPEGWriteStreamAcTable
+#define OJPEGWriteStreamCompressed gdal_OJPEGWriteStreamCompressed
+#define OJPEGWriteStreamDcTable gdal_OJPEGWriteStreamDcTable
+#define OJPEGWriteStreamDri gdal_OJPEGWriteStreamDri
+#define OJPEGWriteStreamEoi gdal_OJPEGWriteStreamEoi
+#define OJPEGWriteStreamQTable gdal_OJPEGWriteStreamQTable
+#define OJPEGWriteStreamRst gdal_OJPEGWriteStreamRst
+#define OJPEGWriteStreamSof gdal_OJPEGWriteStreamSof
+#define OJPEGWriteStreamSoi gdal_OJPEGWriteStreamSoi
+#define OJPEGWriteStreamSos gdal_OJPEGWriteStreamSos
+#define OkToChangeTag gdal_OkToChangeTag
+#define oog_encode gdal_oog_encode
+#define PackBitsDecode gdal_PackBitsDecode
+#define PackBitsEncode gdal_PackBitsEncode
+#define PackBitsEncodeChunk gdal_PackBitsEncodeChunk
+#define PackBitsPostEncode gdal_PackBitsPostEncode
+#define PackBitsPreEncode gdal_PackBitsPreEncode
+#define PickContigCase gdal_PickContigCase
+#define PickSeparateCase gdal_PickSeparateCase
+#define PixarLogCleanup gdal_PixarLogCleanup
+#define PixarLogClose gdal_PixarLogClose
+#define PixarLogDecode gdal_PixarLogDecode
+#define PixarLogEncode gdal_PixarLogEncode
+#define PixarLogFixupTags gdal_PixarLogFixupTags
+#define PixarLogGuessDataFmt gdal_PixarLogGuessDataFmt
+#define PixarLogMakeTables gdal_PixarLogMakeTables
+#define PixarLogPostEncode gdal_PixarLogPostEncode
+#define PixarLogPreDecode gdal_PixarLogPreDecode
+#define PixarLogPreEncode gdal_PixarLogPreEncode
+#define PixarLogSetupDecode gdal_PixarLogSetupDecode
+#define PixarLogSetupEncode gdal_PixarLogSetupEncode
+#define PixarLogVGetField gdal_PixarLogVGetField
+#define PixarLogVSetField gdal_PixarLogVSetField
+#define PredictorDecodeRow gdal_PredictorDecodeRow
+#define PredictorDecodeTile gdal_PredictorDecodeTile
+#define PredictorEncodeRow gdal_PredictorEncodeRow
+#define PredictorEncodeTile gdal_PredictorEncodeTile
+#define PredictorPrintDir gdal_PredictorPrintDir
+#define PredictorSetup gdal_PredictorSetup
+#define PredictorSetupDecode gdal_PredictorSetupDecode
+#define PredictorSetupEncode gdal_PredictorSetupEncode
+#define PredictorVGetField gdal_PredictorVGetField
+#define PredictorVSetField gdal_PredictorVSetField
+#define put16bitbwtile gdal_put16bitbwtile
+#define put1bitbwtile gdal_put1bitbwtile
+#define put1bitcmaptile gdal_put1bitcmaptile
+#define put2bitbwtile gdal_put2bitbwtile
+#define put2bitcmaptile gdal_put2bitcmaptile
+#define put4bitbwtile gdal_put4bitbwtile
+#define put4bitcmaptile gdal_put4bitcmaptile
+#define put8bitcmaptile gdal_put8bitcmaptile
+#define putcontig8bitCIELab gdal_putcontig8bitCIELab
+#define putcontig8bitYCbCr11tile gdal_putcontig8bitYCbCr11tile
+#define putcontig8bitYCbCr12tile gdal_putcontig8bitYCbCr12tile
+#define putcontig8bitYCbCr21tile gdal_putcontig8bitYCbCr21tile
+#define putcontig8bitYCbCr22tile gdal_putcontig8bitYCbCr22tile
+#define putcontig8bitYCbCr41tile gdal_putcontig8bitYCbCr41tile
+#define putcontig8bitYCbCr42tile gdal_putcontig8bitYCbCr42tile
+#define putcontig8bitYCbCr44tile gdal_putcontig8bitYCbCr44tile
+#define putgreytile gdal_putgreytile
+#define putRGBAAcontig16bittile gdal_putRGBAAcontig16bittile
+#define putRGBAAcontig8bittile gdal_putRGBAAcontig8bittile
+#define putRGBAAseparate16bittile gdal_putRGBAAseparate16bittile
+#define putRGBAAseparate8bittile gdal_putRGBAAseparate8bittile
+#define putRGBcontig16bittile gdal_putRGBcontig16bittile
+#define putRGBcontig8bitCMYKMaptile gdal_putRGBcontig8bitCMYKMaptile
+#define putRGBcontig8bitCMYKtile gdal_putRGBcontig8bitCMYKtile
+#define putRGBcontig8bittile gdal_putRGBcontig8bittile
+#define putRGBseparate16bittile gdal_putRGBseparate16bittile
+#define putRGBseparate8bittile gdal_putRGBseparate8bittile
+#define putRGBUAcontig16bittile gdal_putRGBUAcontig16bittile
+#define putRGBUAcontig8bittile gdal_putRGBUAcontig8bittile
+#define putRGBUAseparate16bittile gdal_putRGBUAseparate16bittile
+#define putRGBUAseparate8bittile gdal_putRGBUAseparate8bittile
+#define putseparate8bitYCbCr11tile gdal_putseparate8bitYCbCr11tile
+#define putspan gdal_putspan
+#define setByteArray gdal_setByteArray
+#define setDoubleArrayOneValue gdal_setDoubleArrayOneValue
+#define setExtraSamples gdal_setExtraSamples
+#define setorientation gdal_setorientation
+#define setupMap gdal_setupMap
+#define swabHorAcc16 gdal_swabHorAcc16
+#define swabHorAcc32 gdal_swabHorAcc32
+#define tagCompare gdal_tagCompare
+#define tagNameCompare gdal_tagNameCompare
+#define td_lfind gdal_td_lfind
+#define ThunderDecode gdal_ThunderDecode
+#define ThunderDecodeRow gdal_ThunderDecodeRow
+#define ThunderSetupDecode gdal_ThunderSetupDecode
+#define TIFFAccessTagMethods gdal_TIFFAccessTagMethods
+#define TIFFAdvanceDirectory gdal_TIFFAdvanceDirectory
+#define TIFFAppendToStrip gdal_TIFFAppendToStrip
+#define TIFFCheckDirOffset gdal_TIFFCheckDirOffset
+#define _TIFFCheckMalloc gdal__TIFFCheckMalloc
+#define TIFFCheckpointDirectory gdal_TIFFCheckpointDirectory
+#define TIFFCheckRead gdal_TIFFCheckRead
+#define _TIFFCheckRealloc gdal__TIFFCheckRealloc
+#define TIFFCheckTile gdal_TIFFCheckTile
+#define TIFFCIELabToRGBInit gdal_TIFFCIELabToRGBInit
+#define TIFFCIELabToXYZ gdal_TIFFCIELabToXYZ
+#define TIFFCleanup gdal_TIFFCleanup
+#define TIFFClientdata gdal_TIFFClientdata
+#define TIFFClientOpen gdal_TIFFClientOpen
+#define TIFFClose gdal_TIFFClose
+#define _tiffCloseProc gdal__tiffCloseProc
+#define TIFFComputeStrip gdal_TIFFComputeStrip
+#define TIFFComputeTile gdal_TIFFComputeTile
+#define _TIFFCreateAnonField gdal__TIFFCreateAnonField
+#define TIFFCreateDirectory gdal_TIFFCreateDirectory
+#define TIFFCurrentDirectory gdal_TIFFCurrentDirectory
+#define TIFFCurrentDirOffset gdal_TIFFCurrentDirOffset
+#define TIFFCurrentRow gdal_TIFFCurrentRow
+#define TIFFCurrentStrip gdal_TIFFCurrentStrip
+#define TIFFCurrentTile gdal_TIFFCurrentTile
+#define _TIFFDataSize gdal__TIFFDataSize
+#define TIFFDataWidth gdal_TIFFDataWidth
+#define TIFFDefaultDirectory gdal_TIFFDefaultDirectory
+#define TIFFDefaultRefBlackWhite gdal_TIFFDefaultRefBlackWhite
+#define TIFFDefaultStripSize gdal_TIFFDefaultStripSize
+#define _TIFFDefaultStripSize gdal__TIFFDefaultStripSize
+#define TIFFDefaultTileSize gdal_TIFFDefaultTileSize
+#define _TIFFDefaultTileSize gdal__TIFFDefaultTileSize
+#define TIFFDefaultTransferFunction gdal_TIFFDefaultTransferFunction
+#define _tiffDummyMapProc gdal__tiffDummyMapProc
+#define _tiffDummyUnmapProc gdal__tiffDummyUnmapProc
+#define TIFFError gdal_TIFFError
+#define TIFFErrorExt gdal_TIFFErrorExt
+#define _TIFFFax3fillruns gdal__TIFFFax3fillruns
+#define TIFFFdOpen gdal_TIFFFdOpen
+#define TIFFFetchDirectory gdal_TIFFFetchDirectory
+#define TIFFFetchNormalTag gdal_TIFFFetchNormalTag
+#define TIFFFetchStripThing gdal_TIFFFetchStripThing
+#define TIFFFetchSubjectDistance gdal_TIFFFetchSubjectDistance
+#define TIFFFieldWithName gdal_TIFFFieldWithName
+#define TIFFFieldWithTag gdal_TIFFFieldWithTag
+#define TIFFFileName gdal_TIFFFileName
+#define TIFFFileno gdal_TIFFFileno
+#define _TIFFFillStriles gdal__TIFFFillStriles
+#define TIFFFillStrip gdal_TIFFFillStrip
+#define TIFFFillStripPartial gdal_TIFFFillStripPartial
+#define TIFFFillTile gdal_TIFFFillTile
+#define TIFFFindCODEC gdal_TIFFFindCODEC
+#define TIFFFindField gdal_TIFFFindField
+#define _TIFFFindFieldByName gdal__TIFFFindFieldByName
+#define TIFFFindFieldInfo gdal_TIFFFindFieldInfo
+#define TIFFFindFieldInfoByName gdal_TIFFFindFieldInfoByName
+#define _TIFFFindOrRegisterField gdal__TIFFFindOrRegisterField
+#define TIFFFlush gdal_TIFFFlush
+#define TIFFFlushData gdal_TIFFFlushData
+#define TIFFFlushData1 gdal_TIFFFlushData1
+#define _TIFFfree gdal__TIFFfree
+#define TIFFFreeDirectory gdal_TIFFFreeDirectory
+#define TIFFGetBitRevTable gdal_TIFFGetBitRevTable
+#define TIFFGetClientInfo gdal_TIFFGetClientInfo
+#define TIFFGetCloseProc gdal_TIFFGetCloseProc
+#define TIFFGetConfiguredCODECs gdal_TIFFGetConfiguredCODECs
+#define _TIFFGetExifFields gdal__TIFFGetExifFields
+#define TIFFGetField gdal_TIFFGetField
+#define TIFFGetFieldDefaulted gdal_TIFFGetFieldDefaulted
+#define _TIFFGetFields gdal__TIFFGetFields
+#define TIFFGetMapFileProc gdal_TIFFGetMapFileProc
+#define _TIFFgetMode gdal__TIFFgetMode
+#define TIFFGetMode gdal_TIFFGetMode
+#define TIFFGetReadProc gdal_TIFFGetReadProc
+#define TIFFGetSeekProc gdal_TIFFGetSeekProc
+#define TIFFGetSizeProc gdal_TIFFGetSizeProc
+#define TIFFGetTagListCount gdal_TIFFGetTagListCount
+#define TIFFGetTagListEntry gdal_TIFFGetTagListEntry
+#define TIFFGetUnmapFileProc gdal_TIFFGetUnmapFileProc
+#define TIFFGetVersion gdal_TIFFGetVersion
+#define TIFFGetWriteProc gdal_TIFFGetWriteProc
+#define TIFFGrowStrips gdal_TIFFGrowStrips
+#define TIFFIsBigEndian gdal_TIFFIsBigEndian
+#define TIFFIsByteSwapped gdal_TIFFIsByteSwapped
+#define TIFFIsCODECConfigured gdal_TIFFIsCODECConfigured
+#define TIFFIsMSB2LSB gdal_TIFFIsMSB2LSB
+#define TIFFIsTiled gdal_TIFFIsTiled
+#define TIFFIsUpSampled gdal_TIFFIsUpSampled
+#define TIFFLastDirectory gdal_TIFFLastDirectory
+#define TIFFLinkDirectory gdal_TIFFLinkDirectory
+#define _TIFFmalloc gdal__TIFFmalloc
+#define _tiffMapProc gdal__tiffMapProc
+#define _TIFFmemcmp gdal__TIFFmemcmp
+#define _TIFFmemcpy gdal__TIFFmemcpy
+#define _TIFFmemset gdal__TIFFmemset
+#define TIFFMergeFieldInfo gdal_TIFFMergeFieldInfo
+#define _TIFFMergeFields gdal__TIFFMergeFields
+#define _TIFFMultiply32 gdal__TIFFMultiply32
+#define _TIFFMultiply64 gdal__TIFFMultiply64
+#define TIFFNoDecode gdal_TIFFNoDecode
+#define TIFFNoEncode gdal_TIFFNoEncode
+#define _TIFFNoFixupTags gdal__TIFFNoFixupTags
+#define _TIFFNoPostDecode gdal__TIFFNoPostDecode
+#define _TIFFNoPreCode gdal__TIFFNoPreCode
+#define _TIFFNoRowDecode gdal__TIFFNoRowDecode
+#define _TIFFNoRowEncode gdal__TIFFNoRowEncode
+#define _TIFFNoSeek gdal__TIFFNoSeek
+#define _TIFFNoStripDecode gdal__TIFFNoStripDecode
+#define _TIFFNoStripEncode gdal__TIFFNoStripEncode
+#define _TIFFNoTileDecode gdal__TIFFNoTileDecode
+#define _TIFFNoTileEncode gdal__TIFFNoTileEncode
+#define TIFFNumberOfDirectories gdal_TIFFNumberOfDirectories
+#define TIFFNumberOfStrips gdal_TIFFNumberOfStrips
+#define TIFFNumberOfTiles gdal_TIFFNumberOfTiles
+#define TIFFOpen gdal_TIFFOpen
+#define TIFFPredictorCleanup gdal_TIFFPredictorCleanup
+#define TIFFPredictorInit gdal_TIFFPredictorInit
+#define _TIFFPrettyPrintField gdal__TIFFPrettyPrintField
+#define _TIFFprintAscii gdal__TIFFprintAscii
+#define _TIFFprintAsciiTag gdal__TIFFprintAsciiTag
+#define TIFFPrintDirectory gdal_TIFFPrintDirectory
+#define _TIFFPrintField gdal__TIFFPrintField
+#define _TIFFPrintFieldInfo gdal__TIFFPrintFieldInfo
+#define TIFFRasterScanlineSize gdal_TIFFRasterScanlineSize
+#define TIFFRasterScanlineSize64 gdal_TIFFRasterScanlineSize64
+#define TIFFRawStripSize gdal_TIFFRawStripSize
+#define TIFFRawStripSize64 gdal_TIFFRawStripSize64
+#define TIFFReadBufferSetup gdal_TIFFReadBufferSetup
+#define TIFFReadCustomDirectory gdal_TIFFReadCustomDirectory
+#define TIFFReadDirectory gdal_TIFFReadDirectory
+#define TIFFReadDirectoryCheckOrder gdal_TIFFReadDirectoryCheckOrder
+#define TIFFReadDirectoryFindEntry gdal_TIFFReadDirectoryFindEntry
+#define TIFFReadDirectoryFindFieldInfo gdal_TIFFReadDirectoryFindFieldInfo
+#define TIFFReadDirEntryArray gdal_TIFFReadDirEntryArray
+#define TIFFReadDirEntryByte gdal_TIFFReadDirEntryByte
+#define TIFFReadDirEntryByteArray gdal_TIFFReadDirEntryByteArray
+#define TIFFReadDirEntryCheckedByte gdal_TIFFReadDirEntryCheckedByte
+#define TIFFReadDirEntryCheckedDouble gdal_TIFFReadDirEntryCheckedDouble
+#define TIFFReadDirEntryCheckedFloat gdal_TIFFReadDirEntryCheckedFloat
+#define TIFFReadDirEntryCheckedLong gdal_TIFFReadDirEntryCheckedLong
+#define TIFFReadDirEntryCheckedLong8 gdal_TIFFReadDirEntryCheckedLong8
+#define TIFFReadDirEntryCheckedRational gdal_TIFFReadDirEntryCheckedRational
+#define TIFFReadDirEntryCheckedSbyte gdal_TIFFReadDirEntryCheckedSbyte
+#define TIFFReadDirEntryCheckedShort gdal_TIFFReadDirEntryCheckedShort
+#define TIFFReadDirEntryCheckedSlong gdal_TIFFReadDirEntryCheckedSlong
+#define TIFFReadDirEntryCheckedSlong8 gdal_TIFFReadDirEntryCheckedSlong8
+#define TIFFReadDirEntryCheckedSrational gdal_TIFFReadDirEntryCheckedSrational
+#define TIFFReadDirEntryCheckedSshort gdal_TIFFReadDirEntryCheckedSshort
+#define TIFFReadDirEntryCheckRangeByteLong gdal_TIFFReadDirEntryCheckRangeByteLong
+#define TIFFReadDirEntryCheckRangeByteLong8 gdal_TIFFReadDirEntryCheckRangeByteLong8
+#define TIFFReadDirEntryCheckRangeByteSbyte gdal_TIFFReadDirEntryCheckRangeByteSbyte
+#define TIFFReadDirEntryCheckRangeByteShort gdal_TIFFReadDirEntryCheckRangeByteShort
+#define TIFFReadDirEntryCheckRangeByteSlong gdal_TIFFReadDirEntryCheckRangeByteSlong
+#define TIFFReadDirEntryCheckRangeByteSlong8 gdal_TIFFReadDirEntryCheckRangeByteSlong8
+#define TIFFReadDirEntryCheckRangeByteSshort gdal_TIFFReadDirEntryCheckRangeByteSshort
+#define TIFFReadDirEntryCheckRangeLong8Sbyte gdal_TIFFReadDirEntryCheckRangeLong8Sbyte
+#define TIFFReadDirEntryCheckRangeLong8Slong gdal_TIFFReadDirEntryCheckRangeLong8Slong
+#define TIFFReadDirEntryCheckRangeLong8Slong8 gdal_TIFFReadDirEntryCheckRangeLong8Slong8
+#define TIFFReadDirEntryCheckRangeLong8Sshort gdal_TIFFReadDirEntryCheckRangeLong8Sshort
+#define TIFFReadDirEntryCheckRangeLongLong8 gdal_TIFFReadDirEntryCheckRangeLongLong8
+#define TIFFReadDirEntryCheckRangeLongSbyte gdal_TIFFReadDirEntryCheckRangeLongSbyte
+#define TIFFReadDirEntryCheckRangeLongSlong gdal_TIFFReadDirEntryCheckRangeLongSlong
+#define TIFFReadDirEntryCheckRangeLongSlong8 gdal_TIFFReadDirEntryCheckRangeLongSlong8
+#define TIFFReadDirEntryCheckRangeLongSshort gdal_TIFFReadDirEntryCheckRangeLongSshort
+#define TIFFReadDirEntryCheckRangeSbyteByte gdal_TIFFReadDirEntryCheckRangeSbyteByte
+#define TIFFReadDirEntryCheckRangeSbyteLong gdal_TIFFReadDirEntryCheckRangeSbyteLong
+#define TIFFReadDirEntryCheckRangeSbyteLong8 gdal_TIFFReadDirEntryCheckRangeSbyteLong8
+#define TIFFReadDirEntryCheckRangeSbyteShort gdal_TIFFReadDirEntryCheckRangeSbyteShort
+#define TIFFReadDirEntryCheckRangeSbyteSlong gdal_TIFFReadDirEntryCheckRangeSbyteSlong
+#define TIFFReadDirEntryCheckRangeSbyteSlong8 gdal_TIFFReadDirEntryCheckRangeSbyteSlong8
+#define TIFFReadDirEntryCheckRangeSbyteSshort gdal_TIFFReadDirEntryCheckRangeSbyteSshort
+#define TIFFReadDirEntryCheckRangeShortLong gdal_TIFFReadDirEntryCheckRangeShortLong
+#define TIFFReadDirEntryCheckRangeShortLong8 gdal_TIFFReadDirEntryCheckRangeShortLong8
+#define TIFFReadDirEntryCheckRangeShortSbyte gdal_TIFFReadDirEntryCheckRangeShortSbyte
+#define TIFFReadDirEntryCheckRangeShortSlong gdal_TIFFReadDirEntryCheckRangeShortSlong
+#define TIFFReadDirEntryCheckRangeShortSlong8 gdal_TIFFReadDirEntryCheckRangeShortSlong8
+#define TIFFReadDirEntryCheckRangeShortSshort gdal_TIFFReadDirEntryCheckRangeShortSshort
+#define TIFFReadDirEntryCheckRangeSlong8Long8 gdal_TIFFReadDirEntryCheckRangeSlong8Long8
+#define TIFFReadDirEntryCheckRangeSlongLong gdal_TIFFReadDirEntryCheckRangeSlongLong
+#define TIFFReadDirEntryCheckRangeSlongLong8 gdal_TIFFReadDirEntryCheckRangeSlongLong8
+#define TIFFReadDirEntryCheckRangeSlongSlong8 gdal_TIFFReadDirEntryCheckRangeSlongSlong8
+#define TIFFReadDirEntryCheckRangeSshortLong gdal_TIFFReadDirEntryCheckRangeSshortLong
+#define TIFFReadDirEntryCheckRangeSshortLong8 gdal_TIFFReadDirEntryCheckRangeSshortLong8
+#define TIFFReadDirEntryCheckRangeSshortShort gdal_TIFFReadDirEntryCheckRangeSshortShort
+#define TIFFReadDirEntryCheckRangeSshortSlong gdal_TIFFReadDirEntryCheckRangeSshortSlong
+#define TIFFReadDirEntryCheckRangeSshortSlong8 gdal_TIFFReadDirEntryCheckRangeSshortSlong8
+#define TIFFReadDirEntryData gdal_TIFFReadDirEntryData
+#define TIFFReadDirEntryDouble gdal_TIFFReadDirEntryDouble
+#define TIFFReadDirEntryDoubleArray gdal_TIFFReadDirEntryDoubleArray
+#define TIFFReadDirEntryFloat gdal_TIFFReadDirEntryFloat
+#define TIFFReadDirEntryFloatArray gdal_TIFFReadDirEntryFloatArray
+#define TIFFReadDirEntryIfd8 gdal_TIFFReadDirEntryIfd8
+#define TIFFReadDirEntryIfd8Array gdal_TIFFReadDirEntryIfd8Array
+#define TIFFReadDirEntryLong gdal_TIFFReadDirEntryLong
+#define TIFFReadDirEntryLong8 gdal_TIFFReadDirEntryLong8
+#define TIFFReadDirEntryLong8Array gdal_TIFFReadDirEntryLong8Array
+#define TIFFReadDirEntryLongArray gdal_TIFFReadDirEntryLongArray
+#define TIFFReadDirEntryOutputErr gdal_TIFFReadDirEntryOutputErr
+#define TIFFReadDirEntryPersampleShort gdal_TIFFReadDirEntryPersampleShort
+#define TIFFReadDirEntrySbyteArray gdal_TIFFReadDirEntrySbyteArray
+#define TIFFReadDirEntryShort gdal_TIFFReadDirEntryShort
+#define TIFFReadDirEntryShortArray gdal_TIFFReadDirEntryShortArray
+#define TIFFReadDirEntrySlong8Array gdal_TIFFReadDirEntrySlong8Array
+#define TIFFReadDirEntrySlongArray gdal_TIFFReadDirEntrySlongArray
+#define TIFFReadDirEntrySshortArray gdal_TIFFReadDirEntrySshortArray
+#define TIFFReadEncodedStrip gdal_TIFFReadEncodedStrip
+#define TIFFReadEncodedTile gdal_TIFFReadEncodedTile
+#define TIFFReadEXIFDirectory gdal_TIFFReadEXIFDirectory
+#define _tiffReadProc gdal__tiffReadProc
+#define TIFFReadRawStrip gdal_TIFFReadRawStrip
+#define TIFFReadRawStrip1 gdal_TIFFReadRawStrip1
+#define TIFFReadRawTile gdal_TIFFReadRawTile
+#define TIFFReadRawTile1 gdal_TIFFReadRawTile1
+#define TIFFReadRGBAImage gdal_TIFFReadRGBAImage
+#define TIFFReadRGBAImageOriented gdal_TIFFReadRGBAImageOriented
+#define TIFFReadRGBAStrip gdal_TIFFReadRGBAStrip
+#define TIFFReadRGBATile gdal_TIFFReadRGBATile
+#define TIFFReadScanline gdal_TIFFReadScanline
+#define TIFFReadTile gdal_TIFFReadTile
+#define TIFFReadUInt64 gdal_TIFFReadUInt64
+#define _TIFFrealloc gdal__TIFFrealloc
+#define TIFFRegisterCODEC gdal_TIFFRegisterCODEC
+#define TIFFReverseBits gdal_TIFFReverseBits
+#define TIFFRewriteDirectory gdal_TIFFRewriteDirectory
+#define _TIFFRewriteField gdal__TIFFRewriteField
+#define TIFFRGBAImageBegin gdal_TIFFRGBAImageBegin
+#define TIFFRGBAImageEnd gdal_TIFFRGBAImageEnd
+#define TIFFRGBAImageGet gdal_TIFFRGBAImageGet
+#define TIFFRGBAImageOK gdal_TIFFRGBAImageOK
+#define TIFFScanlineSize gdal_TIFFScanlineSize
+#define TIFFScanlineSize64 gdal_TIFFScanlineSize64
+#define TIFFSeek gdal_TIFFSeek
+#define _tiffSeekProc gdal__tiffSeekProc
+#define _TIFFsetByteArray gdal__TIFFsetByteArray
+#define TIFFSetClientdata gdal_TIFFSetClientdata
+#define TIFFSetClientInfo gdal_TIFFSetClientInfo
+#define TIFFSetCompressionScheme gdal_TIFFSetCompressionScheme
+#define _TIFFSetDefaultCompressionState gdal__TIFFSetDefaultCompressionState
+#define TIFFSetDirectory gdal_TIFFSetDirectory
+#define _TIFFsetDoubleArray gdal__TIFFsetDoubleArray
+#define TIFFSetErrorHandler gdal_TIFFSetErrorHandler
+#define TIFFSetErrorHandlerExt gdal_TIFFSetErrorHandlerExt
+#define TIFFSetField gdal_TIFFSetField
+#define TIFFSetFileName gdal_TIFFSetFileName
+#define TIFFSetFileno gdal_TIFFSetFileno
+#define _TIFFsetFloatArray gdal__TIFFsetFloatArray
+#define _TIFFSetGetType gdal__TIFFSetGetType
+#define _TIFFsetLong8Array gdal__TIFFsetLong8Array
+#define _TIFFsetLongArray gdal__TIFFsetLongArray
+#define TIFFSetMode gdal_TIFFSetMode
+#define _TIFFsetNString gdal__TIFFsetNString
+#define _TIFFsetShortArray gdal__TIFFsetShortArray
+#define _TIFFsetString gdal__TIFFsetString
+#define TIFFSetSubDirectory gdal_TIFFSetSubDirectory
+#define TIFFSetTagExtender gdal_TIFFSetTagExtender
+#define _TIFFSetupFields gdal__TIFFSetupFields
+#define TIFFSetupStrips gdal_TIFFSetupStrips
+#define TIFFSetWarningHandler gdal_TIFFSetWarningHandler
+#define TIFFSetWarningHandlerExt gdal_TIFFSetWarningHandlerExt
+#define TIFFSetWriteOffset gdal_TIFFSetWriteOffset
+#define _tiffSizeProc gdal__tiffSizeProc
+#define TIFFStartStrip gdal_TIFFStartStrip
+#define TIFFStartTile gdal_TIFFStartTile
+#define TIFFStripSize gdal_TIFFStripSize
+#define TIFFStripSize64 gdal_TIFFStripSize64
+#define TIFFTileRowSize gdal_TIFFTileRowSize
+#define TIFFTileRowSize64 gdal_TIFFTileRowSize64
+#define TIFFTileSize gdal_TIFFTileSize
+#define TIFFTileSize64 gdal_TIFFTileSize64
+#define _TIFFtrue gdal__TIFFtrue
+#define _TIFFUInt64ToDouble gdal__TIFFUInt64ToDouble
+#define _TIFFUInt64ToFloat gdal__TIFFUInt64ToFloat
+#define TIFFUnlinkDirectory gdal_TIFFUnlinkDirectory
+#define _tiffUnmapProc gdal__tiffUnmapProc
+#define TIFFUnRegisterCODEC gdal_TIFFUnRegisterCODEC
+#define TIFFUnsetField gdal_TIFFUnsetField
+#define TIFFVGetField gdal_TIFFVGetField
+#define _TIFFVGetField gdal__TIFFVGetField
+#define TIFFVGetFieldDefaulted gdal_TIFFVGetFieldDefaulted
+#define _TIFFvoid gdal__TIFFvoid
+#define TIFFVSetField gdal_TIFFVSetField
+#define _TIFFVSetField gdal__TIFFVSetField
+#define TIFFVStripSize gdal_TIFFVStripSize
+#define TIFFVStripSize64 gdal_TIFFVStripSize64
+#define TIFFVTileSize gdal_TIFFVTileSize
+#define TIFFVTileSize64 gdal_TIFFVTileSize64
+#define TIFFWarning gdal_TIFFWarning
+#define TIFFWarningExt gdal_TIFFWarningExt
+#define TIFFWriteBufferSetup gdal_TIFFWriteBufferSetup
+#define TIFFWriteCheck gdal_TIFFWriteCheck
+#define TIFFWriteCustomDirectory gdal_TIFFWriteCustomDirectory
+#define TIFFWriteDirectory gdal_TIFFWriteDirectory
+#define TIFFWriteDirectorySec gdal_TIFFWriteDirectorySec
+#define TIFFWriteDirectoryTagAscii gdal_TIFFWriteDirectoryTagAscii
+#define TIFFWriteDirectoryTagByteArray gdal_TIFFWriteDirectoryTagByteArray
+#define TIFFWriteDirectoryTagCheckedAscii gdal_TIFFWriteDirectoryTagCheckedAscii
+#define TIFFWriteDirectoryTagCheckedByteArray gdal_TIFFWriteDirectoryTagCheckedByteArray
+#define TIFFWriteDirectoryTagCheckedDoubleArray gdal_TIFFWriteDirectoryTagCheckedDoubleArray
+#define TIFFWriteDirectoryTagCheckedFloatArray gdal_TIFFWriteDirectoryTagCheckedFloatArray
+#define TIFFWriteDirectoryTagCheckedIfd8Array gdal_TIFFWriteDirectoryTagCheckedIfd8Array
+#define TIFFWriteDirectoryTagCheckedIfdArray gdal_TIFFWriteDirectoryTagCheckedIfdArray
+#define TIFFWriteDirectoryTagCheckedLong gdal_TIFFWriteDirectoryTagCheckedLong
+#define TIFFWriteDirectoryTagCheckedLong8Array gdal_TIFFWriteDirectoryTagCheckedLong8Array
+#define TIFFWriteDirectoryTagCheckedLongArray gdal_TIFFWriteDirectoryTagCheckedLongArray
+#define TIFFWriteDirectoryTagCheckedRational gdal_TIFFWriteDirectoryTagCheckedRational
+#define TIFFWriteDirectoryTagCheckedRationalArray gdal_TIFFWriteDirectoryTagCheckedRationalArray
+#define TIFFWriteDirectoryTagCheckedSbyteArray gdal_TIFFWriteDirectoryTagCheckedSbyteArray
+#define TIFFWriteDirectoryTagCheckedShort gdal_TIFFWriteDirectoryTagCheckedShort
+#define TIFFWriteDirectoryTagCheckedShortArray gdal_TIFFWriteDirectoryTagCheckedShortArray
+#define TIFFWriteDirectoryTagCheckedSlong8Array gdal_TIFFWriteDirectoryTagCheckedSlong8Array
+#define TIFFWriteDirectoryTagCheckedSlongArray gdal_TIFFWriteDirectoryTagCheckedSlongArray
+#define TIFFWriteDirectoryTagCheckedSrationalArray gdal_TIFFWriteDirectoryTagCheckedSrationalArray
+#define TIFFWriteDirectoryTagCheckedSshortArray gdal_TIFFWriteDirectoryTagCheckedSshortArray
+#define TIFFWriteDirectoryTagCheckedUndefinedArray gdal_TIFFWriteDirectoryTagCheckedUndefinedArray
+#define TIFFWriteDirectoryTagColormap gdal_TIFFWriteDirectoryTagColormap
+#define TIFFWriteDirectoryTagData gdal_TIFFWriteDirectoryTagData
+#define TIFFWriteDirectoryTagDoubleArray gdal_TIFFWriteDirectoryTagDoubleArray
+#define TIFFWriteDirectoryTagFloatArray gdal_TIFFWriteDirectoryTagFloatArray
+#define TIFFWriteDirectoryTagIfdArray gdal_TIFFWriteDirectoryTagIfdArray
+#define TIFFWriteDirectoryTagIfdIfd8Array gdal_TIFFWriteDirectoryTagIfdIfd8Array
+#define TIFFWriteDirectoryTagLong gdal_TIFFWriteDirectoryTagLong
+#define TIFFWriteDirectoryTagLong8Array gdal_TIFFWriteDirectoryTagLong8Array
+#define TIFFWriteDirectoryTagLongArray gdal_TIFFWriteDirectoryTagLongArray
+#define TIFFWriteDirectoryTagLongLong8Array gdal_TIFFWriteDirectoryTagLongLong8Array
+#define TIFFWriteDirectoryTagRational gdal_TIFFWriteDirectoryTagRational
+#define TIFFWriteDirectoryTagRationalArray gdal_TIFFWriteDirectoryTagRationalArray
+#define TIFFWriteDirectoryTagSampleformatArray gdal_TIFFWriteDirectoryTagSampleformatArray
+#define TIFFWriteDirectoryTagSbyteArray gdal_TIFFWriteDirectoryTagSbyteArray
+#define TIFFWriteDirectoryTagShort gdal_TIFFWriteDirectoryTagShort
+#define TIFFWriteDirectoryTagShortArray gdal_TIFFWriteDirectoryTagShortArray
+#define TIFFWriteDirectoryTagShortLong gdal_TIFFWriteDirectoryTagShortLong
+#define TIFFWriteDirectoryTagShortPerSample gdal_TIFFWriteDirectoryTagShortPerSample
+#define TIFFWriteDirectoryTagSlong8Array gdal_TIFFWriteDirectoryTagSlong8Array
+#define TIFFWriteDirectoryTagSlongArray gdal_TIFFWriteDirectoryTagSlongArray
+#define TIFFWriteDirectoryTagSrationalArray gdal_TIFFWriteDirectoryTagSrationalArray
+#define TIFFWriteDirectoryTagSshortArray gdal_TIFFWriteDirectoryTagSshortArray
+#define TIFFWriteDirectoryTagSubifd gdal_TIFFWriteDirectoryTagSubifd
+#define TIFFWriteDirectoryTagTransferfunction gdal_TIFFWriteDirectoryTagTransferfunction
+#define TIFFWriteDirectoryTagUndefinedArray gdal_TIFFWriteDirectoryTagUndefinedArray
+#define TIFFWriteEncodedStrip gdal_TIFFWriteEncodedStrip
+#define TIFFWriteEncodedTile gdal_TIFFWriteEncodedTile
+#define _tiffWriteProc gdal__tiffWriteProc
+#define TIFFWriteRawStrip gdal_TIFFWriteRawStrip
+#define TIFFWriteRawTile gdal_TIFFWriteRawTile
+#define TIFFWriteScanline gdal_TIFFWriteScanline
+#define TIFFWriteTile gdal_TIFFWriteTile
+#define TIFFXYZToRGB gdal_TIFFXYZToRGB
+#define TIFFYCbCrtoRGB gdal_TIFFYCbCrtoRGB
+#define TIFFYCbCrToRGBInit gdal_TIFFYCbCrToRGBInit
+#define unixErrorHandler gdal_unixErrorHandler
+#define unixWarningHandler gdal_unixWarningHandler
+#define uv_decode gdal_uv_decode
+#define uv_encode gdal_uv_encode
+#define XYZtoRGB24 gdal_XYZtoRGB24
+#define ZIPCleanup gdal_ZIPCleanup
+#define ZIPDecode gdal_ZIPDecode
+#define ZIPEncode gdal_ZIPEncode
+#define ZIPFixupTags gdal_ZIPFixupTags
+#define ZIPPostEncode gdal_ZIPPostEncode
+#define ZIPPreDecode gdal_ZIPPreDecode
+#define ZIPPreEncode gdal_ZIPPreEncode
+#define ZIPSetupDecode gdal_ZIPSetupDecode
+#define ZIPSetupEncode gdal_ZIPSetupEncode
+#define ZIPVGetField gdal_ZIPVGetField
+#define ZIPVSetField gdal_ZIPVSetField
+#define _msbmask gdal__msbmask
+#define zeroruns gdal_zeroruns
+#define oneruns gdal_oneruns
+#define horizcode gdal_horizcode
+#define passcode gdal_passcode
+#define vcodes gdal_vcodes
+#define photoTag gdal_photoTag
+#define display_sRGB gdal_display_sRGB
+#define TIFFBitRevTable gdal_TIFFBitRevTable
+#define TIFFNoBitRevTable gdal_TIFFNoBitRevTable
+#define twobitdeltas gdal_twobitdeltas
+#define threebitdeltas gdal_threebitdeltas
+#define TIFFVersion gdal_TIFFVersion
+#define TIFFFaxWhiteCodes gdal_TIFFFaxWhiteCodes
+#define TIFFFaxWhiteTable gdal_TIFFFaxWhiteTable
+#define TIFFFaxBlackCodes gdal_TIFFFaxBlackCodes
+#define TIFFFaxMainTable gdal_TIFFFaxMainTable
+#define TIFFFaxBlackTable gdal_TIFFFaxBlackTable
+#define tiffFieldArray gdal_tiffFieldArray
+#define tiffFields gdal_tiffFields
+#define exifFieldArray gdal_exifFieldArray
+#define exifFields gdal_exifFields
+#define faxFields gdal_faxFields
+#define fax3Fields gdal_fax3Fields
+#define fax4Fields gdal_fax4Fields
+#define uv_row gdal_uv_row
+#define LogLuvFields gdal_LogLuvFields
+#define lzmaFields gdal_lzmaFields
+#define ojpegFields gdal_ojpegFields
+#define pixarlogFields gdal_pixarlogFields
+#define predictFields gdal_predictFields
+#define photoNames gdal_photoNames
+#define orientNames gdal_orientNames
+#define zipFields gdal_zipFields
+#define _TIFFerrorHandler gdal__TIFFerrorHandler
+#define _TIFFBuiltinCODECS gdal__TIFFBuiltinCODECS
+#define _TIFFwarningHandler gdal__TIFFwarningHandler
+#define registeredCODECS gdal_registeredCODECS
+#define _TIFFextender gdal__TIFFextender
+#define Fltsize gdal_Fltsize
+#define LogK1 gdal_LogK1
+#define LogK2 gdal_LogK2
+#define _TIFFwarningHandlerExt gdal__TIFFwarningHandlerExt
+#define _TIFFerrorHandlerExt gdal__TIFFerrorHandlerExt
+#define TIFFInitDumpMode gdal_TIFFInitDumpMode
+#define TIFFReInitJPEG_12 gdal_TIFFReInitJPEG_12
+#ifdef LZW_SUPPORT
+#define TIFFInitLZW gdal_TIFFInitLZW
+#endif
+#ifdef PACKBITS_SUPPORT
+#define TIFFInitPackBits gdal_TIFFInitPackBits
+#endif
+#ifdef THUNDER_SUPPORT
+#define TIFFInitThunderScan gdal_TIFFInitThunderScan
+#endif
+#ifdef NEXT_SUPPORT
+#define TIFFInitNeXT gdal_TIFFInitNeXT
+#endif
+#ifdef JPEG_SUPPORT
+#define TIFFInitJPEG gdal_TIFFInitJPEG
+#define TIFFInitJPEG_12 gdal_TIFFInitJPEG_12
+#endif
+#ifdef OJPEG_SUPPORT
+#define TIFFInitOJPEG gdal_TIFFInitOJPEG
+#endif
+#ifdef CCITT_SUPPORT
+#define TIFFInitCCITTRLE gdal_TIFFInitCCITTRLE
+#define TIFFInitCCITTRLEW gdal_TIFFInitCCITTRLEW
+#define TIFFInitCCITTFax3 gdal_TIFFInitCCITTFax3
+#define TIFFInitCCITTFax4 gdal_TIFFInitCCITTFax4
+#endif
+#ifdef JBIG_SUPPORT
+#define TIFFInitJBIG gdal_TIFFInitJBIG
+#endif
+#ifdef ZIP_SUPPORT
+#define TIFFInitZIP gdal_TIFFInitZIP
+#endif
+#ifdef PIXARLOG_SUPPORT
+#define TIFFInitPixarLog gdal_TIFFInitPixarLog
+#endif
+#ifdef LOGLUV_SUPPORT
+#define TIFFInitSGILog gdal_TIFFInitSGILog
+#endif
+#ifdef LZMA_SUPPORT
+#define TIFFInitLZMA gdal_TIFFInitLZMA
+#endif
diff --git a/frmts/gtiff/libtiff/makefile.vc b/frmts/gtiff/libtiff/makefile.vc
index ff39e06..2337536 100644
--- a/frmts/gtiff/libtiff/makefile.vc
+++ b/frmts/gtiff/libtiff/makefile.vc
@@ -42,7 +42,8 @@ OBJ	= \
 GDAL_ROOT	=	..\..\..
 
 EXTRAFLAGS = 	-I..\..\zlib -DZIP_SUPPORT -DPIXARLOG_SUPPORT \
-		$(JPEG_FLAGS) $(JPEG12_FLAGS) $(LZMA_FLAGS)
+		$(JPEG_FLAGS) $(JPEG12_FLAGS) $(LZMA_FLAGS) \
+		$(SOFTWARNFLAGS)
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
diff --git a/frmts/gtiff/libtiff/tif_config.h b/frmts/gtiff/libtiff/tif_config.h
index a9976b6..3947399 100644
--- a/frmts/gtiff/libtiff/tif_config.h
+++ b/frmts/gtiff/libtiff/tif_config.h
@@ -35,6 +35,7 @@
 #define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
 
 #define CHUNKY_STRIP_READ_SUPPORT 1
+#define DEFER_STRILE_LOAD 1
 
 /* Default size of the strip in bytes (when strip chopping enabled) */
 #define STRIP_SIZE_DEFAULT 8192
@@ -84,3 +85,7 @@
 #ifdef JPEG_DUAL_MODE_8_12
 #  define LIBJPEG_12_PATH "../../jpeg/libjpeg12/jpeglib.h"
 #endif
+
+#ifdef RENAME_INTERNAL_LIBTIFF_SYMBOLS
+#include "gdal_libtiff_symbol_rename.h"
+#endif
diff --git a/frmts/gtiff/libtiff/tif_dir.c b/frmts/gtiff/libtiff/tif_dir.c
index a4bc48b..90d258f 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.105 2010-07-02 09:48:25 dron Exp $ */
+/* $Id: tif_dir.c,v 1.107 2011-02-18 20:53:04 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -70,6 +70,19 @@ void _TIFFsetFloatArray(float** fpp, float* fp, uint32 n)
 void _TIFFsetDoubleArray(double** dpp, double* dp, uint32 n)
     { setByteArray((void**) dpp, (void*) dp, n, sizeof (double)); }
 
+static void
+setDoubleArrayOneValue(double** vpp, double value, size_t nmemb)
+{
+	if (*vpp)
+		_TIFFfree(*vpp);
+	*vpp = _TIFFmalloc(nmemb*sizeof(double));
+	if (*vpp)
+	{
+		while (nmemb--)
+			((double*)*vpp)[nmemb] = value;
+	}
+}
+
 /*
  * Install extra samples information.
  */
@@ -242,10 +255,16 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 		td->td_maxsamplevalue = (uint16) va_arg(ap, uint16_vap);
 		break;
 	case TIFFTAG_SMINSAMPLEVALUE:
-		td->td_sminsamplevalue = (double) va_arg(ap, double);
+		if (tif->tif_flags & TIFF_PERSAMPLE)
+			_TIFFsetDoubleArray(&td->td_sminsamplevalue, va_arg(ap, double*), td->td_samplesperpixel);
+		else
+			setDoubleArrayOneValue(&td->td_sminsamplevalue, va_arg(ap, double), td->td_samplesperpixel);
 		break;
 	case TIFFTAG_SMAXSAMPLEVALUE:
-		td->td_smaxsamplevalue = (double) va_arg(ap, double);
+		if (tif->tif_flags & TIFF_PERSAMPLE)
+			_TIFFsetDoubleArray(&td->td_smaxsamplevalue, va_arg(ap, double*), td->td_samplesperpixel);
+		else
+			setDoubleArrayOneValue(&td->td_smaxsamplevalue, va_arg(ap, double), td->td_samplesperpixel);
 		break;
 	case TIFFTAG_XRESOLUTION:
 		td->td_xresolution = (float) va_arg(ap, double);
@@ -394,6 +413,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 			td->td_inknameslen = v;
 		}
 		break;
+	case TIFFTAG_PERSAMPLE:
+		v = (uint16) va_arg(ap, uint16_vap);
+		if( v == PERSAMPLE_MULTI )
+			tif->tif_flags |= TIFF_PERSAMPLE;
+		else
+			tif->tif_flags &= ~TIFF_PERSAMPLE;
+		break;
 	default: {
 		TIFFTagValue *tv;
 		int tv_size, iCustom;
@@ -803,10 +829,32 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
 			*va_arg(ap, uint16*) = td->td_maxsamplevalue;
 			break;
 		case TIFFTAG_SMINSAMPLEVALUE:
-			*va_arg(ap, double*) = td->td_sminsamplevalue;
+			if (tif->tif_flags & TIFF_PERSAMPLE)
+				*va_arg(ap, double**) = td->td_sminsamplevalue;
+			else
+			{
+				/* libtiff historially treats this as a single value. */
+				uint16 i;
+				double v = td->td_sminsamplevalue[0];
+				for (i=1; i < td->td_samplesperpixel; ++i)
+					if( td->td_sminsamplevalue[i] < v )
+						v = td->td_sminsamplevalue[i];
+				*va_arg(ap, double*) = v;
+			}
 			break;
 		case TIFFTAG_SMAXSAMPLEVALUE:
-			*va_arg(ap, double*) = td->td_smaxsamplevalue;
+			if (tif->tif_flags & TIFF_PERSAMPLE)
+				*va_arg(ap, double**) = td->td_smaxsamplevalue;
+			else
+			{
+				/* libtiff historially treats this as a single value. */
+				uint16 i;
+				double v = td->td_smaxsamplevalue[0];
+				for (i=1; i < td->td_samplesperpixel; ++i)
+					if( td->td_smaxsamplevalue[i] > v )
+						v = td->td_smaxsamplevalue[i];
+				*va_arg(ap, double*) = v;
+			}
 			break;
 		case TIFFTAG_XRESOLUTION:
 			*va_arg(ap, float*) = td->td_xresolution;
@@ -841,10 +889,12 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
 			break;
 		case TIFFTAG_STRIPOFFSETS:
 		case TIFFTAG_TILEOFFSETS:
+			_TIFFFillStriles( tif );
 			*va_arg(ap, uint64**) = td->td_stripoffset;
 			break;
 		case TIFFTAG_STRIPBYTECOUNTS:
 		case TIFFTAG_TILEBYTECOUNTS:
+			_TIFFFillStriles( tif );
 			*va_arg(ap, uint64**) = td->td_stripbytecount;
 			break;
 		case TIFFTAG_MATTEING:
@@ -1090,6 +1140,8 @@ TIFFFreeDirectory(TIFF* tif)
 	int            i;
 
 	_TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS);
+	CleanupField(td_sminsamplevalue);
+	CleanupField(td_smaxsamplevalue);
 	CleanupField(td_colormap[0]);
 	CleanupField(td_colormap[1]);
 	CleanupField(td_colormap[2]);
@@ -1113,6 +1165,11 @@ TIFFFreeDirectory(TIFF* tif)
 
 	td->td_customValueCount = 0;
 	CleanupField(td_customValues);
+
+#if defined(DEFER_STRILE_LOAD)
+        _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
+        _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
+#endif        
 }
 #undef CleanupField
 
diff --git a/frmts/gtiff/libtiff/tif_dir.h b/frmts/gtiff/libtiff/tif_dir.h
index a6e66c8..6af5f3d 100644
--- a/frmts/gtiff/libtiff/tif_dir.h
+++ b/frmts/gtiff/libtiff/tif_dir.h
@@ -1,4 +1,4 @@
-/* $Id: tif_dir.h,v 1.52 2010-03-10 18:56:48 bfriesen Exp $ */
+/* $Id: tif_dir.h,v 1.54 2011-02-18 20:53:05 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -37,6 +37,28 @@ typedef struct {
 } TIFFTagValue;
 
 /*
+ * TIFF Image File Directories are comprised of a table of field
+ * descriptors of the form shown below.  The table is sorted in
+ * ascending order by tag.  The values associated with each entry are
+ * disjoint and may appear anywhere in the file (so long as they are
+ * placed on a word boundary).
+ *
+ * If the value is 4 bytes or less, in ClassicTIFF, or 8 bytes or less in
+ * BigTIFF, then it is placed in the offset field to save space. If so,
+ * it is left-justified in the offset field.
+ */
+typedef struct {
+	uint16 tdir_tag;        /* see below */
+	uint16 tdir_type;       /* data type; see below */
+	uint64 tdir_count;      /* number of items; length in spec */
+	union {
+		uint16 toff_short;
+		uint32 toff_long;
+		uint64 toff_long8;
+	} tdir_offset;		/* either offset or the data itself if fits */
+} TIFFDirEntry;
+
+/*
  * Internal format of a TIFF directory entry.
  */
 typedef struct {
@@ -57,7 +79,8 @@ typedef struct {
 	uint16  td_samplesperpixel;
 	uint32  td_rowsperstrip;
 	uint16  td_minsamplevalue, td_maxsamplevalue;
-	double  td_sminsamplevalue, td_smaxsamplevalue;
+	double* td_sminsamplevalue;
+	double* td_smaxsamplevalue;
 	float   td_xresolution, td_yresolution;
 	uint16  td_resolutionunit;
 	uint16  td_planarconfig;
@@ -75,6 +98,10 @@ typedef struct {
 	uint64* td_stripoffset;
 	uint64* td_stripbytecount;
 	int     td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
+#if defined(DEFER_STRILE_LOAD)
+        TIFFDirEntry td_stripoffset_entry;    /* for deferred loading */
+        TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */
+#endif
 	uint16  td_nsubifd;
 	uint64* td_subifd;
 	/* YCbCr parameters */
@@ -231,6 +258,8 @@ extern const TIFFFieldArray* _TIFFGetExifFields(void);
 extern void _TIFFSetupFields(TIFF* tif, const TIFFFieldArray* infoarray);
 extern void _TIFFPrintFieldInfo(TIFF*, FILE*);
 
+extern int _TIFFFillStriles(TIFF*);        
+
 typedef enum {
 	tfiatImage,
 	tfiatExif,
diff --git a/frmts/gtiff/libtiff/tif_dirinfo.c b/frmts/gtiff/libtiff/tif_dirinfo.c
index 2b1f82b..06b5a5a 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.111 2010-07-06 14:16:05 dron Exp $ */
+/* $Id: tif_dirinfo.c,v 1.114 2011-05-17 00:21:17 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -191,6 +191,8 @@ tiffFields[] = {
 	{ TIFFTAG_CURRENTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CurrentICCProfile", NULL },
 	{ TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CurrentPreProfileMatrix", NULL },
 	/* end DNG tags */
+	/* begin pseudo tags */
+	{ TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL},
 };
 
 static TIFFField
@@ -894,75 +896,6 @@ TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], uint32 n)
 	return 0;
 }
 
-const TIFFFieldInfo*
-TIFFFindFieldInfoByName(TIFF* tif, const char *field_name, TIFFDataType dt)
-{
-#if 0
-	TIFFFieldInfo key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL};
-	TIFFFieldInfo* pkey = &key;
-	const TIFFFieldInfo **ret;
-	if (tif->tif_foundfield
-	    && streq(tif->tif_foundfield->field_name, field_name)
-	    && (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
-		return (tif->tif_foundfield);
-
-	/* If we are invoked with no field information, then just return. */
-	if ( !tif->tif_fields ) {
-		return NULL;
-	}
-
-	/* NB: use sorted search (e.g. binary search) */
-
-	key.field_name = (char *)field_name;
-	key.field_type = dt;
-
-	ret = (const TIFFFieldInfo **) 
-            td_lfind(&pkey, tif->tif_fields, &tif->tif_nfields,
-                     sizeof(TIFFFieldInfo *), tagNameCompare );
-	return tif->tif_foundfield = (ret ? *ret : NULL);
-#else
-        (void) tif;
-        (void) field_name;
-        (void) dt;
-#endif
-	return NULL;
-}
-
-const TIFFFieldInfo*
-TIFFFindFieldInfo(TIFF* tif, uint32 tag, TIFFDataType dt)
-{
-#if 0
-	TIFFFieldInfo key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL};
-	TIFFFieldInfo* pkey = &key;
-	const TIFFFieldInfo **ret;
-	if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag &&
-	    (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
-		return tif->tif_foundfield;
-
-	/* If we are invoked with no field information, then just return. */
-	if ( !tif->tif_fields ) {
-		return NULL;
-	}
-
-	/* NB: use sorted search (e.g. binary search) */
-
-	key.field_tag = tag;
-	key.field_type = dt;
-
-	ret = (const TIFFFieldInfo **) bsearch(&pkey,
-					       tif->tif_fields,
-					       tif->tif_nfields,
-					       sizeof(TIFFFieldInfo *),
-					       tagCompare);
-	return tif->tif_foundfield = (ret ? *ret : NULL);
-#else
-        (void) tif;
-        (void) tag;
-        (void) dt;
-#endif
-	return NULL;
-}
-
 /* vim: set ts=8 sts=8 sw=8 noet: */
 
 /*
diff --git a/frmts/gtiff/libtiff/tif_dirread.c b/frmts/gtiff/libtiff/tif_dirread.c
index fc29da8..5db5147 100644
--- a/frmts/gtiff/libtiff/tif_dirread.c
+++ b/frmts/gtiff/libtiff/tif_dirread.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirread.c,v 1.165 2010-12-15 01:05:02 faxguy Exp $ */
+/* $Id: tif_dirread.c,v 1.172 2011-12-09 03:29:10 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -85,7 +85,9 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryDoubleArray(TIFF* tif, TIFFDirEn
 static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value);
 
 static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value);
+#if 0
 static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble(TIFF* tif, TIFFDirEntry* direntry, double* value);
+#endif
 
 static void TIFFReadDirEntryCheckedByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value);
 static void TIFFReadDirEntryCheckedSbyte(TIFF* tif, TIFFDirEntry* direntry, int8* value);
@@ -2758,6 +2760,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleShort(TIFF* tif, TIFFDi
 	return(err);
 }
 
+#if 0
 static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble(TIFF* tif, TIFFDirEntry* direntry, double* value)
 {
 	enum TIFFReadDirEntryErr err;
@@ -2785,6 +2788,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble(TIFF* tif, TIFFD
 	_TIFFfree(m);
 	return(err);
 }
+#endif
 
 static void TIFFReadDirEntryCheckedByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value)
 {
@@ -3588,6 +3592,8 @@ TIFFReadDirectory(TIFF* tif)
 	if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG)&&
 	    (tif->tif_dir.td_planarconfig==PLANARCONFIG_SEPARATE))
 	{
+        if (!_TIFFFillStriles(tif))
+            goto bad;
 		dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_STRIPOFFSETS);
 		if ((dp!=0)&&(dp->tdir_count==1))
 		{
@@ -3683,7 +3689,8 @@ TIFFReadDirectory(TIFF* tif)
 						err=TIFFReadDirEntryPersampleShort(tif,dp,&value);
 					if (err!=TIFFReadDirEntryErrOk)
 					{
-						TIFFReadDirEntryOutputErr(tif,err,module,TIFFFieldWithTag(tif,dp->tdir_tag)->field_name,0);
+                        fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+						TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
 						goto bad;
 					}
 					if (!TIFFSetField(tif,dp->tdir_tag,value))
@@ -3693,27 +3700,49 @@ TIFFReadDirectory(TIFF* tif)
 			case TIFFTAG_SMINSAMPLEVALUE:
 			case TIFFTAG_SMAXSAMPLEVALUE:
 				{
-					double value;
+
+					double *data;
 					enum TIFFReadDirEntryErr err;
-					err=TIFFReadDirEntryPersampleDouble(tif,dp,&value);
+					uint32 saved_flags;
+					int m;
+					if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel)
+						err = TIFFReadDirEntryErrCount;
+					else
+						err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
 					if (err!=TIFFReadDirEntryErrOk)
 					{
-						TIFFReadDirEntryOutputErr(tif,err,module,TIFFFieldWithTag(tif,dp->tdir_tag)->field_name,0);
+                        fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+						TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
 						goto bad;
 					}
-					if (!TIFFSetField(tif,dp->tdir_tag,value))
+					saved_flags = tif->tif_flags;
+					tif->tif_flags |= TIFF_PERSAMPLE;
+					m = TIFFSetField(tif,dp->tdir_tag,data);
+					tif->tif_flags = saved_flags;
+					_TIFFfree(data);
+					if (!m)
 						goto bad;
 				}
 				break;
 			case TIFFTAG_STRIPOFFSETS:
 			case TIFFTAG_TILEOFFSETS:
+#if defined(DEFER_STRILE_LOAD)
+                                _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry),
+                                             dp, sizeof(TIFFDirEntry) );
+#else                          
 				if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset))  
 					goto bad;
+#endif                                
 				break;
 			case TIFFTAG_STRIPBYTECOUNTS:
 			case TIFFTAG_TILEBYTECOUNTS:
+#if defined(DEFER_STRILE_LOAD)
+                                _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry),
+                                             dp, sizeof(TIFFDirEntry) );
+#else                          
 				if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount))  
 					goto bad;
+#endif                                
 				break;
 			case TIFFTAG_COLORMAP:
 			case TIFFTAG_TRANSFERFUNCTION:
@@ -3739,7 +3768,10 @@ TIFFReadDirectory(TIFF* tif)
 					else
 						err=TIFFReadDirEntryShortArray(tif,dp,&value);
 					if (err!=TIFFReadDirEntryErrOk)
-						TIFFReadDirEntryOutputErr(tif,err,module,TIFFFieldWithTag(tif,dp->tdir_tag)->field_name,1);
+                    {
+                        fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+						TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1);
+                    }
 					else
 					{
 						TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample);
@@ -3905,6 +3937,7 @@ TIFFReadDirectory(TIFF* tif)
 		       tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) )
 
 		} else if (tif->tif_dir.td_nstrips == 1
+                           && _TIFFFillStriles(tif)
 			   && tif->tif_dir.td_stripoffset[0] != 0
 			   && BYTECOUNTLOOKSBAD) {
 			/*
@@ -3918,6 +3951,8 @@ TIFFReadDirectory(TIFF* tif)
 			    TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
 			if(EstimateStripByteCounts(tif, dir, dircount) < 0)
 			    goto bad;
+
+#if !defined(DEFER_STRILE_LOAD)
 		} else if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG
 			   && tif->tif_dir.td_nstrips > 2
 			   && tif->tif_dir.td_compression == COMPRESSION_NONE
@@ -3929,12 +3964,17 @@ TIFFReadDirectory(TIFF* tif)
 			 * absolutely wrong values (it can be equal to
 			 * StripOffset array, for example). Catch this case
 			 * here.
+                         *
+                         * We avoid this check if deferring strile loading
+                         * as it would always force us to load the strip/tile
+                         * information.
 			 */
 			TIFFWarningExt(tif->tif_clientdata, module,
 			    "Wrong \"%s\" field, ignoring and calculating from imagelength",
 			    TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
 			if (EstimateStripByteCounts(tif, dir, dircount) < 0)
 			    goto bad;
+#endif /* !defined(DEFER_STRILE_LOAD) */                        
 		}
 	}
 	if (dir)
@@ -3954,6 +3994,7 @@ TIFFReadDirectory(TIFF* tif)
 	 * bytecounts array. See also comments for TIFFAppendToStrip()
 	 * function in tif_write.c.
 	 */
+#if !defined(DEFER_STRILE_LOAD)        
 	if (tif->tif_dir.td_nstrips > 1) {
 		uint32 strip;
 
@@ -3966,6 +4007,8 @@ TIFFReadDirectory(TIFF* tif)
 			}
 		}
 	}
+#endif /* !defined(DEFER_STRILE_LOAD) */
+        
 	/*
 	 * An opportunity for compression mode dependent tag fixup
 	 */
@@ -3984,7 +4027,11 @@ TIFFReadDirectory(TIFF* tif)
 	    (tif->tif_dir.td_nstrips==1)&&
 	    (tif->tif_dir.td_compression==COMPRESSION_NONE)&&  
 	    ((tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED))==TIFF_STRIPCHOP))
+    {
+        if ( !_TIFFFillStriles(tif) || !tif->tif_dir.td_stripbytecount )
+            return 0;
 		ChopUpSingleUncompressedStrip(tif);
+    }
 
         /*
          * Clear the dirty directory flag. 
@@ -4223,6 +4270,8 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
 	TIFFDirectory *td = &tif->tif_dir;
 	uint32 strip;
 
+    _TIFFFillStriles( tif );
+
 	if (td->td_stripbytecount)
 		_TIFFfree(td->td_stripbytecount);
 	td->td_stripbytecount = (uint64*)
@@ -4356,15 +4405,17 @@ static int
 CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count)
 {
 	if ((uint64)count > dir->tdir_count) {
+        const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag);
 		TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
 	"incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag ignored",
-		    TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+		    fip ? fip->field_name : "unknown tagname",
 		    dir->tdir_count, count);
 		return (0);
 	} else if ((uint64)count < dir->tdir_count) {
+        const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag);
 		TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
 	"incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag trimmed",
-		    TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+		    fip ? fip->field_name : "unknown tagname",
 		    dir->tdir_count, count);
 		dir->tdir_count = count;
 		return (1);
@@ -4536,6 +4587,12 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir,
 			dircount16 = (uint16)dircount64;
 			dirsize = 20;
 		}
+		if (dircount16 == 0 )
+		{
+			TIFFErrorExt(tif->tif_clientdata, module,
+			             "Sanity check on directory count failed, zero tag directories not supported");
+			return 0;
+		}
 		origdir = _TIFFCheckMalloc(tif, dircount16,
 						dirsize,
 						"to read TIFF directory");
@@ -4633,7 +4690,7 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
 	static const char module[] = "TIFFFetchNormalTag";
 	enum TIFFReadDirEntryErr err;
 	uint32 fii;
-	const TIFFField* fip;
+	const TIFFField* fip = NULL;
 	TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii);
         if( fii == FAILED_FII )
         {
@@ -5282,7 +5339,7 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
 	}
 	if (err!=TIFFReadDirEntryErrOk)
 	{
-		TIFFReadDirEntryOutputErr(tif,err,module,fip->field_name,recover);
+		TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",recover);
 		return(0);
 	}
 	return(1);
@@ -5301,15 +5358,18 @@ TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp)
 	err=TIFFReadDirEntryLong8Array(tif,dir,&data);
 	if (err!=TIFFReadDirEntryErrOk)
 	{
-		TIFFReadDirEntryOutputErr(tif,err,module,TIFFFieldWithTag(tif,dir->tdir_tag)->field_name,0);
+        const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag); 
+		TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
 		return(0);
 	}
 	if (dir->tdir_count!=(uint64)nstrips)
 	{
 		uint64* resizeddata;
 		resizeddata=(uint64*)_TIFFCheckMalloc(tif,nstrips,sizeof(uint64),"for strip array");
-		if (resizeddata==0)
+		if (resizeddata==0) {
+			_TIFFfree(data);
 			return(0);
+		}
 		if (dir->tdir_count<(uint64)nstrips)
 		{
 			_TIFFmemcpy(resizeddata,data,(uint32)dir->tdir_count*sizeof(uint64));
@@ -5479,6 +5539,54 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
 	td->td_stripbytecountsorted = 1;
 }
 
+int _TIFFFillStriles( TIFF *tif )
+{
+#if defined(DEFER_STRILE_LOAD)
+        register TIFFDirectory *td = &tif->tif_dir;
+        int return_value = 1;
+
+        if( td->td_stripoffset != NULL )
+                return 1;
+
+        if( td->td_stripoffset_entry.tdir_count == 0 )
+                return 0;
+
+        if (!TIFFFetchStripThing(tif,&(td->td_stripoffset_entry),
+                                 td->td_nstrips,&td->td_stripoffset))
+        {
+                return_value = 0;
+        }
+
+        if (!TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry),
+                                 td->td_nstrips,&td->td_stripbytecount))
+        {
+                return_value = 0;
+        }
+
+        _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
+        _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
+
+	if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) {
+		uint32 strip;
+
+		tif->tif_dir.td_stripbytecountsorted = 1;
+		for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) {
+			if (tif->tif_dir.td_stripoffset[strip - 1] >
+			    tif->tif_dir.td_stripoffset[strip]) {
+				tif->tif_dir.td_stripbytecountsorted = 0;
+				break;
+			}
+		}
+	}
+
+        return return_value;
+#else /* !defined(DEFER_STRILE_LOAD) */
+        (void) tif;
+        return 1;
+#endif 
+}
+
+
 /* vim: set ts=8 sts=8 sw=8 noet: */
 /*
  * Local Variables:
diff --git a/frmts/gtiff/libtiff/tif_dirwrite.c b/frmts/gtiff/libtiff/tif_dirwrite.c
index 22512e6..11738cf 100644
--- a/frmts/gtiff/libtiff/tif_dirwrite.c
+++ b/frmts/gtiff/libtiff/tif_dirwrite.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirwrite.c,v 1.74 2010-12-31 17:51:08 olivier Exp $ */
+/* $Id: tif_dirwrite.c,v 1.76 2011-02-18 20:53:04 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -41,7 +41,10 @@ extern void TIFFCvtNativeToIEEEDouble(TIFF* tif, uint32 n, double* dp);
 
 static int TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff);
 
+static int TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value);
+#if 0
 static int TIFFWriteDirectoryTagSampleformatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
+#endif
 
 static int TIFFWriteDirectoryTagAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value);
 static int TIFFWriteDirectoryTagUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value);
@@ -49,12 +52,16 @@ static int TIFFWriteDirectoryTagUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirE
 static int TIFFWriteDirectoryTagByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value);
 #endif
 static int TIFFWriteDirectoryTagByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value);
+#if 0
 static int TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value);
+#endif
 #ifdef notdef
 static int TIFFWriteDirectoryTagSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value);
 #endif
 static int TIFFWriteDirectoryTagSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value);
+#if 0
 static int TIFFWriteDirectoryTagSbytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value);
+#endif
 static int TIFFWriteDirectoryTagShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value);
 static int TIFFWriteDirectoryTagShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value);
 static int TIFFWriteDirectoryTagShortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value);
@@ -62,15 +69,21 @@ static int TIFFWriteDirectoryTagShortPerSample(TIFF* tif, uint32* ndir, TIFFDirE
 static int TIFFWriteDirectoryTagSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value);
 #endif
 static int TIFFWriteDirectoryTagSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value);
+#if 0
 static int TIFFWriteDirectoryTagSshortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value);
+#endif
 static int TIFFWriteDirectoryTagLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value);
 static int TIFFWriteDirectoryTagLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value);
+#if 0
 static int TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value);
+#endif
 #ifdef notdef
 static int TIFFWriteDirectoryTagSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value);
 #endif
 static int TIFFWriteDirectoryTagSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value);
+#if 0
 static int TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value);
+#endif
 #ifdef notdef
 static int TIFFWriteDirectoryTagLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value);
 #endif
@@ -86,12 +99,16 @@ static int TIFFWriteDirectoryTagSrationalArray(TIFF* tif, uint32* ndir, TIFFDirE
 static int TIFFWriteDirectoryTagFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value);
 #endif
 static int TIFFWriteDirectoryTagFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value);
+#if 0
 static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value);
+#endif
 #ifdef notdef
 static int TIFFWriteDirectoryTagDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
 #endif
 static int TIFFWriteDirectoryTagDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value);
+#if 0
 static int TIFFWriteDirectoryTagDoublePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
+#endif
 static int TIFFWriteDirectoryTagIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value);
 #ifdef notdef
 static int TIFFWriteDirectoryTagIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);
@@ -353,6 +370,9 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 	uint32 m;
 	if (tif->tif_mode == O_RDONLY)
 		return (1);
+
+        _TIFFFillStriles( tif );
+        
 	/*
 	 * Clear write state so that subsequent images with
 	 * different characteristics get the right buffers
@@ -554,12 +574,12 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 			}
 			if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE))
 			{
-				if (!TIFFWriteDirectoryTagSampleformatPerSample(tif,&ndir,dir,TIFFTAG_SMINSAMPLEVALUE,tif->tif_dir.td_sminsamplevalue))
+				if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMINSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_sminsamplevalue))
 					goto bad;
 			}
 			if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE))
 			{
-				if (!TIFFWriteDirectoryTagSampleformatPerSample(tif,&ndir,dir,TIFFTAG_SMAXSAMPLEVALUE,tif->tif_dir.td_smaxsamplevalue))
+				if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMAXSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_smaxsamplevalue))
 					goto bad;
 			}
 			if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH))
@@ -906,6 +926,83 @@ bad:
 }
 
 static int
+TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value)
+{
+	static const char module[] = "TIFFWriteDirectoryTagSampleformatArray";
+	void* conv;
+	uint32 i;
+	int ok;
+	conv = _TIFFmalloc(count*sizeof(double));
+	if (conv == NULL)
+	{
+		TIFFErrorExt(tif->tif_clientdata, module, "Out of memory");
+		return (0);
+	}
+
+	switch (tif->tif_dir.td_sampleformat)
+	{
+		case SAMPLEFORMAT_IEEEFP:
+			if (tif->tif_dir.td_bitspersample<=32)
+			{
+				for (i = 0; i < count; ++i)
+					((float*)conv)[i] = (float)value[i];
+				ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv);
+			}
+			else
+			{
+				ok = TIFFWriteDirectoryTagDoubleArray(tif,ndir,dir,tag,count,value);
+			}
+			break;
+		case SAMPLEFORMAT_INT:
+			if (tif->tif_dir.td_bitspersample<=8)
+			{
+				for (i = 0; i < count; ++i)
+					((int8*)conv)[i] = (int8)value[i];
+				ok = TIFFWriteDirectoryTagSbyteArray(tif,ndir,dir,tag,count,(int8*)conv);
+			}
+			else if (tif->tif_dir.td_bitspersample<=16)
+			{
+				for (i = 0; i < count; ++i)
+					((int16*)conv)[i] = (int16)value[i];
+				ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv);
+			}
+			else
+			{
+				for (i = 0; i < count; ++i)
+					((int32*)conv)[i] = (int32)value[i];
+				ok = TIFFWriteDirectoryTagSlongArray(tif,ndir,dir,tag,count,(int32*)conv);
+			}
+			break;
+		case SAMPLEFORMAT_UINT:
+			if (tif->tif_dir.td_bitspersample<=8)
+			{
+				for (i = 0; i < count; ++i)
+					((uint8*)conv)[i] = (uint8)value[i];
+				ok = TIFFWriteDirectoryTagByteArray(tif,ndir,dir,tag,count,(uint8*)conv);
+			}
+			else if (tif->tif_dir.td_bitspersample<=16)
+			{
+				for (i = 0; i < count; ++i)
+					((uint16*)conv)[i] = (uint16)value[i];
+				ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv);
+			}
+			else
+			{
+				for (i = 0; i < count; ++i)
+					((uint32*)conv)[i] = (uint32)value[i];
+				ok = TIFFWriteDirectoryTagLongArray(tif,ndir,dir,tag,count,(uint32*)conv);
+			}
+			break;
+		default:
+			ok = 0;
+	}
+
+	_TIFFfree(conv);
+	return (ok);
+}
+
+#if 0
+static int
 TIFFWriteDirectoryTagSampleformatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
 {
 	switch (tif->tif_dir.td_sampleformat)
@@ -933,6 +1030,7 @@ TIFFWriteDirectoryTagSampleformatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry
 			return(1);
 	}
 }
+#endif
 
 static int
 TIFFWriteDirectoryTagAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value)
@@ -980,6 +1078,7 @@ TIFFWriteDirectoryTagByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint1
 	return(TIFFWriteDirectoryTagCheckedByteArray(tif,ndir,dir,tag,count,value));
 }
 
+#if 0
 static int
 TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value)
 {
@@ -1005,6 +1104,7 @@ TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, u
 	_TIFFfree(m);
 	return(o);
 }
+#endif
 
 #ifdef notdef
 static int
@@ -1030,6 +1130,7 @@ TIFFWriteDirectoryTagSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint
 	return(TIFFWriteDirectoryTagCheckedSbyteArray(tif,ndir,dir,tag,count,value));
 }
 
+#if 0
 static int
 TIFFWriteDirectoryTagSbytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value)
 {
@@ -1055,6 +1156,7 @@ TIFFWriteDirectoryTagSbytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir,
 	_TIFFfree(m);
 	return(o);
 }
+#endif
 
 static int
 TIFFWriteDirectoryTagShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value)
@@ -1128,6 +1230,7 @@ TIFFWriteDirectoryTagSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uin
 	return(TIFFWriteDirectoryTagCheckedSshortArray(tif,ndir,dir,tag,count,value));
 }
 
+#if 0
 static int
 TIFFWriteDirectoryTagSshortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value)
 {
@@ -1153,6 +1256,7 @@ TIFFWriteDirectoryTagSshortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir,
 	_TIFFfree(m);
 	return(o);
 }
+#endif
 
 static int
 TIFFWriteDirectoryTagLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value)
@@ -1176,6 +1280,7 @@ TIFFWriteDirectoryTagLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint1
 	return(TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,value));
 }
 
+#if 0
 static int
 TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value)
 {
@@ -1201,6 +1306,7 @@ TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, u
 	_TIFFfree(m);
 	return(o);
 }
+#endif
 
 #ifdef notdef
 static int
@@ -1226,6 +1332,7 @@ TIFFWriteDirectoryTagSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint
 	return(TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,count,value));
 }
 
+#if 0
 static int
 TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value)
 {
@@ -1251,6 +1358,7 @@ TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir,
 	_TIFFfree(m);
 	return(o);
 }
+#endif
 
 #ifdef notdef
 static int
@@ -1355,6 +1463,7 @@ static int TIFFWriteDirectoryTagFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry
 	return(TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,count,value));
 }
 
+#if 0
 static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value)
 {
 	static const char module[] = "TIFFWriteDirectoryTagFloatPerSample";
@@ -1379,6 +1488,7 @@ static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirE
 	_TIFFfree(m);
 	return(o);
 }
+#endif
 
 #ifdef notdef
 static int TIFFWriteDirectoryTagDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
@@ -1402,6 +1512,7 @@ static int TIFFWriteDirectoryTagDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntr
 	return(TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,count,value));
 }
 
+#if 0
 static int TIFFWriteDirectoryTagDoublePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
 {
 	static const char module[] = "TIFFWriteDirectoryTagDoublePerSample";
@@ -1426,6 +1537,7 @@ static int TIFFWriteDirectoryTagDoublePerSample(TIFF* tif, uint32* ndir, TIFFDir
 	_TIFFfree(m);
 	return(o);
 }
+#endif
 
 static int
 TIFFWriteDirectoryTagIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value)
diff --git a/frmts/gtiff/libtiff/tif_dumpmode.c b/frmts/gtiff/libtiff/tif_dumpmode.c
index c668964..a94cf0b 100644
--- a/frmts/gtiff/libtiff/tif_dumpmode.c
+++ b/frmts/gtiff/libtiff/tif_dumpmode.c
@@ -1,4 +1,4 @@
-/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.13 2010-03-10 18:56:48 bfriesen Exp $ */
+/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.14 2011-04-02 20:54:09 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -80,7 +80,7 @@ DumpModeDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 	static const char module[] = "DumpModeDecode";
 	(void) s;
 	if (tif->tif_rawcc < cc) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 		TIFFErrorExt(tif->tif_clientdata, module,
 "Not enough data for scanline %lu, expected a request for at most %I64d bytes, got a request for %I64d bytes",
 		             (unsigned long) tif->tif_row,
diff --git a/frmts/gtiff/libtiff/tif_fax3.h b/frmts/gtiff/libtiff/tif_fax3.h
index 581c122..b0f46c9 100644
--- a/frmts/gtiff/libtiff/tif_fax3.h
+++ b/frmts/gtiff/libtiff/tif_fax3.h
@@ -1,4 +1,4 @@
-/* $Id: tif_fax3.h,v 1.7 2010-03-10 18:56:48 bfriesen Exp $ */
+/* $Id: tif_fax3.h,v 1.9 2011-03-10 20:23:07 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1990-1997 Sam Leffler
@@ -478,6 +478,12 @@ done1d:									\
 	    break;							\
 	case S_VL:							\
 	    CHECK_b1;							\
+	    if (b1 <= (int) (a0 + TabEnt->Param)) {			\
+		if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) {	\
+		    unexpected("VL", a0);				\
+		    goto eol2d;						\
+		}							\
+	    }								\
 	    SETVALUE(b1 - a0 - TabEnt->Param);				\
 	    b1 -= *--pb;						\
 	    break;							\
diff --git a/frmts/gtiff/libtiff/tif_getimage.c b/frmts/gtiff/libtiff/tif_getimage.c
index 42c75e0..6a09b4d 100644
--- a/frmts/gtiff/libtiff/tif_getimage.c
+++ b/frmts/gtiff/libtiff/tif_getimage.c
@@ -1,4 +1,4 @@
-/* $Id: tif_getimage.c,v 1.77 2010-07-02 13:39:10 dron Exp $ */
+/* $Id: tif_getimage.c,v 1.78 2011-02-23 21:46:09 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -215,6 +215,7 @@ TIFFRGBAImageEnd(TIFFRGBAImage* img)
 		_TIFFfree( img->redcmap );
 		_TIFFfree( img->greencmap );
 		_TIFFfree( img->bluecmap );
+                img->redcmap = img->greencmap = img->bluecmap = NULL;
 	}
 }
 
@@ -261,7 +262,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 		default:
 			sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
 			    img->bitspersample);
-			return (0);
+			goto fail_return;
 	}
 	img->alpha = 0;
 	TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
@@ -310,7 +311,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 				break;
 			default:
 				sprintf(emsg, "Missing needed %s tag", photoTag);
-				return (0);
+                                goto fail_return;
 		}
 	}
 	switch (img->photometric) {
@@ -318,7 +319,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
 			    &red_orig, &green_orig, &blue_orig)) {
 				sprintf(emsg, "Missing required \"Colormap\" tag");
-				return (0);
+                                goto fail_return;
 			}
 
 			/* copy the colormaps so we can modify them */
@@ -328,7 +329,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
 			if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
 				sprintf(emsg, "Out of memory for colormap copy");
-				return (0);
+                                goto fail_return;
 			}
 
 			_TIFFmemcpy( img->redcmap, red_orig, n_color * 2 );
@@ -347,7 +348,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 				    photoTag, img->photometric,
 				    "Samples/pixel", img->samplesperpixel,
 				    img->bitspersample);
-				return (0);
+                                goto fail_return;
 			}
 			break;
 		case PHOTOMETRIC_YCBCR:
@@ -380,7 +381,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			if (colorchannels < 3) {
 				sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
 				    "Color channels", colorchannels);
-				return (0);
+                                goto fail_return;
 			}
 			break;
 		case PHOTOMETRIC_SEPARATED:
@@ -390,12 +391,12 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 				if (inkset != INKSET_CMYK) {
 					sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
 					    "InkSet", inkset);
-					return (0);
+                                        goto fail_return;
 				}
 				if (img->samplesperpixel < 4) {
 					sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
 					    "Samples/pixel", img->samplesperpixel);
-					return (0);
+                                        goto fail_return;
 				}
 			}
 			break;
@@ -403,7 +404,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			if (compress != COMPRESSION_SGILOG) {
 				sprintf(emsg, "Sorry, LogL data must have %s=%d",
 				    "Compression", COMPRESSION_SGILOG);
-				return (0);
+                                goto fail_return;
 			}
 			TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
 			img->photometric = PHOTOMETRIC_MINISBLACK;	/* little white lie */
@@ -413,7 +414,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) {
 				sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
 				    "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
-				return (0);
+                                goto fail_return;
 			}
 			if (planarconfig != PLANARCONFIG_CONTIG) {
 				sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
@@ -429,7 +430,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 		default:
 			sprintf(emsg, "Sorry, can not handle image with %s=%d",
 			    photoTag, img->photometric);
-			return (0);
+                        goto fail_return;
 	}
 	img->Map = NULL;
 	img->BWmap = NULL;
@@ -446,15 +447,22 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 	if (img->isContig) {
 		if (!PickContigCase(img)) {
 			sprintf(emsg, "Sorry, can not handle image");
-			return 0;
+			goto fail_return;
 		}
 	} else {
 		if (!PickSeparateCase(img)) {
 			sprintf(emsg, "Sorry, can not handle image");
-			return 0;
+			goto fail_return;
 		}
 	}
 	return 1;
+
+  fail_return:
+        _TIFFfree( img->redcmap );
+        _TIFFfree( img->greencmap );
+        _TIFFfree( img->bluecmap );
+        img->redcmap = img->greencmap = img->bluecmap = NULL;
+        return 0;
 }
 
 int
diff --git a/frmts/gtiff/libtiff/tif_jpeg.c b/frmts/gtiff/libtiff/tif_jpeg.c
index 6ae6c83..7b39bf5 100644
--- a/frmts/gtiff/libtiff/tif_jpeg.c
+++ b/frmts/gtiff/libtiff/tif_jpeg.c
@@ -1,4 +1,4 @@
-/* $Id: tif_jpeg.c,v 1.99 2011-01-06 05:51:13 fwarmerdam Exp $ */
+/* $Id: tif_jpeg.c,v 1.104 2011-05-31 17:00:03 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1994-1997 Sam Leffler
@@ -688,12 +688,13 @@ static void JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData* da
 static int
 JPEGFixupTags(TIFF* tif)
 {
-	#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
+#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
 	if ((tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR)&&
 	    (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&&
 	    (tif->tif_dir.td_samplesperpixel==3))
 		JPEGFixupTagsSubsampling(tif);
-	#endif
+#endif
+        
 	return(1);
 }
 
@@ -725,6 +726,8 @@ JPEGFixupTagsSubsampling(TIFF* tif)
 	static const char module[] = "JPEGFixupTagsSubsampling";
 	struct JPEGFixupTagsSubsamplingData m;
 
+        _TIFFFillStriles( tif );
+        
         if( tif->tif_dir.td_stripbytecount == NULL
             || tif->tif_dir.td_stripbytecount[0] == 0 )
         {
@@ -1212,6 +1215,9 @@ JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
         */
 	sp->src.next_input_byte = (const JOCTET*) tif->tif_rawcp;
 	sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc;
+
+        if( sp->bytesperline == 0 )
+                return 0;
         
 	nrows = cc / sp->bytesperline;
 	if (cc % sp->bytesperline)
@@ -1345,6 +1351,11 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 		unsigned short* tmpbuf = _TIFFmalloc(sizeof(unsigned short) *
 		    sp->cinfo.d.output_width *
 		    sp->cinfo.d.num_components);
+		if(tmpbuf==NULL) {
+                        TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw",
+				     "Out of memory");
+			return 0;
+                }
 #endif
 
 		do {
@@ -1812,6 +1823,7 @@ JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
         {
             line16_count = (sp->bytesperline * 2) / 3;
             line16 = (short *) _TIFFmalloc(sizeof(short) * line16_count);
+	    // FIXME: undiagnosed malloc failure
         }
             
 	while (nrows-- > 0) {
@@ -2178,8 +2190,6 @@ JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
 static int JPEGInitializeLibJPEG( TIFF * tif, int decompress )
 {
     JPEGState* sp = JState(tif);
-    uint64* byte_counts = NULL;
-    int     data_is_empty = TRUE;
 
     if(sp->cinfo_initialized)
     {
@@ -2194,24 +2204,6 @@ static int JPEGInitializeLibJPEG( TIFF * tif, int decompress )
     }
 
     /*
-     * Do we have tile data already?  Make sure we initialize the
-     * the state in decompressor mode if we have tile data, even if we
-     * are not in read-only file access mode. 
-     */
-    if( TIFFIsTiled( tif ) 
-        && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &byte_counts ) 
-        && byte_counts != NULL )
-    {
-        data_is_empty = byte_counts[0] == 0;
-    }
-    if( !TIFFIsTiled( tif ) 
-        && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &byte_counts) 
-        && byte_counts != NULL )
-    {
-        data_is_empty = byte_counts[0] == 0;
-    }
-
-    /*
      * Initialize libjpeg.
      */
     if ( decompress ) {
@@ -2320,6 +2312,7 @@ here hopefully is harmless.
 */
             sp->jpegtables_length = SIZE_OF_JPEGTABLES;
             sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length);
+	    // FIXME: NULL-deref after malloc failure
 	    _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES);
 #undef SIZE_OF_JPEGTABLES
         }
diff --git a/frmts/gtiff/libtiff/tif_luv.c b/frmts/gtiff/libtiff/tif_luv.c
index 5253c6b..eba6c08 100644
--- a/frmts/gtiff/libtiff/tif_luv.c
+++ b/frmts/gtiff/libtiff/tif_luv.c
@@ -1,4 +1,4 @@
-/* $Id: tif_luv.c,v 1.34 2010-03-10 18:56:48 bfriesen Exp $ */
+/* $Id: tif_luv.c,v 1.35 2011-04-02 20:54:09 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1997 Greg Ward Larson
@@ -224,7 +224,7 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 					tp[i++] |= (int16)*bp++ << shft;
 			}
 		if (i != npixels) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 			    "Not enough data at row %lu (short %I64d pixels)",
 				     (unsigned long) tif->tif_row,
@@ -282,7 +282,7 @@ LogLuvDecode24(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	tif->tif_rawcp = (uint8*) bp;
 	tif->tif_rawcc = cc;
 	if (i != npixels) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 		TIFFErrorExt(tif->tif_clientdata, module,
 			"Not enough data at row %lu (short %I64d pixels)",
 			     (unsigned long) tif->tif_row,
@@ -347,7 +347,7 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 					tp[i++] |= (uint32)*bp++ << shft;
 			}
 		if (i != npixels) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 			"Not enough data at row %lu (short %I64d pixels)",
 				     (unsigned long) tif->tif_row,
diff --git a/frmts/gtiff/libtiff/tif_lzma.c b/frmts/gtiff/libtiff/tif_lzma.c
index 3b4b5ab..c176a50 100644
--- a/frmts/gtiff/libtiff/tif_lzma.c
+++ b/frmts/gtiff/libtiff/tif_lzma.c
@@ -1,4 +1,4 @@
-/* $Id: tif_lzma.c,v 1.2 2010-12-23 13:07:38 dron Exp $ */
+/* $Id: tif_lzma.c,v 1.3 2011-02-22 21:55:13 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 2010, Andrey Kiselev <dron at ak4719.spb.edu>
@@ -171,6 +171,9 @@ LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	assert(sp != NULL);
 	assert(sp->state == LSTATE_INIT_DECODE);
 
+        sp->stream.next_in = tif->tif_rawcp;
+        sp->stream.avail_in = (size_t) tif->tif_rawcc;
+
 	sp->stream.next_out = op;
 	sp->stream.avail_out = (size_t) occ;
 	if ((tmsize_t)sp->stream.avail_out != occ) {
@@ -216,6 +219,10 @@ LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 		    (unsigned long) tif->tif_row, (unsigned long) sp->stream.avail_out);
 		return 0;
 	}
+
+        tif->tif_rawcp = sp->stream.next_in;
+        tif->tif_rawcc = sp->stream.avail_in;
+        
 	return 1;
 }
 
diff --git a/frmts/gtiff/libtiff/tif_lzw.c b/frmts/gtiff/libtiff/tif_lzw.c
index e89ce2c..fd9c7a0 100644
--- a/frmts/gtiff/libtiff/tif_lzw.c
+++ b/frmts/gtiff/libtiff/tif_lzw.c
@@ -1,4 +1,4 @@
-/* $Id: tif_lzw.c,v 1.44 2010-03-30 17:02:57 fwarmerdam Exp $ */
+/* $Id: tif_lzw.c,v 1.45 2011-04-02 20:54:09 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -549,7 +549,7 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 	sp->dec_maxcodep = maxcodep;
 
 	if (occ > 0) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 		TIFFErrorExt(tif->tif_clientdata, module,
 			"Not enough data at scanline %d (short %I64d bytes)",
 			     tif->tif_row, (unsigned __int64) occ);
@@ -753,7 +753,7 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 	sp->dec_maxcodep = maxcodep;
 
 	if (occ > 0) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 		TIFFErrorExt(tif->tif_clientdata, module,
 			"Not enough data at scanline %d (short %I64d bytes)",
 			     tif->tif_row, (unsigned __int64) occ);
diff --git a/frmts/gtiff/libtiff/tif_ojpeg.c b/frmts/gtiff/libtiff/tif_ojpeg.c
index d985a5a..0c9301d 100644
--- a/frmts/gtiff/libtiff/tif_ojpeg.c
+++ b/frmts/gtiff/libtiff/tif_ojpeg.c
@@ -1,4 +1,4 @@
-/* $Id: tif_ojpeg.c,v 1.51 2010-12-11 23:52:27 faxguy Exp $ */
+/* $Id: tif_ojpeg.c,v 1.54 2011-05-31 17:05:07 bfriesen Exp $ */
 
 /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0
    specification is now totally obsolete and deprecated for new applications and
@@ -120,6 +120,8 @@
    session.
 */
 
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
 
 #include "tiffiop.h"
 #ifdef OJPEG_SUPPORT
@@ -194,6 +196,16 @@ static const TIFFField ojpegFields[] = {
 #undef FAR
 #endif
 
+/*
+  Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
+  not defined.  Unfortunately, the MinGW and Borland compilers include
+  a typedef for INT32, which causes a conflict.  MSVC does not include
+  a conficting typedef given the headers which are included.
+*/
+#if defined(__BORLANDC__) || defined(__MINGW32__)
+# define XMD_H 1
+#endif
+
 /* Define "boolean" as unsigned char, not int, per Windows custom. */
 #if defined(__WIN32__) && !defined(__MINGW32__)
 # ifndef __RPCNDR_H__            /* don't conflict if rpcndr.h already read */
@@ -967,6 +979,8 @@ OJPEGSubsamplingCorrect(TIFF* tif)
 	OJPEGState* sp=(OJPEGState*)tif->tif_data;
 	uint8 mh;
 	uint8 mv;
+        _TIFFFillStriles( tif );
+        
 	assert(sp->subsamplingcorrect_done==0);
 	if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) &&
 	    (tif->tif_dir.td_photometric!=PHOTOMETRIC_ITULAB)))
@@ -1419,12 +1433,15 @@ OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif)
 			nb[sizeof(uint32)+1]=JPEG_MARKER_DQT;
 			nb[sizeof(uint32)+2]=0;
 			nb[sizeof(uint32)+3]=67;
-			if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0)
+			if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0) {
+				_TIFFfree(nb);
 				return(0);
+			}
 			o=nb[sizeof(uint32)+4]&15;
 			if (3<o)
 			{
 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
+				_TIFFfree(nb);
 				return(0);
 			}
 			if (sp->qtable[o]!=0)
diff --git a/frmts/gtiff/libtiff/tif_print.c b/frmts/gtiff/libtiff/tif_print.c
index 0afba65..9481eb6 100644
--- a/frmts/gtiff/libtiff/tif_print.c
+++ b/frmts/gtiff/libtiff/tif_print.c
@@ -1,4 +1,4 @@
-/* $Id: tif_print.c,v 1.50 2010-05-06 02:56:17 olivier Exp $ */
+/* $Id: tif_print.c,v 1.54 2011-04-02 20:54:09 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -93,7 +93,7 @@ _TIFFPrintField(FILE* fd, const TIFFField *fip,
 			|| fip->field_type == TIFF_FLOAT)
 			fprintf(fd, "%f", ((float *) raw_data)[j]);
 		else if(fip->field_type == TIFF_LONG8)
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			fprintf(fd, "%I64u",
 			    (unsigned __int64)((uint64 *) raw_data)[j]);
 #else
@@ -101,13 +101,13 @@ _TIFFPrintField(FILE* fd, const TIFFField *fip,
 			    (unsigned long long)((uint64 *) raw_data)[j]);
 #endif
 		else if(fip->field_type == TIFF_SLONG8)
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			fprintf(fd, "%I64d", (__int64)((int64 *) raw_data)[j]);
 #else
 			fprintf(fd, "%lld", (long long)((int64 *) raw_data)[j]);
 #endif
 		else if(fip->field_type == TIFF_IFD8)
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			fprintf(fd, "0x%I64x",
 				(unsigned __int64)((uint64 *) raw_data)[j]);
 #else
@@ -138,8 +138,8 @@ static int
 _TIFFPrettyPrintField(TIFF* tif, FILE* fd, uint32 tag,
 		      uint32 value_count, void *raw_data)
 {
-	TIFFDirectory *td = &tif->tif_dir;
-
+        (void) tif;
+        
 	switch (tag)
 	{
 		case TIFFTAG_INKSET:
@@ -212,7 +212,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 	uint16 i;
 	long l, n;
 
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 	fprintf(fd, "TIFF Directory at offset 0x%I64x (%I64u)\n",
 		(unsigned __int64) tif->tif_diroff,
 		(unsigned __int64) tif->tif_diroff);
@@ -448,12 +448,18 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 		fprintf(fd, "  Min Sample Value: %u\n", td->td_minsamplevalue);
 	if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE))
 		fprintf(fd, "  Max Sample Value: %u\n", td->td_maxsamplevalue);
-	if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE))
-		fprintf(fd, "  SMin Sample Value: %g\n",
-		    td->td_sminsamplevalue);
-	if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE))
-		fprintf(fd, "  SMax Sample Value: %g\n",
-		    td->td_smaxsamplevalue);
+	if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) {
+		fprintf(fd, "  SMin Sample Value:");
+		for (i = 0; i < td->td_samplesperpixel; ++i)
+			fprintf(fd, " %g", td->td_sminsamplevalue[i]);
+		fprintf(fd, "\n");
+	}
+	if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) {
+		fprintf(fd, "  SMax Sample Value:");
+		for (i = 0; i < td->td_samplesperpixel; ++i)
+			fprintf(fd, " %g", td->td_smaxsamplevalue[i]);
+		fprintf(fd, "\n");
+	}
 	if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) {
 		fprintf(fd, "  Planar Configuration: ");
 		switch (td->td_planarconfig) {
@@ -512,7 +518,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 	if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) {
 		fprintf(fd, "  SubIFD Offsets:");
 		for (i = 0; i < td->td_nsubifd; i++)
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			fprintf(fd, " %5I64u",
 				(unsigned __int64) td->td_subifd[i]);
 #else
@@ -614,6 +620,9 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
         
 	if (tif->tif_tagmethods.printdir)
 		(*tif->tif_tagmethods.printdir)(tif, fd, flags);
+
+        _TIFFFillStriles( tif );
+        
 	if ((flags & TIFFPRINT_STRIPS) &&
 	    TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
 		uint32 s;
@@ -622,7 +631,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 		    (long) td->td_nstrips,
 		    isTiled(tif) ? "Tiles" : "Strips");
 		for (s = 0; s < td->td_nstrips; s++)
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			fprintf(fd, "    %3lu: [%8I64u, %8I64u]\n",
 			    (unsigned long) s,
 			    (unsigned __int64) td->td_stripoffset[s],
diff --git a/frmts/gtiff/libtiff/tif_read.c b/frmts/gtiff/libtiff/tif_read.c
index 9537762..594733f 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.33 2011-01-06 05:51:13 fwarmerdam Exp $ */
+/* $Id: tif_read.c,v 1.38 2011-12-09 03:29:10 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -50,15 +50,18 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
         uint64 unused_data;
         uint64 read_offset;
         tmsize_t cc, to_read;
+        tmsize_t bytecountm;
+        
+        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+            return 0;
         
         /*
          * Expand raw data buffer, if needed, to hold data
          * strip coming from file (perhaps should set upper
          * bound on the size of a buffer we'll use?).
          */
-        tmsize_t bytecountm;
+
         bytecountm=(tmsize_t) td->td_stripbytecount[strip];
-                        
         if (read_ahead*2 > tif->tif_rawdatasize) {
                 assert( restart );
                 
@@ -120,7 +123,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
         cc = TIFFReadFile(tif, tif->tif_rawdata + unused_data, to_read);
 
         if (cc != to_read) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
                 TIFFErrorExt(tif->tif_clientdata, module,
                              "Read error at scanline %lu; got %I64u bytes, expected %I64u",
                              (unsigned long) tif->tif_row,
@@ -196,7 +199,9 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
          * Do we want to treat this strip as one whole chunk or
          * read it a few lines at a time?
          */
-#if defined(CHUNKY_STRIP_READ_SUPPORT)        
+#if defined(CHUNKY_STRIP_READ_SUPPORT)
+        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+            return 0;
         whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10
                 || isMapped(tif);
 #else
@@ -357,6 +362,9 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
 {
 	TIFFDirectory *td = &tif->tif_dir;
 
+    if (!_TIFFFillStriles( tif ))
+        return ((tmsize_t)(-1));
+        
 	assert((tif->tif_flags&TIFF_NOREADRAW)==0);
 	if (!isMapped(tif)) {
 		tmsize_t cc;
@@ -369,7 +377,7 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
 		}
 		cc = TIFFReadFile(tif, buf, size);
 		if (cc != size) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 		"Read error at scanline %lu; got %I64u bytes, expected %I64u",
 				     (unsigned long) tif->tif_row,
@@ -396,7 +404,7 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
 		else
 			n=size;
 		if (n!=size) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 	"Read error at scanline %lu, strip %lu; got %I64u bytes, expected %I64u",
 				     (unsigned long) tif->tif_row,
@@ -447,7 +455,7 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
 	}
 	bytecount = td->td_stripbytecount[strip];
 	if (bytecount <= 0) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 		TIFFErrorExt(tif->tif_clientdata, module,
 			     "%I64u: Invalid strip byte count, strip %lu",
 			     (unsigned __int64) bytecount,
@@ -480,11 +488,14 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
 	static const char module[] = "TIFFFillStrip";
 	TIFFDirectory *td = &tif->tif_dir;
 
+    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+        return 0;
+        
 	if ((tif->tif_flags&TIFF_NOREADRAW)==0)
 	{
 		uint64 bytecount = td->td_stripbytecount[strip];
 		if (bytecount <= 0) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 				"Invalid strip byte count %I64u, strip %lu",
 				     (unsigned __int64) bytecount,
@@ -530,7 +541,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
 				 * it's what would happen if a read were done
 				 * instead.
 				 */
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 				TIFFErrorExt(tif->tif_clientdata, module,
 
 					"Read error on strip %lu; "
@@ -647,6 +658,9 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
 {
 	TIFFDirectory *td = &tif->tif_dir;
 
+    if (!_TIFFFillStriles( tif ))
+        return ((tmsize_t)(-1));
+
 	assert((tif->tif_flags&TIFF_NOREADRAW)==0);
 	if (!isMapped(tif)) {
 		tmsize_t cc;
@@ -661,7 +675,7 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
 		}
 		cc = TIFFReadFile(tif, buf, size);
 		if (cc != size) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 	"Read error at row %lu, col %lu; got %I64u bytes, expected %I64u",
 				     (unsigned long) tif->tif_row,
@@ -690,7 +704,7 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
 		else
 			n=size;
 		if (n!=size) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 "Read error at row %lu, col %lu, tile %lu; got %I64u bytes, expected %I64u",
 				     (unsigned long) tif->tif_row,
@@ -761,11 +775,14 @@ TIFFFillTile(TIFF* tif, uint32 tile)
 	static const char module[] = "TIFFFillTile";
 	TIFFDirectory *td = &tif->tif_dir;
 
+    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+        return 0;
+        
 	if ((tif->tif_flags&TIFF_NOREADRAW)==0)
 	{
 		uint64 bytecount = td->td_stripbytecount[tile];
 		if (bytecount <= 0) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
 				"%I64u: Invalid tile byte count, tile %lu",
 				     (unsigned __int64) bytecount,
@@ -904,6 +921,9 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
 {
 	TIFFDirectory *td = &tif->tif_dir;
 
+    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+        return 0;
+
 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
 		if (!(*tif->tif_setupdecode)(tif))
 			return (0);
@@ -936,6 +956,9 @@ TIFFStartTile(TIFF* tif, uint32 tile)
 {
 	TIFFDirectory *td = &tif->tif_dir;
 
+    if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
+        return 0;
+
 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
 		if (!(*tif->tif_setupdecode)(tif))
 			return (0);
diff --git a/frmts/gtiff/libtiff/tif_strip.c b/frmts/gtiff/libtiff/tif_strip.c
index bddb6c5..3ced5a8 100644
--- a/frmts/gtiff/libtiff/tif_strip.c
+++ b/frmts/gtiff/libtiff/tif_strip.c
@@ -1,4 +1,4 @@
-/* $Id: tif_strip.c,v 1.33 2010-07-01 15:33:28 dron Exp $ */
+/* $Id: tif_strip.c,v 1.34 2011-04-02 20:54:09 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -152,7 +152,7 @@ TIFFRawStripSize64(TIFF* tif, uint32 strip)
 
 	if (bytecount == 0)
 	{
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 		TIFFErrorExt(tif->tif_clientdata, module,
 			     "%I64u: Invalid strip byte count, strip %lu",
 			     (unsigned __int64) bytecount,
diff --git a/frmts/gtiff/libtiff/tif_thunder.c b/frmts/gtiff/libtiff/tif_thunder.c
index dcb1a77..390891c 100644
--- a/frmts/gtiff/libtiff/tif_thunder.c
+++ b/frmts/gtiff/libtiff/tif_thunder.c
@@ -1,4 +1,4 @@
-/* $Id: tif_thunder.c,v 1.10 2010-03-10 18:56:49 bfriesen Exp $ */
+/* $Id: tif_thunder.c,v 1.12 2011-04-02 20:54:09 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -25,6 +25,7 @@
  */
 
 #include "tiffiop.h"
+#include <assert.h>
 #ifdef THUNDER_SUPPORT
 /*
  * TIFF Library.
@@ -55,12 +56,32 @@
 static const int twobitdeltas[4] = { 0, 1, 0, -1 };
 static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 };
 
-#define	SETPIXEL(op, v) { \
-	lastpixel = (v) & 0xf; \
-	if (npixels++ & 1) \
-	    *op++ |= lastpixel; \
-	else \
+#define	SETPIXEL(op, v) {                     \
+	lastpixel = (v) & 0xf;                \
+        if ( npixels < maxpixels )         \
+        {                                     \
+	  if (npixels++ & 1)                  \
+	    *op++ |= lastpixel;               \
+	  else                                \
 	    op[0] = (uint8) (lastpixel << 4); \
+        }                                     \
+}
+
+static int
+ThunderSetupDecode(TIFF* tif)
+{
+	static const char module[] = "ThunderSetupDecode";
+
+        if( tif->tif_dir.td_bitspersample != 4 )
+        {
+                TIFFErrorExt(tif->tif_clientdata, module,
+                             "Wrong bitspersample value (%d), Thunder decoder only supports 4bits per sample.",
+                             (int) tif->tif_dir.td_bitspersample );
+                return 0;
+        }
+        
+
+	return (1);
 }
 
 static int
@@ -122,7 +143,7 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels)
 	tif->tif_rawcp = (uint8*) bp;
 	tif->tif_rawcc = cc;
 	if (npixels != maxpixels) {
-#if defined(__WIN32__) && defined(_MSC_VER)
+#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 		TIFFErrorExt(tif->tif_clientdata, module,
 			     "%s data at scanline %lu (%I64u != %I64u)",
 			     npixels < maxpixels ? "Not enough" : "Too much",
@@ -139,7 +160,8 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels)
 #endif
 		return (0);
 	}
-	return (1);
+
+        return (1);
 }
 
 static int
@@ -167,6 +189,8 @@ int
 TIFFInitThunderScan(TIFF* tif, int scheme)
 {
 	(void) scheme;
+
+        tif->tif_setupdecode = ThunderSetupDecode;
 	tif->tif_decoderow = ThunderDecodeRow;
 	tif->tif_decodestrip = ThunderDecodeRow; 
 	return (1);
diff --git a/frmts/gtiff/libtiff/tif_write.c b/frmts/gtiff/libtiff/tif_write.c
index 585973e..eaa1f81 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.35 2010-03-10 18:56:49 bfriesen Exp $ */
+/* $Id: tif_write.c,v 1.36 2011-02-18 20:53:04 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -498,6 +498,8 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
 		    "Can not write scanlines to a tiled image");
 		return (0);
 	}
+
+        _TIFFFillStriles( tif );
         
 	/*
 	 * On the first write verify all the required information
diff --git a/frmts/gtiff/libtiff/tiff.h b/frmts/gtiff/libtiff/tiff.h
index 40592de..5c32d3a 100644
--- a/frmts/gtiff/libtiff/tiff.h
+++ b/frmts/gtiff/libtiff/tiff.h
@@ -1,4 +1,4 @@
-/* $Id: tiff.h,v 1.66 2010-12-14 12:53:00 dron Exp $ */
+/* $Id: tiff.h,v 1.67 2011-01-24 21:06:32 olivier Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -569,6 +569,9 @@ typedef enum {
 #define     SGILOGENCODE_NODITHER	0     /* do not dither encoded values*/
 #define     SGILOGENCODE_RANDITHER	1     /* randomly dither encd values */
 #define	TIFFTAG_LZMAPRESET		65562	/* LZMA2 preset (compression level) */
+#define TIFFTAG_PERSAMPLE       65563	/* interface for per sample tags */
+#define     PERSAMPLE_MERGED        0	/* present as a single value */
+#define     PERSAMPLE_MULTI         1	/* present as multiple values */
 
 /*
  * EXIF tags
diff --git a/frmts/gtiff/libtiff/tiffio.h b/frmts/gtiff/libtiff/tiffio.h
index af6082f..d223b2c 100644
--- a/frmts/gtiff/libtiff/tiffio.h
+++ b/frmts/gtiff/libtiff/tiffio.h
@@ -1,4 +1,4 @@
-/* $Id: tiffio.h,v 1.86 2010-03-10 18:56:49 bfriesen Exp $ */
+/* $Id: tiffio.h,v 1.88 2011-05-17 00:21:17 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -530,10 +530,7 @@ typedef	struct {
 } TIFFFieldInfo;
 
 extern int TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], uint32);
-extern const TIFFFieldInfo* TIFFFindFieldInfo(TIFF*, uint32, TIFFDataType);
-extern const TIFFFieldInfo* TIFFFindFieldInfoByName(TIFF* , const char *,
-						    TIFFDataType);
-
+        
 #if defined(c_plusplus) || defined(__cplusplus)
 }
 #endif
diff --git a/frmts/gtiff/libtiff/tiffiop.h b/frmts/gtiff/libtiff/tiffiop.h
index 7a2d8b2..7bed4ab 100644
--- a/frmts/gtiff/libtiff/tiffiop.h
+++ b/frmts/gtiff/libtiff/tiffiop.h
@@ -1,4 +1,4 @@
-/* $Id: tiffiop.h,v 1.80 2010-07-01 15:33:28 dron Exp $ */
+/* $Id: tiffiop.h,v 1.82 2011-02-18 20:53:05 fwarmerdam Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -58,6 +58,7 @@ extern void *lfind(const void *, const void *, size_t *, size_t,
 #endif
 
 #include "tiffio.h"
+
 #include "tif_dir.h"
 
 #ifndef STRIP_SIZE_DEFAULT
@@ -71,28 +72,6 @@ extern void *lfind(const void *, const void *, size_t *, size_t,
 #define	FALSE	0
 #endif
 
-/*
- * TIFF Image File Directories are comprised of a table of field
- * descriptors of the form shown below.  The table is sorted in
- * ascending order by tag.  The values associated with each entry are
- * disjoint and may appear anywhere in the file (so long as they are
- * placed on a word boundary).
- *
- * If the value is 4 bytes or less, in ClassicTIFF, or 8 bytes or less in
- * BigTIFF, then it is placed in the offset field to save space. If so,
- * it is left-justified in the offset field.
- */
-typedef struct {
-	uint16 tdir_tag;        /* see below */
-	uint16 tdir_type;       /* data type; see below */
-	uint64 tdir_count;      /* number of items; length in spec */
-	union {
-		uint16 toff_short;
-		uint32 toff_long;
-		uint64 toff_long8;
-	} tdir_offset;		/* either offset or the data itself if fits */
-} TIFFDirEntry;
-
 typedef struct client_info {
     struct client_info *next;
     void *data;
@@ -141,6 +120,7 @@ struct tiff {
 	#define TIFF_BIGTIFF     0x80000 /* read/write bigtiff */
         #define TIFF_BUF4WRITE  0x100000 /* rawcc bytes are for writing */
         #define TIFF_DIRTYSTRIP 0x200000 /* stripoffsets/stripbytecount dirty*/
+        #define TIFF_PERSAMPLE  0x400000 /* get/set per sample tags as arrays */
 	uint64               tif_diroff;       /* file offset of current directory */
 	uint64               tif_nextdiroff;   /* file offset of following directory */
 	uint64*              tif_dirlist;      /* list of offsets to already seen directories to prevent IFD looping */
diff --git a/frmts/gtiff/libtiff/tiffvers.h b/frmts/gtiff/libtiff/tiffvers.h
index 88ec059..b10177e 100644
--- a/frmts/gtiff/libtiff/tiffvers.h
+++ b/frmts/gtiff/libtiff/tiffvers.h
@@ -1,4 +1,4 @@
-#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.0beta6\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
 /*
  * This define can be used in code that requires
  * compilation-related definitions specific to a
@@ -6,4 +6,4 @@
  * version checking should be done based on the
  * string returned by TIFFGetVersion.
  */
-#define TIFFLIB_VERSION 20100611
+#define TIFFLIB_VERSION 20111221
diff --git a/frmts/gtiff/tifvsi.cpp b/frmts/gtiff/tifvsi.cpp
index 7b69202..c173cfb 100644
--- a/frmts/gtiff/tifvsi.cpp
+++ b/frmts/gtiff/tifvsi.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tifvsi.cpp 21102 2010-11-08 20:47:38Z rouault $
+ * $Id: tifvsi.cpp 22639 2011-07-03 15:51:39Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -38,6 +38,10 @@
 // We avoid including xtiffio.h since it drags in the libgeotiff version
 // of the VSI functions.
 
+#ifdef RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
+#include "gdal_libgeotiff_symbol_rename.h"
+#endif
+
 CPL_C_START
 extern TIFF CPL_DLL * XTIFFClientOpen(const char* name, const char* mode, 
                                       thandle_t thehandle,
diff --git a/frmts/gxf/gxfdataset.cpp b/frmts/gxf/gxfdataset.cpp
index 12cfcff..4003564 100644
--- a/frmts/gxf/gxfdataset.cpp
+++ b/frmts/gxf/gxfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfdataset.cpp 21085 2010-11-07 17:54:54Z warmerdam $
+ * $Id: gxfdataset.cpp 22401 2011-05-18 22:20:45Z warmerdam $
  *
  * Project:  GXF Reader
  * Purpose:  GDAL binding for GXF reader.
@@ -30,7 +30,7 @@
 #include "gxfopen.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: gxfdataset.cpp 21085 2010-11-07 17:54:54Z warmerdam $");
+CPL_CVSID("$Id: gxfdataset.cpp 22401 2011-05-18 22:20:45Z warmerdam $");
 
 #ifndef PI
 #  define PI 3.14159265358979323846
@@ -363,6 +363,11 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
diff --git a/frmts/hdf4/frmt_hdf4.html b/frmts/hdf4/frmt_hdf4.html
index 4447348..34fa36b 100644
--- a/frmts/hdf4/frmt_hdf4.html
+++ b/frmts/hdf4/frmt_hdf4.html
@@ -1,4 +1,4 @@
-<!-- $Id: frmt_hdf4.html 10296 2006-11-15 18:09:08Z fwarmerdam $ -->
+<!-- $Id: frmt_hdf4.html 22813 2011-07-25 19:01:41Z winkey $ -->
 
 <html>
 <head>
@@ -175,6 +175,13 @@ shown in parenthesis):<p>
 	<li> SeaWiFS Level 3 Standard Mapped Image Products (<B>SEAWIFS_L3</B>)
 </ul>
 
+<p>
+By default the hdf4 driver only reads the gcps from every 10th row and column
+from EOS_SWATH datasets. You can change this behaviour by setting the
+GEOL_AS_GCPS environment variable to PARTIAL (default), NONE, or FULL.
+</p>
+
+
 <h2>Creation Issues</h2>
 
 This driver supports creation of the HDF4 Scientific Datasets. You may create
diff --git a/frmts/hdf4/hdf-eos/EHapi.c b/frmts/hdf4/hdf-eos/EHapi.c
index 811dca4..7da3113 100644
--- a/frmts/hdf4/hdf-eos/EHapi.c
+++ b/frmts/hdf4/hdf-eos/EHapi.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: EHapi.c 12769 2007-11-14 15:12:27Z dron $
+ * $Id: EHapi.c 22144 2011-04-12 15:37:38Z warmerdam $
  *
  * This module has a number of additions and improvements over the original
  * implementation to be suitable for usage in GDAL HDF driver.
@@ -3365,7 +3365,7 @@ EHinquire(char *filename, char *type, char *objectlist, int32 * strbufsize)
     int32           nobj = 0;	/* Number of HDFEOS objects in file */
     int32           slen;	/* String length */
 
-    char            name[80];	/* Object name */
+    char            name[512];	/* Object name */
     char            class[80];	/* Object class */
 
 
diff --git a/frmts/hdf4/hdf-eos/gctp_wrap.c b/frmts/hdf4/hdf-eos/gctp_wrap.c
index ea4f3b1..97d2d2e 100644
--- a/frmts/hdf4/hdf-eos/gctp_wrap.c
+++ b/frmts/hdf4/hdf-eos/gctp_wrap.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gctp_wrap.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gctp_wrap.c 22751 2011-07-18 15:25:05Z winkey $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  This is the wrapper code to use OGR Coordinate Transformation
@@ -29,10 +29,33 @@
  ****************************************************************************/
 
 #include "ogr_srs_api.h"
+#include <stdlib.h>
+
 #include "mfhdf.h"
 
-static int iOutsys, iOutzone, iOutdatum, iInsys, iInzone, iIndatum;
-static double *pdfOutparm, *pdfInparm;
+#include <math.h>
+
+#ifndef PI
+#ifndef M_PI
+#define PI (3.141592653589793238)
+#else
+#define PI (M_PI)
+#endif
+#endif
+
+#define DEG (180.0 / PI)
+#define RAD (PI / 180.0)
+
+/***** static vars to store the transformers in *****/
+/***** this is not thread safe *****/
+
+static OGRCoordinateTransformationH hForCT, hInvCT;
+
+/******************************************************************************
+ function for forward gctp transformation
+
+ gctp expects Longitude and Latitude values to be in radians
+******************************************************************************/
 
 int32 osr_for(
 double lon,			/* (I) Longitude 		*/
@@ -40,96 +63,116 @@ double lat,			/* (I) Latitude 		*/
 double *x,			/* (O) X projection coordinate 	*/
 double *y)			/* (O) Y projection coordinate 	*/
 {
-    OGRSpatialReferenceH hSourceSRS, hLatLong;
-    OGRCoordinateTransformationH hCT;
-    double dfX, dfY, dfZ = 0.0;
-
-    hSourceSRS = OSRNewSpatialReference( NULL );
-    OSRImportFromUSGS( hSourceSRS, iOutsys, iOutzone, pdfOutparm, iOutdatum );
-    hLatLong = OSRCloneGeogCS( hSourceSRS );
-    hCT = OCTNewCoordinateTransformation( hLatLong, hSourceSRS );
-    if( hCT == NULL )
-    {
-        ;
-    }
 
-    dfY = lon, dfX = lat;
-    if( !OCTTransform( hCT, 1, &dfX, &dfY, &dfZ ) )
-        ;
-
-    *x = dfX, *y = dfY;
+    double dfX, dfY, dfZ = 0.0;
 
-    OSRDestroySpatialReference( hSourceSRS );
-    OSRDestroySpatialReference( hLatLong );
+    dfX = lon * DEG;
+    dfY = lat * DEG;
+    
+    OCTTransform( hForCT, 1, &dfX, &dfY, &dfZ);
 
+    *x = dfX;
+    *y = dfY;
+    
     return 0;
 }
 
+/******************************************************************************
+ function to init a forward gctp transformer
+******************************************************************************/
+
 void for_init(
-int32 outsys,		/* output system code				*/
-int32 outzone,		/* output zone number				*/
-float64 *outparm,	/* output array of projection parameters	*/
-int32 outdatum,		/* output datum					*/
-char *fn27,		/* NAD 1927 parameter file			*/
-char *fn83,		/* NAD 1983 parameter file			*/
-int32 *iflg,		/* status flag					*/
+int32 outsys,       /* output system code				*/
+int32 outzone,      /* output zone number				*/
+float64 *outparm,   /* output array of projection parameters	*/
+int32 outdatum,     /* output datum					*/
+char *fn27,         /* NAD 1927 parameter file			*/
+char *fn83,         /* NAD 1983 parameter file			*/
+int32 *iflg,        /* status flag					*/
 int32 (*for_trans[])(double, double, double *, double *))
                         /* forward function pointer			*/
 {
-    iflg = 0;
-    iOutsys = outsys;
-    iOutzone = outzone;
-    pdfOutparm = outparm;
-    iOutdatum = outdatum;
-    for_trans[iOutsys] = osr_for;
+    OGRSpatialReferenceH hOutSourceSRS, hLatLong = NULL;
+    
+    *iflg = 0;
+    
+    hOutSourceSRS = OSRNewSpatialReference( NULL );
+    OSRImportFromUSGS( hOutSourceSRS, outsys, outzone, outparm, outdatum     );
+    hLatLong = OSRNewSpatialReference ( SRS_WKT_WGS84 );
+
+    hForCT = OCTNewCoordinateTransformation( hLatLong, hOutSourceSRS );
+
+    OSRDestroySpatialReference( hOutSourceSRS );
+    OSRDestroySpatialReference( hLatLong );
+    
+    for_trans[outsys] = osr_for;
 }
 
+/******************************************************************************
+ function for inverse gctp transformation
+
+ gctp returns Longitude and Latitude values in radians
+******************************************************************************/
+
 int32 osr_inv(
-double x,			/* (O) X projection coordinate 	*/
-double y,			/* (O) Y projection coordinate 	*/
-double *lon,			/* (I) Longitude 		*/
-double *lat)			/* (I) Latitude 		*/
+double x,           /* (I) X projection coordinate 	*/
+double y,           /* (I) Y projection coordinate 	*/
+double *lon,        /* (O) Longitude 		*/
+double *lat)        /* (O) Latitude 		*/
 {
-    OGRSpatialReferenceH hSourceSRS, hLatLong;
-    OGRCoordinateTransformationH hCT;
-    double dfX, dfY, dfZ = 0.0;
-
-    hSourceSRS = OSRNewSpatialReference( NULL );
-    OSRImportFromUSGS( hSourceSRS, iInsys, iInzone, pdfInparm, iIndatum );
-    hLatLong = OSRCloneGeogCS( hSourceSRS );
-    hCT = OCTNewCoordinateTransformation( hSourceSRS, hLatLong );
-    if( hCT == NULL )
-    {
-        ;
-    }
 
-    //OSRDestroySpatialReference();
+    double dfX, dfY, dfZ = 0.0;
+    
+    dfX = x;
+    dfY = y;
 
-    dfX = x, dfY = x;
-    if( !OCTTransform( hCT, 1, &dfX, &dfY, &dfZ ) )
-        ;
+    OCTTransform( hInvCT, 1, &dfX, &dfY, &dfZ );
 
-    *lon = dfX, *lat = dfY;
+    *lon = dfX * RAD;
+    *lat = dfY * RAD;
 
     return 0;
 }
 
+/******************************************************************************
+ function to init a inverse gctp transformer
+******************************************************************************/
+
 void inv_init(
 int32 insys,		/* input system code				*/
 int32 inzone,		/* input zone number				*/
 float64 *inparm,	/* input array of projection parameters         */
-int32 indatum,	        /* input datum code			        */
-char *fn27,		/* NAD 1927 parameter file			*/
-char *fn83,		/* NAD 1983 parameter file			*/
+int32 indatum,	    /* input datum code			        */
+char *fn27,		    /* NAD 1927 parameter file			*/
+char *fn83,		    /* NAD 1983 parameter file			*/
 int32 *iflg,		/* status flag					*/
 int32 (*inv_trans[])(double, double, double*, double*))	
                         /* inverse function pointer			*/
 {
-    iflg = 0;
-    iInsys = insys;
-    iInzone = inzone;
-    pdfInparm = inparm; 
-    iIndatum = indatum;
+    
+    OGRSpatialReferenceH hInSourceSRS, hLatLong = NULL;
+    *iflg = 0;
+    
+    hInSourceSRS = OSRNewSpatialReference( NULL );
+    OSRImportFromUSGS( hInSourceSRS, insys, inzone, inparm, indatum );
+
+    hLatLong = OSRNewSpatialReference ( SRS_WKT_WGS84 );
+    
+    hInvCT = OCTNewCoordinateTransformation( hInSourceSRS, hLatLong );
+
+    OSRDestroySpatialReference( hInSourceSRS );
+    OSRDestroySpatialReference( hLatLong );
+    
     inv_trans[insys] = osr_inv;
 }
 
+/******************************************************************************
+ function to cleanup the transformers
+
+ note: gctp does not have a function that does this
+******************************************************************************/
+
+void gctp_destroy(void) {
+    OCTDestroyCoordinateTransformation ( hForCT );
+    OCTDestroyCoordinateTransformation ( hInvCT );
+}
diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp
index 7f2556f..f987537 100644
--- a/frmts/hdf4/hdf4dataset.cpp
+++ b/frmts/hdf4/hdf4dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.cpp 19769 2010-05-25 00:39:46Z ilucena $
+ * $Id: hdf4dataset.cpp 22838 2011-07-30 17:55:35Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
@@ -39,7 +39,7 @@
 #include "hdf4compat.h"
 #include "hdf4dataset.h"
 
-CPL_CVSID("$Id: hdf4dataset.cpp 19769 2010-05-25 00:39:46Z ilucena $");
+CPL_CVSID("$Id: hdf4dataset.cpp 22838 2011-07-30 17:55:35Z rouault $");
 
 CPL_C_START
 void	GDALRegister_HDF4(void);
@@ -771,6 +771,12 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*  Process swath layers.                                               */
 /* -------------------------------------------------------------------- */
         hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ );
+        if( hHDF4 < 0)
+        {
+            delete poDS;
+            CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open HDF4 `%s'.\n", poOpenInfo->pszFilename );
+            return NULL;
+        } 
         nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
 #if DEBUG
         CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", (int)nSubDatasets );
@@ -1093,8 +1099,17 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
         pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets,
                             "SUBDATASET_1_NAME" ));
         delete poDS;
-        poDS = (HDF4Dataset *) GDALOpen( pszSDSName, poOpenInfo->eAccess );
+        poDS = NULL;
+
+        GDALDataset* poRetDS = (GDALDataset*) GDALOpen( pszSDSName, poOpenInfo->eAccess );
         CPLFree( pszSDSName );
+
+        if (poRetDS)
+        {
+            poRetDS->SetDescription(poOpenInfo->pszFilename);
+        }
+
+        return poRetDS;
     }
     else
     {
diff --git a/frmts/hdf4/hdf4imagedataset.cpp b/frmts/hdf4/hdf4imagedataset.cpp
index 706b513..f6d69a1 100644
--- a/frmts/hdf4/hdf4imagedataset.cpp
+++ b/frmts/hdf4/hdf4imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4imagedataset.cpp 21126 2010-11-13 12:02:01Z dron $
+ * $Id: hdf4imagedataset.cpp 22765 2011-07-23 09:56:53Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Read subdatasets of HDF4 file.
@@ -45,7 +45,7 @@
 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: hdf4imagedataset.cpp 21126 2010-11-13 12:02:01Z dron $");
+CPL_CVSID("$Id: hdf4imagedataset.cpp 22765 2011-07-23 09:56:53Z rouault $");
 
 CPL_C_START
 void    GDALRegister_HDF4(void);
@@ -2693,7 +2693,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
             case H4ST_EOS_SWATH:
             case H4ST_EOS_SWATH_GEOL:
             {
-                int32   hSW, nStrBufSize;
+                int32   hSW;
                 char    *pszDimList = NULL;
 
                 if( poOpenInfo->eAccess == GA_ReadOnly )
@@ -2721,10 +2721,28 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Decode the dimension map.                                       */
 /* -------------------------------------------------------------------- */
-                SWnentries( hSW, HDFE_NENTDIM, &nStrBufSize );
+                int32   nStrBufSize = 0;
+
+                if ( SWnentries( hSW, HDFE_NENTDIM, &nStrBufSize ) < 0
+                     || nStrBufSize <= 0 )
+                {
+                    CPLDebug( "HDF4Image",
+                              "Can't read a number of dimension maps." );
+                    delete poDS;
+                    return NULL;
+                }
+
                 pszDimList = (char *)CPLMalloc( nStrBufSize + 1 );
-                SWfieldinfo( hSW, poDS->pszFieldName, &poDS->iRank,
-                             poDS->aiDimSizes, &poDS->iNumType, pszDimList );
+                if ( SWfieldinfo( hSW, poDS->pszFieldName, &poDS->iRank,
+                                  poDS->aiDimSizes, &poDS->iNumType,
+                                  pszDimList ) < 0 )
+                {
+                    CPLDebug( "HDF4Image", "Can't read dimension maps." );
+                    CPLFree( pszDimList );
+                    delete poDS;
+                    return NULL;
+                }
+                pszDimList[nStrBufSize] = '\0';
 #ifdef DEBUG
                 CPLDebug( "HDF4Image",
                           "List of dimensions in swath \"%s\": %s",
@@ -3548,6 +3566,7 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Can't create HDF4 file %s", pszFilename );
+        delete poDS;
         return NULL;
     }
     poDS->iXDim = 1;
diff --git a/frmts/hdf5/bagdataset.cpp b/frmts/hdf5/bagdataset.cpp
index ddca112..1bd047c 100644
--- a/frmts/hdf5/bagdataset.cpp
+++ b/frmts/hdf5/bagdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bagdataset.cpp 21651 2011-02-08 19:22:03Z warmerdam $
+ * $Id: bagdataset.cpp 22145 2011-04-12 15:42:18Z warmerdam $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read BAG datasets.
@@ -34,7 +34,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: bagdataset.cpp 21651 2011-02-08 19:22:03Z warmerdam $");
+CPL_CVSID("$Id: bagdataset.cpp 22145 2011-04-12 15:42:18Z warmerdam $");
 
 CPL_C_START
 void    GDALRegister_BAG(void);
@@ -116,6 +116,8 @@ BAGRasterBand::BAGRasterBand( BAGDataset *poDS, int nBand )
     this->nBand      = nBand;
     
     hDatasetID = -1;
+    dataspace = -1;
+    native = -1;
     bMinMaxSet = false;
 }
 
@@ -125,6 +127,14 @@ BAGRasterBand::BAGRasterBand( BAGDataset *poDS, int nBand )
 
 BAGRasterBand::~BAGRasterBand()
 {
+  if( dataspace > 0 )
+    H5Sclose(dataspace);
+
+  if( native > 0 )
+    H5Tclose( native );
+
+  if( hDatasetID > 0 )
+    H5Dclose( hDatasetID );
 }
 
 /************************************************************************/
@@ -150,8 +160,8 @@ bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
     {
         H5Sget_simple_extent_dims( dataspace, dims, maxdims );
 
-        nRasterXSize = dims[1];
-        nRasterYSize = dims[0];
+        nRasterXSize = (int) dims[1];
+        nRasterYSize = (int) dims[0];
     }
     else
     {
@@ -174,8 +184,8 @@ bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
         {
             hsize_t panChunkDims[3];
             int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
-            nBlockXSize   = panChunkDims[nDimSize-1];
-            nBlockYSize   = panChunkDims[nDimSize-2];
+            nBlockXSize  = (int) panChunkDims[nDimSize-1];
+            nBlockYSize  = (int) panChunkDims[nDimSize-2];
         }
         H5Pclose(listid);
     }
@@ -289,7 +299,7 @@ CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     col_dims[0]=nBlockYSize;
     col_dims[1]=nBlockXSize;
-    memspace = H5Screate_simple( rank, col_dims, NULL );
+    memspace = H5Screate_simple( (int) rank, col_dims, NULL );
     H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
     status =  H5Sselect_hyperslab(memspace,
                                   H5S_SELECT_SET,
@@ -529,10 +539,11 @@ void BAGDataset::LoadMetadata()
 
     H5Sget_simple_extent_dims( dataspace, dims, maxdims );
 
-    pszXMLMetadata = (char *) CPLCalloc(dims[0]+1,1);
+    pszXMLMetadata = (char *) CPLCalloc((int) (dims[0]+1),1);
 
     H5Dread( hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata );
 
+    H5Tclose( native );
     H5Sclose( dataspace );
     H5Tclose( datatype );
     H5Dclose( hMDDS );
diff --git a/frmts/hdf5/frmt_bag.html b/frmts/hdf5/frmt_bag.html
index f6b6440..7cd95ef 100644
--- a/frmts/hdf5/frmt_bag.html
+++ b/frmts/hdf5/frmt_bag.html
@@ -1,4 +1,4 @@
-<!-- $Id: frmt_hdf5.html 17235 2009-06-15 14:26:45Z warmerdam $ -->
+<!-- $Id: frmt_bag.html 22975 2011-08-24 19:41:41Z rouault $ -->
 
 <html>
 <head>
@@ -9,7 +9,7 @@
 
 <h1>BAG --- Bathymetry Attributed Grid</h1>
 
-This driver provides read-onl support for bathymetry data in the BAG format.
+This driver provides read-only support for bathymetry data in the BAG format.
 BAG files are actually a specific product profile in an HDF5 file, but a 
 custom driver exists to present the data in a more convenient manner than
 is available through the generic HDF5 driver.<p>
diff --git a/frmts/hdf5/gh5_convenience.cpp b/frmts/hdf5/gh5_convenience.cpp
index 6d59e15..842cee5 100644
--- a/frmts/hdf5/gh5_convenience.cpp
+++ b/frmts/hdf5/gh5_convenience.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gh5_convenience.cpp 21651 2011-02-08 19:22:03Z warmerdam $
+ * $Id: gh5_convenience.cpp 22145 2011-04-12 15:42:18Z 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 21651 2011-02-08 19:22:03Z warmerdam $");
+CPL_CVSID("$Id: gh5_convenience.cpp 22145 2011-04-12 15:42:18Z warmerdam $");
 
 /************************************************************************/
 /*                    GH5_FetchAttribute(CPLString)                     */
@@ -79,6 +79,7 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
         retVal = false;
     }
 
+    H5Tclose( hAttrNativeType );
     H5Tclose( hAttrTypeID );
     H5Aclose( hAttr );
     return retVal;
@@ -118,7 +119,7 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
     int i, nAttrElements = 1;
 
     for( i=0; i < nAttrDims; i++ ) {
-        nAttrElements *= anSize[i];
+        nAttrElements *= (int) anSize[i];
     }
 
     if( nAttrElements != 1 )
@@ -128,6 +129,8 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
                       "Attempt to read attribute %s failed, count=%d, not 1.",
                       pszAttrName, nAttrElements );
 
+        H5Sclose( hAttrSpace );
+        H5Tclose( hAttrNativeType );
         H5Tclose( hAttrTypeID );
         H5Aclose( hAttr );
         return false;
@@ -156,6 +159,8 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
                       pszAttrName );
         CPLFree( buf );
 
+        H5Sclose( hAttrSpace );
+        H5Tclose( hAttrNativeType );
         H5Tclose( hAttrTypeID );
         H5Aclose( hAttr );
 
@@ -164,6 +169,8 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
 
     CPLFree( buf );
 
+    H5Sclose( hAttrSpace );
+    H5Tclose( hAttrNativeType );
     H5Tclose( hAttrTypeID );
     H5Aclose( hAttr );
     return true;
diff --git a/frmts/hdf5/hdf5dataset.cpp b/frmts/hdf5/hdf5dataset.cpp
index 32a6f4f..ea5920b 100644
--- a/frmts/hdf5/hdf5dataset.cpp
+++ b/frmts/hdf5/hdf5dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5dataset.cpp 22531 2011-06-13 21:06:11Z warmerdam $
+ * $Id: hdf5dataset.cpp 23068 2011-09-06 20:50:23Z antonio $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 Datasets. Open HDF5 file, fetch metadata and list of
@@ -39,40 +39,40 @@
 #include "cpl_string.h"
 #include "hdf5dataset.h"
 
-CPL_CVSID("$Id: hdf5dataset.cpp 22531 2011-06-13 21:06:11Z warmerdam $");
+CPL_CVSID("$Id: hdf5dataset.cpp 23068 2011-09-06 20:50:23Z antonio $");
 
 CPL_C_START
-void	GDALRegister_HDF5(void);
+void GDALRegister_HDF5(void);
 CPL_C_END
 
 
 
 /************************************************************************/
 /* ==================================================================== */
-/*				HDF5Dataset				*/
+/*                              HDF5Dataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
 /************************************************************************/
-/*                        GDALRegister_HDF5()				*/
+/*                        GDALRegister_HDF5()                           */
 /************************************************************************/
 void GDALRegister_HDF5()
-    
+
 {
     GDALDriver	*poDriver;
     if( GDALGetDriverByName("HDF5") == NULL )
-	{
-	    poDriver = new GDALDriver();
-	    poDriver->SetDescription("HDF5");
-	    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 
-				      "Hierarchical Data Format Release 5");
-	    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, 
-				      "frmt_hdf5.html");
-	    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf5");
-	    poDriver->pfnOpen = HDF5Dataset::Open;
-	    poDriver->pfnIdentify = HDF5Dataset::Identify;
-	    GetGDALDriverManager()->RegisterDriver(poDriver);
-	}
+    {
+        poDriver = new GDALDriver();
+        poDriver->SetDescription("HDF5");
+        poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
+                                  "Hierarchical Data Format Release 5");
+        poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
+                                  "frmt_hdf5.html");
+        poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf5");
+        poDriver->pfnOpen = HDF5Dataset::Open;
+        poDriver->pfnIdentify = HDF5Dataset::Identify;
+        GetGDALDriverManager()->RegisterDriver(poDriver);
+    }
 }
 
 /************************************************************************/
@@ -98,17 +98,17 @@ HDF5Dataset::~HDF5Dataset()
 {
     CSLDestroy( papszMetadata );
     if( hHDF5 > 0 )
-	H5Fclose( hHDF5 );
+        H5Fclose( hHDF5 );
     if( hGroupID > 0 )
-	H5Gclose( hGroupID );
+        H5Gclose( hGroupID );
     CSLDestroy( papszSubDatasets );
-    if( poH5RootGroup != NULL ){
-	DestroyH5Objects( poH5RootGroup );
-	CPLFree( poH5RootGroup->pszName );
-	CPLFree( poH5RootGroup->pszPath );
-	CPLFree( poH5RootGroup->pszUnderscorePath );
-	CPLFree( poH5RootGroup->poHchild );
-	CPLFree( poH5RootGroup );
+    if( poH5RootGroup != NULL ) {
+        DestroyH5Objects( poH5RootGroup );
+        CPLFree( poH5RootGroup->pszName );
+        CPLFree( poH5RootGroup->pszPath );
+        CPLFree( poH5RootGroup->pszUnderscorePath );
+        CPLFree( poH5RootGroup->poHchild );
+        CPLFree( poH5RootGroup );
     }
 }
 
@@ -117,44 +117,44 @@ HDF5Dataset::~HDF5Dataset()
 /*                                                                      */
 /*      Transform HDF5 datatype to GDAL datatype                        */
 /************************************************************************/
-GDALDataType HDF5Dataset::GetDataType(hid_t TypeID) 
+GDALDataType HDF5Dataset::GetDataType(hid_t TypeID)
 {
     if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
-	return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) ) 
-	return GDT_Byte;
+        return GDT_Byte;
+    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) )
+        return GDT_Byte;
     else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
-	return GDT_Int16;
-    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) ) 
-	return GDT_UInt16;
-    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) ) 
-	return GDT_Int32;      
-    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) ) 
-	return GDT_UInt32;
-    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) ) 
+        return GDT_Int16;
+    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) )
+        return GDT_UInt16;
+    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) )
+        return GDT_Int32;
+    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) )
+        return GDT_UInt32;
+    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) )
     {
         if( sizeof(long) == 4 )
-            return GDT_Int32;      
+            return GDT_Int32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) ) 
+    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) )
     {
         if( sizeof(unsigned long) == 4 )
-            return GDT_UInt32;      
+            return GDT_UInt32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) ) 
-	return GDT_Float32;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
-	return GDT_Float64;
-    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) ) 
-	return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) ) 
-	return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
-	return GDT_Unknown;
+    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) )
+        return GDT_Float32;
+    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
+        return GDT_Float64;
+    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) )
+        return GDT_Unknown;
+    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) )
+        return GDT_Unknown;
+    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
+        return GDT_Unknown;
 
     return GDT_Unknown;
 }
@@ -167,32 +167,32 @@ GDALDataType HDF5Dataset::GetDataType(hid_t TypeID)
 const char *HDF5Dataset::GetDataTypeName(hid_t TypeID)
 {
     if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
-	return "8-bit character";
-    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) ) 
-	return "8-bit unsigned character";    
+        return "8-bit character";
+    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) )
+        return "8-bit unsigned character";
     else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
-	return "16-bit integer";
-    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) ) 
-	return "16-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) ) 
-	return "32-bit integer";
-    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) ) 
-	return "32-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) ) 
-	return "32/64-bit integer";
-    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) ) 
-	return "32/64-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) ) 
-	return "32-bit floating-point";
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
-	return "64-bit floating-point";
-    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) ) 
-	return "64-bit integer";
-    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) ) 
-	return "64-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
+        return "16-bit integer";
+    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) )
+        return "16-bit unsigned integer";
+    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) )
+        return "32-bit integer";
+    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) )
+        return "32-bit unsigned integer";
+    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) )
+        return "32/64-bit integer";
+    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) )
+        return "32/64-bit unsigned integer";
+    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) )
+        return "32-bit floating-point";
+    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
+        return "64-bit floating-point";
+    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) )
+        return "64-bit integer";
+    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) )
+        return "64-bit unsigned integer";
+    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
         return "64-bit floating-point";
-    
+
     return "Unknown";
 }
 
@@ -208,11 +208,19 @@ int HDF5Dataset::Identify( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     static const char achSignature[] = "\211HDF\r\n\032\n";
 
-    if( poOpenInfo->pabyHeader == NULL
-        || memcmp(poOpenInfo->pabyHeader,achSignature,8) != 0 )
-        return FALSE;
+    if( poOpenInfo->pabyHeader )
+    {
+        if( memcmp(poOpenInfo->pabyHeader,achSignature,8) == 0 )
+            return TRUE;
+
+        if( memcmp(poOpenInfo->pabyHeader,"<HDF_UserBlock>",15) == 0)
+        {
+            if( H5Fis_hdf5(poOpenInfo->pszFilename) )
+              return TRUE;
+        }
+    }
 
-    return TRUE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -222,7 +230,7 @@ GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
 {
     HDF5Dataset *poDS;
     CPLErr      Err;
-    
+
     if( !Identify( poOpenInfo ) )
         return NULL;
 
@@ -236,26 +244,26 @@ GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    poDS->hHDF5 = H5Fopen( poOpenInfo->pszFilename, 
-			   H5F_ACC_RDONLY, 
-			   H5P_DEFAULT );
+    poDS->hHDF5 = H5Fopen( poOpenInfo->pszFilename,
+                           H5F_ACC_RDONLY,
+                           H5P_DEFAULT );
     if( poDS->hHDF5 < 0 )  {
         delete poDS;
-   	return NULL;
+        return NULL;
     }
-    
-    poDS->hGroupID = H5Gopen( poDS->hHDF5, "/" ); 
-    if( poDS->hGroupID < 0 ){
-	poDS->bIsHDFEOS=false;
+
+    poDS->hGroupID = H5Gopen( poDS->hHDF5, "/" );
+    if( poDS->hGroupID < 0 ) {
+        poDS->bIsHDFEOS=false;
         delete poDS;
-	return NULL;
+        return NULL;
     }
-    
+
     poDS->bIsHDFEOS=true;
     Err = poDS->ReadGlobalAttributes( true );
 
     poDS->SetMetadata( poDS->papszMetadata  );
-    
+
     if ( CSLCount( poDS->papszSubDatasets ) / 2 >= 1 )
         poDS->SetMetadata( poDS->papszSubDatasets, "SUBDATASETS" );
 
@@ -281,7 +289,7 @@ GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
         if( poOpenInfo->eAccess == GA_Update )
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_NotSupported, 
+            CPLError( CE_Failure, CPLE_NotSupported,
                       "The HDF5 driver does not support update access to existing"
                       " datasets.\n" );
             return NULL;
@@ -297,25 +305,24 @@ GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
 {
-    int i;
-
+    unsigned i;
 
 /* -------------------------------------------------------------------- */
 /*      Visit all objects                                               */
 /* -------------------------------------------------------------------- */
 
     for( i=0; i < poH5Object->nbObjs; i++ )
-	if( poH5Object->poHchild+i != NULL )
-	    DestroyH5Objects( poH5Object->poHchild+i );
+        if( poH5Object->poHchild+i != NULL )
+            DestroyH5Objects( poH5Object->poHchild+i );
 
     if( poH5Object->poHparent ==NULL )
-	return;
+        return;
 
 /* -------------------------------------------------------------------- */
 /*      Erase some data                                                 */
 /* -------------------------------------------------------------------- */
     CPLFree( poH5Object->paDims );
-    poH5Object->paDims = NULL; 
+    poH5Object->paDims = NULL;
 
     CPLFree( poH5Object->pszPath );
     poH5Object->pszPath = NULL;
@@ -329,7 +336,7 @@ void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
 /*      All Children are visited and can be deleted.                    */
 /* -------------------------------------------------------------------- */
     if( ( i==poH5Object->nbObjs ) && ( poH5Object->nbObjs!=0 ) ) {
-	CPLFree( poH5Object->poHchild );
+        CPLFree( poH5Object->poHchild );
         poH5Object->poHchild = NULL;
     }
 
@@ -353,16 +360,16 @@ char* CreatePath( HDF5GroupObjects *poH5Object )
 /* -------------------------------------------------------------------- */
     pszPath[0]='\0';
     if( poH5Object->poHparent !=NULL ) {
-	popszPath=CreatePath( poH5Object->poHparent );
-	strcpy( pszPath,popszPath );
+        popszPath=CreatePath( poH5Object->poHparent );
+        strcpy( pszPath,popszPath );
     }
-	
+
 /* -------------------------------------------------------------------- */
 /*      add name to the path                                            */
 /* -------------------------------------------------------------------- */
     if( !EQUAL( poH5Object->pszName,"/" ) ){
-	strcat( pszPath,"/" );
-	strcat( pszPath,poH5Object->pszName );
+        strcat( pszPath,"/" );
+        strcat( pszPath,poH5Object->pszName );
     }
 
 /* -------------------------------------------------------------------- */
@@ -370,28 +377,28 @@ char* CreatePath( HDF5GroupObjects *poH5Object )
 /* -------------------------------------------------------------------- */
     if( poH5Object->pszPath == NULL ) {
 
-	if( strlen( poH5Object->pszName ) == 1 ) {
-	    strcat(pszPath, poH5Object->pszName );
-	    strcpy(pszUnderscoreSpaceInName, poH5Object->pszName);
-	}
-	else {
+        if( strlen( poH5Object->pszName ) == 1 ) {
+            strcat(pszPath, poH5Object->pszName );
+            strcpy(pszUnderscoreSpaceInName, poH5Object->pszName);
+        }
+        else {
 /* -------------------------------------------------------------------- */
 /*      Change space for underscore                                     */
 /* -------------------------------------------------------------------- */
-	    papszPath = CSLTokenizeString2( pszPath,
-					    " ", CSLT_HONOURSTRINGS );
-	    
-	    strcpy(pszUnderscoreSpaceInName,papszPath[0]);
-	    for( i=1; i < CSLCount( papszPath ); i++ ) {
-		strcat( pszUnderscoreSpaceInName, "_" );
-		strcat( pszUnderscoreSpaceInName, papszPath[ i ] );
-	    }
-	    CSLDestroy(papszPath);
+            papszPath = CSLTokenizeString2( pszPath,
+                            " ", CSLT_HONOURSTRINGS );
 
-	}
-	poH5Object->pszUnderscorePath  = 
-	    CPLStrdup( pszUnderscoreSpaceInName );
-	poH5Object->pszPath  = CPLStrdup( pszPath );
+            strcpy(pszUnderscoreSpaceInName,papszPath[0]);
+            for( i=1; i < CSLCount( papszPath ); i++ ) {
+                strcat( pszUnderscoreSpaceInName, "_" );
+                strcat( pszUnderscoreSpaceInName, papszPath[ i ] );
+            }
+            CSLDestroy(papszPath);
+
+        }
+        poH5Object->pszUnderscorePath  =
+            CPLStrdup( pszUnderscoreSpaceInName );
+        poH5Object->pszPath  = CPLStrdup( pszPath );
     }
 
     return( poH5Object->pszPath );
@@ -425,15 +432,15 @@ static int HDF5GroupCheckDuplicate( HDF5GroupObjects *poHparent,
 /*                                                                      */
 /*      Create HDF5 hierarchy into a linked list                        */
 /************************************************************************/
-herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName, 
-			   void *poHObjParent)
+herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
+                           void *poHObjParent)
 {
-    herr_t	ret;			/* error return status */
-    hid_t	hGroupID;		/* identifier of group */
-    hid_t	hDatasetID;		/* identifier of dataset */
-    hsize_t     nbObjs=0;		/* number of objects in a group */
-    int         nbAttrs=0;		/* number of attributes in object */
-    int		idx;
+    herr_t      ret;            /* error return status */
+    hid_t       hGroupID;       /* identifier of group */
+    hid_t       hDatasetID;     /* identifier of dataset */
+    hsize_t     nbObjs=0;       /* number of objects in a group */
+    int         nbAttrs=0;      /* number of attributes in object */
+    unsigned    idx;
     int         n_dims;
     H5G_stat_t  oStatbuf;
     hsize_t     *dims=NULL;
@@ -443,8 +450,6 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
     hid_t       native;
     herr_t status;
 
-    char *CreatePath( HDF5GroupObjects *poH5Object );
-
     HDF5GroupObjects *poHchild;
     HDF5GroupObjects *poHparent;
 
@@ -452,25 +457,25 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
     poHchild=poHparent->poHchild;
 
     if( H5Gget_objinfo( hHDF5, pszObjName, FALSE, &oStatbuf ) < 0  )
-	return -1;
+        return -1;
+
 
-    
 /* -------------------------------------------------------------------- */
 /*      Look for next child                                             */
 /* -------------------------------------------------------------------- */
-    for( idx=0; idx < poHparent->nbObjs; idx++ )	{
-	if( poHchild->pszName == NULL ) break;
-	poHchild++;
+    for( idx=0; idx < poHparent->nbObjs; idx++ ) {
+        if( poHchild->pszName == NULL ) break;
+        poHchild++;
     }
 
-    if( idx == poHparent->nbObjs ) 
-	return -1;  // all children parsed
-    
+    if( idx == poHparent->nbObjs )
+        return -1;  // all children parsed
+
 /* -------------------------------------------------------------------- */
 /*      Save child information                                          */
 /* -------------------------------------------------------------------- */
     poHchild->pszName  = CPLStrdup( pszObjName );
-    
+
     poHchild->nType  = oStatbuf.type;
     poHchild->nIndex = idx;
     poHchild->poHparent = poHparent;
@@ -480,107 +485,108 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
     poHchild->objno[0]  = oStatbuf.objno[0];
     poHchild->objno[1]  = oStatbuf.objno[1];
     if( poHchild->pszPath == NULL ) {
-	poHchild->pszPath  = CreatePath( poHchild );
+        poHchild->pszPath  = CreatePath( poHchild );
     }
     if( poHparent->pszPath == NULL ) {
-	poHparent->pszPath = CreatePath( poHparent );
-    }
-
-
-    switch ( oStatbuf.type ) 
-	{
-	case H5G_LINK:
-	    poHchild->nbAttrs = 0;
-	    poHchild->nbObjs = 0;
-	    poHchild->poHchild = NULL;
-	    poHchild->nRank      = 0;
-	    poHchild->paDims    = 0;
-	    poHchild->HDatatype = 0;
-	    break;
-	    
-	case H5G_GROUP:
-	    if( ( hGroupID = H5Gopen( hHDF5, pszObjName ) ) == -1  ) {
-		printf( "Error: unable to access \"%s\" group.\n", 
-			pszObjName );
-		return -1;
-	    }
-	    nbAttrs          = H5Aget_num_attrs( hGroupID );
-	    ret              = H5Gget_num_objs( hGroupID, &nbObjs );
-	    poHchild->nbAttrs= nbAttrs;
-	    poHchild->nbObjs = nbObjs;
-	    poHchild->nRank      = 0;
-	    poHchild->paDims    = 0;
-	    poHchild->HDatatype = 0;
-	    
-	    if( nbObjs > 0 ) {
-		poHchild->poHchild =( HDF5GroupObjects * )
-		    CPLCalloc( nbObjs, sizeof( HDF5GroupObjects ) );
-		memset( poHchild->poHchild,0,
-			sizeof( HDF5GroupObjects ) * nbObjs );
-	    }
-	    else 
-		poHchild->poHchild = NULL;
+        poHparent->pszPath = CreatePath( poHparent );
+    }
+
+
+    switch ( oStatbuf.type )
+    {
+        case H5G_LINK:
+            poHchild->nbAttrs = 0;
+            poHchild->nbObjs = 0;
+            poHchild->poHchild = NULL;
+            poHchild->nRank      = 0;
+            poHchild->paDims    = 0;
+            poHchild->HDatatype = 0;
+            break;
+
+        case H5G_GROUP:
+            if( ( hGroupID = H5Gopen( hHDF5, pszObjName ) ) == -1  ) {
+                printf( "Error: unable to access \"%s\" group.\n",
+                        pszObjName );
+                return -1;
+            }
+            nbAttrs          = H5Aget_num_attrs( hGroupID );
+            ret              = H5Gget_num_objs( hGroupID, &nbObjs );
+            poHchild->nbAttrs= nbAttrs;
+            poHchild->nbObjs = (int) nbObjs;
+            poHchild->nRank      = 0;
+            poHchild->paDims    = 0;
+            poHchild->HDatatype = 0;
+
+            if( nbObjs > 0 ) {
+                poHchild->poHchild =( HDF5GroupObjects * )
+                CPLCalloc( (int)nbObjs, sizeof( HDF5GroupObjects ) );
+                memset( poHchild->poHchild, 0,
+                        (size_t) (sizeof( HDF5GroupObjects ) * nbObjs) );
+            }
+            else
+                poHchild->poHchild = NULL;
 
             if( !HDF5GroupCheckDuplicate( poHparent, oStatbuf.objno ) )
-                H5Giterate( hHDF5, pszObjName, NULL, 
+                H5Giterate( hHDF5, pszObjName, NULL,
                             HDF5CreateGroupObjs,  (void*) poHchild );
             else
-                CPLDebug( "HDF5", "avoiding link looping on node '%s'.", 
-                          pszObjName );
-	    H5Gclose( hGroupID );
-	    break;
-	    
-	case H5G_DATASET:
-	    
-	    if( ( hDatasetID = H5Dopen( hHDF5, pszObjName ) ) == -1  ) {
-		printf( "Error: unable to access \"%s\" dataset.\n", 
-		       pszObjName );
-		return -1;
-	    }
-	    nbAttrs      = H5Aget_num_attrs( hDatasetID );
-	    datatype     = H5Dget_type( hDatasetID );
-	    dataspace    = H5Dget_space( hDatasetID );
-	    n_dims       = H5Sget_simple_extent_ndims( dataspace );
-	    native       = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
-	    
-	    if( n_dims > 0 ) {
-		dims     = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
-		maxdims  = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
-	    }
-	    status     = H5Sget_simple_extent_dims( dataspace, dims, maxdims );
-	    if( maxdims != NULL )
-		CPLFree( maxdims );
-	    
-	    if( n_dims > 0 ) {
-		poHchild->nRank     = n_dims;   // rank of the array
-		poHchild->paDims    = dims;      // dimmension of the array.
-		poHchild->HDatatype = datatype;  // HDF5 datatype
-	    }
-	    else  {
-		poHchild->nRank     = -1;
-		poHchild->paDims    = NULL;
-		poHchild->HDatatype = 0;
-	}
-	    poHchild->nbAttrs   = nbAttrs;
-	    poHchild->nbObjs    = 0;
-	    poHchild->poHchild  = NULL;
-	    poHchild->native    = native;
-	    ret                 = H5Dclose( hDatasetID );
-	    break;
-	    
-	case H5G_TYPE:
-	    poHchild->nbAttrs = 0;
-	    poHchild->nbObjs = 0;
-	    poHchild->poHchild = NULL;
-	    poHchild->nRank      = 0;
-	    poHchild->paDims    = 0;
-	    poHchild->HDatatype = 0;
-	    break;
-	    
-	default:
-	    break;
-	}
-    
+                CPLDebug( "HDF5", "avoiding link looping on node '%s'.",
+                        pszObjName );
+
+            H5Gclose( hGroupID );
+            break;
+
+        case H5G_DATASET:
+
+            if( ( hDatasetID = H5Dopen( hHDF5, pszObjName ) ) == -1  ) {
+                printf( "Error: unable to access \"%s\" dataset.\n",
+                        pszObjName );
+                return -1;
+            }
+            nbAttrs      = H5Aget_num_attrs( hDatasetID );
+            datatype     = H5Dget_type( hDatasetID );
+            dataspace    = H5Dget_space( hDatasetID );
+            n_dims       = H5Sget_simple_extent_ndims( dataspace );
+            native       = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
+
+            if( n_dims > 0 ) {
+                dims     = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
+                maxdims  = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
+            }
+            status     = H5Sget_simple_extent_dims( dataspace, dims, maxdims );
+            if( maxdims != NULL )
+                CPLFree( maxdims );
+
+            if( n_dims > 0 ) {
+                poHchild->nRank     = n_dims;   // rank of the array
+                poHchild->paDims    = dims;      // dimmension of the array.
+                poHchild->HDatatype = datatype;  // HDF5 datatype
+            }
+            else  {
+                poHchild->nRank     = -1;
+                poHchild->paDims    = NULL;
+                poHchild->HDatatype = 0;
+            }
+            poHchild->nbAttrs   = nbAttrs;
+            poHchild->nbObjs    = 0;
+            poHchild->poHchild  = NULL;
+            poHchild->native    = native;
+            ret                 = H5Dclose( hDatasetID );
+            break;
+
+        case H5G_TYPE:
+            poHchild->nbAttrs = 0;
+            poHchild->nbObjs = 0;
+            poHchild->poHchild = NULL;
+            poHchild->nRank      = 0;
+            poHchild->paDims    = 0;
+            poHchild->HDatatype = 0;
+            break;
+
+        default:
+            break;
+    }
+
     return 0;
 }
 
@@ -589,9 +595,9 @@ herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName,
 /*                          HDF5AttrIterate()                           */
 /************************************************************************/
 
-herr_t HDF5AttrIterate( hid_t hH5ObjID, 
-			const char *AttrName, 
-			void *pDS )
+herr_t HDF5AttrIterate( hid_t hH5ObjID,
+                        const char *pszAttrName,
+                        void *pDS )
 {
     hid_t           hAttrID;
     hid_t           hAttrTypeID;
@@ -600,142 +606,198 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
 
     char           *szData = NULL;
     hsize_t        nSize[64];
-    unsigned int            nAttrElmts;
+    unsigned int   nAttrElmts;
     hsize_t        nAttrSize;
     hsize_t        i;
     void           *buf = NULL;
-    unsigned int             nAttrDims;
+    unsigned int   nAttrDims;
 
+    char          **papszTokens;
 
     HDF5Dataset    *poDS;
-    char           *szTemp = (char*) CPLMalloc( 8192 );
+    CPLString       osKey;
     char           *szValue = NULL;
 
     poDS = (HDF5Dataset *) pDS;
-    sprintf( szTemp, "%s:%s", poDS->poH5CurrentObject->pszName, 
-	     AttrName );
 
-    hAttrID          = H5Aopen_name( hH5ObjID, AttrName );
+    // Convert "/" into "_" for the path component
+    const char* pszPath = poDS->poH5CurrentObject->pszUnderscorePath;
+    if(pszPath != NULL && strlen(pszPath) > 0)
+    {
+        papszTokens = CSLTokenizeString2( pszPath, "/", CSLT_HONOURSTRINGS );
+
+        for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
+        {
+            if( i != 0)
+                osKey += '_';
+            osKey += papszTokens[i];
+        }
+        CSLDestroy( papszTokens );
+    }
+
+    // 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 )
+    {
+        if(!osKey.empty())
+            osKey += '_';
+        osKey += papszTokens[i];
+    }
+    CSLDestroy( papszTokens );
+
+    hAttrID          = H5Aopen_name( hH5ObjID, pszAttrName );
     hAttrTypeID      = H5Aget_type( hAttrID );
     hAttrNativeType  = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
     hAttrSpace       = H5Aget_space( hAttrID );
     nAttrDims        = H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
 
-    if( H5Tget_class( hAttrNativeType ) == H5T_STRING ) {
-        nAttrSize = H5Aget_storage_size( hAttrID );
-	szData = (char*) CPLMalloc(nAttrSize+1);
-	szValue = (char*) CPLMalloc(nAttrSize+1);
-	H5Aread( hAttrID, hAttrNativeType, szData  );
-	szData[nAttrSize]='\0';
-	sprintf( szValue, "%s", szData );
+    nAttrElmts = 1;
+    for( i=0; i < nAttrDims; i++ ) {
+        nAttrElmts *= (int) nSize[i];
+    }
 
+    if( H5Tget_class( hAttrNativeType ) == H5T_STRING )
+    {
+        if ( H5Tis_variable_str(hAttrNativeType) )
+        {
+            char** papszStrings;
+            papszStrings = (char**) CPLMalloc( nAttrElmts * sizeof(char*) );
+
+            // Read the values
+            H5Aread( hAttrID, hAttrNativeType, papszStrings );
+
+            // Concatenate all values as one string (separated by a space)
+            CPLString osVal = papszStrings[0];
+            for( i=1; i < nAttrElmts; i++ ) {
+                osVal += " ";
+                osVal += papszStrings[i];
+            }
+
+            szValue = (char*) CPLMalloc(osVal.length() + 1);
+            strcpy( szValue, osVal.c_str() );
+
+            H5Dvlen_reclaim( hAttrNativeType, hAttrSpace, H5P_DEFAULT,
+                             papszStrings );
+            CPLFree( papszStrings );
+        }
+        else
+        {
+            nAttrSize = H5Aget_storage_size( hAttrID );
+            szValue = (char*) CPLMalloc((size_t) (nAttrSize+1));
+            H5Aread( hAttrID, hAttrNativeType, szValue );
+            szValue[nAttrSize] = '\0';
+        }
     }
     else {
-	nAttrElmts = 1;
-	for( i=0; i < nAttrDims; i++ ) {
-	    nAttrElmts *= nSize[i];
-	}
-	if( nAttrElmts > 0 ){
-	    buf = (void *) CPLMalloc( nAttrElmts*
-				      H5Tget_size( hAttrNativeType ));
-	    szData = (char*) CPLMalloc( 8192 );
-	    szValue = (char*) CPLMalloc( MAX_METADATA_LEN );
-	    szData[0]='\0';
-	    szValue[0] ='\0';
-	    H5Aread( hAttrID, hAttrNativeType, buf );
-	}
-	if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType ) ){
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%c ", ((char *) buf)[i]);
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_UCHAR,  hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%c", ((char *) buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_SHORT,  hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%d ", ((short *) buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_USHORT, hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%ud ", ((unsigned short *) buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_INT,    hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%d ", ((int *) buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_UINT,   hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%ud ", ((unsigned int *) buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_LONG,   hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%ld ", ((long *)buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_ULONG,  hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%ld ", ((unsigned long *)buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_FLOAT,  hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%.8g ",  ((float *)buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	else if( H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) ) {
-	    for( i=0; i < nAttrElmts; i++ ) {
-		sprintf( szData, "%.15g ",  ((double *)buf)[i] );
-		if( CPLStrlcat(szValue,szData,MAX_METADATA_LEN) >= MAX_METADATA_LEN )
-		    CPLError( CE_Warning, CPLE_OutOfMemory,
-			      "Header data too long. Truncated\n");
-	    }
-	}
-	CPLFree( buf );
+        if( nAttrElmts > 0 ) {
+            buf = (void *) CPLMalloc( nAttrElmts*
+                          H5Tget_size( hAttrNativeType ));
+            szData = (char*) CPLMalloc( 8192 );
+            szValue = (char*) CPLMalloc( MAX_METADATA_LEN );
+            szData[0] = '\0';
+            szValue[0] ='\0';
+            H5Aread( hAttrID, hAttrNativeType, buf );
+        }
+        if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType ) ){
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%c ", ((char *) buf)[i]);
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_UCHAR,  hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%c", ((char *) buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_SHORT,  hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%d ", ((short *) buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_USHORT, hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%ud ", ((unsigned short *) buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_INT,    hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%d ", ((int *) buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_UINT,   hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%ud ", ((unsigned int *) buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_LONG,   hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%ld ", ((long *)buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_ULONG,  hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%ld ", ((unsigned long *)buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_FLOAT,  hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%.8g ",  ((float *)buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        else if( H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) ) {
+            for( i=0; i < nAttrElmts; i++ ) {
+                sprintf( szData, "%.15g ",  ((double *)buf)[i] );
+                if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
+                                                            MAX_METADATA_LEN )
+                    CPLError( CE_Warning, CPLE_OutOfMemory,
+                              "Header data too long. Truncated\n");
+            }
+        }
+        CPLFree( buf );
 
     }
     H5Sclose(hAttrSpace);
     H5Tclose(hAttrNativeType);
     H5Tclose(hAttrTypeID);
     H5Aclose( hAttrID );
-    //printf( "%s = %s\n",szTemp, szValue );
-    poDS->papszMetadata =
-	CSLSetNameValue( poDS->papszMetadata, szTemp,  
-			 CPLSPrintf( "%s", szValue ) );
-    CPLFree( szTemp );
+    poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata, osKey, szValue);
+
     CPLFree( szData );
     CPLFree( szValue );
 
@@ -747,7 +809,7 @@ herr_t HDF5AttrIterate( hid_t hH5ObjID,
 /************************************************************************/
 CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
 {
-    hid_t	hGroupID;		/* identifier of group */
+    hid_t       hGroupID;       /* identifier of group */
     hid_t       hDatasetID;
     int         nbAttrs;
     herr_t      ret;
@@ -763,34 +825,34 @@ CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
     nbAttrs = poH5Object->nbAttrs;
 
     if( poH5Object->pszPath == NULL || EQUAL(poH5Object->pszPath, "" ) )
-	return CE_None;
+        return CE_None;
 
     switch( nType ) {
 
     case H5G_GROUP:
 
-	hGroupID = H5Gopen( hHDF5, poH5Object->pszPath );
-	if( nbAttrs > 0 ) { 
-	    ret = H5Aiterate( hGroupID, NULL, 
-			      HDF5AttrIterate, (void *)poDS  );
-	    ret = H5Gclose( hGroupID );
-	}
+        hGroupID = H5Gopen( hHDF5, poH5Object->pszPath );
+        if( nbAttrs > 0 ) {
+            ret = H5Aiterate( hGroupID, NULL,
+                              HDF5AttrIterate, (void *)poDS  );
+            ret = H5Gclose( hGroupID );
+        }
 
-	break;
+        break;
 
     case H5G_DATASET:
 
-	hDatasetID =  H5Dopen(hHDF5, poH5Object->pszPath );
+        hDatasetID =  H5Dopen(hHDF5, poH5Object->pszPath );
 
-	if( nbAttrs > 0 ) { 
-	    ret = H5Aiterate( hDatasetID, NULL, 
-			      HDF5AttrIterate, (void *)poDS );
-	    ret = H5Dclose( hDatasetID );
-	}
-	break;
+        if( nbAttrs > 0 ) {
+            ret = H5Aiterate( hDatasetID, NULL,
+                              HDF5AttrIterate, (void *)poDS );
+            ret = H5Dclose( hDatasetID );
+        }
+        break;
 
     default:
-	break;
+        break;
     }
 
     return CE_None;
@@ -804,32 +866,33 @@ CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
 HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjectsbyPath
     ( HDF5GroupObjects *poH5Objects, const char* pszDatasetPath )
 {
-    int i;
+    unsigned i;
     HDF5Dataset *poDS;
     HDF5GroupObjects *poObjectsFound;
     poDS=this;
-    
+
     if( poH5Objects->nType == H5G_DATASET &&
-       EQUAL( poH5Objects->pszUnderscorePath,pszDatasetPath ) )	{
-	    /*      printf("found it! %ld\n",(long) poH5Objects);*/
-	    return( poH5Objects );
-	}
-    
+        EQUAL( poH5Objects->pszUnderscorePath,pszDatasetPath ) ) {
+
+        /*      printf("found it! %ld\n",(long) poH5Objects);*/
+        return( poH5Objects );
+    }
+
     if( poH5Objects->nbObjs >0 )
-	for( i=0; i <poH5Objects->nbObjs; i++ )   {
-	    poObjectsFound=
-		poDS->HDF5FindDatasetObjectsbyPath( poH5Objects->poHchild+i, 
-						    pszDatasetPath );
+        for( i=0; i <poH5Objects->nbObjs; i++ )   {
+            poObjectsFound=
+            poDS->HDF5FindDatasetObjectsbyPath( poH5Objects->poHchild+i,
+                                                pszDatasetPath );
 /* -------------------------------------------------------------------- */
 /*      Is this our dataset??                                           */
 /* -------------------------------------------------------------------- */
-	    if( poObjectsFound != NULL ) return( poObjectsFound );
-	}
+            if( poObjectsFound != NULL ) return( poObjectsFound );
+        }
 /* -------------------------------------------------------------------- */
 /*      Dataset has not been found!                                     */
 /* -------------------------------------------------------------------- */
     return( NULL );
-    
+
 }
 
 
@@ -840,33 +903,34 @@ HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjectsbyPath
 HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjects
     ( HDF5GroupObjects *poH5Objects, const char* pszDatasetName )
 {
-    int i;
+    unsigned i;
     HDF5Dataset *poDS;
     HDF5GroupObjects *poObjectsFound;
     poDS=this;
-    
+
     if( poH5Objects->nType == H5G_DATASET &&
-       EQUAL( poH5Objects->pszName,pszDatasetName ) )	{
-	    /*      printf("found it! %ld\n",(long) poH5Objects);*/
-	    return( poH5Objects );
-	}
-    
+        EQUAL( poH5Objects->pszName,pszDatasetName ) ) {
+
+        /*      printf("found it! %ld\n",(long) poH5Objects);*/
+        return( poH5Objects );
+    }
+
     if( poH5Objects->nbObjs >0 )
-	for( i=0; i <poH5Objects->nbObjs; i++ )   {
-	    poObjectsFound=
-		poDS->HDF5FindDatasetObjects( poH5Objects->poHchild+i, 
-					      pszDatasetName );
+        for( i=0; i <poH5Objects->nbObjs; i++ )   {
+            poObjectsFound=
+            poDS->HDF5FindDatasetObjects( poH5Objects->poHchild+i,
+                                          pszDatasetName );
 /* -------------------------------------------------------------------- */
 /*      Is this our dataset??                                           */
 /* -------------------------------------------------------------------- */
-	    if( poObjectsFound != NULL ) return( poObjectsFound );
-	    
-	}
+            if( poObjectsFound != NULL ) return( poObjectsFound );
+
+        }
 /* -------------------------------------------------------------------- */
 /*      Dataset has not been found!                                     */
 /* -------------------------------------------------------------------- */
     return( NULL );
-    
+
 }
 
 
@@ -878,74 +942,76 @@ HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjects
 CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
 					  int bSUBDATASET )
 {
-    int i;
     char szTemp[8192];
     char szDim[8192];
     HDF5Dataset *poDS;
     poDS=this;
-    
-    if( poRootGroup->nbObjs >0 )  
-	for( i=0; i < poRootGroup->nbObjs; i++ ) {
-	    poDS->HDF5ListGroupObjects( poRootGroup->poHchild+i, bSUBDATASET );
-	}
-    
+
+    if( poRootGroup->nbObjs >0 )
+        for( hsize_t i=0; i < poRootGroup->nbObjs; i++ ) {
+            poDS->HDF5ListGroupObjects( poRootGroup->poHchild+i, bSUBDATASET );
+        }
+
 
     if( poRootGroup->nType == H5G_GROUP ) {
-	CreateMetadata( poRootGroup, H5G_GROUP );
+        CreateMetadata( poRootGroup, H5G_GROUP );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create Sub dataset list                                         */
 /* -------------------------------------------------------------------- */
-    if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET 
+    if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET
         && poDS->GetDataType( poRootGroup->native ) == GDT_Unknown )
     {
-        CPLDebug( "HDF5", "Skipping unsupported %s of type %s", 
-                  poRootGroup->pszUnderscorePath, 
+        CPLDebug( "HDF5", "Skipping unsupported %s of type %s",
+                  poRootGroup->pszUnderscorePath,
                   poDS->GetDataTypeName( poRootGroup->native ) );
     }
-    else if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET ) 
+    else if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET )
     {
-	szDim[0]='\0';
-	switch( poRootGroup->nRank ) {
-	case 3: 
-	    sprintf( szTemp,"%dx%dx%d",
-		    (int)poRootGroup->paDims[0],
-		    (int)poRootGroup->paDims[1],
-		    (int)poRootGroup->paDims[2] );
-	    break;
-	    
-  	case 2: 
-	    sprintf( szTemp,"%dx%d",
-		    (int)poRootGroup->paDims[0],
-		    (int)poRootGroup->paDims[1] );
-	  break;
+        CreateMetadata( poRootGroup, H5G_DATASET );
+
+        szDim[0]='\0';
+        switch( poRootGroup->nRank ) {
+        case 3:
+            sprintf( szTemp,"%dx%dx%d",
+                (int)poRootGroup->paDims[0],
+                (int)poRootGroup->paDims[1],
+                (int)poRootGroup->paDims[2] );
+            break;
+
+        case 2:
+            sprintf( szTemp,"%dx%d",
+                (int)poRootGroup->paDims[0],
+                (int)poRootGroup->paDims[1] );
+            break;
+
         default:
-	    return CE_None;
-	    
-	}
-	strcat( szDim,szTemp );
-	
-	sprintf( szTemp, "SUBDATASET_%d_NAME", ++(poDS->nSubDataCount) );
-
-	poDS->papszSubDatasets =
-	    CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-			    CPLSPrintf( "HDF5:\"%s\":%s",
-					poDS->GetDescription(),
-					poRootGroup->pszUnderscorePath ) );
-	
-	sprintf(  szTemp, "SUBDATASET_%d_DESC", poDS->nSubDataCount );
-	
-	poDS->papszSubDatasets =
-	    CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-			    CPLSPrintf( "[%s] %s (%s)", 
-					szDim,
-					poRootGroup->pszUnderscorePath,
-					poDS->GetDataTypeName
-					( poRootGroup->native ) ) );
-
-    }
-    
+            return CE_None;
+
+        }
+        strcat( szDim,szTemp );
+
+        sprintf( szTemp, "SUBDATASET_%d_NAME", ++(poDS->nSubDataCount) );
+
+        poDS->papszSubDatasets =
+            CSLSetNameValue( poDS->papszSubDatasets, szTemp,
+                    CPLSPrintf( "HDF5:\"%s\":%s",
+                        poDS->GetDescription(),
+                        poRootGroup->pszUnderscorePath ) );
+
+        sprintf(  szTemp, "SUBDATASET_%d_DESC", poDS->nSubDataCount );
+
+        poDS->papszSubDatasets =
+            CSLSetNameValue( poDS->papszSubDatasets, szTemp,
+                    CPLSPrintf( "[%s] %s (%s)",
+                        szDim,
+                        poRootGroup->pszUnderscorePath,
+                        poDS->GetDataTypeName
+                        ( poRootGroup->native ) ) );
+
+    }
+
     return CE_None;
 }
 
@@ -955,11 +1021,11 @@ CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
 /************************************************************************/
 CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
 {
-    
+
     HDF5GroupObjects *poRootGroup;
-    
+
     poRootGroup = (HDF5GroupObjects*) CPLCalloc(sizeof(HDF5GroupObjects), 1);
-    
+
     poH5RootGroup=poRootGroup;
     poRootGroup->pszName   = CPLStrdup( "/" );
     poRootGroup->nType     = H5G_GROUP;
@@ -968,35 +1034,35 @@ CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
     poRootGroup->pszUnderscorePath = NULL;
 
     if( hHDF5 < 0 )  {
-	printf( "hHDF5 <0!!\n" );
-	return CE_None;
+        printf( "hHDF5 <0!!\n" );
+        return CE_None;
     }
-    
+
     H5G_stat_t  oStatbuf;
     if( H5Gget_objinfo( hHDF5, "/", FALSE, &oStatbuf ) < 0  )
-	return CE_Failure;
+        return CE_Failure;
     poRootGroup->objno[0] = oStatbuf.objno[0];
     poRootGroup->objno[1] = oStatbuf.objno[1];
-    
-    hGroupID = H5Gopen( hHDF5, "/" ); 
+
+    hGroupID = H5Gopen( hHDF5, "/" );
     if( hGroupID < 0 ){
-	printf( "hGroupID <0!!\n" );
-	return CE_None;
+        printf( "hGroupID <0!!\n" );
+        return CE_None;
     }
-    
+
     poRootGroup->nbAttrs = H5Aget_num_attrs( hGroupID );
 
-    H5Gget_num_objs( hGroupID, (hsize_t *) &( poRootGroup->nbObjs ) );
-    
+    H5Gget_num_objs( hGroupID, &( poRootGroup->nbObjs ) );
+
     if( poRootGroup->nbObjs > 0 ) {
-	poRootGroup->poHchild = ( HDF5GroupObjects * ) 
-	    CPLCalloc( poRootGroup->nbObjs,
-		sizeof( HDF5GroupObjects ) );
-	H5Giterate( hGroupID, "/", NULL, 
-		   HDF5CreateGroupObjs, (void *)poRootGroup );
+        poRootGroup->poHchild = ( HDF5GroupObjects * )
+            CPLCalloc( poRootGroup->nbObjs,
+            sizeof( HDF5GroupObjects ) );
+        H5Giterate( hGroupID, "/", NULL,
+               HDF5CreateGroupObjs, (void *)poRootGroup );
     }
     else poRootGroup->poHchild = NULL;
-    
+
     HDF5ListGroupObjects( poRootGroup, bSUBDATASET );
     return CE_None;
 }
diff --git a/frmts/hdf5/hdf5dataset.h b/frmts/hdf5/hdf5dataset.h
index 1a63945..41f3fda 100644
--- a/frmts/hdf5/hdf5dataset.h
+++ b/frmts/hdf5/hdf5dataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5dataset.h 20115 2010-07-22 13:52:05Z dron $
+ * $Id: hdf5dataset.h 23035 2011-09-04 10:28:41Z antonio $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Header file for HDF5 datasets reader.
@@ -34,14 +34,14 @@
 #include "cpl_list.h"
 
 typedef struct HDF5GroupObjects {
-  char	       *pszName;
+  char         *pszName;
   char         *pszPath;
   char         *pszUnderscorePath;
   char         *pszTemp;
-  int		nType;
-  int		nIndex;
-  int		nbObjs;
-  int		nbAttrs;
+  int           nType;
+  int           nIndex;
+  hsize_t       nbObjs;
+  int           nbAttrs;
   int           nRank;
   hsize_t       *paDims;
   hid_t          native;
@@ -56,14 +56,14 @@ herr_t HDF5CreateGroupObjs(hid_t, const char *,void *);
 
 /************************************************************************/
 /* ==================================================================== */
-/*				HDF5Dataset				*/
+/*                              HDF5Dataset                             */
 /* ==================================================================== */
 /************************************************************************/
 class HDF5Dataset : public GDALPamDataset
 {
   protected:
 
-  hid_t            hHDF5;     
+  hid_t            hHDF5;
   hid_t            hDatasetID;
   hid_t            hGroupID; /* H handler interface */
   char             **papszSubDatasets;
@@ -82,18 +82,18 @@ class HDF5Dataset : public GDALPamDataset
   HDF5GroupObjects* HDF5FindDatasetObjectsbyPath( HDF5GroupObjects *, const char * );
   char* CreatePath(HDF5GroupObjects *);
   void DestroyH5Objects(HDF5GroupObjects *);
- 
+
   GDALDataType GetDataType(hid_t);
   const char * GetDataTypeName(hid_t);
 
   public:
 
   char	           **papszMetadata;
-  HDF5GroupObjects *poH5CurrentObject; 
+  HDF5GroupObjects *poH5CurrentObject;
 
   HDF5Dataset();
   ~HDF5Dataset();
-    
+
   static GDALDataset *Open(GDALOpenInfo *);
   static int Identify(GDALOpenInfo *);
 };
diff --git a/frmts/hdf5/hdf5imagedataset.cpp b/frmts/hdf5/hdf5imagedataset.cpp
index eff7442..01148ce 100644
--- a/frmts/hdf5/hdf5imagedataset.cpp
+++ b/frmts/hdf5/hdf5imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5imagedataset.cpp 22341 2011-05-09 16:54:11Z warmerdam $
+ * $Id: hdf5imagedataset.cpp 23068 2011-09-06 20:50:23Z antonio $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read subdatasets of HDF5 file.
@@ -37,10 +37,10 @@
 #include "hdf5dataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hdf5imagedataset.cpp 22341 2011-05-09 16:54:11Z warmerdam $");
+CPL_CVSID("$Id: hdf5imagedataset.cpp 23068 2011-09-06 20:50:23Z antonio $");
 
 CPL_C_START
-void    GDALRegister_HDF5Image(void);
+void GDALRegister_HDF5Image(void);
 CPL_C_END
 
 /* release 1.6.3 or 1.6.4 changed the type of count in some api functions */
@@ -69,7 +69,7 @@ class HDF5ImageDataset : public HDF5Dataset
     hid_t        dataset_id;
     hid_t        dataspace_id;
     hsize_t      size;
-    int          address;
+    haddr_t      address;
     hid_t        datatype;
     hid_t        native;
     H5T_class_t  clas;
@@ -77,7 +77,7 @@ class HDF5ImageDataset : public HDF5Dataset
 public:
     HDF5ImageDataset();
     ~HDF5ImageDataset();
-    
+
     CPLErr CreateProjections( );
     static GDALDataset  *Open( GDALOpenInfo * );
     static int           Identify( GDALOpenInfo * );
@@ -85,8 +85,8 @@ public:
     const char          *GetProjectionRef();
     virtual int         GetGCPCount( );
     virtual const char  *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs( ); 
-    
+    virtual const GDAL_GCP *GetGCPs( );
+
 };
 
 /************************************************************************/
@@ -122,10 +122,10 @@ HDF5ImageDataset::~HDF5ImageDataset( )
     CPLFree(pszGCPProjection);
 
     if( dims )
-	CPLFree( dims );
+        CPLFree( dims );
 
     if( maxdims )
-	CPLFree( maxdims );
+        CPLFree( maxdims );
 
     if( nGCPCount > 0 )
     {
@@ -135,7 +135,7 @@ HDF5ImageDataset::~HDF5ImageDataset( )
                 CPLFree( pasGCPList[i].pszId );
             if( pasGCPList[i].pszInfo )
                 CPLFree( pasGCPList[i].pszInfo );
-	}
+        }
 
         CPLFree( pasGCPList );
     }
@@ -155,13 +155,13 @@ class HDF5ImageRasterBand : public GDALPamRasterBand
     char        *pszFilename;
 
 public:
-  
+
     HDF5ImageRasterBand( HDF5ImageDataset *, int, GDALDataType );
     ~HDF5ImageRasterBand();
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual double	    GetNoDataValue( int * ); 
-    virtual CPLErr	    SetNoDataValue( double );
+    virtual CPLErr      IReadBlock( int, int, void * );
+    virtual double      GetNoDataValue( int * );
+    virtual CPLErr      SetNoDataValue( double );
     /*  virtual CPLErr          IWriteBlock( int, int, void * ); */
 };
 
@@ -198,7 +198,7 @@ HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDS, int nBand,
     poDS->papszMetadata = NULL;
 
     if( poDS->poH5Objects->nType == H5G_DATASET ) {
-	poDS->CreateMetadata( poDS->poH5Objects, H5G_DATASET );
+        poDS->CreateMetadata( poDS->poH5Objects, H5G_DATASET );
     }
 
 /* -------------------------------------------------------------------- */
@@ -211,7 +211,7 @@ HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDS, int nBand,
     poDS->papszMetadata = CSLDuplicate( papszMetaGlobal );
     CSLDestroy( papszMetaGlobal );
 
-/* check for chunksize and set it as the blocksize (optimizes read) */
+    /* check for chunksize and set it as the blocksize (optimizes read) */
     hid_t listid = H5Dget_create_plist(((HDF5ImageDataset * )poDS)->dataset_id);
     if (listid>0)
     {
@@ -219,8 +219,8 @@ HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDS, int nBand,
         {
             hsize_t panChunkDims[3];
             int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
-            nBlockXSize   = panChunkDims[nDimSize-1];
-            nBlockYSize   = panChunkDims[nDimSize-2];
+            nBlockXSize   = (int) panChunkDims[nDimSize-1];
+            nBlockYSize   = (int) panChunkDims[nDimSize-2];
         }
         H5Pclose(listid);
     }
@@ -237,7 +237,7 @@ double HDF5ImageRasterBand::GetNoDataValue( int * pbSuccess )
     {
         if( pbSuccess )
             *pbSuccess = bNoDataSet;
-        
+
         return dfNoDataValue;
     }
     else
@@ -271,21 +271,21 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     hsize_t     rank;
 
     HDF5ImageDataset    *poGDS = ( HDF5ImageDataset * ) poDS;
-   
+
     if( poGDS->eAccess == GA_Update ) {
-	memset( pImage, 0,
-		nBlockXSize * nBlockYSize * 
-		GDALGetDataTypeSize( eDataType )/8 );
-	return CE_None;
+        memset( pImage, 0,
+            nBlockXSize * nBlockYSize *
+            GDALGetDataTypeSize( eDataType )/8 );
+        return CE_None;
     }
 
     rank=2;
 
     if( poGDS->ndims == 3 ){
-	rank=3;
-	offset[0]   = nBand-1;
-	count[0]    = 1;
-	col_dims[0] = 1;
+        rank=3;
+        offset[0]   = nBand-1;
+        count[0]    = 1;
+        col_dims[0] = 1;
     }
 
     offset[poGDS->ndims - 2] = nBlockYOff*nBlockYSize;
@@ -307,17 +307,17 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Select block from file space                                    */
 /* -------------------------------------------------------------------- */
-    status =  H5Sselect_hyperslab( poGDS->dataspace_id, 
-				  H5S_SELECT_SET, 
-				  offset, NULL, 
-				  count, NULL );
-   
+    status =  H5Sselect_hyperslab( poGDS->dataspace_id,
+                                   H5S_SELECT_SET,
+                                   offset, NULL,
+                                   count, NULL );
+
 /* -------------------------------------------------------------------- */
 /*      Create memory space to receive the data                         */
 /* -------------------------------------------------------------------- */
     col_dims[poGDS->ndims-2]=nBlockYSize;
     col_dims[poGDS->ndims-1]=nBlockXSize;
-    memspace = H5Screate_simple( rank, col_dims, NULL );
+    memspace = H5Screate_simple( (int) rank, col_dims, NULL );
     H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
     status =  H5Sselect_hyperslab(memspace,
                                   H5S_SELECT_SET,
@@ -325,11 +325,13 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   count, NULL);
 
     status = H5Dread ( poGDS->dataset_id,
-		      poGDS->native, 
-		      memspace,
-		      poGDS->dataspace_id,
-		      H5P_DEFAULT, 
-		      pImage );
+                       poGDS->native,
+                       memspace,
+                       poGDS->dataspace_id,
+                       H5P_DEFAULT,
+                       pImage );
+
+    H5Sclose( memspace );
 
     return CE_None;
 }
@@ -342,7 +344,7 @@ int HDF5ImageDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
     if(!EQUALN( poOpenInfo->pszFilename, "HDF5:", 5 ) )
-	return FALSE;
+        return FALSE;
     else
         return TRUE;
 }
@@ -358,26 +360,26 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if(!EQUALN( poOpenInfo->pszFilename, "HDF5:", 5 ) ||
         strlen(poOpenInfo->pszFilename) > sizeof(szFilename) - 3 )
-	return NULL;
-    
+        return NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The HDF5ImageDataset driver does not support update access to existing"
                   " datasets.\n" );
         return NULL;
     }
-    
+
     poDS = new HDF5ImageDataset();
 
     /* -------------------------------------------------------------------- */
     /*      Create a corresponding GDALDataset.                             */
     /* -------------------------------------------------------------------- */
     /* printf("poOpenInfo->pszFilename %s\n",poOpenInfo->pszFilename); */
-    char **papszName = 
+    char **papszName =
         CSLTokenizeString2(  poOpenInfo->pszFilename,
                              ":", CSLT_HONOURSTRINGS|CSLT_PRESERVEESCAPES );
 
@@ -389,17 +391,17 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     poDS->SetDescription( poOpenInfo->pszFilename );
-  
+
     /* -------------------------------------------------------------------- */
     /*    Check for drive name in windows HDF5:"D:\...                      */
     /* -------------------------------------------------------------------- */
     strcpy(szFilename, papszName[1]);
 
-    if( strlen(papszName[1]) == 1 && papszName[3] != NULL ) 
+    if( strlen(papszName[1]) == 1 && papszName[3] != NULL )
     {
-	strcat(szFilename, ":");
-	strcat(szFilename, papszName[2]);
-        
+        strcat(szFilename, ":");
+        strcat(szFilename, papszName[2]);
+
         poDS->SetSubdatasetName( papszName[3] );
     }
     else
@@ -419,19 +421,21 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     /*      Try opening the dataset.                                        */
     /* -------------------------------------------------------------------- */
     poDS->hHDF5 = H5Fopen(szFilename,
-			  H5F_ACC_RDONLY, 
-			  H5P_DEFAULT );
-  
-    if( poDS->hHDF5 < 0 )  {
+                          H5F_ACC_RDONLY,
+                          H5P_DEFAULT );
+
+    if( poDS->hHDF5 < 0 )
+    {
         delete poDS;
-	return NULL;
+        return NULL;
     }
-  
-    poDS->hGroupID = H5Gopen( poDS->hHDF5, "/" ); 
-    if( poDS->hGroupID < 0 ){
-	poDS->bIsHDFEOS=false;
+
+    poDS->hGroupID = H5Gopen( poDS->hHDF5, "/" );
+    if( poDS->hGroupID < 0 )
+    {
+        poDS->bIsHDFEOS=false;
         delete poDS;
-	return NULL;
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -439,52 +443,51 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->bIsHDFEOS=TRUE;
     poDS->ReadGlobalAttributes( FALSE );
-  
+
 /* -------------------------------------------------------------------- */
 /*      Create HDF5 Data Hierarchy in a link list                       */
 /* -------------------------------------------------------------------- */
-    poDS->poH5Objects = 
-	poDS->HDF5FindDatasetObjectsbyPath( poDS->poH5RootGroup, 
+    poDS->poH5Objects =
+        poDS->HDF5FindDatasetObjectsbyPath( poDS->poH5RootGroup,
                                             (char *)poDS->GetSubdatasetName() );
 
     if( poDS->poH5Objects == NULL ) {
-	return NULL;
+        delete poDS;
+        return NULL;
     }
 /* -------------------------------------------------------------------- */
 /*      Retrieve HDF5 data information                                  */
 /* -------------------------------------------------------------------- */
-    poDS->dataset_id   = H5Dopen( poDS->hHDF5,poDS->poH5Objects->pszPath ); 
-    poDS->dataspace_id = H5Dget_space( poDS->dataset_id );                       
+    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 );
-    poDS->dims         = ( hsize_t * )CPLCalloc( poDS->ndims, 
-						 sizeof( hsize_t ) );
-    poDS->maxdims      = ( hsize_t * )CPLCalloc( poDS->ndims, 
-						 sizeof( hsize_t ) );
+    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,
-						   poDS->dims,
-						   poDS->maxdims );
+                                                    poDS->dims,
+                                                    poDS->maxdims );
     poDS->datatype = H5Dget_type( poDS->dataset_id );
     poDS->clas     = H5Tget_class( poDS->datatype );
     poDS->size     = H5Tget_size( poDS->datatype );
     poDS->address = H5Dget_offset( poDS->dataset_id );
     poDS->native  = H5Tget_native_type( poDS->datatype, H5T_DIR_ASCEND );
 
-    poDS->nRasterYSize=poDS->dims[poDS->ndims-2];   // Y
-    poDS->nRasterXSize=poDS->dims[poDS->ndims-1];   // X alway last
+    poDS->nRasterYSize=(int)poDS->dims[poDS->ndims-2];   // Y
+    poDS->nRasterXSize=(int)poDS->dims[poDS->ndims-1];   // X alway last
 
     poDS->nBands=1;
 
-    if( poDS->ndims == 3 ) poDS->nBands=poDS->dims[0];
+    if( poDS->ndims == 3 ) poDS->nBands=(int) poDS->dims[0];
 
 
     for(  i = 1; i <= poDS->nBands; i++ ) {
-	HDF5ImageRasterBand *poBand = 
-	    new HDF5ImageRasterBand( poDS, i, 
-				     poDS->GetDataType( poDS->native ) );
-	
-	poDS->SetBand( i, poBand );
-	if( poBand->bNoDataSet )
-		poBand->SetNoDataValue( 255 );
+        HDF5ImageRasterBand *poBand =
+            new HDF5ImageRasterBand( poDS, i,
+                            poDS->GetDataType( poDS->native ) );
+
+        poDS->SetBand( i, poBand );
+        if( poBand->bNoDataSet )
+            poBand->SetNoDataValue( 255 );
     }
 
     poDS->CreateProjections( );
@@ -512,18 +515,18 @@ void GDALRegister_HDF5Image( )
 
 {
     GDALDriver  *poDriver;
-    
+
     if (! GDAL_CHECK_VERSION("HDF5Image driver"))
         return;
 
     if(  GDALGetDriverByName( "HDF5Image" ) == NULL )
     {
         poDriver = new GDALDriver( );
-        
+
         poDriver->SetDescription( "HDF5Image" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
                                    "HDF5 Dataset" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                    "frmt_hdf5.html" );
         poDriver->pfnOpen = HDF5ImageDataset::Open;
         poDriver->pfnIdentify = HDF5ImageDataset::Identify;
@@ -561,82 +564,84 @@ CPLErr HDF5ImageDataset::CreateProjections()
 /* -------------------------------------------------------------------- */
     poH5Objects=HDF5FindDatasetObjects( poH5RootGroup,  "Latitude" );
     if( !poH5Objects ) {
-	return CE_None;
+        return CE_None;
     }
 /* -------------------------------------------------------------------- */
 /*      The Lattitude and Longitude arrays must have a rank of 2 to     */
 /*      retrieve GCPs.                                                  */
 /* -------------------------------------------------------------------- */
     if( poH5Objects->nRank != 2 ) {
-	return CE_None;
+        return CE_None;
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Retrieve HDF5 data information                                  */
 /* -------------------------------------------------------------------- */
-    LatitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath ); 
-    LatitudeDataspaceID = H5Dget_space( dataset_id );                       
+    LatitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
+    LatitudeDataspaceID = H5Dget_space( dataset_id );
 
     poH5Objects=HDF5FindDatasetObjects( poH5RootGroup, "Longitude" );
-    LongitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath ); 
-    LongitudeDataspaceID = H5Dget_space( dataset_id );                       
+    LongitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
+    LongitudeDataspaceID = H5Dget_space( dataset_id );
 
     if( ( LatitudeDatasetID > 0 ) && ( LongitudeDatasetID > 0) ) {
-	
-	Latitude         = ( float * ) CPLCalloc(  nRasterYSize*nRasterXSize, 
-						sizeof( float ) );
-	Longitude         = ( float * ) CPLCalloc( nRasterYSize*nRasterXSize, 
-						 sizeof( float ) );
-	memset( Latitude, 0, nRasterXSize*nRasterYSize*sizeof(  float ) );
-	memset( Longitude, 0, nRasterXSize*nRasterYSize*sizeof( float ) );
-	
-	H5Dread ( LatitudeDatasetID,
-		  H5T_NATIVE_FLOAT, 
-		  H5S_ALL,
-		  H5S_ALL,
-		  H5P_DEFAULT, 
-		  Latitude );
-	
-	H5Dread ( LongitudeDatasetID,
-		  H5T_NATIVE_FLOAT, 
-		  H5S_ALL,
-		  H5S_ALL,
-		  H5P_DEFAULT, 
-		  Longitude );
-	
-	oSRS.SetWellKnownGeogCS( "WGS84" );
+
+        Latitude         = ( float * ) CPLCalloc(  nRasterYSize*nRasterXSize,
+                            sizeof( float ) );
+        Longitude         = ( float * ) CPLCalloc( nRasterYSize*nRasterXSize,
+                            sizeof( float ) );
+        memset( Latitude, 0, nRasterXSize*nRasterYSize*sizeof(  float ) );
+        memset( Longitude, 0, nRasterXSize*nRasterYSize*sizeof( float ) );
+
+        H5Dread ( LatitudeDatasetID,
+            H5T_NATIVE_FLOAT,
+            H5S_ALL,
+            H5S_ALL,
+            H5P_DEFAULT,
+            Latitude );
+
+        H5Dread ( LongitudeDatasetID,
+            H5T_NATIVE_FLOAT,
+            H5S_ALL,
+            H5S_ALL,
+            H5P_DEFAULT,
+            Longitude );
+
+        oSRS.SetWellKnownGeogCS( "WGS84" );
         CPLFree(pszProjection);
         CPLFree(pszGCPProjection);
-	oSRS.exportToWkt( &pszProjection );
-	oSRS.exportToWkt( &pszGCPProjection );
-	
-/* -------------------------------------------------------------------- */
-/*  Fill the GCPs list.                                                 */
-/* -------------------------------------------------------------------- */
-	nGCPCount = nRasterYSize/nDeltaLat * nRasterXSize/nDeltaLon;
-
-	pasGCPList = ( GDAL_GCP * )
-	    CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) );
-	
-	GDALInitGCPs( nGCPCount, pasGCPList );
-	int k=0;
-
-	int nYLimit = ((int)nRasterYSize/nDeltaLat) * nDeltaLat;
-	int nXLimit = ((int)nRasterXSize/nDeltaLon) * nDeltaLon;
-	for( j = 0; j < nYLimit; j+=nDeltaLat ) {
-	    for( i = 0; i < nXLimit; i+=nDeltaLon ) {
-		int iGCP =  j * nRasterXSize + i;
-		pasGCPList[k].dfGCPX = ( double ) Longitude[iGCP]+180.0;
-		pasGCPList[k].dfGCPY = ( double ) Latitude[iGCP];
-		
-		pasGCPList[k].dfGCPPixel = i + 0.5;
-		pasGCPList[k++].dfGCPLine =  j + 0.5;
-		
-	    }
-	}
-	
-	CPLFree( Latitude );
-	CPLFree( Longitude );
+        oSRS.exportToWkt( &pszProjection );
+        oSRS.exportToWkt( &pszGCPProjection );
+
+    /* -------------------------------------------------------------------- */
+    /*  Fill the GCPs list.                                                 */
+    /* -------------------------------------------------------------------- */
+        nGCPCount = nRasterYSize/nDeltaLat * nRasterXSize/nDeltaLon;
+
+        pasGCPList = ( GDAL_GCP * )
+            CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) );
+
+        GDALInitGCPs( nGCPCount, pasGCPList );
+        int k=0;
+
+        int nYLimit = ((int)nRasterYSize/nDeltaLat) * nDeltaLat;
+        int nXLimit = ((int)nRasterXSize/nDeltaLon) * nDeltaLon;
+        for( j = 0; j < nYLimit; j+=nDeltaLat )
+        {
+            for( i = 0; i < nXLimit; i+=nDeltaLon )
+            {
+                int iGCP =  j * nRasterXSize + i;
+                pasGCPList[k].dfGCPX = ( double ) Longitude[iGCP]+180.0;
+                pasGCPList[k].dfGCPY = ( double ) Latitude[iGCP];
+
+                pasGCPList[k].dfGCPPixel = i + 0.5;
+                pasGCPList[k++].dfGCPLine =  j + 0.5;
+
+            }
+        }
+
+        CPLFree( Latitude );
+        CPLFree( Longitude );
     }
     return CE_None;
 
@@ -646,7 +651,7 @@ CPLErr HDF5ImageDataset::CreateProjections()
 /************************************************************************/
 
 const char *HDF5ImageDataset::GetProjectionRef( )
-    
+
 {
     if( pszProjection )
         return pszProjection;
@@ -659,7 +664,7 @@ const char *HDF5ImageDataset::GetProjectionRef( )
 /************************************************************************/
 
 int HDF5ImageDataset::GetGCPCount( )
-    
+
 {
     if( nGCPCount > 0 )
         return nGCPCount;
@@ -675,9 +680,9 @@ const char *HDF5ImageDataset::GetGCPProjection( )
 
 {
     if( nGCPCount > 0 )
-	return pszGCPProjection;
+        return pszGCPProjection;
     else
-	return GDALPamDataset::GetGCPProjection();
+        return GDALPamDataset::GetGCPProjection();
 }
 
 /************************************************************************/
@@ -691,8 +696,3 @@ const GDAL_GCP *HDF5ImageDataset::GetGCPs( )
     else
         return GDALPamDataset::GetGCPs();
 }
-
-
-
-
-
diff --git a/frmts/hf2/hf2dataset.cpp b/frmts/hf2/hf2dataset.cpp
index b560b25..d728d0c 100644
--- a/frmts/hf2/hf2dataset.cpp
+++ b/frmts/hf2/hf2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hf2dataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: hf2dataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  HF2 driver
  * Purpose:  GDALDataset driver for HF2/HFZ dataset.
@@ -31,7 +31,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hf2dataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: hf2dataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 CPL_C_START
 void    GDALRegister_HF2(void);
@@ -716,7 +716,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
 
     GDALDataType eSrcDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     GDALDataType eReqDT;
-    float fVertPres = 0.01;
+    float fVertPres = (float) 0.01;
     if (eSrcDT == GDT_Byte || eSrcDT == GDT_Int16)
     {
         fVertPres = 1;
@@ -736,12 +736,12 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
     const char* pszVerticalPrecision = CSLFetchNameValue(papszOptions, "VERTICAL_PRECISION");
     if (pszVerticalPrecision)
     {
-        fVertPres = CPLAtofM(pszVerticalPrecision);
+        fVertPres = (float) CPLAtofM(pszVerticalPrecision);
         if (fVertPres <= 0)
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Unsupported value for VERTICAL_PRECISION. Defaulting to 0.01");
-            fVertPres = 0.01;
+            fVertPres = (float) 0.01;
         }
         if (eReqDT == GDT_Int16 && fVertPres > 1)
             eReqDT = GDT_Float32;
@@ -846,9 +846,9 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
     WriteShort(fp, 0);
     WriteInt(fp, nXSize);
     WriteInt(fp, nYSize);
-    WriteShort(fp, nTileSize);
+    WriteShort(fp, (GInt16) nTileSize);
     WriteFloat(fp, fVertPres);
-    float fHorizScale = (fabs(adfGeoTransform[1]) + fabs(adfGeoTransform[5])) / 2;
+    float fHorizScale = (float) ((fabs(adfGeoTransform[1]) + fabs(adfGeoTransform[5])) / 2);
     WriteFloat(fp, fHorizScale);
     WriteInt(fp, nExtendedHeaderLen);
 
@@ -864,7 +864,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
         strcpy(szBlockName, "georef-extents");
         VSIFWriteL(szBlockName, 16, 1, fp);
         WriteInt(fp, 34);
-        WriteShort(fp, nExtentUnits);
+        WriteShort(fp, (GInt16) nExtentUnits);
         WriteDouble(fp, adfGeoTransform[0]);
         WriteDouble(fp, adfGeoTransform[0] + nXSize * adfGeoTransform[1]);
         WriteDouble(fp, adfGeoTransform[3] + nYSize * adfGeoTransform[5]);
@@ -877,7 +877,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
         strcpy(szBlockName, "georef-utm");
         VSIFWriteL(szBlockName, 16, 1, fp);
         WriteInt(fp, 2);
-        WriteShort(fp, (bNorth) ? nUTMZone : -nUTMZone);
+        WriteShort(fp, (GInt16) ((bNorth) ? nUTMZone : -nUTMZone));
     }
     if (nDatumCode != -2)
     {
@@ -886,7 +886,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
         strcpy(szBlockName, "georef-datum");
         VSIFWriteL(szBlockName, 16, 1, fp);
         WriteInt(fp, 2);
-        WriteShort(fp, nDatumCode);
+        WriteShort(fp, (GInt16) nDatumCode);
     }
     if (nEPSGCode != 0)
     {
@@ -895,7 +895,7 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
         strcpy(szBlockName, "georef-epsg-prj");
         VSIFWriteL(szBlockName, 16, 1, fp);
         WriteInt(fp, 2);
-        WriteShort(fp, nEPSGCode);
+        WriteShort(fp, (GInt16) nEPSGCode);
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/frmts/hfa/TODO_Projections.txt b/frmts/hfa/TODO_Projections.txt
new file mode 100644
index 0000000..7109051
--- /dev/null
+++ b/frmts/hfa/TODO_Projections.txt
@@ -0,0 +1,17 @@
+
+EPRJ_LAMBERT_CONFORMAL_CONIC:
+EPRJ_TRANSVERSE_MERCATOR:
+  1.6-esri has special handling for HARN / Wisconsin!
+
+EPRJ_HOTINE_OBLIQUE_MERCATOR:
+  What should we do if proParams[12] *not* > 0.0?
+
+EPRJ_KROVAK:
+  still issues around axis orientation - esri uses special parameters to 
+  represent this.  hfadataset.cpp is ignoring these parameters from .img.
+
+"Anchored LSR" (53) 
+  - was EPRJ_LOCAL in 1.6-esri.
+
+ 
+
diff --git a/frmts/hfa/hfa.h b/frmts/hfa/hfa.h
index 63a043f..a4fe34e 100644
--- a/frmts/hfa/hfa.h
+++ b/frmts/hfa/hfa.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfa.h 21432 2011-01-07 22:28:22Z warmerdam $
+ * $Id: hfa.h 21687 2011-02-12 03:59:15Z warmerdam $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Public (C callable) interface for the Erdas Imagine reading
@@ -306,11 +306,27 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 #define EPRJ_STEREOGRAPHIC_EXTENDED             50
 #define EPRJ_CASSINI                            51
 #define EPRJ_TWO_POINT_EQUIDISTANT              52
-#define EPRJ_STEREOGRAPHIC_NORTH_POLE           53
-#define EPRJ_STEREOGRAPHIC_SOUTH_POLE           54
+#define EPRJ_ANCHORED_LSR                       53
+#define EPRJ_KROVAK                             54
+#define EPRJ_DOUBLE_STEREOGRAPHIC               55
+#define EPRJ_AITOFF                             56
+#define EPRJ_CRASTER_PARABOLIC                  57
+#define EPRJ_CYLINDRICAL_EQUAL_AREA             58
+#define EPRJ_FLAT_POLAR_QUARTIC                 59
+#define EPRJ_TIMES                              60
+#define EPRJ_WINKEL_TRIPEL                      61
+#define EPRJ_HAMMER_AITOFF                      62
+#define EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE     63
+#define EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER           64
+#define EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER         65
+#define EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN 66
+#define EPRJ_LAMBERT_CONFORMAL_CONIC_1SP        67
+#define EPRJ_PSEUDO_MERCATOR                    68
+#define EPRJ_MERCATOR_VARIANT_A                 69
 
 #define EPRJ_EXTERNAL_RSO			"eprj_rso"
 #define EPRJ_EXTERNAL_NZMG                      "nzmg"
+#define EPRJ_EXTERNAL_INTEGERIZED_SINUSOIDAL    "isin"
 
 CPL_C_END
 
diff --git a/frmts/hfa/hfa_p.h b/frmts/hfa/hfa_p.h
index 873b3b7..c15db95 100644
--- a/frmts/hfa/hfa_p.h
+++ b/frmts/hfa/hfa_p.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfa_p.h 21476 2011-01-13 00:58:39Z warmerdam $
+ * $Id: hfa_p.h 23495 2011-12-08 00:16:33Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Private class declarations for the HFA classes used to read
@@ -273,7 +273,8 @@ public:
     HFAEntry	*GetNext();
     HFAEntry    *GetNamedChild( const char * );
     std::vector<HFAEntry*> FindChildren( const char *pszName, 
-                                         const char *pszType );
+                                         const char *pszType,
+                                         int nRecLevel = 0);
 
     GInt32	GetIntField( const char *, CPLErr * = NULL );
     double	GetDoubleField( const char *, CPLErr * = NULL );
@@ -352,6 +353,8 @@ class HFAField
 
 class HFAType
 {
+    int     bInCompleteDefn;
+
   public:
     int		nBytes;
     
diff --git a/frmts/hfa/hfaband.cpp b/frmts/hfa/hfaband.cpp
index 95debc1..c670bb2 100644
--- a/frmts/hfa/hfaband.cpp
+++ b/frmts/hfa/hfaband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaband.cpp 21672 2011-02-10 17:24:28Z warmerdam $
+ * $Id: hfaband.cpp 23498 2011-12-08 22:06:39Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFABand, for accessing one Eimg_Layer.
@@ -32,7 +32,7 @@
 
 /* include the compression code */
 
-CPL_CVSID("$Id: hfaband.cpp 21672 2011-02-10 17:24:28Z warmerdam $");
+CPL_CVSID("$Id: hfaband.cpp 23498 2011-12-08 22:06:39Z rouault $");
 
 /************************************************************************/
 /*                              HFABand()                               */
@@ -609,9 +609,9 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             }
             else
             {
-                printf( "nNumBits = %d\n", nNumBits );
-                CPLAssert( FALSE );
-                nRawValue = 0;
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Unsupported nNumBits value : %d", nNumBits);
+                return CE_Failure;
             }
 
 /* -------------------------------------------------------------------- */
@@ -829,7 +829,7 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             
             for( i = 0; i < nRepeatCount; i++ )
             {
-                CPLAssert( nDataValue < 256 );
+                //CPLAssert( nDataValue < 256 );
                 ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
             }
         }
@@ -848,7 +848,7 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             
             for( i = 0; i < nRepeatCount; i++ )
             {
-                CPLAssert( nDataValue < 256 );
+                //CPLAssert( nDataValue < 256 );
                 ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
             }
         }
@@ -894,7 +894,7 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
         {
             int		i;
 
-            CPLAssert( nDataValue == 0 || nDataValue == 1 );
+            //CPLAssert( nDataValue == 0 || nDataValue == 1 );
             
             if( nDataValue == 1 )
             {
@@ -917,7 +917,7 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
         {
             int		i;
 
-            CPLAssert( nDataValue >= 0 && nDataValue < 4 );
+            //CPLAssert( nDataValue >= 0 && nDataValue < 4 );
 
             for( i = 0; i < nRepeatCount; i++ )
             {
@@ -936,7 +936,7 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
         {
             int		i;
 
-            CPLAssert( nDataValue >= 0 && nDataValue < 16 );
+            //CPLAssert( nDataValue >= 0 && nDataValue < 16 );
             
             for( i = 0; i < nRepeatCount; i++ )
             {
@@ -974,15 +974,24 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
 void HFABand::NullBlock( void *pData )
 
 {
+    int nChunkSize = MAX(1,HFAGetDataTypeBits(nDataType)/8);
+    int nWords = nBlockXSize * nBlockYSize;
+
     if( !bNoDataSet )
-        memset( pData, 0, 
-                HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
+    {
+#ifdef ESRI_BUILD
+        // We want special defaulting for 1 bit data in ArcGIS.
+        if ( nDataType >= EPT_u2 )
+            memset( pData,   0, nChunkSize*nWords );
+        else
+            memset( pData, 255, nChunkSize*nWords );
+#else
+        memset( pData,   0, nChunkSize*nWords );
+#endif
+    }
     else
-            
     {
         double adfND[2];
-        int nChunkSize = MAX(1,HFAGetDataTypeBits(nDataType)/8);
-        int nWords = nBlockXSize * nBlockYSize;
         int i;
 
         switch( nDataType )
@@ -1362,6 +1371,12 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 
         /* create the compressor object */
         HFACompress compress( pData, nInBlockSize, nDataType );
+        if( compress.getCounts() == NULL ||
+            compress.getValues() == NULL)
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
+            return CE_Failure;
+        }
      
         /* compress the data */
         if( compress.compressBlock() )
diff --git a/frmts/hfa/hfacompress.cpp b/frmts/hfa/hfacompress.cpp
index 046e37b..3fcff76 100644
--- a/frmts/hfa/hfacompress.cpp
+++ b/frmts/hfa/hfacompress.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfacompress.cpp 17547 2009-08-21 10:02:01Z rouault $
+ * $Id: hfacompress.cpp 23624 2011-12-21 19:31:43Z rouault $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -30,7 +30,7 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfacompress.cpp 17547 2009-08-21 10:02:01Z rouault $");
+CPL_CVSID("$Id: hfacompress.cpp 23624 2011-12-21 19:31:43Z rouault $");
 
 HFACompress::HFACompress( void *pData, GUInt32 nBlockSize, int nDataType )
 {
@@ -42,10 +42,10 @@ HFACompress::HFACompress( void *pData, GUInt32 nBlockSize, int nDataType )
 
   /* Allocate some memory for the count and values - probably too big */
   /* About right for worst case scenario tho */
-  m_pCounts     = (GByte*)CPLMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
+  m_pCounts     = (GByte*)VSIMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
   m_nSizeCounts = 0;
   
-  m_pValues     = (GByte*)CPLMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
+  m_pValues     = (GByte*)VSIMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
   m_nSizeValues = 0;
   
   m_nMin        = 0;
@@ -168,14 +168,14 @@ void HFACompress::makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCoun
       lower 2 bits of the data it restricts what we can use */
   if( count < 0x40 )
   {
-    pCounter[0] = count;
+    pCounter[0] = (GByte) count;
     *pnSizeCount = 1;
   }
   else if( count < 0x8000 )
   {
     pCounter[1] = count & 0xff;
     count /= 256;
-    pCounter[0] = count | 0x40;
+    pCounter[0] = (GByte) (count | 0x40);
     *pnSizeCount = 2;
   }
   else if( count < 0x800000 )
@@ -184,7 +184,7 @@ void HFACompress::makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCoun
     count /= 256;
     pCounter[1] = count & 0xff;
     count /= 256;
-    pCounter[0] = count | 0x80;
+    pCounter[0] = (GByte) (count | 0x80);
     *pnSizeCount = 3;
   }
   else
@@ -195,7 +195,7 @@ void HFACompress::makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCoun
     count /= 256;
     pCounter[1] = count & 0xff;
     count /= 256;
-    pCounter[0] = count | 0xc0;
+    pCounter[0] = (GByte) (count | 0xc0);
     *pnSizeCount = 4;
   }
 }
diff --git a/frmts/hfa/hfadataset.cpp b/frmts/hfa/hfadataset.cpp
index dd82c73..9282819 100644
--- a/frmts/hfa/hfadataset.cpp
+++ b/frmts/hfa/hfadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfadataset.cpp 21764 2011-02-20 16:19:53Z warmerdam $
+ * $Id: hfadataset.cpp 23624 2011-12-21 19:31:43Z rouault $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -33,7 +33,7 @@
 #include "hfa_p.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hfadataset.cpp 21764 2011-02-20 16:19:53Z warmerdam $");
+CPL_CVSID("$Id: hfadataset.cpp 23624 2011-12-21 19:31:43Z rouault $");
 
 CPL_C_START
 void	GDALRegister_HFA(void);
@@ -59,6 +59,7 @@ static const char *apszDatumMap[] = {
     "NAD83", "North_American_Datum_1983",
     "WGS 84", "WGS_1984",
     "WGS 1972", "WGS_1972",
+    "GDA94", "Geocentric_Datum_of_Australia_1994",
     NULL, NULL
 };
 
@@ -357,6 +358,8 @@ class HFARasterBand : public GDALPamRasterBand
     void        ReadAuxMetadata();
     void        ReadHistogramMetadata();
     void        EstablishOverviews();
+    CPLErr      WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT );
+
 
     GDALRasterAttributeTable* ReadNamedRAT( const char *pszName );
 
@@ -431,9 +434,13 @@ HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
         int nHFADataTypeO;
 
         nOverviews = 0;
-        HFAGetOverviewInfo( hHFA, nBand, iOverview,
-                            &nRasterXSize, &nRasterYSize,
-                            &nBlockXSize, &nBlockYSize, &nHFADataTypeO  );
+        if (HFAGetOverviewInfo( hHFA, nBand, iOverview,
+                                &nRasterXSize, &nRasterYSize,
+                                &nBlockXSize, &nBlockYSize, &nHFADataTypeO ) != CE_None)
+        {
+            nRasterXSize = nRasterYSize = 0;
+            return;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      If we are an 8bit overview of a 1bit layer, we need to mark     */
@@ -878,7 +885,7 @@ double HFARasterBand::GetMinimum( int *pbSuccess )
     {
         if( pbSuccess )
             *pbSuccess = TRUE;
-        return atof(pszValue);
+        return CPLAtofM(pszValue);
     }
     else
     {
@@ -899,7 +906,7 @@ double HFARasterBand::GetMaximum( int *pbSuccess )
     {
         if( pbSuccess )
             *pbSuccess = TRUE;
-        return atof(pszValue);
+        return CPLAtofM(pszValue);
     }
     else
     {
@@ -929,6 +936,11 @@ void HFARasterBand::EstablishOverviews()
         {
             papoOverviewBands[iOvIndex] =
                 new HFARasterBand( (HFADataset *) poDS, nBand, iOvIndex );
+            if (papoOverviewBands[iOvIndex]->GetXSize() == 0)
+            {
+                delete papoOverviewBands[iOvIndex];
+                papoOverviewBands[iOvIndex] = NULL;
+            }
         }
     }
 }
@@ -1478,7 +1490,7 @@ HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 CPLErr HFARasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
 
 {
-    return GDALPamRasterBand::SetDefaultRAT( poRAT );
+    return WriteNamedRAT( "Descriptor_Table", poRAT );
 }
 
 /************************************************************************/
@@ -1545,7 +1557,7 @@ GDALRasterAttributeTable *HFARasterBand::ReadNamedRAT( const char *pszName )
             
             if( padfBinValues != NULL )
             {
-                poRAT->CreateColumn( "Value", GFT_Integer, GFU_MinMax );
+                poRAT->CreateColumn( "BinValues", GFT_Real, GFU_MinMax );
                 for( i = 0; i < nRowCount; i++ )
                     poRAT->SetValue( i, poRAT->GetColumnCount()-1, 
                                      padfBinValues[i] );
@@ -1675,6 +1687,171 @@ GDALRasterAttributeTable *HFARasterBand::ReadNamedRAT( const char *pszName )
 }
 
 /************************************************************************/
+/*                            WriteNamedRAT()                            */
+/************************************************************************/
+ 
+CPLErr HFARasterBand::WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT )
+{
+/* -------------------------------------------------------------------- */
+/*      Find the requested table.                                       */
+/* -------------------------------------------------------------------- */
+    HFAEntry * poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild( "Descriptor_Table" );
+    if( poDT == NULL || !EQUAL(poDT->GetType(),"Edsc_Table") )
+        poDT = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo, 
+                             "Descriptor_Table", "Edsc_Table",
+                             hHFA->papoBand[nBand-1]->poNode );
+   
+  
+    int nRowCount = poRAT->GetRowCount();
+
+    poDT->SetIntField( "numrows", nRowCount );
+    /* Check if binning is set on this RAT */    
+    double dfBinSize, dfRow0Min;
+    if(poRAT->GetLinearBinning( &dfRow0Min, &dfBinSize)) 
+    {
+        /* then it should have an Edsc_BinFunction */
+        HFAEntry *poBinFunction = poDT->GetNamedChild( "#Bin_Function#" );
+        if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
+            poBinFunction = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
+                                          "#Bin_Function#", "Edsc_BinFunction",
+                                          poDT );
+       
+        poBinFunction->SetStringField("binFunction", "direct");
+        poBinFunction->SetDoubleField("minLimit",dfRow0Min);
+        poBinFunction->SetDoubleField("maxLimit",(nRowCount -1)*dfBinSize+dfRow0Min);
+        poBinFunction->SetIntField("numBins",nRowCount);
+    }
+ 
+/* -------------------------------------------------------------------- */
+/*      Loop through each column in the RAT                             */
+/* -------------------------------------------------------------------- */
+    for(int col = 0; col < poRAT->GetColumnCount(); col++)
+    {
+        const char *pszName = NULL;
+ 
+        if( poRAT->GetUsageOfCol(col) == GFU_Red )
+        {
+            pszName = "Red";
+        }
+        else if( poRAT->GetUsageOfCol(col) == GFU_Green )
+        {
+            pszName = "Green";
+        }
+        else if( poRAT->GetUsageOfCol(col) == GFU_Blue )
+        {
+            pszName = "Blue";
+        }
+        else if( poRAT->GetUsageOfCol(col) == GFU_Alpha )
+        {
+            pszName = "Alpha";
+        }
+        else if( poRAT->GetUsageOfCol(col) == GFU_PixelCount )
+        {
+            pszName = "Histogram";
+        }
+        else if( poRAT->GetUsageOfCol(col) == GFU_Name )
+        {
+            pszName = "Class_Names";
+        }
+        else
+        {
+            pszName = poRAT->GetNameOfCol(col);
+        }
+            
+/* -------------------------------------------------------------------- */
+/*      Check to see if a column with pszName exists and create if      */
+/*      if necessary.                                                   */
+/* -------------------------------------------------------------------- */
+
+        HFAEntry        *poColumn;
+        poColumn = poDT->GetNamedChild(pszName);
+	    
+        if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
+	    poColumn = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
+                                     pszName, "Edsc_Column",
+                                     poDT );
+
+
+        poColumn->SetIntField( "numRows", nRowCount );
+   
+        if( poRAT->GetTypeOfCol(col) == GFT_Real )
+        {
+            int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
+                                            nRowCount * sizeof(double) );
+            poColumn->SetIntField( "columnDataPtr", nOffset );
+            poColumn->SetStringField( "dataType", "real" );
+            
+            double *padfColData = (double*)CPLCalloc( nRowCount, sizeof(double) );
+            for( int i = 0; i < nRowCount; i++)
+            {
+                padfColData[i] = poRAT->GetValueAsDouble(i,col);
+            }
+#ifdef CPL_MSB
+            GDALSwapWords( padfColData, 8, nRowCount, 8 );
+#endif
+            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
+            VSIFWriteL( padfColData, nRowCount, sizeof(double), hHFA->fp );
+            CPLFree( padfColData );
+        }
+        else if( poRAT->GetTypeOfCol(col) == GFT_String )
+        {
+            unsigned int nMaxNumChars = 0;
+            /* find the length of the longest string */
+            for( int i = 0; i < nRowCount; i++)
+            {
+                if(nMaxNumChars < strlen(poRAT->GetValueAsString(i,col)))
+                {
+                    nMaxNumChars = strlen(poRAT->GetValueAsString(i,col));
+                }
+            }
+       
+            int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
+                                            (nRowCount+1) * nMaxNumChars );
+            poColumn->SetIntField( "columnDataPtr", nOffset );
+            poColumn->SetStringField( "dataType", "string" );
+            poColumn->SetIntField( "maxNumChars", nMaxNumChars );
+       
+            char *pachColData = (char*)CPLCalloc(nRowCount+1,nMaxNumChars);
+            for( int i = 0; i < nRowCount; i++)
+            {
+                strcpy(&pachColData[nMaxNumChars*i],poRAT->GetValueAsString(i,col));
+            }
+            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
+            VSIFWriteL( pachColData, nRowCount, nMaxNumChars, hHFA->fp );
+            CPLFree( pachColData );
+        }
+        else if (poRAT->GetTypeOfCol(col) == GFT_Integer)
+        {
+            int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
+                                            nRowCount * sizeof(GInt32) );
+            poColumn->SetIntField( "columnDataPtr", nOffset );
+            poColumn->SetStringField( "dataType", "integer" );
+            
+            GInt32 *panColData = (GInt32*)CPLCalloc(nRowCount, sizeof(GInt32));
+            for( int i = 0; i < nRowCount; i++)
+            {
+                panColData[i] = poRAT->GetValueAsInt(i,col);
+            }
+#ifdef CPL_MSB
+            GDALSwapWords( panColData, 4, nRowCount, 4 );
+#endif
+            VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
+            VSIFWriteL( panColData, nRowCount, sizeof(GInt32), hHFA->fp );
+            CPLFree( panColData );
+        }
+        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_None;  
+}
+
+
+/************************************************************************/
 /* ==================================================================== */
 /*                            HFADataset                               */
 /* ==================================================================== */
@@ -1842,6 +2019,8 @@ CPLErr HFADataset::WriteProjection()
             sDatum.datumname = (char*) "NAD27";
         if( nGCS == 4269 )
             sDatum.datumname = (char*) "NAD83";
+        if( nGCS == 4283 )
+            sDatum.datumname = (char*) "GDA94";
             
         if( poGeogSRS->GetTOWGS84( sDatum.params ) == OGRERR_NONE )
             sDatum.type = EPRJ_DATUM_PARAMETRIC;
@@ -1936,16 +2115,45 @@ CPLErr HFADataset::WriteProjection()
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) )
+    else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) 
+             && oSRS.GetProjParm(SRS_PP_SCALE_FACTOR) == 1.0 )
     {
         sPro.proNumber = EPRJ_MERCATOR;
         sPro.proName = (char*) "Mercator";
         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
-        /* hopefully the scale factor is 1.0! */
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
+    else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) )
+    {
+        sPro.proNumber = EPRJ_MERCATOR_VARIANT_A;
+        sPro.proName = (char*) "Mercator (Variant A)";
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName,SRS_PT_KROVAK) )
+    {
+        sPro.proNumber = EPRJ_KROVAK;
+        sPro.proName = (char*) "Krovak";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1);
+
+        // XY plane rotation
+        sPro.proParams[8] = 0.0;
+        // X scale
+        sPro.proParams[10] = 1.0;
+        // Y scale
+        sPro.proParams[11] = 1.0;
+    }
     else if( EQUAL(pszProjName,SRS_PT_POLAR_STEREOGRAPHIC) )
     {
         sPro.proNumber = EPRJ_POLAR_STEREOGRAPHIC;
@@ -2046,7 +2254,7 @@ CPLErr HFADataset::WriteProjection()
         sPro.proNumber = EPRJ_EQUIRECTANGULAR;
         sPro.proName = (char*) "Equirectangular";
         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
@@ -2080,6 +2288,18 @@ CPLErr HFADataset::WriteProjection()
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
         sPro.proParams[12] = 1.0;
     }
+    else if( EQUAL(pszProjName,"Hotine_Oblique_Mercator_Azimuth_Center") )
+    {
+        sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
+        sPro.proName = (char*) "Hotine Oblique Mercator Azimuth Center";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+        sPro.proParams[12] = 1.0;
+    }
     else if( EQUAL(pszProjName,SRS_PT_ROBINSON) )
     {
         sPro.proNumber = EPRJ_ROBINSON;
@@ -2161,6 +2381,17 @@ CPLErr HFADataset::WriteProjection()
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
+    else if( EQUAL(pszProjName,SRS_PT_TWO_POINT_EQUIDISTANT) )
+    {
+        sPro.proNumber = EPRJ_TWO_POINT_EQUIDISTANT;
+        sPro.proName = (char*) "Two_Point_Equidistant";
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+        sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
+        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
+        sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
+        sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
+    }
     else if( EQUAL(pszProjName,SRS_PT_BONNE) )
     {
         sPro.proNumber = EPRJ_BONNE;
@@ -2205,23 +2436,153 @@ CPLErr HFADataset::WriteProjection()
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Winkel_II") )
+    else if( EQUAL(pszProjName,"Behrmann") )
     {
-        sPro.proNumber = EPRJ_WINKEL_II;
-        sPro.proName = (char*) "Winkel II";
+        sPro.proNumber = EPRJ_BEHRMANN;
+        sPro.proName = (char*) "Behrmann";
         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName,"Equidistant_Cylindrical") )
+    {
+        sPro.proNumber = EPRJ_EQUIDISTANT_CYLINDRICAL;
+        sPro.proName = (char*) "Equidistant_Cylindrical";
         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Behrmann") )
+    else if( EQUAL(pszProjName, SRS_PT_KROVAK) )
     {
-        sPro.proNumber = EPRJ_BEHRMANN;
-        sPro.proName = (char*) "Behrmann";
+        sPro.proNumber = EPRJ_KROVAK;
+        sPro.proName = (char*) "Krovak";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+        sPro.proParams[8] = oSRS.GetProjParm("XY_Plane_Rotation", 0.0)*D2R;
+        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proParams[10] = oSRS.GetProjParm("X_Scale", 1.0);
+        sPro.proParams[11] = oSRS.GetProjParm("Y_Scale", 1.0);
+    }
+    else if( EQUAL(pszProjName, "Double_Stereographic") )
+    {
+        sPro.proNumber = EPRJ_DOUBLE_STEREOGRAPHIC;
+        sPro.proName = (char*) "Double_Stereographic";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Aitoff") )
+    {
+        sPro.proNumber = EPRJ_AITOFF;
+        sPro.proName = (char*) "Aitoff";
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Craster_Parabolic") )
+    {
+        sPro.proNumber = EPRJ_CRASTER_PARABOLIC;
+        sPro.proName = (char*) "Craster_Parabolic";
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, SRS_PT_CYLINDRICAL_EQUAL_AREA) )
+    {
+        sPro.proNumber = EPRJ_CYLINDRICAL_EQUAL_AREA;
+        sPro.proName = (char*) "Cylindrical_Equal_Area";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Flat_Polar_Quartic") )
+    {
+        sPro.proNumber = EPRJ_FLAT_POLAR_QUARTIC;
+        sPro.proName = (char*) "Flat_Polar_Quartic";
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Times") )
+    {
+        sPro.proNumber = EPRJ_TIMES;
+        sPro.proName = (char*) "Times";
         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
+    else if( EQUAL(pszProjName, "Winkel_Tripel") )
+    {
+        sPro.proNumber = EPRJ_WINKEL_TRIPEL;
+        sPro.proName = (char*) "Winkel_Tripel";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Hammer_Aitoff") )
+    {
+        sPro.proNumber = EPRJ_HAMMER_AITOFF;
+        sPro.proName = (char*) "Hammer_Aitoff";
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Vertical_Near_Side_Perspective") )
+    {
+        sPro.proNumber = EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE;
+        sPro.proName = (char*) "Vertical_Near_Side_Perspective";
+        sPro.proParams[2] = oSRS.GetProjParm("Height");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Hotine_Oblique_Mercator_Azimuth_Center") )
+    {
+        sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
+        sPro.proName = (char*) "Hotine_Oblique_Mercator_Azimuth_Center";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH, 45.0)*D2R; 
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0)*D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+    else if( EQUAL(pszProjName, "Hotine_Oblique_Mercator_Two_Point_Center") )
+    {
+        sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER;
+        sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Center";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+        sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
+        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
+        sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
+        sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
+    }
+    else if( EQUAL(pszProjName, SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
+    {
+        sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN;
+        sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Natural_Origin";
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+        sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
+        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
+        sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
+        sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
+    }
     else if( EQUAL(pszProjName,"New_Zealand_Map_Grid") )
     {
         sPro.proType = EPRJ_EXTERNAL;
@@ -2683,6 +3044,15 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
         // UTM description.
         oSRS.SetProjCS( "unnamed" );
         oSRS.SetUTM( psPro->proZone, psPro->proParams[3] >= 0.0 );
+
+        // The PCS name from the above function may be different with the input name. 
+        // If there is a PCS name in psMapInfo that is different with 
+        // the one in psPro, just use it as the PCS name. This case happens 
+        // if the dataset's SR was written by the new GDAL. 
+        if( psMapInfo && strlen(psMapInfo->proName) > 0 
+            && strlen(psPro->proName) > 0 
+            && !EQUAL(psMapInfo->proName, psPro->proName) )
+            oSRS.SetProjCS( psMapInfo->proName );
         break;
 
       case EPRJ_STATE_PLANE:
@@ -2692,12 +3062,45 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           
           pszUnitsName = CPLStrdup( pszUnitsName );
 
+          /* Historically, hfa used esri state plane zone code. Try esri pe string first. */ 
+          int zoneCode = ESRIToUSGSZone(psPro->proZone);
+          char nad[32];
+          strcpy(nad, "HARN");
+          if(psDatum)
+              strcpy(nad, psDatum->datumname);
+          char units[32];
+          strcpy(units, "meters");
+          if(psMapInfo)
+              strcpy(units, psMapInfo->units);
+          else if(pszUnitsName && strlen(pszUnitsName) > 0)
+              strcpy(units, pszUnitsName);
+          int proNu = 0;
+          if(psPro)
+              proNu = psPro->proNumber;
+          if(oSRS.ImportFromESRIStatePlaneWKT(zoneCode, nad, units, proNu) == OGRERR_NONE)
+          {
+              CPLFree( pszUnitsName );
+              oSRS.morphFromESRI();
+              oSRS.AutoIdentifyEPSG();
+              oSRS.Fixup();
+              if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+                  return pszNewProj;
+              else
+                  return NULL;
+          }
+
           /* Set state plane zone.  Set NAD83/27 on basis of spheroid */
           oSRS.SetStatePlane( ESRIToUSGSZone(psPro->proZone), 
                               fabs(psPro->proSpheroid.a - 6378137.0)< 1.0,
                               pszUnitsName, dfLinearUnits );
 
           CPLFree( pszUnitsName );
+
+          // Same as the UTM, The following is needed.
+          if( psMapInfo && strlen(psMapInfo->proName) > 0 
+              && strlen(psPro->proName) > 0 
+              && !EQUAL(psMapInfo->proName, psPro->proName) )
+              oSRS.SetProjCS( psMapInfo->proName );
       }
       break;
 
@@ -2708,6 +3111,18 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
         break;
 
       case EPRJ_LAMBERT_CONFORMAL_CONIC:
+        // check the possible Wisconsin first
+        if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
+        {
+            if(oSRS.ImportFromESRIWisconsinWKT("Lambert_Conformal_Conic", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
+            {
+                oSRS.morphFromESRI();
+                oSRS.AutoIdentifyEPSG();
+                oSRS.Fixup();
+                if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+                    return pszNewProj;
+            }
+        }
         oSRS.SetLCC( psPro->proParams[2]*R2D, psPro->proParams[3]*R2D,
                      psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
                      psPro->proParams[6], psPro->proParams[7] );
@@ -2743,6 +3158,19 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
         break;
 
       case EPRJ_TRANSVERSE_MERCATOR:
+      case EPRJ_GAUSS_KRUGER:
+        // check the possible Wisconsin first
+        if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
+        {
+            if(oSRS.ImportFromESRIWisconsinWKT("Transverse_Mercator", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
+            {
+                oSRS.morphFromESRI();
+                oSRS.AutoIdentifyEPSG();
+                oSRS.Fixup();
+                if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+                    return pszNewProj;
+            }
+        }
         oSRS.SetTM( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
                     psPro->proParams[2],
                     psPro->proParams[6], psPro->proParams[7] );
@@ -2862,6 +3290,14 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
                     psPro->proParams[6], psPro->proParams[7] );
         break;
 
+      case EPRJ_TWO_POINT_EQUIDISTANT:
+        oSRS.SetTPED( psPro->proParams[9] * R2D,
+                      psPro->proParams[8] * R2D,
+                      psPro->proParams[11] * R2D,
+                      psPro->proParams[10] * R2D,
+                      psPro->proParams[6], psPro->proParams[7] );
+      break;
+
       case EPRJ_STEREOGRAPHIC_EXTENDED:
         oSRS.SetStereographic( psPro->proParams[5]*R2D,psPro->proParams[4]*R2D,
                                psPro->proParams[2],
@@ -2881,7 +3317,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           oSRS.SetNormProjParm( "central_parallel", 
                            psPro->proParams[5] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
       }
       break;
 
@@ -2891,7 +3327,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
       }
       break;
 
@@ -2903,7 +3339,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 
                            psPro->proParams[2] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
       }
       break;
 
@@ -2915,7 +3351,7 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 
                            psPro->proParams[2] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
       }
       break;
 
@@ -2925,10 +3361,175 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
                            psPro->proParams[4] * R2D );
           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_KROVAK:
+        oSRS.SetKrovak( psPro->proParams[4]*R2D, psPro->proParams[5]*R2D,
+                        psPro->proParams[3]*R2D, psPro->proParams[9]*R2D,
+                        psPro->proParams[2],
+                        psPro->proParams[6], psPro->proParams[7] );
+        break;
+
+      case EPRJ_DOUBLE_STEREOGRAPHIC:
+      {
+          oSRS.SetProjection( "Double_Stereographic" );
+          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 
+                           psPro->proParams[5] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR, psPro->proParams[2] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_AITOFF:
+      {
+          oSRS.SetProjection( "Aitoff" );
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
       }
       break;
 
+      case EPRJ_CRASTER_PARABOLIC:
+      {
+          oSRS.SetProjection( "Craster_Parabolic" );
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_CYLINDRICAL_EQUAL_AREA:
+          oSRS.SetCEA(psPro->proParams[2] * R2D, psPro->proParams[4] * R2D, 
+                      psPro->proParams[6], psPro->proParams[7]);
+      break;
+
+      case EPRJ_FLAT_POLAR_QUARTIC:
+      {
+          oSRS.SetProjection( "Flat_Polar_Quartic" );
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_TIMES:
+      {
+          oSRS.SetProjection( "Times" );
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_WINKEL_TRIPEL:
+      {
+          oSRS.SetProjection( "Winkel_Tripel" );
+          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
+                           psPro->proParams[2] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_HAMMER_AITOFF:
+      {
+          oSRS.SetProjection( "Hammer_Aitoff" );
+          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE:
+      {
+          oSRS.SetProjection( "Vertical_Near_Side_Perspective" );
+          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
+                           psPro->proParams[5] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( "height",
+                           psPro->proParams[2] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER:
+      {
+          oSRS.SetProjection( "Hotine_Oblique_Mercator_Azimuth_Center" );
+          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
+                           psPro->proParams[5] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,
+                           psPro->proParams[4] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_AZIMUTH,
+                           psPro->proParams[3] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR,
+                           psPro->proParams[2] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER:
+      {
+          oSRS.SetProjection( "Hotine_Oblique_Mercator_Twp_Point_Center" );
+          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
+                           psPro->proParams[5] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_1ST_POINT,
+                           psPro->proParams[9] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_1ST_POINT,
+                           psPro->proParams[8] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_2ND_POINT,
+                           psPro->proParams[11] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_2ND_POINT,
+                           psPro->proParams[10] * R2D );
+          oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR,
+                           psPro->proParams[2] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
+          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+      }
+      break;
+
+      case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN:
+        oSRS.SetHOM2PNO( psPro->proParams[5] * R2D, 
+                         psPro->proParams[8] * R2D,
+                         psPro->proParams[9] * R2D,
+                         psPro->proParams[10] * R2D,
+                         psPro->proParams[11] * R2D,
+                         psPro->proParams[2],
+                         psPro->proParams[6], psPro->proParams[7] );
+      break;
+
+      case EPRJ_LAMBERT_CONFORMAL_CONIC_1SP:
+        oSRS.SetLCC1SP( psPro->proParams[3]*R2D, psPro->proParams[2]*R2D,
+                        psPro->proParams[4],
+                        psPro->proParams[5], psPro->proParams[6] );
+        break;
+
+      case EPRJ_MERCATOR_VARIANT_A:
+        oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
+                          psPro->proParams[2],
+                          psPro->proParams[6], psPro->proParams[7] );
+        break;
+
+      case EPRJ_PSEUDO_MERCATOR: // likely this is google mercator?
+        oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
+                          1.0,
+                          psPro->proParams[6], psPro->proParams[7] );
+        break;
+
       default:
         if( oSRS.IsProjected() )
             oSRS.GetRoot()->SetValue( "LOCAL_CS" );
@@ -3080,10 +3681,22 @@ CPLErr HFADataset::IBuildOverviews( const char *pszResampling,
     int i;
 
     if( GetAccess() == GA_ReadOnly )
+    {
+        for( i = 0; i < nListBands; i++ )
+        {
+            if (HFAGetOverviewCount(hHFA, panBandList[i]) > 0)
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                        "Cannot add external overviews when there are already internal overviews");
+                return CE_Failure;
+            }
+        }
+
         return GDALDataset::IBuildOverviews( pszResampling, 
                                              nOverviews, panOverviewList, 
                                              nListBands, panBandList, 
                                              pfnProgress, pProgressData );
+    }
 
     for( i = 0; i < nListBands; i++ )
     {
@@ -3955,7 +4568,10 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                            NULL, pfnProgress, pProgressData );
         
         if( eErr != CE_None )
+        {
+            delete poDS;
             return NULL;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -4037,6 +4653,8 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 CPLFree( pszBinValues );
             }
 
+            CPLFree(panHistogram);
+
             if( CSLCount(papszStatsMD) > 0 )
                 HFASetMetadata( poDS->hHFA, iBand+1, papszStatsMD );
 
diff --git a/frmts/hfa/hfaentry.cpp b/frmts/hfa/hfaentry.cpp
index 6f512c9..7c59243 100644
--- a/frmts/hfa/hfaentry.cpp
+++ b/frmts/hfa/hfaentry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaentry.cpp 22538 2011-06-15 15:53:17Z warmerdam $
+ * $Id: hfaentry.cpp 23494 2011-12-07 23:56:41Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAEntry class for reading and relating
@@ -37,7 +37,7 @@
 #include "hfa_p.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: hfaentry.cpp 22538 2011-06-15 15:53:17Z warmerdam $");
+CPL_CVSID("$Id: hfaentry.cpp 23494 2011-12-07 23:56:41Z rouault $");
 
 /************************************************************************/
 /*                              HFAEntry()                              */
@@ -102,10 +102,14 @@ HFAEntry::HFAEntry( HFAInfo_t * psHFAIn, GUInt32 nPos,
     if( VSIFReadL( szName, 1, 64, psHFA->fp ) < 1
         || VSIFReadL( szType, 1, 32, psHFA->fp ) < 1 )
     {
+        szName[sizeof(szName)-1] = '\0';
+        szType[sizeof(szType)-1] = '\0';
         CPLError( CE_Failure, CPLE_FileIO,
                   "VSIFReadL() failed in HFAEntry()." );
         return;
     }
+    szName[sizeof(szName)-1] = '\0';
+    szType[sizeof(szType)-1] = '\0';
 }
 
 /************************************************************************/
@@ -578,12 +582,20 @@ void HFAEntry::DumpFieldValues( FILE * fp, const char * pszPrefix )
 /************************************************************************/
 
 std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
-                                               const char *pszType )
+                                               const char *pszType,
+                                               int nRecLevel )
 
 {
     std::vector<HFAEntry*> apoChildren;
     HFAEntry *poEntry;
 
+    if( nRecLevel == 50 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Bad entry structure: recursion detected !");
+        return apoChildren;
+    }
+
     if( this == NULL )
         return apoChildren;
     
@@ -596,7 +608,7 @@ std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
             && (pszType == NULL || EQUAL(poEntry->GetType(),pszType)) )
             apoChildren.push_back( poEntry );
 
-        apoEntryChildren = poEntry->FindChildren( pszName, pszType );
+        apoEntryChildren = poEntry->FindChildren( pszName, pszType, nRecLevel + 1 );
 
         for( i = 0; i < apoEntryChildren.size(); i++ )
             apoChildren.push_back( apoEntryChildren[i] );
diff --git a/frmts/hfa/hfafield.cpp b/frmts/hfa/hfafield.cpp
index 2077a59..2202eb3 100644
--- a/frmts/hfa/hfafield.cpp
+++ b/frmts/hfa/hfafield.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfafield.cpp 21184 2010-12-01 03:11:03Z warmerdam $
+ * $Id: hfafield.cpp 22913 2011-08-08 20:47:11Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAField class for managing information
@@ -30,7 +30,7 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfafield.cpp 21184 2010-12-01 03:11:03Z warmerdam $");
+CPL_CVSID("$Id: hfafield.cpp 22913 2011-08-08 20:47:11Z rouault $");
 
 #define MAX_ENTRY_REPORT   16
                            
@@ -181,13 +181,18 @@ const char *HFAField::Initialize( const char * pszInput )
         int	nEnumCount = atoi(pszInput);
         int	iEnum;
 
+        if (nEnumCount < 0 || nEnumCount > 100000)
+            return NULL;
+
         pszInput = strchr(pszInput,':');
         if( pszInput == NULL )
             return NULL;
 
         pszInput++;
 
-        papszEnumNames = (char **) CPLCalloc(sizeof(char *), nEnumCount+1);
+        papszEnumNames = (char **) VSICalloc(sizeof(char *), nEnumCount+1);
+        if (papszEnumNames == NULL)
+            return NULL;
         
         for( iEnum = 0; iEnum < nEnumCount; iEnum++ )
         {
@@ -676,7 +681,7 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
         // or type?
         
         if( nIndexValue == -3 )
-            nBaseItemType = nIntValue;
+            nBaseItemType = (GInt16) nIntValue;
         else if( nIndexValue == -2 )
             nColumns = nIntValue;
         else if( nIndexValue == -1 )
diff --git a/frmts/hfa/hfaopen.cpp b/frmts/hfa/hfaopen.cpp
index e96b743..a069a72 100644
--- a/frmts/hfa/hfaopen.cpp
+++ b/frmts/hfa/hfaopen.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfaopen.cpp 21764 2011-02-20 16:19:53Z warmerdam $
+ * $Id: hfaopen.cpp 23624 2011-12-21 19:31:43Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Supporting functions for HFA (.img) ... main (C callable) API
@@ -41,7 +41,7 @@
 #include <limits.h>
 #include <vector>
 
-CPL_CVSID("$Id: hfaopen.cpp 21764 2011-02-20 16:19:53Z warmerdam $");
+CPL_CVSID("$Id: hfaopen.cpp 23624 2011-12-21 19:31:43Z rouault $");
 
 
 static const char *apszAuxMetadataItems[] = {
@@ -586,6 +586,13 @@ int HFAGetBandNoData( HFAHandle hHFA, int nBand, double *pdfNoData )
 
     HFABand *poBand = hHFA->papoBand[nBand-1];
 
+    if( !poBand->bNoDataSet && poBand->nOverviews > 0 )
+    {
+      poBand = poBand->papoOverviews[0];
+      if( poBand == NULL )
+          return FALSE;
+    }
+
     *pdfNoData = poBand->dfNoData;
     return poBand->bNoDataSet;
 }
@@ -658,6 +665,10 @@ CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
         return CE_Failure;
     }
     poBand = poBand->papoOverviews[iOverview];
+    if( poBand == NULL )
+    {
+        return CE_Failure;
+    }
 
     if( pnXSize != NULL )
         *pnXSize = poBand->nWidth;
@@ -1025,11 +1036,15 @@ int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
         padfGeoTransform[0] = psMapInfo->upperLeftCenter.x
             - psMapInfo->pixelSize.width*0.5;
         padfGeoTransform[1] = psMapInfo->pixelSize.width;
+        if(padfGeoTransform[1] == 0.0)
+            padfGeoTransform[1] = 1.0;
         padfGeoTransform[2] = 0.0;
         if( psMapInfo->upperLeftCenter.y >= psMapInfo->lowerRightCenter.y )
             padfGeoTransform[5] = - psMapInfo->pixelSize.height;
         else
             padfGeoTransform[5] = psMapInfo->pixelSize.height;
+        if(padfGeoTransform[5] == 0.0)
+            padfGeoTransform[5] = 1.0;
 
         padfGeoTransform[3] = psMapInfo->upperLeftCenter.y
             - padfGeoTransform[5]*0.5;
@@ -1440,6 +1455,9 @@ CPLErr HFASetProParameters( HFAHandle hHFA, const Eprj_ProParameters *poPro )
             nSize += strlen(poPro->proExeName) + 1;
 
         pabyData = poMIEntry->MakeData( nSize );
+        if(!pabyData)
+            return CE_Failure;
+
         poMIEntry->SetPosition();
 
         // Initialize the whole thing to zeros for a clean start.
@@ -1585,6 +1603,9 @@ CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
             nSize += strlen(poDatum->gridname) + 1;
 
         pabyData = poDatumEntry->MakeData( nSize );
+        if(!pabyData)
+            return CE_Failure;
+
         poDatumEntry->SetPosition();
 
         // Initialize the whole thing to zeros for a clean start.
diff --git a/frmts/hfa/hfatest.cpp b/frmts/hfa/hfatest.cpp
index d15da0e..7031841 100644
--- a/frmts/hfa/hfatest.cpp
+++ b/frmts/hfa/hfatest.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfatest.cpp 18624 2010-01-24 02:54:43Z warmerdam $
+ * $Id: hfatest.cpp 22802 2011-07-24 14:16:58Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Testing mainline for HFA services - transitory.
@@ -28,8 +28,9 @@
  ****************************************************************************/
 
 #include "hfa_p.h"
+#include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: hfatest.cpp 18624 2010-01-24 02:54:43Z warmerdam $");
+CPL_CVSID("$Id: hfatest.cpp 22802 2011-07-24 14:16:58Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -219,6 +220,9 @@ int main( int argc, char ** argv )
     
     HFAClose( hHFA );
 
+    VSICleanupFileManager();
+    CPLCleanupTLS();
+
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
diff --git a/frmts/hfa/hfatype.cpp b/frmts/hfa/hfatype.cpp
index 0a14d1b..bc3fb08 100644
--- a/frmts/hfa/hfatype.cpp
+++ b/frmts/hfa/hfatype.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfatype.cpp 18895 2010-02-23 19:30:01Z warmerdam $
+ * $Id: hfatype.cpp 23495 2011-12-08 00:16:33Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAType class, for managing one type
@@ -30,7 +30,7 @@
 
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfatype.cpp 18895 2010-02-23 19:30:01Z warmerdam $");
+CPL_CVSID("$Id: hfatype.cpp 23495 2011-12-08 00:16:33Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -49,6 +49,7 @@ HFAType::HFAType()
     nFields = 0;
     papoFields = NULL;
     pszTypeName = NULL;
+    bInCompleteDefn = FALSE;
 }
 
 /************************************************************************/
@@ -150,7 +151,16 @@ void HFAType::CompleteDefn( HFADictionary * poDict )
 /* -------------------------------------------------------------------- */
     if( nBytes != 0 )
         return;
-    
+
+
+    if( bInCompleteDefn )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Recursion detected in HFAType::CompleteDefn()");
+        return;
+    }
+    bInCompleteDefn = TRUE;
+
 /* -------------------------------------------------------------------- */
 /*      Complete each of the fields, totaling up the sizes.  This       */
 /*      isn't really accurate for object with variable sized            */
@@ -164,6 +174,8 @@ void HFAType::CompleteDefn( HFADictionary * poDict )
         else
             nBytes += papoFields[i]->nBytes;
     }
+
+    bInCompleteDefn = FALSE;
 }
 
 /************************************************************************/
diff --git a/frmts/idrisi/IdrisiDataset.cpp b/frmts/idrisi/IdrisiDataset.cpp
index 62e1170..21f36b3 100644
--- a/frmts/idrisi/IdrisiDataset.cpp
+++ b/frmts/idrisi/IdrisiDataset.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
-* $Id: IdrisiDataset.cpp 22446 2011-05-28 15:05:57Z rouault $
+* $Id: IdrisiDataset.cpp 23431 2011-11-27 15:02:24Z rouault $
 *
 * Project:  Idrisi Raster Image File Driver
 * Purpose:  Read/write Idrisi Raster Image Format RST
@@ -35,8 +35,9 @@
 #include "gdal_pam.h"
 #include "gdal_alg.h"
 #include "gdal_rat.h"
+#include "idrisi.h"
 
-CPL_CVSID( "$Id: IdrisiDataset.cpp 22446 2011-05-28 15:05:57Z rouault $" );
+CPL_CVSID( "$Id: IdrisiDataset.cpp 23431 2011-11-27 15:02:24Z rouault $" );
 
 CPL_C_START
 void GDALRegister_IDRISI( void);
@@ -275,10 +276,6 @@ private:
     char **papszCategories;
     char *pszUnitType;
 
-    CPLErr GeoReference2Wkt( const char *pszRefSystem,
-        const char *pszRefUnits,
-        char **pszProjString );
-
     CPLErr Wkt2GeoReference( const char *pszProjString,
         char **pszRefSystem, 
         char **pszRefUnit );
@@ -427,8 +424,7 @@ IdrisiDataset::~IdrisiDataset()
 
 GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
 {
-    if( ( poOpenInfo->fp == NULL ) || 
-        ( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), extRST ) == FALSE ) )
+    if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), extRST ) == FALSE )
         return NULL;
 
     // --------------------------------------------------------------------
@@ -481,6 +477,7 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
     if( poDS->fp == NULL )
     {
         CSLDestroy( papszLRDC );
+        delete poDS;
         return NULL;
     }
 
@@ -980,13 +977,18 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     }
     else
     {
-        CSLSetNameValue( poDS->papszRDC, rdcMIN_X, CPLSPrintf( "%.1f", -0.5 ));
-        CSLSetNameValue( poDS->papszRDC, rdcMAX_X, CPLSPrintf( "%.1f", 
+        poDS->papszRDC =
+            CSLSetNameValue( poDS->papszRDC, rdcMIN_X, CPLSPrintf( "%.1f", -0.5 ));
+        poDS->papszRDC =
+            CSLSetNameValue( poDS->papszRDC, rdcMAX_X, CPLSPrintf( "%.1f",
             poSrcDS->GetRasterXSize() - 0.5 ) );
-        CSLSetNameValue( poDS->papszRDC, rdcMIN_Y, CPLSPrintf( "%.1f", 
+        poDS->papszRDC =
+            CSLSetNameValue( poDS->papszRDC, rdcMIN_Y, CPLSPrintf( "%.1f",
             poSrcDS->GetRasterYSize() + 0.5 ) );
-        CSLSetNameValue( poDS->papszRDC, rdcMAX_Y, CPLSPrintf( "%.1f", 0.5 ));
-        CSLSetNameValue( poDS->papszRDC, rdcRESOLUTION, "1" );
+        poDS->papszRDC =
+            CSLSetNameValue( poDS->papszRDC, rdcMAX_Y, CPLSPrintf( "%.1f", 0.5 ));
+        poDS->papszRDC =
+            CSLSetNameValue( poDS->papszRDC, rdcRESOLUTION, "1" );
     }
 
     // --------------------------------------------------------------------
@@ -1171,11 +1173,11 @@ CPLErr  IdrisiDataset::SetGeoTransform( double * padfTransform )
         dfMinY   = padfTransform[3];
     }
 
-    CSLSetNameValue( papszRDC, rdcMIN_X,      CPLSPrintf( "%.7f", dfMinX ) );
-    CSLSetNameValue( papszRDC, rdcMAX_X,      CPLSPrintf( "%.7f", dfMaxX ) );
-    CSLSetNameValue( papszRDC, rdcMIN_Y,      CPLSPrintf( "%.7f", dfMinY ) );
-    CSLSetNameValue( papszRDC, rdcMAX_Y,      CPLSPrintf( "%.7f", dfMaxY ) );
-    CSLSetNameValue( papszRDC, rdcRESOLUTION, CPLSPrintf( "%.7f", fabs( dfYPixSz ) ) );
+    papszRDC = CSLSetNameValue( papszRDC, rdcMIN_X,      CPLSPrintf( "%.7f", dfMinX ) );
+    papszRDC = CSLSetNameValue( papszRDC, rdcMAX_X,      CPLSPrintf( "%.7f", dfMaxX ) );
+    papszRDC = CSLSetNameValue( papszRDC, rdcMIN_Y,      CPLSPrintf( "%.7f", dfMinY ) );
+    papszRDC = CSLSetNameValue( papszRDC, rdcMAX_Y,      CPLSPrintf( "%.7f", dfMaxY ) );
+    papszRDC = CSLSetNameValue( papszRDC, rdcRESOLUTION, CPLSPrintf( "%.7f", fabs( dfYPixSz ) ) );
 
     // --------------------------------------------------------------------
     // Update the Dataset attribute
@@ -1203,7 +1205,7 @@ const char *IdrisiDataset::GetProjectionRef( void )
         const char *pszRefUnit = CSLFetchNameValue( papszRDC, rdcREF_UNITS );
 
         if (pszRefSystem != NULL && pszRefUnit != NULL)
-            GeoReference2Wkt( pszRefSystem, pszRefUnit, &pszProjection );
+            IdrisiGeoReference2Wkt( pszFilename, pszRefSystem, pszRefUnit, &pszProjection );
         else
             pszProjection = CPLStrdup("");
     }
@@ -1225,8 +1227,8 @@ CPLErr IdrisiDataset::SetProjection( const char *pszProjString )
 
     eResult = Wkt2GeoReference( pszProjString, &pszRefSystem, &pszRefUnit );
 
-    CSLSetNameValue( papszRDC, rdcREF_SYSTEM, pszRefSystem );
-    CSLSetNameValue( papszRDC, rdcREF_UNITS,  pszRefUnit );
+    papszRDC = CSLSetNameValue( papszRDC, rdcREF_SYSTEM, pszRefSystem );
+    papszRDC = CSLSetNameValue( papszRDC, rdcREF_UNITS,  pszRefUnit );
 
     CPLFree( pszRefSystem );
     CPLFree( pszRefUnit );
@@ -1636,7 +1638,7 @@ CPLErr IdrisiRasterBand::SetCategoryNames( char **papszCategoryNames )
         }
     }
 
-    CSLSetNameValue( poGDS->papszRDC, rdcLEGEND_CATS, CPLSPrintf( "%d", nCount ) );
+    poGDS->papszRDC = CSLSetNameValue( poGDS->papszRDC, rdcLEGEND_CATS, CPLSPrintf( "%d", nCount ) );
 
     return CE_None;
 }
@@ -2085,7 +2087,7 @@ const GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
 }
 
 /************************************************************************/
-/*                       GeoReference2Wkt()                             */
+/*                       IdrisiGeoReference2Wkt()                       */
 /************************************************************************/
 
 /***
@@ -2095,7 +2097,7 @@ const GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
 * geographic reference, RefSystem and RefUnit. 
 * 
 * RefSystem can contains the world "plane" or the name of a georeference 
-* file <refsystem>.ref that details the geographic reference  
+* file <refsystem>.ref that details the geographic reference
 * system( coordinate system and projection parameters ). RefUnits 
 * indicates the unit of the image bounds. 
 * 
@@ -2116,12 +2118,15 @@ const GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
 * need to be read then the projection string will result as unknown. 
 ***/
 
-CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
-                                        const char *pszRefUnits,
-                                        char **pszProjString )
+CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
+                               const char *pszRefSystem,
+                               const char *pszRefUnits,
+                               char **ppszProjString )
 {
     OGRSpatialReference oSRS;
 
+    *ppszProjString = NULL;
+
     // ---------------------------------------------------------
     //  Plane 
     // ---------------------------------------------------------
@@ -2136,7 +2141,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
             oSRS.SetLinearUnits( aoLinearUnitsConv[nDeft].pszName,
                 aoLinearUnitsConv[nDeft].dfConv );
         }
-        oSRS.exportToWkt( pszProjString );
+        oSRS.exportToWkt( ppszProjString );
         return CE_None;
     }
 
@@ -2148,7 +2153,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
         EQUAL( pszRefSystem, rstLATLONG2 ) )
     {
         oSRS.SetWellKnownGeogCS( "WGS84" );
-        oSRS.exportToWkt( pszProjString );
+        oSRS.exportToWkt( ppszProjString );
         return CE_None;
     }
 
@@ -2171,7 +2176,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
         sscanf( pszRefSystemLower, rstUTM, &nZone, &cNorth );
         oSRS.SetWellKnownGeogCS( "WGS84" );
         oSRS.SetUTM( nZone,( cNorth == 'n' ) );
-        oSRS.exportToWkt( pszProjString );
+        oSRS.exportToWkt( ppszProjString );
         CPLFree( pszRefSystemLower );
         return CE_None;
     }
@@ -2193,7 +2198,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
 
             if( oSRS.SetStatePlane( nZone, ( nNAD == 83 ) ) != OGRERR_FAILURE )
             {
-                oSRS.exportToWkt( pszProjString );
+                oSRS.exportToWkt( ppszProjString );
                 CPLFree( pszRefSystemLower );
                 return CE_None;
             }
@@ -2252,7 +2257,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
                     aoLinearUnitsConv[nDeft].dfConv );
             }
         }
-        oSRS.exportToWkt( pszProjString );
+        oSRS.exportToWkt( ppszProjString );
         return CE_Failure;
     }
 
@@ -2370,7 +2375,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
 
     if( EQUAL( pszProjName, "none" ) )
     {
-        oSRS.exportToWkt( pszProjString );
+        oSRS.exportToWkt( ppszProjString );
         
         CPLFree( pszGeorefName );
         CPLFree( pszProjName );
@@ -2468,7 +2473,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
             "[\"%s\" in georeference file \"%s\"]",
             pszProjName, pszFName );
         oSRS.Clear();
-        oSRS.exportToWkt( pszProjString );
+        oSRS.exportToWkt( ppszProjString );
         
         CPLFree( pszGeorefName );
         CPLFree( pszProjName );
@@ -2500,7 +2505,7 @@ CPLErr IdrisiDataset::GeoReference2Wkt( const char *pszRefSystem,
 
     oSRS.SetProjCS( pszGeorefName );
 
-    oSRS.exportToWkt( pszProjString );
+    oSRS.exportToWkt( ppszProjString );
         
     CPLFree( pszGeorefName );
     CPLFree( pszProjName );
@@ -2837,9 +2842,9 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
 
 bool FileExists( const char *pszPath )
 {
-    VSIStatBuf  sStat;
+    VSIStatBufL  sStat;
 
-    return (bool) ( CPLStat( pszPath, &sStat ) == 0 );
+    return (bool) ( VSIStatL( pszPath, &sStat ) == 0 );
 }
 
 /************************************************************************/
@@ -2991,6 +2996,7 @@ int  SaveAsCRLF(char **papszStrList, const char *pszFname)
 /************************************************************************/
 /*                        GDALRegister_IDRISI()                         */
 /************************************************************************/
+
 void GDALRegister_IDRISI()
 {
     GDALDriver  *poDriver;
@@ -3004,6 +3010,9 @@ void GDALRegister_IDRISI()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_Idrisi.html" );
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, extRST );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 Float32" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = IdrisiDataset::Open;
         poDriver->pfnCreate = IdrisiDataset::Create;
         poDriver->pfnCreateCopy = IdrisiDataset::CreateCopy;
diff --git a/frmts/idrisi/idrisi.h b/frmts/idrisi/idrisi.h
new file mode 100644
index 0000000..5ed93f2
--- /dev/null
+++ b/frmts/idrisi/idrisi.h
@@ -0,0 +1,40 @@
+/*****************************************************************************
+* $Id: idrisi.h 23040 2011-09-04 14:42:12Z rouault $
+*
+* Project:  Idrisi Raster Image File Driver
+* Purpose:  Read/write Idrisi Raster Image Format RST
+* Author:   Ivan Lucena, ivan.lucena at pmldnet.com
+*
+******************************************************************************
+* Copyright( c ) 2006, 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 _IDRISI_H_INCLUDED
+#define _IDRISI_H_INCLUDED
+
+#include "cpl_error.h"
+
+CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
+                               const char *pszRefSystem,
+                               const char *pszRefUnits,
+                               char **ppszProjString );
+
+#endif /*  _IDRISI_H_INCLUDED */
diff --git a/frmts/ilwis/ilwisdataset.cpp b/frmts/ilwis/ilwisdataset.cpp
index eb24705..80337f0 100644
--- a/frmts/ilwis/ilwisdataset.cpp
+++ b/frmts/ilwis/ilwisdataset.cpp
@@ -812,6 +812,11 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
@@ -1931,7 +1936,7 @@ void ValueRange::init(double rRaw0)
             iBeforeDec = (short)floor(log10(rMax)) + 1;
         if (get_rLo() < 0)
             iBeforeDec++;
-        _iWidth = iBeforeDec + _iDec;
+        _iWidth = (short) (iBeforeDec + _iDec);
         if (_iDec > 0)
             _iWidth++;
         if (_iWidth > 12)
diff --git a/frmts/ingr/GNUmakefile b/frmts/ingr/GNUmakefile
index c627992..4b20c83 100644
--- a/frmts/ingr/GNUmakefile
+++ b/frmts/ingr/GNUmakefile
@@ -7,6 +7,9 @@ OBJ	=	IntergraphDataset.o IntergraphBand.o IngrTypes.o JpegHelper.o
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS)
 
 ifeq ($(TIFF_SETTING),internal)
+ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
+CPPFLAGS 	:=	$(CPPFLAGS) -DRENAME_INTERNAL_LIBTIFF_SYMBOLS
+endif
 CPPFLAGS	:=	$(CPPFLAGS) -I../gtiff/libtiff
 endif
 
diff --git a/frmts/ingr/IngrTypes.cpp b/frmts/ingr/IngrTypes.cpp
index 55693f5..4461bbd 100644
--- a/frmts/ingr/IngrTypes.cpp
+++ b/frmts/ingr/IngrTypes.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IngrTypes.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: IngrTypes.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Types support function
@@ -760,7 +760,7 @@ uint32 CPL_STDCALL INGR_GetDataBlockSize( const char *pszFilename,
 
         VSIStatBufL  sStat;
         VSIStatL( pszFilename, &sStat );
-        return sStat.st_size - nDataOffset;
+        return (uint32) (sStat.st_size - nDataOffset);
     }
     else
     {
diff --git a/frmts/ingr/IntergraphBand.cpp b/frmts/ingr/IntergraphBand.cpp
index e1db4ed..240c881 100644
--- a/frmts/ingr/IntergraphBand.cpp
+++ b/frmts/ingr/IntergraphBand.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IntergraphBand.cpp 16620 2009-03-19 21:07:13Z rouault $
+ * $Id: IntergraphBand.cpp 23117 2011-09-24 15:06:37Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read/Write Intergraph Raster Format, band support
@@ -194,6 +194,13 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS,
     SetMetadataItem( "ORIENTATION", 
         INGR_GetOrientation( hHeaderOne.ScanlineOrientation ),
         "IMAGE_STRUCTURE" );
+
+    if( eFormat == PackedBinary ||
+        eFormat == RunLengthEncoded ||
+        eFormat == CCITTGroup4 )
+    {
+        SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
+    }
 }
 
 //  ----------------------------------------------------------------------------
diff --git a/frmts/ingr/JpegHelper.cpp b/frmts/ingr/JpegHelper.cpp
index 6e78509..60afe23 100644
--- a/frmts/ingr/JpegHelper.cpp
+++ b/frmts/ingr/JpegHelper.cpp
@@ -202,7 +202,7 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
         *( pabNext++ )  = 0xDB;         // DQT
         *( pabNext++ )  = 0;            // Segment Length (msb)
         *( pabNext++ )  = 67;           // Length (msb)
-        *( pabNext++ )  = i;            // Table ID
+        *( pabNext++ )  = (GByte) i;    // Table ID
         memcpy( pabNext, abQuantTables[i], 64 );
         pabNext += 64;
     }
@@ -219,11 +219,11 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
     else
         *( pabNext++ )  = 11;           // Segment Length (lsb)
     *( pabNext++ )      = 8;            // 8-bit Precision 
-    *( pabNext++ )      = nRows >> 8;   // Height in rows (msb) 
-    *( pabNext++ )      = nRows;        // Height in rows (lsb) 
-    *( pabNext++ )      = nCols >> 8;   // Width in columns (msb)
-    *( pabNext++ )      = nCols;        // Width in columns (lsb)
-    *( pabNext++ )      = nComponents;  // Number of components 
+    *( pabNext++ )      = (GByte) (nRows >> 8); // Height in rows (msb) 
+    *( pabNext++ )      = (GByte) nRows;// Height in rows (lsb) 
+    *( pabNext++ )      = (GByte) (nCols >> 8); // Width in columns (msb)
+    *( pabNext++ )      = (GByte) nCols;// Width in columns (lsb)
+    *( pabNext++ )      = (GByte) nComponents;// Number of components 
     *( pabNext++ )      = 0;            // Component ID
     *( pabNext++ )      = 0x21;         // Hozontal/Vertical Sampling
     *( pabNext++ )      = 0;            // Quantization table ID 
@@ -274,8 +274,8 @@ int JPGHLP_HeaderMaker( GByte *pabyBuffer,
             *( pabNext++ ) = 0xFF;                  // Tag Mark
             *( pabNext++ ) = 0xc4;                  // DHT 
             *( pabNext++ ) = 0;                     // Segment Length (msb)
-            *( pabNext++ ) = 3 + nCodes + nSymbols; // Segment Length (lsb)
-            *( pabNext++ ) = (j << 4) | i;          // Table ID
+            *( pabNext++ ) = (GByte) (3 + nCodes + nSymbols); // Segment Length (lsb)
+            *( pabNext++ ) = (GByte) ((j << 4) | i);          // Table ID
             memcpy( pabNext, pabHuffTab[i][j], nCodes );
             pabNext += nCodes;
             memcpy( pabNext, pabHuffTab[i][k], nSymbols );
diff --git a/frmts/iso8211/ddfmodule.cpp b/frmts/iso8211/ddfmodule.cpp
index 2381ad7..592726c 100644
--- a/frmts/iso8211/ddfmodule.cpp
+++ b/frmts/iso8211/ddfmodule.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfmodule.cpp 17405 2009-07-17 06:13:24Z chaitanya $
+ * $Id: ddfmodule.cpp 23595 2011-12-18 22:58:47Z rouault $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFModule class.
@@ -30,7 +30,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfmodule.cpp 17405 2009-07-17 06:13:24Z chaitanya $");
+CPL_CVSID("$Id: ddfmodule.cpp 23595 2011-12-18 22:58:47Z rouault $");
 
 /************************************************************************/
 /*                             DDFModule()                              */
@@ -161,7 +161,7 @@ void DDFModule::Close()
 int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 
 {
-    static const size_t nLeaderSize = 24;
+    static const int nLeaderSize = 24;
 
 /* -------------------------------------------------------------------- */
 /*      Close the existing file if there is one.                        */
@@ -188,7 +188,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 /* -------------------------------------------------------------------- */
     char        achLeader[nLeaderSize];
     
-    if( VSIFReadL( achLeader, 1, nLeaderSize, fpDDF ) != nLeaderSize )
+    if( (int)VSIFReadL( achLeader, 1, nLeaderSize, fpDDF ) != nLeaderSize )
     {
         VSIFCloseL( fpDDF );
         fpDDF = NULL;
@@ -206,7 +206,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 /* -------------------------------------------------------------------- */
     int         i, bValid = TRUE;
 
-    for( i = 0; i < (int)nLeaderSize; i++ )
+    for( i = 0; i < nLeaderSize; i++ )
     {
         if( achLeader[i] < 32 || achLeader[i] > 126 )
             bValid = FALSE;
@@ -242,7 +242,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
         _sizeFieldPos                 = DDFScanInt(achLeader+21,1);
         _sizeFieldTag                 = DDFScanInt(achLeader+23,1);
 
-        if( _recLength < 12 || _fieldControlLength == 0
+        if( _recLength < nLeaderSize || _fieldControlLength == 0
             || _fieldAreaStart < 24 || _sizeFieldLength == 0
             || _sizeFieldPos == 0 || _sizeFieldTag == 0 )
         {
@@ -319,6 +319,18 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
         
         nEntryOffset += _sizeFieldLength;
         nFieldPos = DDFScanInt( pachRecord+nEntryOffset, _sizeFieldPos );
+
+        if (_fieldAreaStart+nFieldPos < 0 ||
+            _recLength - (_fieldAreaStart+nFieldPos) < nFieldLength)
+        {
+            if( !bFailQuietly )
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "Header record invalid on DDF file `%s'.",
+                        pszFilename );
+
+            CPLFree( pachRecord );
+            return FALSE;
+        }
         
         poFDefn = new DDFFieldDefn();
         if( poFDefn->Initialize( this, szTag, nFieldLength,
diff --git a/frmts/iso8211/ddfrecord.cpp b/frmts/iso8211/ddfrecord.cpp
index 3a829eb..102b094 100644
--- a/frmts/iso8211/ddfrecord.cpp
+++ b/frmts/iso8211/ddfrecord.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfrecord.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ddfrecord.cpp 23598 2011-12-18 23:40:29Z rouault $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFRecord class.
@@ -30,9 +30,9 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfrecord.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ddfrecord.cpp 23598 2011-12-18 23:40:29Z rouault $");
 
-static const size_t nLeaderSize = 24;
+static const int nLeaderSize = 24;
 
 /************************************************************************/
 /*                             DDFRecord()                              */
@@ -409,6 +409,15 @@ int DDFRecord::ReadHeader()
                 return FALSE;
             }
 
+            if (_fieldAreaStart + nFieldPos - nLeaderSize < 0 ||
+                nDataSize - (_fieldAreaStart + nFieldPos - nLeaderSize) < nFieldLength)
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Not enough byte to initialize field `%s'.",
+                          szTag );
+                return FALSE;
+            }
+
 /* -------------------------------------------------------------------- */
 /*      Assign info the DDFField.                                       */
 /* -------------------------------------------------------------------- */
@@ -444,6 +453,15 @@ int DDFRecord::ReadHeader()
         int nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag;
         nFieldCount = 0;
         int i=0;
+
+        if (nFieldEntryWidth == 0)
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                      "Invalid record buffer size : %d.",
+                      nFieldEntryWidth );
+            return FALSE;
+        }
+        
         char *tmpBuf = (char*)VSIMalloc(nFieldEntryWidth);
 
         if( tmpBuf == NULL )
@@ -553,6 +571,15 @@ int DDFRecord::ReadHeader()
                 return FALSE;
             }
 
+            if (_fieldAreaStart + nFieldPos - nLeaderSize < 0 ||
+                nDataSize - (_fieldAreaStart + nFieldPos - nLeaderSize) < nFieldLength)
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Not enough byte to initialize field `%s'.",
+                          szTag );
+                return FALSE;
+            }
+
             /* ------------------------------------------------------------- */
             /* Assign info the DDFField.                                     */
             /* ------------------------------------------------------------- */
diff --git a/frmts/iso8211/ddfsubfielddefn.cpp b/frmts/iso8211/ddfsubfielddefn.cpp
index 426e020..4859699 100644
--- a/frmts/iso8211/ddfsubfielddefn.cpp
+++ b/frmts/iso8211/ddfsubfielddefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ddfsubfielddefn.cpp 17405 2009-07-17 06:13:24Z chaitanya $
+ * $Id: ddfsubfielddefn.cpp 23595 2011-12-18 22:58:47Z rouault $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFSubfieldDefn class.
@@ -30,7 +30,7 @@
 #include "iso8211.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfsubfielddefn.cpp 17405 2009-07-17 06:13:24Z chaitanya $");
+CPL_CVSID("$Id: ddfsubfielddefn.cpp 23595 2011-12-18 22:58:47Z rouault $");
 
 /************************************************************************/
 /*                          DDFSubfieldDefn()                           */
@@ -135,7 +135,13 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
         bIsVariable = FALSE;
         if( pszFormatString[1] == '(' )
         {
-            CPLAssert( atoi(pszFormatString+2) % 8 == 0 );
+            if( atoi(pszFormatString+2) % 8 != 0 )
+            {
+                 CPLError( CE_Failure, CPLE_AppDefined,
+                           "Format width %s is invalid.",
+                           pszFormatString+2 );
+                return FALSE;
+            }
             
             nFormatWidth = atoi(pszFormatString+2) / 8;
             eBinaryFormat = SInt; // good default, works for SDTS.
@@ -166,7 +172,6 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
                   "Format type of `%c' not supported.\n",
                   pszFormatString[0] );
         
-        CPLAssert( FALSE );
         return FALSE;
         
       default:
@@ -174,7 +179,6 @@ int DDFSubfieldDefn::SetFormat( const char * pszFormat )
                   "Format type of `%c' not recognised.\n",
                   pszFormatString[0] );
         
-        CPLAssert( FALSE );
         return FALSE;
     }
     
@@ -445,7 +449,15 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
       {
           unsigned char   abyData[8];
 
-          CPLAssert( nFormatWidth <= nMaxBytes );
+          if( nFormatWidth > nMaxBytes )
+          {
+              CPLError( CE_Warning, CPLE_AppDefined,
+                        "Attempt to extract float subfield %s with format %s\n"
+                        "failed as only %d bytes available.  Using zero.",
+                        pszName, pszFormatString, nMaxBytes );
+              return 0;
+          }
+
           if( pnConsumedBytes != NULL )
               *pnConsumedBytes = nFormatWidth;
 
@@ -478,7 +490,7 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
                   return( *((GUInt32 *) abyData) );
               else
               {
-                  CPLAssert( FALSE );
+                  //CPLAssert( FALSE );
                   return 0.0;
               }
             
@@ -491,7 +503,7 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
                   return( *((GInt32 *) abyData) );
               else
               {
-                  CPLAssert( FALSE );
+                  //CPLAssert( FALSE );
                   return 0.0;
               }
             
@@ -502,14 +514,14 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
                   return( *((double *) abyData) );
               else
               {
-                  CPLAssert( FALSE );
+                  //CPLAssert( FALSE );
                   return 0.0;
               }
 
             case NotBinary:            
             case FPReal:
             case FloatComplex:
-              CPLAssert( FALSE );
+              //CPLAssert( FALSE );
               return 0.0;
           }
           break;
@@ -517,11 +529,11 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
       }
 
       default:
-        CPLAssert( FALSE );
+        //CPLAssert( FALSE );
         return 0.0;
     }
 
-    CPLAssert( FALSE );
+    //CPLAssert( FALSE );
     return 0.0;
 }
 
@@ -613,7 +625,7 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
                   return( *((GUInt16 *) abyData) );
               else
               {
-                  CPLAssert( FALSE );
+                  //CPLAssert( FALSE );
                   return 0;
               }
             
@@ -626,7 +638,7 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
                   return( *((GInt16 *) abyData) );
               else
               {
-                  CPLAssert( FALSE );
+                  //CPLAssert( FALSE );
                   return 0;
               }
             
@@ -637,14 +649,14 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
                   return( (int) *((double *) abyData) );
               else
               {
-                  CPLAssert( FALSE );
+                  //CPLAssert( FALSE );
                   return 0;
               }
 
             case NotBinary:            
             case FPReal:
             case FloatComplex:
-              CPLAssert( FALSE );
+              //CPLAssert( FALSE );
               return 0;
           }
           break;
@@ -652,11 +664,11 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
       }
 
       default:
-        CPLAssert( FALSE );
+        //CPLAssert( FALSE );
         return 0;
     }
 
-    CPLAssert( FALSE );
+    //CPLAssert( FALSE );
     return 0;
 }
 
diff --git a/frmts/iso8211/makefile.vc b/frmts/iso8211/makefile.vc
index bb1f98d..0fdab6d 100644
--- a/frmts/iso8211/makefile.vc
+++ b/frmts/iso8211/makefile.vc
@@ -26,12 +26,12 @@ iso8211.dll: $(OBJ) $(CPLLIB)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 
 
 8211view.exe:	8211view.obj $(OBJ) $(CPLLIB) 
-	$(CC) $(CFLAGS) 8211view.obj $(OBJ) $(CPLLIB) $(CURL_LIB) ../zlib/*.obj /link $(LINKER_FLAGS)
+	$(CC) $(CFLAGS) 8211view.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) ../zlib/*.obj /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 
 	del 8211view.obj
 
 8211dump.exe:	8211dump.obj $(OBJ) $(CPLLIB) 
-	$(CC) $(CFLAGS) 8211dump.obj $(OBJ) $(CPLLIB) $(CURL_LIB) ../zlib/*.obj  /link $(LINKER_FLAGS)
+	$(CC) $(CFLAGS) 8211dump.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) ../zlib/*.obj  /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 
 	del 8211dump.obj
 
diff --git a/frmts/jaxapalsar/jaxapalsardataset.cpp b/frmts/jaxapalsar/jaxapalsardataset.cpp
index af956c8..500dbcb 100644
--- a/frmts/jaxapalsar/jaxapalsardataset.cpp
+++ b/frmts/jaxapalsar/jaxapalsardataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jaxapalsardataset.cpp 22632 2011-07-02 11:49:27Z antonio $
+ * $Id: jaxapalsardataset.cpp 22636 2011-07-03 10:39:11Z rouault $
  *
  * Project:  PALSAR JAXA imagery reader
  * Purpose:  Support for PALSAR L1.1/1.5 imagery and appropriate metadata from
@@ -31,7 +31,7 @@
 
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jaxapalsardataset.cpp 22632 2011-07-02 11:49:27Z antonio $");
+CPL_CVSID("$Id: jaxapalsardataset.cpp 22636 2011-07-03 10:39:11Z rouault $");
 
 CPL_C_START
 void	GDALRegister_PALSARJaxa(void);
@@ -138,7 +138,8 @@ CPL_C_END
 /* a few useful enums */
 enum eFileType {
 	level_11 = 0,
-	level_15
+	level_15,
+    level_10
 };
 
 enum ePolarization {
@@ -231,6 +232,10 @@ PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDS,
         eDataType = GDT_CFloat32;
         nFileType = level_11;
     }
+    else if (nBitsPerSample == 8 && nSamplesPerGroup == 2) {
+        eDataType = GDT_CInt16; /* shuold be 2 x signed byte */
+        nFileType = level_10;
+    }
     else {
         eDataType = GDT_UInt16;
         nFileType = level_15;
@@ -243,8 +248,8 @@ PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDS,
     READ_CHAR_VAL( nRasterYSize, NUMBER_LINES_LENGTH, fp );
     VSIFSeekL( fp, SAR_DATA_RECORD_LENGTH_OFFSET, SEEK_SET );
     READ_CHAR_VAL( nRecordSize, SAR_DATA_RECORD_LENGTH_LENGTH, fp );
-    nRasterXSize = (nRecordSize - 
-                    (nFileType == level_11 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET))
+    nRasterXSize = (nRecordSize -
+                    (nFileType != level_15 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET))
         / ((nBitsPerSample / 8) * nSamplesPerGroup);
 
     poDS->nRasterXSize = nRasterXSize;
@@ -351,7 +356,11 @@ const GDAL_GCP *PALSARJaxaDataset::GetGCPs() {
 void PALSARJaxaDataset::ReadMetadata( PALSARJaxaDataset *poDS, VSILFILE *fp ) {
     /* seek to the end fo the leader file descriptor */
     VSIFSeekL( fp, LEADER_FILE_DESCRIPTOR_LENGTH, SEEK_SET );
-    if (poDS->nFileType == level_11) {
+    if (poDS->nFileType == level_10) {
+        poDS->SetMetadataItem( "PRODUCT_LEVEL", "1.0" );
+        poDS->SetMetadataItem( "AZIMUTH_LOOKS", "1.0" );
+    }
+    else if (poDS->nFileType == level_11) {
         poDS->SetMetadataItem( "PRODUCT_LEVEL", "1.1" );
         poDS->SetMetadataItem( "AZIMUTH_LOOKS", "1.0" );
     }
@@ -459,7 +468,7 @@ void PALSARJaxaDataset::ReadMetadata( PALSARJaxaDataset *poDS, VSILFILE *fp ) {
 /************************************************************************/
 
 int PALSARJaxaDataset::Identify( GDALOpenInfo *poOpenInfo ) {
-    if ( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 360 )
+    if ( poOpenInfo->nHeaderBytes < 360 )
         return 0;
 
     /* First, check that this is a PALSAR image indeed */
@@ -582,6 +591,16 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to find any image data. Aborting opening as PALSAR image.");
         delete poDS;
+        VSIFree( pszSuffix );
+        return NULL;
+    }
+
+    /* Level 1.0 products are not supported */
+    if (poDS->nFileType == level_10) {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ALOS PALSAR Level 1.0 products are not supported. Aborting opening as PALSAR image.");
+        delete poDS;
+        VSIFree( pszSuffix );
         return NULL;
     }
 
@@ -633,6 +652,8 @@ void GDALRegister_PALSARJaxa() {
                                    "frmt_palsar.html" );
         poDriver->pfnOpen = PALSARJaxaDataset::Open;
         poDriver->pfnIdentify = PALSARJaxaDataset::Identify;
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
 }
diff --git a/frmts/jdem/jdemdataset.cpp b/frmts/jdem/jdemdataset.cpp
index 8a8dd36..9cf5719 100644
--- a/frmts/jdem/jdemdataset.cpp
+++ b/frmts/jdem/jdemdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jdemdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: jdemdataset.cpp 21837 2011-02-24 21:16:42Z rouault $
  *
  * Project:  JDEM Reader
  * Purpose:  All code for Japanese DEM Reader
@@ -29,7 +29,7 @@
 
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jdemdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: jdemdataset.cpp 21837 2011-02-24 21:16:42Z rouault $");
 
 CPL_C_START
 void	GDALRegister_JDEM(void);
@@ -89,9 +89,11 @@ class JDEMDataset : public GDALPamDataset
     GByte	abyHeader[1012];
 
   public:
-		~JDEMDataset();
+                     JDEMDataset();
+                    ~JDEMDataset();
     
     static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
 
     CPLErr 	GetGeoTransform( double * padfTransform );
     const char *GetProjectionRef();
@@ -208,7 +210,17 @@ CPLErr JDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 /************************************************************************/
-/*                            ~JDEMDataset()                             */
+/*                            JDEMDataset()                             */
+/************************************************************************/
+
+JDEMDataset::JDEMDataset() : fp(NULL)
+
+{
+    fp = NULL;
+}
+
+/************************************************************************/
+/*                           ~JDEMDataset()                             */
 /************************************************************************/
 
 JDEMDataset::~JDEMDataset()
@@ -256,10 +268,10 @@ const char *JDEMDataset::GetProjectionRef()
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                              Identify()                              */
 /************************************************************************/
 
-GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
+int JDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
 /* -------------------------------------------------------------------- */
@@ -267,7 +279,7 @@ GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      expected locations.  Sadly this is a relatively weak test.      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 50 )
-        return NULL;
+        return FALSE;
 
     /* check if century values seem reasonable */
     if( (!EQUALN((char *)poOpenInfo->pabyHeader+11,"19",2)
@@ -277,9 +289,22 @@ GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
         || (!EQUALN((char *)poOpenInfo->pabyHeader+19,"19",2)
              && !EQUALN((char *)poOpenInfo->pabyHeader+19,"20",2)) )
     {
-        return NULL;
+        return FALSE;
     }
-    
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if (!Identify(poOpenInfo))
+        return NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
@@ -299,6 +324,11 @@ GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS = new JDEMDataset();
 
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+    if (poDS->fp == NULL)
+    {
+        delete poDS;
+        return NULL;
+    }
     
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
@@ -354,8 +384,10 @@ void GDALRegister_JDEM()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_various.html#JDEM" );
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mem" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = JDEMDataset::Open;
+        poDriver->pfnIdentify = JDEMDataset::Identify;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/jp2kak/frmt_jp2kak.html b/frmts/jp2kak/frmt_jp2kak.html
index 1d1b630..122323d 100644
--- a/frmts/jp2kak/frmt_jp2kak.html
+++ b/frmts/jp2kak/frmt_jp2kak.html
@@ -35,6 +35,33 @@ and coordinate system information will be available if the file is a
 GeoJP2 (tm) file.  Files color encoded in YCbCr color space will be 
 automatically translated to RGB.  Paletted images are also supported.<P>
 
+Starting with GDAL 1.9.0, XMP metadata can be extracted from JPEG2000 files, and will be
+stored as XML raw content in the xml:XMP metadata domain.<p>
+
+<h2>Configuration Options</h2>
+
+The JP2KAK driver supports the following 
+<a href="http://trac.osgeo.org/gdal/ConfigOptions">Config Options</a>.
+These runtime options can be used to alter the behavior of the driver.
+
+<ul>
+<li> <b>JP2KAK_THREADS</b>=n: By default an effort is made to take advantage of
+multi-threading on multi-core computers using default rules from the Kakadu 
+library.  This option may be set to a value of zero to avoid using additional
+threads or to a specific count to create the requested number of worker threads.<p>
+
+<li> <b>JP2KAK_FUSSY</b>=YES/NO: This can be set to YES to turn on fussy reporting
+of problems with the JPEG2000 data stream.  Defaults to NO.<p>
+
+<li> <b>JP2KAK_RESILIENT</b>=YES/NO: This can be set to YES to force Kakadu to
+maximimize resilience with incorrectly created JPEG2000 data files, likely at
+some cost in performance.  This is likely to be necessary if, amoung other reasons,
+you get an error message about "Expected to find EPH marker following packet header"
+or error reports indicating the need to run with the resilient and sequential flags
+on.  Defaults to NO.<p>
+
+</ul>
+
 <h2>Creation Issues</h2>
 
 JPEG2000 files can only be created using the CreateCopy mechanism to
diff --git a/frmts/jp2kak/jp2kakdataset.cpp b/frmts/jp2kak/jp2kakdataset.cpp
index 5521f1c..bef828f 100644
--- a/frmts/jp2kak/jp2kakdataset.cpp
+++ b/frmts/jp2kak/jp2kakdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jp2kakdataset.cpp 22650 2011-07-06 00:59:22Z warmerdam $
+ * $Id: jp2kakdataset.cpp 23582 2011-12-17 00:15:35Z warmerdam $
  *
  * Project:  JPEG-2000
  * Purpose:  Implementation of the ISO/IEC 15444-1 standard based on Kakadu.
@@ -66,7 +66,7 @@
 
 // #define KAKADU_JPX	1
 
-CPL_CVSID("$Id: jp2kakdataset.cpp 22650 2011-07-06 00:59:22Z warmerdam $");
+CPL_CVSID("$Id: jp2kakdataset.cpp 23582 2011-12-17 00:15:35Z warmerdam $");
 
 static int kakadu_initialized = FALSE;
 
@@ -639,10 +639,24 @@ JP2KAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             pData, nBufXSize, nBufYSize, eBufType, 
             nPixelSpace, nLineSpace );
     else
+    {
+        int nOverviewDiscard = nDiscardLevels;
+
+        // Adjust request for overview level.
+        while( nOverviewDiscard > 0 )
+        {
+            nXOff  = nXOff * 2;
+            nYOff  = nYOff * 2;
+            nXSize = nXSize * 2;
+            nYSize = nYSize * 2;
+            nOverviewDiscard--;
+        }
+
         return poBaseDS->DirectRasterIO( 
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
             pData, nBufXSize, nBufYSize, eBufType, 
             1, &nBand, nPixelSpace, nLineSpace, 0 );
+    }
 }
 
 /************************************************************************/
@@ -1015,11 +1029,14 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !Identify( poOpenInfo ) )
         return NULL;
 
+    int bResilient = CSLTestBoolean(
+        CPLGetConfigOption( "JP2KAK_RESILIENT", "NO" ) );
+
 /* -------------------------------------------------------------------- */
 /*      Handle setting up datasource for JPIP.                          */
 /* -------------------------------------------------------------------- */
     KakaduInitialize();
-        
+
     pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
     if( poOpenInfo->nHeaderBytes < 16 )
     {
@@ -1037,7 +1054,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             try
             {
                 poRawInput = new subfile_source;
-                poRawInput->open( poOpenInfo->pszFilename );
+                poRawInput->open( poOpenInfo->pszFilename, bResilient );
                 poRawInput->seek( 0 );
 
                 poRawInput->read( abySubfileHeader, 16 );
@@ -1061,17 +1078,18 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we think this should be access via vsil, then open it        */
-/*      accordingly.                                                    */
+/*      If we think this should be access via vsil, then open it using  */
+/*      subfile_source.  We do this if it does not seem to open normally*/
+/*      or if we want to operate in resilient (sequential) mode.        */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->fp == NULL
-        && poRawInput == NULL
-        && !bIsJPIP )
+    if( poRawInput == NULL
+        && !bIsJPIP
+        && (bResilient || poOpenInfo->fp == NULL) )
     {
         try
         {
             poRawInput = new subfile_source;
-            poRawInput->open( poOpenInfo->pszFilename );
+            poRawInput->open( poOpenInfo->pszFilename, bResilient );
             poRawInput->seek( 0 );
         }
         catch( ... )
@@ -1216,8 +1234,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->oCodeStream.create( poInput );
         poDS->oCodeStream.set_persistent();
 
-        poDS->bResilient = CSLTestBoolean(
-            CPLGetConfigOption( "JP2KAK_RESILIENT", "NO" ) );
+        poDS->bResilient = bResilient;
         poDS->bFussy = CSLTestBoolean(
             CPLGetConfigOption( "JP2KAK_FUSSY", "NO" ) );
 
@@ -1296,8 +1313,8 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
         siz_params *siz = poDS->oCodeStream.access_siz();
         kdu_params *cod = siz->access_cluster(COD_params);
-        bool use_precincts; 
-        
+        bool use_precincts;
+
         cod->get(Cuse_precincts,0,0,use_precincts);
 
         const char *pszPersist = CPLGetConfigOption( "JP2KAK_PERSIST", "AUTO");
@@ -1308,7 +1325,7 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
                 > 100000000.0 )
                 poDS->bPreferNPReads = true;
         }
-        else 
+        else
             poDS->bPreferNPReads = !CSLTestBoolean(pszPersist);
 
         CPLDebug( "JP2KAK", "Cuse_precincts=%d, PreferNonPersistentReads=%d", 
@@ -1387,6 +1404,14 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
                 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?                                                */
@@ -1417,33 +1442,11 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Do we have other misc metadata?                                 */
 /* -------------------------------------------------------------------- */
-            if( CSLFetchNameValue( oJP2Geo.papszGMLMetadata,
-                                   "TIFFTAG_XRESOLUTION" ) != NULL )
+            if( oJP2Geo.papszMetadata != NULL )
             {
                 char **papszMD = poDS->GDALPamDataset::GetMetadata();
-                const char *pszItem;
-
-                pszItem = CSLFetchNameValue( oJP2Geo.papszGMLMetadata,
-                                             "TIFFTAG_XRESOLUTION" );
-                if( pszItem )
-                    papszMD = 
-                        CSLSetNameValue( papszMD, "TIFFTAG_XRESOLUTION", 
-                                         pszItem );
-                                         
-                pszItem = CSLFetchNameValue( oJP2Geo.papszGMLMetadata,
-                                             "TIFFTAG_YRESOLUTION" );
-                if( pszItem )
-                    papszMD = 
-                        CSLSetNameValue( papszMD, "TIFFTAG_YRESOLUTION", 
-                                         pszItem );
-                                         
-                pszItem = CSLFetchNameValue( oJP2Geo.papszGMLMetadata,
-                                             "TIFFTAG_RESOLUTIONUNIT" );
-                if( pszItem )
-                    papszMD = 
-                        CSLSetNameValue( papszMD, "TIFFTAG_RESOLUTIONUNIT", 
-                                         pszItem );
-                                         
+
+                papszMD = CSLMerge( papszMD, oJP2Geo.papszMetadata );
                 poDS->GDALPamDataset::SetMetadata( papszMD );
 
                 CSLDestroy( papszMD );
@@ -1582,8 +1585,8 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag eRWFlag,
 
     if( bPreferNPReads )
     {
-        subfile_src.open( GetDescription() );
-        
+        subfile_src.open( GetDescription(), bResilient );
+
         if( family != NULL )
         {
             wrk_family.open( &subfile_src );
@@ -1959,6 +1962,7 @@ static void JP2KAKWriteBox( jp2_target *jp2_out, GDALJP2Box *poBox )
         return;
 
     memcpy( &nBoxType, poBox->GetType(), 4 );
+    CPL_MSBPTR32( &nBoxType );
     
 /* -------------------------------------------------------------------- */
 /*      Write to a box on the JP2 file.                                 */
@@ -1966,7 +1970,7 @@ static void JP2KAKWriteBox( jp2_target *jp2_out, GDALJP2Box *poBox )
     jp2_out->open_next( nBoxType );
 
     jp2_out->write( (kdu_byte *) poBox->GetWritableData(), 
-                    poBox->GetDataLength() );
+                    (int) poBox->GetDataLength() );
 
     jp2_out->close();
 
@@ -1981,7 +1985,7 @@ static int
 JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                             kdu_roi_image *poROIImage, 
                             int nXOff, int nYOff, int nXSize, int nYSize,
-                            int bReversible, int nBits, GDALDataType eType,
+                            bool bReversible, int nBits, GDALDataType eType,
                             kdu_codestream &oCodeStream, int bFlushEnabled,
                             kdu_long *layer_bytes, int layer_count,
                             GDALProgressFunc pfnProgress, void * pProgressData,
@@ -2086,7 +2090,7 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                     kdu_sample32 *dest = lines[c].get_buf32();
                     kdu_byte *sp = pabyBuffer;
                     int nOffset = 1 << (nBits-1);
-                    float fScale = 1.0 / (1 << nBits);
+                    float fScale = (float) (1.0 / (1 << nBits));
                 
                     for (int n=nXSize; n > 0; n--, dest++, sp++)
                         dest->fval = (float) 
@@ -2096,7 +2100,7 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
                     GInt16  *sp = (GInt16 *) pabyBuffer;
-                    float fScale = 1.0 / (1 << nBits);
+                    float fScale = (float) (1.0 / (1 << nBits));
                 
                     for (int n=nXSize; n > 0; n--, dest++, sp++)
                         dest->fval = (float) 
@@ -2107,7 +2111,7 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                     kdu_sample32 *dest = lines[c].get_buf32();
                     GUInt16  *sp = (GUInt16 *) pabyBuffer;
                     int nOffset = 1 << (nBits-1);
-                    float fScale = 1.0 / (1 << nBits);
+                    float fScale = (float) (1.0 / (1 << nBits));
                 
                     for (int n=nXSize; n > 0; n--, dest++, sp++)
                         dest->fval = (float) 
@@ -2333,7 +2337,10 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
     bool bComseg;
 
-    bComseg = (bool) CSLFetchBoolean( papszOptions, "COMSEG", TRUE );
+    if( CSLFetchBoolean( papszOptions, "COMSEG", TRUE ) )
+        bComseg = true;
+    else
+        bComseg = false;
 
 /* -------------------------------------------------------------------- */
 /*      Work out the precision.                                         */
diff --git a/frmts/jp2kak/subfile_source.h b/frmts/jp2kak/subfile_source.h
index ac017c6..391f813 100644
--- a/frmts/jp2kak/subfile_source.h
+++ b/frmts/jp2kak/subfile_source.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: subfile_source.h 21098 2010-11-08 00:34:26Z warmerdam $
+ * $Id: subfile_source.h 23357 2011-11-07 18:34:42Z warmerdam $
  *
  * Project:  JPEG-2000
  * Purpose:  Implements read-only virtual io on a subregion of a file.
@@ -45,7 +45,7 @@ class subfile_source : public kdu_compressed_source {
 
     bool operator!() { return (file == NULL); }
 
-    void open(const char *fname )
+    void open(const char *fname, int bSequential )
       {
           const char *real_filename;
           close();
@@ -55,13 +55,13 @@ class subfile_source : public kdu_compressed_source {
               char** papszTokens = CSLTokenizeString2(fname + 12, ",", 0);
               if (CSLCount(papszTokens) >= 2)
               {
-                  subfile_offset = CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
-                  subfile_size = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
+                  subfile_offset = (int) CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
+                  subfile_size = (int) CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
               }
               else
               {
                   kdu_error e;
-                  
+
                   e << "Corrupt subfile definition:" << fname;
                   return;
               }
@@ -75,7 +75,7 @@ class subfile_source : public kdu_compressed_source {
               else
               {
                   kdu_error e;
-              
+
                   e << "Could not find filename in subfile definition." << fname;
                   return;
               }
@@ -96,7 +96,10 @@ class subfile_source : public kdu_compressed_source {
               return;
           }
 
-          capabilities = KDU_SOURCE_CAP_SEQUENTIAL | KDU_SOURCE_CAP_SEEKABLE;
+          if( bSequential ) 
+            capabilities = KDU_SOURCE_CAP_SEQUENTIAL;
+          else
+            capabilities = KDU_SOURCE_CAP_SEQUENTIAL | KDU_SOURCE_CAP_SEEKABLE;
 
           seek_origin = subfile_offset;
           seek( 0 );
@@ -163,4 +166,3 @@ class subfile_source : public kdu_compressed_source {
     
     VSILFILE *file;
   };
-
diff --git a/frmts/jp2kak/vsil_target.h b/frmts/jp2kak/vsil_target.h
index 3a54220..8fb6d70 100644
--- a/frmts/jp2kak/vsil_target.h
+++ b/frmts/jp2kak/vsil_target.h
@@ -70,7 +70,7 @@ public:
             if( file == NULL )
                 return false;
 
-            if( VSIFSeekL( file, SEEK_CUR, -1 * backtrack ) != 0 )
+            if( VSIFSeekL( file, VSIFTellL(file)-backtrack, SEEK_SET ) != 0 )
                 return false;
             else
                 return true;
diff --git a/frmts/jpeg/GNUmakefile b/frmts/jpeg/GNUmakefile
index da59fbb..e430373 100644
--- a/frmts/jpeg/GNUmakefile
+++ b/frmts/jpeg/GNUmakefile
@@ -19,6 +19,13 @@ OBJ	=	jpgdataset.o vsidataio.o
 XTRA_OPT	=	
 endif
 
+ifeq ($(TIFF_SETTING),internal)
+ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
+XTRA_OPT 	:=	$(XTRA_OPT) -DRENAME_INTERNAL_LIBTIFF_SYMBOLS
+endif
+XTRA_OPT	:=	$(XTRA_OPT) -I../gtiff/libtiff
+endif
+
 ifeq ($(JPEG12_ENABLED),yes)
 XTRA_OPT_12 	=	-Ilibjpeg12 -DDEFAULT_MAX_MEM=500000000L
 XTRA_OPT := -DJPEG_DUAL_MODE_8_12 $(XTRA_OPT)
diff --git a/frmts/jpeg/frmt_jpeg.html b/frmts/jpeg/frmt_jpeg.html
index 029bbd1..a9e222d 100644
--- a/frmts/jpeg/frmt_jpeg.html
+++ b/frmts/jpeg/frmt_jpeg.html
@@ -42,6 +42,9 @@ It is also possible to use the JPEG driver with the libjpeg-turbo, a
 version of libjpeg, API and ABI compatible with IJG libjpeg-6b, which uses MMX, SSE,
 and SSE2 SIMD instructions to accelerate baseline JPEG compression/decompression.<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>Creation Options</h2>
 
 JPEG files are created using the "JPEG" driver code.  Only Byte band types
diff --git a/frmts/jpeg/gdalexif.h b/frmts/jpeg/gdalexif.h
index dd1227b..edbe332 100644
--- a/frmts/jpeg/gdalexif.h
+++ b/frmts/jpeg/gdalexif.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalexif.h 17443 2009-07-25 09:27:02Z rouault $
+ * $Id: gdalexif.h 22639 2011-07-03 15:51:39Z rouault $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -33,6 +33,9 @@
 #define GPSOFFSETTAG     0x8825
 #define MAXSTRINGLENGTH 65535
 
+#ifdef RENAME_INTERNAL_LIBTIFF_SYMBOLS
+#include "gdal_libtiff_symbol_rename.h"
+#endif
 
 static const struct gpsname {
     GUInt16     tag;
diff --git a/frmts/jpeg/jpgdataset.cpp b/frmts/jpeg/jpgdataset.cpp
index f86eee0..2f6aced 100644
--- a/frmts/jpeg/jpgdataset.cpp
+++ b/frmts/jpeg/jpgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpgdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: jpgdataset.cpp 22847 2011-08-01 13:26:16Z rouault $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -38,7 +38,7 @@
 #include <setjmp.h>
 
 
-CPL_CVSID("$Id: jpgdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: jpgdataset.cpp 22847 2011-08-01 13:26:16Z rouault $");
 
 CPL_C_START
 #ifdef LIBJPEG_12_PATH 
@@ -48,12 +48,18 @@ CPL_C_START
 #endif
 CPL_C_END
 
+// we believe it is ok to use setjmp() in this situation.
+#ifdef _MSC_VER
+#  pragma warning(disable:4611)
+#endif
+
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
 GDALDataset* JPEGDataset12Open(GDALOpenInfo* poOpenInfo);
-GDALDataset*
-        JPEGCreateCopy12( const char * pszFilename, GDALDataset *poSrcDS, 
-                          int bStrict, char ** papszOptions, 
-                          GDALProgressFunc pfnProgress, void * pProgressData );
+GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
 #endif
 
 CPL_C_START
@@ -104,6 +110,7 @@ class JPGDataset : public GDALPamDataset
     GByte  *pabyScanline;
 
     int    bHasReadEXIFMetadata;
+    int    bHasReadXMPMetadata;
     char   **papszMetadata;
     char   **papszSubDatasets;
     int	   bigendian;
@@ -113,6 +120,7 @@ class JPGDataset : public GDALPamDataset
     int	   bSwabflag;
     int    nTiffDirStart;
     int    nTIFFHEADER;
+    int    bHasDoneJpegCreateDecompress;
     int    bHasDoneJpegStartDecompress;
 
     CPLErr LoadScanline(int);
@@ -129,6 +137,7 @@ class JPGDataset : public GDALPamDataset
     void   DecompressMask();
 
     void   ReadEXIFMetadata();
+    void   ReadXMPMetadata();
 
     int    bHasCheckedForMask;
     JPGMaskBand *poMaskBand;
@@ -140,6 +149,11 @@ class JPGDataset : public GDALPamDataset
     J_COLOR_SPACE eGDALColorSpace;   /* color space exposed by GDAL. Not necessarily the in_color_space nor */
                                      /* the out_color_space of JPEG library */
 
+    int    bIsSubfile;
+    int    bHasTriedLoadWorldFileOrTab;
+    void   LoadWorldFileOrTab();
+    CPLString osWldFilename;
+
   public:
                  JPGDataset();
                  ~JPGDataset();
@@ -158,9 +172,15 @@ class JPGDataset : public GDALPamDataset
     virtual const char *GetMetadataItem( const char * pszName,
                                          const char * pszDomain = "" );
 
+    virtual char **GetFileList(void);
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
+    static GDALDataset* CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
 
     static void ErrorExit(j_common_ptr cinfo);
 };
@@ -252,13 +272,93 @@ void JPGDataset::ReadEXIFMetadata()
 }
 
 /************************************************************************/
+/*                        ReadXMPMetadata()                             */
+/************************************************************************/
+
+/* See §2.1.3 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
+
+void JPGDataset::ReadXMPMetadata()
+{
+    if (bHasReadXMPMetadata)
+        return;
+
+    /* Save current position to avoid disturbing JPEG stream decoding */
+    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+
+/* -------------------------------------------------------------------- */
+/*      Search for APP1 chunk.                                          */
+/* -------------------------------------------------------------------- */
+    GByte abyChunkHeader[2+2+29];
+    int nChunkLoc = 2;
+    int bFoundXMP = TRUE;
+
+    for( ; TRUE; )
+    {
+        if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
+            break;
+
+        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage ) != 1 )
+            break;
+
+        if( abyChunkHeader[0] != 0xFF
+            || (abyChunkHeader[1] & 0xf0) != 0xe0 )
+            break; // Not an APP chunk.
+
+        if( abyChunkHeader[1] == 0xe1
+            && strncmp((const char *) abyChunkHeader + 4,"http://ns.adobe.com/xap/1.0/",28) == 0 )
+        {
+            bFoundXMP = TRUE;
+            break; // APP1 - XMP
+        }
+
+        nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
+    }
+
+    if (bFoundXMP)
+    {
+        int nXMPLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
+        if (nXMPLength > 2 + 29)
+        {
+            char* pszXMP = (char*)VSIMalloc(nXMPLength - 2 - 29 + 1);
+            if (pszXMP)
+            {
+                if (VSIFReadL( pszXMP, nXMPLength - 2 - 29, 1, fpImage ) == 1)
+                {
+                    pszXMP[nXMPLength - 2 - 29] = '\0';
+
+                    /* Avoid setting the PAM dirty bit just for that */
+                    int nOldPamFlags = nPamFlags;
+
+                    char *apszMDList[2];
+                    apszMDList[0] = pszXMP;
+                    apszMDList[1] = NULL;
+                    SetMetadata(apszMDList, "xml:XMP");
+
+                    nPamFlags = nOldPamFlags;
+                }
+                VSIFree(pszXMP);
+            }
+        }
+    }
+
+    VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+
+    bHasReadXMPMetadata = TRUE;
+}
+
+/************************************************************************/
 /*                           GetMetadata()                              */
 /************************************************************************/
 char  **JPGDataset::GetMetadata( const char * pszDomain )
 {
+    if (fpImage == NULL)
+        return NULL;
     if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
         (pszDomain == NULL || EQUAL(pszDomain, "")))
         ReadEXIFMetadata();
+    if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
+        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        ReadXMPMetadata();
     return GDALPamDataset::GetMetadata(pszDomain);
 }
 
@@ -268,10 +368,15 @@ char  **JPGDataset::GetMetadata( const char * pszDomain )
 const char *JPGDataset::GetMetadataItem( const char * pszName,
                                          const char * pszDomain )
 {
+    if (fpImage == NULL)
+        return NULL;
     if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
         (pszDomain == NULL || EQUAL(pszDomain, "")) &&
         pszName != NULL && EQUALN(pszName, "EXIF_", 5))
         ReadEXIFMetadata();
+    if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
+        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        ReadXMPMetadata();
     return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
 }
 
@@ -452,7 +557,7 @@ int JPGDataset::EXIFInit(VSILFILE *fp)
             || (abyChunkHeader[1] & 0xf0) != 0xe0 )
             return FALSE; // Not an APP chunk.
 
-        if( abyChunkHeader[1] == 0xe1 
+        if( abyChunkHeader[1] == 0xe1
             && strncmp((const char *) abyChunkHeader + 4,"Exif",4) == 0 )
         {
             nTIFFHEADER = nChunkLoc + 10;
@@ -848,6 +953,12 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     
     CPLAssert( nBlockXOff == 0 );
 
+    if (poGDS->fpImage == NULL)
+    {
+        memset( pImage, 0, nXSize * nWordSize );
+        return CE_None;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Load the desired scanline into the working buffer.              */
 /* -------------------------------------------------------------------- */
@@ -887,7 +998,7 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 {
                     int C = poGDS->pabyScanline[i * 4 + 0];
                     int K = poGDS->pabyScanline[i * 4 + 3];
-                    ((GByte*)pImage)[i] = (C * K) / 255;
+                    ((GByte*)pImage)[i] = (GByte) ((C * K) / 255);
                 }
             }
             else  if (nBand == 2)
@@ -896,7 +1007,7 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 {
                     int M = poGDS->pabyScanline[i * 4 + 1];
                     int K = poGDS->pabyScanline[i * 4 + 3];
-                    ((GByte*)pImage)[i] = (M * K) / 255;
+                    ((GByte*)pImage)[i] = (GByte) ((M * K) / 255);
                 }
             }
             else if (nBand == 3)
@@ -905,7 +1016,7 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 {
                     int Y = poGDS->pabyScanline[i * 4 + 2];
                     int K = poGDS->pabyScanline[i * 4 + 3];
-                    ((GByte*)pImage)[i] = (Y * K) / 255;
+                    ((GByte*)pImage)[i] = (GByte) ((Y * K) / 255);
                 }
             }
         }
@@ -931,7 +1042,8 @@ CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         {
             poBlock = 
                 poGDS->GetRasterBand(iBand)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
-            poBlock->DropLock();
+            if( poBlock != NULL )
+                poBlock->DropLock();
         }
     }
 
@@ -1003,6 +1115,9 @@ GDALColorInterp JPGRasterBand::GetColorInterpretation()
 GDALRasterBand *JPGRasterBand::GetMaskBand()
 
 {
+    if (poGDS->fpImage == NULL)
+        return NULL;
+
     if( !poGDS->bHasCheckedForMask)
     {
         poGDS->CheckForMask();
@@ -1026,6 +1141,9 @@ GDALRasterBand *JPGRasterBand::GetMaskBand()
 int JPGRasterBand::GetMaskFlags()
 
 {
+    if (poGDS->fpImage == NULL)
+        return 0;
+
     GetMaskBand();
     if( poGDS->poMaskBand != NULL )
         return GMF_PER_DATASET;
@@ -1047,10 +1165,13 @@ int JPGRasterBand::GetMaskFlags()
 JPGDataset::JPGDataset()
 
 {
+    fpImage = NULL;
+
     pabyScanline = NULL;
     nLoadedScanline = -1;
 
     bHasReadEXIFMetadata = FALSE;
+    bHasReadXMPMetadata = FALSE;
     papszMetadata   = NULL;
     papszSubDatasets= NULL;
     nExifOffset     = -1;
@@ -1068,6 +1189,7 @@ JPGDataset::JPGDataset()
     nGCPCount = 0;
     pasGCPList = NULL;
 
+    bHasDoneJpegCreateDecompress = FALSE;
     bHasDoneJpegStartDecompress = FALSE;
 
     bHasCheckedForMask = FALSE;
@@ -1077,6 +1199,11 @@ JPGDataset::JPGDataset()
     nCMaskSize = 0;
 
     eGDALColorSpace = JCS_UNKNOWN;
+
+    sDInfo.data_precision = 8;
+
+    bIsSubfile = FALSE;
+    bHasTriedLoadWorldFileOrTab = FALSE;
 }
 
 /************************************************************************/
@@ -1088,8 +1215,14 @@ JPGDataset::~JPGDataset()
 {
     FlushCache();
 
-    jpeg_abort_decompress( &sDInfo );
-    jpeg_destroy_decompress( &sDInfo );
+    if (bHasDoneJpegStartDecompress)
+    {
+        jpeg_abort_decompress( &sDInfo );
+    }
+    if (bHasDoneJpegCreateDecompress)
+    {
+        jpeg_destroy_decompress( &sDInfo );
+    }
 
     if( fpImage != NULL )
         VSIFCloseL( fpImage );
@@ -1387,6 +1520,8 @@ void JPGDataset::Restart()
 CPLErr JPGDataset::GetGeoTransform( double * padfTransform )
 
 {
+    LoadWorldFileOrTab();
+
     if( bGeoTransformValid )
     {
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
@@ -1404,6 +1539,8 @@ CPLErr JPGDataset::GetGeoTransform( double * padfTransform )
 int JPGDataset::GetGCPCount()
 
 {
+    LoadWorldFileOrTab();
+
     return nGCPCount;
 }
 
@@ -1414,6 +1551,8 @@ int JPGDataset::GetGCPCount()
 const char *JPGDataset::GetGCPProjection()
 
 {
+    LoadWorldFileOrTab();
+
     if( pszProjection && nGCPCount > 0 )
         return pszProjection;
     else
@@ -1427,6 +1566,8 @@ const char *JPGDataset::GetGCPProjection()
 const GDAL_GCP *JPGDataset::GetGCPs()
 
 {
+    LoadWorldFileOrTab();
+
     return pasGCPList;
 }
 
@@ -1597,8 +1738,7 @@ GDALDataset *JPGDataset::Open( GDALOpenInfo * poOpenInfo )
     const char *real_filename = poOpenInfo->pszFilename;
     int nQLevel = -1;
 
-    if( ( poOpenInfo->fp == NULL ) &&
-        ( EQUALN(poOpenInfo->pszFilename,"JPEG_SUBFILE:",13) ) )
+    if( EQUALN(poOpenInfo->pszFilename,"JPEG_SUBFILE:",13) )
     {
         char** papszTokens;
         int bScan = FALSE;
@@ -1657,28 +1797,28 @@ GDALDataset *JPGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
-    JPGDataset	*poDS;
-
-    poDS = new JPGDataset();
-    poDS->nQLevel = nQLevel;
-
-/* -------------------------------------------------------------------- */
 /*      Open the file using the large file api.                         */
 /* -------------------------------------------------------------------- */
-    poDS->fpImage = VSIFOpenL( real_filename, "rb" );
-    
-    if( poDS->fpImage == NULL )
+    VSILFILE* fpImage = VSIFOpenL( real_filename, "rb" );
+
+    if( fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp", 
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
                   real_filename );
-        delete poDS;
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    JPGDataset	*poDS;
+
+    poDS = new JPGDataset();
+    poDS->nQLevel = nQLevel;
+    poDS->fpImage = fpImage;
+
+/* -------------------------------------------------------------------- */
 /*      Move to the start of jpeg data.                                 */
 /* -------------------------------------------------------------------- */
     poDS->nSubfileOffset = subfile_offset;
@@ -1691,6 +1831,7 @@ GDALDataset *JPGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->sDInfo.client_data = (void *) &(poDS->setjmp_buffer);
 
     jpeg_create_decompress( &(poDS->sDInfo) );
+    poDS->bHasDoneJpegCreateDecompress = TRUE;
 
     /* This is to address bug related in ticket #1795 */
     if (CPLGetConfigOption("JPEGMEM", NULL) == NULL)
@@ -1829,43 +1970,86 @@ GDALDataset *JPGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     
     if( !bIsSubfile )
-        poDS->TryLoadXML();
+        poDS->TryLoadXML( poOpenInfo->papszSiblingFiles );
     else
         poDS->nPamFlags |= GPF_NOSAVE;
 
 /* -------------------------------------------------------------------- */
 /*      Open overviews.                                                 */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, real_filename );
+    poDS->oOvManager.Initialize( poDS, real_filename, poOpenInfo->papszSiblingFiles );
 
-/* -------------------------------------------------------------------- */
-/*      Check for world file.                                           */
-/* -------------------------------------------------------------------- */
-    if( !bIsSubfile )
+    poDS->bIsSubfile = bIsSubfile;
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                       LoadWorldFileOrTab()                           */
+/************************************************************************/
+
+void JPGDataset::LoadWorldFileOrTab()
+{
+    if (bIsSubfile)
+        return;
+    if (bHasTriedLoadWorldFileOrTab)
+        return;
+    bHasTriedLoadWorldFileOrTab = TRUE;
+
+    char* pszWldFilename = NULL;
+
+    /* TIROS3 JPEG files have a .wld extension, so don't look for .wld as */
+    /* as worldfile ! */
+    int bEndsWithWld = strlen(GetDescription()) > 4 &&
+                        EQUAL( GetDescription() + strlen(GetDescription()) - 4, ".wld");
+    bGeoTransformValid =
+        GDALReadWorldFile2( GetDescription(), NULL,
+                            adfGeoTransform,
+                            oOvManager.GetSiblingFiles(), &pszWldFilename )
+        || GDALReadWorldFile2( GetDescription(), ".jpw",
+                                adfGeoTransform,
+                               oOvManager.GetSiblingFiles(), &pszWldFilename )
+        || ( !bEndsWithWld && GDALReadWorldFile2( GetDescription(), ".wld",
+                                adfGeoTransform,
+                                oOvManager.GetSiblingFiles(), &pszWldFilename ));
+
+    if( !bGeoTransformValid )
     {
-        int bEndsWithWld = strlen(poOpenInfo->pszFilename) > 4 &&
-                           EQUAL( poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename) - 4, ".wld");
-        poDS->bGeoTransformValid = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, NULL, 
-                               poDS->adfGeoTransform )
-            || GDALReadWorldFile( poOpenInfo->pszFilename, ".jpw", 
-                                  poDS->adfGeoTransform )
-            || ( !bEndsWithWld && GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
-                                  poDS->adfGeoTransform ));
-
-        if( !poDS->bGeoTransformValid )
-        {
-            int bTabFileOK =
-                GDALReadTabFile( poOpenInfo->pszFilename, poDS->adfGeoTransform,
-                                 &poDS->pszProjection,
-                                 &poDS->nGCPCount, &poDS->pasGCPList );
-            
-            if( bTabFileOK && poDS->nGCPCount == 0 )
-                poDS->bGeoTransformValid = TRUE;
-        }
+        int bTabFileOK =
+            GDALReadTabFile2( GetDescription(), adfGeoTransform,
+                              &pszProjection,
+                              &nGCPCount, &pasGCPList,
+                              oOvManager.GetSiblingFiles(), &pszWldFilename );
+
+        if( bTabFileOK && nGCPCount == 0 )
+            bGeoTransformValid = TRUE;
     }
 
-    return poDS;
+    if (pszWldFilename)
+    {
+        osWldFilename = pszWldFilename;
+        CPLFree(pszWldFilename);
+    }
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **JPGDataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+    LoadWorldFileOrTab();
+
+    if (osWldFilename.size() != 0 &&
+        CSLFindString(papszFileList, osWldFilename) == -1)
+    {
+        papszFileList = CSLAddString( papszFileList, osWldFilename );
+    }
+
+    return papszFileList;
 }
 
 /************************************************************************/
@@ -2019,6 +2203,11 @@ void JPGDataset::ErrorExit(j_common_ptr cinfo)
 /*      file (or really any file) pulled from an existing mask band.    */
 /************************************************************************/
 
+// MSVC does not know that memset() has initialized sStream.
+#ifdef _MSC_VER
+#  pragma warning(disable:4701)
+#endif
+
 static void JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask )
 
 {
@@ -2122,7 +2311,7 @@ static void JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask )
         {
             VSIFSeekL( fpOut, 0, SEEK_END );
 
-            nImageSize = VSIFTellL( fpOut );
+            nImageSize = (GUInt32) VSIFTellL( fpOut );
             CPL_LSBPTR32( &nImageSize );
 
             if( VSIFWriteL( pabyCMask, 1, sStream.total_out, fpOut ) 
@@ -2145,13 +2334,13 @@ static void JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask )
 }
 
 /************************************************************************/
-/*                           JPEGCreateCopy()                           */
+/*                              CreateCopy()                            */
 /************************************************************************/
 
 GDALDataset *
-JPEGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                int bStrict, char ** papszOptions, 
-                GDALProgressFunc pfnProgress, void * pProgressData )
+JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                        int bStrict, char ** papszOptions,
+                        GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
     int  nBands = poSrcDS->GetRasterCount();
@@ -2205,7 +2394,7 @@ JPEGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( eDT == GDT_UInt16 || eDT == GDT_Int16 )
     {
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
-        return JPEGCreateCopy12(pszFilename, poSrcDS,
+        return JPEGDataset12CreateCopy(pszFilename, poSrcDS,
                                 bStrict, papszOptions, 
                                 pfnProgress, pProgressData );
 #else
@@ -2416,12 +2605,27 @@ JPEGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxilary pam information.         */
 /* -------------------------------------------------------------------- */
-    JPGDataset *poDS = (JPGDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+    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);
+    JPGDataset *poDS = (JPGDataset*) JPGDataset::Open( &oOpenInfo );
+    CPLPopErrorHandler();
     if( poDS )
+    {
         poDS->CloneInfo( poSrcDS, nCloneFlags );
+        return poDS;
+    }
 
-    return poDS;
+    CPLErrorReset();
+
+    JPGDataset* poJPG_DS = new JPGDataset();
+    poJPG_DS->nRasterXSize = nXSize;
+    poJPG_DS->nRasterYSize = nYSize;
+    for(int i=0;i<nBands;i++)
+        poJPG_DS->SetBand( i+1, new JPGRasterBand( poJPG_DS, i+1) );
+    return poJPG_DS;
 }
 
 /************************************************************************/
@@ -2464,7 +2668,7 @@ void GDALRegister_JPEG()
 
         poDriver->pfnIdentify = JPGDataset::Identify;
         poDriver->pfnOpen = JPGDataset::Open;
-        poDriver->pfnCreateCopy = JPEGCreateCopy;
+        poDriver->pfnCreateCopy = JPGDataset::CreateCopy;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/jpeg/jpgdataset_12.cpp b/frmts/jpeg/jpgdataset_12.cpp
index 16aaa03..79d70fb 100644
--- a/frmts/jpeg/jpgdataset_12.cpp
+++ b/frmts/jpeg/jpgdataset_12.cpp
@@ -3,11 +3,22 @@
 #define JPGDataset        JPGDataset12
 #define JPGRasterBand     JPGRasterBand12
 #define JPGMaskBand       JPGMaskBand12
-#define JPEGCreateCopy    JPEGCreateCopy12
 #include "jpgdataset.cpp"
 
 GDALDataset* JPEGDataset12Open(GDALOpenInfo* poOpenInfo)
 {
     return JPGDataset12::Open(poOpenInfo);
 }
+
+GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData )
+{
+    return JPGDataset12::CreateCopy(pszFilename, poSrcDS,
+                                    bStrict, papszOptions,
+                                    pfnProgress, pProgressData);
+}
+
 #endif /* defined(JPEG_DUAL_MODE_8_12) */
diff --git a/frmts/jpeg/libjpeg/makefile.vc b/frmts/jpeg/libjpeg/makefile.vc
index aa5533a..88be6c1 100644
--- a/frmts/jpeg/libjpeg/makefile.vc
+++ b/frmts/jpeg/libjpeg/makefile.vc
@@ -14,7 +14,7 @@ OBJ	=	\
 
 GDAL_ROOT	=	..\..\..
 
-EXTRAFLAGS      = -DDEFAULT_MAX_MEM=500000000L
+EXTRAFLAGS      = -DDEFAULT_MAX_MEM=500000000L $(SOFTWARNFLAGS)
 
 default:	$(OBJ)
         lib /out:libjpeg.lib $(OBJ)
diff --git a/frmts/jpeg/libjpeg12/makefile.vc b/frmts/jpeg/libjpeg12/makefile.vc
index 8f9fcd1..389ebf4 100644
--- a/frmts/jpeg/libjpeg12/makefile.vc
+++ b/frmts/jpeg/libjpeg12/makefile.vc
@@ -14,7 +14,7 @@ OBJ	=	\
 
 GDAL_ROOT	=	..\..\..
 
-EXTRAFLAGS      = -DDEFAULT_MAX_MEM=500000000L
+EXTRAFLAGS      = -DDEFAULT_MAX_MEM=500000000L $(SOFTWARNFLAGS) 
 
 default:	jcapimin12.c $(OBJ)
 	xcopy /D  /Y *.obj ..\..\o
diff --git a/frmts/jpeg/makefile.vc b/frmts/jpeg/makefile.vc
index f33f39d..777ed3c 100644
--- a/frmts/jpeg/makefile.vc
+++ b/frmts/jpeg/makefile.vc
@@ -8,7 +8,7 @@ OBJ	=    jpgdataset.obj jpgdataset_12.obj vsidataio.obj
 !IFDEF JPEG_EXTERNAL_LIB
 EXTRAFLAGS      = -I..\zlib -I$(JPEGDIR)
 !ELSE
-EXTRAFLAGS = 	-I..\zlib -Ilibjpeg $(JPEG12_FLAGS) 
+EXTRAFLAGS = 	-I..\zlib -Ilibjpeg $(JPEG12_FLAGS)
 !ENDIF
 
 !IFDEF JPEG12_SUPPORTED
diff --git a/frmts/jpeg2000/frmt_jpeg2000.html b/frmts/jpeg2000/frmt_jpeg2000.html
index 19ba461..8e70e87 100644
--- a/frmts/jpeg2000/frmt_jpeg2000.html
+++ b/frmts/jpeg2000/frmt_jpeg2000.html
@@ -8,7 +8,10 @@
 
 <h1>JPEG2000 --- Implementation of the JPEG-2000 part 1</h1>
 
-This implementation based on JasPer software (see below).
+This implementation based on JasPer software (see below).<p>
+
+Starting with GDAL 1.9.0, XMP metadata can be extracted from JPEG2000 files, and will be
+stored as XML raw content in the xml:XMP metadata domain.<p>
 
 <h2>Creation Options</h2>
 <ul>
diff --git a/frmts/jpeg2000/jpeg2000dataset.cpp b/frmts/jpeg2000/jpeg2000dataset.cpp
index 1b93336..356f049 100644
--- a/frmts/jpeg2000/jpeg2000dataset.cpp
+++ b/frmts/jpeg2000/jpeg2000dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeg2000dataset.cpp 20599 2010-09-12 22:13:18Z rouault $
+ * $Id: jpeg2000dataset.cpp 22678 2011-07-09 19:47:12Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Partial implementation of the ISO/IEC 15444-1 standard
@@ -34,7 +34,7 @@
 #include <jasper/jasper.h>
 #include "jpeg2000_vsil_io.h"
 
-CPL_CVSID("$Id: jpeg2000dataset.cpp 20599 2010-09-12 22:13:18Z rouault $");
+CPL_CVSID("$Id: jpeg2000dataset.cpp 22678 2011-07-09 19:47:12Z rouault $");
 
 CPL_C_START
 void    GDALRegister_JPEG2000(void);
@@ -849,6 +849,14 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
             GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
     }
 
+    if (oJP2Geo.pszXMPMetadata)
+    {
+        char *apszMDList[2];
+        apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
+        apszMDList[1] = NULL;
+        poDS->SetMetadata(apszMDList, "xml:XMP");
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/jpipkak/jpipkak.html b/frmts/jpipkak/frmt_jpipkak.html
similarity index 100%
copy from frmts/jpipkak/jpipkak.html
copy to frmts/jpipkak/frmt_jpipkak.html
diff --git a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
index 4edb021..b95393b 100644
--- a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
+++ b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
@@ -63,6 +63,9 @@ void GenerateTiles(std::string filename,
    
     GByte* pafScanline = new GByte[dxsize];
     bool* hadnoData = new bool[dxsize];
+
+    if (isJpegDriver && bands == 4)
+        bands = 3;
    
     poTmpDataset = poMemDriver->Create("", dxsize, dysize, bands, GDT_Byte, NULL);
    
@@ -181,7 +184,8 @@ void GenerateTiles(std::string filename,
     GDALDataset* outDs = poOutputTileDriver->CreateCopy(filename.c_str(), poTmpDataset, FALSE, NULL, NULL, NULL);
 
     GDALClose(poTmpDataset);
-    GDALClose(outDs);
+    if (outDs)
+        GDALClose(outDs);
 }
 
 /************************************************************************/
@@ -351,10 +355,10 @@ int  GenerateChildKml(std::string filename,
     VSIFPrintfL(fp, "\t\t\t</Icon>\n");
     VSIFPrintfL(fp, "\t\t\t<gx:LatLonQuad>\n");
     VSIFPrintfL(fp, "\t\t\t\t<coordinates>\n");
-    VSIFPrintfL(fp, "\t\t\t\t\t%f, %f, 0\n", lowerleftT, leftbottomT);
-    VSIFPrintfL(fp, "\t\t\t\t\t%f, %f, 0\n", lowerrightT, rightbottomT);
-    VSIFPrintfL(fp, "\t\t\t\t\t%f, %f, 0\n", upperrightT, righttopT);
-    VSIFPrintfL(fp, "\t\t\t\t\t%f, %f, 0\n", upperleftT, lefttopT);
+    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", lowerleftT, leftbottomT);
+    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", lowerrightT, rightbottomT);
+    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", upperrightT, righttopT);
+    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", upperleftT, lefttopT);
     VSIFPrintfL(fp, "\t\t\t\t</coordinates>\n");
     VSIFPrintfL(fp, "\t\t\t</gx:LatLonQuad>\n");
     VSIFPrintfL(fp, "\t\t</GroundOverlay>\n");
@@ -578,6 +582,10 @@ GDALDataset *KmlSuperOverlayDataset::CreateCopy( const char * pszFilename, GDALD
                                                  int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData)
 {
     bool isKmz = false;
+
+    int bands = poSrcDS->GetRasterCount();
+    if (bands != 1 && bands != 3 && bands != 4)
+        return NULL;
    
     //correct the file and get the directory
     char* output_dir = NULL;
@@ -647,7 +655,6 @@ GDALDataset *KmlSuperOverlayDataset::CreateCopy( const char * pszFilename, GDALD
         return NULL;
     }
 
-    int bands = poSrcDS->GetRasterCount();
     int xsize = poSrcDS->GetRasterXSize();
     int ysize = poSrcDS->GetRasterYSize();
 
@@ -719,6 +726,7 @@ GDALDataset *KmlSuperOverlayDataset::CreateCopy( const char * pszFilename, GDALD
         tileysize = (int)dtileysize;
         tilexsize = (int)( (double)(dtileysize * xsize) / ysize );
     }
+    maxzoom = 0;
 
     std::vector<double> zoomxpixels;
     std::vector<double> zoomypixels;
@@ -730,7 +738,6 @@ GDALDataset *KmlSuperOverlayDataset::CreateCopy( const char * pszFilename, GDALD
     }
 
     std::string tmpFileName; 
-    std::vector<std::string> dirVector;
     std::vector<std::string> fileVector;
     int nRet;
     if (isKmz)
@@ -784,18 +791,14 @@ GDALDataset *KmlSuperOverlayDataset::CreateCopy( const char * pszFilename, GDALD
                 ixStr << ix;
                 iyStr << iy;
 
-                std::string zoomDir = outDir + "/" + zoomStr.str();
+                std::string zoomDir = outDir;
+                zoomDir+= "/" + zoomStr.str();
                 VSIMkdir(zoomDir.c_str(), 0775);
         
 
                 zoomDir = zoomDir + "/" + ixStr.str();
                 VSIMkdir(zoomDir.c_str(), 0775);
 
-                if (isKmz)
-                {
-                    dirVector.push_back(zoomDir);
-                }
-
                 std::string fileExt = ".jpg";
                 if (isJpegDriver == false)
                 {
diff --git a/frmts/l1b/l1bdataset.cpp b/frmts/l1b/l1bdataset.cpp
index e5bacbc..460d74d 100644
--- a/frmts/l1b/l1bdataset.cpp
+++ b/frmts/l1b/l1bdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: l1bdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: l1bdataset.cpp 22715 2011-07-12 10:34:07Z rouault $
  *
  * Project:  NOAA Polar Orbiter Level 1b Dataset Reader (AVHRR)
  * Purpose:  Can read NOAA-9(F)-NOAA-17(M) AVHRR datasets
@@ -32,7 +32,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: l1bdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: l1bdataset.cpp 22715 2011-07-12 10:34:07Z rouault $");
 
 CPL_C_START
 void    GDALRegister_L1B(void);
@@ -646,8 +646,14 @@ void L1BDataset::ProcessRecordHeaders()
 /* -------------------------------------------------------------------- */
 /*      Initialize the GCP list.                                        */
 /* -------------------------------------------------------------------- */
-    pasGCPList = (GDAL_GCP *)CPLCalloc( nTargetLines * nGCPsPerLine,
+    pasGCPList = (GDAL_GCP *)VSICalloc( nTargetLines * nGCPsPerLine,
                                         sizeof(GDAL_GCP) );
+    if (pasGCPList == NULL)
+    {
+        CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
+        CPLFree( pRecordHeader );
+        return;
+    }
     GDALInitGCPs( nTargetLines * nGCPsPerLine, pasGCPList );
 
 /* -------------------------------------------------------------------- */
@@ -1584,9 +1590,6 @@ int L1BDataset::DetectFormat( GDALOpenInfo *poOpenInfo )
 int L1BDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if( poOpenInfo->fp == NULL )
-        return FALSE;
-
     if ( DetectFormat(poOpenInfo) == L1B_NONE )
         return FALSE;
 
@@ -1625,7 +1628,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
     L1BDataset  *poDS;
-    VSIStatBuf  sStat;
+    VSIStatBufL  sStat;
     const char  *pszFilename = poOpenInfo->pszFilename;
 
     poDS = new L1BDataset( eL1BFormat );
@@ -1646,7 +1649,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
         goto bad;
     }
 
-    CPLStat(pszFilename, &sStat);
+    VSIStatL(pszFilename, &sStat);
 
     if ( poDS->bGuessDataFormat )
     {
@@ -1817,6 +1820,11 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 
 bad:
@@ -1843,6 +1851,8 @@ void GDALRegister_L1B()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_l1b.html" );
 
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = L1BDataset::Open;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
diff --git a/frmts/leveller/levellerdataset.cpp b/frmts/leveller/levellerdataset.cpp
index fa6612c..c8dc83f 100644
--- a/frmts/leveller/levellerdataset.cpp
+++ b/frmts/leveller/levellerdataset.cpp
@@ -34,7 +34,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: levellerdataset.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: levellerdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 void	GDALRegister_Leveller(void);
@@ -488,8 +488,8 @@ CPLErr LevellerRasterBand::IWriteBlock
 		for(size_t x = 0; x < (size_t)nBlockXSize; x++)
 		{
 			// Convert logical elevations to physical.
-			m_pLine[x] = 
-				(pfImage[x] - ds.m_dElevBase) / ds.m_dElevScale;
+                    m_pLine[x] = (float) 
+				((pfImage[x] - ds.m_dElevBase) / ds.m_dElevScale);
 		}
 
 #ifdef CPL_MSB 
@@ -1567,6 +1567,11 @@ GDALDataset *LevellerDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
diff --git a/frmts/makefile.vc b/frmts/makefile.vc
index 7397abf..f8df3b0 100644
--- a/frmts/makefile.vc
+++ b/frmts/makefile.vc
@@ -13,7 +13,8 @@ EXTRAFLAGS =	-DFRMT_ceos -DFRMT_aigrid -DFRMT_elas -DFRMT_hfa -DFRMT_gtiff\
 		-DFRMT_gff -DFRMT_terragen -DFRMT_gsg -DFRMT_cosar -DFRMT_pds \
 		-DFRMT_adrg -DFRMT_coasp -DFRMT_tsx -DFRMT_blx -DFRMT_til \
 		-DFRMT_r -DFRMT_northwood -DFRMT_saga -DFRMT_xyz -DFRMT_hf2 \
-		-DFRMT_kmlsuperoverlay -DFRMT_ozi
+		-DFRMT_kmlsuperoverlay -DFRMT_ozi -DFRMT_ctg -DFRMT_e00grid \
+		-DFRMT_zmap -DFRMT_ngsgeoid
 
 MOREEXTRA 	=	
 
@@ -153,6 +154,18 @@ EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_rasterlite
 
 !IFDEF POPPLER_ENABLED
 EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_pdf
+!ELSE
+!IFDEF PODOFO_ENABLED
+EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_pdf
+!ENDIF
+!ENDIF
+
+!IFDEF WEBP_ENABLED
+EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_webp
+!ENDIF
+
+!IFDEF GTA_CFLAGS
+EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_gta
 !ENDIF
 
 default:	o\gdalallregister.obj subdirs
diff --git a/frmts/mem/memdataset.cpp b/frmts/mem/memdataset.cpp
index 04ac178..08aab83 100644
--- a/frmts/mem/memdataset.cpp
+++ b/frmts/mem/memdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: memdataset.cpp 21451 2011-01-09 22:07:21Z rouault $
+ * $Id: memdataset.cpp 21803 2011-02-22 22:12:22Z warmerdam $
  *
  * Project:  Memory Array Translator
  * Purpose:  Complete implementation.
@@ -30,7 +30,7 @@
 #include "memdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: memdataset.cpp 21451 2011-01-09 22:07:21Z rouault $");
+CPL_CVSID("$Id: memdataset.cpp 21803 2011-02-22 22:12:22Z warmerdam $");
 
 /************************************************************************/
 /*                        MEMCreateRasterBand()                         */
@@ -54,7 +54,7 @@ GDALRasterBandH MEMCreateRasterBand( GDALDataset *poDS, int nBand,
 MEMRasterBand::MEMRasterBand( GDALDataset *poDS, int nBand,
                               GByte *pabyDataIn, GDALDataType eTypeIn, 
                               int nPixelOffsetIn, int nLineOffsetIn,
-                              int bAssumeOwnership )
+                              int bAssumeOwnership, const char * pszPixelType)
 
 {
     //CPLDebug( "MEM", "MEMRasterBand(%p)", this );
@@ -91,6 +91,10 @@ MEMRasterBand::MEMRasterBand( GDALDataset *poDS, int nBand,
     dfOffset = 0.0;
     dfScale = 1.0;
     pszUnitType = NULL;
+    psSavedHistograms = NULL;
+
+    if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
+        this->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
 }
 
 /************************************************************************/
@@ -360,6 +364,90 @@ CPLErr MEMRasterBand::SetCategoryNames( char ** papszNewNames )
 }
 
 /************************************************************************/
+/*                        SetDefaultHistogram()                         */
+/************************************************************************/
+
+CPLErr MEMRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
+                                           int nBuckets, int *panHistogram)
+
+{
+    CPLXMLNode *psNode;
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a matching histogram we should replace?              */
+/* -------------------------------------------------------------------- */
+    psNode = PamFindMatchingHistogram( psSavedHistograms, 
+                                       dfMin, dfMax, nBuckets,
+                                       TRUE, TRUE );
+    if( psNode != NULL )
+    {
+        /* blow this one away */
+        CPLRemoveXMLChild( psSavedHistograms, psNode );
+        CPLDestroyXMLNode( psNode );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Translate into a histogram XML tree.                            */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psHistItem;
+
+    psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
+                                        panHistogram, TRUE, FALSE );
+
+/* -------------------------------------------------------------------- */
+/*      Insert our new default histogram at the front of the            */
+/*      histogram list so that it will be the default histogram.        */
+/* -------------------------------------------------------------------- */
+
+    if( psSavedHistograms == NULL )
+        psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
+                                              "Histograms" );
+            
+    psHistItem->psNext = psSavedHistograms->psChild;
+    psSavedHistograms->psChild = psHistItem;
+    
+    return CE_None;
+}
+/************************************************************************/
+/*                        GetDefaultHistogram()                         */
+/************************************************************************/
+
+CPLErr 
+MEMRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
+                                    int *pnBuckets, int **ppanHistogram, 
+                                    int bForce,
+                                    GDALProgressFunc pfnProgress, 
+                                    void *pProgressData )
+    
+{
+    if( psSavedHistograms != NULL )
+    {
+        CPLXMLNode *psXMLHist;
+
+        for( psXMLHist = psSavedHistograms->psChild;
+             psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
+        {
+            int bApprox, bIncludeOutOfRange;
+
+            if( psXMLHist->eType != CXT_Element
+                || !EQUAL(psXMLHist->pszValue,"HistItem") )
+                continue;
+
+            if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets, 
+                                   ppanHistogram, &bIncludeOutOfRange,
+                                   &bApprox ) )
+                return CE_None;
+            else
+                return CE_Failure;
+        }
+    }
+
+    return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets, 
+                                                ppanHistogram, bForce, 
+                                                pfnProgress,pProgressData);
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*      MEMDataset                                                     */
 /* ==================================================================== */
@@ -789,16 +877,16 @@ GDALDataset *MEMDataset::Create( const char * pszFilename,
         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
-    {
-        for( iBand = 0; iBand < nBands; iBand++ )
+        else
         {
+            for( iBand = 0; iBand < nBands; iBand++ )
+            {
             apbyBandData.push_back( 
                 (GByte *) VSIMalloc3( nWordSize, nXSize, nYSize ) );
             if( apbyBandData[iBand] == NULL )
@@ -808,7 +896,7 @@ GDALDataset *MEMDataset::Create( const char * pszFilename,
             }
             memset(apbyBandData[iBand], 0, ((size_t)nWordSize) * nXSize * nYSize);
         }
-    }
+            }
 
     if( !bAllocOK )
     {
@@ -817,10 +905,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.                             */
@@ -833,6 +921,10 @@ GDALDataset *MEMDataset::Create( const char * pszFilename,
     poDS->nRasterYSize = nYSize;
     poDS->eAccess = GA_Update;
 
+    const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" );
+    if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
+        poDS->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
+
     if( bPixelInterleaved )
         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
 
diff --git a/frmts/mem/memdataset.h b/frmts/mem/memdataset.h
index ab9bf7d..3edffe8 100644
--- a/frmts/mem/memdataset.h
+++ b/frmts/mem/memdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: memdataset.h 17601 2009-09-02 02:46:59Z warmerdam $
+ * $Id: memdataset.h 21803 2011-02-22 22:12:22Z warmerdam $
  *
  * Project:  Memory Array Translator
  * Purpose:  Declaration of MEMDataset, and MEMRasterBand.
@@ -108,12 +108,13 @@ class CPL_DLL MEMRasterBand : public GDALPamRasterBand
     double         dfOffset;
     double         dfScale;
 
+    CPLXMLNode    *psSavedHistograms;
   public:
 
                    MEMRasterBand( GDALDataset *poDS, int nBand,
                                   GByte *pabyData, GDALDataType eType,
                                   int nPixelOffset, int nLineOffset,
-                                  int bAssumeOwnership );
+                                  int bAssumeOwnership,  const char * pszPixelType = NULL);
     virtual        ~MEMRasterBand();
 
     // should override RasterIO eventually.
@@ -141,6 +142,13 @@ class CPL_DLL MEMRasterBand : public GDALPamRasterBand
     virtual double GetScale( int *pbSuccess = NULL );
     CPLErr SetScale( double );
 
+    virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
+                                        int nBuckets, int *panHistogram );
+    virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                        int *pnBuckets, int ** ppanHistogram,
+                                        int bForce,
+                                        GDALProgressFunc, void *pProgressData);
+
     // allow access to MEM driver's private internal memory buffer
     GByte *GetData(void) const {return(pabyData);}
 };
diff --git a/frmts/mrsid/GNUmakefile b/frmts/mrsid/GNUmakefile
index 07cc216..022800a 100644
--- a/frmts/mrsid/GNUmakefile
+++ b/frmts/mrsid/GNUmakefile
@@ -7,6 +7,9 @@ PLUGIN_DLL	=	gdal_MrSID.so
 
 ifeq ($(GEOTIFF_SETTING),internal)
 GEOTIFF_INCLUDE	=	-I../../frmts/gtiff/libgeotiff
+ifeq ($(RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS),yes)
+CPPFLAGS	:=	-DRENAME_INTERNAL_LIBGEOTIFF_SYMBOLS $(CPPFLAGS)
+endif
 endif
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(MRSID_FLAGS) $(MRSID_INCLUDE) $(GEOTIFF_INCLUDE) $(CPPFLAGS)
diff --git a/frmts/mrsid/frmt_mrsid.html b/frmts/mrsid/frmt_mrsid.html
index 6ee4466..3c5901d 100644
--- a/frmts/mrsid/frmt_mrsid.html
+++ b/frmts/mrsid/frmt_mrsid.html
@@ -35,6 +35,9 @@ in tag names. These characters replaced in GDAL with `_' during translation.
 So if you are using other software to work with MrSID be ready that names
 of metadata keys will be shown differently in GDAL.<p>
 
+Starting with GDAL 1.9.0, XMP metadata can be extracted from JPEG2000 files, and will be
+stored as XML raw content in the xml:XMP metadata domain.<p>
+
 <h2>Georeference</h2>
 
 MrSID images may contain georeference and coordinate system information in
diff --git a/frmts/mrsid/mrsiddataset.cpp b/frmts/mrsid/mrsiddataset.cpp
index 37513a1..9e2fb07 100644
--- a/frmts/mrsid/mrsiddataset.cpp
+++ b/frmts/mrsid/mrsiddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mrsiddataset.cpp 21465 2011-01-12 19:15:14Z kirk $
+ * $Id: mrsiddataset.cpp 22753 2011-07-18 19:53:26Z rouault $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Read/write LizardTech's MrSID file format - Version 4+ SDK.
@@ -32,12 +32,13 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
+#include "gdaljp2metadata.h"
 #include <string>
 
 #include <geo_normalize.h>
 #include <geovalues.h>
 
-CPL_CVSID("$Id: mrsiddataset.cpp 21465 2011-01-12 19:15:14Z kirk $");
+CPL_CVSID("$Id: mrsiddataset.cpp 22753 2011-07-18 19:53:26Z rouault $");
 
 CPL_C_START
 double GTIFAngleToDD( double dfAngle, int nUOMAngle );
@@ -210,7 +211,9 @@ class MrSIDDataset : public GDALPamDataset
 {
     friend class MrSIDRasterBand;
 
-    LTIVSIStream        oStream;
+    LTIOStreamInf       *poStream;
+    LTIOFileStream      oLTIStream;
+    LTIVSIStream        oVSIStream;
 
 #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
     LTIImageFilter      *poImageReader;
@@ -260,6 +263,12 @@ class MrSIDDataset : public GDALPamDataset
                                    int, int, GDALDataType, int, int *,int,
                                    int, int );
 
+  protected:
+    virtual int         CloseDependentDatasets();
+
+    virtual CPLErr      IBuildOverviews( const char *, int, int *,
+                                         int, int *, GDALProgressFunc, void * );
+
   public:
                 MrSIDDataset(int bIsJPEG2000);
                 ~MrSIDDataset();
@@ -423,7 +432,8 @@ MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDS, int nBand )
                 eBandInterp = GCI_Undefined;
             break;
 
-        case LTI_COLORSPACE_RGBK:
+#if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 8
+        case LTI_COLORSPACE_RGBA:
             if( nBand == 1 )
                 eBandInterp = GCI_RedBand;
             else if( nBand == 2 )
@@ -435,6 +445,7 @@ MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDS, int nBand )
             else
                 eBandInterp = GCI_Undefined;
             break;
+#endif
 
         case LTI_COLORSPACE_CMYK:
             if( nBand == 1 )
@@ -723,6 +734,7 @@ GDALRasterBand *MrSIDRasterBand::GetOverview( int i )
 
 MrSIDDataset::MrSIDDataset(int bIsJPEG2000)
 {
+    poStream = NULL;
     poImageReader = NULL;
 #ifdef MRSID_ESDK
     poImageWriter = NULL;
@@ -786,17 +798,33 @@ MrSIDDataset::~MrSIDDataset()
 #else
         delete poImageReader;
 #endif
+    // points to another member, don't delete
+    poStream = NULL;
 
     if ( pszProjection )
         CPLFree( pszProjection );
     if ( psDefn )
         delete psDefn;
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                      CloseDependentDatasets()                        */
+/************************************************************************/
+
+int MrSIDDataset::CloseDependentDatasets()
+{
+    int bRet = GDALPamDataset::CloseDependentDatasets();
+
     if ( papoOverviewDS )
     {
         for( int i = 0; i < nOverviewCount; i++ )
             delete papoOverviewDS[i];
         CPLFree( papoOverviewDS );
+        papoOverviewDS = NULL;
+        bRet = TRUE;
     }
+    return bRet;
 }
 
 /************************************************************************/
@@ -1002,6 +1030,21 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
 }
 
 /************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+CPLErr MrSIDDataset::IBuildOverviews( const char *, int, int *,
+                                      int, int *, GDALProgressFunc,
+                                      void * )
+{
+	CPLError( CE_Warning, CPLE_AppDefined,
+			  "MrSID overviews are built-in, so building external "
+			  "overviews is unnecessary. Ignoring.\n" );
+
+	return CE_None;
+}
+
+/************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
@@ -1464,18 +1507,43 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
     LT_STATUS       eStat;
 
     poDS = new MrSIDDataset(bIsJP2);
-    eStat = poDS->oStream.initialize( poOpenInfo->pszFilename, "rb" );
-    if ( !LT_SUCCESS(eStat) )
+
+    // try the LTIOFileStream first, since it uses filesystem caching
+    eStat = poDS->oLTIStream.initialize( poOpenInfo->pszFilename, "rb" );
+    if ( LT_SUCCESS(eStat) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "MrSIDStream::initialize(): "
-                  "failed to open file \"%s\".\n%s",
-                  poOpenInfo->pszFilename, getLastStatusString( eStat ) );
-        delete poDS;
-        return NULL;
+        eStat = poDS->oLTIStream.open();
+        if ( LT_SUCCESS(eStat) )
+            poDS->poStream = &(poDS->oLTIStream);
     }
 
-    poDS->oStream.open();
+    // fall back on VSI for non-files
+    if ( !LT_SUCCESS(eStat) || !poDS->poStream )
+    {
+        eStat = poDS->oVSIStream.initialize( poOpenInfo->pszFilename, "rb" );
+        if ( !LT_SUCCESS(eStat) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "LTIVSIStream::initialize(): "
+                      "failed to open file \"%s\".\n%s",
+                      poOpenInfo->pszFilename, getLastStatusString( eStat ) );
+            delete poDS;
+            return NULL;
+        }
+
+        eStat = poDS->oVSIStream.open();
+        if ( !LT_SUCCESS(eStat) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "LTIVSIStream::open(): "
+                      "failed to open file \"%s\".\n%s",
+                      poOpenInfo->pszFilename, getLastStatusString( eStat ) );
+            delete poDS;
+            return NULL;
+        }
+
+        poDS->poStream = &(poDS->oVSIStream);
+    }
 
 #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
 
@@ -1483,14 +1551,14 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
     if ( bIsJP2 )
     {
         J2KImageReader  *reader = J2KImageReader::create();
-        eStat = reader->initialize( poDS->oStream );
+        eStat = reader->initialize( *(poDS->poStream) );
         poDS->poImageReader = reader;
     }
     else
 #endif /* MRSID_J2K */
     {
         MrSIDImageReader    *reader = MrSIDImageReader::create();
-	eStat = reader->initialize( &poDS->oStream, NULL );
+        eStat = reader->initialize( poDS->poStream, NULL );
         poDS->poImageReader = reader;           
     }
 
@@ -1500,14 +1568,14 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
     if ( bIsJP2 )
     {
         poDS->poImageReader =
-            new LTIDLLReader<J2KImageReader>( poDS->oStream, true );
+            new LTIDLLReader<J2KImageReader>( *(poDS->poStream), true );
         eStat = poDS->poImageReader->initialize();
     }
     else
 #endif /* MRSID_J2K */
     {
         poDS->poImageReader =
-            new LTIDLLReader<MrSIDImageReader>( &poDS->oStream, NULL );
+            new LTIDLLReader<MrSIDImageReader>( poDS->poStream, NULL );
         eStat = poDS->poImageReader->initialize();
     }
 
@@ -1624,11 +1692,40 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
     if( poDS->nBands > 1 )
         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
 
+    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");
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Initialize the overview manager for mask band support.          */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
     return( poDS );
 }
 
@@ -3540,6 +3637,11 @@ void GDALRegister_MrSID()
 "</CreationOptionList>" );
 
         poDriver->pfnCreateCopy = MrSIDCreateCopy;
+
+#else
+        /* In read-only mode, we support VirtualIO. I don't think this is the case */
+        /* for MrSIDCreateCopy() */
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 #endif
         poDriver->pfnIdentify = MrSIDIdentify;
         poDriver->pfnOpen = MrSIDOpen;
@@ -3572,6 +3674,10 @@ void GDALRegister_MrSID()
 "</CreationOptionList>" );
 
         poDriver->pfnCreateCopy = JP2CreateCopy;
+#else
+        /* In read-only mode, we support VirtualIO. I don't think this is the case */
+        /* for JP2CreateCopy() */
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 #endif
         poDriver->pfnIdentify = JP2Identify;
         poDriver->pfnOpen = JP2Open;
diff --git a/frmts/mrsid_lidar/gdal_MG4Lidar.cpp b/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
index a1431df..5a64581 100644
--- a/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
+++ b/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
@@ -819,7 +819,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    // Calculate the number of levels to expose.  The highest level correpsonds to a
    // raster size of 256 on the longest side.
    double blocksizefactor = MaxRasterSize/256.0;
-   poDS->nOverviewCount = (int)(log(blocksizefactor)/log(RESOLUTION_RATIO) + 0.5);
+   poDS->nOverviewCount = MAX(0, (int)(log(blocksizefactor)/log(RESOLUTION_RATIO) + 0.5));
    if ( poDS->nOverviewCount > 0 )
    {
       int i;
diff --git a/frmts/msgn/msgndataset.cpp b/frmts/msgn/msgndataset.cpp
index 8e72e06..d20761b 100644
--- a/frmts/msgn/msgndataset.cpp
+++ b/frmts/msgn/msgndataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgndataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: msgndataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  MSG Native Reader
  * Purpose:  All code for EUMETSAT Archive format reader
@@ -33,7 +33,7 @@
 #include "msg_reader_core.h"
 using namespace msg_native_format;
 
-CPL_CVSID("$Id: msgndataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
+CPL_CVSID("$Id: msgndataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 CPL_C_START
 void   GDALRegister_MSGN(void);
@@ -434,7 +434,7 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
             }
             if (ok_to_add) {
                 poDS->SetBand( band_count, new MSGNRasterBand( poDS, band_count, open_mode, i+1, i+1 - missing_band_count));
-                band_map[band_count] = i+1;
+                band_map[band_count] = (unsigned char) (i+1);
                 band_count++;
             }
         } else {
diff --git a/frmts/netcdf/GNUmakefile b/frmts/netcdf/GNUmakefile
index 8d3f41f..42c56a7 100644
--- a/frmts/netcdf/GNUmakefile
+++ b/frmts/netcdf/GNUmakefile
@@ -3,6 +3,20 @@ include ../../GDALmake.opt
 
 OBJ	=	netcdfdataset.o gmtdataset.o
 
+XTRA_OPT = 
+ifeq ($(NETCDF_HAS_NC4),yes)
+XTRA_OPT := -DNETCDF_HAS_NC4  $(XTRA_OPT)
+endif
+ifeq ($(NETCDF_HAS_HDF4),yes)
+XTRA_OPT := -DNETCDF_HAS_HDF4 $(XTRA_OPT)
+endif
+ifeq ($(HAVE_HDF4),yes)
+XTRA_OPT := -DHAVE_HDF4 $(XTRA_OPT)
+endif
+ifeq ($(HAVE_HDF5),yes)
+XTRA_OPT := -DHAVE_HDF5 $(XTRA_OPT)
+endif
+
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(XTRA_OPT) 
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/netcdf/frmt_netcdf.html b/frmts/netcdf/frmt_netcdf.html
index 1d912d6..bc4d479 100644
--- a/frmts/netcdf/frmt_netcdf.html
+++ b/frmts/netcdf/frmt_netcdf.html
@@ -281,27 +281,66 @@ Variables attributes for: tos, lon, lat and time
   time#original_units=seconds since 2001-1-1
 </pre>
 
-<h2>Driver building</h2>
+<h2>Driver Improvements (GDAL >= 1.9.0)</h2>
 
-This driver is compiled with the  UNIDATA netCDF library.<p>
+The driver has undergone significant changes in GDAL 1.9.0, see NEWS file and <a href="http://trac.osgeo.org/gdal/wiki/NetCDF_Improvements">NetCDF Improvements</a>.
 
-You need to download or compile the netCDF library before 
-configuring  GDAL with netCDF support. <p>
+<h3>Important Changes</h3>
 
+<ul>
 
-Please note that with <b>CygWIN</b> you need to be sure that the DLLs 
-are executable, or GDAL will not execute.
-<pre>
-chmod a+rx [NetCDF DLLs]
-</pre>
+<li><p>Added support for NC2, NC4 and NC4C file types for reading and writing, and HDF4 for reading. See <a href="http://www.unidata.ucar.edu/software/netcdf/docs/netcdf/File-Format.html#File-Format">NetCDF File Format</a> for details.
+<ul>
+<li><tt>NC</tt> : NetCDF Classic Format: The Original Binary Format.</li>
+<li><tt>NC2</tt> : 64-bit Offset Format: Supporting Larger Variables</li>
+<li><tt>NC4</tt> : NetCDF-4 Format: Uses HDF5</li>
+<li><tt>NC4C</tt> : NetCDF-4 Classic Model Format: HDF5 with NetCDF Limitations</li>
+<li><tt>HDF4</tt> : HDF4 SD Format</li>
+</ul>
+</p></li>
+<li><p>Improved support for CF-1.5 projected and geographic SRS reading and writing</p></li>
+<li><p>Improvements to metadata (global and variable) handling</p></li>
+<li><p>Added simple progress indicator</p></li>
+<li><p>Added support for DEFLATE compression (reading and writing) and szip (reading) - requires NetCDF-4 support</p></li>
+<li><p>Added support for valid_range/valid_min/valid_max</p></li>
+<li><p>Proper handling of signed/unsigned byte data</p></li>
+<li><p>Added support for Create() function - enables to use netcdf directly with gdalwarp</p></li>
+</ul>
+
+<h3>Creation Options</h3>
+
+<ul>
+
+<li><p><b>FORMAT=[NC/NC2/NC4/NC4C]</b>: Set the netcdf file format to use, NC is the default. NC2 is normally supported by recent netcdf installations, but NC4 and NC4C are available if netcdf was compiled with NetCDF-4 (and HDF5) support. 
+<li><p><b>COMPRESS=[NONE/DEFLATE]</b>: Set the compression to use.  DEFLATE is only available if netcdf has been compiled with NetCDF-4 support. NC4C format is the default if DEFLATE compression is used.</p></li>
+<li><p><b>ZLEVEL=[1-9]</b>: Set the level of compression when using DEFLATE compression. A value of 9 is best, and 1 is least compression. The default is 1, which offers the best time/compression ratio.</p></li>
+<li><p><b>WRITE_BOTTOMUP=[YES/NO]</b>: Set the y-axis order for export, overriding the order detected by the driver. NetCDF files are usually assumed "bottom-up", contrary to GDAL's model which is "north up". This normally does not create a problem in the y-axis order, unless there is no y axis geo-referencing. Files without geo-referencing information will be exported in the netcdf default "bottom-up" order, and the contrary for files with geo-referencing. For import see Configuration Option GDAL_NETCDF_BOTTOMUP below.</p></li>
+<li><p><b>WRITE_GDAL_TAGS=[YES/NO]</b>: Define if GDAL tags used for georeferencing (spatial_ref and GeoTransform) should be exported, in addition to CF tags. Not all information is stored in the CF tags (such as named datums and EPSG codes), therefore the driver exports these variables by default.  In import the CF "grid_mapping" variable takes precedence and the GDAL tags are used if they do not conflict with CF metadata.</p></li>
+<li><p><b>WRITE_LONLAT=[YES/NO/IF_NEEDED]</b>: Define if CF lon/lat variables are written to file. Default is YES for geographic SRS and NO for projected SRS. This is normally not necessary for projected SRS as GDAL and many applications use the X/Y dimension variables and CF projection information.  Use of IF_NEEDED option creates lon/lat variables if the projection is not part of the CF-1.5 standard.</p></li>
+<li><p><b>TYPE_LONLAT=[float/double]</b>: Set the variable type to use for lon/lat variables. Default is double for geographic SRS and float for projected SRS. If lon/lat variables are written for a projected SRS, the file is considerably large (each variable uses X*Y space), therefore TYPE_LONLAT=float and COMPRESS=DEFLATE are advisable in order to save space.</p></li>
+<li><p><b>PIXELTYPE=[DEFAULT/SIGNEDBYTE]</b>: By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte.</p></li>
+
+</ul>
+
+<h3>Configuration Options</h3>
+
+<ul>
+<li><b>GDAL_NETCDF_BOTTOMUP=[YES/NO]</b> : Set the y-axis order for import, overriding the order detected by the driver. This option is usually not needed unless a specific dataset is causing problems (which should be reported in GDAL trac).</li>
+</ul>
+
+<h2>Driver building</h2>
+
+This driver is compiled with the UNIDATA netCDF library.<p>
+
+You need to download or compile the netCDF library before configuring  GDAL with netCDF support. <p>
 
-The netCDF DLLs directory <b>must be</b> to be in your <b>PATH</b>.
+See <a href="http://trac.osgeo.org/gdal/wiki/NetCDF">NetCDF GDAL wiki</a> for build instructions and information regarding HDF4, NetCDF-4 and HDF5. 
 
 
 <h2>See Also:</h2>
 <ul>
 <li>
-<a href="http://www.cgd.ucar.edu/cms/eaton/cf-metadata/index.html">NetCDF CF-1.0 convention </a>
+<a href="http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.5/cf-conventions.html">NetCDF CF-1.5 convention</a>
 <li><a href="http://www.unidata.ucar.edu/downloads/netcdf/index.jsp">NetCDF compiled libraries</a>
 <li><a href="http://www.unidata.ucar.edu/software/netcdf/docs/">NetCDF Documentation</A>
 </ul>
diff --git a/frmts/netcdf/gmtdataset.cpp b/frmts/netcdf/gmtdataset.cpp
index 5a6116e..b07e691 100644
--- a/frmts/netcdf/gmtdataset.cpp
+++ b/frmts/netcdf/gmtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmtdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: gmtdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library for GMT Grids.
@@ -31,7 +31,7 @@
 #include "gdal_frmts.h"
 #include "netcdf.h"
 
-CPL_CVSID("$Id: gmtdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
+CPL_CVSID("$Id: gmtdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -129,7 +129,7 @@ CPLErr GMTRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 {
     size_t start[2], edge[2];
-    int    nErr;
+    int    nErr = NC_NOERR;
     int    cdfid = ((GMTDataset *) poDS)->cdfid;
 
     start[0] = nBlockYOff * nBlockXSize;
@@ -358,6 +358,11 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
diff --git a/frmts/netcdf/makefile.vc b/frmts/netcdf/makefile.vc
index 9e3760d..5759168 100644
--- a/frmts/netcdf/makefile.vc
+++ b/frmts/netcdf/makefile.vc
@@ -9,6 +9,19 @@ PLUGIN_DLL 	=	gdal_netCDF.dll
 
 EXTRAFLAGS 	= 	/I$(NETCDF_INC_DIR)
 
+!IFDEF NETCDF_HAS_NC4
+EXTRAFLAGS = $(EXTRAFLAGS) -DNETCDF_HAS_NC4
+!ENDIF
+!IFDEF NETCDF_HAS_HDF4
+EXTRAFLAGS = $(EXTRAFLAGS) -DNETCDF_HAS_HDF4
+!ENDIF
+!IFDEF HDF4_DIR
+EXTRAFLAGS = $(EXTRAFLAGS) -DHAVE_HDF4
+!ENDIF
+!IFDEF HDF5_DIR
+EXTRAFLAGS = $(EXTRAFLAGS) -DHAVE_HDF5
+!ENDIF
+
 default:	$(OBJ)
 	$(INSTALL) *.obj ..\o
 
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index 50bb62f..3f1a219 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: netcdfdataset.cpp 20997 2010-10-28 19:10:19Z kyle $
+ * $Id: netcdfdataset.cpp 23644 2011-12-23 03:18:40Z etourigny $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -29,8 +29,37 @@
 
 #include "netcdfdataset.h"
 #include "cpl_error.h"
-CPL_CVSID("$Id: netcdfdataset.cpp 20997 2010-10-28 19:10:19Z kyle $");
+CPL_CVSID("$Id: netcdfdataset.cpp 23644 2011-12-23 03:18:40Z etourigny $");
 
+#include <map> //for NCDFWriteProjAttribs()
+
+/* Internal function declarations */
+
+int NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget);
+
+void NCDFAddGDALHistory( int fpImage, 
+                         const char * pszFilename, const char *pszOldHist,
+                         const char * pszFunctionName );
+
+void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist);
+
+int NCDFIsCfProjection( const char* pszProjection );
+
+void NCDFWriteProjAttribs(const OGR_SRSNode *poPROJCS,
+                            const char* pszProjection,
+                            const int fpImage, const int NCDFVarID);
+
+CPLErr NCDFSafeStrcat(char** ppszDest, char* pszSrc, size_t* nDestSize);
+
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
+                    double *pdfValue );
+
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
+                    char **pszValue );
+
+CPLErr NCDFPutAttr( int nCdfId, int nVarId, 
+                    const char *pszAttrName, const char *pszValue );
+ 
 
 /************************************************************************/
 /* ==================================================================== */
@@ -40,333 +69,91 @@ CPL_CVSID("$Id: netcdfdataset.cpp 20997 2010-10-28 19:10:19Z kyle $");
 
 class netCDFRasterBand : public GDALPamRasterBand
 {
-    nc_type nc_datatype;
+    friend class netCDFDataset;
+
+    nc_type     nc_datatype;
+    int         cdfid;
     int         nZId;
     int         nZDim;
-    int		nLevel;
+    int         nLevel;
     int         nBandXPos;
     int         nBandYPos;
     int         *panBandZPos;
     int         *panBandZLev;
     int         bNoDataSet;
     double      dfNoDataValue;
+    double      adfValidRange[2];
     double      dfScale;
     double      dfOffset;
-    CPLErr	    CreateBandMetadata( ); 
+    int         bSignedData;
+    int         status;
+
+    CPLErr	    CreateBandMetadata( int *paDimIds ); 
+    template <class T> void  CheckValidData ( void * pImage, 
+                                              int bCheckIsNan=FALSE ) ;
     
   public:
 
     netCDFRasterBand( netCDFDataset *poDS, 
-		      int nZId, 
-		      int nZDim,
-		      int nLevel, 
-		      int *panBandZLen,
-		      int *panBandPos, 
-		      int nBand );
+                      int nZId, 
+                      int nZDim,
+                      int nLevel, 
+                      int *panBandZLen,
+                      int *panBandPos,
+                      int *paDimIds,
+                      int nBand );
+    netCDFRasterBand( netCDFDataset *poDS, 
+                      GDALDataType eType,
+                      int nBand,
+                      int bSigned=TRUE,
+                      char *pszBandName=NULL,
+                      char *pszLongName=NULL );
     ~netCDFRasterBand( );
-    virtual double          GetNoDataValue( int * );
-    virtual CPLErr          SetNoDataValue( double );
-    virtual double          GetOffset( int * );
-    virtual CPLErr          SetOffset( double );
-    virtual double          GetScale( int * );
-    virtual CPLErr          SetScale( double );
+
+    virtual double GetNoDataValue( int * );
+    virtual CPLErr SetNoDataValue( double );
+    virtual double GetOffset( int * );
+    virtual CPLErr SetOffset( double );
+    virtual double GetScale( int * );
+    virtual CPLErr SetScale( double );
     virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IWriteBlock( int, int, void * );
 
 };
 
-/************************************************************************/ 
-/*                             GetOffset()                              */ 
-/************************************************************************/ 
-double netCDFRasterBand::GetOffset( int *pbSuccess ) 
-{ 
-    if( pbSuccess != NULL ) 
-        *pbSuccess = TRUE; 
-	 
-    return dfOffset; 
-}
-
-/************************************************************************/ 
-/*                             SetOffset()                              */ 
-/************************************************************************/ 
-CPLErr netCDFRasterBand::SetOffset( double dfNewOffset ) 
-{ 
-    dfOffset = dfNewOffset; 
-    return CE_None; 
-}
-
-/************************************************************************/ 
-/*                              GetScale()                              */ 
-/************************************************************************/ 
-double netCDFRasterBand::GetScale( int *pbSuccess ) 
-{ 
-    if( pbSuccess != NULL ) 
-        *pbSuccess = TRUE; 
-    return dfScale; 
-}
-
-/************************************************************************/ 
-/*                              SetScale()                              */ 
-/************************************************************************/ 
-CPLErr netCDFRasterBand::SetScale( double dfNewScale )  
-{ 
-    dfScale = dfNewScale; 
-    return CE_None; 
-} 
-
-/************************************************************************/
-/*                            GetMetadata()                             */
-/************************************************************************/
-char **netCDFDataset::GetMetadata( const char *pszDomain )
-{
-    if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) )
-        return papszSubDatasets;
-    else
-        return GDALDataset::GetMetadata( pszDomain );
-}
-
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
-
-const char * netCDFDataset::GetProjectionRef()
-{
-    if( bGotGeoTransform )
-        return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
-}
-
-/************************************************************************/
-/*                           GetNoDataValue()                           */
-/************************************************************************/
-
-double netCDFRasterBand::GetNoDataValue( int * pbSuccess )
-
-{
-    if( pbSuccess )
-        *pbSuccess = bNoDataSet;
-
-    if( bNoDataSet )
-        return dfNoDataValue;
-    else
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
-}
-
-/************************************************************************/
-/*                           SetNoDataValue()                           */
-/************************************************************************/
-
-CPLErr netCDFRasterBand::SetNoDataValue( double dfNoData )
-
-{
-    bNoDataSet = TRUE;
-    dfNoDataValue = dfNoData;
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                         ~netCDFRasterBand()                          */
-/************************************************************************/
-
-netCDFRasterBand::~netCDFRasterBand()
-{
-    if( panBandZPos ) 
-        CPLFree( panBandZPos );
-    if( panBandZLev )
-        CPLFree( panBandZLev );
-}
-
-/************************************************************************/
-/*                         CreateBandMetadata()                         */
-/************************************************************************/
-
-CPLErr netCDFRasterBand::CreateBandMetadata( ) 
-{
-    char     szVarName[NC_MAX_NAME];
-    char     szMetaName[NC_MAX_NAME];
-    char     szMetaTemp[8192];
-    int      nd;
-    int      i,j;
-    int      Sum  = 1;
-    int      Taken = 0;
-    int      result = 0;
-    int      status;
-    int      nVarID = -1;
-    int      nDims;
-    size_t   start[1];
-    size_t   count[1];
-    char     szTemp[NC_MAX_NAME];
-    const char *pszValue;
-
-    nc_type nVarType;
-    netCDFDataset *poDS;
-
-    poDS = (netCDFDataset *) this->poDS;
-/* -------------------------------------------------------------------- */
-/*      Compute all dimensions from Band number and save in Metadata    */
-/* -------------------------------------------------------------------- */
-    nc_inq_varname( poDS->cdfid, nZId, szVarName );
-    nc_inq_varndims( poDS->cdfid, nZId, &nd );
-/* -------------------------------------------------------------------- */
-/*      Compute multidimention band position                            */
-/*                                                                      */
-/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
-/* if Data[2,3,4,x,y]                                                   */
-/*                                                                      */
-/*  BandPos0 = (nBand ) / (3*4)                                         */
-/*  BandPos1 = (nBand - BandPos0*(3*4) ) / (4)                          */
-/*  BandPos2 = (nBand - BandPos0*(3*4) ) % (4)                          */
-/* -------------------------------------------------------------------- */
-
-    sprintf( szMetaName,"NETCDF_VARNAME");
-    sprintf( szMetaTemp,"%s",szVarName);
-    SetMetadataItem( szMetaName, szMetaTemp );
-    if( nd == 3 ) {
-        Sum *= panBandZLev[0];
-    }
-
-    for( i=0; i < nd-2 ; i++ ) {
-        if( i != nd - 2 -1 ) {
-            Sum = 1;
-            for( j=i+1; j < nd-2; j++ ) {
-                Sum *= panBandZLev[j];
-            }
-            result = (int) ( ( nLevel-Taken) / Sum );
-        }
-        else {
-            result = (int) ( ( nLevel-Taken) % Sum );
-        }
-        
-        strcpy(szVarName, poDS->papszDimName[poDS->paDimIds[
-                       panBandZPos[i]]] );
-
-        sprintf( szMetaName,"NETCDF_DIMENSION_%s",  szVarName );
-
-        status=nc_inq_varid(poDS->cdfid,  
-                            szVarName,
-                            &nVarID );
-
-/* -------------------------------------------------------------------- */
-/*      Try to uppercase the first letter of the variable               */
-/* -------------------------------------------------------------------- */
-
-        if( status != NC_NOERR ) {
-            szVarName[0]=toupper(szVarName[0]);
-            status=nc_inq_varid(poDS->cdfid,  
-                                szVarName,
-                                &nVarID );
-        }
-
-        status = nc_inq_vartype( poDS->cdfid, nVarID, &nVarType );
-
-        nDims = 0;
-        status = nc_inq_varndims( poDS->cdfid, nVarID, &nDims );
-
-        if( nDims == 1 ) {
-            count[0]=1;
-            start[0]=result;
-            switch( nVarType ) {
-                case NC_SHORT:
-                    short sData;
-                    status =  nc_get_vara_short( poDS->cdfid, nVarID, 
-                                                 start,
-                                                 count, &sData );
-                    sprintf( szMetaTemp,"%d", sData );
-                    break;
-                case NC_INT:
-                    int nData;
-                    status =  nc_get_vara_int( poDS->cdfid, nVarID, 
-                                               start,
-                                               count, &nData );
-                    sprintf( szMetaTemp,"%d", nData );
-                    break;
-                case NC_FLOAT:
-                    float fData;
-                    status =  nc_get_vara_float( poDS->cdfid, nVarID, 
-                                                 start,
-                                                 count, &fData );
-                    sprintf( szMetaTemp,"%f", fData );
-                    break;
-                case NC_DOUBLE:
-                    double dfData;
-                    status =  nc_get_vara_double( poDS->cdfid, nVarID, 
-                                                  start,
-                                                  count, &dfData);
-                    sprintf( szMetaTemp,"%g", dfData );
-                    break;
-                default:
-                    break;
-            }
-        }
-        else
-            sprintf( szMetaTemp,"%d", result+1);
-	
-        SetMetadataItem( szMetaName, szMetaTemp );
-
-/* -------------------------------------------------------------------- */
-/*      Fetch dimension units                                           */
-/* -------------------------------------------------------------------- */
-
-        strcpy( szTemp, szVarName );
-        strcat( szTemp, "#units" );
-        pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-        if( pszValue != NULL ) {
-            if( EQUAL( pszValue, "T") ) { 
-                strcpy( szTemp, szVarName );
-                strcat( szTemp, "#original_units" );
-                pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-                strcpy( szTemp, "NETCDF_");
-                strcat( szTemp, szVarName );
-                strcat( szTemp, "_original_units" );
-                SetMetadataItem( szTemp, pszValue );
-            }
-            else {
-                strcpy( szTemp, "NETCDF_");
-                strcat( szTemp, szVarName  );
-                strcat( szTemp, "_units" );
-                SetMetadataItem( szTemp, pszValue );
-            }
-        }
-        Taken += result * Sum;
-    }
-
-
-
-    return CE_None;
-}
-
 /************************************************************************/
 /*                          netCDFRasterBand()                          */
 /************************************************************************/
 
-netCDFRasterBand::netCDFRasterBand( netCDFDataset *poDS, 
+netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS, 
                                     int nZId, 
                                     int nZDim,
                                     int nLevel, 
                                     int *panBandZLev, 
                                     int *panBandDimPos, 
+                                    int *paDimIds,
                                     int nBand)
 
 {
-    double   dfNoData;
+    double   dfNoData = 0.0;
     int      bNoDataSet = FALSE;
     nc_type  vartype=NC_NAT;
     nc_type  atttype=NC_NAT;
     size_t   attlen;
-    int      status;
-    char     szNoValueName[8192];
-
+    char     szNoValueName[NCDF_MAX_STR_LEN];
 
+    this->poDS = poNCDFDS;
     this->panBandZPos = NULL;
     this->panBandZLev = NULL;
-    this->poDS = poDS;
     this->nBand = nBand;
     this->nZId = nZId;
     this->nZDim = nZDim;
     this->nLevel = nLevel;
     this->nBandXPos = panBandDimPos[0];
     this->nBandYPos = panBandDimPos[1];
+    this->bSignedData = TRUE; //default signed, except for Byte 
+    this->cdfid = poNCDFDS->GetCDFID();
+    this->status = NC_NOERR;
 
 /* -------------------------------------------------------------------- */
 /*      Take care of all other dimmensions                              */
@@ -382,25 +169,33 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poDS,
             this->panBandZLev[i] = panBandZLev[i];
         }
     }
-    CreateBandMetadata();
     bNoDataSet    = FALSE;
-    dfNoDataValue = -9999.0;
+    dfNoDataValue = 0.0;
 
+    nRasterXSize  = poDS->GetRasterXSize( );
+    nRasterYSize  = poDS->GetRasterYSize( );
     nBlockXSize   = poDS->GetRasterXSize( );
     nBlockYSize   = 1;
 
 /* -------------------------------------------------------------------- */
 /*      Get the type of the "z" variable, our target raster array.      */
 /* -------------------------------------------------------------------- */
-    if( nc_inq_var( poDS->cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
+    if( nc_inq_var( cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
                     NULL ) != NC_NOERR ){
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Error in nc_var_inq() on 'z'." );
         return;
     }
 
-    if( (nc_datatype == NC_BYTE) ) 
+    if( nc_datatype == NC_BYTE )
         eDataType = GDT_Byte;
+#ifdef NETCDF_HAS_NC4
+    /* NC_UBYTE (unsigned byte) is only available for NC4 */
+    else if( nc_datatype == NC_UBYTE )
+        eDataType = GDT_Byte;
+#endif    
+    else if( nc_datatype == NC_CHAR )
+        eDataType = GDT_Byte;        
     else if( nc_datatype == NC_SHORT )
         eDataType = GDT_Int16;
     else if( nc_datatype == NC_INT )
@@ -417,11 +212,12 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poDS,
                       (int) nc_datatype );
         eDataType = GDT_Float32;
     }
+
 /* -------------------------------------------------------------------- */
 /*      Find out what is No Data for this variable                      */
 /* -------------------------------------------------------------------- */
 
-    status = nc_inq_att( poDS->cdfid, nZId, 
+    status = nc_inq_att( cdfid, nZId, 
                          _FillValue, &atttype, &attlen);
 
 /* -------------------------------------------------------------------- */
@@ -432,60 +228,33 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poDS,
         strcpy(szNoValueName, _FillValue );
     }
     else {
-        status = nc_inq_att( poDS->cdfid, nZId, 
+        status = nc_inq_att( cdfid, nZId, 
                              "missing_value", &atttype, &attlen );
         if( status == NC_NOERR ) {
-
             strcpy( szNoValueName, "missing_value" );
         }
     }
 
-    nc_inq_vartype( poDS->cdfid, nZId, &vartype );
-
     if( status == NC_NOERR ) {
-        switch( atttype ) {
-            case NC_CHAR:
-                char *fillc;
-                fillc = (char *) CPLCalloc( attlen+1, sizeof(char) );
-                status=nc_get_att_text( poDS->cdfid, nZId,
-                                        szNoValueName, fillc );
-                dfNoData = atof( fillc );
-                CPLFree(fillc);
-                break;
-            case NC_SHORT:
-                short sNoData;
-                status = nc_get_att_short( poDS->cdfid, nZId,
-                                           szNoValueName, &sNoData );
-                dfNoData = (double) sNoData;
-                break;
-            case NC_INT:
-                int nNoData;
-                status = nc_get_att_int( poDS->cdfid, nZId,
-                                         szNoValueName, &nNoData );
-                dfNoData = (double) nNoData;
-                break;
-            case NC_FLOAT:
-                float fNoData;
-                status = nc_get_att_float( poDS->cdfid, nZId,
-                                           szNoValueName, &fNoData );
-                dfNoData = (double) fNoData;
-                break;
-            case NC_DOUBLE:
-                status = nc_get_att_double( poDS->cdfid, nZId,
-                                            szNoValueName, &dfNoData );
-                break;
-            default:
-                break;
-        }
-        status = nc_get_att_double( poDS->cdfid, nZId, 
-                                    szNoValueName, &dfNoData );
-	
-    } else {
+        if ( NCDFGetAttr( cdfid, nZId, szNoValueName, 
+                          &dfNoData ) == CE_None )
+            bNoDataSet = TRUE;
+    }
+
+    nc_inq_vartype( cdfid, nZId, &vartype );
+
+    /* if not found NoData, set the default one */
+    if ( ! bNoDataSet ) { 
         switch( vartype ) {
             case NC_BYTE:
+#ifdef NETCDF_HAS_NC4
+            case NC_UBYTE:
+#endif    
                 /* don't do default fill-values for bytes, too risky */
                 dfNoData = 0.0;
-                break;
+                /* should print a warning as users might not be expecting this */
+                /* CPLError(CE_Warning, 1,"GDAL netCDF driver is setting default NoData value to 0.0 for NC_BYTE data\n"); */
+               break;
             case NC_CHAR:
                 dfNoData = NC_FILL_CHAR;
                 break;
@@ -506,1158 +275,3099 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poDS,
                 break;
         }
 	    bNoDataSet = TRUE;
+    } 
+    
+    if ( bNoDataSet ) 
+        SetNoDataValue( dfNoData );
+    else 
+        CPLDebug( "GDAL_netCDF", "did not get nodata value for variable #%d", nZId );
+
+/* -------------------------------------------------------------------- */
+/*  Look for valid_range or valid_min/valid_max                         */
+/* -------------------------------------------------------------------- */
+    /* set valid_range to nodata, then check for actual values */
+    adfValidRange[0] = dfNoData;
+    adfValidRange[1] = dfNoData;
+    /* first look for valid_range */
+    int bGotValidRange = FALSE;
+    status = nc_inq_att( cdfid, nZId, 
+                         "valid_range", &atttype, &attlen);
+    if( (status == NC_NOERR) && (attlen == 2)) {
+        int vrange[2];
+        int vmin, vmax;
+        status = nc_get_att_int( cdfid, nZId,
+                                 "valid_range", vrange ); 
+        if( status == NC_NOERR ) {
+            bGotValidRange = TRUE;
+            adfValidRange[0] = vrange[0];
+            adfValidRange[1] = vrange[1];
+        }
+        /* if not found look for valid_min and valid_max */
+        else {
+            status = nc_get_att_int( cdfid, nZId,
+                                     "valid_min", &vmin );
+            if( status == NC_NOERR ) {
+                adfValidRange[0] = vmin;
+                status = nc_get_att_int( cdfid, nZId,
+                                         "valid_max", &vmax );
+                if( status == NC_NOERR ) {
+                    adfValidRange[1] = vmax;
+                    bGotValidRange = TRUE;
+                }
+            }
+        }
+    }
+
+    CPLDebug( "GDAL_netCDF", "valid_range={%f,%f}",
+              adfValidRange[0], adfValidRange[1] );
+
+/* -------------------------------------------------------------------- */
+/*  Special For Byte Bands: check for signed/unsigned byte              */
+/* -------------------------------------------------------------------- */
+    if ( nc_datatype == NC_BYTE ) {
+
+        /* netcdf uses signed byte by default, but GDAL uses unsigned by default */
+        /* This may cause unexpected results, but is needed for back-compat */
+        if ( poNCDFDS->bIsGdalFile )
+            this->bSignedData = FALSE;
+        else 
+            this->bSignedData = TRUE;
+
+        /* For NC4 format NC_BYTE is signed, NC_UBYTE is unsigned */
+        if ( poNCDFDS->nFormat == NCDF_FORMAT_NC4 ) {
+            this->bSignedData = TRUE;
+        }   
+        else  {
+            /* if we got valid_range, test for signed/unsigned range */
+            /* http://www.unidata.ucar.edu/software/netcdf/docs/netcdf/Attribute-Conventions.html */
+            if ( bGotValidRange == TRUE ) {
+                /* If we got valid_range={0,255}, treat as unsigned */
+                if ( (adfValidRange[0] == 0) && (adfValidRange[1] == 255) ) {
+                    bSignedData = FALSE;
+                    /* reset valid_range */
+                    adfValidRange[0] = dfNoData;
+                    adfValidRange[1] = dfNoData;
+                }
+                /* If we got valid_range={-128,127}, treat as signed */
+                else if ( (adfValidRange[0] == -128) && (adfValidRange[1] == 127) ) {
+                    bSignedData = TRUE;
+                    /* reset valid_range */
+                    adfValidRange[0] = dfNoData;
+                    adfValidRange[1] = dfNoData;
+                }
+            }
+            /* else test for _Unsigned */
+            /* http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html */
+            else {
+                char *pszTemp = NULL;
+                if ( NCDFGetAttr( cdfid, nZId, "_Unsigned", &pszTemp ) 
+
+                     == CE_None ) {
+                    if ( EQUAL(pszTemp,"true"))
+                        bSignedData = FALSE;
+                    else if ( EQUAL(pszTemp,"false"))
+                        bSignedData = TRUE;
+                    CPLFree( pszTemp );
+                }
+            }
+        }
+
+        if ( bSignedData )
+        {
+            /* set PIXELTYPE=SIGNEDBYTE */
+            /* See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure */
+            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );    
+            CPLDebug( "GDAL_netCDF", "got signed Byte" );        
+        }
+        else 
+            CPLDebug( "GDAL_netCDF", "got unsigned Byte" );
+
     }
-    SetNoDataValue( dfNoData );
 
-    /* -------------------------------------------------------------------- */
-    /* Attempt to fetch the scale_factor and add_offset attributes for the  */
-    /* variable and set them.  If these values are not available, set       */
-    /* offset to 0 and scale to 1                                           */
-    /* -------------------------------------------------------------------- */
+/* -------------------------------------------------------------------- */
+/*      Create Band Metadata                                            */
+/* -------------------------------------------------------------------- */
+    CreateBandMetadata( paDimIds );
+
+/* -------------------------------------------------------------------- */
+/* Attempt to fetch the scale_factor and add_offset attributes for the  */
+/* variable and set them.  If these values are not available, set       */
+/* offset to 0 and scale to 1                                           */
+/* -------------------------------------------------------------------- */
     double dfOff = 0.0; 
     double dfScale = 1.0; 
-    if ( nc_inq_attid ( poDS->cdfid, nZId, "add_offset", NULL) == NC_NOERR ) { 
-        nc_get_att_double( poDS->cdfid, nZId, "add_offset", &dfOff );
+    
+    if ( nc_inq_attid ( cdfid, nZId, CF_ADD_OFFSET, NULL) == NC_NOERR ) { 
+        status = nc_get_att_double( cdfid, nZId, CF_ADD_OFFSET, &dfOff );
+        CPLDebug( "GDAL_netCDF", "got add_offset=%.16g, status=%d", dfOff, status );
     }
-    if ( nc_inq_attid ( poDS->cdfid, nZId, 
-			"scale_factor", NULL) == NC_NOERR ) { 
-	nc_get_att_double( poDS->cdfid, nZId, "scale_factor", &dfScale ); 
+    if ( nc_inq_attid ( cdfid, nZId, 
+                        CF_SCALE_FACTOR, NULL) == NC_NOERR ) { 
+        status = nc_get_att_double( cdfid, nZId, CF_SCALE_FACTOR, &dfScale ); 
+        CPLDebug( "GDAL_netCDF", "got scale_factor=%.16g, status=%d", dfScale, status );
     }
     SetOffset( dfOff ); 
     SetScale( dfScale ); 
 }
 
-/************************************************************************/
-/*                             IReadBlock()                             */
-/************************************************************************/
-
-CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                     void * pImage )
+/* constructor in create mode, assume just 2 dimensions for now */
+netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS, 
+                                    GDALDataType eType,
+                                    int nBand,
+                                    int bSigned,
+                                    char *pszBandName,
+                                    char *pszLongName )
 
 {
-    int    nErr=-1;
-    int    cdfid = ( ( netCDFDataset * ) poDS )->cdfid;
-    size_t start[ MAX_NC_DIMS ];
-    size_t edge[ MAX_NC_DIMS ];
-    char   pszName[ MAX_STR_LEN ];
-    int    i,j;
-    int    Sum=-1;
-    int    Taken=-1;
-    int    nd;
+    int  anBandDims[ NC_MAX_DIMS ]; 
+    int      status;
+   
+    double   dfNoData = 0.0;
+    char szTemp[NCDF_MAX_STR_LEN];
 
-    *pszName='\0';
-    memset( start, 0, sizeof( start ) );
-    memset( edge,  0, sizeof( edge )  );
-    nc_inq_varndims ( cdfid, nZId, &nd );
+    this->poDS = poNCDFDS;
+    this->nBand = nBand;
+    this->nZId = -1;
+    this->nZDim = 2;
+    this->nLevel = 0;
+    this->panBandZPos = NULL;
+    this->panBandZLev = NULL;
+    this->nBandXPos = 1;
+    this->nBandYPos = 0; 
+    this->bSignedData = bSigned;  
+
+    this->status = NC_NOERR;
+    this->cdfid = poNCDFDS->GetCDFID();
+
+    bNoDataSet    = FALSE;
+    dfNoDataValue = 0.0;
+
+    nRasterXSize   = poDS->GetRasterXSize( );
+    nRasterYSize   = poDS->GetRasterYSize( );
+    nBlockXSize   = poDS->GetRasterXSize( );
+    nBlockYSize   = 1;
 
+    if ( poDS->GetAccess() != GA_Update ) {
+        CPLError( CE_Failure, CPLE_NotSupported, 
+                  "Dataset is not in update mode, wrong netCDFRasterBand constructor" );
+        return;
+    }
+    
 /* -------------------------------------------------------------------- */
-/*      Locate X, Y and Z position in the array                         */
+/*      Take care of all other dimmensions                              */
+/* ------------------------------------------------------------------ */
+    // if( nZDim > 2 ) {
+    //     this->panBandZPos = 
+    //         (int *) CPLCalloc( nZDim-1, sizeof( int ) );
+    //     this->panBandZLev = 
+    //         (int *) CPLCalloc( nZDim-1, sizeof( int ) );
+
+    //     for ( int i=0; i < nZDim - 2; i++ ){
+    //         this->panBandZPos[i] = panBandDimPos[i+2];
+    //         this->panBandZLev[i] = panBandZLev[i];
+    //     }
+    // }
+
 /* -------------------------------------------------------------------- */
-	
-    start[nBandXPos] = 0;          // x dim can move arround in array
-    // check y order
-    if( ( ( netCDFDataset *) poDS )->bBottomUp ) {
-        start[nBandYPos] = ( ( netCDFDataset * ) poDS )->ydim - 1 - nBlockYOff;
-    } else {
-        start[nBandYPos] = nBlockYOff; // y
-    }
-        
-    edge[nBandXPos] = nBlockXSize; 
-    edge[nBandYPos] = 1;
+/*      Get the type of the "z" variable, our target raster array.      */
+/* -------------------------------------------------------------------- */
+    eDataType = eType;
 
-    if( nd == 3 ) {
-        start[panBandZPos[0]]  = nLevel;     // z
-        edge [panBandZPos[0]]  = 1;
+    switch ( eDataType ) 
+    {
+        case GDT_Byte:
+            nc_datatype = NC_BYTE;
+#ifdef NETCDF_HAS_NC4
+            /* NC_UBYTE (unsigned byte) is only available for NC4 */
+            if ( ! bSignedData && (poNCDFDS->nFormat == NCDF_FORMAT_NC4) )
+                nc_datatype = NC_UBYTE;
+#endif    
+            break;
+        case GDT_Int16:
+            nc_datatype = NC_SHORT;
+            break;
+        case GDT_Int32:
+            nc_datatype = NC_INT;
+            break;
+        case GDT_Float32:
+            nc_datatype = NC_FLOAT;
+            break;
+        case GDT_Float64:
+            nc_datatype = NC_DOUBLE;
+            break;
+        default:
+            if( nBand == 1 )
+                CPLError( CE_Warning, CPLE_AppDefined, 
+                          "Unsupported GDAL datatype (%d), treat as NC_FLOAT.", 
+                          (int) eDataType );
+            nc_datatype = NC_FLOAT;
+            break;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Compute multidimention band position                            */
-/*                                                                      */
-/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
-/* if Data[2,3,4,x,y]                                                   */
-/*                                                                      */
-/*  BandPos0 = (nBand ) / (3*4)                                         */
-/*  BandPos1 = (nBand - (3*4) ) / (4)                                   */
-/*  BandPos2 = (nBand - (3*4) ) % (4)                                   */
+/*      Define the variable                                             */
 /* -------------------------------------------------------------------- */
-    if (nd > 3) 
-    {
-        Taken = 0;
-        for( i=0; i < nd-2 ; i++ ) 
-        {
-            if( i != nd - 2 -1 ) {
-                Sum = 1;
-                for( j=i+1; j < nd-2; j++ ) {
-                    Sum *= panBandZLev[j];
-                }
-                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) / Sum );
-                edge[panBandZPos[i]] = 1;
-            } else {
-                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) % Sum );
-                edge[panBandZPos[i]] = 1;
+    anBandDims[0] = poNCDFDS->nYDimID;
+    anBandDims[1] = poNCDFDS->nXDimID;
+
+    if ( !pszBandName || EQUAL(pszBandName,"")  )
+        sprintf( szTemp, "Band%d", nBand );
+    else 
+        strcpy( szTemp, pszBandName );
+            CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                      cdfid, szTemp, nc_datatype );
+            status = nc_def_var( cdfid, szTemp, nc_datatype, 
+                         NCDF_NBDIM, anBandDims, &nZId );
+    NCDF_ERR(status);
+
+    if ( !pszLongName || EQUAL(pszLongName,"")  )
+        sprintf( szTemp, "GDAL Band Number %d", nBand );
+    else 
+        strcpy( szTemp, pszLongName );
+    status =  nc_put_att_text( cdfid, nZId, CF_LNG_NAME, 
+                               strlen( szTemp ), szTemp );
+    NCDF_ERR(status);
+
+
+    poNCDFDS->DefVarDeflate(nZId, TRUE);
+
+    /* for Byte data add signed/unsigned info */
+    if ( eDataType == GDT_Byte ) {
+
+        CPLDebug( "GDAL_netCDF", "adding valid_range attributes for Byte Band" );
+        /* For unsigned NC_BYTE (except NC4 format) */
+        /* add valid_range and _Unsigned ( defined in CF-1 and NUG ) */
+        if ( (nc_datatype == NC_BYTE) && (poNCDFDS->nFormat != NCDF_FORMAT_NC4) ) {
+            short int adfValidRange[2]; 
+            if  ( bSignedData ) {
+                adfValidRange[0] = -128;
+                adfValidRange[1] = 127;
+                status = nc_put_att_text( cdfid,nZId, 
+                                          "_Unsigned", 5, "false" );
             }
-            Taken += start[panBandZPos[i]] * Sum;
-        }
-    }
+            else {
+                adfValidRange[0] = 0;
+                adfValidRange[1] = 255;
+                status = nc_put_att_text( cdfid,nZId, 
+                                          "_Unsigned", 4, "true" );
+            }
+            status=nc_put_att_short( cdfid,nZId, "valid_range",
+                                     NC_SHORT, 2, adfValidRange );
+        }         
+        /* for unsigned byte set PIXELTYPE=SIGNEDBYTE */
+        /* See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure */
+        if  ( bSignedData ) 
+            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );    
 
-    if( eDataType == GDT_Byte )
-        nErr = nc_get_vara_uchar( cdfid, nZId, start, edge, 
-                                  (unsigned char *) pImage );
-    else if( eDataType == GDT_Int16 )
-        nErr = nc_get_vara_short( cdfid, nZId, start, edge, 
-                                  (short int *) pImage );
-    else if( eDataType == GDT_Int32 )
-    {
-        if( sizeof(long) == 4 )
-            nErr = nc_get_vara_long( cdfid, nZId, start, edge, 
-                                     (long *) pImage );
-        else
-            nErr = nc_get_vara_int( cdfid, nZId, start, edge, 
-                                    (int *) pImage );
     }
-    else if( eDataType == GDT_Float32 ){
-        nErr = nc_get_vara_float( cdfid, nZId, start, edge, 
-                                  (float *) pImage );
-        for( i=0; i<nBlockXSize; i++ ){
-            if( CPLIsNan( ( (float *) pImage )[i] ) )
-                ( (float *)pImage )[i] = dfNoDataValue;
-        }
-    }
-    else if( eDataType == GDT_Float64 ){
-        nErr = nc_get_vara_double( cdfid, nZId, start, edge, 
-                                   (double *) pImage );
-        for( i=0; i<nBlockXSize; i++ ){
-            if( CPLIsNan( ( (double *) pImage)[i] ) ) 
-                ( (double *)pImage )[i] = dfNoDataValue;
-        }
 
+    /* set default nodata */
+    switch( nc_datatype ) {
+        case NC_BYTE:
+#ifdef NETCDF_HAS_NC4
+        case NC_UBYTE:
+#endif    
+            /* don't do default fill-values for bytes, too risky */
+            dfNoData = 0.0;
+            /* should print a warning as users might not be expecting this */
+            /* CPLError(CE_Warning, 1,"GDAL netCDF driver is setting default NoData value to 0.0 for NC_BYTE data\n"); */
+            break;
+        case NC_CHAR:
+            dfNoData = NC_FILL_CHAR;
+            break;
+        case NC_SHORT:
+            dfNoData = NC_FILL_SHORT;
+            break;
+        case NC_INT:
+            dfNoData = NC_FILL_INT;
+            break;
+        case NC_FLOAT:
+            dfNoData = NC_FILL_FLOAT;
+            break;
+        case NC_DOUBLE:
+            dfNoData = NC_FILL_DOUBLE;
+            break;
+        default:
+            dfNoData = 0.0;
+            break;
     }
 
-    if( nErr != NC_NOERR )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "netCDF scanline fetch failed: %s", 
-                  nc_strerror( nErr ) );
-        return CE_Failure;
-    }
-    else
-        return CE_None;
+    SetNoDataValue( dfNoData );
+
 }
 
 /************************************************************************/
-/* ==================================================================== */
-/*				netCDFDataset				*/
-/* ==================================================================== */
+/*                         ~netCDFRasterBand()                          */
 /************************************************************************/
 
-/************************************************************************/
-/*                           netCDFDataset()                            */
-/************************************************************************/
+netCDFRasterBand::~netCDFRasterBand()
+{
+    FlushCache();
+    if( panBandZPos ) 
+        CPLFree( panBandZPos );
+    if( panBandZLev )
+        CPLFree( panBandZLev );
+}
 
-netCDFDataset::netCDFDataset()
+/************************************************************************/ 
+/*                             GetOffset()                              */ 
+/************************************************************************/ 
+double netCDFRasterBand::GetOffset( int *pbSuccess ) 
+{ 
+    if( pbSuccess != NULL ) 
+        *pbSuccess = TRUE; 
+	 
+    return dfOffset; 
+}
 
-{
-    papszMetadata    = NULL;	
-    papszSubDatasets = NULL;
-    bGotGeoTransform = FALSE;
-    pszProjection    = NULL;
-    cdfid             = 0;
-    bBottomUp        = FALSE;
+/************************************************************************/ 
+/*                             SetOffset()                              */ 
+/************************************************************************/ 
+CPLErr netCDFRasterBand::SetOffset( double dfNewOffset ) 
+{ 
+    dfOffset = dfNewOffset; 
+
+    /* write value if in update mode */
+    if ( poDS->GetAccess() == GA_Update ) {
+
+        /* make sure we are in define mode */
+        ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
+
+        status = nc_put_att_double( cdfid, nZId, CF_ADD_OFFSET,
+                                    NC_DOUBLE, 1, &dfOffset );
+
+        NCDF_ERR(status);
+        if ( status == NC_NOERR )
+            return CE_None;
+        else
+            return CE_Failure;
+
+    }
+
+    return CE_None; 
 }
 
+/************************************************************************/ 
+/*                              GetScale()                              */ 
+/************************************************************************/ 
+double netCDFRasterBand::GetScale( int *pbSuccess ) 
+{ 
+    if( pbSuccess != NULL ) 
+        *pbSuccess = TRUE; 
+    return dfScale; 
+}
 
-/************************************************************************/
-/*                           ~netCDFDataset()                           */
-/************************************************************************/
+/************************************************************************/ 
+/*                              SetScale()                              */ 
+/************************************************************************/ 
+CPLErr netCDFRasterBand::SetScale( double dfNewScale )  
+{ 
+    dfScale = dfNewScale; 
 
-netCDFDataset::~netCDFDataset()
+    /* write value if in update mode */
+    if ( poDS->GetAccess() == GA_Update ) {
 
-{
-    FlushCache();
+        /* make sure we are in define mode */
+        ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
 
-    CSLDestroy( papszMetadata );
-    CSLDestroy( papszSubDatasets );
+        status = nc_put_att_double( cdfid, nZId, CF_SCALE_FACTOR,
+                                    NC_DOUBLE, 1, &dfScale );
 
-    CPLFree( pszProjection );
+        NCDF_ERR(status);
+        if ( status == NC_NOERR )
+            return CE_None;
+        else
+            return CE_Failure;
 
-    if( cdfid ) 
-        nc_close( cdfid );
+    }
+
+    return CE_None;
 }
 
 /************************************************************************/
-/*                           FetchCopyParm()                            */
+/*                           GetNoDataValue()                           */
 /************************************************************************/
 
-double netCDFDataset::FetchCopyParm( const char *pszGridMappingValue, 
-                                     const char *pszParm, double dfDefault )
+double netCDFRasterBand::GetNoDataValue( int * pbSuccess )
 
 {
-    char         szTemp[ MAX_NC_NAME ];
-    const char  *pszValue;
-
-    strcpy(szTemp,pszGridMappingValue);
-    strcat( szTemp, "#" );
-    strcat( szTemp, pszParm );
-    pszValue = CSLFetchNameValue(papszMetadata, szTemp);
+    if( pbSuccess )
+        *pbSuccess = bNoDataSet;
 
-    if( pszValue )
-    {
-        return CPLAtofM(pszValue);
-    }
+    if( bNoDataSet )
+        return dfNoDataValue;
     else
-        return dfDefault;
+        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
 /************************************************************************/
-/*                           FetchStandardParallels()                   */
+/*                           SetNoDataValue()                           */
 /************************************************************************/
 
-char** netCDFDataset::FetchStandardParallels( const char *pszGridMappingValue )
+CPLErr netCDFRasterBand::SetNoDataValue( double dfNoData )
+
 {
-    char         szTemp[ MAX_NC_NAME ];
-    const char   *pszValue;
-    char         **papszValues = NULL;
-    //cf-1.0 tags
-    strcpy( szTemp,pszGridMappingValue );
-    strcat( szTemp, "#" );
-    strcat( szTemp, STD_PARALLEL );
-    pszValue = CSLFetchNameValue( papszMetadata, szTemp );
-    if( pszValue != NULL )
-        papszValues = CSLTokenizeString2( pszValue, ",", CSLT_STRIPLEADSPACES |
-                                          CSLT_STRIPENDSPACES );
-    //try gdal tags
-    else
-    {
-        strcpy( szTemp, pszGridMappingValue );
-        strcat( szTemp, "#" );
-        strcat( szTemp, STD_PARALLEL_1 );
+    bNoDataSet = TRUE;
+    dfNoDataValue = dfNoData;
 
-        pszValue = CSLFetchNameValue( papszMetadata, szTemp );
-	
-        if ( pszValue != NULL )
-            papszValues = CSLAddString( papszValues, pszValue );
-				    
-        strcpy( szTemp,pszGridMappingValue );
-        strcat( szTemp, "#" );
-        strcat( szTemp, STD_PARALLEL_2 );
+    /* write value if in update mode */
+    if ( poDS->GetAccess() == GA_Update ) {
+
+        /* make sure we are in define mode */
+        ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
+
+        if ( eDataType == GDT_Byte) {
+            if ( bSignedData ) {
+                signed char cNoDataValue = (signed char) dfNoData;
+                status = nc_put_att_schar( cdfid, nZId, _FillValue,
+                                           nc_datatype, 1, &cNoDataValue );            
+            }
+            else {
+                unsigned char ucNoDataValue = (unsigned char) dfNoDataValue;
+                status = nc_put_att_uchar( cdfid, nZId, _FillValue,
+                                           nc_datatype, 1, &ucNoDataValue );            
+            }
+        }
+        else if ( eDataType == GDT_Int16 ) {
+            short int nsNoDataValue = (short int) dfNoDataValue;
+            status = nc_put_att_short( cdfid, nZId, _FillValue,
+                                       nc_datatype, 1, &nsNoDataValue );
+        }
+        else if ( eDataType == GDT_Int32) {
+            int nNoDataValue = (int) dfNoDataValue;
+            status = nc_put_att_int( cdfid, nZId, _FillValue,
+                                     nc_datatype, 1, &nNoDataValue );
+        }
+        else if ( eDataType == GDT_Float32) {
+            float fNoDataValue = (float) dfNoDataValue;
+            status = nc_put_att_float( cdfid, nZId, _FillValue,
+                                       nc_datatype, 1, &fNoDataValue );
+        }
+        else 
+            status = nc_put_att_double( cdfid, nZId, _FillValue,
+                                        nc_datatype, 1, &dfNoDataValue );
+
+        NCDF_ERR(status);
+        if ( status == NC_NOERR )
+            return CE_None;
+        else
+            return CE_Failure;
 
-        pszValue = CSLFetchNameValue( papszMetadata, szTemp );
-	
-        if( pszValue != NULL )	
-            papszValues = CSLAddString( papszValues, pszValue );
     }
-    
-    return papszValues;
+    return CE_None;
 }
 
 /************************************************************************/
-/*                           SetProjection()                            */
+/*                         CreateBandMetadata()                         */
 /************************************************************************/
-void netCDFDataset::SetProjection( int var )
+
+CPLErr netCDFRasterBand::CreateBandMetadata( int *paDimIds ) 
+
 {
+    char     szVarName[NC_MAX_NAME];
+    char     szMetaName[NC_MAX_NAME];
+    char     szMetaTemp[NCDF_MAX_STR_LEN];
+    char     *pszMetaValue = NULL;
+    char     szTemp[NC_MAX_NAME];
+    const char *pszValue;
+
+    int      nd;
+    int      i,j;
+    int      Sum  = 1;
+    int      Taken = 0;
+    int      result = 0;
+    int      status;
+    int      nVarID = -1;
+    int      nDims;
+    size_t   start[1];
+    size_t   count[1];
+    nc_type  nVarType = NC_NAT;
+    int      nAtt=0;
+
+    netCDFDataset *poDS = (netCDFDataset *) this->poDS;
+  
+/* -------------------------------------------------------------------- */
+/*      Compute all dimensions from Band number and save in Metadata    */
+/* -------------------------------------------------------------------- */
+    nc_inq_varname( cdfid, nZId, szVarName );
+    nc_inq_varndims( cdfid, nZId, &nd );
 /* -------------------------------------------------------------------- */
-/*      Set Projection                                                  */
+/*      Compute multidimention band position                            */
+/*                                                                      */
+/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
+/* if Data[2,3,4,x,y]                                                   */
+/*                                                                      */
+/*  BandPos0 = (nBand ) / (3*4)                                         */
+/*  BandPos1 = (nBand - BandPos0*(3*4) ) / (4)                          */
+/*  BandPos2 = (nBand - BandPos0*(3*4) ) % (4)                          */
 /* -------------------------------------------------------------------- */
 
-    size_t       start[2], edge[2];
-    int          status;
-    unsigned int i;
-    const char   *pszValue;
-    int          nVarProjectionID;
-    char         szVarName[ MAX_NC_NAME ];
-    char         szTemp[ MAX_NC_NAME ];
-    char         szGridMappingName[ MAX_NC_NAME ];
-    char         szGridMappingValue[ MAX_NC_NAME ];
+    sprintf( szMetaName,"NETCDF_VARNAME");
+    sprintf( szMetaTemp,"%s",szVarName);
+    SetMetadataItem( szMetaName, szMetaTemp );
+    if( nd == 3 ) {
+        Sum *= panBandZLev[0];
+    }
 
-    double       dfStdP1;
-    double       dfStdP2;
-    double       dfCenterLat;
-    double       dfCenterLon;
-    double       dfScale;
-    double       dfFalseEasting;
-    double       dfFalseNorthing;
-    double       dfCentralMeridian;
-    double       dfEarthRadius;
-    double       dfInverseFlattening;
-    double       dfLonPrimeMeridian;
-    double       dfSemiMajorAxis;
-    double       dfSemiMinorAxis;
-    
-    int          bGotGeogCS = FALSE;
+    for( i=0; i < nd-2 ; i++ ) {
+        if( i != nd - 2 -1 ) {
+            Sum = 1;
+            for( j=i+1; j < nd-2; j++ ) {
+                Sum *= panBandZLev[j];
+            }
+            result = (int) ( ( nLevel-Taken) / Sum );
+        }
+        else {
+            result = (int) ( ( nLevel-Taken) % Sum );
+        }
+        
+        strcpy(szVarName, 
+               poDS->papszDimName[paDimIds[panBandZPos[i]]] );
 
-    OGRSpatialReference oSRS;
-    int          nVarDimXID = -1;
-    int          nVarDimYID = -1;
-    double       *pdfXCoord;
-    double       *pdfYCoord;
-    char         szDimNameX[ MAX_NC_NAME ];
-    char         szDimNameY[ MAX_NC_NAME ];
-    int          nSpacingBegin;
-    int          nSpacingMiddle;
-    int          nSpacingLast;
+        sprintf( szMetaName,"NETCDF_DIMENSION_%s",  szVarName );
+
+        status=nc_inq_varid( cdfid, szVarName, &nVarID );
+
+/* -------------------------------------------------------------------- */
+/*      Try to uppercase the first letter of the variable               */
+/* -------------------------------------------------------------------- */
+
+        if( status != NC_NOERR ) {
+            szVarName[0]=(char) toupper(szVarName[0]);
+            status=nc_inq_varid( cdfid, szVarName, &nVarID );
+        }
+
+        status = nc_inq_vartype( cdfid, nVarID, &nVarType );
+
+        nDims = 0;
+        status = nc_inq_varndims( cdfid, nVarID, &nDims );
+
+        if( nDims == 1 ) {
+            count[0]=1;
+            start[0]=result;
+            switch( nVarType ) {
+                case NC_SHORT:
+                    short sData;
+                    status =  nc_get_vara_short( cdfid, nVarID, 
+                                                 start,
+                                                 count, &sData );
+                    sprintf( szMetaTemp,"%d", sData );
+                    break;
+                case NC_INT:
+                    int nData;
+                    status =  nc_get_vara_int( cdfid, nVarID, 
+                                               start,
+                                               count, &nData );
+                    sprintf( szMetaTemp,"%d", nData );
+                    break;
+                case NC_FLOAT:
+                    float fData;
+                    status =  nc_get_vara_float( cdfid, nVarID, 
+                                                 start,
+                                                 count, &fData );
+                    sprintf( szMetaTemp,"%.8g", fData );
+                    break;
+                case NC_DOUBLE:
+                    double dfData;
+                    status =  nc_get_vara_double( cdfid, nVarID, 
+                                                  start,
+                                                  count, &dfData);
+                    sprintf( szMetaTemp,"%.16g", dfData );
+                    break;
+                default: 
+                    CPLDebug( "GDAL_netCDF", "invalid dim %s, type=%d", 
+                              szMetaTemp, nVarType);
+                    break;
+            }
+        }
+        else
+            sprintf( szMetaTemp,"%d", result+1);
+	
+        CPLDebug( "GDAL_netCDF", "setting dimension metadata %s=%s", 
+                  szMetaName, szMetaTemp );
+
+        SetMetadataItem( szMetaName, szMetaTemp );
+
+/* -------------------------------------------------------------------- */
+/*      Fetch dimension units                                           */
+/* -------------------------------------------------------------------- */
+
+        strcpy( szTemp, szVarName );
+        strcat( szTemp, "#units" );
+        pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+        if( pszValue != NULL ) {
+            if( EQUAL( pszValue, "T") ) { 
+                strcpy( szTemp, szVarName );
+                strcat( szTemp, "#original_units" );
+                pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+                strcpy( szTemp, "NETCDF_");
+                strcat( szTemp, szVarName );
+                strcat( szTemp, "_original_units" );
+                SetMetadataItem( szTemp, pszValue );
+            }
+            else {
+                strcpy( szTemp, "NETCDF_");
+                strcat( szTemp, szVarName  );
+                strcat( szTemp, "_units" );
+                SetMetadataItem( szTemp, pszValue );
+            }
+        }
+        Taken += result * Sum;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get all other metadata                                          */
+/* -------------------------------------------------------------------- */
+    nc_inq_varnatts( cdfid, nZId, &nAtt );
+
+    for( i=0; i < nAtt ; i++ ) {
+
+    	status = nc_inq_attname( cdfid, nZId, i, szTemp);
+    	// if(strcmp(szTemp,_FillValue) ==0) continue;
+    	sprintf( szMetaName,"%s",szTemp);       
+
+        if ( NCDFGetAttr( cdfid, nZId, szMetaName, &pszMetaValue) 
+             == CE_None ) {
+            SetMetadataItem( szMetaName, pszMetaValue );
+        }
+        else {
+            CPLDebug( "GDAL_netCDF", "invalid Band metadata %s", szMetaName );
+        }
+
+        if ( pszMetaValue )  {
+            CPLFree( pszMetaValue );
+            pszMetaValue = NULL;
+        }
+
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                             CheckValidData()                         */
+/************************************************************************/
+template <class T>
+void  netCDFRasterBand::CheckValidData ( void * pImage, int bCheckIsNan ) 
+{
+    int i;
+    CPLAssert( pImage != NULL );
+
+    /* check if needed or requested */
+    if (  (adfValidRange[0] != dfNoDataValue) || 
+          (adfValidRange[1] != dfNoDataValue) ||
+          bCheckIsNan ) {
+
+        for( i=0; i<nBlockXSize; i++ ) {         
+            /* check for nodata and nan */
+            if ( CPLIsEqual( (double) ((T *)pImage)[i], dfNoDataValue ) )
+                continue;
+            if( bCheckIsNan && CPLIsNan( ( (T *) pImage)[i] ) ) {
+                ( (T *)pImage )[i] = (T)dfNoDataValue;
+                continue;
+            }
+            /* check for valid_range */
+            if ( ( ( adfValidRange[0] != dfNoDataValue ) && 
+                   ( ((T *)pImage)[i] < (T)adfValidRange[0] ) ) 
+                 || 
+                 ( ( adfValidRange[1] != dfNoDataValue ) && 
+                   ( ((T *)pImage)[i] > (T)adfValidRange[1] ) ) ) {
+                ( (T *)pImage )[i] = (T)dfNoDataValue;
+            }
+        }
+        
+    }
+
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                     void * pImage )
+
+{
+    size_t start[ MAX_NC_DIMS ];
+    size_t edge[ MAX_NC_DIMS ];
+    char   pszName[ NCDF_MAX_STR_LEN ];
+    int    i,j;
+    int    Sum=-1;
+    int    Taken=-1;
+    int    nd;
+
+    *pszName='\0';
+    memset( start, 0, sizeof( start ) );
+    memset( edge,  0, sizeof( edge )  );
+    nc_inq_varndims ( cdfid, nZId, &nd );
+
+/* -------------------------------------------------------------------- */
+/*      Locate X, Y and Z position in the array                         */
+/* -------------------------------------------------------------------- */
+	
+    start[nBandXPos] = 0;          // x dim can move arround in array
+    // check y order
+    if( ( ( netCDFDataset *) poDS )->bBottomUp ) {
+        start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;
+    } else {
+        start[nBandYPos] = nBlockYOff; // y
+    }
+        
+    edge[nBandXPos] = nBlockXSize; 
+    edge[nBandYPos] = 1;
+
+    if( nd == 3 ) {
+        start[panBandZPos[0]]  = nLevel;     // z
+        edge [panBandZPos[0]]  = 1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute multidimention band position                            */
+/*                                                                      */
+/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
+/* if Data[2,3,4,x,y]                                                   */
+/*                                                                      */
+/*  BandPos0 = (nBand ) / (3*4)                                         */
+/*  BandPos1 = (nBand - (3*4) ) / (4)                                   */
+/*  BandPos2 = (nBand - (3*4) ) % (4)                                   */
+/* -------------------------------------------------------------------- */
+    if (nd > 3) 
+    {
+        Taken = 0;
+        for( i=0; i < nd-2 ; i++ ) 
+        {
+            if( i != nd - 2 -1 ) {
+                Sum = 1;
+                for( j=i+1; j < nd-2; j++ ) {
+                    Sum *= panBandZLev[j];
+                }
+                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) / Sum );
+                edge[panBandZPos[i]] = 1;
+            } else {
+                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) % Sum );
+                edge[panBandZPos[i]] = 1;
+            }
+            Taken += start[panBandZPos[i]] * Sum;
+        }
+    }
+
+    if( eDataType == GDT_Byte ) 
+    {
+        if (this->bSignedData) 
+        {
+            status = nc_get_vara_schar( cdfid, nZId, start, edge, 
+                                      (signed char *) pImage );
+            if ( status == NC_NOERR ) CheckValidData<signed char>( pImage );
+        }
+        else {
+            status = nc_get_vara_uchar( cdfid, nZId, start, edge, 
+                                      (unsigned char *) pImage );
+            if ( status == NC_NOERR ) CheckValidData<unsigned char>( pImage );
+        }
+    }
+    else if( eDataType == GDT_Int16 )
+    {
+        status = nc_get_vara_short( cdfid, nZId, start, edge, 
+                                  (short int *) pImage );
+        if ( status == NC_NOERR ) CheckValidData<short int>( pImage );
+    }
+    else if( eDataType == GDT_Int32 )
+    {
+        if( sizeof(long) == 4 )
+        {
+            status = nc_get_vara_long( cdfid, nZId, start, edge, 
+                                     (long *) pImage );
+            if ( status == NC_NOERR ) CheckValidData<long>( pImage );
+        }
+        else
+        {
+            status = nc_get_vara_int( cdfid, nZId, start, edge, 
+                                    (int *) pImage );
+            if ( status == NC_NOERR ) CheckValidData<int>( pImage );
+        }
+    }
+    else if( eDataType == GDT_Float32 )
+    {
+        status = nc_get_vara_float( cdfid, nZId, start, edge, 
+                                  (float *) pImage );
+        if ( status == NC_NOERR ) CheckValidData<float>( pImage, TRUE );
+    }
+    else if( eDataType == GDT_Float64 )
+    {
+        status = nc_get_vara_double( cdfid, nZId, start, edge, 
+                                   (double *) pImage ); 
+        if ( status == NC_NOERR ) CheckValidData<double>( pImage, TRUE );
+    } 
+    else
+        status = NC_EBADTYPE;
+
+    if( status != NC_NOERR )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "netCDF scanline fetch failed: %s", 
+                  nc_strerror( status ) );
+        return CE_Failure;
+    }
+    else
+        return CE_None;
+}
+
+/************************************************************************/
+/*                             IWriteBlock()                            */
+/************************************************************************/
+
+CPLErr netCDFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
+                                      void * pImage )
+
+{
+    int    status=-1;//, status2=-1;
+    // int    cdfid = ( ( netCDFDataset * ) poDS )->cdfid;
+    size_t start[ NCDF_NBDIM ];
+    size_t edge[ MAX_NC_DIMS ];
+    char   pszName[ NCDF_MAX_STR_LEN ];
+    int    i,j;
+    int    Sum=-1;
+    int    Taken=-1;
+    int    nd;
+
+    *pszName='\0';
+    memset( start, 0, sizeof( start ) );
+    memset( edge,  0, sizeof( edge )  );
+    // nc_inq_varndims ( cdfid, nZId, &nd );
+    nd=2;
+  
+/* -------------------------------------------------------------------- */
+/*      Locate X, Y and Z position in the array                         */
+/* -------------------------------------------------------------------- */
+	
+    start[nBandXPos] = 0;          // x dim can move arround in array
+    // check y order
+    if( ( ( netCDFDataset *) poDS )->bBottomUp ) {
+        start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;
+    } else {
+        start[nBandYPos] = nBlockYOff; // y
+    }
+        
+    edge[nBandXPos] = nBlockXSize; 
+    edge[nBandYPos] = 1;
+
+    if( nd == 3 ) {
+        start[panBandZPos[0]]  = nLevel;     // z
+        edge [panBandZPos[0]]  = 1;
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Compute multidimention band position                            */
+/*                                                                      */
+/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
+/* if Data[2,3,4,x,y]                                                   */
+/*                                                                      */
+/*  BandPos0 = (nBand ) / (3*4)                                         */
+/*  BandPos1 = (nBand - (3*4) ) / (4)                                   */
+/*  BandPos2 = (nBand - (3*4) ) % (4)                                   */
+/* -------------------------------------------------------------------- */
+    if (nd > 3) 
+    {
+        Taken = 0;
+        for( i=0; i < nd-2 ; i++ ) 
+        {
+            if( i != nd - 2 -1 ) {
+                Sum = 1;
+                for( j=i+1; j < nd-2; j++ ) {
+                    Sum *= panBandZLev[j];
+                }
+                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) / Sum );
+                edge[panBandZPos[i]] = 1;
+            } else {
+                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) % Sum );
+                edge[panBandZPos[i]] = 1;
+            }
+            Taken += start[panBandZPos[i]] * Sum;
+        }
+    }
+    
+    /* make sure we are in data mode */
+    ( ( netCDFDataset * ) poDS )->SetDefineMode( FALSE );
+
+    /* copy data according to type */
+    if( eDataType == GDT_Byte ) {
+        if ( this->bSignedData ) 
+            status = nc_put_vara_schar( cdfid, nZId, start, edge, 
+                                         (signed char*) pImage);
+        else
+            status = nc_put_vara_uchar( cdfid, nZId, start, edge, 
+                                         (unsigned char*) pImage);
+    }
+    else if( ( eDataType == GDT_UInt16 ) || ( eDataType == GDT_Int16 ) ) {
+        status = nc_put_vara_short( cdfid, nZId, start, edge, 
+                                     (short int *) pImage);
+    }
+    else if( eDataType == GDT_Int32 ) {
+        status = nc_put_vara_int( cdfid, nZId, start, edge, 
+                                   (int *) pImage);
+    }
+    else if( eDataType == GDT_Float32 ) {
+        status = nc_put_vara_float( cdfid, nZId, start, edge, 
+                                    (float *) pImage);
+    }
+    else if( eDataType == GDT_Float64 ) {
+        status = nc_put_vara_double( cdfid, nZId, start, edge, 
+                                     (double *) pImage);
+    }
+    else {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "The NetCDF driver does not support GDAL data type %d",
+                  eDataType );
+        status = NC_EBADTYPE;
+    }
+    NCDF_ERR(status);
+
+    if( status != NC_NOERR )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "netCDF scanline write failed: %s", 
+                  nc_strerror( status ) );
+        return CE_Failure;
+    }
+    else 
+        return CE_None;
+
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*				netCDFDataset				                            */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                           netCDFDataset()                            */
+/************************************************************************/
+
+netCDFDataset::netCDFDataset()
+
+{
+    /* basic dataset vars */
+    cdfid            = -1;
+    papszSubDatasets = NULL;
+    papszMetadata    = NULL;	
+    bBottomUp        = TRUE;
+    nFormat          = NCDF_FORMAT_NONE;
+    bIsGdalFile      = FALSE;
+    bIsGdalCfFile    = FALSE;
+
+    /* projection/GT */
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
+    pszProjection    = NULL;
+    nXDimID = -1;
+    nYDimID = -1;
+    bIsProjected = FALSE;
+    bIsGeographic = FALSE; /* can be not projected, and also not geographic */
+
+    /* state vars */
+    status = NC_NOERR;
+    bDefineMode = TRUE;    
+    bSetProjection = FALSE;
+    bSetGeoTransform = FALSE;    
+    bAddedProjectionVars = FALSE;
+
+    /* create vars */
+    papszCreationOptions = NULL;
+    nCompress = NCDF_COMPRESS_NONE;
+    nZLevel = NCDF_DEFLATE_LEVEL;
+    nCreateMode = NC_CLOBBER;
+    bSignedData = TRUE;
+}
+
+
+/************************************************************************/
+/*                           ~netCDFDataset()                           */
+/************************************************************************/
+
+netCDFDataset::~netCDFDataset()
+
+{
+    /* make sure projection is written if GeoTransform OR Projection are missing */
+        if( (GetAccess() == GA_Update) && (! bAddedProjectionVars) ) {
+        if ( bSetProjection && ! bSetGeoTransform )
+            AddProjectionVars();
+        else if ( bSetGeoTransform && ! bSetProjection )
+            AddProjectionVars();
+            // CPLError( CE_Warning, CPLE_AppDefined, 
+            //           "netCDFDataset::~netCDFDataset() Projection was not defined, projection will be missing" );
+    }
+    FlushCache();
+
+    CSLDestroy( papszMetadata );
+    CSLDestroy( papszSubDatasets );
+    CSLDestroy( papszCreationOptions );
+
+    if( pszProjection )
+        CPLFree( pszProjection );
+
+    if( cdfid ) 
+        nc_close( cdfid );
+}
+
+/************************************************************************/
+/*                            SetDefineMode()                           */
+/************************************************************************/
+int netCDFDataset::SetDefineMode( int bNewDefineMode )
+{
+    /* do nothing, already in same mode */
+    if ( bDefineMode == bNewDefineMode ) return CE_None;
+
+    CPLDebug( "GDAL_netCDF", "SetDefineMode(%d) old=%d",
+              bNewDefineMode, bDefineMode );
+
+    bDefineMode = bNewDefineMode;
+    
+    if ( bDefineMode == TRUE ) 
+        status = nc_redef( cdfid );
+    else
+        status = nc_enddef( cdfid );
+
+    NCDF_ERR(status);
+    return status;
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+char **netCDFDataset::GetMetadata( const char *pszDomain )
+{
+    if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) )
+        return papszSubDatasets;
+    else
+        return GDALDataset::GetMetadata( pszDomain );
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char * netCDFDataset::GetProjectionRef()
+{
+    if( bSetProjection )
+        return pszProjection;
+    else
+        return GDALPamDataset::GetProjectionRef();
+}
+
+/************************************************************************/
+/*                           FetchCopyParm()                            */
+/************************************************************************/
+
+double netCDFDataset::FetchCopyParm( const char *pszGridMappingValue, 
+                                     const char *pszParm, double dfDefault )
+
+{
+    char         szTemp[ MAX_NC_NAME ];
+    const char  *pszValue;
+
+    strcpy(szTemp,pszGridMappingValue);
+    strcat( szTemp, "#" );
+    strcat( szTemp, pszParm );
+    pszValue = CSLFetchNameValue(papszMetadata, szTemp);
+
+    if( pszValue )
+    {
+        return CPLAtofM(pszValue);
+    }
+    else
+        return dfDefault;
+}
+
+/************************************************************************/
+/*                           FetchStandardParallels()                   */
+/************************************************************************/
+
+char** netCDFDataset::FetchStandardParallels( const char *pszGridMappingValue )
+{
+    char         szTemp[ MAX_NC_NAME ];
+    const char   *pszValue;
+    char         **papszValues = NULL;
+    //cf-1.0 tags
+    strcpy( szTemp,pszGridMappingValue );
+    strcat( szTemp, "#" );
+    strcat( szTemp, CF_PP_STD_PARALLEL );
+    pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+    if( pszValue != NULL ) {
+        // papszValues = CSLTokenizeString2( pszValue, ",", CSLT_STRIPLEADSPACES |
+        //                                   CSLT_STRIPENDSPACES );
+        /* format has changed to { std1, std2 }, must remove { and } */
+        strcpy( szTemp,pszValue );
+        int last_char = strlen(pszValue) - 1;
+        if ( szTemp[0] == '{' ) szTemp[0] = ' ';
+        if ( szTemp[last_char] == '}' ) szTemp[last_char] = ' ';
+        papszValues = CSLTokenizeString2( szTemp, ",", CSLT_STRIPLEADSPACES |
+                                          CSLT_STRIPENDSPACES );
+    }
+    //try gdal tags
+    else
+    {
+        strcpy( szTemp, pszGridMappingValue );
+        strcat( szTemp, "#" );
+        strcat( szTemp, CF_PP_STD_PARALLEL_1 );
+
+        pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+	
+        if ( pszValue != NULL )
+            papszValues = CSLAddString( papszValues, pszValue );
+				    
+        strcpy( szTemp,pszGridMappingValue );
+        strcat( szTemp, "#" );
+        strcat( szTemp, CF_PP_STD_PARALLEL_2 );
+
+        pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+	
+        if( pszValue != NULL )	
+            papszValues = CSLAddString( papszValues, pszValue );
+    }
+    
+    return papszValues;
+}
+
+/************************************************************************/
+/*                      SetProjectionFromVar()                          */
+/************************************************************************/
+void netCDFDataset::SetProjectionFromVar( int var )
+{
+    size_t       start[2], edge[2];
+    unsigned int i;
+    const char   *pszValue;
+    int          nVarProjectionID;
+    char         szVarName[ MAX_NC_NAME ];
+    char         szTemp[ MAX_NC_NAME ];
+    char         szGridMappingName[ MAX_NC_NAME ];
+    char         szGridMappingValue[ MAX_NC_NAME ];
+
+    double       dfStdP1=0.0;
+    double       dfStdP2=0.0;
+    double       dfCenterLat;
+    double       dfCenterLon;
+    double       dfScale;
+    double       dfFalseEasting;
+    double       dfFalseNorthing;
+    double       dfCentralMeridian;
+    double       dfEarthRadius;
+    double       dfInverseFlattening;
+    double       dfLonPrimeMeridian;
+    double       dfSemiMajorAxis;
+    double       dfSemiMinorAxis;
+    
+    int          bGotGeogCS = FALSE;
+    int          bGotCfSRS = FALSE;
+    int          bGotGdalSRS = FALSE;
+    int          bGotCfGT = FALSE;
+    int          bGotGdalGT = FALSE;
+    int          bLookForWellKnownGCS = FALSE;  //this could be a Config Option
+
+    /* These values from CF metadata */
+    OGRSpatialReference oSRS;
+    int          nVarDimXID = -1;
+    int          nVarDimYID = -1;
+    double       *pdfXCoord;
+    double       *pdfYCoord;
+    char         szDimNameX[ MAX_NC_NAME ];
+    char         szDimNameY[ MAX_NC_NAME ];
+    int          nSpacingBegin;
+    int          nSpacingMiddle;
+    int          nSpacingLast;
+    size_t       xdim = nRasterXSize;
+    size_t       ydim = nRasterYSize;
+
+    const char  *pszUnits = NULL;
+
+    /* These values from GDAL metadata */
+    const char *pszWKT = NULL;
+    const char *pszGeoTransform = NULL;
+    char **papszGeoTransform = NULL;
+
+    netCDFDataset * poDS = this; /* perhaps this should be removed for clarity */
+
+    /* temp variables to use in SetGeoTransform() and SetProjection() */
+    double      adfTempGeoTransform[6];
+    char        *pszTempProjection;
+
+    CPLDebug( "GDAL_netCDF", "\n=====\nSetProjectionFromVar( %d )\n", var );
+
+/* -------------------------------------------------------------------- */
+/*      Get x/y range information.                                      */
+/* -------------------------------------------------------------------- */
+
+    adfTempGeoTransform[0] = 0.0;
+    adfTempGeoTransform[1] = 1.0;
+    adfTempGeoTransform[2] = 0.0;
+    adfTempGeoTransform[3] = 0.0;
+    adfTempGeoTransform[4] = 0.0;
+    adfTempGeoTransform[5] = 1.0;
+    pszTempProjection = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Look for grid_mapping metadata                                  */
+/* -------------------------------------------------------------------- */
+
+    strcpy( szGridMappingValue, "" );
+    strcpy( szGridMappingName, "" );
+
+    nc_inq_varname( cdfid, var, szVarName );
+    strcpy(szTemp,szVarName);
+    strcat(szTemp,"#");
+    strcat(szTemp,CF_GRD_MAPPING);
+
+    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+    if( pszValue ) {
+        strcpy(szGridMappingName,szTemp);
+        strcpy(szGridMappingValue,pszValue);
+    }
+
+    if( !EQUAL( szGridMappingValue, "" )  ) {
+
+        /*  Read grid_mapping metadata */
+        nc_inq_varid( cdfid, szGridMappingValue, &nVarProjectionID );
+        poDS->ReadAttributes( cdfid, nVarProjectionID );
+        
+/* -------------------------------------------------------------------- */
+/*      Look for GDAL spatial_ref and GeoTransform within grid_mapping  */
+/* -------------------------------------------------------------------- */
+        CPLDebug( "GDAL_netCDF", "got grid_mapping %s", szGridMappingValue );
+        strcpy( szTemp,szGridMappingValue);
+        strcat( szTemp, "#" );
+        strcat( szTemp, NCDF_SPATIAL_REF);
+
+        pszWKT = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+	
+        if( pszWKT != NULL ) {
+            strcpy( szTemp,szGridMappingValue);
+            strcat( szTemp, "#" );
+            strcat( szTemp, NCDF_GEOTRANSFORM);
+            pszGeoTransform = CSLFetchNameValue(poDS->papszMetadata, szTemp);	    
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get information about the file.                                 */
+/* -------------------------------------------------------------------- */
+/*      Was this file created by the GDAL netcdf driver?                */
+/*      Was this file created by the newer (CF-conformant) driver?      */
+/* -------------------------------------------------------------------- */
+/* 1) If GDAL netcdf metadata is set, and version >= 1.9,               */
+/*    it was created with the new driver                                */
+/* 2) Else, if spatial_ref and GeoTransform are present in the          */
+/*    grid_mapping variable, it was created by the old driver           */
+/* -------------------------------------------------------------------- */
+    pszValue = CSLFetchNameValue(poDS->papszMetadata, "NC_GLOBAL#GDAL");
+
+   if( pszValue && NCDFIsGDALVersionGTE(pszValue, 1900)) {
+        bIsGdalFile = TRUE;
+        bIsGdalCfFile = TRUE;
+    }
+    else  if( pszWKT != NULL && pszGeoTransform != NULL ) {
+        bIsGdalFile = TRUE;
+        bIsGdalCfFile = FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set default bottom-up default value                             */
+/*      Y axis dimension and absence of GT can modify this value        */
+/*      Override with Config option GDAL_NETCDF_BOTTOMUP                */ 
+/* -------------------------------------------------------------------- */
+   /* new driver is bottom-up by default */
+   if ( bIsGdalFile && ! bIsGdalCfFile )
+       poDS->bBottomUp = FALSE;
+   else
+       poDS->bBottomUp = TRUE;
+
+    CPLDebug( "GDAL_netCDF", 
+              "bIsGdalFile=%d bIsGdalCfFile=%d bBottomUp=%d", 
+              bIsGdalFile, bIsGdalCfFile, bBottomUp );
+ 
+/* -------------------------------------------------------------------- */
+/*      Look for dimension: lon                                         */
+/* -------------------------------------------------------------------- */
+
+    memset( szDimNameX, '\0', sizeof( char ) * MAX_NC_NAME );
+    memset( szDimNameY, '\0', sizeof( char ) * MAX_NC_NAME );
+
+    for( i = 0; (i < strlen( poDS->papszDimName[ poDS->nXDimID ] )  && 
+                 i < 3 ); i++ ) {
+        szDimNameX[i]=(char)tolower( ( poDS->papszDimName[poDS->nXDimID] )[i] );
+    }
+    szDimNameX[3] = '\0';
+    for( i = 0; (i < strlen( poDS->papszDimName[ poDS->nYDimID ] )  && 
+                 i < 3 ); i++ ) {
+        szDimNameY[i]=(char)tolower( ( poDS->papszDimName[poDS->nYDimID] )[i] );
+    }
+    szDimNameY[3] = '\0';
+
+/* -------------------------------------------------------------------- */
+/*      Read grid_mapping information and set projections               */
+/* -------------------------------------------------------------------- */
+
+    if( !( EQUAL(szGridMappingName,"" ) ) ) {
+     
+        strcpy( szTemp, szGridMappingValue );
+        strcat( szTemp, "#" );
+        strcat( szTemp, CF_GRD_MAPPING_NAME );
+        pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+
+        if( pszValue != NULL ) {
+
+/* -------------------------------------------------------------------- */
+/*      Check for datum/spheroid information                            */
+/* -------------------------------------------------------------------- */
+            dfEarthRadius = 
+                poDS->FetchCopyParm( szGridMappingValue, 
+                                     CF_PP_EARTH_RADIUS, 
+                                     -1.0 );
+
+            dfLonPrimeMeridian = 
+                poDS->FetchCopyParm( szGridMappingValue,
+                                     CF_PP_LONG_PRIME_MERIDIAN, 
+                                     0.0 );
+
+            dfInverseFlattening = 
+                poDS->FetchCopyParm( szGridMappingValue, 
+                                     CF_PP_INVERSE_FLATTENING, 
+                                     -1.0 );
+	    
+            dfSemiMajorAxis = 
+                poDS->FetchCopyParm( szGridMappingValue, 
+                                     CF_PP_SEMI_MAJOR_AXIS, 
+                                     -1.0 );
+	    
+            dfSemiMinorAxis = 
+                poDS->FetchCopyParm( szGridMappingValue, 
+                                     CF_PP_SEMI_MINOR_AXIS, 
+                                     -1.0 );
+
+            //see if semi-major exists if radius doesn't
+            if( dfEarthRadius < 0.0 )
+                dfEarthRadius = dfSemiMajorAxis;
+	    
+            //if still no radius, check old tag
+            if( dfEarthRadius < 0.0 )
+                dfEarthRadius = poDS->FetchCopyParm( szGridMappingValue, 
+                                                     CF_PP_EARTH_RADIUS_OLD,
+                                                     -1.0 );
+
+            //has radius value
+            if( dfEarthRadius > 0.0 ) {
+                //check for inv_flat tag
+                if( dfInverseFlattening < 0.0 ) {
+                    //no inv_flat tag, check for semi_minor
+                    if( dfSemiMinorAxis < 0.0 ) {
+                        //no way to get inv_flat, use sphere
+                        oSRS.SetGeogCS( "unknown", 
+                                        NULL, 
+                                        "Sphere", 
+                                        dfEarthRadius, 0.0 );
+                        bGotGeogCS = TRUE;
+                    }
+                    else {
+                        if( dfSemiMajorAxis < 0.0 )
+                            dfSemiMajorAxis = dfEarthRadius;
+                        //set inv_flat using semi_minor/major
+                        dfInverseFlattening = 
+                            1.0 / ( dfSemiMajorAxis - dfSemiMinorAxis ) / dfSemiMajorAxis;
+                        oSRS.SetGeogCS( "unknown", 
+                                        NULL, 
+                                        "Spheroid", 
+                                        dfEarthRadius, dfInverseFlattening );
+                        bGotGeogCS = TRUE;
+                    }
+                }
+                else {
+                    oSRS.SetGeogCS( "unknown", 
+                                    NULL, 
+                                    "Spheroid", 
+                                    dfEarthRadius, dfInverseFlattening );
+                    bGotGeogCS = TRUE;
+                }  
+
+                if ( bGotGeogCS )
+                    CPLDebug( "GDAL_netCDF", "got spheroid from CF: (%f , %f)", dfEarthRadius, dfInverseFlattening );
+
+            }
+            //no radius, set as wgs84 as default?
+            else {
+                // This would be too indiscrimant.  But we should set
+                // it if we know the data is geographic.
+                //oSRS.SetWellKnownGeogCS( "WGS84" );
+            }
+	    		
+/* -------------------------------------------------------------------- */
+/*      Transverse Mercator                                             */
+/* -------------------------------------------------------------------- */
+
+            if( EQUAL( pszValue, CF_PT_TM ) ) {
+
+                dfScale = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_SCALE_FACTOR_MERIDIAN, 1.0 );
+
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
+
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+ 
+                bGotCfSRS = TRUE;
+                oSRS.SetTM( dfCenterLat, 
+                            dfCenterLon,
+                            dfScale,
+                            dfFalseEasting,
+                            dfFalseNorthing );
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Albers Equal Area                                               */
+/* -------------------------------------------------------------------- */
+
+            if( EQUAL( pszValue, CF_PT_AEA ) ) {
+
+                char **papszStdParallels = NULL;
+		
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
+
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+		
+                papszStdParallels = 
+                    FetchStandardParallels( szGridMappingValue );
+
+                if( papszStdParallels != NULL ) {
+		  
+                    if ( CSLCount( papszStdParallels ) == 1 ) {
+                        /* TODO CF-1 standard says it allows AEA to be encoded with only 1 standard parallel */
+                        /* how should this actually map to a 2StdP OGC WKT version? */
+                        CPLError( CE_Warning, CPLE_NotSupported, 
+                                  "NetCDF driver import of AEA-1SP is not tested, using identical std. parallels\n" );
+                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                        dfStdP2 = dfStdP1;
+
+                    }
+		
+                    else if( CSLCount( papszStdParallels ) == 2 ) {
+                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                        dfStdP2 = CPLAtofM( papszStdParallels[1] );
+                    }
+                }
+                //old default
+                else {
+                    dfStdP1 = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_STD_PARALLEL_1, 0.0 );
+
+                    dfStdP2 = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_STD_PARALLEL_2, 0.0 );
+                }
+
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                bGotCfSRS = TRUE;
+                oSRS.SetACEA( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
+                              dfFalseEasting, dfFalseNorthing );
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+
+                CSLDestroy( papszStdParallels );
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Cylindrical Equal Area                                          */
+/* -------------------------------------------------------------------- */
+
+            else if( EQUAL( pszValue, CF_PT_CEA ) || EQUAL( pszValue, CF_PT_LCEA ) ) {
+
+                char **papszStdParallels = NULL;
+
+                papszStdParallels = 
+                    FetchStandardParallels( szGridMappingValue );
+
+                if( papszStdParallels != NULL ) {
+                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                }
+                else {
+                    //TODO: add support for 'scale_factor_at_projection_origin' variant to standard parallel
+                    //Probably then need to calc a std parallel equivalent
+                    CPLError( CE_Failure, CPLE_NotSupported, 
+                              "NetCDF driver does not support import of CF-1 LCEA "
+                              "'scale_factor_at_projection_origin' variant yet.\n" );
+                }
+
+                dfCentralMeridian = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+		
+                bGotCfSRS = TRUE;
+                oSRS.SetCEA( dfStdP1, dfCentralMeridian,
+                             dfFalseEasting, dfFalseNorthing );
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+		
+                CSLDestroy( papszStdParallels );
+            }
+
+/* -------------------------------------------------------------------- */
+/*      lambert_azimuthal_equal_area                                    */
+/* -------------------------------------------------------------------- */
+            else if( EQUAL( pszValue, CF_PT_LAEA ) ) {
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+
+                oSRS.SetProjCS( "LAEA (WGS84) " );
+		
+                bGotCfSRS = TRUE;
+                oSRS.SetLAEA( dfCenterLat, dfCenterLon,
+                              dfFalseEasting, dfFalseNorthing );
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+		
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Azimuthal Equidistant                                           */
+/* -------------------------------------------------------------------- */
+            else if( EQUAL( pszValue, CF_PT_AE ) ) {
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+
+                bGotCfSRS = TRUE;
+                oSRS.SetAE( dfCenterLat, dfCenterLon,
+                            dfFalseEasting, dfFalseNorthing );
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+		
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Lambert conformal conic                                         */
+/* -------------------------------------------------------------------- */
+            else if( EQUAL( pszValue, CF_PT_LCC ) ) {
+		
+                char **papszStdParallels = NULL;
+		
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
+
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+		
+                papszStdParallels = 
+                    FetchStandardParallels( szGridMappingValue );
+
+                /* 2SP variant */
+                if( CSLCount( papszStdParallels ) == 2 ) {
+                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                    dfStdP2 = CPLAtofM( papszStdParallels[1] );
+                    oSRS.SetLCC( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
+                                 dfFalseEasting, dfFalseNorthing );
+                }
+                /* 1SP variant (with standard_parallel or center lon) */
+                /* See comments in netcdfdataset.h for this projection. */
+                else {
+
+                    dfScale = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_SCALE_FACTOR_ORIGIN, -1.0 );
+                    
+                    /* CF definition, without scale factor */
+                    if( CPLIsEqual(dfScale, -1.0) ) {
+
+                        /* with standard_parallel */
+                        if( CSLCount( papszStdParallels ) == 1 )
+                            dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                        /* with center lon instead */
+                        else 
+                            dfStdP1 = dfCenterLat;
+                        dfStdP2 = dfStdP1;
+                        
+                        /* test if we should actually compute scale factor */
+                        if ( ! CPLIsEqual( dfStdP1, dfCenterLat ) ) {
+                            CPLError( CE_Warning, CPLE_NotSupported, 
+                                      "NetCDF driver import of LCC-1SP with standard_parallel1 != latitude_of_projection_origin\n"
+                                      "(which forces a computation of scale_factor) is experimental (bug #3324)\n" );
+                            /* use Snyder eq. 15-4 to compute dfScale from dfStdP1 and dfCenterLat */
+                            /* only tested for dfStdP1=dfCenterLat and (25,26), needs more data for testing */
+                            /* other option: use the 2SP variant - how to compute new standard parallels? */
+                            dfScale = ( cos(dfStdP1) * pow( tan(NCDF_PI/4 + dfStdP1/2), sin(dfStdP1) ) ) /
+                                ( cos(dfCenterLat) * pow( tan(NCDF_PI/4 + dfCenterLat/2), sin(dfCenterLat) ) );
+                        }
+                        /* default is 1.0 */
+                        else                    
+                            dfScale = 1.0;
+                        
+                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale, 
+                                        dfFalseEasting, dfFalseNorthing );
+                        /* store dfStdP1 so we can output it to CF later */
+                        oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
+                    }
+                    /* OGC/PROJ.4 definition with scale factor */
+                    else {
+                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale, 
+                                        dfFalseEasting, dfFalseNorthing );
+                    }
+                }
+		
+
+                bGotCfSRS = TRUE;
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+
+                CSLDestroy( papszStdParallels );
+            }
+		
+/* -------------------------------------------------------------------- */
+/*      Is this Latitude/Longitude Grid explicitly                      */
+/* -------------------------------------------------------------------- */
+	    
+            else if ( EQUAL ( pszValue, CF_PT_LATITUDE_LONGITUDE ) ) {
+                bGotCfSRS = TRUE;
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+            }
+/* -------------------------------------------------------------------- */
+/*      Mercator                                                        */
+/* -------------------------------------------------------------------- */
+		  
+            else if ( EQUAL ( pszValue, CF_PT_MERCATOR ) ) {
+
+                char **papszStdParallels = NULL;
+
+                /* If there is a standard_parallel, know it is Mercator 2SP */
+                papszStdParallels = 
+                    FetchStandardParallels( szGridMappingValue );
+                
+                if (NULL != papszStdParallels) {
+                    /* CF-1 Mercator 2SP always has lat centered at equator */
+                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
+
+                    dfCenterLat = 0.0;
+
+                    dfCenterLon = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_LON_PROJ_ORIGIN, 0.0 );
+              
+                    dfFalseEasting = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_FALSE_EASTING, 0.0 );
+
+                    dfFalseNorthing = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_FALSE_NORTHING, 0.0 );
+
+                    oSRS.SetMercator2SP( dfStdP1, dfCenterLat, dfCenterLon, 
+                                      dfFalseEasting, dfFalseNorthing );
+                }
+                else {
+                    dfCenterLon = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_LON_PROJ_ORIGIN, 0.0 );
+              
+                    dfCenterLat = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                    dfScale = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_SCALE_FACTOR_ORIGIN,
+                                             1.0 );
+
+                    dfFalseEasting = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_FALSE_EASTING, 0.0 );
+
+                    dfFalseNorthing = 
+                        poDS->FetchCopyParm( szGridMappingValue, 
+                                             CF_PP_FALSE_NORTHING, 0.0 );
+
+                    oSRS.SetMercator( dfCenterLat, dfCenterLon, dfScale, 
+                                      dfFalseEasting, dfFalseNorthing );
+                }                      
+
+                bGotCfSRS = TRUE;
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+
+                CSLDestroy( papszStdParallels );
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Orthographic                                                    */
+/* -------------------------------------------------------------------- */
+		  
+
+            else if ( EQUAL ( pszValue, CF_PT_ORTHOGRAPHIC ) ) {
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+	      
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+
+                bGotCfSRS = TRUE;
+
+                oSRS.SetOrthographic( dfCenterLat, dfCenterLon, 
+                                      dfFalseEasting, dfFalseNorthing );
+
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Polar Stereographic                                             */
+/* -------------------------------------------------------------------- */
+		  
+            else if ( EQUAL ( pszValue, CF_PT_POLAR_STEREO ) ) {
+
+                char **papszStdParallels = NULL;
+
+                dfScale = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_SCALE_FACTOR_ORIGIN, 
+                                         -1.0 );
+                
+                papszStdParallels = 
+                    FetchStandardParallels( szGridMappingValue );
+                
+                /* CF allows the use of standard_parallel (lat_ts) OR scale_factor (k0),
+                   make sure we have standard_parallel, using Snyder eq. 22-7
+                   with k=1 and lat=standard_parallel */
+                if ( papszStdParallels != NULL ) {
+                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                    /* compute scale_factor from standard_parallel */
+                    /* this creates WKT that is inconsistent, don't write for now 
+                       also proj4 does not seem to use this parameter */                    
+                    // dfScale = ( 1.0 + fabs( sin( dfStdP1 * NCDF_PI / 180.0 ) ) ) / 2.0;
+                }
+                else {
+                    if ( ! CPLIsEqual(dfScale,-1.0) ) {
+                        /* compute standard_parallel from scale_factor */
+                        dfStdP1 = asin( 2*dfScale - 1 ) * 180.0 / NCDF_PI;
+
+                        /* fetch latitude_of_projection_origin (+90/-90) 
+                           used here for the sign of standard_parallel */
+                        double dfLatProjOrigin = 
+                            poDS->FetchCopyParm( szGridMappingValue, 
+                                                 CF_PP_LAT_PROJ_ORIGIN, 
+                                                 0.0 );
+                        if ( ! CPLIsEqual(dfLatProjOrigin,90.0)  &&
+                             ! CPLIsEqual(dfLatProjOrigin,-90.0) ) {
+                            CPLError( CE_Failure, CPLE_NotSupported, 
+                                      "Polar Stereographic must have a %s parameter equal to +90 or -90\n.",
+                                      CF_PP_LAT_PROJ_ORIGIN );
+                            dfLatProjOrigin = 90.0;
+                        }
+                        if ( CPLIsEqual(dfLatProjOrigin,-90.0) )
+                            dfStdP1 = - dfStdP1;
+                    }
+                    else {
+                        dfStdP1 = 0.0; //just to avoid warning at compilation
+                        CPLError( CE_Failure, CPLE_NotSupported, 
+                                  "The NetCDF driver does not support import of CF-1 Polar stereographic "
+                                  "without standard_parallel and scale_factor_at_projection_origin parameters.\n" );
+                    }
+                }
+
+                /* set scale to default value 1.0 if it was not set */
+                if ( CPLIsEqual(dfScale,-1.0) )
+                    dfScale = 1.0;
+
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_VERT_LONG_FROM_POLE, 0.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
 
-    const char *pszWKT;
-    const char *pszGeoTransform;
-    char **papszGeoTransform=NULL;
+                bGotCfSRS = TRUE;
+                /* map CF CF_PP_STD_PARALLEL_1 to WKT SRS_PP_LATITUDE_OF_ORIGIN */
+                oSRS.SetPS( dfStdP1, dfCenterLon, dfScale, 
+                            dfFalseEasting, dfFalseNorthing );
 
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
 
-    netCDFDataset * poDS;
-    poDS = this;
+                CSLDestroy( papszStdParallels );
+            }
 
 /* -------------------------------------------------------------------- */
-/*      Get x/y range information.                                      */
+/*      Stereographic                                                   */
 /* -------------------------------------------------------------------- */
+		  
+            else if ( EQUAL ( pszValue, CF_PT_STEREO ) ) {
+	        
+                dfCenterLon = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+	      
+                dfCenterLat = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
 
-    poDS->adfGeoTransform[0] = 0.0;
-    poDS->adfGeoTransform[1] = 1.0;
-    poDS->adfGeoTransform[2] = 0.0;
-    poDS->adfGeoTransform[3] = 0.0;
-    poDS->adfGeoTransform[4] = 0.0;
-    poDS->adfGeoTransform[5] = 1.0;
-    poDS->pszProjection = NULL;
-    
+                dfScale = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_SCALE_FACTOR_ORIGIN,
+                                         1.0 );
+
+                dfFalseEasting = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_EASTING, 0.0 );
+
+                dfFalseNorthing = 
+                    poDS->FetchCopyParm( szGridMappingValue, 
+                                         CF_PP_FALSE_NORTHING, 0.0 );
+
+                bGotCfSRS = TRUE;
+                oSRS.SetStereographic( dfCenterLat, dfCenterLon, dfScale, 
+                                       dfFalseEasting, dfFalseNorthing );
 
+                if( !bGotGeogCS )
+                    oSRS.SetWellKnownGeogCS( "WGS84" );
+            }
+  
 /* -------------------------------------------------------------------- */
-/*      Look for grid_mapping metadata                                  */
+/*      Is this Latitude/Longitude Grid, default                        */
 /* -------------------------------------------------------------------- */
+	    
+        } else if( EQUAL( szDimNameX,"lon" ) ) {
+            oSRS.SetWellKnownGeogCS( "WGS84" );
 
-    strcpy( szGridMappingValue, "" );
-    strcpy( szGridMappingName, "" );
-
-    nc_inq_varname(  cdfid, var, szVarName );
-    strcpy(szTemp,szVarName);
-    strcat(szTemp,"#grid_mapping");
-    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-    if( pszValue ) {
-        strcpy(szGridMappingName,szTemp);
-        strcpy(szGridMappingValue,pszValue);
+        } else {
+            // This would be too indiscrimant.  But we should set
+            // it if we know the data is geographic.
+            //oSRS.SetWellKnownGeogCS( "WGS84" );
+        }
     }
-
 /* -------------------------------------------------------------------- */
-/*      Look for dimension: lon                                         */
+/*      Read projection coordinates                                     */
 /* -------------------------------------------------------------------- */
 
-    memset( szDimNameX, '\0', sizeof( char ) * MAX_NC_NAME );
-    memset( szDimNameY, '\0', sizeof( char ) * MAX_NC_NAME );
+    nc_inq_varid( cdfid, poDS->papszDimName[nXDimID], &nVarDimXID );
+    nc_inq_varid( cdfid, poDS->papszDimName[nYDimID], &nVarDimYID );
+    
+    if( ( nVarDimXID != -1 ) && ( nVarDimYID != -1 ) ) {
+        pdfXCoord = (double *) CPLCalloc( xdim, sizeof(double) );
+        pdfYCoord = (double *) CPLCalloc( ydim, sizeof(double) );
 
-    for( i = 0; (i < strlen( poDS->papszDimName[ poDS->nDimXid ] )  && 
-                 i < 3 ); i++ ) {
-        szDimNameX[i] = tolower( ( poDS->papszDimName[poDS->nDimXid] )[i] );
-    }
-    szDimNameX[3] = '\0';
-    for( i = 0; (i < strlen( poDS->papszDimName[ poDS->nDimYid ] )  && 
-                 i < 3 ); i++ ) {
-        szDimNameY[i] = tolower( ( poDS->papszDimName[poDS->nDimYid] )[i] );
-    }
-    szDimNameY[3] = '\0';
+        start[0] = 0;
+        edge[0]  = xdim;
+        status = nc_get_vara_double( cdfid, nVarDimXID, 
+                                     start, edge, pdfXCoord);
+        
+        edge[0]  = ydim;
+        status = nc_get_vara_double( cdfid, nVarDimYID, 
+                                     start, edge, pdfYCoord);
 
 /* -------------------------------------------------------------------- */
-/*      Read grid_mappinginformation and set projections               */
+/*      Check for bottom-up from the Y-axis order                       */
+/*      see bugs #4284 and #4251                                        */
 /* -------------------------------------------------------------------- */
 
-    if( !( EQUAL(szGridMappingName,"" ) ) ) {
-        nc_inq_varid( cdfid, szGridMappingValue, &nVarProjectionID );
-        poDS->ReadAttributes( cdfid, nVarProjectionID );
-    
-        strcpy( szTemp, szGridMappingValue );
-        strcat( szTemp, "#" );
-        strcat( szTemp, GRD_MAPPING_NAME );
-        pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+        if ( pdfYCoord[0] > pdfYCoord[1] )
+            poDS->bBottomUp = FALSE;
+        else
+            poDS->bBottomUp = TRUE;
 
-        if( pszValue != NULL ) {
+        CPLDebug( "GDAL_netCDF", "set bBottomUp = %d from Y axis", poDS->bBottomUp );
 
 /* -------------------------------------------------------------------- */
-/*      Check for datum/spheroid information                            */
+/*      Is pixel spacing is uniform accross the map?                    */
 /* -------------------------------------------------------------------- */
-            dfEarthRadius = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     EARTH_RADIUS, 
-                                     -1.0 );
 
-            dfLonPrimeMeridian = 
-                poDS->FetchCopyParm( szGridMappingValue,
-                                     LONG_PRIME_MERIDIAN, 
-                                     0.0 );
+/* -------------------------------------------------------------------- */
+/*      Check Longitude                                                 */
+/* -------------------------------------------------------------------- */
 
-            dfInverseFlattening = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     INVERSE_FLATTENING, 
-                                     -1.0 );
-	    
-            dfSemiMajorAxis = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     SEMI_MAJOR_AXIS, 
-                                     -1.0 );
-	    
-            dfSemiMinorAxis = 
-                poDS->FetchCopyParm( szGridMappingValue, 
-                                     SEMI_MINOR_AXIS, 
-                                     -1.0 );
+        nSpacingBegin   = (int) poDS->rint((pdfXCoord[1]-pdfXCoord[0]) * 1000);
+	
+        nSpacingMiddle  = (int) poDS->rint((pdfXCoord[xdim / 2] - 
+                                            pdfXCoord[(xdim / 2) + 1]) * 1000);
+	
+        nSpacingLast    = (int) poDS->rint((pdfXCoord[xdim - 2] - 
+                                            pdfXCoord[xdim-1]) * 1000);
+	
+        if( ( abs( nSpacingBegin )  ==  abs( nSpacingLast )     )  &&
+            ( abs( nSpacingBegin )  ==  abs( nSpacingMiddle )   ) &&
+            ( abs( nSpacingMiddle ) ==  abs( nSpacingLast )     ) ) {
 
-            //see if semi-major exists if radius doesn't
-            if( dfEarthRadius < 0.0 )
-                dfEarthRadius = dfSemiMajorAxis;
+/* -------------------------------------------------------------------- */
+/*      Longitude is equally spaced, check latitude                     */
+/* -------------------------------------------------------------------- */
+            nSpacingBegin   = (int) poDS->rint((pdfYCoord[1]-pdfYCoord[0]) * 
+                                               1000); 
 	    
-            //if still no radius, check old tag
-            if( dfEarthRadius < 0.0 )
-                dfEarthRadius = poDS->FetchCopyParm( szGridMappingValue, 
-                                                     "spherical_earth_radius_meters",
-                                                     -1.0 );
+            nSpacingMiddle  = (int) poDS->rint((pdfYCoord[ydim / 2] - 
+                                                pdfYCoord[(ydim / 2) + 1]) * 
+                                               1000);
 
-            //has radius value
-            if( dfEarthRadius > 0.0 ) {
-                //check for inv_flat tag
-                if( dfInverseFlattening < 0.0 ) {
-                    //no inv_flat tag, check for semi_minor
-                    if( dfSemiMinorAxis < 0.0 ) {
-                        //no way to get inv_flat, use sphere
-                        oSRS.SetGeogCS( "unknown", 
-                                        NULL, 
-                                        "Sphere", 
-                                        dfEarthRadius, 0.0 );
-                        bGotGeogCS = TRUE;
-                    }
-                    else {
-                        if( dfSemiMajorAxis < 0.0 )
-                            dfSemiMajorAxis = dfEarthRadius;
-                        //set inv_flat using semi_minor/major
-                        dfInverseFlattening = 
-                            1.0 / ( dfSemiMajorAxis - dfSemiMinorAxis ) / dfSemiMajorAxis;
-                        oSRS.SetGeogCS( "unknown", 
-                                        NULL, 
-                                        "Spheroid", 
-                                        dfEarthRadius, dfInverseFlattening );
-                        bGotGeogCS = TRUE;
-                    }
-                }
-                else {
-                    oSRS.SetGeogCS( "unknown", 
-                                    NULL, 
-                                    "Spheroid", 
-                                    dfEarthRadius, dfInverseFlattening );
-                    bGotGeogCS = TRUE;
-                }
-            }
-            //no radius, set as wgs84 as default?
-            else {
-                // This would be too indiscrimant.  But we should set
-                // it if we know the data is geographic.
-                //oSRS.SetWellKnownGeogCS( "WGS84" );
-            }
-	    		
+            nSpacingLast    = (int) poDS->rint((pdfYCoord[ydim - 2] - 
+                                                pdfYCoord[ydim-1]) * 
+                                               1000);
+
+		    
 /* -------------------------------------------------------------------- */
-/*      Transverse Mercator                                             */
+/*   For Latitude  we allow an error of 0.1 degrees for gaussian        */
+/*   gridding                                                           */
 /* -------------------------------------------------------------------- */
 
-            if( EQUAL( pszValue, TM ) ) {
+            if((( abs( abs(nSpacingBegin) - abs(nSpacingLast) ) )   < 100 ) &&
+               (( abs( abs(nSpacingBegin) -  abs(nSpacingMiddle) ) ) < 100 ) &&
+               (( abs( abs(nSpacingMiddle) - abs(nSpacingLast) ) )   < 100) ) {
 
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         SCALE_FACTOR_ORIGIN, 1.0 );
+                if( ( abs( nSpacingBegin )  !=  abs( nSpacingLast )     )  ||
+                    ( abs( nSpacingBegin )  !=  abs( nSpacingMiddle )   ) ||
+                    ( abs( nSpacingMiddle ) !=  abs( nSpacingLast )     ) ) {
+		    
+                    CPLError(CE_Warning, 1,"Latitude grid not spaced evenly.\nSeting projection for grid spacing is within 0.1 degrees threshold.\n");
 
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LONG_CENTRAL_MERIDIAN, 0.0 );
+                }
+/* -------------------------------------------------------------------- */
+/*      We have gridded data s we can set the Gereferencing info.       */
+/* -------------------------------------------------------------------- */
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
+/* -------------------------------------------------------------------- */
+/*      Enable GeoTransform                                             */
+/* -------------------------------------------------------------------- */
+                /* ----------------------------------------------------------*/
+                /*    In the following "actual_range" and "node_offset"      */
+                /*    are attributes used by netCDF files created by GMT.    */
+                /*    If we find them we know how to proceed. Else, use      */
+                /*    the original algorithm.                                */
+                /* --------------------------------------------------------- */
+                double	dummy[2], xMinMax[2], yMinMax[2];
+                int	node_offset = 0;
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+                bGotCfGT = TRUE;
+                
+                nc_get_att_int (cdfid, NC_GLOBAL, "node_offset", &node_offset);
+                
+                if (!nc_get_att_double (cdfid, nVarDimXID, "actual_range", dummy)) {
+                    xMinMax[0] = dummy[0];		
+                    xMinMax[1] = dummy[1];
+                }
+                else {
+                    xMinMax[0] = pdfXCoord[0];
+                    xMinMax[1] = pdfXCoord[xdim-1];
+                    node_offset = 0;
+                }
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
+                if (!nc_get_att_double (cdfid, nVarDimYID, "actual_range", dummy)) {
+                    yMinMax[0] = dummy[0];		
+                    yMinMax[1] = dummy[1];
+                }
+                else {
+                    yMinMax[0] = pdfYCoord[0];	
+                    yMinMax[1] = pdfYCoord[ydim-1];
+                    node_offset = 0;
+                }
 
-                oSRS.SetTM( dfCenterLat, 
-                            dfCenterLon,
-                            dfScale,
-                            dfFalseEasting,
-                            dfFalseNorthing );
+                /* Check for reverse order of y-coordinate */
+                if ( yMinMax[0] > yMinMax[1] ) {
+                    dummy[0] = yMinMax[1];
+                    dummy[1] = yMinMax[0];
+                    yMinMax[0] = dummy[0];
+                    yMinMax[1] = dummy[1];
+                }
+                
+                adfTempGeoTransform[0] = xMinMax[0];
+                adfTempGeoTransform[2] = 0;
+                adfTempGeoTransform[3] = yMinMax[1];
+                adfTempGeoTransform[4] = 0;
+                adfTempGeoTransform[1] = ( xMinMax[1] - xMinMax[0] ) / 
+                    ( poDS->nRasterXSize + (node_offset - 1) );
+                adfTempGeoTransform[5] = ( yMinMax[0] - yMinMax[1] ) / 
+                    ( poDS->nRasterYSize + (node_offset - 1) );
+
+/* -------------------------------------------------------------------- */
+/*     Compute the center of the pixel                                  */
+/* -------------------------------------------------------------------- */
+                if ( !node_offset ) {	// Otherwise its already the pixel center
+                    adfTempGeoTransform[0] -= (adfTempGeoTransform[1] / 2);
+                    adfTempGeoTransform[3] -= (adfTempGeoTransform[5] / 2);
+                }
+            }// end if (Latitude is equally spaced, within 0.1 degrees)
+            else {
+                CPLDebug( "GDAL_netCDF", 
+                          "Latitude is not equally spaced." );
+            }
+        }// end if (Longitude is equally spaced)
+        else {
+            CPLDebug( "GDAL_netCDF", 
+                      "Longitude is not equally spaced." );
+        }
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+        CPLFree( pdfXCoord );
+        CPLFree( pdfYCoord );
+    }// end if (has dims)
+
+/* -------------------------------------------------------------------- */
+/*     Set Projection from CF                                           */
+/* -------------------------------------------------------------------- */
+    if ( bGotGeogCS || bGotCfSRS ) {
+        /* Set SRS Units */
+
+        /* check units for x and y */
+        if( oSRS.IsProjected( ) ) {
+            const char *pszUnitsX = NULL;
+            const char *pszUnitsY = NULL;
+
+            strcpy( szTemp, "x" );
+            strcat( szTemp, "#units" );
+            pszValue = CSLFetchNameValue( poDS->papszMetadata, 
+                                          szTemp );
+            if( pszValue != NULL ) 
+                pszUnitsX = pszValue;
+
+            strcpy( szTemp, "y" );
+            strcat( szTemp, "#units" );
+            pszValue = CSLFetchNameValue( poDS->papszMetadata, 
+                                          szTemp );
+            if( pszValue != NULL )
+                pszUnitsY = pszValue;
+
+            /* TODO: what to do if units are not equal in X and Y */
+            if ( (pszUnitsX != NULL) && (pszUnitsY != NULL) && 
+                 EQUAL(pszUnitsX,pszUnitsY) )
+                pszUnits = pszUnitsX;
+
+            /* add units to PROJCS */
+            if ( pszUnits != NULL && ! EQUAL(pszUnits,"") ) {
+                if ( EQUAL(pszUnits,"m") ) {
+                    oSRS.SetLinearUnits( CF_UNITS_M, 1.0 );
+                    oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", 9001 );
+                }
+                else if ( EQUAL(pszUnits,"km") ) {
+                    oSRS.SetLinearUnits( CF_UNITS_M, 1000.0 );
+                    oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", 9001 );
+                }
+                /* TODO check for other values */
+                // else 
+                //     oSRS.SetLinearUnits(pszUnits, 1.0);
             }
+        }
+        else if ( oSRS.IsGeographic() ) {
+            oSRS.SetAngularUnits( CF_UNITS_D, CPLAtof(SRS_UA_DEGREE_CONV) );
+            oSRS.SetAuthority( "GEOGCS|UNIT", "EPSG", 9122 );
+        }
+        
+        /* Set Projection */
+        oSRS.exportToWkt( &(pszTempProjection) );
+        CPLDebug( "GDAL_netCDF", "setting WKT from CF" );
+        SetProjection( pszTempProjection );
+        CPLFree( pszTempProjection );
+
+        if ( !bGotCfGT )
+            CPLDebug( "GDAL_netCDF", "got SRS but no geotransform from CF!");
+    }
 
 /* -------------------------------------------------------------------- */
-/*      Albers Equal Area                                               */
+/*      Process custom GDAL values (spatial_ref, GeoTransform)          */
 /* -------------------------------------------------------------------- */
-
-            if( EQUAL( pszValue, AEA ) ) {
-                char **papszStdParallels = NULL;
-		
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LONG_CENTRAL_MERIDIAN, 0.0 );
-
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
-
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         SCALE_FACTOR, 1.0 );
-
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
-
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
-		
-                papszStdParallels = 
-                    FetchStandardParallels( szGridMappingValue );
-
-                if( papszStdParallels != NULL ) {
-		  
-                    if ( CSLCount( papszStdParallels ) == 1 ) {
-                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                        dfStdP2 = dfStdP1;
-                    }
-		
-                    else if( CSLCount( papszStdParallels ) == 2 ) {
-                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                        dfStdP2 = CPLAtofM( papszStdParallels[1] );
-                    }
+    if( !EQUAL( szGridMappingValue, "" )  ) {
+        
+        if( pszWKT != NULL ) {
+            
+/* -------------------------------------------------------------------- */
+/*      Compare SRS obtained from CF attributes and GDAL WKT            */
+/*      If possible use the more complete GDAL WKT                      */
+/* -------------------------------------------------------------------- */
+            /* Set the SRS to the one written by GDAL */
+            if ( ! bGotCfSRS || poDS->pszProjection == NULL || ! bIsGdalCfFile ) {   
+                bGotGdalSRS = TRUE;
+                CPLDebug( "GDAL_netCDF", "setting WKT from GDAL" );
+                SetProjection( pszWKT );
+            }
+            else { /* use the SRS from GDAL if it doesn't conflict with the one from CF */
+                char *pszProjectionGDAL = (char*) pszWKT ;
+                OGRSpatialReference oSRSGDAL;
+                oSRSGDAL.importFromWkt( &pszProjectionGDAL );
+                /* set datum to unknown or else datums will not match, see bug #4281 */
+                if ( oSRSGDAL.GetAttrNode( "DATUM" ) )
+                    oSRSGDAL.GetAttrNode( "DATUM" )->GetChild(0)->SetValue( "unknown" );
+                /* need this for setprojection autotest */ 
+                if ( oSRSGDAL.GetAttrNode( "PROJCS" ) )
+                    oSRSGDAL.GetAttrNode( "PROJCS" )->GetChild(0)->SetValue( "unnamed" );
+                if ( oSRSGDAL.GetAttrNode( "GEOGCS" ) )
+                    oSRSGDAL.GetAttrNode( "GEOGCS" )->GetChild(0)->SetValue( "unknown" );   
+                oSRSGDAL.GetRoot()->StripNodes( "UNIT" );
+                if ( oSRS.IsSame(&oSRSGDAL) ) {
+                    // printf("ARE SAME, using GDAL WKT\n");
+                    bGotGdalSRS = TRUE;
+                    CPLDebug( "GDAL_netCDF", "setting WKT from GDAL" );
+                    SetProjection( pszWKT );
                 }
-                //old default
                 else {
-                    dfStdP1 = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
-                                             STD_PARALLEL_1, 0.0 );
-
-                    dfStdP2 = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
-                                             STD_PARALLEL_2, 0.0 );
+                    CPLDebug( "GDAL_netCDF", 
+                              "got WKT from GDAL \n[%s]\nbut not using it because conflicts with CF\n[%s]\n", 
+                              pszWKT, poDS->pszProjection );
                 }
-                oSRS.SetACEA( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
-                              dfFalseEasting, dfFalseNorthing );
-
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-
-                CSLDestroy( papszStdParallels );
             }
 
 /* -------------------------------------------------------------------- */
-/*      Cylindrical Equal Area                                          */
+/*      Look for GeoTransform Array, if not found in CF                 */
 /* -------------------------------------------------------------------- */
+            if ( !bGotCfGT ) {
 
-            else if( EQUAL( pszValue, CEA ) || EQUAL( pszValue, LCEA ) ) {
-                dfStdP1 = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         STD_PARALLEL_1, 0.0 );
-                dfCentralMeridian = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LONG_CENTRAL_MERIDIAN, 0.0 );
-
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
-
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
-		
-                oSRS.SetCEA( dfStdP1, dfCentralMeridian,
-                             dfFalseEasting, dfFalseNorthing );
+                /* TODO read the GT values and detect for conflict with CF */
+                /* this could resolve the GT precision loss issue  */
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-		
-            }
+                if( pszGeoTransform != NULL ) {
 
+                    bGotGdalGT = TRUE;
+                    
+                    papszGeoTransform = CSLTokenizeString2( pszGeoTransform,
+                                                            " ", 
+                                                            CSLT_HONOURSTRINGS );
+                    adfTempGeoTransform[0] = atof( papszGeoTransform[0] );
+                    adfTempGeoTransform[1] = atof( papszGeoTransform[1] );
+                    adfTempGeoTransform[2] = atof( papszGeoTransform[2] );
+                    adfTempGeoTransform[3] = atof( papszGeoTransform[3] );
+                    adfTempGeoTransform[4] = atof( papszGeoTransform[4] );
+                    adfTempGeoTransform[5] = atof( papszGeoTransform[5] );
+                    
 /* -------------------------------------------------------------------- */
-/*      lambert_azimuthal_equal_area                                    */
+/*      Look for corner array values                                    */
 /* -------------------------------------------------------------------- */
-            else if( EQUAL( pszValue, LAEA ) ) {
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LON_PROJ_ORIGIN, 0.0 );
+                } else {
+                    double dfNN=0.0, dfSN=0.0, dfEE=0.0, dfWE=0.0;
+                    int bGotNN=FALSE, bGotSN=FALSE, bGotEE=FALSE, bGotWE=FALSE;
+                    // CPLDebug( "GDAL_netCDF", "looking for geotransform corners\n" );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
+                    strcpy(szTemp,szGridMappingValue);
+                    strcat( szTemp, "#" );
+                    strcat( szTemp, "Northernmost_Northing");
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+                    if( pszValue != NULL ) {
+                        dfNN = atof( pszValue );
+                        bGotNN = TRUE;
+                    }
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+                    strcpy(szTemp,szGridMappingValue);
+                    strcat( szTemp, "#" );
+                    strcat( szTemp, "Southernmost_Northing");
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+                    if( pszValue != NULL ) {
+                        dfSN = atof( pszValue );
+                        bGotSN = TRUE;
+                    }
+                    
+                    strcpy(szTemp,szGridMappingValue);
+                    strcat( szTemp, "#" );
+                    strcat( szTemp, "Easternmost_Easting");
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+                    if( pszValue != NULL ) {
+                        dfEE = atof( pszValue );
+                        bGotEE = TRUE;
+                    }
+                    
+                    strcpy(szTemp,szGridMappingValue);
+                    strcat( szTemp, "#" );
+                    strcat( szTemp, "Westernmost_Easting");
+                    pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);                    
+                    if( pszValue != NULL ) {
+                        dfWE = atof( pszValue ); 
+                        bGotWE = TRUE;
+                    }
+                    
+                    /* Only set the GeoTransform if we got all the values */
+                    if (  bGotNN && bGotSN && bGotEE && bGotWE ) {
+
+                        bGotGdalGT = TRUE;
+
+                        adfTempGeoTransform[0] = dfWE;
+                        adfTempGeoTransform[1] = (dfEE - dfWE) / 
+                            ( poDS->GetRasterXSize() - 1 );
+                        adfTempGeoTransform[2] = 0.0;
+                        adfTempGeoTransform[3] = dfNN;
+                        adfTempGeoTransform[4] = 0.0;
+                        adfTempGeoTransform[5] = (dfSN - dfNN) / 
+                            ( poDS->GetRasterYSize() - 1 );
+                        /* compute the center of the pixel */
+                        adfTempGeoTransform[0] = dfWE
+                            - (adfTempGeoTransform[1] / 2);                        
+                        adfTempGeoTransform[3] = dfNN
+                            - (adfTempGeoTransform[5] / 2);
+                    }
+                } // (pszGeoTransform != NULL)
+                CSLDestroy( papszGeoTransform );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
+                if ( bGotGdalSRS && ! bGotGdalGT )
+                    CPLDebug( "GDAL_netCDF", "got SRS but not geotransform from GDAL!");
 
-                /*
-                  dfLonOrig =
-                  poDS->FetchCopyParm( szGridMappingValue, 
-                  LON_PROJ_ORIGIN, 0.0 );
+            } // if ( !bGotCfGT )
 
-                  dfLatOrig =
-                  poDS->FetchCopyParm( szGridMappingValue, 
-                  LAT_PROJ_ORIGIN, 0.0 );
+        }
+    }
 
-                  dfScaleFactorOrig = 
-                  poDS->FetchCopyParm( szGridMappingValue,
-                  SCALE_FACTOR_ORIGN, 0.0 );
+    /* Set GeoTransform if we got a complete one - after projection has been set */
+    if ( bGotCfGT || bGotGdalGT ) {
+        SetGeoTransform( adfTempGeoTransform );
+    }
+  
+    /* debuging reports */
+    CPLDebug( "GDAL_netCDF", 
+              "bGotGeogCS=%d bGotCfSRS=%d bGotCfGT=%d bGotGdalSRS=%d bGotGdalGT=%d",
+              bGotGeogCS, bGotCfSRS, bGotCfGT, bGotGdalSRS, bGotGdalGT );
+
+    if ( !bGotCfGT && !bGotGdalGT )
+        CPLDebug( "GDAL_netCDF", "did not get geotransform from CF nor GDAL!");      
+
+    if ( !bGotGeogCS && !bGotCfSRS && !bGotGdalSRS && !bGotCfGT)
+        CPLDebug( "GDAL_netCDF",  "did not get projection from CF nor GDAL!");   
+
+/* -------------------------------------------------------------------- */
+/*     Search for Well-known GeogCS if got only CF WKT                  */
+/*     Disabled for now, as a named datum also include control points   */
+/*     (see mailing list and bug#4281                                   */
+/*     For example, WGS84 vs. GDA94 (EPSG:3577) - AEA in netcdf_cf.py   */
+/* -------------------------------------------------------------------- */
+    /* disabled for now, but could be set in a config option */
+    bLookForWellKnownGCS = FALSE; 
+    if ( bLookForWellKnownGCS && bGotCfSRS && ! bGotGdalSRS ) {
+        /* ET - could use a more exhaustive method by scanning all EPSG codes in data/gcs.csv */
+        /* as proposed by Even in the gdal-dev mailing list "help for comparing two WKT" */
+        /* this code could be contributed to a new function */
+        /* OGRSpatialReference * OGRSpatialReference::FindMatchingGeogCS( const OGRSpatialReference *poOther ) */ 
+        CPLDebug( "GDAL_netCDF", "Searching for Well-known GeogCS" );
+        const char *pszWKGCSList[] = { "WGS84", "WGS72", "NAD27", "NAD83" };
+        char *pszWKGCS = NULL;
+        oSRS.exportToPrettyWkt( &pszWKGCS );
+        for( size_t i=0; i<sizeof(pszWKGCSList)/8; i++ ) {
+            pszWKGCS = CPLStrdup( pszWKGCSList[i] );
+            OGRSpatialReference oSRSTmp;
+            oSRSTmp.SetWellKnownGeogCS( pszWKGCSList[i] );
+            /* set datum to unknown, bug #4281 */
+            if ( oSRSTmp.GetAttrNode( "DATUM" ) )
+                oSRSTmp.GetAttrNode( "DATUM" )->GetChild(0)->SetValue( "unknown" );
+            /* could use  OGRSpatialReference::StripCTParms() but let's keep TOWGS84 */
+            oSRSTmp.GetRoot()->StripNodes( "AXIS" );
+            oSRSTmp.GetRoot()->StripNodes( "AUTHORITY" );
+            oSRSTmp.GetRoot()->StripNodes( "EXTENSION" );
+
+            oSRSTmp.exportToPrettyWkt( &pszWKGCS );
+            if ( oSRS.IsSameGeogCS(&oSRSTmp) ) {
+                oSRS.SetWellKnownGeogCS( pszWKGCSList[i] );
+                oSRS.exportToWkt( &(pszTempProjection) );
+                SetProjection( pszTempProjection );
+                CPLFree( pszTempProjection );
+            }
+        }
+    }
 
-                  dfProjXOrig =
-                  poDS->FetchCopyParm( szGridMappingValue,
-                  PROJ_X_ORIGIN, 0.0 );
 
-                  dfProjYOrig =
-                  poDS->FetchCopyParm( szGridMappingValue,
-                  PROJ_Y_ORIGIN, 0.0 );
+}
 
-                  dfFalseEasting = 
-                  poDS->FetchCopyParm( szGridMappingValue, 
-                  FALSE_EASTING, 0.0 );
+/************************************************************************/
+/*                          SetProjection()                           */
+/************************************************************************/
+CPLErr 	netCDFDataset::SetProjection( const char * pszNewProjection )
+{
+/* TODO look if proj. already defined, like in geotiff */
+    if( pszNewProjection == NULL ) 
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "NULL projection." );
+        return CE_Failure;
+    }
 
-                  dfFalseNorthing = 
-                  poDS->FetchCopyParm( szGridMappingValue, 
-                  FALSE_NORTHING, 0.0 );
-                */
-                oSRS.SetProjCS( "LAEA (WGS84) " );
-		
-                oSRS.SetLAEA( dfCenterLat, dfCenterLon,
-                              dfFalseEasting, dfFalseNorthing );
+    if( bSetProjection && (GetAccess() == GA_Update) ) 
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "netCDFDataset::SetProjection() should only be called once "
+                  "in update mode!\npszNewProjection=\n%s",
+                  pszNewProjection );
+    }
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-		
-            }
+    CPLDebug( "GDAL_netCDF", "SetProjection, WKT = %s", pszNewProjection );
 
-/* -------------------------------------------------------------------- */
-/*      Azimuthal Equidistant                                           */
-/* -------------------------------------------------------------------- */
-            else if( EQUAL( pszValue, AE ) ) {
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LON_PROJ_ORIGIN, 0.0 );
+    if( !EQUALN(pszNewProjection,"GEOGCS",6)
+        && !EQUALN(pszNewProjection,"PROJCS",6)
+        && !EQUAL(pszNewProjection,"") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Only OGC WKT GEOGCS and PROJCS Projections supported for writing to NetCDF.\n"
+                  "%s not supported.",
+                  pszNewProjection );
+        
+        return CE_Failure;
+    }
+        
+    CPLFree( pszProjection );
+    pszProjection = CPLStrdup( pszNewProjection );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
+    if( GetAccess() == GA_Update )
+    {
+        if ( bSetGeoTransform && ! bSetProjection ) {
+            bSetProjection = TRUE;
+            return AddProjectionVars();
+        }
+    }
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+    bSetProjection = TRUE;
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
+    return CE_None;
 
-                oSRS.SetAE( dfCenterLat, dfCenterLon,
-                            dfFalseEasting, dfFalseNorthing );
+}
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-		
-            }
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
 
-/* -------------------------------------------------------------------- */
-/*      Lambert conformal conic                                         */
-/* -------------------------------------------------------------------- */
-            else if( EQUAL( pszValue, L_C_CONIC ) ) {
-		
-                char **papszStdParallels = NULL;
-		
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LONG_CENTRAL_MERIDIAN, 0.0 );
+CPLErr 	netCDFDataset::SetGeoTransform ( double * padfTransform )
+{
+    memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
+    // bGeoTransformValid = TRUE;
+    // bGeoTIFFInfoChanged = TRUE;
+    
+    CPLDebug( "GDAL_netCDF", 
+              "SetGeoTransform(%f,%f,%f,%f,%f,%f)",
+              padfTransform[0],padfTransform[1],padfTransform[2],
+              padfTransform[3],padfTransform[4],padfTransform[5]);
+    
+    if( GetAccess() == GA_Update )
+    {
+        if ( bSetProjection && ! bSetGeoTransform ) {
+            bSetGeoTransform = TRUE;
+            return AddProjectionVars();
+        }
+    }
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
+    bSetGeoTransform = TRUE;
 
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         SCALE_FACTOR, 1.0 );
+    return CE_None;
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+}
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
-		
-                papszStdParallels = 
-                    FetchStandardParallels( szGridMappingValue );
+/************************************************************************/
+/*                          AddProjectionVars()                         */
+/************************************************************************/
 
-                if( papszStdParallels != NULL ) {
-		  
-                    if ( CSLCount( papszStdParallels ) == 1 ) {
-                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                        dfStdP2 = dfStdP1;
-                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale, 
-                                        dfFalseEasting, dfFalseNorthing );
-                    }
-		
-                    else if( CSLCount( papszStdParallels ) == 2 ) {
-                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                        dfStdP2 = CPLAtofM( papszStdParallels[1] );
-                        oSRS.SetLCC( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
-                                     dfFalseEasting, dfFalseNorthing );
-                    }
-                }
-                //old default
-                else {
-                    dfStdP1 = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
-                                             STD_PARALLEL_1, 0.0 );
+CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress, 
+                                         void * pProgressData )
+{
+    OGRSpatialReference oSRS;
+    int NCDFVarID = -1;
+    double dfTemp = 0.0;
+    const char  *pszValue = NULL;
+    char       szTemp[ NCDF_MAX_STR_LEN ];
 
-                    dfStdP2 = 
-                        poDS->FetchCopyParm( szGridMappingValue, 
-                                             STD_PARALLEL_2, 0.0 );
+    char   szGeoTransform[ NCDF_MAX_STR_LEN ];
+    *szGeoTransform = '\0';
+    char *pszWKT = NULL;    
+    const char *pszUnits = NULL;
+    char   szUnits[ NCDF_MAX_STR_LEN ];    
+    szUnits[0]='\0';
 
-                    oSRS.SetLCC( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
-                                 dfFalseEasting, dfFalseNorthing );
-                }				
+    int  bWriteGridMapping = FALSE;
+    int  bWriteLonLat = FALSE;
+    int  bWriteGDALTags = FALSE;
+    int  bWriteGeoTransform = FALSE;
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+    nc_type eLonLatType = NC_NAT;
+    int nVarLonID=-1, nVarLatID=-1;
+    int nVarXID=-1, nVarYID=-1;
 
-                CSLDestroy( papszStdParallels );
-            }
-		
-/* -------------------------------------------------------------------- */
-/*      Is this Latitude/Longitude Grid explicitly                      */
-/* -------------------------------------------------------------------- */
-	    
-            else if ( EQUAL ( pszValue, LATITUDE_LONGITUDE ) ) {
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-            }
-/* -------------------------------------------------------------------- */
-/*      Mercator                                                        */
-/* -------------------------------------------------------------------- */
-		  
-            else if ( EQUAL ( pszValue, MERCATOR ) ) {
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LON_PROJ_ORIGIN, 0.0 );
-	      
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
+    char szNetcdfProjection[ NC_MAX_NAME ];
+    szNetcdfProjection[0]='\0';
 
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         SCALE_FACTOR_ORIGIN,
-                                         1.0 );
+    bAddedProjectionVars = TRUE;
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+    pszWKT = (char *) pszProjection;
+    oSRS.importFromWkt( &pszWKT );
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
+    if( oSRS.IsProjected() )
+        bIsProjected = TRUE;
+    else if( oSRS.IsGeographic() )
+        bIsGeographic = TRUE;
 
-                oSRS.SetMercator( dfCenterLat, dfCenterLon, dfScale, 
-                                  dfFalseEasting, dfFalseNorthing );
+    CPLDebug( "GDAL_netCDF", "SetProjection, WKT now = [%s]\nprojected: %d geographic: %d", 
+              pszProjection,bIsProjected,bIsGeographic );
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-            }
+    if ( ! bSetGeoTransform )
+        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
+                  "but GeoTransform has not yet been defined!" );
 
-/* -------------------------------------------------------------------- */
-/*      Orthographic                                                    */
-/* -------------------------------------------------------------------- */
-		  
-            else if ( EQUAL ( pszValue, ORTHOGRAPHIC ) ) {
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LON_PROJ_ORIGIN, 0.0 );
-	      
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
+    if ( ! bSetProjection )
+        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
+                  "but Projection has not yet been defined!" );
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+    /* process projection options */
+    if( bIsProjected ) 
+    {
+        int bIsCfProjection = NCDFIsCfProjection( oSRS.GetAttrValue( "PROJECTION" ) );
+        bWriteGridMapping = TRUE;
+        bWriteGDALTags = CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", TRUE );
+        /* force WRITE_GDAL_TAGS if is not a CF projection */
+        if ( ! bWriteGDALTags && ! bIsCfProjection )
+            bWriteGDALTags = TRUE;
+        if ( bWriteGDALTags ) 
+            bWriteGeoTransform = TRUE;
+
+        pszValue = CSLFetchNameValueDef(papszCreationOptions,"WRITE_LONLAT", "NO");
+        if ( EQUAL( pszValue, "IF_NEEDED" ) ) {
+            if  ( bIsCfProjection )
+                bWriteLonLat = FALSE;
+            else 
+                bWriteLonLat = TRUE;
+        }
+        else bWriteLonLat = CSLTestBoolean( pszValue );
+
+        eLonLatType = NC_FLOAT;
+        pszValue =  CSLFetchNameValueDef(papszCreationOptions,"TYPE_LONLAT", "FLOAT");
+        if ( EQUAL(pszValue, "DOUBLE" ) ) 
+            eLonLatType = NC_DOUBLE;
+    }
+    else 
+    { 
+        /* files without a Datum will not have a grid_mapping variable and geographic information */
+        if ( bIsGeographic )  bWriteGridMapping = TRUE;
+        else  bWriteGridMapping = FALSE;
+        bWriteGDALTags = CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", bWriteGridMapping );        
+        if ( bWriteGDALTags ) 
+            bWriteGeoTransform = TRUE;
+
+        pszValue =  CSLFetchNameValueDef(papszCreationOptions,"WRITE_LONLAT", "YES");
+        if ( EQUAL( pszValue, "IF_NEEDED" ) )  
+            bWriteLonLat = TRUE;
+        else bWriteLonLat = CSLTestBoolean( pszValue );
+        /*  Don't write lon/lat if no source geotransform */
+        if ( ! bSetGeoTransform )
+            bWriteLonLat = FALSE;
+        /* If we don't write lon/lat, set dimnames to X/Y and write gdal tags*/
+        if ( ! bWriteLonLat ) {
+            CPLError( CE_Warning, CPLE_AppDefined, 
+                      "creating geographic file without lon/lat values!");
+            if ( bSetGeoTransform ) {
+                bWriteGDALTags = TRUE; //not desireable if no geotransform
+                bWriteGeoTransform = TRUE;
+            }
+        }
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
+        eLonLatType = NC_DOUBLE;
+        pszValue =  CSLFetchNameValueDef(papszCreationOptions,"TYPE_LONLAT", "DOUBLE");
+        if ( EQUAL(pszValue, "FLOAT" ) ) 
+            eLonLatType = NC_FLOAT;
+    }
+    
+    /* make sure we write grid_mapping if we need to write GDAL tags */
+    if ( bWriteGDALTags ) bWriteGridMapping = TRUE;
 
-                oSRS.SetOrthographic( dfCenterLat, dfCenterLon, 
-                                      dfFalseEasting, dfFalseNorthing );
+    /* bottom-up value: new driver is bottom-up by default */
+    /* override with WRITE_BOTTOMUP */
+    bBottomUp = CSLFetchBoolean( papszCreationOptions, "WRITE_BOTTOMUP", TRUE );       
+    
+    CPLDebug( "GDAL_netCDF", 
+              "bIsProjected=%d bIsGeographic=%d bWriteGridMapping=%d bWriteGDALTags=%d bWriteLonLat=%d bBottomUp=%d",
+              bIsProjected,bIsGeographic,bWriteGridMapping,bWriteGDALTags,bWriteLonLat,bBottomUp );
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-            }
+    /* exit if nothing to do */
+    if ( !bIsProjected && !bWriteLonLat )
+        return CE_None;
 
 /* -------------------------------------------------------------------- */
-/*      Polar Stereographic                                             */
+/*      Define dimension names                                          */
 /* -------------------------------------------------------------------- */
-		  
-            else if ( EQUAL ( pszValue, POLAR_STEREO ) ) {
+    /* make sure we are in define mode */
+    SetDefineMode( TRUE );
 
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LON_PROJ_ORIGIN, 0.0 );
 
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
-		
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         SCALE_FACTOR_ORIGIN, 
-                                         1.0 );
+/* -------------------------------------------------------------------- */
+/*      Rename dimensions if lon/lat                                    */
+/* -------------------------------------------------------------------- */
+    if( ! bIsProjected ) 
+    {
+        /* rename dims to lat/lon */
+        papszDimName.Clear(); //if we add other dims one day, this has to change
+        papszDimName.AddString( NCDF_DIMNAME_LAT );
+        papszDimName.AddString( NCDF_DIMNAME_LON );
+
+        status = nc_rename_dim(cdfid, nYDimID, NCDF_DIMNAME_LAT );
+        NCDF_ERR(status);
+        status = nc_rename_dim(cdfid, nXDimID, NCDF_DIMNAME_LON );
+        NCDF_ERR(status);
+    }
 
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+/* -------------------------------------------------------------------- */
+/*      Write projection attributes                                     */
+/* -------------------------------------------------------------------- */
+    if( bWriteGridMapping == TRUE ) 
+    {
+    
+        if( bIsProjected ) 
+        {
+/* -------------------------------------------------------------------- */
+/*      Write CF-1.5 compliant Projected attributes                     */
+/* -------------------------------------------------------------------- */
+ 
+            const OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
+            const char  *pszProjName;
+            pszProjName = oSRS.GetAttrValue( "PROJECTION" );
+
+            /* Basic Projection info (grid_mapping and datum) */
+            for( int i=0; poNetcdfSRS_PT[i].WKT_SRS != NULL; i++ ) {
+                if( EQUAL( poNetcdfSRS_PT[i].WKT_SRS, pszProjName ) ) {
+                    CPLDebug( "GDAL_netCDF", "GDAL PROJECTION = %s , NCDF PROJECTION = %s", 
+                              poNetcdfSRS_PT[i].WKT_SRS, 
+                              poNetcdfSRS_PT[i].CF_SRS);
+                    strcpy( szNetcdfProjection, poNetcdfSRS_PT[i].CF_SRS );
+                    CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                              cdfid, poNetcdfSRS_PT[i].CF_SRS, NC_CHAR ); 
+                    status = nc_def_var( cdfid, 
+                                         poNetcdfSRS_PT[i].CF_SRS,
+                                         NC_CHAR, 
+                                         0, NULL, &NCDFVarID );
+                    NCDF_ERR(status);
+                    break;
+                }
+            }
+            nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
+                             strlen( szNetcdfProjection ),
+                             szNetcdfProjection );
+            
+            /* Various projection attributes */
+            // PDS: keep in synch with SetProjection function
+            NCDFWriteProjAttribs(poPROJCS, pszProjName, cdfid, NCDFVarID);
+            
+        }
+        else 
+        {
+/* -------------------------------------------------------------------- */
+/*      Write CF-1.5 compliant Geographics attributes                   */
+/*      Note: WKT information will not be preserved (e.g. WGS84)        */
+/* -------------------------------------------------------------------- */
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
+            strcpy( szNetcdfProjection, "crs" );
+            CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                      cdfid, szNetcdfProjection, NC_CHAR );
+            nc_def_var( cdfid, szNetcdfProjection, NC_CHAR, 
+                        0, NULL, &NCDFVarID );
+            NCDF_ERR(status);
+            nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
+                             strlen(CF_PT_LATITUDE_LONGITUDE),
+                             CF_PT_LATITUDE_LONGITUDE );
+        }
+        
+/* -------------------------------------------------------------------- */
+/*      Write CF-1.5 compliant common attributes                        */
+/* -------------------------------------------------------------------- */
 
-                oSRS.SetPS( dfCenterLat, dfCenterLon, dfScale, 
-                            dfFalseEasting, dfFalseNorthing );
+        /* DATUM information */
+        dfTemp = oSRS.GetPrimeMeridian();
+        nc_put_att_double( cdfid, NCDFVarID, CF_PP_LONG_PRIME_MERIDIAN,
+                           NC_DOUBLE, 1, &dfTemp );
+        dfTemp = oSRS.GetSemiMajor();
+        nc_put_att_double( cdfid, NCDFVarID, CF_PP_SEMI_MAJOR_AXIS,
+                           NC_DOUBLE, 1, &dfTemp );
+        dfTemp = oSRS.GetInvFlattening();
+        nc_put_att_double( cdfid, NCDFVarID, CF_PP_INVERSE_FLATTENING,
+                           NC_DOUBLE, 1, &dfTemp );
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+        /*  Optional GDAL custom projection tags */
+        if ( bWriteGDALTags == TRUE ) {
+            
+            *szGeoTransform = '\0';
+            for( int i=0; i<6; i++ ) {
+                sprintf( szTemp, "%.16g ",
+                         adfGeoTransform[i] );
+                strcat( szGeoTransform, szTemp );
+            }
+            CPLDebug( "GDAL_netCDF", "szGeoTranform = %s", szGeoTransform );
+            
+            // if ( strlen(pszProj4Defn) > 0 ) {
+            //     nc_put_att_text( cdfid, NCDFVarID, "proj4",
+            //                      strlen( pszProj4Defn ), pszProj4Defn );
+            // }
+            nc_put_att_text( cdfid, NCDFVarID, NCDF_SPATIAL_REF,
+                             strlen( pszProjection ), pszProjection );
+            /* for now write the geotransform for back-compat or else 
+               the old (1.8.1) driver overrides the CF geotransform with 
+               empty values from dfNN, dfSN, dfEE, dfWE; */
+            /* TODO: fix this in 1.8 branch, and then remove this here */
+            if ( bWriteGeoTransform && bSetGeoTransform ) {
+                nc_put_att_text( cdfid, NCDFVarID, NCDF_GEOTRANSFORM,
+                                 strlen( szGeoTransform ),
+                                 szGeoTransform );
             }
+        }
 
 /* -------------------------------------------------------------------- */
-/*      Stereographic                                                   */
+/*      Write Projection var in Bands                                   */
 /* -------------------------------------------------------------------- */
-		  
-            else if ( EQUAL ( pszValue, STEREO ) ) {
-	        
-                dfCenterLon = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LON_PROJ_ORIGIN, 0.0 );
-	      
-                dfCenterLat = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         LAT_PROJ_ORIGIN, 0.0 );
 
-                dfScale = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         SCALE_FACTOR_ORIGIN,
-                                         1.0 );
-
-                dfFalseEasting = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_EASTING, 0.0 );
+        for( int i=1; i <= nBands; i++ ) {
+            netCDFRasterBand *poSrcBand = 
+                (netCDFRasterBand *) GetRasterBand( i );
+            status = nc_put_att_text( cdfid, poSrcBand->nZId, 
+                                      CF_GRD_MAPPING,
+                                      strlen( szNetcdfProjection ),
+                                      szNetcdfProjection );
+            NCDF_ERR(status);
+            if ( bWriteLonLat == TRUE ) {
+                status = nc_put_att_text( cdfid, poSrcBand->nZId, 
+                                          CF_COORDINATES,
+                                          strlen( NCDF_LONLAT ), NCDF_LONLAT );
+                NCDF_ERR(status);
+            }
+        }           
 
-                dfFalseNorthing = 
-                    poDS->FetchCopyParm( szGridMappingValue, 
-                                         FALSE_NORTHING, 0.0 );
+    }  /* end if( bWriteGridMapping ) */
 
-                oSRS.SetStereographic( dfCenterLat, dfCenterLon, dfScale, 
-                                       dfFalseEasting, dfFalseNorthing );
+    pfnProgress( 0.10, NULL, pProgressData );    
 
-                if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-            }
-  
 /* -------------------------------------------------------------------- */
-/*      Is this Latitude/Longitude Grid, default                        */
+/*      Write CF Projection vars                                        */
 /* -------------------------------------------------------------------- */
-	    
-        } else if( EQUAL( szDimNameX,"lon" ) ) {
-            oSRS.SetWellKnownGeogCS( "WGS84" );
 
-        } else {
-            // This would be too indiscrimant.  But we should set
-            // it if we know the data is geographic.
-            //oSRS.SetWellKnownGeogCS( "WGS84" );
-        }
-    }
 /* -------------------------------------------------------------------- */
-/*      Read projection coordinates                                     */
+/*      Write X/Y attributes                                            */
 /* -------------------------------------------------------------------- */
+    if( bIsProjected )
+    {
+        pszUnits = oSRS.GetAttrValue("PROJCS|UNIT",1);
+        if ( pszUnits == NULL || EQUAL(pszUnits,"1") ) 
+            strcpy(szUnits,"m");
+        else if ( EQUAL(pszUnits,"1000") ) 
+            strcpy(szUnits,"km");
+
+        /* X */
+        int anXDims[1];
+        anXDims[0] = nXDimID;
+        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                  cdfid, NCDF_DIMNAME_X, NC_DOUBLE );
+        status = nc_def_var( cdfid, NCDF_DIMNAME_X, NC_DOUBLE, 
+                             1, anXDims, &NCDFVarID );
+        NCDF_ERR(status);
+        nVarXID=NCDFVarID;
+        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
+                         strlen(CF_PROJ_X_COORD),
+                         CF_PROJ_X_COORD );
+        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
+                         strlen("x coordinate of projection"),
+                         "x coordinate of projection" );
+        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS, strlen(szUnits), szUnits ); 
+
+        /* Y */
+        int anYDims[1];
+        anYDims[0] = nYDimID;
+        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                  cdfid, NCDF_DIMNAME_Y, NC_DOUBLE );
+        status = nc_def_var( cdfid, NCDF_DIMNAME_Y, NC_DOUBLE, 
+                             1, anYDims, &NCDFVarID );
+        NCDF_ERR(status);
+        nVarYID=NCDFVarID;
+        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
+                         strlen(CF_PROJ_Y_COORD),
+                         CF_PROJ_Y_COORD );
+        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
+                         strlen("y coordinate of projection"),
+                         "y coordinate of projection" );
+        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS, strlen(szUnits), szUnits ); 
+    }
 
-    nc_inq_varid( cdfid, poDS->papszDimName[nDimXid], &nVarDimXID );
-    nc_inq_varid( cdfid, poDS->papszDimName[nDimYid], &nVarDimYID );
-    
-    if( ( nVarDimXID != -1 ) && ( nVarDimYID != -1 ) ) {
-        pdfXCoord = (double *) CPLCalloc( xdim, sizeof(double) );
-        pdfYCoord = (double *) CPLCalloc( ydim, sizeof(double) );
-    
 /* -------------------------------------------------------------------- */
-/*      Is pixel spacing is uniform accross the map?                    */
+/*      Write lat/lon attributes if needed                              */
 /* -------------------------------------------------------------------- */
-        start[0] = 0;
-        edge[0]  = xdim;
-	
-        status = nc_get_vara_double( cdfid, nVarDimXID, 
-                                     start, edge, pdfXCoord);
-        edge[0]  = ydim;
-        status = nc_get_vara_double( cdfid, nVarDimYID, 
-                                     start, edge, pdfYCoord);
+    if ( bWriteLonLat == TRUE ) {
+
+        /* latitude attributes */
+        if ( bIsProjected ) {
+            int anLatDims[2];
+            anLatDims[0] =  nYDimID;
+            anLatDims[1] =  nXDimID;
+            CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                      cdfid, NCDF_DIMNAME_LAT, eLonLatType );
+            status = nc_def_var( cdfid, NCDF_DIMNAME_LAT, eLonLatType, 
+                                 2, anLatDims, &NCDFVarID );
+            NCDF_ERR(status);
+            /* compress lon/lat to save space */
+            DefVarDeflate( NCDFVarID );
+        }
+        else {
+            int anLatDims[1];
+            // anLatDims[0] = nLatDimID;
+            anLatDims[0] =  nYDimID;
+            CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                      cdfid, NCDF_DIMNAME_LAT, eLonLatType );
+            status = nc_def_var( cdfid, NCDF_DIMNAME_LAT, eLonLatType, 
+                                 1, anLatDims, &NCDFVarID );  
+            NCDF_ERR(status);                
+        }
+        nVarLatID = NCDFVarID;
+        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
+                         8,"latitude" );
+        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
+                         8, "latitude" );
+        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS,
+                         13, "degrees_north" );
+
+        /* longitude attributes */
+        if ( bIsProjected ) {
+            int anLonDims[2];
+            anLonDims[0] = nYDimID;
+            anLonDims[1] = nXDimID;
+            CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                      cdfid, NCDF_DIMNAME_LON, eLonLatType );
+            status = nc_def_var( cdfid, NCDF_DIMNAME_LON, eLonLatType, 
+                                 2, anLonDims, &NCDFVarID );
+            NCDF_ERR(status);
+            /* compress lon/lat to save space */
+            DefVarDeflate( NCDFVarID );
+        }
+        else {
+            int anLonDims[1];
+            // anLonDims[0] = nLonDimID;
+            anLonDims[0] = nXDimID;
+            CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                      cdfid, NCDF_DIMNAME_LON, eLonLatType );
+            status = nc_def_var( cdfid, NCDF_DIMNAME_LON, eLonLatType, 
+                                 1, anLonDims, &NCDFVarID );
+            NCDF_ERR(status);
+        }
+        nVarLonID = NCDFVarID;
+        nc_put_att_text( cdfid, NCDFVarID, CF_STD_NAME,
+                         9, "longitude" );
+        nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
+                         9, "longitude" );
+        nc_put_att_text( cdfid, NCDFVarID, CF_UNITS,
+                         12, "degrees_east" );
+    }
+
+    pfnProgress( 0.50, NULL, pProgressData );
 
 /* -------------------------------------------------------------------- */
-/*      Check Longitude                                                 */
+/*      Get projection values                                           */
 /* -------------------------------------------------------------------- */
 
-        nSpacingBegin   = (int) poDS->rint((pdfXCoord[1]-pdfXCoord[0]) * 1000);
-	
-        nSpacingMiddle  = (int) poDS->rint((pdfXCoord[xdim / 2] - 
-                                            pdfXCoord[(xdim / 2) + 1]) * 1000);
-	
-        nSpacingLast    = (int) poDS->rint((pdfXCoord[xdim - 2] - 
-                                            pdfXCoord[xdim-1]) * 1000);
-	
-        if( ( abs( nSpacingBegin )  ==  abs( nSpacingLast )     )  &&
-            ( abs( nSpacingBegin )  ==  abs( nSpacingMiddle )   ) &&
-            ( abs( nSpacingMiddle ) ==  abs( nSpacingLast )     ) ) {
+    double dfX0, dfDX, dfY0, dfDY;
+    dfX0=0.0, dfDX=0.0, dfY0=0.0, dfDY=0.0;
+    double *padLonVal = NULL;
+    double *padLatVal = NULL; /* should use float for projected, save space */
+
+    if( bIsProjected )
+    {
+        // const char  *pszProjection;
+        OGRSpatialReference oSRS;
+        OGRSpatialReference *poLatLonSRS = NULL;
+        OGRCoordinateTransformation *poTransform = NULL;
+
+        char *pszWKT = (char *) pszProjection;
+        oSRS.importFromWkt( &pszWKT );
+
+        double *padYVal = NULL;
+        double *padXVal = NULL;
+        size_t startX[1];
+        size_t countX[1];
+        size_t startY[1];
+        size_t countY[1];
+
+        CPLDebug("GDAL_netCDF", "Getting (X,Y) values" );
+
+        padXVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
+        padYVal = (double *) CPLMalloc( nRasterYSize * sizeof( double ) );
 
 /* -------------------------------------------------------------------- */
-/*      Longitude is equaly spaced, check lattitde                      */
+/*      Get Y values                                                    */
 /* -------------------------------------------------------------------- */
-            nSpacingBegin   = (int) poDS->rint((pdfYCoord[1]-pdfYCoord[0]) * 
-                                               1000); 
-	    
-            nSpacingMiddle  = (int) poDS->rint((pdfYCoord[ydim / 2] - 
-                                                pdfYCoord[(ydim / 2) + 1]) * 
-                                               1000);
-	    
-            nSpacingLast    = (int) poDS->rint((pdfYCoord[ydim - 2] - 
-                                                pdfYCoord[ydim-1]) * 
-                                               1000);
+        if ( ! bBottomUp )
+            dfY0 = adfGeoTransform[3];
+        else /* invert latitude values */ 
+            dfY0 = adfGeoTransform[3] + ( adfGeoTransform[5] * nRasterYSize );
+        dfDY = adfGeoTransform[5];
+        
+        for( int j=0; j<nRasterYSize; j++ ) {
+            /* The data point is centered inside the pixel */
+            if ( ! bBottomUp )
+                padYVal[j] = dfY0 + (j+0.5)*dfDY ;
+            else /* invert latitude values */ 
+                padYVal[j] = dfY0 - (j+0.5)*dfDY ;            
+        }
+        startX[0] = 0;
+        countX[0] = nRasterXSize;
 
-		    
 /* -------------------------------------------------------------------- */
-/*   For Latitude  we allow an error of 0.1 degrees for gaussion        */
-/*   gridding                                                           */
+/*      Get X values                                                    */
 /* -------------------------------------------------------------------- */
+        dfX0 = adfGeoTransform[0];
+        dfDX = adfGeoTransform[1];
 
-            if((( abs( abs(nSpacingBegin) - abs(nSpacingLast) ) )   < 100 ) &&
-               (( abs( abs(nSpacingBegin) -  abs(nSpacingMiddle) ) ) < 100 ) &&
-               (( abs( abs(nSpacingMiddle) - abs(nSpacingLast) ) )   < 100) ) {
-
-                if( ( abs( nSpacingBegin )  !=  abs( nSpacingLast )     )  ||
-                    ( abs( nSpacingBegin )  !=  abs( nSpacingMiddle )   ) ||
-                    ( abs( nSpacingMiddle ) !=  abs( nSpacingLast )     ) ) {
-		    
-                    CPLError(CE_Warning, 1,"Latitude grid not spaced evenly.\nSeting projection for grid spacing is within 0.1 degrees threshold.\n");
+        for( int i=0; i<nRasterXSize; i++ ) {
+            /* The data point is centered inside the pixel */
+            padXVal[i] = dfX0 + (i+0.5)*dfDX ;
+        }
+        startY[0] = 0;
+        countY[0] = nRasterYSize;
 
-                }
 /* -------------------------------------------------------------------- */
-/*      We have gridded data s we can set the Gereferencing info.       */
+/*      Write X/Y values                                                */
 /* -------------------------------------------------------------------- */
+        /* make sure we are in data mode */
+        SetDefineMode( FALSE );
+
+        CPLDebug("GDAL_netCDF", "Writing X values" );
+        status = nc_put_vara_double( cdfid, nVarXID, startX,
+                                     countX, padXVal);
+        NCDF_ERR(status);
+
+        CPLDebug("GDAL_netCDF", "Writing Y values" );
+        status = nc_put_vara_double( cdfid, nVarYID, startY,
+                                     countY, padYVal);
+        NCDF_ERR(status);
+
+        pfnProgress( 0.20, NULL, pProgressData );
 
 /* -------------------------------------------------------------------- */
-/*      Enable GeoTransform                                             */
+/*      Transform (X,Y) values to (lon,lat)                             */
 /* -------------------------------------------------------------------- */
-                /* ----------------------------------------------------------*/
-                /*    In the following "actual_range" and "node_offset"      */
-                /*    are attributes used by netCDF files created by GMT.    */
-                /*    If we find them we know how to proceed. Else, use      */
-                /*    the original algorithm.                                */
-                /* --------------------------------------------------------- */
-                double	dummy[2], xMinMax[2], yMinMax[2];
-                int	node_offset = 0;
 
-                poDS->bGotGeoTransform = TRUE;
+        /* Get OGR transform */
+        if ( bWriteLonLat == TRUE ) {
+            poLatLonSRS = oSRS.CloneGeogCS();
+            if ( poLatLonSRS != NULL )
+                poTransform = OGRCreateCoordinateTransformation( &oSRS, poLatLonSRS );
+            /* if no OGR transform, then don't write CF lon/lat */
+            if( poTransform == NULL ) {
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                          "Unable to get Coordinate Transform" );
+                bWriteLonLat = FALSE;
+            }
+        }
+            
+        if ( bWriteLonLat == TRUE )  {
 
-                nc_get_att_int (cdfid, NC_GLOBAL, "node_offset", &node_offset);
+            CPLDebug("GDAL_netCDF", "Transforming (X,Y)->(lon,lat)" );
 
-                if (!nc_get_att_double (cdfid, nVarDimXID, "actual_range", dummy)) {
-                    xMinMax[0] = dummy[0];		
-                    xMinMax[1] = dummy[1];
-                }
-                else {
-                    xMinMax[0] = pdfXCoord[0];
-                    xMinMax[1] = pdfXCoord[xdim-1];
-                    node_offset = 0;
-                }
+            padLatVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
+            padLonVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
+            size_t start[2], count[2];
+            start[1] = 0; //X
+            count[1] = nRasterXSize; 
+            start[0] = 0; //Y
+            count[0] = 1;
 
-                if (!nc_get_att_double (cdfid, nVarDimYID, "actual_range", dummy)) {
-                    yMinMax[0] = dummy[0];		
-                    yMinMax[1] = dummy[1];
-                }
-                else {
-                    yMinMax[0] = pdfYCoord[0];	
-                    yMinMax[1] = pdfYCoord[ydim-1];
-                    node_offset = 0;
-                }
-                /* for CF-1 conventions, assume bottom first */
-                if( ( EQUAL( szDimNameY, "lat" ) || EQUAL( szDimNameY, "y" ) )
-                    && pdfYCoord[0] < pdfYCoord[1] )
-                    poDS->bBottomUp = TRUE;
+            int bOK = TRUE;
+            double dfTemp;
+            int i,j;
+            dfTemp = 0.2;
 
-                // Check for reverse order of y-coordinate
-                if ( yMinMax[0] > yMinMax[1] ) {
-                    dummy[0] = yMinMax[1];
-                    dummy[1] = yMinMax[0];
-                    yMinMax[0] = dummy[0];
-                    yMinMax[1] = dummy[1];
-                }
+            for( j = 0; (j < nRasterYSize) && bOK && (status == NC_NOERR); j++ ) {
+                
+                start[0] = j;
 
-                /* ----------------------------------------------------------*/
-                /*    Many netcdf files are weather files distributed        */
-                /*    in km for the x/y resolution.  This isn't perfect,     */
-                /*    but geotransforms can be terribly off if this isn't    */
-                /*    checked and accounted for.  Maybe one more level of    */
-                /*    checking (grid_mapping_value#GRIB_param_Dx, or         */
-                /*    x#grid_spacing), but those are not cf tags.            */
-                /*    Have to change metadata value if change Create() to    */
-                /*    write cf tags                                          */
-                /* ----------------------------------------------------------*/
+                /* fill values to transform */
+                for( i=0; i<nRasterXSize; i++ ) {
+                    padLatVal[i] = padYVal[j];
+                    padLonVal[i] = padXVal[i];
+                }
                 
-                //check units for x and y, expand to other values 
-                //and conversions.
-                if( oSRS.IsProjected( ) ) {
-                    strcpy( szTemp, "x" );
-                    strcat( szTemp, "#units" );
-                    pszValue = CSLFetchNameValue( poDS->papszMetadata, 
-                                                  szTemp );
-                    if( pszValue != NULL ) {
-                        if( EQUAL( pszValue, "km" ) ) {
-                            xMinMax[0] = xMinMax[0] * 1000;
-                            xMinMax[1] = xMinMax[1] * 1000;
-                        }
-                    }
-                    strcpy( szTemp, "y" );
-                    strcat( szTemp, "#units" );
-                    pszValue = CSLFetchNameValue( poDS->papszMetadata, 
-                                                  szTemp );
-                    if( pszValue != NULL ) {
-                        if( EQUAL( pszValue, "km" ) ) {
-                            yMinMax[0] = yMinMax[0] * 1000;
-                            yMinMax[1] = yMinMax[1] * 1000;
-                        }
-                    }
+                /* do the transform */
+                bOK = poTransform->Transform( nRasterXSize, 
+                                              padLonVal, padLatVal, NULL );
+                /* write data */
+                if ( bOK ) {
+                    status = nc_put_vara_double( cdfid, nVarLatID, start,
+                                                 count, padLatVal);
+                    NCDF_ERR(status);
+                    status = nc_put_vara_double( cdfid, nVarLonID, start,
+                                                 count, padLonVal);
+                    NCDF_ERR(status);
                 }
+                else 
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Unable to Transform (X,Y) to (lon,lat).\n" );
 
-                poDS->adfGeoTransform[0] = xMinMax[0];
-                poDS->adfGeoTransform[2] = 0;
-                poDS->adfGeoTransform[3] = yMinMax[1];
-                poDS->adfGeoTransform[4] = 0;
-                poDS->adfGeoTransform[1] = ( xMinMax[1] - xMinMax[0] ) / 
-                    ( poDS->nRasterXSize + (node_offset - 1) );
-                poDS->adfGeoTransform[5] = ( yMinMax[0] - yMinMax[1] ) / 
-                    ( poDS->nRasterYSize + (node_offset - 1) );
-
-/* -------------------------------------------------------------------- */
-/*     Compute the center of the pixel                                  */
-/* -------------------------------------------------------------------- */
-                if ( !node_offset ) {	// Otherwise its already the pixel center
-                    poDS->adfGeoTransform[0] -= (poDS->adfGeoTransform[1] / 2);
-                    poDS->adfGeoTransform[3] -= (poDS->adfGeoTransform[5] / 2);
+                if ( j % (nRasterYSize/10) == 0 ) {
+                    dfTemp += 0.08;
+                    pfnProgress( dfTemp , NULL, pProgressData );
                 }
+            }
 
-                oSRS.exportToWkt( &(poDS->pszProjection) );
-		    
-            } 
         }
 
-        CPLFree( pdfXCoord );
-        CPLFree( pdfYCoord );
-    }
+        /* Free the srs and transform objects */
+        if ( poLatLonSRS != NULL ) CPLFree( poLatLonSRS );
+        if ( poTransform != NULL ) CPLFree( poTransform );
 
+        /* Free data */
+        CPLFree( padXVal );
+        CPLFree( padYVal );
+        CPLFree( padLonVal );
+        CPLFree( padLatVal);
 
-/* -------------------------------------------------------------------- */
-/*      Is this a netCDF file created by GDAL?                          */
-/* -------------------------------------------------------------------- */
-    if( !EQUAL( szGridMappingValue, "" )  ) {
-        strcpy( szTemp,szGridMappingValue);
-        strcat( szTemp, "#" );
-        strcat( szTemp, "spatial_ref");
-        pszWKT = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-	
-        if( pszWKT != NULL ) {
-	    
-            pszProjection = CPLStrdup( pszWKT );
-	    
-            strcpy(szTemp,szGridMappingValue);
-            strcat( szTemp, "#" );
-            strcat( szTemp, "GeoTransform");
-	    
-            pszGeoTransform = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-	    
-/* -------------------------------------------------------------------- */
-/*      Look for GeoTransform Array                                     */
-/* -------------------------------------------------------------------- */
+    } // projected
 
-            if( pszGeoTransform != NULL ) {
-                papszGeoTransform = CSLTokenizeString2( pszGeoTransform,
-                                                        " ", 
-                                                        CSLT_HONOURSTRINGS );
-                poDS->bGotGeoTransform   = TRUE;
-		
-                poDS->adfGeoTransform[0] = atof( papszGeoTransform[0] );
-                poDS->adfGeoTransform[1] = atof( papszGeoTransform[1] );
-                poDS->adfGeoTransform[2] = atof( papszGeoTransform[2] );
-                poDS->adfGeoTransform[3] = atof( papszGeoTransform[3] );
-                poDS->adfGeoTransform[4] = atof( papszGeoTransform[4] );
-                poDS->adfGeoTransform[5] = atof( papszGeoTransform[5] );
-/* -------------------------------------------------------------------- */
-/*      Look for corner array values                                    */
+    /* If not Projected assume Geographic to catch grids without Datum */
+    else if ( bWriteLonLat == TRUE )  {  
+        	
 /* -------------------------------------------------------------------- */
-            } else {
-                double dfNN, dfSN, dfEE, dfWE;
-                strcpy(szTemp,szGridMappingValue);
-                strcat( szTemp, "#" );
-                strcat( szTemp, "Northernmost_Northing");
-                pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-		
-                if( pszValue != NULL ) {
-                    dfNN = atof( pszValue );
-                }
-                strcpy(szTemp,szGridMappingValue);
-                strcat( szTemp, "#" );
-                strcat( szTemp, "Southernmost_Northing");
-                pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-		
-                if( pszValue != NULL ) {
-                    dfSN = atof( pszValue );
-                }
-		
-                strcpy(szTemp,szGridMappingValue);
-                strcat( szTemp, "#" );
-                strcat( szTemp, "Easternmost_Easting");
-                pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-		
-                if( pszValue != NULL ) {
-                    dfEE = atof( pszValue );
-                }
-		
-                strcpy(szTemp,szGridMappingValue);
-                strcat( szTemp, "#" );
-                strcat( szTemp, "Westernmost_Easting");
-                pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-		
-                if( pszValue != NULL ) {
-                    dfWE = atof( pszValue );
-                }
-		
-                adfGeoTransform[0] = dfWE;
-                adfGeoTransform[1] = (dfEE - dfWE) / 
-                    ( poDS->GetRasterXSize() - 1 );
-                adfGeoTransform[2] = 0.0;
-                adfGeoTransform[3] = dfNN;
-                adfGeoTransform[4] = 0.0;
-                adfGeoTransform[5] = (dfSN - dfNN) / 
-                    ( poDS->GetRasterYSize() - 1 );
+/*      Get latitude values                                             */
 /* -------------------------------------------------------------------- */
-/*     Compute the center of the pixel                                  */
+        if ( ! bBottomUp )
+            dfY0 = adfGeoTransform[3];
+        else /* invert latitude values */ 
+            dfY0 = adfGeoTransform[3] + ( adfGeoTransform[5] * nRasterYSize );
+        dfDY = adfGeoTransform[5];
+        
+        padLatVal = (double *) CPLMalloc( nRasterYSize * sizeof( double ) );
+        for( int i=0; i<nRasterYSize; i++ ) {
+            /* The data point is centered inside the pixel */
+            if ( ! bBottomUp )
+                padLatVal[i] = dfY0 + (i+0.5)*dfDY ;
+            else /* invert latitude values */ 
+                padLatVal[i] = dfY0 - (i+0.5)*dfDY ;
+        }
+        
+        size_t startLat[1];
+        size_t countLat[1];
+        startLat[0] = 0;
+        countLat[0] = nRasterYSize;
+                
+/* -------------------------------------------------------------------- */
+/*      Get longitude values                                            */
+/* -------------------------------------------------------------------- */
+        dfX0 = adfGeoTransform[0];
+        dfDX = adfGeoTransform[1];
+        
+        padLonVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
+        for( int i=0; i<nRasterXSize; i++ ) {
+            /* The data point is centered inside the pixel */
+            padLonVal[i] = dfX0 + (i+0.5)*dfDX ;
+        }
+        
+        size_t startLon[1];
+        size_t countLon[1];
+        startLon[0] = 0;
+        countLon[0] = nRasterXSize;
+
+/* -------------------------------------------------------------------- */
+/*      Write latitude and longitude values                             */
 /* -------------------------------------------------------------------- */
-                adfGeoTransform[0] = dfWE
-                    - (adfGeoTransform[1] / 2);
+        /* latitude values */
+        CPLDebug("GDAL_netCDF", "Writing lat values" );
 
-                adfGeoTransform[3] = dfNN
-                    - (adfGeoTransform[5] / 2);
+        /* make sure we are in data mode */
+        SetDefineMode( FALSE );
 
+        status = nc_put_vara_double( cdfid, nVarLatID, startLat,
+                                     countLat, padLatVal);
+        NCDF_ERR(status);
 
-                bGotGeoTransform = TRUE;
-            }
-            CSLDestroy( papszGeoTransform );
-        }
-    }
+        /* free values */
+        CPLFree( padLatVal );  
+
+        /* longitude values */
+        CPLDebug("GDAL_netCDF", "Writing lon values" );
+        status = nc_put_vara_double( cdfid, nVarLonID, startLon,
+                                     countLon, padLonVal);
+        NCDF_ERR(status);
+        
+        /* free values */
+        CPLFree( padLonVal );  
+        
+    }// not projected 
+            
+
+    pfnProgress( 1.00, NULL, pProgressData );
 
+    return CE_None;
 }
+
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -1666,10 +3376,10 @@ CPLErr netCDFDataset::GetGeoTransform( double * padfTransform )
 
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-    if( bGotGeoTransform )
+    if( bSetGeoTransform )
         return CE_None;
     else
-        return GDALPamDataset::GetGeoTransform( padfTransform );;
+        return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -1700,18 +3410,6 @@ double netCDFDataset::rint( double dfX)
 /************************************************************************/
 /*                        ReadAttributes()                              */
 /************************************************************************/
-CPLErr netCDFDataset::SafeStrcat(char** ppszDest, char* pszSrc, size_t* nDestSize)
-{
-    /* Reallocate the data string until the content fits */
-    while(*nDestSize < (strlen(*ppszDest) + strlen(pszSrc) + 1)) {
-        (*nDestSize) *= 2;
-        *ppszDest = (char*) CPLRealloc((void*) *ppszDest, *nDestSize);
-    }
-    strcat(*ppszDest, pszSrc);
-    
-    return CE_None;
-}
-
 CPLErr netCDFDataset::ReadAttributes( int cdfid, int var)
 
 {
@@ -1719,95 +3417,35 @@ CPLErr netCDFDataset::ReadAttributes( int cdfid, int var)
     char    szVarName [ NC_MAX_NAME ];
     char    szMetaName[ NC_MAX_NAME * 2 ];
     char    *pszMetaTemp = NULL;
-    size_t  nMetaTempSize;
-    nc_type nAttrType;
-    size_t  nAttrLen, m;
     int     nbAttr;
-    char    szTemp[ MAX_STR_LEN ];
 
     nc_inq_varnatts( cdfid, var, &nbAttr );
     if( var == NC_GLOBAL ) {
         strcpy( szVarName,"NC_GLOBAL" );
     }
     else {
-        nc_inq_varname(  cdfid, var, szVarName );
+        nc_inq_varname( cdfid, var, szVarName );
     }
 
     for( int l=0; l < nbAttr; l++) {
 	
         nc_inq_attname( cdfid, var, l, szAttrName);
         sprintf( szMetaName, "%s#%s", szVarName, szAttrName  );
-        nc_inq_att( cdfid, var, szAttrName, &nAttrType, &nAttrLen );
-	
-        /* Allocate guaranteed minimum size */
-        nMetaTempSize = nAttrLen + 1;
-        pszMetaTemp = (char *) CPLCalloc( nMetaTempSize, sizeof( char ));
-        *pszMetaTemp = '\0';
-	
-        switch (nAttrType) {
-            case NC_CHAR:
-                nc_get_att_text( cdfid, var, szAttrName, pszMetaTemp );
-                pszMetaTemp[nAttrLen]='\0';
-                break;
-            case NC_SHORT:
-                short *psTemp;
-                psTemp = (short *) CPLCalloc( nAttrLen, sizeof( short ) );
-                nc_get_att_short( cdfid, var, szAttrName, psTemp );
-                for(m=0; m < nAttrLen-1; m++) {
-                    sprintf( szTemp, "%hd, ", psTemp[m] );
-                    SafeStrcat(&pszMetaTemp, szTemp, &nMetaTempSize);
-                }
-                sprintf( szTemp, "%hd", psTemp[m] );
-                SafeStrcat(&pszMetaTemp, szTemp, &nMetaTempSize);
-                CPLFree(psTemp);
-                break;
-            case NC_INT:
-                int *pnTemp;
-                pnTemp = (int *) CPLCalloc( nAttrLen, sizeof( int ) );
-                nc_get_att_int( cdfid, var, szAttrName, pnTemp );
-                for(m=0; m < nAttrLen-1; m++) {
-                    sprintf( szTemp, "%d, ", pnTemp[m] );
-                    SafeStrcat(&pszMetaTemp, szTemp, &nMetaTempSize);
-                }
-        	    sprintf( szTemp, "%d", pnTemp[m] );
-        	    SafeStrcat(&pszMetaTemp, szTemp, &nMetaTempSize);
-                CPLFree(pnTemp);
-                break;
-            case NC_FLOAT:
-                float *pfTemp;
-                pfTemp = (float *) CPLCalloc( nAttrLen, sizeof( float ) );
-                nc_get_att_float( cdfid, var, szAttrName, pfTemp );
-                for(m=0; m < nAttrLen-1; m++) {
-                    sprintf( szTemp, "%e, ", pfTemp[m] );
-                    SafeStrcat(&pszMetaTemp, szTemp, &nMetaTempSize);
-                }
-        	    sprintf( szTemp, "%e", pfTemp[m] );
-        	    SafeStrcat(&pszMetaTemp,szTemp, &nMetaTempSize);
-                CPLFree(pfTemp);
-                break;
-            case NC_DOUBLE:
-                double *pdfTemp;
-                pdfTemp = (double *) CPLCalloc(nAttrLen, sizeof(double));
-                nc_get_att_double( cdfid, var, szAttrName, pdfTemp );
-                for(m=0; m < nAttrLen-1; m++) {
-                    sprintf( szTemp, "%g, ", pdfTemp[m] );
-                    SafeStrcat(&pszMetaTemp, szTemp, &nMetaTempSize);
-                }
-        	    sprintf( szTemp, "%g", pdfTemp[m] );
-        	    SafeStrcat(&pszMetaTemp, szTemp, &nMetaTempSize);
-                CPLFree(pdfTemp);
-                break;
-            default:
-                break;
+
+        if ( NCDFGetAttr( cdfid, var, szAttrName, &pszMetaTemp )
+             == CE_None ) {
+            papszMetadata = CSLSetNameValue(papszMetadata, 
+                                            szMetaName, 
+                                            pszMetaTemp);
+            CPLFree(pszMetaTemp);
+            pszMetaTemp = NULL;
+        }
+        else {
+            CPLDebug( "GDAL_netCDF", "invalid global metadata %s", szMetaName );
         }
 
-        papszMetadata = CSLSetNameValue(papszMetadata, 
-                                        szMetaName, 
-                                        pszMetaTemp);
-        CPLFree(pszMetaTemp);
     }
 	
-
     return CE_None;
 
 }
@@ -1866,6 +3504,9 @@ void netCDFDataset::CreateSubDatasetList( )
             switch( nVarType ) {
 		
                 case NC_BYTE:
+#ifdef NETCDF_HAS_NC4
+                case NC_UBYTE:
+#endif    
                 case NC_CHAR:
                     strcpy(szType, "8-bit character");
                     break;
@@ -1886,9 +3527,9 @@ void netCDFDataset::CreateSubDatasetList( )
                 default:
                     break;
             }
-            nc_inq_varname  ( cdfid, nVar, szName);
-            nc_inq_att( cdfid, nVar, "standard_name", &nAttype, &nAttlen);
-            if( nc_get_att_text ( cdfid, nVar, "standard_name", 
+            nc_inq_varname( cdfid, nVar, szName);
+            nc_inq_att( cdfid, nVar, CF_STD_NAME, &nAttype, &nAttlen);
+            if( nc_get_att_text ( cdfid, nVar, CF_STD_NAME, 
                                   szVarStdName ) == NC_NOERR ) {
                 szVarStdName[nAttlen] = '\0';
             }
@@ -1919,11 +3560,100 @@ void netCDFDataset::CreateSubDatasetList( )
 }
     
 /************************************************************************/
+/*                              IdentifyFormat()                      */
+/************************************************************************/
+
+int netCDFDataset::IdentifyFormat( GDALOpenInfo * poOpenInfo, bool bCheckExt = TRUE )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Does this appear to be a netcdf file? If so, which format?      */
+/*      http://www.unidata.ucar.edu/software/netcdf/docs/faq.html#fv1_5 */
+/* -------------------------------------------------------------------- */
+
+    if( EQUALN(poOpenInfo->pszFilename,"NETCDF:",7) )
+        return NCDF_FORMAT_UNKNOWN;
+    if ( poOpenInfo->nHeaderBytes < 4 )
+        return NCDF_FORMAT_NONE;
+    if ( EQUALN((char*)poOpenInfo->pabyHeader,"CDF\001",4) )
+        return NCDF_FORMAT_NC;
+    else if ( EQUALN((char*)poOpenInfo->pabyHeader,"CDF\002",4) )
+        return NCDF_FORMAT_NC2;
+    else if ( EQUALN((char*)poOpenInfo->pabyHeader,"\211HDF\r\n\032\n",8) ) {
+        /* Requires netCDF-4/HDF5 support in libnetcdf (not just libnetcdf-v4).
+           If HDF5 is not supported in GDAL, this driver will try to open the file 
+           Else, make sure this driver does not try to open HDF5 files 
+           If user really wants to open with this driver, use NETCDF:file.h5 format. 
+           This check should be relaxed, but there is no clear way to make a difference. 
+        */
+
+        /* Check for HDF5 support in GDAL */
+#ifdef HAVE_HDF5
+        if ( bCheckExt ) { /* Check by default */
+            const char* pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
+            if ( ! ( EQUAL( pszExtension, "nc")  || EQUAL( pszExtension, "cdf") 
+                     || EQUAL( pszExtension, "nc2") || EQUAL( pszExtension, "nc4") ) )
+                return NCDF_FORMAT_HDF5;
+        }
+#endif
+
+        /* Check for netcdf-4 support in libnetcdf */
+#ifdef NETCDF_HAS_NC4
+        return NCDF_FORMAT_NC4;
+#else
+        return NCDF_FORMAT_HDF5;
+#endif
+
+    }
+    else if ( EQUALN((char*)poOpenInfo->pabyHeader,"\016\003\023\001",4) ) {
+        /* Requires HDF4 support in libnetcdf, but if HF4 is supported by GDAL don't try to open. */
+        /* If user really wants to open with this driver, use NETCDF:file.hdf syntax. */
+
+        /* Check for HDF4 support in GDAL */
+#ifdef HAVE_HDF4
+        if ( bCheckExt ) { /* Check by default */
+            /* Always treat as HDF4 file */
+            return NCDF_FORMAT_HDF4;
+        }
+#endif
+
+        /* Check for HDF4 support in libnetcdf */
+#ifdef NETCDF_HAS_HDF4
+        return NCDF_FORMAT_NC4; 
+#else
+        return NCDF_FORMAT_HDF4;
+#endif
+    }
+
+    return NCDF_FORMAT_NONE;
+} 
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int netCDFDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    if( EQUALN(poOpenInfo->pszFilename,"NETCDF:",7) ) {
+        return TRUE;
+    }
+    int nTmpFormat = IdentifyFormat( poOpenInfo );
+    if( NCDF_FORMAT_NC  == nTmpFormat ||
+        NCDF_FORMAT_NC2  == nTmpFormat ||
+        NCDF_FORMAT_NC4  == nTmpFormat ||
+        NCDF_FORMAT_NC4C  == nTmpFormat )
+        return TRUE;
+    else
+        return FALSE;
+} 
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
 GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
-
+    
 {
     int          j;
     unsigned int k;
@@ -1940,27 +3670,50 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     int          nCount=0;
     int          nVarID=-1;
 
+    int          nTmpFormat=NCDF_FORMAT_NONE;
+    int          *panBandDimPos;         // X, Y, Z postion in array
+    int          *panBandZLev;
+    int          *paDimIds;
+    size_t        xdim, ydim;
+    char         szTemp[NC_MAX_NAME];
+
+    CPLString    osSubdatasetName;
+    int          bTreatAsSubdataset;
+
 /* -------------------------------------------------------------------- */
 /*      Does this appear to be a netcdf file?                           */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(poOpenInfo->pszFilename,"NETCDF:",7)
-        && ( poOpenInfo->nHeaderBytes < 5 
-             || !EQUALN((const char *) (poOpenInfo->pabyHeader),"CDF\001",5)))
-        return NULL;
+    if( ! EQUALN(poOpenInfo->pszFilename,"NETCDF:",7) ) {
+        nTmpFormat = IdentifyFormat( poOpenInfo );
+        /* Note: not calling Identify() directly, because we want the file type */
+        /* Only support NCDF_FORMAT* formats */
+        if( ! ( NCDF_FORMAT_NC  == nTmpFormat ||
+                NCDF_FORMAT_NC2  == nTmpFormat ||
+                NCDF_FORMAT_NC4  == nTmpFormat ||
+                NCDF_FORMAT_NC4C  == nTmpFormat ) )
+            return NULL;
+    }
 
-/* -------------------------------------------------------------------- */
-/*       Check if filename start with NETCDF: tag                       */
-/* -------------------------------------------------------------------- */
     netCDFDataset 	*poDS;
     poDS = new netCDFDataset();
-    poDS->SetDescription( poOpenInfo->pszFilename );
 
+/* -------------------------------------------------------------------- */
+/*      Disable PAM, at least temporarily. See bug #4244                */
+/* -------------------------------------------------------------------- */
+    poDS->nPamFlags |= GPF_DISABLED;
+
+
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    
+/* -------------------------------------------------------------------- */
+/*       Check if filename start with NETCDF: tag                       */
+/* -------------------------------------------------------------------- */
     if( EQUALN( poOpenInfo->pszFilename,"NETCDF:",7) )
     {
         char **papszName =
             CSLTokenizeString2( poOpenInfo->pszFilename,
                                 ":", CSLT_HONOURSTRINGS|CSLT_PRESERVEESCAPES );
-                   
+        
         /* -------------------------------------------------------------------- */
         /*    Check for drive name in windows NETCDF:"D:\...                    */
         /* -------------------------------------------------------------------- */
@@ -1971,15 +3724,22 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->osFilename = papszName[1];
             poDS->osFilename += ':';
             poDS->osFilename += papszName[2];
-            poDS->osSubdatasetName = papszName[3];
-            poDS->bTreatAsSubdataset = TRUE;
+            osSubdatasetName = papszName[3];
+            bTreatAsSubdataset = TRUE;
             CSLDestroy( papszName );
         }
         else if( CSLCount(papszName) == 3 )
         {
             poDS->osFilename = papszName[1];
-            poDS->osSubdatasetName = papszName[2];
-            poDS->bTreatAsSubdataset = TRUE;
+            osSubdatasetName = papszName[2];
+            bTreatAsSubdataset = TRUE;
+            CSLDestroy( papszName );
+    	}
+        else if( CSLCount(papszName) == 2 )
+        {
+            poDS->osFilename = papszName[1];
+            osSubdatasetName = "";
+            bTreatAsSubdataset = FALSE;
             CSLDestroy( papszName );
     	}
         else
@@ -1987,23 +3747,35 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
             CSLDestroy( papszName );
             delete poDS;
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Failed to parse NETCDF: prefix string into expected three fields." );
+                      "Failed to parse NETCDF: prefix string into expected 2, 3 or 4 fields." );
             return NULL;
         }
+        /* Identify Format from real file, with bCheckExt=FALSE */ 
+        GDALOpenInfo* poOpenInfo2 = new GDALOpenInfo(poDS->osFilename.c_str(), GA_ReadOnly );
+        poDS->nFormat = IdentifyFormat( poOpenInfo2, FALSE );
+        delete poOpenInfo2;
+        if( NCDF_FORMAT_NONE == poDS->nFormat ||
+            NCDF_FORMAT_UNKNOWN == poDS->nFormat ) {
+            delete poDS;
+            return NULL;
+        }        
     }
     else 
     {
         poDS->osFilename = poOpenInfo->pszFilename;
-        poDS->bTreatAsSubdataset = FALSE;
+        bTreatAsSubdataset = FALSE;
+        poDS->nFormat = nTmpFormat;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
+    CPLDebug( "GDAL_netCDF", "\n=====\ncalling nc_open( %s )\n", poDS->osFilename.c_str() );
     if( nc_open( poDS->osFilename, NC_NOWRITE, &cdfid ) != NC_NOERR ) {
         delete poDS;
         return NULL;
     }
+
 /* -------------------------------------------------------------------- */
 /*      Is this a real netCDF file?                                     */
 /* -------------------------------------------------------------------- */
@@ -2011,8 +3783,33 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     if( status != NC_NOERR ) {
         delete poDS;
         return NULL;
+    }   
+
+/* -------------------------------------------------------------------- */
+/*      Get file type from netcdf                                       */
+/* -------------------------------------------------------------------- */
+    status = nc_inq_format (cdfid, &nTmpFormat);
+    if ( status != NC_NOERR ) {
+        NCDF_ERR(status);
     }
-    
+    else {
+        CPLDebug( "GDAL_netCDF", 
+                  "driver detected file type=%d, libnetcdf detected type=%d",
+                  poDS->nFormat, nTmpFormat );
+        if ( nTmpFormat != poDS->nFormat ) {
+            /* warn if file detection conflicts with that from libnetcdf */
+            /* except for NC4C, which we have no way of detecting initially */
+            if ( nTmpFormat != NCDF_FORMAT_NC4C ) {
+                CPLError( CE_Warning, CPLE_AppDefined, 
+                          "NetCDF driver detected file type=%d, but libnetcdf detected type=%d",
+                          poDS->nFormat, nTmpFormat );
+            }
+            CPLDebug( "GDAL_netCDF", "seting file type to %d, was %d", 
+                      nTmpFormat, poDS->nFormat );
+            poDS->nFormat = nTmpFormat;
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
@@ -2029,14 +3826,14 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Does the request variable exist?                                */
 /* -------------------------------------------------------------------- */
-    if( poDS->bTreatAsSubdataset )
+    if( bTreatAsSubdataset )
     {
-        status = nc_inq_varid( cdfid, poDS->osSubdatasetName, &var);
+        status = nc_inq_varid( cdfid, osSubdatasetName, &var);
         if( status != NC_NOERR ) {
             CPLError( CE_Warning, CPLE_AppDefined, 
                       "%s is a netCDF file, but %s is not a variable.",
                       poOpenInfo->pszFilename, 
-                      poDS->osSubdatasetName.c_str() );
+                      osSubdatasetName.c_str() );
             
             nc_close( cdfid );
             delete poDS;
@@ -2055,7 +3852,7 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    CPLDebug( "GDAL_netCDF", "dim_count = %d\n", dim_count );
+    CPLDebug( "GDAL_netCDF", "dim_count = %d", dim_count );
 
     if( (status = nc_get_att_text( cdfid, NC_GLOBAL, "Conventions",
                                    attname )) != NC_NOERR ) {
@@ -2074,7 +3871,7 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }    
     
-    CPLDebug( "GDAL_netCDF", "var_count = %d\n", var_count );
+    CPLDebug( "GDAL_netCDF", "var_count = %d", var_count );
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
@@ -2100,7 +3897,7 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      We have more than one variable with 2 dimensions in the         */
 /*      file, then treat this as a subdataset container dataset.        */
 /* -------------------------------------------------------------------- */
-    if( (nCount > 1) && !poDS->bTreatAsSubdataset )
+    if( (nCount > 1) && !bTreatAsSubdataset )
     {
         poDS->CreateSubDatasetList();
         poDS->SetMetadata( poDS->papszMetadata );
@@ -2112,33 +3909,33 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      If we are not treating things as a subdataset, then capture     */
 /*      the name of the single available variable as the subdataset.    */
 /* -------------------------------------------------------------------- */
-    if( !poDS->bTreatAsSubdataset ) // nCount must be 1!
+    if( !bTreatAsSubdataset ) // nCount must be 1!
     {
         char szVarName[NC_MAX_NAME];
 
         nc_inq_varname( cdfid, nVarID, szVarName);
-        poDS->osSubdatasetName = szVarName;
+        osSubdatasetName = szVarName;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Open the NETCDF subdataset NETCDF:"filename":subdataset         */
 /* -------------------------------------------------------------------- */
     var=-1;
-    nc_inq_varid( cdfid, poDS->osSubdatasetName, &var);
+    nc_inq_varid( cdfid, osSubdatasetName, &var);
     nd = 0;
     nc_inq_varndims ( cdfid, var, &nd );
 
-    poDS->paDimIds = (int *)CPLCalloc(nd, sizeof( int ) );
-    poDS->panBandDimPos = ( int * ) CPLCalloc( nd, sizeof( int ) );
+    paDimIds = (int *)CPLCalloc(nd, sizeof( int ) );
+    panBandDimPos = ( int * ) CPLCalloc( nd, sizeof( int ) );
 
-    nc_inq_vardimid( cdfid, var, poDS->paDimIds );
+    nc_inq_vardimid( cdfid, var, paDimIds );
 	
 /* -------------------------------------------------------------------- */
 /*      Check fi somebody tried to pass a variable with less than 2D    */
 /* -------------------------------------------------------------------- */
     if ( nd < 2 ) {
-        CPLFree( poDS->paDimIds );
-        CPLFree( poDS->panBandDimPos );
+        CPLFree( paDimIds );
+        CPLFree( panBandDimPos );
         delete poDS;
         return NULL;
     }
@@ -2154,25 +3951,25 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get X dimensions information                                    */
 /* -------------------------------------------------------------------- */
-    poDS->nDimXid = poDS->paDimIds[nd-1];
-    nc_inq_dimlen ( cdfid, poDS->nDimXid, &poDS->xdim );
-    poDS->nRasterXSize = poDS->xdim;
+    poDS->nXDimID = paDimIds[nd-1];
+    nc_inq_dimlen ( cdfid, poDS->nXDimID, &xdim );
+    poDS->nRasterXSize = xdim;
 
 /* -------------------------------------------------------------------- */
 /*      Get Y dimension information                                     */
 /* -------------------------------------------------------------------- */
-    poDS->nDimYid = poDS->paDimIds[nd-2];
-    nc_inq_dimlen ( cdfid, poDS->nDimYid, &poDS->ydim );
-    poDS->nRasterYSize = poDS->ydim;
+    poDS->nYDimID = paDimIds[nd-2];
+    nc_inq_dimlen ( cdfid, poDS->nYDimID, &ydim );
+    poDS->nRasterYSize = ydim;
 
 
     for( j=0,k=0; j < nd; j++ ){
-        if( poDS->paDimIds[j] == poDS->nDimXid ){ 
-            poDS->panBandDimPos[0] = j;         // Save Position of XDim
+        if( paDimIds[j] == poDS->nXDimID ){ 
+            panBandDimPos[0] = j;         // Save Position of XDim
             k++;
         }
-        if( poDS->paDimIds[j] == poDS->nDimYid ){
-            poDS->panBandDimPos[1] = j;         // Save Position of YDim
+        if( paDimIds[j] == poDS->nYDimID ){
+            panBandDimPos[1] = j;         // Save Position of YDim
             k++;
         }
     }
@@ -2180,14 +3977,16 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      X and Y Dimension Ids were not found!                           */
 /* -------------------------------------------------------------------- */
     if( k != 2 ) {
-        CPLFree( poDS->paDimIds );
-        CPLFree( poDS->panBandDimPos );
+        CPLFree( paDimIds );
+        CPLFree( panBandDimPos );
         return NULL;
     }
 	    
 /* -------------------------------------------------------------------- */
 /*      Read Metadata for this variable                                 */
 /* -------------------------------------------------------------------- */
+/* should disable as is also done at band level, except driver needs the 
+   variables as metadata (e.g. projection) */
     poDS->ReadAttributes( cdfid, var );
 	
 /* -------------------------------------------------------------------- */
@@ -2195,31 +3994,45 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     
     for( j=0; j < dim_count; j++ ){
-        nc_inq_dimname( cdfid, j, poDS->papszDimName[j] );
+        nc_inq_dimname( cdfid, j, szTemp );
+        poDS->papszDimName.AddString( szTemp );
         status = nc_inq_varid( cdfid, poDS->papszDimName[j], &nDimID );
         if( status == NC_NOERR ) {
             poDS->ReadAttributes( cdfid, nDimID );
         }
     }
 
-    poDS->SetProjection( var );
+/* -------------------------------------------------------------------- */
+/*      Set projection info                                             */
+/* -------------------------------------------------------------------- */
+    poDS->SetProjectionFromVar( var );
+
+    /* override bottom-up with GDAL_NETCDF_BOTTOMUP config option */
+    const char *pszValue = CPLGetConfigOption( "GDAL_NETCDF_BOTTOMUP", NULL );
+    if ( pszValue ) {
+        poDS->bBottomUp = CSLTestBoolean( pszValue ) != FALSE; 
+        CPLDebug( "GDAL_netCDF", 
+                  "set bBottomUp=%d because GDAL_NETCDF_BOTTOMUP=%s",
+                  poDS->bBottomUp, pszValue );
+    }
+
     poDS->SetMetadata( poDS->papszMetadata );
 
 /* -------------------------------------------------------------------- */
 /*      Create bands                                                    */
 /* -------------------------------------------------------------------- */
-    poDS->panBandZLev = (int *)CPLCalloc( nd-2, sizeof( int ) );
+    panBandZLev = (int *)CPLCalloc( nd-2, sizeof( int ) );
     
     nTotLevCount = 1;
     if ( dim_count > 2 ) {
         nDim=2;
         for( j=0; j < nd; j++ ){
-            if( ( poDS->paDimIds[j] != poDS->nDimXid ) && 
-                ( poDS->paDimIds[j] != poDS->nDimYid ) ){
-                nc_inq_dimlen ( cdfid, poDS->paDimIds[j], &lev_count );
+            if( ( paDimIds[j] != poDS->nXDimID ) && 
+                ( paDimIds[j] != poDS->nYDimID ) ){
+                nc_inq_dimlen ( cdfid, paDimIds[j], &lev_count );
                 nTotLevCount *= lev_count;
-                poDS->panBandZLev[ nDim-2 ] = lev_count;
-                poDS->panBandDimPos[ nDim++ ] = j;  //Save Position of ZDim
+                panBandZLev[ nDim-2 ] = lev_count;
+                panBandDimPos[ nDim++ ] = j;  //Save Position of ZDim
             }
         }
     }
@@ -2231,15 +4044,16 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
         netCDFRasterBand *poBand =
             new netCDFRasterBand(poDS, var, nDim, lev,
-                                 poDS->panBandZLev, poDS->panBandDimPos, i+1 );
+                                 panBandZLev, panBandDimPos, 
+                                 paDimIds, i+1 );
 
         poDS->SetBand( i+1, poBand );
         i++;
     } 
 
-    CPLFree( poDS->paDimIds );
-    CPLFree( poDS->panBandDimPos );
-    CPLFree( poDS->panBandZLev );
+    CPLFree( paDimIds );
+    CPLFree( panBandDimPos );
+    CPLFree( panBandZLev );
     
     poDS->nBands = i;
 
@@ -2248,15 +4062,15 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
-    if( poDS->bTreatAsSubdataset )
+    if( bTreatAsSubdataset )
     {
         poDS->SetPhysicalFilename( poDS->osFilename );
-        poDS->SetSubdatasetName( poDS->osSubdatasetName );
+        poDS->SetSubdatasetName( osSubdatasetName );
     }
     
     poDS->TryLoadXML();
 
-    if( poDS->bTreatAsSubdataset )
+    if( bTreatAsSubdataset )
         poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
     else
         poDS->oOvManager.Initialize( poDS, poDS->osFilename );
@@ -2273,39 +4087,30 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 void CopyMetadata( void  *poDS, int fpImage, int CDFVarID ) {
 
-/* -------------------------------------------------------------------- */
-/*      Add CF-1.0 Conventions Global attribute                         */
-/* -------------------------------------------------------------------- */
     char       **papszMetadata;
     char       **papszFieldData;
     const char *pszField;
-    char       szMetaName[ MAX_STR_LEN ];
-    char       szMetaValue[ MAX_STR_LEN ];
-    int        nDataLength;
+    char       szMetaName[ NCDF_MAX_STR_LEN ];
+    char       szMetaValue[ NCDF_MAX_STR_LEN ];
+    char       szTemp[ NCDF_MAX_STR_LEN ];
     int        nItems;
+    int        bCopyItem;
 
-/* -------------------------------------------------------------------- */
-/*      Global metadata are set with NC_GLOBAL as the varid             */
-/* -------------------------------------------------------------------- */
-    
-    if( CDFVarID == NC_GLOBAL ) {
+    /* Remove the following band meta but set them later from band data */
+    const char *papszIgnore[] = { CF_ADD_OFFSET, CF_SCALE_FACTOR, 
+                                  "valid_range", "_Unsigned", 
+                                  _FillValue, NULL };
 
+    if( CDFVarID == NC_GLOBAL ) {
         papszMetadata = GDALGetMetadata( (GDALDataset *) poDS,"");
-
-        nc_put_att_text( fpImage, 
-                         NC_GLOBAL, 
-                         "Conventions", 
-                         6,
-                         "CF-1.0" );
     } else {
-
         papszMetadata = GDALGetMetadata( (GDALRasterBandH) poDS, NULL );
-
     }
 
     nItems = CSLCount( papszMetadata );             
     
     for(int k=0; k < nItems; k++ ) {
+        bCopyItem = TRUE;
         pszField = CSLGetField( papszMetadata, k );
         papszFieldData = CSLTokenizeString2 (pszField, "=", 
                                              CSLT_HONOURSTRINGS );
@@ -2313,49 +4118,289 @@ void CopyMetadata( void  *poDS, int fpImage, int CDFVarID ) {
             strcpy( szMetaName,  papszFieldData[ 0 ] );
             strcpy( szMetaValue, papszFieldData[ 1 ] );
 
-/* -------------------------------------------------------------------- */
-/*      netCDF attributes do not like the '#' character.                */
-/* -------------------------------------------------------------------- */
+            /* Fix various issues with metadata translation */ 
+            if( CDFVarID == NC_GLOBAL ) {
+                /* Remove NC_GLOBAL prefix for netcdf global Metadata */ 
+                if( strncmp( szMetaName, "NC_GLOBAL#", 10 ) == 0 ) {
+                    strcpy( szTemp, szMetaName+10 );
+                    strcpy( szMetaName, szTemp );
+                } 
+                /* GDAL Metadata renamed as GDAL-[meta] */
+                else if ( strstr( szMetaName, "#" ) == NULL ) {
+                    strcpy( szTemp, "GDAL_" );
+                    strcat( szTemp, szMetaName );
+                    strcpy( szMetaName, szTemp );
+                }
+                /* Keep time, lev and depth information for safe-keeping */
+                /* Time and vertical coordinate handling need improvements */
+                else if( strncmp( szMetaName, "time#", 5 ) == 0 ) {
+                    szMetaName[4] = '-';
+                }
+                else if( strncmp( szMetaName, "lev#", 4 ) == 0 ) {
+                    szMetaName[3] = '-';
+                }
+                else if( strncmp( szMetaName, "depth#", 6 ) == 0 ) {
+                    szMetaName[5] = '-';
+                }
+                /* Only copy data without # (previously all data was copied)  */
+                if ( strstr( szMetaName, "#" ) != NULL ) {   
+                    bCopyItem = FALSE;
+                }
+                /* netCDF attributes do not like the '#' character. */
+                // for( unsigned int h=0; h < strlen( szMetaName ) -1 ; h++ ) {
+                //     if( szMetaName[h] == '#' ) szMetaName[h] = '-'; 
+                // }
+            }
+            else {
+                /* for variables, don't copy varname */
+                if ( strncmp( szMetaName, "NETCDF_VARNAME", 14) == 0 ) 
+                    bCopyItem = FALSE;
+                /* Don't copy band statistics */
+                else if ( strncmp( szMetaName, "STATISTICS_", 11) == 0 ) 
+                    bCopyItem = FALSE;
+                if ( CSLFindString( (char **)papszIgnore, szMetaName ) != -1 ) {
+                    bCopyItem = FALSE;
+                }
+            }
 
-            for( unsigned int h=0; h < strlen( szMetaName ) -1 ; h++ ) {
-                if( szMetaName[h] == '#' ) szMetaName[h] = '-'; 
+            if ( bCopyItem ) {
+                if ( NCDFPutAttr( fpImage, CDFVarID,szMetaName, 
+                                  szMetaValue ) != CE_None )
+                    CPLDebug( "GDAL_netCDF", "NCDFPutAttr(%d, %d, %s, %s) failed", 
+                              fpImage, CDFVarID,szMetaName, szMetaValue );
             }
-	    
-            nDataLength = strlen( szMetaValue );
-            nc_put_att_text( fpImage, 
-                             CDFVarID, 
-                             szMetaName,
-                             nDataLength,
-                             szMetaValue );
 
-	    
         }
         CSLDestroy( papszFieldData );
+    }
+
+    /* Set add_offset and scale_factor here if present */
+    if( CDFVarID != NC_GLOBAL ) {
+
+        int bGotAddOffset, bGotScale;
+        GDALRasterBandH poRB = (GDALRasterBandH) poDS;
+        double dfAddOffset = GDALGetRasterOffset( poRB , &bGotAddOffset );
+        double dfScale = GDALGetRasterScale( poRB, &bGotScale );
+
+        if ( bGotAddOffset && dfAddOffset != 0.0 && bGotScale && dfScale != 1.0 ) {
+            GDALSetRasterOffset( poRB, dfAddOffset );
+            GDALSetRasterScale( poRB, dfScale );
+        }
+
+    }
+
+}
+
+/*
+Driver options:
+
+FORMAT=NC/NC2/NC4/NC4C (COMPRESS=DEFLATE sets FORMAT=NC4C)
+COMPRESS=NONE/DEFLATE (default: NONE)
+ZLEVEL=[1-9] (default: 1)
+WRITE_BOTTOMUP=YES/NO (default: YES)
+WRITE_GDAL_TAGS=YES/NO (default: YES)
+WRITE_LONLAT=YES/NO/IF_NEEDED (default: YES for geographic, NO for projected)
+TYPE_LONLAT=float/double (default: double for geographic, float for projected)
+PIXELTYPE=DEFAULT/SIGNEDBYTE (use SIGNEDBYTE to get a signed Byte Band)
+
+Config Options:
+
+GDAL_NETCDF_BOTTOMUP=YES/NO overrides bottom-up value on import
+
+*/
+
+/************************************************************************/
+/*                            CreateLL()                                */
+/*                                                                      */
+/*      Shared functionality between netCDFDataset::Create() and        */
+/*      netCDF::CreateCopy() for creating netcdf file based on a set of */
+/*      options and a configuration.                                    */
+/************************************************************************/
+
+netCDFDataset *
+netCDFDataset::CreateLL( const char * pszFilename,
+                         int nXSize, int nYSize, int nBands,
+                         char ** papszOptions )
+{
+    int status = NC_NOERR;
+    netCDFDataset *poDS;
+    
+    poDS = new netCDFDataset();
+    poDS->nRasterXSize = nXSize;
+    poDS->nRasterYSize = nYSize;
+    poDS->eAccess = GA_Update;
+    poDS->osFilename = pszFilename;
+
+    /* from gtiff driver, is this ok? */
+    /*
+    poDS->nBlockXSize = nXSize;
+    poDS->nBlockYSize = 1;
+    poDS->nBlocksPerBand =
+        ((nYSize + poDS->nBlockYSize - 1) / poDS->nBlockYSize)
+        * ((nXSize + poDS->nBlockXSize - 1) / poDS->nBlockXSize);
+        */
 
+    /* process options */
+    poDS->papszCreationOptions = CSLDuplicate( papszOptions );
+    poDS->ProcessCreationOptions( );
+
+/* -------------------------------------------------------------------- */
+/*      Create the dataset.                                             */
+/* -------------------------------------------------------------------- */
+    status = nc_create( pszFilename, poDS->nCreateMode,  &(poDS->cdfid) );
+
+    /* put into define mode */
+    poDS->SetDefineMode(TRUE);
+
+    if( status != NC_NOERR )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Unable to create netCDF file %s (Error code %d): %s .\n", 
+                  pszFilename, status, nc_strerror(status) );
+        delete poDS;
+        return NULL;
     }
+
+/* -------------------------------------------------------------------- */
+/*      Define dimensions                                               */
+/* -------------------------------------------------------------------- */
+    poDS->papszDimName.AddString( NCDF_DIMNAME_Y );
+    poDS->papszDimName.AddString( NCDF_DIMNAME_X );
+
+    status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_X, nXSize, 
+                         &(poDS->nXDimID) );
+    NCDF_ERR(status);
+    CPLDebug( "GDAL_netCDF", "status nc_def_dim %s = %d, nXDimID = %d", 
+              NCDF_DIMNAME_X, status, poDS->nXDimID );   
+
+    status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_Y, nYSize, 
+                         &(poDS->nYDimID) );
+    NCDF_ERR(status);
+    CPLDebug( "GDAL_netCDF", "status nc_def_dim %s = %d, nYDimID = %d", 
+              NCDF_DIMNAME_Y, status, poDS->nYDimID );   
+
+    return poDS;
+
 }
+
 /************************************************************************/
-/*                             CreateCopy()                             */
+/*                            Create()                                  */
 /************************************************************************/
 
+GDALDataset *
+netCDFDataset::Create( const char * pszFilename,
+                       int nXSize, int nYSize, int nBands,
+                       GDALDataType eType,
+                       char ** papszOptions )
+{
+    netCDFDataset *poDS;
+
+    CPLDebug( "GDAL_netCDF", 
+              "\n=====\nnetCDFDataset::Create( %s, ... )\n", 
+              pszFilename );
+    
+    poDS =  netCDFDataset::CreateLL( pszFilename,
+                                     nXSize, nYSize, nBands,
+                                     papszOptions );
+
+    if ( ! poDS ) 
+        return NULL;
+
+    /* should we write signed or unsigned byte? */
+    /* TODO should this only be done in Create() */
+    poDS->bSignedData = TRUE;
+    const char *pszValue  =
+        CSLFetchNameValue( papszOptions, "PIXELTYPE" );
+    if( pszValue == NULL )
+        pszValue = "";
+    if( eType == GDT_Byte && ( ! EQUAL(pszValue,"SIGNEDBYTE") ) )
+        poDS->bSignedData = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Add Conventions, GDAL info and history                          */
+/* -------------------------------------------------------------------- */
+    NCDFAddGDALHistory( poDS->cdfid, pszFilename, "", "Create" );
+
+/* -------------------------------------------------------------------- */
+/*      Define bands                                                    */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 1; iBand <= nBands; iBand++ )
+    {
+        poDS->SetBand( iBand, new netCDFRasterBand( poDS, eType, iBand,
+                                                    poDS->bSignedData ) );
+    }
+
+    CPLDebug( "GDAL_netCDF", 
+              "netCDFDataset::Create( %s, ... ) done", 
+              pszFilename );
+/* -------------------------------------------------------------------- */
+/*      Return same dataset                                             */
+/* -------------------------------------------------------------------- */
+     return( poDS );
+
+}
 
-static GDALDataset*
-NCDFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                int bStrict, char ** papszOptions, 
-                GDALProgressFunc pfnProgress, void * pProgressData )
 
+template <class T>
+CPLErr  NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poBand,
+                      int nXSize, int nYSize,
+                      GDALProgressFunc pfnProgress, void * pProgressData )
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    int  bProgressive = FALSE;
-    int  iBand;
+    GDALDataType eDT = poSrcBand->GetRasterDataType();
+    CPLErr eErr = CE_None;
+    T *patScanline = (T *) CPLMalloc( nXSize * sizeof(T) );
+        
+    for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {                
+        eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
+                                    patScanline, nXSize, 1, eDT,
+                                    0,0);
+        if ( eErr == CE_None )
+            eErr = poBand->RasterIO( GF_Write, 0, iLine, nXSize, 1, 
+                                     patScanline, nXSize, 1, eDT,
+                                     0,0);
+
+        if ( ( nYSize>10 ) && ( iLine % (nYSize/10) == 1 ) ) {
+            pfnProgress( 1.0*iLine/nYSize , NULL, pProgressData );
+        }
+    }
+           
+    CPLFree( patScanline );
+
+    pfnProgress( 1.0, NULL, pProgressData );
+
+    return eErr;
+}
+
+
+/************************************************************************/
+/*                            CreateCopy()                              */
+/************************************************************************/
 
-    int  anBandDims[ NC_MAX_DIMS ];
-    int  anBandMap[  NC_MAX_DIMS ];
+GDALDataset*
+netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
+                           int bStrict, char ** papszOptions, 
+                           GDALProgressFunc pfnProgress, void * pProgressData )
+{
+    netCDFDataset *poDS;
+    void *pScaledProgress;
+    GDALDataType eDT;
+    CPLErr eErr = CE_None;
+    int nBands, nXSize, nYSize;
+    double adfGeoTransform[6];
+    const char *pszWKT;
+    int iBand;
+    
+    CPLDebug( "GDAL_netCDF", 
+              "\n=====\nnetCDFDataset::CreateCopy( %s, ... )\n", 
+              pszFilename );
 
-    int    bWriteGeoTransform = FALSE;
-    char  pszNetcdfProjection[ NC_MAX_NAME ];
+    nBands = poSrcDS->GetRasterCount();
+    nXSize = poSrcDS->GetRasterXSize();
+    nYSize = poSrcDS->GetRasterYSize();
+  
+/* -------------------------------------------------------------------- */
+/*      Check input bands for errors                                    */
+/* -------------------------------------------------------------------- */
 
     if (nBands == 0)
     {
@@ -2367,7 +4412,7 @@ NCDFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     for( iBand=1; iBand <= nBands; iBand++ )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand );
-        GDALDataType eDT = poSrcBand->GetRasterDataType();
+        eDT = poSrcBand->GetRasterDataType();
         if (eDT == GDT_Unknown || GDALDataTypeIsComplex(eDT))
         {
             CPLError( CE_Failure, CPLE_NotSupported, 
@@ -2379,789 +4424,1033 @@ NCDFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
-
-    bProgressive = CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE );
+    /* same as in Create() */
+    poDS = netCDFDataset::CreateLL( pszFilename,
+                                    nXSize, nYSize, nBands,
+                                    papszOptions );
+    if ( ! poDS ) 
+        return NULL;
 
 /* -------------------------------------------------------------------- */
-/*      Create the dataset.                                             */
+/*      Copy global metadata                                            */
+/*      Add Conventions, GDAL info and history                          */
 /* -------------------------------------------------------------------- */
-    int fpImage;
-    int status;
-    int nXDimID = 0;
-    int nYDimID = 0;
+    CopyMetadata((void *) poSrcDS, poDS->cdfid, NC_GLOBAL );
+    NCDFAddGDALHistory( poDS->cdfid, pszFilename,
+                        poSrcDS->GetMetadataItem("NC_GLOBAL#history",""),
+                        "CreateCopy" );
 
-    status = nc_create( pszFilename, NC_CLOBBER,  &fpImage );
+    pfnProgress( 0.1, NULL, pProgressData );
 
-    if( status != NC_NOERR )
-    {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create netCDF file %s.\n", 
-                  pszFilename );
-        return NULL;
-    }
+/* -------------------------------------------------------------------- */
+/*      Define Bands                                                    */
+/* -------------------------------------------------------------------- */
+    for( iBand=1; iBand <= nBands; iBand++ ) {
+        CPLDebug( "GDAL_netCDF", "creating band # %d/%d ",
+                  iBand,nBands );
 
-    GDALDataType eDT;
+        char szBandName[ NC_MAX_NAME ];
+        char szLongName[ NC_MAX_NAME ];
+        const char *tmpMetadata;
+        netCDFRasterBand *poBand;
+        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand );
+        eDT = poSrcBand->GetRasterDataType();
+
+        /* Get var name from NETCDF_VARNAME */
+        tmpMetadata = poSrcBand->GetMetadataItem("NETCDF_VARNAME");
+       	if( tmpMetadata != NULL) {
+            if( nBands > 1 ) sprintf(szBandName,"%s%d",tmpMetadata,iBand);
+            else strcpy( szBandName, tmpMetadata );
+            // poSrcBand->SetMetadataItem("NETCDF_VARNAME","");
+        }
+        else 
+            szBandName[0]='\0';
+        
+        /* Get long_name from <var>#long_name */
+        sprintf(szLongName,"%s#%s",
+                poSrcBand->GetMetadataItem("NETCDF_VARNAME"),
+                CF_LNG_NAME);
+        tmpMetadata = poSrcDS->GetMetadataItem(szLongName);
+        if( tmpMetadata != NULL) 
+            strcpy( szLongName, tmpMetadata);
+        else 
+            szLongName[0]='\0';
+
+        int bSignedData = TRUE;
+        if ( eDT == GDT_Byte ) {
+            /* GDAL defaults to unsigned bytes, but check if metadata says its
+               signed, as NetCDF can support this for certain formats. */
+            bSignedData = FALSE;
+            tmpMetadata = poSrcBand->GetMetadataItem("PIXELTYPE",
+                                                     "IMAGE_STRUCTURE");
+            if ( tmpMetadata && EQUAL(tmpMetadata,"SIGNEDBYTE") )
+                bSignedData = TRUE;
+        }
 
-    status = nc_def_dim( fpImage, "x", nXSize, &nXDimID );
-    CPLDebug( "GDAL_netCDF", "status nc_def_dim X = %d\n", status );
+        poBand = new netCDFRasterBand( poDS, eDT, iBand,
+                                       bSignedData,
+                                       szBandName, szLongName );
+        poDS->SetBand( iBand, poBand );
+        
+        /* Copy Metadata for band */
+        poBand->SetNoDataValue( poSrcBand->GetNoDataValue(0) );
+        CopyMetadata( (void *) GDALGetRasterBand( poSrcDS, iBand ), 
+                      poDS->cdfid, poBand->nZId );
+        
+    }
 
-    status = nc_def_dim( fpImage, "y", nYSize, &nYDimID );
-    CPLDebug( "GDAL_netCDF", "status nc_def_dim Y = %d\n", status );
+    pfnProgress( 0.2, NULL, pProgressData );
 
-    CPLDebug( "GDAL_netCDF", "nYDimID = %d\n", nXDimID );
-    CPLDebug( "GDAL_netCDF", "nXDimID = %d\n", nYDimID );
-    CPLDebug( "GDAL_netCDF", "nXSize = %d\n", nXSize );
-    CPLDebug( "GDAL_netCDF", "nYSize = %d\n", nYSize );
+/* -------------------------------------------------------------------- */
+/*      Copy GeoTransform and Projection                                */
+/* -------------------------------------------------------------------- */
+    int bGotGeoTransform = FALSE;
+    eErr = poSrcDS->GetGeoTransform( adfGeoTransform );
+    if ( eErr == CE_None ) {
+        poDS->SetGeoTransform( adfGeoTransform );
+        /* disable AddProjectionVars() from being called */
+        bGotGeoTransform = TRUE;
+        poDS->bSetGeoTransform = FALSE;
+    }
 
+    pszWKT = poSrcDS->GetProjectionRef( );
+    if ( pszWKT ) {
+        poDS->SetProjection( pszWKT );
+        /* now we can call AddProjectionVars() directly */
+        poDS->bSetGeoTransform = bGotGeoTransform;
+        pScaledProgress = GDALCreateScaledProgress( 0.20, 0.50, pfnProgress, 
+                                                    pProgressData );
+        poDS->AddProjectionVars( GDALScaledProgress, pScaledProgress );
+        GDALDestroyScaledProgress( pScaledProgress );
 
-    CopyMetadata((void *) poSrcDS, fpImage, NC_GLOBAL );
+    }
 
+    pfnProgress( 0.5, NULL, pProgressData );
+    
 /* -------------------------------------------------------------------- */
-/*      Set Projection for netCDF data CF-1 Convention                  */
+/*      Write Bands                                                     */
 /* -------------------------------------------------------------------- */
+    /* make sure we are in data mode */
+    poDS->SetDefineMode( FALSE );
 
-    OGRSpatialReference oSRS;
-    char *pszWKT = (char *) poSrcDS->GetProjectionRef();
-
+    double dfTemp,dfTemp2;
+    dfTemp = dfTemp2 = 0.5;
 
-    if( pszWKT != NULL )
-        oSRS.importFromWkt( &pszWKT );
+    for( iBand=1; iBand <= nBands; iBand++ ) {
+        
+        dfTemp2 = dfTemp + 0.4/nBands; 
+        pScaledProgress = 
+            GDALCreateScaledProgress( dfTemp, dfTemp2,
+                                      pfnProgress, pProgressData );
+        dfTemp = dfTemp2;
 
-    if( oSRS.IsGeographic() ) {
+        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand );
 
-        int status;
-        int i;
-        int NCDFVarID;
+        /* new */
+        GDALDataType eDT;
+        CPLErr eErr = CE_None;
 
-        double dfNN=0.0;
-        double dfSN=0.0;
-        double dfEE=0.0;
-        double dfWE=0.0;
-        double adfGeoTransform[6];
-        char   szGeoTransform[ MAX_STR_LEN ];
-        char   szTemp[ MAX_STR_LEN ];
+        CPLDebug( "GDAL_netCDF", "copying band data # %d/%d ",
+                  iBand,nBands );
 
+        // hBand = GDALGetRasterBand( poSrcDS, i );
+        GDALRasterBand *poBand = poDS->GetRasterBand( iBand );
+        eDT = poSrcBand->GetRasterDataType();
+        eErr = CE_None;
 
 /* -------------------------------------------------------------------- */
-/*      Copy GeoTransform array from source                             */
+/*      Copy Band data                                                  */
 /* -------------------------------------------------------------------- */
-        poSrcDS->GetGeoTransform( adfGeoTransform );
-        bWriteGeoTransform = TRUE;
-
-        *szGeoTransform = '\0';
-        for( i=0; i<6; i++ ) {
-            sprintf( szTemp, "%g ",
-                     adfGeoTransform[i] );
-            strcat( szGeoTransform, szTemp );
+        if( eDT == GDT_Byte ) {
+            CPLDebug( "GDAL_netCDF", "GByte Band#%d", iBand );
+            NCDFCopyBand<GByte>( poSrcBand, poBand, nXSize, nYSize,
+                                 GDALScaledProgress, pScaledProgress );
+        } 
+        else if( ( eDT == GDT_UInt16 ) || ( eDT == GDT_Int16 ) ) {
+            CPLDebug( "GDAL_netCDF", "GInt16 Band#%d", iBand );
+            NCDFCopyBand<GInt16>( poSrcBand, poBand, nXSize, nYSize,
+                                 GDALScaledProgress, pScaledProgress );
+        } 
+        else if( (eDT == GDT_UInt32) || (eDT == GDT_Int32) ) {
+            CPLDebug( "GDAL_netCDF", "GInt16 Band#%d", iBand );
+            NCDFCopyBand<GInt32>( poSrcBand, poBand, nXSize, nYSize,
+                                 GDALScaledProgress, pScaledProgress );
+        }
+        else if( (eDT == GDT_Float32) ) {
+            CPLDebug( "GDAL_netCDF", "float Band#%d", iBand);
+            NCDFCopyBand<float>( poSrcBand, poBand, nXSize, nYSize,
+                                 GDALScaledProgress, pScaledProgress );
+        }
+        else if( (eDT == GDT_Float64) ) {
+            CPLDebug( "GDAL_netCDF", "double Band#%d", iBand);
+            NCDFCopyBand<double>( poSrcBand, poBand, nXSize, nYSize,
+                                 GDALScaledProgress, pScaledProgress );
+        }
+        else {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "The NetCDF driver does not support GDAL data type %d",
+                      eDT );
         }
-        CPLDebug( "GDAL_netCDF", "szGeoTranform = %s", szGeoTransform );
-        strcpy( pszNetcdfProjection, "GDAL_Geographics" );
+        
+        GDALDestroyScaledProgress( pScaledProgress );
 
-        status = nc_def_var( fpImage, 
-                             pszNetcdfProjection, 
-                             NC_CHAR, 
-                             0, NULL, &NCDFVarID );
-	
-        dfNN = adfGeoTransform[3];
-        dfSN = ( adfGeoTransform[5] * nYSize ) + dfNN;
-        dfWE = adfGeoTransform[0];
-        dfEE = ( adfGeoTransform[1] * nXSize ) + dfWE;
-
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID, 
-                                    "Northernmost_Northing",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfNN );
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID, 
-                                    "Southernmost_Northing",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfSN );
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID,
-                                    "Easternmost_Easting",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfEE );
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID,
-                                    "Westernmost_Easting",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfWE );
-        pszWKT = (char *) poSrcDS->GetProjectionRef() ;
-
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         "spatial_ref",
-                         strlen( pszWKT ),
-                         pszWKT );
-
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         "GeoTransform",
-                         strlen( szGeoTransform ),
-                         szGeoTransform );
-
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         GRD_MAPPING_NAME,
-                         30,
-                         "Geographics Coordinate System" );
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         LNG_NAME,
-                         14,
-                         "Grid_latitude" );
     }
 
-    if( oSRS.IsProjected() )
-    {
-        const char *pszParamStr, *pszParamVal;
-        const OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
-        int status;
-        int i;
-        int NCDFVarID;
-        const char  *pszProjection;
-        double dfNN=0.0;
-        double dfSN=0.0;
-        double dfEE=0.0;
-        double dfWE=0.0;
-        double adfGeoTransform[6];
-        char   szGeoTransform[ MAX_STR_LEN ];
-        char   szTemp[ MAX_STR_LEN ];
+/* -------------------------------------------------------------------- */
+/*      Cleanup and close.                                              */
+/* -------------------------------------------------------------------- */
+    delete( poDS );
+// CPLFree(pszProj4Defn );
+ 
+    pfnProgress( 0.95, NULL, pProgressData );
 
-        poSrcDS->GetGeoTransform( adfGeoTransform );
+/* -------------------------------------------------------------------- */
+/*      Re-open dataset, and copy any auxilary pam information.         */
+/*      Disable PAM, at least temporarily. See bug #4244                */
+/* -------------------------------------------------------------------- */
+    poDS = (netCDFDataset *) GDALOpen( pszFilename, GA_ReadOnly );
 
-        *szGeoTransform = '\0';
-        for( i=0; i<6; i++ ) {
-            sprintf( szTemp, "%g ",
-                     adfGeoTransform[i] );
-            strcat( szGeoTransform, szTemp );
-        }
+    // if( poDS )
+    //     poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+    
+    pfnProgress( 1.0, NULL, pProgressData );
 
-        CPLDebug( "GDAL_netCDF", "szGeoTranform = %s", szGeoTransform );
+    return poDS;
+}
 
-        pszProjection = oSRS.GetAttrValue( "PROJECTION" );
-        bWriteGeoTransform = TRUE;
 
+/* note: some logic depends on bIsProjected and bIsGeoGraphic */
+/* which may not be known when Create() is called, see AddProjectionVars() */
+void
+netCDFDataset::ProcessCreationOptions( )
+{ 
+    const char *pszValue;
 
-        for(i=0; poNetcdfSRS[i].netCDFSRS != NULL; i++ ) {
-            if( EQUAL( poNetcdfSRS[i].SRS, pszProjection ) ) {
-                CPLDebug( "GDAL_netCDF", "PROJECTION = %s", 
-                          poNetcdfSRS[i].netCDFSRS);
-                strcpy( pszNetcdfProjection, poNetcdfSRS[i].netCDFSRS );
+    /* File format */
+    nFormat = NCDF_FORMAT_NC;
+    pszValue = CSLFetchNameValue( papszCreationOptions, "FORMAT" );
+    if ( pszValue != NULL ) {
+        if ( EQUAL( pszValue, "NC" ) ) {
+            nFormat = NCDF_FORMAT_NC;
+        }
+#ifdef NETCDF_HAS_NC2
+        else if ( EQUAL( pszValue, "NC2" ) ) {
+            nFormat = NCDF_FORMAT_NC2;
+        }
+#endif
+#ifdef NETCDF_HAS_NC4
+        else if ( EQUAL( pszValue, "NC4" ) ) {
+            nFormat = NCDF_FORMAT_NC4;
+        }    
+        else if ( EQUAL( pszValue, "NC4C" ) ) {
+            nFormat = NCDF_FORMAT_NC4C;
+        }    
+#endif
+        else {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "FORMAT=%s in not supported, using the default NC format.", pszValue );        
+        }
+    }
 
-                break;
+    /* compression only available for NC4 */
+#ifdef NETCDF_HAS_NC4
+
+    /* COMPRESS option */
+    pszValue = CSLFetchNameValue( papszCreationOptions, "COMPRESS" );
+    if ( pszValue != NULL ) {
+        if ( EQUAL( pszValue, "NONE" ) ) {
+            nCompress = NCDF_COMPRESS_NONE;
+        }       
+        else if ( EQUAL( pszValue, "DEFLATE" ) ) {
+            nCompress = NCDF_COMPRESS_DEFLATE;
+            if ( !((nFormat == NCDF_FORMAT_NC4) || (nFormat == NCDF_FORMAT_NC4C)) ) {
+                CPLError( CE_Warning, CPLE_IllegalArg,
+                          "NOTICE: Format set to NC4C because compression is set to DEFLATE." );
+                nFormat = NCDF_FORMAT_NC4C;
             }
         }
+        else {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "COMPRESS=%s is not supported.", pszValue );
+        }
+    }
 
-        status = nc_def_var( fpImage, 
-                             poNetcdfSRS[i].netCDFSRS, 
-                             NC_CHAR, 
-                             0, NULL, &NCDFVarID );
-
-        dfNN = adfGeoTransform[3];
-        dfSN = ( adfGeoTransform[5] * nYSize ) + dfNN;
-        dfWE = adfGeoTransform[0];
-        dfEE = ( adfGeoTransform[1] * nXSize ) + dfWE;
-
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID, 
-                                    "Northernmost_Northing",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfNN );
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID, 
-                                    "Southernmost_Northing",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfSN );
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID,
-                                    "Easternmost_Easting",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfEE );
-        status = nc_put_att_double( fpImage,
-                                    NCDFVarID,
-                                    "Westernmost_Easting",
-                                    NC_DOUBLE,
-                                    1,
-                                    &dfWE );
-        pszWKT = (char *) poSrcDS->GetProjectionRef() ;
-
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         "spatial_ref",
-                         strlen( pszWKT ),
-                         pszWKT );
-
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         "GeoTransform",
-                         strlen( szGeoTransform ),
-                         szGeoTransform );
-
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         GRD_MAPPING_NAME,
-                         strlen( pszNetcdfProjection ),
-                         pszNetcdfProjection );
-
-
-        for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
+    /* ZLEVEL option */
+    pszValue = CSLFetchNameValue( papszCreationOptions, "ZLEVEL" );
+    if( pszValue != NULL )
+    {
+        nZLevel =  atoi( pszValue );
+        if (!(nZLevel >= 1 && nZLevel <= 9))
         {
-            const OGR_SRSNode    *poNode;
-            float fValue;
-
-            poNode = poPROJCS->GetChild( iChild );
-            if( !EQUAL(poNode->GetValue(),"PARAMETER") 
-                || poNode->GetChildCount() != 2 )
-                continue;
-
-/* -------------------------------------------------------------------- */
-/*      Look for projection attributes                                  */
-/* -------------------------------------------------------------------- */
-            pszParamStr = poNode->GetChild(0)->GetValue();
-            pszParamVal = poNode->GetChild(1)->GetValue();
-	    
-
-            for(i=0; poNetcdfSRS[i].netCDFSRS != NULL; i++ ) {
-                if( EQUAL( poNetcdfSRS[i].SRS, pszParamStr ) ) {
-                    CPLDebug( "GDAL_netCDF", "%s = %s", 
-                              poNetcdfSRS[i].netCDFSRS, 
-                              pszParamVal );
-                    break;
-                }
-            }
-/* -------------------------------------------------------------------- */
-/*      Write Projection attribute                                      */
-/* -------------------------------------------------------------------- */
-            sscanf( pszParamVal, "%f", &fValue );
-            if( poNetcdfSRS[i].netCDFSRS != NULL ) {
-                nc_put_att_float( fpImage, 
-                                  NCDFVarID, 
-                                  poNetcdfSRS[i].netCDFSRS, 
-                                  NC_FLOAT,
-                                  1,
-                                  &fValue );
-
-            }	
+            CPLError( CE_Warning, CPLE_IllegalArg, 
+                    "ZLEVEL=%s value not recognised, ignoring.",
+                    pszValue );
+            nZLevel = NCDF_DEFLATE_LEVEL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize Band Map                                             */
-/* -------------------------------------------------------------------- */
-
-    for(int j=1; j <= nBands; j++ ) {
-        anBandMap[j-1]=j;
+#endif
+
+    /* set nCreateMode based on nFormat */
+    switch ( nFormat ) {        
+#ifdef NETCDF_HAS_NC2
+        case NCDF_FORMAT_NC2:
+            nCreateMode = NC_CLOBBER|NC_64BIT_OFFSET;
+            break;
+#endif
+#ifdef NETCDF_HAS_NC4
+        case NCDF_FORMAT_NC4:
+            nCreateMode = NC_CLOBBER|NC_NETCDF4;
+            break;
+        case NCDF_FORMAT_NC4C:
+            nCreateMode = NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL;
+            break;
+#endif
+        case NCDF_FORMAT_NC:
+        default:
+            nCreateMode = NC_CLOBBER;
+            break;
     }
-    
-/* -------------------------------------------------------------------- */
-/*      Create netCDF variable                                          */
-/* -------------------------------------------------------------------- */
-
-    for( int i=1; i <= nBands; i++ ) {
 
-        char      szBandName[ NC_MAX_NAME ];
-        GByte     *pabScanline  = NULL;
-        GInt16    *pasScanline  = NULL;
-        GInt32    *panScanline  = NULL;
-        float     *pafScanline  = NULL;
-        double    *padScanline  = NULL;
-        int       NCDFVarID;
-        size_t    start[ GDALNBDIM ];
-        size_t    count[ GDALNBDIM ];
-        size_t    nBandNameLen;
-        double    dfNoDataValue;
-        unsigned char      cNoDataValue;
-        float     fNoDataValue;
-        int       nlNoDataValue;
-        short     nsNoDataValue;
-        GDALRasterBandH	hBand;
+    CPLDebug( "GDAL_netCDF", 
+              "file options: format=%d compress=%d zlevel=%d",
+              nFormat, nCompress, nZLevel );
 
-        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( i );
-        hBand = GDALGetRasterBand( poSrcDS, i );
-
-        sprintf( szBandName, "Band%d", i );
+}
 
-        eDT = poSrcDS->GetRasterBand(i)->GetRasterDataType();
-        anBandDims[0] = nYDimID;
-        anBandDims[1] = nXDimID;
-        CPLErr      eErr = CE_None;
+int netCDFDataset::DefVarDeflate( int nVarId, int bChunking )
+{
+#ifdef NETCDF_HAS_NC4
+    if ( nCompress == NCDF_COMPRESS_DEFLATE ) {                         
+        // must set chunk size to avoid huge performace hit (set bChunking=TRUE)             
+        // perhaps another solution it to change the chunk cache?
+        // http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#Chunk-Cache   
+        // TODO make sure this is ok
+        CPLDebug( "GDAL_netCDF", 
+                  "DefVarDeflate( %d, %d ) nZlevel=%d",
+                  nVarId, bChunking, nZLevel );
+        status = nc_def_var_deflate(cdfid,nVarId,1,1,nZLevel);
+        NCDF_ERR(status);
+        if ( (status == NC_NOERR) && bChunking ) {
+            size_t chunksize[] = { 1, nRasterXSize };                   
+            CPLDebug( "GDAL_netCDF", 
+                      "DefVarDeflate() chunksize={%ld, %ld}",
+                      chunksize[0], chunksize[1] );
+            status = nc_def_var_chunking( cdfid, nVarId,          
+                                          NC_CHUNKED, chunksize );
+            NCDF_ERR(status);
+        }
+        return status;
+    } 
+#endif
+    return NC_NOERR;
+}
 
-        dfNoDataValue = poSrcBand->GetNoDataValue(0);
 
-        if( eDT == GDT_Byte ) {
-            CPLDebug( "GDAL_netCDF", "%s = GDT_Byte ", szBandName );
+/************************************************************************/
+/*                          GDALRegister_netCDF()                       */
+/************************************************************************/
 
-            status = nc_def_var( fpImage, szBandName, NC_BYTE, 
-                                 GDALNBDIM, anBandDims, &NCDFVarID );
+void GDALRegister_netCDF()
 
+{
+    if (! GDAL_CHECK_VERSION("netCDF driver"))
+        return;
 
-/* -------------------------------------------------------------------- */
-/*      Write data line per line                                        */
-/* -------------------------------------------------------------------- */
+    if( GDALGetDriverByName( "netCDF" ) == NULL )
+    {
+        GDALDriver	*poDriver;
+        char szCreateOptions[3072];
 
-            pabScanline = (GByte *) CPLMalloc( nBands * nXSize );
-            for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {
+        poDriver = new GDALDriver( );
 
 /* -------------------------------------------------------------------- */
-/*      Read data from band i                                           */
-/* -------------------------------------------------------------------- */
-                eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                            pabScanline, nXSize, 1, GDT_Byte,
-                                            0,0);
+/*      Build full creation option list.                                */
+/* -------------------------------------------------------------------- */
+    sprintf( szCreateOptions, "%s", 
+"<CreationOptionList>"
+"   <Option name='FORMAT' type='string-select' default='NC'>"
+"     <Value>NC</Value>"
+#ifdef NETCDF_HAS_NC2
+"     <Value>NC2</Value>"
+#endif
+#ifdef NETCDF_HAS_NC4
+"     <Value>NC4</Value>"
+"     <Value>NC4C</Value>"
+#endif
+"   </Option>"
+#ifdef NETCDF_HAS_NC4
+"   <Option name='COMPRESS' type='string-select' default='NONE'>"
+"     <Value>NONE</Value>"
+"     <Value>DEFLATE</Value>"
+"   </Option>"
+"   <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='1'/>"
+#endif
+"   <Option name='WRITE_BOTTOMUP' type='boolean' default='YES'>"
+"   </Option>"
+"   <Option name='WRITE_GDAL_TAGS' type='boolean' default='YES'>"
+"   </Option>"
+"   <Option name='WRITE_LONLAT' type='string-select'>"
+"     <Value>YES</Value>"
+"     <Value>NO</Value>"
+"     <Value>IF_NEEDED</Value>"
+"   </Option>"
+"   <Option name='TYPE_LONLAT' type='string-select'>"
+"     <Value>float</Value>"
+"     <Value>double</Value>"
+"   </Option>"
+"   <Option name='PIXELTYPE' type='string-select' description='only used in Create()'>"
+"       <Value>DEFAULT</Value>"
+"       <Value>SIGNEDBYTE</Value>"
+"   </Option>"
+"</CreationOptionList>" );
 
+        
 /* -------------------------------------------------------------------- */
-/*      Write Fill Value                                                */
+/*      Set the driver details.                                         */
 /* -------------------------------------------------------------------- */
+        poDriver->SetDescription( "netCDF" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                   "Network Common Data Format" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
+                                   "frmt_netcdf.html" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+                                   szCreateOptions );
+
+        /* make driver config and capabilities available */
+        poDriver->SetMetadataItem( "NETCDF_VERSION", nc_inq_libvers() );
+        poDriver->SetMetadataItem( "NETCDF_CONVENTIONS", NCDF_CONVENTIONS_CF );
+#ifdef NETCDF_HAS_NC2
+        poDriver->SetMetadataItem( "NETCDF_HAS_NC2", "YES" );
+#endif
+#ifdef NETCDF_HAS_NC4
+        poDriver->SetMetadataItem( "NETCDF_HAS_NC4", "YES" );
+#endif
+#ifdef NETCDF_HAS_HDF4
+        poDriver->SetMetadataItem( "NETCDF_HAS_HDF4", "YES" );
+#endif
+#ifdef HAVE_HDF4
+        poDriver->SetMetadataItem( "GDAL_HAS_HDF4", "YES" );
+#endif
+#ifdef HAVE_HDF5
+        poDriver->SetMetadataItem( "GDAL_HAS_HDF5", "YES" );
+#endif
+ 
+        /* set pfns and register driver */
+        poDriver->pfnOpen = netCDFDataset::Open;
+        poDriver->pfnCreateCopy = netCDFDataset::CreateCopy;
+        poDriver->pfnCreate = netCDFDataset::Create;
+        poDriver->pfnIdentify = netCDFDataset::Identify;
 
-                cNoDataValue=(unsigned char) dfNoDataValue;
-                nc_put_att_uchar( fpImage,
-                                  NCDFVarID,
-                                  _FillValue,
-                                  NC_CHAR,
-                                  1,
-                                  &cNoDataValue );
-			   
-/* -------------------------------------------------------------------- */
-/*      Write Data from Band i                                          */
-/* -------------------------------------------------------------------- */
-                start[0]=iLine;
-                start[1]=0;
-                count[0]=1;
-                count[1]=nXSize;
+        GetGDALDriverManager( )->RegisterDriver( poDriver );
+    }
+}
 
-/* -------------------------------------------------------------------- */
-/*      Put NetCDF file in data mode.                                   */
-/* -------------------------------------------------------------------- */
-                status = nc_enddef( fpImage );
-                status = nc_put_vara_uchar (fpImage, NCDFVarID, start,
-                                            count, pabScanline);
+/************************************************************************/
+/*                          New functions                               */
+/************************************************************************/
 
+/* Test for GDAL version string >= target */
+int NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget)
+{
+    int nVersion = 0;
+    int nVersions [] = {0,0,0,0};
+    char **papszTokens;
+
+    /* Valid strings are "GDAL 1.9dev, released 2011/01/18" and "GDAL 1.8.1 " */
+    if ( pszVersion == NULL || EQUAL( pszVersion, "" ) )
+        return FALSE;
+    else if ( ! EQUALN("GDAL ", pszVersion, 5) )
+        return FALSE;
+    else if ( EQUALN("GDAL 1.9dev", pszVersion,11 ) )
+        return nTarget <= 1900;
+    else if ( EQUALN("GDAL 1.8dev", pszVersion,11 ) )
+        return nTarget <= 1800;
+
+    papszTokens = CSLTokenizeString2( pszVersion+5, ".", 0 );
+
+    for ( int iToken = 0; papszTokens && papszTokens[iToken]; iToken++ )  {
+        nVersions[iToken] = atoi( papszTokens[iToken] );
+    }
+    /* (GDAL_VERSION_MAJOR*1000+GDAL_VERSION_MINOR*100+GDAL_VERSION_REV*10+GDAL_VERSION_BUILD) */
+    nVersion = nVersions[0]*1000 + nVersions[1]*100 + 
+        nVersions[2]*10 + nVersions[3]; 
+    
+    CSLDestroy( papszTokens );
+    return nTarget <= nVersion;
+}
 
-/* -------------------------------------------------------------------- */
-/*      Put NetCDF file back in define mode.                            */
-/* -------------------------------------------------------------------- */
-                status = nc_redef( fpImage );
-		
-            }
-            CPLFree( pabScanline );
-/* -------------------------------------------------------------------- */
-/*      Int16                                                           */
-/* -------------------------------------------------------------------- */
+/* Add Conventions, GDAL version and history  */ 
+void NCDFAddGDALHistory( int fpImage, 
+                         const char * pszFilename, const char *pszOldHist,
+                         const char * pszFunctionName)
+{
+    char     szTemp[NC_MAX_NAME];
 
-        } else if( ( eDT == GDT_UInt16 ) || ( eDT == GDT_Int16 ) ) {
-            CPLDebug( "GDAL_netCDF", "%s = GDT_Int16 ",szBandName );
-            status = nc_def_var( fpImage, szBandName, NC_SHORT, 
-                                 GDALNBDIM, anBandDims, &NCDFVarID );
+    nc_put_att_text( fpImage, NC_GLOBAL, "Conventions", 
+                     strlen(NCDF_CONVENTIONS_CF),
+                     NCDF_CONVENTIONS_CF ); 
+    
+    nc_put_att_text( fpImage, NC_GLOBAL, "GDAL", 
+                     strlen(NCDF_GDAL), NCDF_GDAL ); 
 
-            pasScanline = (GInt16 *) CPLMalloc( nBands * nXSize *
-                                                sizeof( GInt16 ) );
-/* -------------------------------------------------------------------- */
-/*      Write Fill Value                                                */
-/* -------------------------------------------------------------------- */
-            nsNoDataValue= (GInt16) dfNoDataValue;
-            nc_put_att_short( fpImage,
-                              NCDFVarID,
-                              _FillValue,
-                              NC_SHORT,
-                              1,
-                              &nsNoDataValue );
-            for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {
+    /* Add history */
+#ifdef GDAL_SET_CMD_LINE_DEFINED_TMP
+    if ( ! EQUAL(GDALGetCmdLine(), "" ) )
+        strcpy( szTemp, GDALGetCmdLine() );
+    else
+        sprintf( szTemp, "GDAL %s( %s, ... )",pszFunctionName,pszFilename );
+#else
+    sprintf( szTemp, "GDAL %s( %s, ... )",pszFunctionName,pszFilename );
+#endif
+    
+    NCDFAddHistory( fpImage, szTemp, pszOldHist );
 
-                eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                            pasScanline, nXSize, 1, GDT_Int16,
-                                            0,0);
+}
 
-                start[0]=iLine;
-                start[1]=0;
-                count[0]=1;
-                count[1]=nXSize;
+/* code taken from cdo and libcdi, used for writing the history attribute */
+//void cdoDefHistory(int fileID, char *histstring)
+void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist)
+{
+    char strtime[32];
+    time_t tp;
+    struct tm *ltime;
 
+    char *pszNewHist = NULL;
+    size_t nNewHistSize = 0;
+    int disableHistory = FALSE;
+    int status;
 
-                status = nc_enddef( fpImage );
-                status = nc_put_vara_short( fpImage, NCDFVarID, start,
-                                            count, pasScanline);
-                status = nc_redef( fpImage );
-            }
-            CPLFree( pasScanline );
-/* -------------------------------------------------------------------- */
-/*      Int32                                                           */
-/* -------------------------------------------------------------------- */
+    /* Check pszOldHist - as if there was no previous history, it will be
+       a null pointer - if so set as empty. */
+    if (NULL == pszOldHist) {
+        pszOldHist = "";
+    }
 
-        } else if( (eDT == GDT_UInt32) || (eDT == GDT_Int32) ) {
-            CPLDebug( "GDAL_netCDF", "%s = GDT_Int32 ",szBandName );
-            status = nc_def_var( fpImage, szBandName, NC_INT, 
-                                 GDALNBDIM, anBandDims, &NCDFVarID );
+    tp = time(NULL);
+    if ( tp != -1 )
+    {
+        ltime = localtime(&tp);
+        (void) strftime(strtime, sizeof(strtime), "%a %b %d %H:%M:%S %Y: ", ltime);
+    }
 
-            panScanline = (GInt32 *) CPLMalloc( nBands * nXSize *
-                                                sizeof( GInt32 ) );
-/* -------------------------------------------------------------------- */
-/*      Write Fill Value                                                */
-/* -------------------------------------------------------------------- */
-            nlNoDataValue= (GInt32) dfNoDataValue;
+    // status = nc_get_att_text( fpImage, NC_GLOBAL, 
+    //                           "history", pszOldHist );
+    // printf("status: %d pszOldHist: [%s]\n",status,pszOldHist);
+    
+    nNewHistSize = strlen(pszOldHist)+strlen(strtime)+strlen(pszAddHist)+1+1;
+    pszNewHist = (char *) CPLMalloc(nNewHistSize * sizeof(char));
+    
+    strcpy(pszNewHist, strtime);
+    strcat(pszNewHist, pszAddHist);
 
-            nc_put_att_int( fpImage,
-                            NCDFVarID,
-                            _FillValue,
-                            NC_INT,
-                            1,
-                            &nlNoDataValue );
+    if ( disableHistory == FALSE && pszNewHist )
+    {
+        if ( ! EQUAL(pszOldHist,"") )
+            strcat(pszNewHist, "\n");
+        strcat(pszNewHist, pszOldHist);
+    }
 
+    status = nc_put_att_text( fpImage, NC_GLOBAL, 
+                              "history", strlen(pszNewHist),
+                              pszNewHist ); 
+    NCDF_ERR(status);
 
-            for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {
+    CPLFree(pszNewHist);
+}
 
-                eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                            panScanline, nXSize, 1, GDT_Int32,
-                                            0,0);
 
-                start[0]=iLine;
-                start[1]=0;
-                count[0]=1;
-                count[1]=nXSize;
+int NCDFIsCfProjection( const char* pszProjection ) 
+{
+    /* Find the appropriate mapping */
+    for (int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ ) {
+        // printf("now at %d, proj=%s\n",i, poNetcdfSRS_PT[i].GDAL_SRS);
+        if ( EQUAL( pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS ) )  {
+            if ( poNetcdfSRS_PT[iMap].mappings != NULL )
+                return TRUE;            
+            else 
+                return FALSE;
+        }
+    }
+    return FALSE;
+}
 
 
-                status = nc_enddef( fpImage );
-                status = nc_put_vara_int( fpImage, NCDFVarID, start,
-                                          count, panScanline);
-                status = nc_redef( fpImage );
-            }
-            CPLFree( panScanline );
-/* -------------------------------------------------------------------- */
-/*      float                                                           */
-/* -------------------------------------------------------------------- */
-        } else if( (eDT == GDT_Float32) ) {
-            CPLDebug( "GDAL_netCDF", "%s = GDT_Float32 ",szBandName );
-            status = nc_def_var( fpImage, szBandName, NC_FLOAT, 
-                                 GDALNBDIM, anBandDims, &NCDFVarID );
+/* Write any needed projection attributes *
+ * poPROJCS: ptr to proj crd system
+ * pszProjection: name of projection system in GDAL WKT
+ * fpImage: open NetCDF file in writing mode
+ * NCDFVarID: NetCDF Var Id of proj system we're writing in to
+ *
+ * The function first looks for the oNetcdfSRS_PP mapping object
+ * that corresponds to the input projection name. If none is found
+ * the generic mapping is used.  In the case of specific mappings,
+ * the driver looks for each attribute listed in the mapping object
+ * and then looks up the value within the OGR_SRSNode. In the case
+ * of the generic mapping, the lookup is reversed (projection params, 
+ * then mapping).  For more generic code, GDAL->NETCDF 
+ * mappings and the associated value are saved in std::map objects.
+ */
+
+/* NOTE modifications by ET to combine the specific and generic mappings */
+
+void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
+                           const char* pszProjection,
+                           const int fpImage, const int NCDFVarID ) 
+{                            
+    double dfStdP[2];
+    int bFoundStdP1=FALSE,bFoundStdP2=FALSE;
+    double dfValue=0.0;
+    const char *pszParamStr, *pszParamVal;
+    const std::string *pszNCDFAtt, *pszGDALAtt;
+    static const oNetcdfSRS_PP *poMap = NULL;
+    int nMapIndex = -1;
+    int bWriteVal = FALSE;
+
+    //Attribute <GDAL,NCDF> and Value <NCDF,value> mappings
+    std::map< std::string, std::string > oAttMap;
+    std::map< std::string, std::string >::iterator oAttIter;
+    std::map< std::string, double > oValMap;
+    std::map< std::string, double >::iterator oValIter, oValIter2;
+    //results to write
+    std::vector< std::pair<std::string,double> > oOutList;
+ 
+    /* Find the appropriate mapping */
+    for (int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ ) {
+        if ( EQUAL( pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS ) ) {
+            nMapIndex = iMap;
+            poMap = poNetcdfSRS_PT[iMap].mappings;
+            break;
+        }
+    }
 
-            pafScanline = (float *) CPLMalloc( nBands * nXSize *
-                                               sizeof( float ) );
+    //ET TODO if projection name is not found, should we do something special?
+    if ( nMapIndex == -1 ) {
+        CPLError( CE_Warning, CPLE_AppDefined, 
+                  "projection name %s not found in the lookup tables!!!",
+                  pszProjection);
+    }
+    /* if no mapping was found or assigned, set the generic one */
+    if ( !poMap ) {
+        CPLError( CE_Warning, CPLE_AppDefined, 
+                  "projection name %s in not part of the CF standard, will not be supported by CF!",
+                  pszProjection);
+        poMap = poGenericMappings;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Write Fill Value                                                */
-/* -------------------------------------------------------------------- */
-            fNoDataValue= (float) dfNoDataValue;
-            nc_put_att_float( fpImage,
-                              NCDFVarID,
-                              _FillValue,
-                              NC_FLOAT,
-                              1,
-                              &fNoDataValue );
-			   
-            for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {
+    /* initialize local map objects */
+    for ( int iMap = 0; poMap[iMap].WKT_ATT != NULL; iMap++ ) {
+        oAttMap[poMap[iMap].WKT_ATT] = poMap[iMap].CF_ATT;
+    }
 
-                eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                            pafScanline, nXSize, 1, 
-                                            GDT_Float32,
-                                            0,0);
+    for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ ) {
 
-                start[0]=iLine;
-                start[1]=0;
-                count[0]=1;
-                count[1]=nXSize;
+        const OGR_SRSNode *poNode;
 
+        poNode = poPROJCS->GetChild( iChild );
+        if( !EQUAL(poNode->GetValue(),"PARAMETER") 
+            || poNode->GetChildCount() != 2 )
+            continue;
+        pszParamStr = poNode->GetChild(0)->GetValue();
+        pszParamVal = poNode->GetChild(1)->GetValue();
 
-                status = nc_enddef( fpImage );
-                status = nc_put_vara_float( fpImage, NCDFVarID, start,
-                                            count, pafScanline);
-                status = nc_redef( fpImage );
-            }
-            CPLFree( pafScanline );
-/* -------------------------------------------------------------------- */
-/*      double                                                          */
-/* -------------------------------------------------------------------- */
-        } else if( (eDT == GDT_Float64) ) {
-            CPLDebug( "GDAL_netCDF", "%s = GDT_Float64 ",szBandName );
-            status = nc_def_var( fpImage, szBandName, NC_DOUBLE, 
-                                 GDALNBDIM, anBandDims, &NCDFVarID );
+        oValMap[pszParamStr] = atof(pszParamVal);
+    }
 
-            padScanline = (double *) CPLMalloc( nBands * nXSize *
-                                                sizeof( double ) );
+    /* Lookup mappings and fill output vector */
+    if ( poMap != poGenericMappings ) { /* specific mapping, loop over mapping values */
+
+        for ( oAttIter = oAttMap.begin(); oAttIter != oAttMap.end(); oAttIter++ ) {
+
+            pszGDALAtt = &(oAttIter->first);
+            pszNCDFAtt = &(oAttIter->second);
+            oValIter = oValMap.find( *pszGDALAtt );
+
+            if ( oValIter != oValMap.end() ) {
+
+                dfValue = oValIter->second;
+                bWriteVal = TRUE;
+
+                /* special case for PS (Polar Stereographic) grid
+                   See comments in netcdfdataset.h for this projection. */
+                if ( EQUAL( SRS_PP_LATITUDE_OF_ORIGIN, pszGDALAtt->c_str() ) &&
+                     EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) ) {
+                    double dfLatPole = 0.0;
+                    if ( dfValue > 0.0) dfLatPole = 90.0;
+                    else dfLatPole = -90.0;
+                        oOutList.push_back( std::make_pair( CF_PP_LAT_PROJ_ORIGIN, 
+                                                            dfLatPole ) );
+                }              
+
+                /* special case for LCC-1SP
+                   See comments in netcdfdataset.h for this projection. */
+                else if ( EQUAL( SRS_PP_SCALE_FACTOR, pszGDALAtt->c_str() ) &&
+                          EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) ) {
+                    /* default is to not write as it is not CF-1 */
+                    bWriteVal = FALSE;
+                    /* test if there is no standard_parallel1 */
+                    if ( oValMap.find( std::string(CF_PP_STD_PARALLEL_1) ) == oValMap.end() ) {
+                        /* if scale factor != 1.0  write value for GDAL, but this is not supported by CF-1 */
+                        if ( !CPLIsEqual(dfValue,1.0) ) {
+                            CPLError( CE_Failure, CPLE_NotSupported, 
+                                      "NetCDF driver export of LCC-1SP with scale factor != 1.0 "
+                                      "and no standard_parallel1 is not CF-1 (bug #3324).\n" 
+                                      "Use the 2SP variant which is supported by CF." );   
+                            bWriteVal = TRUE;
+                        }
+                        /* else copy standard_parallel1 from latitude_of_origin, because scale_factor=1.0 */
+                        else {                      
+                            oValIter2 = oValMap.find( std::string(SRS_PP_LATITUDE_OF_ORIGIN) );
+                            if (oValIter2 != oValMap.end() ) {
+                                oOutList.push_back( std::make_pair( CF_PP_STD_PARALLEL_1, 
+                                                                    oValIter2->second) );
+                            }
+                            else {
+                                CPLError( CE_Failure, CPLE_NotSupported, 
+                                          "NetCDF driver export of LCC-1SP with no standard_parallel1 "
+                                          "and no latitude_of_origin is not suported (bug #3324).");
+                            }
+                        }                      
+                    }
+                }
+                if ( bWriteVal )
+                    oOutList.push_back( std::make_pair( *pszNCDFAtt, dfValue ) );
 
-/* -------------------------------------------------------------------- */
-/*      Write Fill Value                                                */
-/* -------------------------------------------------------------------- */
-		
-            nc_put_att_double( fpImage,
-                               NCDFVarID,
-                               _FillValue,
-                               NC_DOUBLE,
-                               1,
-                               &dfNoDataValue );
-
-            for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {
-
-                eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                            padScanline, nXSize, 1, 
-                                            GDT_Float64,
-                                            0,0);
-
-                start[0]=iLine;
-                start[1]=0;
-                count[0]=1;
-                count[1]=nXSize;
-
-
-                status = nc_enddef( fpImage );
-                status = nc_put_vara_double( fpImage, NCDFVarID, start,
-                                             count, padScanline);
-                status = nc_redef( fpImage );
             }
-            CPLFree( padScanline );
-        }
-	
-/* -------------------------------------------------------------------- */
-/*      Write Projection for band                                       */
-/* -------------------------------------------------------------------- */
-        if( bWriteGeoTransform == TRUE ) {
-            /*	    nc_put_att_text( fpImage, NCDFVarID, 
-                    COORDINATES,
-                    7,
-                    LONLAT );
-            */
-            nc_put_att_text( fpImage, NCDFVarID, 
-                             GRD_MAPPING,
-                             strlen( pszNetcdfProjection ),
-                             pszNetcdfProjection );
+            // else printf("NOT FOUND!!!\n");
         }
+    
+    }
+    else { /* generic mapping, loop over projected values */
 
-        sprintf( szBandName, "GDAL Band Number %d", i);
-        nBandNameLen = strlen( szBandName );
-        nc_put_att_text( fpImage, 
-                         NCDFVarID, 
-                         "long_name", 
-                         nBandNameLen,
-                         szBandName );
+        for ( oValIter = oValMap.begin(); oValIter != oValMap.end(); oValIter++ ) {
 
-        CopyMetadata( (void *) hBand, fpImage, NCDFVarID );
+            pszGDALAtt = &(oValIter->first);
+            dfValue = oValIter->second;
 
-			   
+            oAttIter = oAttMap.find( *pszGDALAtt );
 
+            if ( oAttIter != oAttMap.end() ) {
+                oOutList.push_back( std::make_pair( oAttIter->second, dfValue ) );
+            }
+            /* for SRS_PP_SCALE_FACTOR write 2 mappings */
+            else if (  EQUAL(pszGDALAtt->c_str(), SRS_PP_SCALE_FACTOR) ) {
+                oOutList.push_back( std::make_pair( CF_PP_SCALE_FACTOR_MERIDIAN,
+                                                    dfValue ) );
+                oOutList.push_back( std::make_pair( CF_PP_SCALE_FACTOR_ORIGIN,
+                                                    dfValue ) );
+            }
+            /* if not found insert the GDAL name */
+            else {
+                oOutList.push_back( std::make_pair( *pszGDALAtt, dfValue ) );
+            }
+        }
     }
 
+    /* Write all the values that were found */
+    // std::vector< std::pair<std::string,double> >::reverse_iterator it;
+    // for (it = oOutList.rbegin();  it != oOutList.rend(); it++ ) {
+    std::vector< std::pair<std::string,double> >::iterator it;
+    for (it = oOutList.begin();  it != oOutList.end(); it++ ) {
+        pszParamVal = (it->first).c_str();
+        dfValue = it->second;
+        /* Handle the STD_PARALLEL attrib */
+        if( EQUAL( pszParamVal, CF_PP_STD_PARALLEL_1 ) ) {
+            bFoundStdP1 = TRUE;
+            dfStdP[0] = dfValue;
+        }
+        else if( EQUAL( pszParamVal, CF_PP_STD_PARALLEL_2 ) ) {
+            bFoundStdP2 = TRUE;
+            dfStdP[1] = dfValue;
+        } 
+        else {
+            nc_put_att_double( fpImage, NCDFVarID, pszParamVal,
+                               NC_DOUBLE, 1,&dfValue );
+        }
+    }
+    /* Now write the STD_PARALLEL attrib */
+    if ( bFoundStdP1 ) { 
+        /* one value or equal values */
+        if ( !bFoundStdP2 || dfStdP[0] ==  dfStdP[1] ) {
+            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL, 
+                               NC_DOUBLE, 1, &dfStdP[0] );
+        }
+        else { /* two values */
+            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL, 
+                               NC_DOUBLE, 2, dfStdP );
+        }
+    }
+}
 
+CPLErr NCDFSafeStrcat(char** ppszDest, char* pszSrc, size_t* nDestSize)
+{
+    /* Reallocate the data string until the content fits */
+    while(*nDestSize < (strlen(*ppszDest) + strlen(pszSrc) + 1)) {
+        (*nDestSize) *= 2;
+        *ppszDest = (char*) CPLRealloc((void*) *ppszDest, *nDestSize);
+    }
+    strcat(*ppszDest, pszSrc);
+    
+    return CE_None;
+}
 
-    //    poDstDS->SetGeoTransform( adfGeoTransform );
+/* helper function for NCDFGetAttr() */
+/* sets pdfValue to first value returned */
+/* and if bSetPszValue=True sets szValue with all values attribute values */
+/* pszValue is the responsibility of the caller and must be freed */
+CPLErr NCDFGetAttr1( int nCdfId, int nVarId, const char *pszAttrName, 
+                     double *pdfValue, char **pszValue, int bSetPszValue )
+{
+    nc_type nAttrType = NC_NAT;
+    size_t  nAttrLen = 0;
+    size_t  nAttrValueSize;
+    int     status = 0; /*rename this */
+    size_t  m;
+    char    szTemp[ NCDF_MAX_STR_LEN ];
+    char    *pszAttrValue = NULL;
+    double  dfValue = 0.0;
+
+    status = nc_inq_att( nCdfId, nVarId, pszAttrName, &nAttrType, &nAttrLen);
+    if ( status != NC_NOERR )
+        return CE_Failure;
 
+    /* Allocate guaranteed minimum size */
+    nAttrValueSize = nAttrLen + 1;
+    pszAttrValue = (char *) CPLCalloc( nAttrValueSize, sizeof( char ));
+    *pszAttrValue = '\0';
+
+    if ( nAttrLen > 1  && nAttrType != NC_CHAR )    
+        NCDFSafeStrcat(&pszAttrValue, (char *)"{ ", &nAttrValueSize);
+
+    switch (nAttrType) {
+        case NC_CHAR:
+            nc_get_att_text( nCdfId, nVarId, pszAttrName, pszAttrValue );
+            pszAttrValue[nAttrLen]='\0';
+            dfValue = 0.0;
+            break;
+        /* TODO support NC_UBYTE */
+        case NC_BYTE:
+            signed char *pscTemp;
+            pscTemp = (signed char *) CPLCalloc( nAttrLen, sizeof( signed char ) );
+            nc_get_att_schar( nCdfId, nVarId, pszAttrName, pscTemp );
+            dfValue = (double)pscTemp[0];
+            for(m=0; m < nAttrLen-1; m++) {
+                sprintf( szTemp, "%d, ", pscTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            sprintf( szTemp, "%d", pscTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(pscTemp);
+            break;
+        case NC_SHORT:
+            short *psTemp;
+            psTemp = (short *) CPLCalloc( nAttrLen, sizeof( short ) );
+            nc_get_att_short( nCdfId, nVarId, pszAttrName, psTemp );
+            dfValue = (double)psTemp[0];
+            for(m=0; m < nAttrLen-1; m++) {
+                sprintf( szTemp, "%hd, ", psTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            sprintf( szTemp, "%hd", psTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(psTemp);
+            break;
+        case NC_INT:
+            int *pnTemp;
+            pnTemp = (int *) CPLCalloc( nAttrLen, sizeof( int ) );
+            nc_get_att_int( nCdfId, nVarId, pszAttrName, pnTemp );
+            dfValue = (double)pnTemp[0];
+            for(m=0; m < nAttrLen-1; m++) {
+                sprintf( szTemp, "%d, ", pnTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            sprintf( szTemp, "%d", pnTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(pnTemp);
+            break;
+        case NC_FLOAT:
+            float *pfTemp;
+            pfTemp = (float *) CPLCalloc( nAttrLen, sizeof( float ) );
+            nc_get_att_float( nCdfId, nVarId, pszAttrName, pfTemp );
+            dfValue = (double)pfTemp[0];
+            for(m=0; m < nAttrLen-1; m++) {
+                sprintf( szTemp, "%.8g, ", pfTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            sprintf( szTemp, "%.8g", pfTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue,szTemp, &nAttrValueSize);
+            CPLFree(pfTemp);
+            break;
+        case NC_DOUBLE:
+            double *pdfTemp;
+            pdfTemp = (double *) CPLCalloc(nAttrLen, sizeof(double));
+            nc_get_att_double( nCdfId, nVarId, pszAttrName, pdfTemp );
+            dfValue = pdfTemp[0];
+            for(m=0; m < nAttrLen-1; m++) {
+                sprintf( szTemp, "%.16g, ", pdfTemp[m] );
+                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            }
+            sprintf( szTemp, "%.16g", pdfTemp[m] );
+            NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+            CPLFree(pdfTemp);
+            break;
+        default:
+            CPLDebug( "GDAL_netCDF", "NCDFGetAttr unsupported type %d for attribute %s",
+                      nAttrType,pszAttrName);
+            CPLFree( pszAttrValue );
+            pszAttrValue = NULL;
+            break;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup and close.                                              */
-/* -------------------------------------------------------------------- */
-//    CPLFree( pabScanline );
+    if ( nAttrLen > 1  && nAttrType!= NC_CHAR )    
+        NCDFSafeStrcat(&pszAttrValue, (char *)" }", &nAttrValueSize);
 
-    nc_close( fpImage );
-/* -------------------------------------------------------------------- */
-/*      Re-open dataset, and copy any auxilary pam information.         */
-/* -------------------------------------------------------------------- */
-    netCDFDataset *poDS = (netCDFDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+    // CPLDebug( "GDAL_netCDF", "NCDFGetAttr got %s=%s / %f",
+    //           pszAttrName,pszAttrValue,dfValue);
 
-    if( poDS )
-        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+    /* set return values */
+    if ( bSetPszValue == TRUE ) *pszValue = pszAttrValue;
+    else CPLFree ( pszAttrValue );
+    if ( pdfValue ) *pdfValue = dfValue;
 
-    return poDS;
+    return CE_None;
 }
 
-/************************************************************************/
-/*                          GDALRegister_netCDF()                       */
-/************************************************************************/
 
-void GDALRegister_netCDF()
+/* sets pdfValue to first value found */
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
+                    double *pdfValue )
+{
+    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, pdfValue, NULL, FALSE );
+}
 
+/* pszValue is the responsibility of the caller and must be freed */
+CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName, 
+                    char **pszValue )
 {
-    GDALDriver	*poDriver;
+    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, FALSE, pszValue, TRUE );
+}
 
-    if (! GDAL_CHECK_VERSION("netCDF driver"))
-        return;
 
-    if( GDALGetDriverByName( "netCDF" ) == NULL )
-    {
-        poDriver = new GDALDriver( );
-        
-        poDriver->SetDescription( "netCDF" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Network Common Data Format" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_netcdf.html" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
+/* By default write NC_CHAR, but detect for int/float/double */
+CPLErr NCDFPutAttr( int nCdfId, int nVarId, 
+                 const char *pszAttrName, const char *pszValue )
+{
+    nc_type nAttrType = NC_CHAR;
+    nc_type nTmpAttrType = NC_CHAR;
+    size_t  nAttrLen = 0;
+    int     status = 0;
+    size_t  i;
+    char    szTemp[ NCDF_MAX_STR_LEN ];
+    char    *pszTemp = NULL;
+    char    **papszValues = NULL;
+    
+    int     bIsArray = FALSE;
+    int     nValue = 0;
+    float   fValue = 0.0f;
+    double  dfValue = 0.0;
 
-        poDriver->pfnOpen = netCDFDataset::Open;
-        poDriver->pfnCreateCopy = NCDFCreateCopy;
+    if ( EQUAL( pszValue, "" ) )
+        return CE_Failure;
 
+    strcpy( szTemp,pszValue );
 
-        GetGDALDriverManager( )->RegisterDriver( poDriver );
+    /* tokenize to find multiple values */
+    int last_char = strlen(pszValue) - 1;
+    if ( ( szTemp[0] == '{' ) && ( szTemp[last_char] == '}' ) ) {
+        bIsArray = TRUE;
+        szTemp[0] = ' '; 
+        szTemp[last_char] = ' ';
     }
-}
-
-
-
-/* -------------------------------------------------------------------- */
-/*      Set Lambert Conformal Conic Projection                          */
-/* -------------------------------------------------------------------- */
-
+    papszValues = CSLTokenizeString2( szTemp, ",", CSLT_STRIPLEADSPACES |
+                                      CSLT_STRIPENDSPACES );
+    if ( papszValues == NULL )
+        return CE_Failure;
 
+    nAttrLen = CSLCount(papszValues);
     
-//Albers equal area
-//
-//grid_mapping_name = albers_conical_equal_area
-//
-//Map parameters:
-//
-//    * standard_parallel - There may be 1 or 2 values.
-//    * longitude_of_central_meridian
-//    * latitude_of_projection_origin
-//    * false_easting
-//    * false_northing
-//Azimuthal equidistant
-//
-//grid_mapping_name = azimuthal_equidistant
-//
-//Map parameters:
-//
-//    * longitude_of_projection_origin
-//    * latitude_of_projection_origin
-//    * false_easting
-//    * false_northing
-//Lambert azimuthal equal area
-//
-//grid_mapping_name = lambert_azimuthal_equal_area
-//
-//Map parameters:
-//
-//    * longitude_of_projection_origin
-//    * latitude_of_projection_origin
-//    * false_easting
-//    * false_northing
-//Lambert conformal
-//
-//grid_mapping_name = lambert_conformal_conic
-//
-//Map parameters:
-//
-//    * standard_parallel - There may be 1 or 2 values.
-//    * longitude_of_central_meridian
-//    * latitude_of_projection_origin
-//    * false_easting
-//    * false_northing
-//Lambert Cylindrical Equal Area
-//
-//grid_mapping_name = lambert_cylindrical_equal_area
-//
-//Map parameters:
-//
-//    * longitude_of_central_meridian
-//    * either standard_parallel or scale_factor_at_projection_origin
-//    * false_easting
-//    * false_northing
-//Latitude-Longitude
-//
-//grid_mapping_name = latitude_longitude
-//
-//Map parameters:
-//
-//    * None
-//Mercator
-//
-//grid_mapping_name = mercator
-//
-//Map parameters:
-//
-//    * longitude_of_projection_origin
-//    * either standard_parallel or scale_factor_at_projection_origin
-//    * false_easting
-//    * false_northing
-//Orthographic
-//
-//grid_mapping_name = orthographic
-//
-//Map parameters:
-//
-//    * longitude_of_projection_origin
-//    * latitude_of_projection_origin
-//    * false_easting
-//    * false_northing
-//Polar stereographic
-//
-//grid_mapping_name = polar_stereographic
-//
-//Map parameters:
-//
-//    * straight_vertical_longitude_from_pole
-//    * latitude_of_projection_origin - Either +90. or -90.
-//    * Either standard_parallel or scale_factor_at_projection_origin
-//    * false_easting
-//    * false_northing
-//Rotated pole
-//
-//grid_mapping_name = rotated_latitude_longitude
-//
-//Map parameters:
-//
-//    * grid_north_pole_latitude
-//    * grid_north_pole_longitude
-//    * north_pole_grid_longitude - This parameter is optional (default is 0.).
-//Stereographic
-//
-//grid_mapping_name = stereographic
-//
-//Map parameters:
-//
-//    * longitude_of_projection_origin
-//    * latitude_of_projection_origin
-//    * scale_factor_at_projection_origin
-//    * false_easting
-//    * false_northing
-//Transverse Mercator
-//
-//grid_mapping_name = transverse_mercator
-//
-//Map parameters:
-//
-//    * scale_factor_at_central_meridian
-//    * longitude_of_central_meridian
-//    * latitude_of_projection_origin
-//    * false_easting
-//    * false_northing
-//Vertical perspective
-//
-//grid_mapping_name = vertical_perspective
-//
-//Map parameters:
-//
-//    * latitude_of_projection_origin
-//    * longitude_of_projection_origin
-//    * perspective_point_height
-//    * false_easting
-//    * false_northing
-//
-//
-//Grid mapping attributes
-//
-//earth_radius
-//false_easting 	
-//false_northing 	
-//grid_mapping_name 	
-//grid_north_pole_latitude
-//grid_north_pole_longitude
-//inverse_flattening
-//latitude_of_projection_origin 
-//longitude_of_central_meridian 
-//longitude_of_prime_meridian
-//longitude_of_projection_origin
-//north_pole_grid_longitude 
-//perspective_point_height	
-//scale_factor_at_central_meridian 
-//scale_factor_at_projection_origin 
-//semi_major_axis
-//semi_minor_axis
-//standard_parallel 	
-//straight_vertical_longitude_from_pole 	
+    /* first detect type */
+    nAttrType = NC_CHAR;
+    for ( i=0; i<nAttrLen; i++ ) {
+        nTmpAttrType = NC_CHAR;
+        errno = 0;
+        nValue = strtol( papszValues[i], &pszTemp, 10 );
+        /* test for int */
+        /* TODO test for Byte and short - can this be done safely? */
+        if ( (errno == 0) && (papszValues[i] != pszTemp) && (*pszTemp == 0) ) {
+            nTmpAttrType = NC_INT;
+        }
+        else {
+            /* test for double */
+            errno = 0;
+            dfValue = strtod( papszValues[i], &pszTemp );
+            if ( (errno == 0) && (papszValues[i] != pszTemp) && (*pszTemp == 0) ) {
+                /* test for float instead of double */
+                /* strtof() is C89, which is not available in MSVC */
+                /* see if we loose precision if we cast to float and write to char* */
+                fValue = (float)dfValue; 
+                sprintf( szTemp,"%.8g",fValue); 
+                if ( EQUAL(szTemp, papszValues[i] ) )
+                    nTmpAttrType = NC_FLOAT;
+                else
+                    nTmpAttrType = NC_DOUBLE;                   
+            }
+        }
+        if ( nTmpAttrType > nAttrType )
+            nAttrType = nTmpAttrType;
+    }
+
+    /* now write the data */
+    if ( !bIsArray && nAttrType == NC_CHAR ) {
+        status = nc_put_att_text( nCdfId, nVarId, pszAttrName,
+                                  strlen( pszValue ), pszValue );
+        NCDF_ERR(status);                        
+    }
+    else {
+        
+        switch( nAttrType ) {
+            case  NC_INT:
+                int *pnTemp;
+                pnTemp = (int *) CPLCalloc( nAttrLen, sizeof( int ) );
+                for(i=0; i < nAttrLen; i++) {
+                    pnTemp[i] = strtol( papszValues[i], &pszTemp, 10 );
+                }
+                status = nc_put_att_int( nCdfId, nVarId, pszAttrName, 
+                                         NC_INT, nAttrLen, pnTemp );  
+                NCDF_ERR(status);
+                CPLFree(pnTemp);
+            break;
+            case  NC_FLOAT:
+                float *pfTemp;
+                pfTemp = (float *) CPLCalloc( nAttrLen, sizeof( float ) );
+                for(i=0; i < nAttrLen; i++) {
+                    pfTemp[i] = (float)strtod( papszValues[i], &pszTemp );
+                }
+                status = nc_put_att_float( nCdfId, nVarId, pszAttrName, 
+                                           NC_FLOAT, nAttrLen, pfTemp );  
+                NCDF_ERR(status);
+                CPLFree(pfTemp);
+            break;
+            case  NC_DOUBLE:
+                double *pdfTemp;
+                pdfTemp = (double *) CPLCalloc( nAttrLen, sizeof( double ) );
+                for(i=0; i < nAttrLen; i++) {
+                    pdfTemp[i] = strtod( papszValues[i], &pszTemp );
+                }
+                status = nc_put_att_double( nCdfId, nVarId, pszAttrName, 
+                                            NC_DOUBLE, nAttrLen, pdfTemp );
+                NCDF_ERR(status);
+                CPLFree(pdfTemp);
+            break;
+        default:
+            if ( papszValues ) CSLDestroy( papszValues );
+            return CE_Failure;
+            break;
+        }   
+    }
 
+    if ( papszValues ) CSLDestroy( papszValues );
 
+     return CE_None;
+}
diff --git a/frmts/netcdf/netcdfdataset.h b/frmts/netcdf/netcdfdataset.h
index adc15af..aa35ae3 100644
--- a/frmts/netcdf/netcdfdataset.h
+++ b/frmts/netcdf/netcdfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: netcdfdataset.h 18931 2010-02-25 20:32:37Z kyle $
+ * $Id: netcdfdataset.h 23627 2011-12-22 02:40:39Z etourigny $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -41,126 +41,586 @@
 
 /************************************************************************/
 /* ==================================================================== */
-/*			     netCDFDataset				*/
+/*			     defines    		                             		*/
 /* ==================================================================== */
 /************************************************************************/
-#define MAX_STR_LEN            8192
-#define AEA                    "albers_conical_equal_area"
-#define AE                     "azimuthal_equidistant"
-#define CEA                    "cylindrical_equal_area"
-#define LCEA                   "lambert_cylindrical_equal_area"
-#define L_C_CONIC              "lambert_conformal_conic"
-#define TM                     "transverse_mercator"
-#define LAEA                   "lambert_azimuthal_equal_area"
-#define GRD_MAPPING_NAME       "grid_mapping_name"
-#define GRD_MAPPING            "grid_mapping"
-#define COORDINATES            "coordinates"
-#define LONLAT                 "lon lat"
-#define LATITUDE_LONGITUDE     "latitude_longitude"
-#define MERCATOR               "mercator"
-#define ORTHOGRAPHIC           "orthographic"
-#define POLAR_STEREO           "polar_stereographic"
-#define STEREO                 "stereographic"
-
-#define STD_PARALLEL           "standard_parallel"
-#define STD_PARALLEL_1         "standard_parallel_1"
-#define STD_PARALLEL_2         "standard_parallel_2"
-#define CENTRAL_MERIDIAN       "central_meridian"
-#define LONG_CENTRAL_MERIDIAN  "longitude_of_central_meridian"
-#define LON_PROJ_ORIGIN        "longitude_of_projection_origin"
-#define LAT_PROJ_ORIGIN        "latitude_of_projection_origin"
-#define SCALE_FACTOR_ORIGIN    "scale_factor_at_projection_origin"
-#define PROJ_X_ORIGIN          "projection_x_coordinate_origin"
-#define PROJ_Y_ORIGIN          "projection_y_coordinate_origin"
-#define EARTH_SHAPE            "GRIB_earth_shape"
-#define EARTH_SHAPE_CODE       "GRIB_earth_shape_code"
-#define SCALE_FACTOR           "scale_factor_at_central_meridian"
-#define FALSE_EASTING          "false_easting"
-#define FALSE_NORTHING         "false_northing"
-#define EARTH_RADIUS           "earth_radius"
-#define INVERSE_FLATTENING     "inverse_flattening"
-#define LONG_PRIME_MERIDIAN    "longitude_of_prime_meridian"
-#define SEMI_MAJOR_AXIS        "semi_major_axis"
-#define SEMI_MINOR_AXIS        "semi_minor_axis"
-
-#define STD_NAME               "standard_name"
-#define LNG_NAME               "long_name"
-#define UNITS                  "units"
-#define AXIS                   "axis"
-#define BOUNDS                 "bounds"
-#define ORIG_AXIS              "original_units"
-
-#define GDALNBDIM  2
 
+/* -------------------------------------------------------------------- */
+/*      Driver-specific defines                                         */
+/* -------------------------------------------------------------------- */
 
+/* NETCDF driver defs */
+#define NCDF_MAX_STR_LEN     8192
+#define NCDF_CONVENTIONS_CF  "CF-1.5"
+#define NCDF_GDAL             GDALVersionInfo("--version")
+#define NCDF_NBDIM           2
+#define NCDF_SPATIAL_REF     "spatial_ref"
+#define NCDF_GEOTRANSFORM    "GeoTransform"
+#define NCDF_DIMNAME_X       "x"
+#define NCDF_DIMNAME_Y       "y"
+#define NCDF_DIMNAME_LON     "lon"
+#define NCDF_DIMNAME_LAT     "lat"
+#define NCDF_LONLAT          "lon lat"
+#define NCDF_PI              3.14159265358979323846
+
+/* netcdf file types, as in libcdi/cdo and compat w/netcdf.h */
+#define NCDF_FORMAT_NONE            0   /* Not a netCDF file */
+#define NCDF_FORMAT_NC              1   /* netCDF classic format */
+#define NCDF_FORMAT_NC2             2   /* netCDF version 2 (64-bit)  */
+#define NCDF_FORMAT_NC4             3   /* netCDF version 4 */
+#define NCDF_FORMAT_NC4C            4   /* netCDF version 4 (classic) */
+#define NCDF_FORMAT_UNKNOWN         10  /* Format not determined (yet) */
+/* HDF files (HDF5 or HDF4) not supported because of lack of support */
+/* in libnetcdf installation or conflict with other drivers */
+#define NCDF_FORMAT_HDF5            5   /* HDF4 file, not supported */
+#define NCDF_FORMAT_HDF4            6   /* HDF4 file, not supported */
+
+/* compression parameters */
+#define NCDF_COMPRESS_NONE            0   
+/* TODO */
+/* http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#Packed%20Data%20Values */
+#define NCDF_COMPRESS_PACKED          1  
+#define NCDF_COMPRESS_DEFLATE         2   
+#define NCDF_DEFLATE_LEVEL            1  /* best time/size ratio */  
+#define NCDF_COMPRESS_SZIP            3  /* no support for writting */ 
+
+/* helper for libnetcdf errors */
+#define NCDF_ERR(status) if ( status != NC_NOERR ){ \
+CPLError( CE_Failure,CPLE_AppDefined, \
+"netcdf error #%d : %s .\nat (%s,%s,%d)\n",status, nc_strerror(status), \
+__FILE__, __FUNCTION__, __LINE__ ); }
+
+/* check for NC2 support in case it wasn't enabled at compile time */
+/* NC4 has to be detected at compile as it requires a special build of netcdf-4 */
+#ifndef NETCDF_HAS_NC2
+#ifdef NC_64BIT_OFFSET
+#define NETCDF_HAS_NC2 1
+#endif
+#endif
+
+/* -------------------------------------------------------------------- */
+/*       CF or NUG (NetCDF User's Guide) defs                           */
+/* -------------------------------------------------------------------- */
+
+/* CF: http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.5/cf-conventions.html */
+/* NUG: http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#Variables */
+#define CF_STD_NAME          "standard_name"
+#define CF_LNG_NAME          "long_name"
+#define CF_UNITS             "units"
+#define CF_ADD_OFFSET        "add_offset"
+#define CF_SCALE_FACTOR      "scale_factor"
+/* should be SRS_UL_METER but use meter now for compat with gtiff files */
+#define CF_UNITS_M           "metre"
+#define CF_UNITS_D           SRS_UA_DEGREE
+#define CF_PROJ_X_COORD      "projection_x_coordinate"
+#define CF_PROJ_Y_COORD      "projection_y_coordinate"
+#define CF_GRD_MAPPING_NAME  "grid_mapping_name"
+#define CF_GRD_MAPPING       "grid_mapping"
+#define CF_COORDINATES       "coordinates"
+/* #define CF_AXIS            "axis" */
+/* #define CF_BOUNDS          "bounds" */
+/* #define CF_ORIG_UNITS      "original_units" */
+
+/* -------------------------------------------------------------------- */
+/*      CF-1 convention standard variables related to                   */
+/*      mapping & projection - see http://cf-pcmdi.llnl.gov/            */
+/* -------------------------------------------------------------------- */
+
+/* projection types */
+#define CF_PT_AEA                    "albers_conical_equal_area"
+#define CF_PT_AE                     "azimuthal_equidistant"
+#define CF_PT_CEA                    "cylindrical_equal_area"
+#define CF_PT_LAEA                   "lambert_azimuthal_equal_area"
+#define CF_PT_LCEA                   "lambert_cylindrical_equal_area"
+#define CF_PT_LCC                    "lambert_conformal_conic"
+#define CF_PT_TM                     "transverse_mercator"
+#define CF_PT_LATITUDE_LONGITUDE     "latitude_longitude"
+#define CF_PT_MERCATOR               "mercator"
+#define CF_PT_ORTHOGRAPHIC           "orthographic"
+#define CF_PT_POLAR_STEREO           "polar_stereographic"
+#define CF_PT_STEREO                 "stereographic"
+
+/* projection parameters */
+#define CF_PP_STD_PARALLEL           "standard_parallel"
+/* CF uses only "standard_parallel" */
+#define CF_PP_STD_PARALLEL_1         "standard_parallel_1"
+#define CF_PP_STD_PARALLEL_2         "standard_parallel_2"
+#define CF_PP_CENTRAL_MERIDIAN       "central_meridian"
+#define CF_PP_LONG_CENTRAL_MERIDIAN  "longitude_of_central_meridian"
+#define CF_PP_LON_PROJ_ORIGIN        "longitude_of_projection_origin"
+#define CF_PP_LAT_PROJ_ORIGIN        "latitude_of_projection_origin"
+/* #define PROJ_X_ORIGIN             "projection_x_coordinate_origin" */
+/* #define PROJ_Y_ORIGIN             "projection_y_coordinate_origin" */
+#define CF_PP_EARTH_SHAPE            "GRIB_earth_shape"
+#define CF_PP_EARTH_SHAPE_CODE       "GRIB_earth_shape_code"
+/* scale_factor is not CF, there are two possible translations  */
+/* for WKT scale_factor : SCALE_FACTOR_MERIDIAN and SCALE_FACTOR_ORIGIN */
+#define CF_PP_SCALE_FACTOR_MERIDIAN  "scale_factor_at_central_meridian"
+#define CF_PP_SCALE_FACTOR_ORIGIN    "scale_factor_at_projection_origin"
+#define CF_PP_VERT_LONG_FROM_POLE    "straight_vertical_longitude_from_pole"
+#define CF_PP_FALSE_EASTING          "false_easting"
+#define CF_PP_FALSE_NORTHING         "false_northing"
+#define CF_PP_EARTH_RADIUS           "earth_radius"
+#define CF_PP_EARTH_RADIUS_OLD       "spherical_earth_radius_meters"
+#define CF_PP_INVERSE_FLATTENING     "inverse_flattening"
+#define CF_PP_LONG_PRIME_MERIDIAN    "longitude_of_prime_meridian"
+#define CF_PP_SEMI_MAJOR_AXIS        "semi_major_axis"
+#define CF_PP_SEMI_MINOR_AXIS        "semi_minor_axis"
+#define CF_PP_VERT_PERSP             "vertical_perspective" /*not used yet */
+
+
+/* -------------------------------------------------------------------- */
+/*         CF-1 to GDAL mappings                                        */
+/* -------------------------------------------------------------------- */
+
+/* Following are a series of mappings from CF-1 convention parameters
+ * for each projection, to the equivalent in OGC WKT used internally by GDAL.
+ * See: http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.5/apf.html
+ */
+
+/* A struct allowing us to map between GDAL(OGC WKT) and CF-1 attributes */
 typedef struct {
-    const char *netCDFSRS;
-    const char *SRS; }
-oNetcdfSRS;
-
-static const oNetcdfSRS poNetcdfSRS[] = {
-    {"albers_conical_equal_area", SRS_PT_ALBERS_CONIC_EQUAL_AREA },
-    {"azimuthal_equidistant", SRS_PT_AZIMUTHAL_EQUIDISTANT },
-    {"cassini_soldner", SRS_PT_CASSINI_SOLDNER },
-    {"cylindrical_equal_area", SRS_PT_CYLINDRICAL_EQUAL_AREA },
-    {"eckert_iv", SRS_PT_ECKERT_IV },      
-    {"eckert_vi", SRS_PT_ECKERT_VI },  
-    {"equidistant_conic", SRS_PT_EQUIDISTANT_CONIC },
-    {"equirectangular", SRS_PT_EQUIRECTANGULAR },
-    {"gall_stereographic", SRS_PT_GALL_STEREOGRAPHIC },
-    {"geostationary_satellite", SRS_PT_GEOSTATIONARY_SATELLITE },
-    {"goode_homolosine", SRS_PT_GOODE_HOMOLOSINE },
-    {"gnomonic", SRS_PT_GNOMONIC },
-    {"hotine_oblique_mercator", SRS_PT_HOTINE_OBLIQUE_MERCATOR},
-    {"hotine_oblique_mercator_2P", 
-     SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN},
-    {"laborde_oblique_mercator", SRS_PT_LABORDE_OBLIQUE_MERCATOR },
-    {"lambert_conformal_conic1", SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP },
-    {"lambert_conformal_conic", SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP },
-    {"lambert_azimuthal_equal_area", SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA },
-    {"mercator_1sp", SRS_PT_MERCATOR_1SP },
-    {"mercator_2sp", SRS_PT_MERCATOR_2SP },
-    {"miller_cylindrical", SRS_PT_MILLER_CYLINDRICAL },
-    {"mollweide", SRS_PT_MOLLWEIDE },
-    {"new_zealand_map_grid", SRS_PT_NEW_ZEALAND_MAP_GRID },
-    {"oblique_stereographic", SRS_PT_OBLIQUE_STEREOGRAPHIC }, 
-    {"orthographic", SRS_PT_ORTHOGRAPHIC },
-    {"polar_stereographic", SRS_PT_POLAR_STEREOGRAPHIC },
-    {"polyconic", SRS_PT_POLYCONIC },
-    {"robinson", SRS_PT_ROBINSON }, 
-    {"sinusoidal", SRS_PT_SINUSOIDAL },  
-    {"stereographic", SRS_PT_STEREOGRAPHIC },
-    {"swiss_oblique_cylindrical", SRS_PT_SWISS_OBLIQUE_CYLINDRICAL},
-    {"transverse_mercator", SRS_PT_TRANSVERSE_MERCATOR },
-    {"TM_south_oriented", SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED },
-
-    {LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN },
-    {SCALE_FACTOR, SRS_PP_SCALE_FACTOR },   
-    {STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1 },
-    {STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2 },
-    {"longitude_of_central_meridian", SRS_PP_LONGITUDE_OF_CENTER },
-    {"longitude_of_projection_origin", SRS_PP_LONGITUDE_OF_ORIGIN }, 
-    {"latitude_of_projection_origin", SRS_PP_LATITUDE_OF_ORIGIN }, 
-    {FALSE_EASTING, SRS_PP_FALSE_EASTING },  
-    {FALSE_NORTHING, SRS_PP_FALSE_NORTHING },       
+    const char *CF_ATT;
+    const char *WKT_ATT; 
+    // TODO: mappings may need default values, like scale factor?
+    //double defval;
+} oNetcdfSRS_PP;
+
+// default mappings, for the generic case
+/* These 'generic' mappings are based on what was previously in the  
+   poNetCDFSRS struct. They will be used as a fallback in case none 
+   of the others match (ie you are exporting a projection that has 
+   no CF-1 equivalent). 
+   They are not used for known CF-1 projections since there is not a 
+   unique 2-way projection-independent 
+   mapping between OGC WKT params and CF-1 ones: it varies per-projection. 
+*/ 
+
+static const oNetcdfSRS_PP poGenericMappings[] = {
+    /* scale_factor is handled as a special case, write 2 values */
+    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1 }, 
+    {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2 }, 
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN }, 
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER }, 
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_ORIGIN },  
+    //Multiple mappings to LAT_PROJ_ORIGIN 
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN },  
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER },  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },   
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },        
     {NULL, NULL },
+};
+
+// Albers equal area 
+//
+// grid_mapping_name = albers_conical_equal_area
+// WKT: Albers_Conic_Equal_Area
+// ESPG:9822 
+//
+// Map parameters:
+//
+//    * standard_parallel - There may be 1 or 2 values.
+//    * longitude_of_central_meridian
+//    * latitude_of_projection_origin
+//    * false_easting
+//    * false_northing
+//
+static const oNetcdfSRS_PP poAEAMappings[] = {
+    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
+    {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2},
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
  };
 
+// Azimuthal equidistant
+//
+// grid_mapping_name = azimuthal_equidistant
+// WKT: Azimuthal_Equidistant
+//
+// Map parameters:
+//
+//    * longitude_of_projection_origin
+//    * latitude_of_projection_origin
+//    * false_easting
+//    * false_northing
+//
+static const oNetcdfSRS_PP poAEMappings[] = {
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_CENTER},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ };
+
+// Lambert azimuthal equal area
+//
+// grid_mapping_name = lambert_azimuthal_equal_area
+// WKT: Lambert_Azimuthal_Equal_Area
+//
+// Map parameters:
+//
+//    * longitude_of_projection_origin
+//    * latitude_of_projection_origin
+//    * false_easting
+//    * false_northing
+//
+static const oNetcdfSRS_PP poLAEAMappings[] = {
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_CENTER},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ };
+
+// Lambert conformal
+//
+// grid_mapping_name = lambert_conformal_conic
+// WKT: Lambert_Conformal_Conic_1SP / Lambert_Conformal_Conic_2SP
+//
+// Map parameters:
+//
+//    * standard_parallel - There may be 1 or 2 values.
+//    * longitude_of_central_meridian
+//    * latitude_of_projection_origin
+//    * false_easting
+//    * false_northing
+//
+// See http://www.remotesensing.org/geotiff/proj_list/lambert_conic_conformal_1sp.html 
+
+// Lambert conformal conic - 1SP
+/* See bug # 3324
+   It seems that the missing scale factor can be computed from standard_parallel1 and latitude_of_projection_origin.
+   If both are equal (the common case) then scale factor=1, else use Snyder eq. 15-4.
+   We save in the WKT standard_parallel1 for export to CF, but do not export scale factor.
+   If a WKT has a scale factor != 1 and no standard_parallel1 then export is not CF, but we output scale factor for compat.
+     is there a formula for that?
+*/
+static const oNetcdfSRS_PP poLCC1SPMappings[] = {
+    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR}, /* special case */
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ };
+
+// Lambert conformal conic - 2SP
+static const oNetcdfSRS_PP poLCC2SPMappings[] = {
+    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
+    {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2},
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ };
+
+// Lambert cylindrical equal area
+//
+// grid_mapping_name = lambert_cylindrical_equal_area
+// WKT: Cylindrical_Equal_Area
+// EPSG:9834 (Spherical) and EPSG:9835 
+//
+// Map parameters:
+//
+//    * longitude_of_central_meridian
+//    * either standard_parallel or scale_factor_at_projection_origin
+//    * false_easting
+//    * false_northing
+//
+// NB: CF-1 specifies a 'scale_factor_at_projection' alternative  
+//  to std_parallel ... but no reference to this in EPSG/remotesensing.org 
+//  ignore for now. 
+//
+static const oNetcdfSRS_PP poLCEAMappings[] = {
+    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ };
+
+// Latitude-Longitude
+//
+// grid_mapping_name = latitude_longitude
+//
+// Map parameters:
+//
+//    * None
+//
+// NB: handled as a special case - !isProjected()
+
+
+// Mercator
+//
+// grid_mapping_name = mercator
+// WKT: Mercator_1SP / Mercator_2SP
+//
+// Map parameters:
+//
+//    * longitude_of_projection_origin
+//    * either standard_parallel or scale_factor_at_projection_origin
+//    * false_easting
+//    * false_northing
+
+// Mercator 1 Standard Parallel (EPSG:9804) 
+static const oNetcdfSRS_PP poM1SPMappings[] = {
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
+    //LAT_PROJ_ORIGIN is always equator (0) in CF-1 
+    {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ };
+
+// Mercator 2 Standard Parallel
+static const oNetcdfSRS_PP poM2SPMappings[] = {
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
+    //From best understanding of this projection, only  
+ 	// actually specify one SP - it is the same N/S of equator. 
+    //{CF_PP_STD_PARALLEL_2, SRS_PP_LATITUDE_OF_ORIGIN}, 
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ };
+
+// Orthographic
+// grid_mapping_name = orthographic
+// WKT: Orthographic
+//
+// Map parameters:
+//
+//    * longitude_of_projection_origin
+//    * latitude_of_projection_origin
+//    * false_easting
+//    * false_northing
+//
+static const oNetcdfSRS_PP poOrthoMappings[] = {
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+ }; 
+
+// Polar stereographic
+//
+// grid_mapping_name = polar_stereographic
+// WKT: Polar_Stereographic
+//
+// Map parameters:
+//
+//    * straight_vertical_longitude_from_pole
+//    * latitude_of_projection_origin - Either +90. or -90.
+//    * Either standard_parallel or scale_factor_at_projection_origin
+//    * false_easting
+//    * false_northing
+
+/* 
+   (http://www.remotesensing.org/geotiff/proj_list/polar_stereographic.html)
+
+   Note: Projection parameters for this projection are quite different in CF-1 from
+     OGC WKT/GeoTiff (for the latter, see above).
+   From our best understanding, this projection requires more than a straight mapping:
+     - As defined below, 'latitude_of_origin' (WKT) -> 'standard_parallel' (CF-1)
+       and 'central_meridian' (WKT) -> 'straight_vertical_longitude_from_pole' (CF-1)
+     - Then the 'latitude_of_projection_origin' in CF-1 must be set to either +90 or -90,
+       depending on the sign of 'latitude_of_origin' in WKT.
+   CF allows the use of standard_parallel (lat_ts in proj4) OR scale_factor (k0 in proj4).
+   This is analogous to the B and A variants (resp.) in EPSG guidelines.
+   When importing a CF file with scale_factor, we compute standard_parallel using 
+     Snyder eq. 22-7 with k=1 and lat=standard_parallel.
+   Currently OGR does NOT relate the scale factor with the standard parallel, so we 
+   use the default. It seems that proj4 uses lat_ts (standard_parallel) and not k0.
+*/
+static const oNetcdfSRS_PP poPSmappings[] = {
+    {CF_PP_STD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN},
+    /* {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},   */
+    {CF_PP_VERT_LONG_FROM_POLE, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+};
+
+// Rotated Pole
+//
+// grid_mapping_name = rotated_latitude_longitude
+// WKT: N/A
+//
+// Map parameters:
+//
+//    * grid_north_pole_latitude
+//    * grid_north_pole_longitude
+//    * north_pole_grid_longitude - This parameter is optional (default is 0.).
+
+/* TODO: No GDAL equivalent of rotated pole? Doesn't seem to have an EPSG
+   code or WKT ... so unless some advanced proj4 features can be used 
+   seems to rule out.
+   see GDAL bug #4285 for a possible fix or workaround
+*/
+
+// Stereographic
+//
+// grid_mapping_name = stereographic
+// WKT: Stereographic (and/or Oblique_Stereographic??)
+//
+// Map parameters:
+//
+//    * longitude_of_projection_origin
+//    * latitude_of_projection_origin
+//    * scale_factor_at_projection_origin
+//    * false_easting
+//    * false_northing
+//
+// NB: see bug#4267 Stereographic vs. Oblique_Stereographic
+//
+static const oNetcdfSRS_PP poStMappings[] = {
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
+    {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},  
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+  };
+
+// Transverse Mercator
+//
+// grid_mapping_name = transverse_mercator
+// WKT: Transverse_Mercator
+//
+// Map parameters:
+//
+//    * scale_factor_at_central_meridian
+//    * longitude_of_central_meridian
+//    * latitude_of_projection_origin
+//    * false_easting
+//    * false_northing
+//
+static const oNetcdfSRS_PP poTMMappings[] = {
+    {CF_PP_SCALE_FACTOR_MERIDIAN, SRS_PP_SCALE_FACTOR},  
+    {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
+    {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
+    {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },  
+    {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
+    {NULL, NULL}
+  };
+
+// Vertical perspective
+//
+// grid_mapping_name = vertical_perspective
+// WKT: ???
+//
+// Map parameters:
+//
+//    * latitude_of_projection_origin
+//    * longitude_of_projection_origin
+//    * perspective_point_height
+//    * false_easting
+//    * false_northing
+//
+// TODO: see how to map this to OGR
+
+
+/* Mappings for various projections, including netcdf and GDAL projection names 
+   and corresponding oNetcdfSRS_PP mapping struct. 
+   A NULL mappings value means that the projection is not included in the CF
+   standard and the generic mapping (poGenericMappings) will be used. */
+typedef struct {
+    const char *CF_SRS;
+    const char *WKT_SRS; 
+    const oNetcdfSRS_PP* mappings;
+} oNetcdfSRS_PT;
+
+static const oNetcdfSRS_PT poNetcdfSRS_PT[] = {
+    {CF_PT_AEA, SRS_PT_ALBERS_CONIC_EQUAL_AREA, poAEAMappings },
+    {CF_PT_AE, SRS_PT_AZIMUTHAL_EQUIDISTANT, poAEMappings },
+    {"cassini_soldner", SRS_PT_CASSINI_SOLDNER, NULL },
+    {CF_PT_LCEA, SRS_PT_CYLINDRICAL_EQUAL_AREA, poLCEAMappings },
+    {"eckert_iv", SRS_PT_ECKERT_IV, NULL },      
+    {"eckert_vi", SRS_PT_ECKERT_VI, NULL },  
+    {"equidistant_conic", SRS_PT_EQUIDISTANT_CONIC, NULL },
+    {"equirectangular", SRS_PT_EQUIRECTANGULAR, NULL },
+    {"gall_stereographic", SRS_PT_GALL_STEREOGRAPHIC, NULL },
+    {"geostationary_satellite", SRS_PT_GEOSTATIONARY_SATELLITE, NULL },
+    {"goode_homolosine", SRS_PT_GOODE_HOMOLOSINE, NULL },
+    {"gnomonic", SRS_PT_GNOMONIC, NULL },
+    {"hotine_oblique_mercator", SRS_PT_HOTINE_OBLIQUE_MERCATOR, NULL },
+    {"hotine_oblique_mercator_2P", 
+     SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN, NULL },
+    {"laborde_oblique_mercator", SRS_PT_LABORDE_OBLIQUE_MERCATOR, NULL },
+    {CF_PT_LCC, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP, poLCC1SPMappings },
+    {CF_PT_LCC, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP, poLCC2SPMappings },
+    {CF_PT_LAEA, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA, poLAEAMappings },
+    {CF_PT_MERCATOR, SRS_PT_MERCATOR_1SP, poM1SPMappings },
+    {CF_PT_MERCATOR, SRS_PT_MERCATOR_2SP, poM2SPMappings },
+    {"miller_cylindrical", SRS_PT_MILLER_CYLINDRICAL, NULL },
+    {"mollweide", SRS_PT_MOLLWEIDE, NULL },
+    {"new_zealand_map_grid", SRS_PT_NEW_ZEALAND_MAP_GRID, NULL },
+    /* for now map to STEREO, see bug #4267 */
+    {"oblique_stereographic", SRS_PT_OBLIQUE_STEREOGRAPHIC, NULL }, 
+    /* {STEREO, SRS_PT_OBLIQUE_STEREOGRAPHIC, poStMappings },  */
+    {CF_PT_ORTHOGRAPHIC, SRS_PT_ORTHOGRAPHIC, poOrthoMappings },
+    {CF_PT_POLAR_STEREO, SRS_PT_POLAR_STEREOGRAPHIC, poPSmappings },
+    {"polyconic", SRS_PT_POLYCONIC, NULL },
+    {"robinson", SRS_PT_ROBINSON, NULL }, 
+    {"sinusoidal", SRS_PT_SINUSOIDAL, NULL },  
+    {CF_PT_STEREO, SRS_PT_STEREOGRAPHIC, poStMappings },
+    {"swiss_oblique_cylindrical", SRS_PT_SWISS_OBLIQUE_CYLINDRICAL, NULL },
+    {CF_PT_TM, SRS_PT_TRANSVERSE_MERCATOR, poTMMappings },
+    {"TM_south_oriented", SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED, NULL },
+    {NULL, NULL, NULL },
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*			     netCDFDataset		                             		*/
+/* ==================================================================== */
+/************************************************************************/
+
 class netCDFRasterBand;
 
 class netCDFDataset : public GDALPamDataset
 {
-    CPLString    osSubdatasetName;
-    int          bTreatAsSubdataset;
-
-    double      adfGeoTransform[6];
-    char        **papszSubDatasets;
-    char        **papszGeolocation;
-    CPLString    osFilename;
-    int          *panBandDimPos;         // X, Y, Z postion in array
-    int          *panBandZLev;
+    friend class netCDFRasterBand; //TMP
+
+    /* basic dataset vars */
+    CPLString     osFilename;
+    int           cdfid;
+    char          **papszSubDatasets;
+    char          **papszMetadata;
+    CPLStringList papszDimName;
+    bool          bBottomUp;
+    int           nFormat;
+    int           bIsGdalFile; /* was this file created by GDAL? */
+    int           bIsGdalCfFile; /* was this file created by the (new) CF-compliant driver? */
+
+    /* projection/GT */
+    double       adfGeoTransform[6];
     char         *pszProjection;
-    int          bGotGeoTransform;
+    int          nXDimID;
+    int          nYDimID;
+    int          bIsProjected;
+    int          bIsGeographic;
+
+    /* state vars */
+    int          status;
+    int          bDefineMode;
+    int          bSetProjection; 
+    int          bSetGeoTransform;
+    int          bAddedProjectionVars;
+
+    /* create vars */
+    char         **papszCreationOptions;
+    int          nCompress;
+    int          nZLevel;
+    int          nCreateMode;
+    int          bSignedData;
+
     double       rint( double );
 
     double       FetchCopyParm( const char *pszGridMappingValue, 
@@ -168,33 +628,53 @@ class netCDFDataset : public GDALPamDataset
 
     char **      FetchStandardParallels( const char *pszGridMappingValue );
 
-  public:
-    int           cdfid;
-    char         **papszMetadata;
-    char          papszDimName[NC_MAX_NAME][1024];
-    int          *paDimIds;
-    size_t        xdim, ydim;
-    int           nDimXid, nDimYid;
-    bool          bBottomUp;
-
-		netCDFDataset( );
-		~netCDFDataset( );
     
-    static GDALDataset *Open( GDALOpenInfo * );
+    /* new */
+    void ProcessCreationOptions( );
+    int DefVarDeflate( int nVarId, int bChunking=TRUE );
+    CPLErr AddProjectionVars( GDALProgressFunc pfnProgress=GDALDummyProgress, 
+                              void * pProgressData=NULL );
+
+    int GetDefineMode() { return bDefineMode; }
+    int SetDefineMode( int bNewDefineMode );
 
-    CPLErr      SafeStrcat(char**, char*, size_t*);
     CPLErr      ReadAttributes( int, int );
 
-    CPLErr 	GetGeoTransform( double * );    
+    void  CreateSubDatasetList( );
+
+    void  SetProjectionFromVar( int );
+
+  public:
 
+    netCDFDataset( );
+    ~netCDFDataset( );
+    
+    /* Projection/GT */
+    CPLErr 	GetGeoTransform( double * );    
+    CPLErr 	SetGeoTransform (double *);
     const char * GetProjectionRef();
+    CPLErr 	SetProjection (const char *);
 
     char ** GetMetadata( const char * );
 
-    void  CreateSubDatasetList( );
+    int GetCDFID() { return cdfid; }
 
-    void  SetProjection( int );
+    /* static functions */
+    static int Identify( GDALOpenInfo * );
+    static int IdentifyFormat( GDALOpenInfo *, bool );
+    static GDALDataset *Open( GDALOpenInfo * );
 
+    static netCDFDataset *CreateLL( const char * pszFilename,
+                                    int nXSize, int nYSize, int nBands,
+                                    char ** papszOptions );
+    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 );
+        
 };
 
 #endif
diff --git a/frmts/ngsgeoid/GNUmakefile b/frmts/ngsgeoid/GNUmakefile
new file mode 100644
index 0000000..227eff8
--- /dev/null
+++ b/frmts/ngsgeoid/GNUmakefile
@@ -0,0 +1,13 @@
+
+OBJ	=	ngsgeoiddataset.o
+
+include ../../GDALmake.opt
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/ngsgeoid/frmt_ngsgeoid.html b/frmts/ngsgeoid/frmt_ngsgeoid.html
new file mode 100644
index 0000000..f30ea7d
--- /dev/null
+++ b/frmts/ngsgeoid/frmt_ngsgeoid.html
@@ -0,0 +1,25 @@
+<html>
+<head>
+<title>NGSGEOID - NOAA NGS Geoid Height Grids</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>NGSGEOID - NOAA NGS Geoid Height Grids</h1>
+
+(Available for GDAL >= 1.9.0)
+<p>
+GDAL supports reading NOAA NGS geoid height grids in binary format (.bin files). Those files
+can be used for vertical datum transformations.
+<p>
+
+<h2>See also</h2>
+
+<ul>
+<li><a href="http://www.ngs.noaa.gov/GEOID/USGG2009/s2009rme.txt">Description of NGS Geoid Height Grids format</a></li>
+<li><a href="http://www.ngs.noaa.gov/PC_PROD/GEOID09/">GEOID09 main page</a></li>
+<li><a href="http://www.ngs.noaa.gov/PC_PROD/USGG2009/">USGG2009 main page</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/ngsgeoid/makefile.vc b/frmts/ngsgeoid/makefile.vc
new file mode 100644
index 0000000..72cd3b7
--- /dev/null
+++ b/frmts/ngsgeoid/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ	=	ngsgeoiddataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/ngsgeoid/ngsgeoiddataset.cpp b/frmts/ngsgeoid/ngsgeoiddataset.cpp
new file mode 100644
index 0000000..ec5c5f1
--- /dev/null
+++ b/frmts/ngsgeoid/ngsgeoiddataset.cpp
@@ -0,0 +1,428 @@
+/******************************************************************************
+ * $Id: ngsgeoiddataset.cpp 23334 2011-11-05 22:40:46Z 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
+ *
+ * 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_vsi_virtual.h"
+#include "cpl_string.h"
+#include "gdal_pam.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: ngsgeoiddataset.cpp 23334 2011-11-05 22:40:46Z rouault $");
+
+CPL_C_START
+void    GDALRegister_NGSGEOID(void);
+CPL_C_END
+
+#define HEADER_SIZE (4 * 8 + 3 * 4)
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            NGSGEOIDDataset                           */
+/* ==================================================================== */
+/************************************************************************/
+
+class NGSGEOIDRasterBand;
+
+class NGSGEOIDDataset : public GDALPamDataset
+{
+    friend class NGSGEOIDRasterBand;
+
+    VSILFILE   *fp;
+    double      adfGeoTransform[6];
+    int         bIsLittleEndian;
+
+    static int   GetHeaderInfo( const GByte* pBuffer,
+                                double* padfGeoTransform,
+                                int* pnRows,
+                                int* pnCols,
+                                int* pbIsLittleEndian );
+
+  public:
+                 NGSGEOIDDataset();
+    virtual     ~NGSGEOIDDataset();
+
+    virtual CPLErr GetGeoTransform( double * );
+    virtual const char* GetProjectionRef();
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          NGSGEOIDRasterBand                          */
+/* ==================================================================== */
+/************************************************************************/
+
+class NGSGEOIDRasterBand : public GDALPamRasterBand
+{
+    friend class NGSGEOIDDataset;
+
+  public:
+
+                NGSGEOIDRasterBand( NGSGEOIDDataset * );
+
+    virtual CPLErr IReadBlock( int, int, void * );
+
+    virtual const char* GetUnitType() { return "m"; }
+};
+
+
+/************************************************************************/
+/*                        NGSGEOIDRasterBand()                          */
+/************************************************************************/
+
+NGSGEOIDRasterBand::NGSGEOIDRasterBand( NGSGEOIDDataset *poDS )
+
+{
+    this->poDS = poDS;
+    this->nBand = 1;
+
+    eDataType = GDT_Float32;
+
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr NGSGEOIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                       void * pImage )
+
+{
+    NGSGEOIDDataset *poGDS = (NGSGEOIDDataset *) poDS;
+
+    /* First values in the file corresponds to the south-most line of the imagery */
+    VSIFSeekL(poGDS->fp,
+              HEADER_SIZE + (nRasterYSize - 1 - nBlockYOff) * nRasterXSize * 4,
+              SEEK_SET);
+
+    if ((int)VSIFReadL(pImage, 4, nRasterXSize, poGDS->fp) != nRasterXSize)
+        return CE_Failure;
+
+    if (poGDS->bIsLittleEndian)
+    {
+#ifdef CPL_MSB
+        GDALSwapWords( pImage, 4, nRasterXSize, 4 );
+#endif
+    }
+    else
+    {
+#ifdef CPL_LSB
+        GDALSwapWords( pImage, 4, nRasterXSize, 4 );
+#endif
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          ~NGSGEOIDDataset()                          */
+/************************************************************************/
+
+NGSGEOIDDataset::NGSGEOIDDataset()
+{
+    fp = NULL;
+    adfGeoTransform[0] = 0;
+    adfGeoTransform[1] = 1;
+    adfGeoTransform[2] = 0;
+    adfGeoTransform[3] = 0;
+    adfGeoTransform[4] = 0;
+    adfGeoTransform[5] = 1;
+    bIsLittleEndian = TRUE;
+}
+
+/************************************************************************/
+/*                           ~NGSGEOIDDataset()                         */
+/************************************************************************/
+
+NGSGEOIDDataset::~NGSGEOIDDataset()
+
+{
+    FlushCache();
+    if (fp)
+        VSIFCloseL(fp);
+}
+
+/************************************************************************/
+/*                            GetHeaderInfo()                           */
+/************************************************************************/
+
+int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
+                                    double* padfGeoTransform,
+                                    int* pnRows,
+                                    int* pnCols,
+                                    int* pbIsLittleEndian )
+{
+    double dfSLAT;
+    double dfWLON;
+    double dfDLAT;
+    double dfDLON;
+    int nNLAT;
+    int nNLON;
+    int nIKIND;
+
+    /* First check IKIND marker to determine if the file */
+    /* is in little or big-endian order, and if it is a valid */
+    /* NGSGEOID dataset */
+    memcpy(&nIKIND, pBuffer + HEADER_SIZE - 4, 4);
+    CPL_LSBPTR32(&nIKIND);
+    if (nIKIND == 1)
+    {
+        *pbIsLittleEndian = TRUE;
+    }
+    else
+    {
+        memcpy(&nIKIND, pBuffer + HEADER_SIZE - 4, 4);
+        CPL_MSBPTR32(&nIKIND);
+        if (nIKIND == 1)
+        {
+            *pbIsLittleEndian = FALSE;
+        }
+        else
+        {
+            return FALSE;
+        }
+    }
+
+    memcpy(&dfSLAT, pBuffer, 8);
+    if (*pbIsLittleEndian)
+    {
+        CPL_LSBPTR64(&dfSLAT);
+    }
+    else
+    {
+        CPL_MSBPTR64(&dfSLAT);
+    }
+    pBuffer += 8;
+    memcpy(&dfWLON, pBuffer, 8);
+    if (*pbIsLittleEndian)
+    {
+        CPL_LSBPTR64(&dfWLON);
+    }
+    else
+    {
+        CPL_MSBPTR64(&dfWLON);
+    }
+    pBuffer += 8;
+    memcpy(&dfDLAT, pBuffer, 8);
+    if (*pbIsLittleEndian)
+    {
+        CPL_LSBPTR64(&dfDLAT);
+    }
+    else
+    {
+        CPL_MSBPTR64(&dfDLAT);
+    }
+    pBuffer += 8;
+    memcpy(&dfDLON, pBuffer, 8);
+    if (*pbIsLittleEndian)
+    {
+        CPL_LSBPTR64(&dfDLON);
+    }
+    else
+    {
+        CPL_MSBPTR64(&dfDLON);
+    }
+    pBuffer += 8;
+    memcpy(&nNLAT, pBuffer, 4);
+    if (*pbIsLittleEndian)
+    {
+        CPL_LSBPTR32(&nNLAT);
+    }
+    else
+    {
+        CPL_MSBPTR32(&nNLAT);
+    }
+    pBuffer += 4;
+    memcpy(&nNLON, pBuffer, 4);
+    if (*pbIsLittleEndian)
+    {
+        CPL_LSBPTR32(&nNLON);
+    }
+    else
+    {
+        CPL_MSBPTR32(&nNLON);
+    }
+    pBuffer += 4;
+
+    /*CPLDebug("NGSGEOID", "SLAT=%f, WLON=%f, DLAT=%f, DLON=%f, NLAT=%d, NLON=%d, IKIND=%d",
+             dfSLAT, dfWLON, dfDLAT, dfDLON, nNLAT, nNLON, nIKIND);*/
+
+    if (nNLAT <= 0 || nNLON <= 0 || dfDLAT <= 0.0 || dfDLON <= 0.0)
+        return FALSE;
+
+    /* Grids go over +180 in longitude */
+    if (dfSLAT < -90.0 || dfSLAT + nNLAT * dfDLAT > 90.0 ||
+        dfWLON < -180.0 || dfWLON + nNLON * dfDLON > 360.0)
+        return FALSE;
+
+    padfGeoTransform[0] = dfWLON - dfDLON / 2;
+    padfGeoTransform[1] = dfDLON;
+    padfGeoTransform[2] = 0.0;
+    padfGeoTransform[3] = dfSLAT + nNLAT * dfDLAT - dfDLAT / 2;
+    padfGeoTransform[4] = 0.0;
+    padfGeoTransform[5] = -dfDLAT;
+
+    *pnRows = nNLAT;
+    *pnCols = nNLON;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int NGSGEOIDDataset::Identify( GDALOpenInfo * poOpenInfo )
+{
+    if (poOpenInfo->nHeaderBytes < HEADER_SIZE)
+        return FALSE;
+
+    double adfGeoTransform[6];
+    int nRows, nCols;
+    int bIsLittleEndian;
+    if ( !GetHeaderInfo( poOpenInfo->pabyHeader,
+                         adfGeoTransform,
+                         &nRows, &nCols, &bIsLittleEndian ) )
+        return FALSE;
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *NGSGEOIDDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+    if (poOpenInfo->eAccess == GA_Update)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "The NGSGEOID driver does not support update access to existing"
+                  " datasets.\n" );
+        return NULL;
+    }
+
+    VSILFILE* fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+    if (fp == NULL)
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    NGSGEOIDDataset         *poDS;
+
+    poDS = new NGSGEOIDDataset();
+    poDS->fp = fp;
+
+    int nRows, nCols;
+    GetHeaderInfo( poOpenInfo->pabyHeader,
+                   poDS->adfGeoTransform,
+                   &nRows,
+                   &nCols,
+                   &poDS->bIsLittleEndian );
+    poDS->nRasterXSize = nCols;
+    poDS->nRasterYSize = nRows;
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    poDS->nBands = 1;
+    poDS->SetBand( 1, new NGSGEOIDRasterBand( poDS ) );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Support overviews.                                              */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    return( poDS );
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr NGSGEOIDDataset::GetGeoTransform( double * padfTransform )
+
+{
+    memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
+
+    return( CE_None );
+}
+
+/************************************************************************/
+/*                         GetProjectionRef()                           */
+/************************************************************************/
+
+const char* NGSGEOIDDataset::GetProjectionRef()
+{
+    return SRS_WKT_WGS84;
+}
+
+/************************************************************************/
+/*                       GDALRegister_NGSGEOID()                        */
+/************************************************************************/
+
+void GDALRegister_NGSGEOID()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "NGSGEOID" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "NGSGEOID" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "NOAA NGS Geoid Height Grids" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                   "frmt_ngsgeoid.html" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bin" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnOpen = NGSGEOIDDataset::Open;
+        poDriver->pfnIdentify = NGSGEOIDDataset::Identify;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
+
diff --git a/frmts/nitf/GNUmakefile b/frmts/nitf/GNUmakefile
index 308df11..d175844 100644
--- a/frmts/nitf/GNUmakefile
+++ b/frmts/nitf/GNUmakefile
@@ -2,13 +2,17 @@
 
 include ../../GDALmake.opt
 
-GDAL_OBJ	=	nitfdataset.o rpftocdataset.o nitfwritejpeg.o nitfwritejpeg_12.o
-NITFLIB_OBJ	=	nitffile.o nitfimage.o mgrs.o nitfaridpcm.o \
-			nitfbilevel.o rpftocfile.o nitfdes.o
+GDAL_OBJ =	nitfdataset.o rpftocdataset.o nitfwritejpeg.o \
+		nitfwritejpeg_12.o nitfrasterband.o ecrgtocdataset.o
+NITFLIB_OBJ =	nitffile.o nitfimage.o mgrs.o nitfaridpcm.o \
+		nitfbilevel.o rpftocfile.o nitfdes.o nitf_gcprpc.o
 
 CPPFLAGS	:=	-I../vrt $(GDAL_INCLUDE) $(CPPFLAGS)
 
 ifeq ($(TIFF_SETTING),internal)
+ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
+CPPFLAGS 	:=	$(CPPFLAGS) -DRENAME_INTERNAL_LIBTIFF_SYMBOLS
+endif
 CPPFLAGS	:=	$(CPPFLAGS) -I../gtiff/libtiff
 endif
 
@@ -22,10 +26,8 @@ endif
 
 ifeq ($(JPEG12_ENABLED),yes)
 CPPFLAGS	:=	$(CPPFLAGS) -DJPEG_DUAL_MODE_8_12
-ifeq ($(JPEG_SETTING),internal)
 PREDEPEND 	=	libjpeg12
 endif
-endif
 
 OBJ = $(GDAL_OBJ) $(NITFLIB_OBJ)
 
diff --git a/frmts/nitf/ecrgtocdataset.cpp b/frmts/nitf/ecrgtocdataset.cpp
new file mode 100644
index 0000000..9cfcad1
--- /dev/null
+++ b/frmts/nitf/ecrgtocdataset.cpp
@@ -0,0 +1,1055 @@
+/******************************************************************************
+ * $Id: ecrgtocdataset.cpp 23033 2011-09-03 18:46:11Z 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
+ *
+ * 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.
+ ****************************************************************************/
+
+// g++ -g -Wall -fPIC frmts/nitf/ecrgtocdataset.cpp -shared -o gdal_ECRGTOC.so -Iport -Igcore -Iogr -Ifrmts/vrt -L. -lgdal
+
+#include "gdal_proxy.h"
+#include "ogr_srs_api.h"
+#include "vrtdataset.h"
+#include "cpl_minixml.h"
+#include <vector>
+
+CPL_CVSID("$Id: ecrgtocdataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
+
+/** Overview of used classes :
+   - ECRGTOCDataset : lists the different subdatasets, listed in the .xml,
+                      as subdatasets
+   - ECRGTOCSubDataset : one of these subdatasets, implemented as a VRT, of
+                         the relevant NITF tiles
+   - ECRGTOCProxyRasterDataSet : a "proxy" dataset that maps to a NITF tile
+*/
+
+typedef struct
+{
+    const char* pszName;
+    const char* pszPath;
+    int         nScale;
+    int         nZone;
+} FrameDesc;
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ECRGTOCDataset                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class ECRGTOCDataset : public GDALPamDataset
+{
+  char	    **papszSubDatasets;
+  double      adfGeoTransform[6];
+  
+  char      **papszFileList;
+
+  public:
+    ECRGTOCDataset()
+    {
+        papszSubDatasets = NULL;
+        papszFileList = NULL;
+    }
+
+    ~ECRGTOCDataset()
+    {
+        CSLDestroy( papszSubDatasets );
+        CSLDestroy(papszFileList);
+    }
+
+    virtual char      **GetMetadata( const char * pszDomain = "" );
+
+    virtual char      **GetFileList() { return CSLDuplicate(papszFileList); }
+
+    void                AddSubDataset(const char* pszFilename,
+                                      const char* pszProductTitle,
+                                      const char* pszDiscId);
+
+    virtual CPLErr GetGeoTransform( double * padfGeoTransform)
+    {
+        memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
+        return CE_None;
+    }
+
+    virtual const char *GetProjectionRef(void)
+    {
+        return SRS_WKT_WGS84;
+    }
+    
+    static GDALDataset* Build(  const char* pszTOCFilename,
+                                CPLXMLNode* psXML,
+                                CPLString osProduct,
+                                CPLString osDiscId,
+                                const char* pszFilename);
+    
+    static int Identify( GDALOpenInfo * poOpenInfo );
+    static GDALDataset* Open( GDALOpenInfo * poOpenInfo );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ECRGTOCSubDataset                          */
+/* ==================================================================== */
+/************************************************************************/
+
+class ECRGTOCSubDataset : public VRTDataset
+{
+  char**       papszFileList;
+
+  public:
+    ECRGTOCSubDataset(int nXSize, int nYSize) : VRTDataset(nXSize, nYSize)
+    {
+        /* Don't try to write a VRT file */
+        SetWritable(FALSE);
+
+        /* The driver is set to VRT in VRTDataset constructor. */
+        /* We have to set it to the expected value ! */
+        poDriver = (GDALDriver *) GDALGetDriverByName( "ECRGTOC" );
+
+        papszFileList = NULL;
+    }
+    
+    ~ECRGTOCSubDataset()
+    {
+        CSLDestroy(papszFileList);
+    }
+
+    virtual char      **GetFileList() { return CSLDuplicate(papszFileList); }
+
+    static GDALDataset* Build(  const char* pszProductTitle,
+                                const char* pszDiscId,
+                                int nScale,
+                                int nCountSubDataset,
+                                const char* pszTOCFilename,
+                                const std::vector<FrameDesc>& aosFrameDesc,
+                                double dfGlobalMinX,
+                                double dfGlobalMinY,
+                                double dfGlobalMaxX,
+                                double dfGlobalMaxY,
+                                double dfGlobalPixelXSize,
+                                double dfGlobalPixelYSize);
+};
+
+/************************************************************************/
+/*                           AddSubDataset()                            */
+/************************************************************************/
+
+void ECRGTOCDataset::AddSubDataset( const char* pszFilename,
+                                    const char* pszProductTitle,
+                                    const char* pszDiscId )
+
+{
+    char	szName[80];
+    int		nCount = CSLCount(papszSubDatasets ) / 2;
+
+    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets = 
+        CSLSetNameValue( papszSubDatasets, szName, 
+              CPLSPrintf( "ECRG_TOC_ENTRY:%s:%s:%s",
+                          pszProductTitle, pszDiscId, pszFilename ) );
+
+    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName,
+            CPLSPrintf( "%s:%s", pszProductTitle, pszDiscId));
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **ECRGTOCDataset::GetMetadata( const char *pszDomain )
+
+{
+    if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+        return papszSubDatasets;
+
+    return GDALPamDataset::GetMetadata( pszDomain );
+}
+
+/************************************************************************/
+/*                         GetScaleFromString()                         */
+/************************************************************************/
+
+static int GetScaleFromString(const char* pszScale)
+{
+    const char* pszPtr = strstr(pszScale, "1:");
+    if (pszPtr)
+        pszPtr = pszPtr + 2;
+    else
+        pszPtr = pszScale;
+
+    int nScale = 0;
+    char ch;
+    while((ch = *pszPtr) != '\0')
+    {
+        if (ch >= '0' && ch <= '9')
+            nScale = nScale * 10 + ch - '0';
+        else if (ch == ' ')
+            ;
+        else if (ch == 'k' || ch == 'K')
+            return nScale * 1000;
+        else if (ch == 'm' || ch == 'M')
+            return nScale * 1000000;
+        else
+            return 0;
+        pszPtr ++;
+    }
+    return nScale;
+}
+
+/************************************************************************/
+/*                            GetFromBase34()                           */
+/************************************************************************/
+
+static GIntBig GetFromBase34(const char* pszVal, int nMaxSize)
+{
+    int i;
+    GIntBig nFrameNumber = 0;
+    for(i=0;i<nMaxSize;i++)
+    {
+        char ch = pszVal[i];
+        if (ch == '\0')
+            break;
+        int chVal;
+        if (ch >= 'A' && ch <= 'Z')
+            ch += 'a' - 'A';
+        /* i and o letters are excluded, */
+        if (ch >= '0' && ch <= '9')
+            chVal = ch - '0';
+        else if (ch >= 'a' && ch <= 'h')
+            chVal = ch - 'a' + 10;
+        else if (ch >= 'j' && ch < 'n')
+            chVal = ch - 'a' + 10 - 1;
+        else if (ch > 'p' && ch <= 'z')
+            chVal = ch - 'a' + 10 - 2;
+        else
+        {
+            CPLDebug("ECRG", "Invalid base34 value : %s", pszVal);
+            break;
+        }
+        nFrameNumber = nFrameNumber * 34 + chVal;
+    }
+
+    return nFrameNumber;
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+/* MIL-PRF-32283 - Table II. ECRG zone limits. */
+/* starting with a fake zone 0 for conveniency */
+static const int anZoneUpperLat[] = { 0, 32, 48, 56, 64, 68, 72, 76, 80 };
+
+/* APPENDIX 70, TABLE III of MIL-A-89007 */
+static const int anACst_ADRG[] =
+    { 369664, 302592, 245760, 199168, 163328, 137216, 110080, 82432 };
+static const int nBCst_ADRG = 400384;
+
+#define CEIL_ROUND(a, b)  (int)(ceil((double)(a)/(b))*(b))
+#define NEAR_ROUND(a, b)  (int)(floor((double)(a)/(b) + 0.5)*(b))
+
+#define ECRG_PIXELS         2304
+
+static
+int GetExtent(const char* pszFrameName, int nScale, int nZone,
+              double& dfMinX, double& dfMaxX, double& dfMinY, double& dfMaxY,
+              double& dfPixelXSize, double& dfPixelYSize)
+{
+    int nAbsZone = abs(nZone);
+
+/************************************************************************/
+/*  Compute east-west constant                                          */
+/************************************************************************/
+    /* MIL-PRF-89038 - 60.1.2 - East-west pixel constant. */
+    int nEW_ADRG = CEIL_ROUND(anACst_ADRG[nAbsZone-1] * (1e6 / nScale), 512);
+    int nEW_CADRG = NEAR_ROUND(nEW_ADRG / (150. / 100.), 256);
+    /* MIL-PRF-32283 - D.2.1.2 - East-west pixel constant. */
+    int nEW = nEW_CADRG / 256 * 384;
+
+/************************************************************************/
+/*  Compute number of longitudinal frames                               */
+/************************************************************************/
+    /* MIL-PRF-32283 - D.2.1.7 - Longitudinal frames and subframes */
+    int nCols = (int)ceil((double)nEW / ECRG_PIXELS);
+
+/************************************************************************/
+/*  Compute north-south constant                                        */
+/************************************************************************/
+    /* MIL-PRF-89038 - 60.1.1 -  North-south. pixel constant */
+    int nNS_ADRG = CEIL_ROUND(nBCst_ADRG * (1e6 / nScale), 512) / 4;
+    int nNS_CADRG = NEAR_ROUND(nNS_ADRG / (150. / 100.), 256);
+    /* MIL-PRF-32283 - D.2.1.1 - North-south. pixel constant and Frame Width/Height */
+    int nNS = nNS_CADRG / 256 * 384;
+
+/************************************************************************/
+/*  Compute number of latitudinal frames and latitude of top of zone    */
+/************************************************************************/
+    dfPixelYSize = 90.0 / nNS;
+
+    double dfFrameLatHeight = dfPixelYSize * ECRG_PIXELS;
+
+    /* MIL-PRF-32283 - D.2.1.5 - Equatorward and poleward zone extents. */
+    int nUpperZoneFrames = (int)ceil(anZoneUpperLat[nAbsZone] / dfFrameLatHeight);
+    int nBottomZoneFrames = (int)floor(anZoneUpperLat[nAbsZone-1] / dfFrameLatHeight);
+    int nRows = nUpperZoneFrames - nBottomZoneFrames;
+
+    /* Not sure to really understand D.2.1.5.a. Testing needed */
+    if (nZone < 0)
+    {
+        nUpperZoneFrames = -nBottomZoneFrames;
+        nBottomZoneFrames = nUpperZoneFrames - nRows;
+    }
+
+    double dfUpperZoneTopLat = dfFrameLatHeight * nUpperZoneFrames;
+
+/************************************************************************/
+/*  Compute coordinates of the frame in the zone                        */
+/************************************************************************/
+
+    /* Converts the first 10 characters into a number from base 34 */
+    GIntBig nFrameNumber = GetFromBase34(pszFrameName, 10);
+
+    /*  MIL-PRF-32283 - A.2.6.1 */
+    GIntBig nY = nFrameNumber / nCols;
+    GIntBig nX = nFrameNumber % nCols;
+
+/************************************************************************/
+/*  Compute extent of the frame                                         */
+/************************************************************************/
+
+    /* The nY is counted from the bottom of the zone... Pfff */
+    dfMaxY = dfUpperZoneTopLat - (nRows - 1 - nY) * dfFrameLatHeight;
+    dfMinY = dfMaxY - dfFrameLatHeight;
+
+    dfPixelXSize = 360.0 / nEW;
+
+    double dfFrameLongWidth = dfPixelXSize * ECRG_PIXELS;
+    dfMinX = -180.0 + nX * dfFrameLongWidth;
+    dfMaxX = dfMinX + dfFrameLongWidth;
+
+    //CPLDebug("ECRG", "Frame %s : minx=%.16g, maxy=%.16g, maxx=%.16g, miny=%.16g",
+    //         pszFrameName, dfMinX, dfMaxY, dfMaxX, dfMinY);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        ECRGTOCProxyRasterDataSet                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class ECRGTOCProxyRasterDataSet : public GDALProxyPoolDataset
+{
+    /* The following parameters are only for sanity checking */
+    int checkDone;
+    int checkOK;
+    double dfMinX;
+    double dfMaxY;
+    double dfPixelXSize;
+    double dfPixelYSize;
+    ECRGTOCSubDataset* poSubDataset;
+
+    public:
+        ECRGTOCProxyRasterDataSet(ECRGTOCSubDataset* poSubDataset,
+                                  const char* fileName,
+                                  int nXSize, int nYSize,
+                                  double dfMinX, double dfMaxY,
+                                  double dfPixelXSize, double dfPixelYSize);
+
+        GDALDataset* RefUnderlyingDataset()
+        {
+            GDALDataset* poSourceDS = GDALProxyPoolDataset::RefUnderlyingDataset();
+            if (poSourceDS)
+            {
+                if (!checkDone)
+                    SanityCheckOK(poSourceDS);
+                if (!checkOK)
+                {
+                    GDALProxyPoolDataset::UnrefUnderlyingDataset(poSourceDS);
+                    poSourceDS = NULL;
+                }
+            }
+            return poSourceDS;
+        }
+
+        void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset)
+        {
+            GDALProxyPoolDataset::UnrefUnderlyingDataset(poUnderlyingDataset);
+        }
+
+        int SanityCheckOK(GDALDataset* poSourceDS);
+};
+
+/************************************************************************/
+/*                    ECRGTOCProxyRasterDataSet()                       */
+/************************************************************************/
+
+ECRGTOCProxyRasterDataSet::ECRGTOCProxyRasterDataSet
+        (ECRGTOCSubDataset* poSubDataset,
+         const char* fileName,
+         int nXSize, int nYSize,
+         double dfMinX, double dfMaxY,
+         double dfPixelXSize, double dfPixelYSize) :
+            /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */
+                GDALProxyPoolDataset(fileName, nXSize, nYSize, GA_ReadOnly, TRUE, SRS_WKT_WGS84)
+{
+    int i;
+    this->poSubDataset = poSubDataset;
+    this->dfMinX = dfMinX;
+    this->dfMaxY = dfMaxY;
+    this->dfPixelXSize = dfPixelXSize;
+    this->dfPixelYSize = dfPixelYSize;
+
+    checkDone = FALSE;
+    checkOK = FALSE;
+
+    for(i=0;i<3;i++)
+    {
+        SetBand(i + 1, new GDALProxyPoolRasterBand(this, i+1, GDT_Byte, nXSize, 1));
+    }
+}
+
+/************************************************************************/
+/*                    SanityCheckOK()                                   */
+/************************************************************************/
+
+#define WARN_CHECK_DS(x) do { if (!(x)) { CPLError(CE_Warning, CPLE_AppDefined,\
+    "For %s, assert '" #x "' failed", GetDescription()); checkOK = FALSE; } } while(0)
+
+int ECRGTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* poSourceDS)
+{
+    /*int nSrcBlockXSize, nSrcBlockYSize;
+    int nBlockXSize, nBlockYSize;*/
+    double adfGeoTransform[6];
+    if (checkDone)
+        return checkOK;
+
+    checkOK = TRUE;
+    checkDone = TRUE;
+
+    poSourceDS->GetGeoTransform(adfGeoTransform);
+    WARN_CHECK_DS(fabs(adfGeoTransform[0] - dfMinX) < 1e-10);
+    WARN_CHECK_DS(fabs(adfGeoTransform[3] - dfMaxY) < 1e-10);
+    WARN_CHECK_DS(fabs(adfGeoTransform[1] - dfPixelXSize) < 1e-10);
+    WARN_CHECK_DS(fabs(adfGeoTransform[5] - (-dfPixelYSize)) < 1e-10);
+    WARN_CHECK_DS(adfGeoTransform[2] == 0 &&
+                  adfGeoTransform[4] == 0); /* No rotation */
+    WARN_CHECK_DS(poSourceDS->GetRasterCount() == 3);
+    WARN_CHECK_DS(poSourceDS->GetRasterXSize() == nRasterXSize);
+    WARN_CHECK_DS(poSourceDS->GetRasterYSize() == nRasterYSize);
+    WARN_CHECK_DS(EQUAL(poSourceDS->GetProjectionRef(), SRS_WKT_WGS84));
+    /*poSourceDS->GetRasterBand(1)->GetBlockSize(&nSrcBlockXSize, &nSrcBlockYSize);
+    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    WARN_CHECK_DS(nSrcBlockXSize == nBlockXSize);
+    WARN_CHECK_DS(nSrcBlockYSize == nBlockYSize);*/
+    WARN_CHECK_DS(poSourceDS->GetRasterBand(1)->GetRasterDataType() == GDT_Byte);
+
+    return checkOK;
+}
+
+/************************************************************************/
+/*                           BuildFullName()                            */
+/************************************************************************/
+
+static const char* BuildFullName(const char* pszTOCFilename,
+                                 const char* pszFramePath,
+                                 const char* pszFrameName)
+{
+    char* pszPath;
+    if (pszFramePath[0] == '.' &&
+        (pszFramePath[1] == '/' ||pszFramePath[1] == '\\'))
+        pszPath = CPLStrdup(pszFramePath + 2);
+    else
+        pszPath = CPLStrdup(pszFramePath);
+    for(int i=0;pszPath[i] != '\0';i++)
+    {
+        if (pszPath[i] == '\\')
+            pszPath[i] = '/';
+    }
+    const char* pszName = CPLFormFilename(pszPath, pszFrameName, NULL);
+    CPLFree(pszPath);
+    pszPath = NULL;
+    const char* pszTOCPath = CPLGetDirname(pszTOCFilename);
+    const char* pszFirstSlashInName = strchr(pszName, '/');
+    if (pszFirstSlashInName != NULL)
+    {
+        int nFirstDirLen = pszFirstSlashInName - pszName;
+        if ((int)strlen(pszTOCPath) >= nFirstDirLen + 1 &&
+            (pszTOCPath[strlen(pszTOCPath) - (nFirstDirLen + 1)] == '/' ||
+                pszTOCPath[strlen(pszTOCPath) - (nFirstDirLen + 1)] == '\\') &&
+            strncmp(pszTOCPath + strlen(pszTOCPath) - nFirstDirLen, pszName, nFirstDirLen) == 0)
+        {
+            pszTOCPath = CPLGetDirname(pszTOCPath);
+        }
+    }
+    return CPLProjectRelativeFilename(pszTOCPath, pszName);
+}
+
+/************************************************************************/
+/*                              Build()                                 */
+/************************************************************************/
+
+/* Builds a ECRGTOCSubDataset from the set of files of the toc entry */
+GDALDataset* ECRGTOCSubDataset::Build(  const char* pszProductTitle,
+                                        const char* pszDiscId,
+                                        int nScale,
+                                        int nCountSubDataset,
+                                        const char* pszTOCFilename,
+                                        const std::vector<FrameDesc>& aosFrameDesc,
+                                        double dfGlobalMinX,
+                                        double dfGlobalMinY,
+                                        double dfGlobalMaxX,
+                                        double dfGlobalMaxY,
+                                        double dfGlobalPixelXSize,
+                                        double dfGlobalPixelYSize)
+    {
+    int i, j;
+    GDALDriver *poDriver;
+    ECRGTOCSubDataset *poVirtualDS;
+    int nSizeX, nSizeY;
+    double adfGeoTransform[6];
+
+    poDriver = GetGDALDriverManager()->GetDriverByName("VRT");
+    if( poDriver == NULL )
+        return NULL;
+
+    nSizeX = (int)((dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize + 0.5);
+    nSizeY = (int)((dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize + 0.5);
+
+    /* ------------------------------------ */
+    /* Create the VRT with the overall size */
+    /* ------------------------------------ */
+    poVirtualDS = new ECRGTOCSubDataset( nSizeX, nSizeY );
+
+    poVirtualDS->SetProjection(SRS_WKT_WGS84);
+
+    adfGeoTransform[0] = dfGlobalMinX;
+    adfGeoTransform[1] = dfGlobalPixelXSize;
+    adfGeoTransform[2] = 0;
+    adfGeoTransform[3] = dfGlobalMaxY;
+    adfGeoTransform[4] = 0;
+    adfGeoTransform[5] = -dfGlobalPixelYSize;
+    poVirtualDS->SetGeoTransform(adfGeoTransform);
+
+    for (i=0;i<3;i++)
+    {
+        poVirtualDS->AddBand(GDT_Byte, NULL);
+        GDALRasterBand *poBand = poVirtualDS->GetRasterBand( i + 1 );
+        poBand->SetColorInterpretation((GDALColorInterp)(GCI_RedBand+i));
+    }
+
+    poVirtualDS->SetDescription(pszTOCFilename);
+
+    poVirtualDS->SetMetadataItem("PRODUCT_TITLE", pszProductTitle);
+    poVirtualDS->SetMetadataItem("DISC_ID", pszDiscId);
+    if (nScale != -1)
+        poVirtualDS->SetMetadataItem("SCALE", CPLString().Printf("%d", nScale));
+
+    /* -------------------------------------------------------------------- */
+    /*      Check for overviews.                                            */
+    /* -------------------------------------------------------------------- */
+
+    poVirtualDS->oOvManager.Initialize( poVirtualDS,
+                                        CPLString().Printf("%s.%d", pszTOCFilename, nCountSubDataset));
+
+    poVirtualDS->papszFileList = poVirtualDS->GDALDataset::GetFileList();
+
+    for(i=0;i<(int)aosFrameDesc.size(); i++)
+    {
+        const char* pszName = BuildFullName(pszTOCFilename,
+                                            aosFrameDesc[i].pszPath,
+                                            aosFrameDesc[i].pszName);
+
+        double dfMinX = 0, dfMaxX = 0, dfMinY = 0, dfMaxY = 0,
+               dfPixelXSize = 0, dfPixelYSize = 0;
+        GetExtent(aosFrameDesc[i].pszName,
+                  aosFrameDesc[i].nScale, aosFrameDesc[i].nZone,
+                  dfMinX, dfMaxX, dfMinY, dfMaxY, dfPixelXSize, dfPixelYSize);
+
+        int nFrameXSize = (int)((dfMaxX - dfMinX) / dfPixelXSize + 0.5);
+        int nFrameYSize = (int)((dfMaxY - dfMinY) / dfPixelYSize + 0.5);
+
+        poVirtualDS->papszFileList = CSLAddString(poVirtualDS->papszFileList, pszName);
+
+        /* We create proxy datasets and raster bands */
+        /* Using real datasets and raster bands is possible in theory */
+        /* However for large datasets, a TOC entry can include several hundreds of files */
+        /* and we finally reach the limit of maximum file descriptors open at the same time ! */
+        /* So the idea is to warp the datasets into a proxy and open the underlying dataset only when it is */
+        /* needed (IRasterIO operation). To improve a bit efficiency, we have a cache of opened */
+        /* underlying datasets */
+        ECRGTOCProxyRasterDataSet* poDS = new ECRGTOCProxyRasterDataSet(
+                (ECRGTOCSubDataset*)poVirtualDS, pszName, nFrameXSize, nFrameYSize,
+                dfMinX, dfMaxY, dfPixelXSize, dfPixelYSize);
+
+        for(j=0;j<3;j++)
+        {
+            VRTSourcedRasterBand *poBand = (VRTSourcedRasterBand*)
+                                        poVirtualDS->GetRasterBand( j + 1 );
+            /* Place the raster band at the right position in the VRT */
+            poBand->AddSimpleSource(poDS->GetRasterBand(j + 1),
+                                    0, 0, nFrameXSize, nFrameYSize,
+                                    (int)((dfMinX - dfGlobalMinX) / dfGlobalPixelXSize + 0.5),
+                                    (int)((dfGlobalMaxY - dfMaxY) / dfGlobalPixelYSize + 0.5),
+                                    (int)((dfMaxX - dfMinX) / dfGlobalPixelXSize + 0.5),
+                                    (int)((dfMaxY - dfMinY) / dfGlobalPixelYSize + 0.5));
+        }
+
+        /* The ECRGTOCProxyRasterDataSet will be destroyed when its last raster band will be */
+        /* destroyed */
+        poDS->Dereference();
+    }
+
+    poVirtualDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+
+    return poVirtualDS;
+}
+
+/************************************************************************/
+/*                             Build()                                  */
+/************************************************************************/
+
+GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
+                                   CPLXMLNode* psXML,
+                                   CPLString osProduct,
+                                   CPLString osDiscId,
+                                   const char* pszOpenInfoFilename)
+{
+    CPLXMLNode* psTOC = CPLGetXMLNode(psXML, "=Table_of_Contents");
+    if (psTOC == NULL)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Cannot find Table_of_Contents element");
+        return NULL;
+    }
+
+    double dfGlobalMinX = 0, dfGlobalMinY = 0, dfGlobalMaxX = 0, dfGlobalMaxY= 0;
+    double dfGlobalPixelXSize = 0, dfGlobalPixelYSize = 0;
+    int bGlobalExtentValid = FALSE;
+
+    ECRGTOCDataset* poDS = new ECRGTOCDataset();
+    int nSubDatasets = 0;
+
+    int bLookForSubDataset = osProduct.size() != 0 && osDiscId.size() != 0;
+
+    int nCountSubDataset = 0;
+
+    poDS->SetDescription( pszOpenInfoFilename );
+    poDS->papszFileList = poDS->GDALDataset::GetFileList();
+
+    for(CPLXMLNode* psIter1 = psTOC->psChild;
+                    psIter1 != NULL;
+                    psIter1 = psIter1->psNext)
+    {
+        if (!(psIter1->eType == CXT_Element && psIter1->pszValue != NULL &&
+              strcmp(psIter1->pszValue, "product") == 0))
+            continue;
+
+        const char* pszProductTitle =
+            CPLGetXMLValue(psIter1, "product_title", NULL);
+        if (pszProductTitle == NULL)
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                        "Cannot find product_title attribute");
+            continue;
+        }
+
+        if (bLookForSubDataset && strcmp(pszProductTitle, osProduct.c_str()) != 0)
+            continue;
+
+        for(CPLXMLNode* psIter2 = psIter1->psChild;
+                        psIter2 != NULL;
+                        psIter2 = psIter2->psNext)
+        {
+            if (!(psIter2->eType == CXT_Element && psIter2->pszValue != NULL &&
+                  strcmp(psIter2->pszValue, "disc") == 0))
+                continue;
+
+            const char* pszDiscId = CPLGetXMLValue(psIter2, "id", NULL);
+            if (pszDiscId == NULL)
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                            "Cannot find id attribute");
+                continue;
+            }
+
+            if (bLookForSubDataset && strcmp(pszDiscId, osDiscId.c_str()) != 0)
+                continue;
+
+            nCountSubDataset ++;
+
+            CPLXMLNode* psFrameList = CPLGetXMLNode(psIter2, "frame_list");
+            if (psFrameList == NULL)
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                            "Cannot find frame_list element");
+                continue;
+            }
+
+            int nValidFrames = 0;
+
+            std::vector<FrameDesc> aosFrameDesc;
+
+            int nSubDatasetScale = -1;
+
+            for(CPLXMLNode* psIter3 = psFrameList->psChild;
+                            psIter3 != NULL;
+                            psIter3 = psIter3->psNext)
+            {
+                if (!(psIter3->eType == CXT_Element &&
+                      psIter3->pszValue != NULL &&
+                      strcmp(psIter3->pszValue, "scale") == 0))
+                    continue;
+
+                const char* pszSize = CPLGetXMLValue(psIter3, "size", NULL);
+                if (pszSize == NULL)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                                "Cannot find size attribute");
+                    continue;
+                }
+
+                int nScale = GetScaleFromString(pszSize);
+                if (nScale <= 0)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Invalid scale %s", pszSize);
+                    continue;
+                }
+
+                if (nValidFrames == 0)
+                    nSubDatasetScale = nScale;
+                else
+                    nSubDatasetScale = -1;
+
+                for(CPLXMLNode* psIter4 = psIter3->psChild;
+                                psIter4 != NULL;
+                                psIter4 = psIter4->psNext)
+                {
+                    if (!(psIter4->eType == CXT_Element &&
+                          psIter4->pszValue != NULL &&
+                          strcmp(psIter4->pszValue, "frame") == 0))
+                        continue;
+
+                    const char* pszFrameName =
+                        CPLGetXMLValue(psIter4, "name", NULL);
+                    if (pszFrameName == NULL)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Cannot find name element");
+                        continue;
+                    }
+
+                    if (strlen(pszFrameName) != 18)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Invalid value for name element : %s",
+                                 pszFrameName);
+                        continue;
+                    }
+
+                    const char* pszFramePath =
+                        CPLGetXMLValue(psIter4, "frame_path", NULL);
+                    if (pszFramePath == NULL)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Cannot find frame_path element");
+                        continue;
+                    }
+
+                    const char* pszFrameZone =
+                        CPLGetXMLValue(psIter4, "frame_zone", NULL);
+                    if (pszFrameZone == NULL)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Cannot find frame_zone element");
+                        continue;
+                    }
+                    if (strlen(pszFrameZone) != 1)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Invalid value for frame_zone element : %s",
+                                 pszFrameZone);
+                        continue;
+                    }
+                    char chZone = pszFrameZone[0];
+                    int nZone = 0;
+                    if (chZone >= '1' && chZone <= '9')
+                        nZone = chZone - '0';
+                    else if (chZone >= 'a' && chZone <= 'h')
+                        nZone = -(chZone - 'a' + 1);
+                    else if (chZone >= 'A' && chZone <= 'H')
+                        nZone = -(chZone - 'A' + 1);
+                    else if (chZone == 'j' || chZone == 'J')
+                        nZone = -9;
+                    else
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Invalid value for frame_zone element : %s",
+                                  pszFrameZone);
+                        continue;
+                    }
+                    if (nZone == 9 || nZone == -9)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Polar zones unhandled by current implementation");
+                        continue;
+                    }
+
+                    double dfMinX = 0, dfMaxX = 0,
+                           dfMinY = 0, dfMaxY = 0,
+                           dfPixelXSize = 0, dfPixelYSize = 0;
+                    if (!GetExtent(pszFrameName, nScale, nZone,
+                                   dfMinX, dfMaxX, dfMinY, dfMaxY,
+                                   dfPixelXSize, dfPixelYSize))
+                    {
+                        continue;
+                    }
+
+                    nValidFrames ++;
+
+                    const char* pszFullName = BuildFullName(pszTOCFilename,
+                                                        pszFramePath,
+                                                        pszFrameName);
+                    poDS->papszFileList = CSLAddString(poDS->papszFileList, pszFullName);
+
+                    if (!bGlobalExtentValid)
+                    {
+                        dfGlobalMinX = dfMinX;
+                        dfGlobalMinY = dfMinY;
+                        dfGlobalMaxX = dfMaxX;
+                        dfGlobalMaxY = dfMaxY;
+                        dfGlobalPixelXSize = dfPixelXSize;
+                        dfGlobalPixelYSize = dfPixelYSize;
+                        bGlobalExtentValid = TRUE;
+                    }
+                    else
+                    {
+                        if (dfMinX < dfGlobalMinX) dfGlobalMinX = dfMinX;
+                        if (dfMinY < dfGlobalMinY) dfGlobalMinY = dfMinY;
+                        if (dfMaxX > dfGlobalMaxX) dfGlobalMaxX = dfMaxX;
+                        if (dfMaxY > dfGlobalMaxY) dfGlobalMaxY = dfMaxY;
+                        if (dfPixelXSize < dfGlobalPixelXSize)
+                            dfGlobalPixelXSize = dfPixelXSize;
+                        if (dfPixelYSize < dfGlobalPixelYSize)
+                            dfGlobalPixelYSize = dfPixelYSize;
+                    }
+
+                    if (bLookForSubDataset)
+                    {
+                        FrameDesc frameDesc;
+                        frameDesc.pszName = pszFrameName;
+                        frameDesc.pszPath = pszFramePath;
+                        frameDesc.nScale = nScale;
+                        frameDesc.nZone = nZone;
+                        aosFrameDesc.push_back(frameDesc);
+                    }
+                }
+            }
+
+            if (bLookForSubDataset)
+            {
+                delete poDS;
+                if (nValidFrames == 0)
+                    return NULL;
+                return ECRGTOCSubDataset::Build(pszProductTitle,
+                                                pszDiscId,
+                                                nSubDatasetScale,
+                                                nCountSubDataset,
+                                                pszTOCFilename,
+                                                aosFrameDesc,
+                                                dfGlobalMinX,
+                                                dfGlobalMinY,
+                                                dfGlobalMaxX,
+                                                dfGlobalMaxY,
+                                                dfGlobalPixelXSize,
+                                                dfGlobalPixelYSize);
+            }
+
+            if (nValidFrames)
+            {
+                poDS->AddSubDataset(pszOpenInfoFilename,
+                                    pszProductTitle, pszDiscId);
+                nSubDatasets ++;
+            }
+        }
+    }
+
+    if (!bGlobalExtentValid)
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    if (nSubDatasets == 1)
+    {
+        const char* pszSubDatasetName = CSLFetchNameValue(
+            poDS->GetMetadata("SUBDATASETS"), "SUBDATASET_1_NAME");
+        GDALOpenInfo oOpenInfo(pszSubDatasetName, GA_ReadOnly);
+        delete poDS;
+        GDALDataset* poRetDS = Open(&oOpenInfo);
+        if (poRetDS)
+            poRetDS->SetDescription(pszOpenInfoFilename);
+        return poRetDS;
+    }
+
+    poDS->adfGeoTransform[0] = dfGlobalMinX;
+    poDS->adfGeoTransform[1] = dfGlobalPixelXSize;
+    poDS->adfGeoTransform[2] = 0.0;
+    poDS->adfGeoTransform[3] = dfGlobalMaxY;
+    poDS->adfGeoTransform[4] = 0.0;
+    poDS->adfGeoTransform[5] = - dfGlobalPixelYSize;
+
+    poDS->nRasterXSize = (int)(0.5 + (dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize);
+    poDS->nRasterYSize = (int)(0.5 + (dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize);
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->TryLoadXML();
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int ECRGTOCDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    const char *pszFilename = poOpenInfo->pszFilename;
+    const char *pabyHeader = (const char *) poOpenInfo->pabyHeader;
+
+/* -------------------------------------------------------------------- */
+/*      Is this a sub-dataset selector? If so, it is obviously ECRGTOC. */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszFilename, "ECRG_TOC_ENTRY:",strlen("ECRG_TOC_ENTRY:")))
+        return TRUE;
+
+/* -------------------------------------------------------------------- */
+/*  First we check to see if the file has the expected header           */
+/*  bytes.                                                              */
+/* -------------------------------------------------------------------- */
+    if( pabyHeader == NULL )
+        return FALSE;
+
+    if ( strstr(pabyHeader, "<Table_of_Contents>") != NULL &&
+         strstr(pabyHeader, "<file_header ") != NULL)
+        return TRUE;
+
+    if ( strstr(pabyHeader, "<!DOCTYPE Table_of_Contents [") != NULL)
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ECRGTOCDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    const char *pszFilename = poOpenInfo->pszFilename;
+    CPLString osProduct, osDiscId;
+
+    if( !Identify( poOpenInfo ) )
+        return NULL;
+
+    if( EQUALN(pszFilename, "ECRG_TOC_ENTRY:",strlen("ECRG_TOC_ENTRY:")))
+    {
+        pszFilename += strlen("ECRG_TOC_ENTRY:");
+        osProduct = pszFilename;
+        size_t iPos = osProduct.find(":");
+        if (iPos == std::string::npos)
+            return NULL;
+        osProduct.resize(iPos);
+
+        pszFilename += iPos + 1;
+        osDiscId = pszFilename;
+        iPos = osDiscId.find(":");
+        if (iPos == std::string::npos)
+            return NULL;
+        osDiscId.resize(iPos);
+
+        pszFilename += iPos + 1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse the XML file                                              */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode* psXML = CPLParseXMLFile(pszFilename);
+    if (psXML == NULL)
+    {
+        return NULL;
+    }
+
+    GDALDataset* poDS = Build( pszFilename, psXML, osProduct, osDiscId,
+                               poOpenInfo->pszFilename);
+    CPLDestroyXMLNode(psXML);
+
+    if (poDS && poOpenInfo->eAccess == GA_Update)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "ECRGTOC driver does not support update mode");
+        delete poDS;
+        return NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         GDALRegister_ECRGTOC()                       */
+/************************************************************************/
+
+void GDALRegister_ECRGTOC()
+
+{
+    GDALDriver	*poDriver;
+
+    if( GDALGetDriverByName( "ECRGTOC" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+        
+        poDriver->SetDescription( "ECRGTOC" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                   "ECRG TOC format" );
+        
+        poDriver->pfnIdentify = ECRGTOCDataset::Identify;
+        poDriver->pfnOpen = ECRGTOCDataset::Open;
+
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
+                                   "frmt_various.html#ECRGTOC" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xml" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/frmts/nitf/frmt_nitf.html b/frmts/nitf/frmt_nitf.html
index 6205a8a..64ed726 100644
--- a/frmts/nitf/frmt_nitf.html
+++ b/frmts/nitf/frmt_nitf.html
@@ -9,17 +9,14 @@
 
 GDAL supports reading of several subtypes of NITF image files, and writing
 simple NITF 2.1 files.  NITF 1.1, NITF 2.0, NITF 2.1 and NSIF 1.0
-files with uncompressed, ARIDPCM, JPEG compressed, JPEG2000 (with Kakadu or ECW SDKs)
-or VQ compressed images should be readable.  Other compression mechanisms are 
-not supported at this time.  The read support test has been tested on CIB and 
-CADRG RPF products.<p>
+files with uncompressed, ARIDPCM, JPEG compressed, JPEG2000 (with Kakadu, ECW SDKs or other JPEG2000 capable driver)
+or VQ compressed images should be readable.<p>
+
+The read support test has been tested on various products,
+including CIB and CADRG frames from RPF products, ECRG frames, HRE products.<p>
 
 Color tables for pseudocolored images are read.  In some cases nodata values
-may be identified.  In theory all input pixel types 
-except 1bit are supported, but only 8bit and 16bit types have actually been 
-tested.<p>
-<!-- New tests have been added to the autotest suite. So this could be probably
-be rephrased differently -->
+may be identified.<p>
 
 Lat/Long extents are read from the IGEOLO information in 
 the image header if available.  If high precision lat/long georeferencing 
@@ -30,7 +27,7 @@ the complete image - that is the L_LINES field with the row count for that
 block is equal to the row count of the image. Additionally, all BLOCKA 
 instances are returned as metadata. If GeoSDE TRE are available, they will be
 used to provide higher precision coordinates.
-<P>
+<p>
 
 Most file header and image header fields are returned as dataset level
 metadata.<p>
@@ -102,6 +99,10 @@ two variations supported are "NITF02.10" (the default), and "NSIF01.00". <p>
 each output band. (Only needed for
 Create() method, not CreateCopy()).<p>
 
+<li> <b>IREPBAND</b>: (GDAL >= 1.9.0) Comma separated list of band IREPBANDs in band order.<p>
+
+<li> <b>ISUBCAT</b>: (GDAL >= 1.9.0) Comma separated list of band ISUBCATs in band order.<p>
+
 <li> <b>LUT_SIZE</b>: Set to control the size of pseudocolor tables for
 RGB/LUT bands.  A value of 256 assumed if not present. (Only needed for
 Create() method, not CreateCopy()).<p>
@@ -135,23 +136,24 @@ more precise georeferencing. This is limited to geographic SRS, and to CreateCop
 </ul>
 
 
+<h2>Links</h2>
+<ul>
+<li><a href="frmt_nitf_advanced.html">Advanced GDAL NITF Driver Information</a></li>
+<li> <a href="http://www.gwg.nga.mil/ntb/">NITFS Technical Board Public Page</a></li>
+<li> <a href="http://www.gwg.nga.mil/ntb/baseline/docs/digest/part2_annex_d.pdf">DIGEST Part 2 Annex D (describe encoding of NITF Spatial Data Extensions)</a></li>
+<li> <a href="frmt_various.html#RPFTOC">RPFTOC</a> driver : to read the Table Of Contents of CIB and CADRG products.</li>
+<li> <a href="http://www.everyspec.com/MIL-PRF/MIL-PRF+%28080000+-+99999%29/MIL-PRF-89038_25371/">MIL-PRF-89038</a> : specification of RPF, CADRG, CIB products</li>
+<li> <a href="frmt_various.html#ECRGTOC">ECRGTOC</a> driver : to read the Table Of Contents of ECRG products.</li>
+<li> <a href="http://www.everyspec.com/MIL-PRF/MIL-PRF+%28030000+-+79999%29/MIL-PRF-32283_26022/">MIL-PRF-32283</a> : specification of ECRG products</li>
+</ul>
+
 <h2>Credit</h2>
 
 The author wishes to thank <a href="http://www.augsignals.com/">AUG
 Signals</a> and the <a href="http://geoconnections.org/">GeoConnections</a>
-program for supporting development of this driver, and to thank 
+program for supporting development of this driver, and to thank
 Steve Rawlinson (JPEG), Reiner Beck (BLOCKA) for assistance adding features.<p>
 
-See Also: <p>
-<ul>
-<li><a href="frmt_nitf_advanced.html">Advanced GDAL NITF Driver Information</a>
-<li> <a href="http://164.214.2.51/ntb/">NITFS Technical Board Public Page</a>
-<li> <a href="http://www.gwg.nga.mil/ntb/baseline/docs/digest/part2_annex_d.pdf">DIGEST Part 2 Annex D (describe encoding of NITF Spatial Data Extensions)</a>
-<li> The <a href="frmt_ogdi.html">OGDI</a> driver supports many NITF based RPF
-products including CIB and CADRG.<p>
-<li> The <a href="frmt_various.html#RPFTOC">RPFTOC</a> driver is an alternative to the OGDI driver for CIB and CADRG products.<p>
-</ul>
-
 </body>
 </html>
 
diff --git a/frmts/nitf/frmt_nitf_advanced.html b/frmts/nitf/frmt_nitf_advanced.html
index 5afc922..2d8b901 100644
--- a/frmts/nitf/frmt_nitf_advanced.html
+++ b/frmts/nitf/frmt_nitf_advanced.html
@@ -136,6 +136,9 @@ TRE which will have the name of the TRE as the name, and the data of the TRE
 as the contents.  The data contents will be "backslash escaped" like CGM
 data above. <p>
 
+In case of multiple occurences of the same TRE, the second occurence will be
+named "TRENAME_2", the third "TRENAME_3" where TRENAME is the TRE name.<p>
+
 <pre>
 Metadata (TRE):
   GEOPSB=MAPM  World Geodetic System 1984                                       
@@ -149,6 +152,79 @@ Metadata (TRE):
   MAPLOB=M  0598005958-000003067885.8-000002163353.8
 </pre>
 
+<h2>TREs as xml:TRE</h2>
+
+Starting with GDAL 1.9.0, all TREs found in file and matching one of the
+TRE description of the <a href="http://trac.osgeo.org/gdal/browser/trunk/gdal/data/nitf_spec.xml">nitf_spec.xml</a> in GDAL data directory will be reported
+as XML content in the xml:TRE metadata domain.<p>
+
+<pre>
+Metadata (xml:TRE):
+<tres>
+  <tre name="RSMDCA" location="des TRE_OVERFLOW">
+    <field name="IID" value="2_8" />
+    <field name="EDITION" value="1101222272-2" />
+    <field name="TID" value="1101222272-1" />
+    <field name="NPAR" value="06" />
+    <field name="NIMGE" value="001" />
+    <field name="NPART" value="00006" />
+    <repeated name="IMAGE" number="1">
+      <group index="0">
+        <field name="IID" value="2_8" />
+        <field name="NPARI" value="06" />
+      </group>
+    </repeated>
+    <field name="XUOL" value="-2.42965895449297E+06" />
+    <field name="YUOL" value="-4.76049894293300E+06" />
+    <field name="ZUOL" value="+3.46898407315533E+06" />
+    <field name="XUXL" value="+8.90698769551156E-01" />
+    <field name="XUYL" value="+2.48664813021570E-01" />
+    <field name="XUZL" value="-3.80554217799520E-01" />
+    <field name="YUXL" value="-4.54593996792805E-01" />
+    <field name="YUYL" value="+4.87215943350720E-01" />
+    <field name="YUZL" value="-7.45630553709282E-01" />
+    <field name="ZUXL" value="+0.00000000000000E+00" />
+    <field name="ZUYL" value="+8.37129879594448E-01" />
+    <field name="ZUZL" value="+5.47004172461403E-01" />
+[...]
+    <repeated name="DERCOV" number="21">
+      <group index="0">
+        <field name="DERCOV" value="+5.77388827727787E+04" />
+      </group>
+[...]
+      <group index="20">
+        <field name="DERCOV" value="+1.14369570920252E-02" />
+      </group>
+    </repeated>
+  </tre>
+  <tre name="RSMECA" location="des TRE_OVERFLOW">
+[...]
+  </tre>
+  <tre name="RSMIDA" location="des TRE_OVERFLOW">
+[...]
+  </tre>
+  <tre name="RSMPCA" location="des TRE_OVERFLOW">
+[...]
+  </tre>
+</tres>
+</pre>
+
+<h2>Raw File / Image Headers</h2>
+
+In some cases application may need to recover very specific information
+from the image or file headers that isn't normally available as metadata.
+In this case it is possible to query the "NITF_METADATA" metadata domain.  
+The complete file and image headers will be returned as metadata in base64 
+encoded format.  Something like:<p>
+
+<pre>
+Metadata (NITF_METADATA):
+  NITFFileHeader=002213 TklURjAyLjAwMDEgICAgVTIxN0cwSjA...
+  NITFImageSubheader=439 SU1NaXNzaW5nIElEMjUxNTI1NTlaTU...
+</pre>
+
+Note that the ascii encoded numeric values prefixing the base64 encoded
+header is the length (decoded) in bytes, followed by one space.  <p>
 
 </body>
 </html>
diff --git a/frmts/nitf/makefile.vc b/frmts/nitf/makefile.vc
index 8791381..5a7da50 100644
--- a/frmts/nitf/makefile.vc
+++ b/frmts/nitf/makefile.vc
@@ -1,7 +1,9 @@
 
-GDAL_OBJ	=	nitfdataset.obj rpftocdataset.obj nitfwritejpeg.obj nitfwritejpeg_12.obj
-NITFLIB_OBJ	=	nitffile.obj nitfimage.obj mgrs.obj nitfaridpcm.obj \
-			nitfbilevel.obj rpftocfile.obj nitfdes.obj
+GDAL_OBJ =	nitfdataset.obj rpftocdataset.obj nitfwritejpeg.obj \
+	 	nitfwritejpeg_12.obj nitfrasterband.obj ecrgtocdataset.obj
+
+NITFLIB_OBJ  =	nitffile.obj nitfimage.obj mgrs.obj nitfaridpcm.obj \
+		nitfbilevel.obj rpftocfile.obj nitfdes.obj nitf_gcprpc.obj
 
 OBJ = $(GDAL_OBJ) $(NITFLIB_OBJ)
 
diff --git a/frmts/nitf/nitf_gcprpc.cpp b/frmts/nitf/nitf_gcprpc.cpp
new file mode 100644
index 0000000..3c39386
--- /dev/null
+++ b/frmts/nitf/nitf_gcprpc.cpp
@@ -0,0 +1,249 @@
+/******************************************************************************
+ * $Id: nitf_gcprpc.cpp 22701 2011-07-11 18:37:31Z rouault $
+ *
+ * Project:  NITF Read/Write Translator
+ * Purpose:  GCP / RPC Georeferencing Model (custom by/for ESRI)
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, ESRI 
+ *
+ * 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_priv.h"
+#include "nitflib.h"
+
+CPL_CVSID("$Id");
+
+/* Unused in normal builds. Caller code in nitfdataset.cpp is protected by #ifdef ESRI_BUILD */
+#ifdef ESRI_BUILD
+
+/************************************************************************/
+/*                               Apply()                                */
+/************************************************************************/
+static double Apply( double *C, double P, double L, double H )
+{
+    // Polynomial equation for RPC00B.
+
+    double H2 = H * H;
+    double L2 = L * L;
+    double P2 = P * P;
+
+    return  C[0]
+        + C[1]*L     + C[2]*P     + C[3]*H     + C[4]*L*P   + C[5]*L*H  
+        + C[6]*P*H   + C[7]*L2    + C[8]*P2    + C[9]*H2    + C[10]*P*L*H
+        + C[11]*L*L2 + C[12]*L*P2 + C[13]*L*H2 + C[14]*L2*P + C[15]*P*P2
+        + C[16]*P*H2 + C[17]*L2*H + C[18]*P2*H + C[19]*H*H2;
+} 
+
+/************************************************************************/
+/*                          NITFDensifyGCPs()                           */
+/************************************************************************/
+void NITFDensifyGCPs( GDAL_GCP **psGCPs, int *pnGCPCount )
+{
+    // Given the four corner points of an extent (UL, UR, LR, LL), this method
+    // will add three points to each line segment and return a total of 16 points
+    // including the four original corner points.
+
+    if ( (*pnGCPCount != 4) || (psGCPs == NULL) ) return;
+
+    const int  nDensifiedGCPs  = 16;
+    GDAL_GCP  *psDensifiedGCPs = (GDAL_GCP*) CPLMalloc(sizeof(GDAL_GCP)*nDensifiedGCPs);
+
+    GDALInitGCPs( nDensifiedGCPs, psDensifiedGCPs );
+
+    bool   ok          = true;
+    double xLeftPt     = 0.0;
+    double xMidPt      = 0.0;
+    double xRightPt    = 0.0;
+    double yLeftPt     = 0.0;
+    double yMidPt      = 0.0;
+    double yRightPt    = 0.0;
+    int    count       = 0;
+    int    idx         = 0;
+
+    for( int ii = 0; ( (ii < *pnGCPCount) && (ok) ) ; ++ii )
+    {
+        idx = ( ii != 3 ) ? ii+1 : 0;
+
+        try
+        {
+            psDensifiedGCPs[count].dfGCPX = (*psGCPs)[ii].dfGCPX;
+            psDensifiedGCPs[count].dfGCPY = (*psGCPs)[ii].dfGCPY;
+
+            xMidPt = ((*psGCPs)[ii].dfGCPX+(*psGCPs)[idx].dfGCPX) * 0.5;
+            yMidPt = ((*psGCPs)[ii].dfGCPY+(*psGCPs)[idx].dfGCPY) * 0.5;
+
+            xLeftPt = ((*psGCPs)[ii].dfGCPX+xMidPt) * 0.5;
+            yLeftPt = ((*psGCPs)[ii].dfGCPY+yMidPt) * 0.5;
+
+            xRightPt = (xMidPt+(*psGCPs)[idx].dfGCPX) * 0.5;
+            yRightPt = (yMidPt+(*psGCPs)[idx].dfGCPY) * 0.5;
+
+            psDensifiedGCPs[count+1].dfGCPX = xLeftPt;
+            psDensifiedGCPs[count+1].dfGCPY = yLeftPt;
+            psDensifiedGCPs[count+2].dfGCPX = xMidPt;
+            psDensifiedGCPs[count+2].dfGCPY = yMidPt;
+            psDensifiedGCPs[count+3].dfGCPX = xRightPt;
+            psDensifiedGCPs[count+3].dfGCPY = yRightPt;
+
+            count += *pnGCPCount;
+
+        }
+        catch (...)
+        {
+            ok = false;
+        }
+    }
+
+    if( !ok )
+    {
+        GDALDeinitGCPs( nDensifiedGCPs, psDensifiedGCPs );
+        CPLFree( psDensifiedGCPs );
+        psDensifiedGCPs = NULL;
+
+        return;
+    }
+
+    GDALDeinitGCPs( *pnGCPCount, *psGCPs );
+    CPLFree( *psGCPs );
+
+    *psGCPs         = psDensifiedGCPs;
+    *pnGCPCount     = nDensifiedGCPs;
+    psDensifiedGCPs = NULL;
+}
+
+/************************************************************************/
+/*                            RPCTransform()                            */
+/************************************************************************/
+
+static bool RPCTransform( NITFRPC00BInfo *psRPCInfo, 
+                          double         *pGCPXCoord,
+                          double         *pGCPYCoord,
+                          int             nGCPCount )
+{
+    if( (psRPCInfo == NULL) || (pGCPXCoord == NULL) ||
+        (pGCPYCoord == NULL) || (nGCPCount <= 0) ) return (false);
+
+    bool   ok = true;
+    double H  = 0.0;
+    double L  = 0.0;
+    double P  = 0.0;
+    double u  = 0.0;
+    double v  = 0.0;
+    double z  = psRPCInfo->HEIGHT_OFF;
+
+    double heightScaleInv = 1.0/psRPCInfo->HEIGHT_SCALE;
+    double latScaleInv    = 1.0/psRPCInfo->LAT_SCALE;
+    double longScaleInv   = 1.0/psRPCInfo->LONG_SCALE;
+
+    for( int ii = 0; ( (ii < nGCPCount) && (ok) ); ++ii )
+    {
+        try
+        {
+            P = ( pGCPYCoord[ii] - psRPCInfo->LAT_OFF )    * latScaleInv;
+            L = ( pGCPXCoord[ii] - psRPCInfo->LONG_OFF)    * longScaleInv;
+            H = ( z              - psRPCInfo->HEIGHT_OFF ) * heightScaleInv;
+
+            u = Apply( psRPCInfo->SAMP_NUM_COEFF, P, L, H )/Apply( psRPCInfo->SAMP_DEN_COEFF, P, L, H );
+            v = Apply( psRPCInfo->LINE_NUM_COEFF, P, L, H )/Apply( psRPCInfo->LINE_DEN_COEFF, P, L, H );
+
+            pGCPXCoord[ii] = u*psRPCInfo->SAMP_SCALE + psRPCInfo->SAMP_OFF;
+            pGCPYCoord[ii] = v*psRPCInfo->LINE_SCALE + psRPCInfo->LINE_OFF;
+        }
+        catch (...)
+        {
+            ok = false;
+        }
+    }
+
+    return (ok);
+}
+
+/************************************************************************/
+/*                       NITFUpdateGCPsWithRPC()                        */
+/************************************************************************/
+
+void NITFUpdateGCPsWithRPC( NITFRPC00BInfo *psRPCInfo,
+                            GDAL_GCP       *psGCPs,
+                            int            *pnGCPCount )
+{
+    if( (psRPCInfo == NULL) || (!psRPCInfo->SUCCESS) ||
+        (psGCPs == NULL) || (*pnGCPCount < 4) ) return;
+
+    double *pGCPXCoord = NULL;
+    double *pGCPYCoord = NULL;
+
+    try
+    {
+        pGCPXCoord = new double[*pnGCPCount];
+        pGCPYCoord = new double[*pnGCPCount];
+    }
+    catch (...)
+    {
+        if( pGCPXCoord != NULL )
+        {
+            delete [] (pGCPXCoord);
+            pGCPXCoord = NULL;
+        }
+
+        if( pGCPYCoord != NULL )
+        {
+            delete [] (pGCPYCoord);
+            pGCPYCoord = NULL;
+        }
+    }
+
+    if( (pGCPXCoord == NULL) || (pGCPYCoord == NULL) ) return;
+
+    bool ok = true;
+
+    for( int ii = 0; ( (ii < *pnGCPCount) && (ok) ); ++ii )
+    {
+        try
+        {
+            pGCPXCoord[ii] = psGCPs[ii].dfGCPX;
+            pGCPYCoord[ii] = psGCPs[ii].dfGCPY;
+        }
+        catch (...)
+        {
+            ok = false;
+        }
+    }
+
+    if( (ok) && (RPCTransform( psRPCInfo, pGCPXCoord, pGCPYCoord, *pnGCPCount )) )
+    {
+        // Replace the image coordinates of the input GCPs.
+
+        for( int jj = 0; jj < *pnGCPCount; ++jj )
+        {
+            psGCPs[jj].dfGCPPixel = pGCPXCoord[jj];
+            psGCPs[jj].dfGCPLine  = pGCPYCoord[jj];
+        }
+    }
+
+    delete [] (pGCPXCoord);
+    delete [] (pGCPYCoord);
+
+    pGCPXCoord = NULL;
+    pGCPYCoord = NULL;
+}
+
+#endif
diff --git a/frmts/nitf/nitfaridpcm.cpp b/frmts/nitf/nitfaridpcm.cpp
index 4ba99e4..3291546 100644
--- a/frmts/nitf/nitfaridpcm.cpp
+++ b/frmts/nitf/nitfaridpcm.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfaridpcm.cpp 16416 2009-02-25 21:13:08Z rouault $
+ * $Id: nitfaridpcm.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  ARIDPCM reading code.
@@ -31,7 +31,7 @@
 #include "nitflib.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: nitfaridpcm.cpp 16416 2009-02-25 21:13:08Z rouault $");
+CPL_CVSID("$Id: nitfaridpcm.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 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*/] = { 
@@ -421,7 +421,7 @@ int NITFUncompressARIDPCM( NITFImage *psImage,
             CPLFree(full_image);
             return FALSE;
         }
-        L00[i] = get_bits( pabyInputData, block_offset[i], 8 );
+        L00[i] = (unsigned char) get_bits( pabyInputData, block_offset[i], 8 );
 
         total += block_size[i];
     }
diff --git a/frmts/nitf/nitfdataset.cpp b/frmts/nitf/nitfdataset.cpp
index a52b84f..d7a71c5 100644
--- a/frmts/nitf/nitfdataset.cpp
+++ b/frmts/nitf/nitfdataset.cpp
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: nitfdataset.cpp 21608 2011-01-30 13:15:38Z rouault $
+ * $Id: nitfdataset.cpp 23491 2011-12-07 20:48:18Z rouault $
  *
  * Project:  NITF Read/Write Translator
- * Purpose:  GDALDataset/GDALRasterBand implementation on top of "nitflib".
+ * Purpose:  NITFDataset and driver related implementations.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -30,14 +30,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
-#include "nitflib.h"
-#include "ogr_spatialref.h"
+#include "nitfdataset.h"
 #include "cpl_string.h"
 #include "cpl_csv.h"
-#include "gdal_proxy.h"
 
-CPL_CVSID("$Id: nitfdataset.cpp 21608 2011-01-30 13:15:38Z rouault $");
+CPL_CVSID("$Id: nitfdataset.cpp 23491 2011-12-07 20:48:18Z rouault $");
 
 static void NITFPatchImageLength( const char *pszFilename,
                                   GUIntBig nImageOffset, 
@@ -45,830 +42,15 @@ static void NITFPatchImageLength( const char *pszFilename,
 static int NITFWriteCGMSegments( const char *pszFilename, char **papszList );
 static void NITFWriteTextSegments( const char *pszFilename, char **papszList );
 
-static CPLErr NITFSetColorInterpretation( NITFImage *psImage, 
-                                          int nBand,
-                                          GDALColorInterp eInterp );
 #ifdef JPEG_SUPPORTED
 static int NITFWriteJPEGImage( GDALDataset *, VSILFILE *, vsi_l_offset, char **,
                                GDALProgressFunc pfnProgress, 
                                void * pProgressData );
 #endif
 
-/************************************************************************/
-/* ==================================================================== */
-/*				NITFDataset				*/
-/* ==================================================================== */
-/************************************************************************/
-
-class NITFRasterBand;
-class NITFWrapperRasterBand;
-
-class NITFDataset : public GDALPamDataset
-{
-    friend class NITFRasterBand;
-    friend class NITFWrapperRasterBand;
-
-    NITFFile    *psFile;
-    NITFImage   *psImage;
-
-    GDALPamDataset *poJ2KDataset;
-    int         bJP2Writing;
-
-    GDALPamDataset *poJPEGDataset;
-
-    int         bGotGeoTransform;
-    double      adfGeoTransform[6];
-
-    char        *pszProjection;
-
-    int         nGCPCount;
-    GDAL_GCP    *pasGCPList;
-    char        *pszGCPProjection;
-
-    GDALMultiDomainMetadata oSpecialMD;
-
-    void         InitializeCGMMetadata();
-    void         InitializeTextMetadata();
-    void         InitializeTREMetadata();
-
-    GIntBig     *panJPEGBlockOffset;
-    GByte       *pabyJPEGBlock;
-    int          nQLevel;
-
-    int          ScanJPEGQLevel( GUIntBig *pnDataStart );
-    CPLErr       ScanJPEGBlocks( void );
-    CPLErr       ReadJPEGBlock( int, int );
-    void         CheckGeoSDEInfo();
-
-    int          nIMIndex;
-    CPLString    osNITFFilename;
-
-    CPLString    osRSetVRT;
-    int          CheckForRSets( const char *pszFilename );
-
-    char       **papszTextMDToWrite;
-    char       **papszCgmMDToWrite;
-    
-    int          bInLoadXML;
-
-  public:
-                 NITFDataset();
-                 ~NITFDataset();
-
-    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
-                               int nBufXSize, int nBufYSize, 
-                               GDALDataType eDT, 
-                               int nBandCount, int *panBandList,
-                               char **papszOptions );
-
-    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                              void *, int, int, GDALDataType,
-                              int, int *, int, int, int );
-
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
-
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-
-    virtual char      **GetMetadata( const char * pszDomain = "" );
-    virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
-    virtual void   FlushCache();
-    virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
-
-    static int          Identify( GDALOpenInfo * );
-    static GDALDataset *Open( GDALOpenInfo *, GDALDataset *poWritableJ2KDataset,
-                              int bOpenForCreate);
-    static GDALDataset *Open( GDALOpenInfo * );
-    static GDALDataset *
-    NITFCreateCopy( const char *pszFilename, GDALDataset *poSrcDS,
-                    int bStrict, char **papszOptions, 
-                    GDALProgressFunc pfnProgress, void * pProgressData );
-    static GDALDataset *
-             NITFDatasetCreate( const char *pszFilename,
-                                int nXSize, int nYSize, int nBands,
-                                GDALDataType eType, char **papszOptions );
-
-};
-
-/************************************************************************/
-/*                       NITFMakeColorTable()                           */
-/************************************************************************/
-
-static GDALColorTable* NITFMakeColorTable(NITFImage* psImage, NITFBandInfo *psBandInfo)
-{
-    GDALColorTable* poColorTable = NULL;
-
-    if( psBandInfo->nSignificantLUTEntries > 0 )
-    {
-        int  iColor;
-
-        poColorTable = new GDALColorTable();
-
-        for( iColor = 0; iColor < psBandInfo->nSignificantLUTEntries; iColor++)
-        {
-            GDALColorEntry sEntry;
-
-            sEntry.c1 = psBandInfo->pabyLUT[  0 + iColor];
-            sEntry.c2 = psBandInfo->pabyLUT[256 + iColor];
-            sEntry.c3 = psBandInfo->pabyLUT[512 + iColor];
-            sEntry.c4 = 255;
-
-            poColorTable->SetColorEntry( iColor, &sEntry );
-        }
-
-        if (psImage->bNoDataSet)
-        {
-            GDALColorEntry sEntry;
-            sEntry.c1 = sEntry.c2 = sEntry.c3 = sEntry.c4 = 0;
-            poColorTable->SetColorEntry( psImage->nNoDataValue, &sEntry );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      We create a color table for 1 bit data too...                   */
-/* -------------------------------------------------------------------- */
-    if( poColorTable == NULL && psImage->nBitsPerSample == 1 )
-    {
-        GDALColorEntry sEntry;
-
-        poColorTable = new GDALColorTable();
-
-        sEntry.c1 = 0;
-        sEntry.c2 = 0;
-        sEntry.c3 = 0;
-        sEntry.c4 = 255;
-        poColorTable->SetColorEntry( 0, &sEntry );
-
-        sEntry.c1 = 255;
-        sEntry.c2 = 255;
-        sEntry.c3 = 255;
-        sEntry.c4 = 255;
-        poColorTable->SetColorEntry( 1, &sEntry );
-    }
-    
-    return poColorTable;
-}
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            NITFRasterBand                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class NITFRasterBand : public GDALPamRasterBand
-{
-    friend class NITFDataset;
-
-    NITFImage   *psImage;
-
-    GDALColorTable *poColorTable;
-
-    GByte       *pUnpackData;
-
-  public:
-                   NITFRasterBand( NITFDataset *, int );
-                  ~NITFRasterBand();
-
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr SetColorTable( GDALColorTable * ); 
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-
-    void Unpack(GByte* pData);
-};
-
-/************************************************************************/
-/*                           NITFRasterBand()                           */
-/************************************************************************/
-
-NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
-
-{
-    NITFBandInfo *psBandInfo = poDS->psImage->pasBandInfo + nBand - 1;
-
-    this->poDS = poDS;
-    this->nBand = nBand;
-
-    this->eAccess = poDS->eAccess;
-    this->psImage = poDS->psImage;
-
-/* -------------------------------------------------------------------- */
-/*      Translate data type(s).                                         */
-/* -------------------------------------------------------------------- */
-    if( psImage->nBitsPerSample <= 8 )
-        eDataType = GDT_Byte;
-    else if( psImage->nBitsPerSample == 16 
-             && EQUAL(psImage->szPVType,"SI") )
-        eDataType = GDT_Int16;
-    else if( psImage->nBitsPerSample == 16 )
-        eDataType = GDT_UInt16;
-    else if( psImage->nBitsPerSample == 12 )
-        eDataType = GDT_UInt16;
-    else if( psImage->nBitsPerSample == 32 
-             && EQUAL(psImage->szPVType,"SI") )
-        eDataType = GDT_Int32;
-    else if( psImage->nBitsPerSample == 32 
-             && EQUAL(psImage->szPVType,"R") )
-        eDataType = GDT_Float32;
-    else if( psImage->nBitsPerSample == 32 )
-        eDataType = GDT_UInt32;
-    else if( psImage->nBitsPerSample == 64 
-             && EQUAL(psImage->szPVType,"R") )
-        eDataType = GDT_Float64;
-    else if( psImage->nBitsPerSample == 64
-              && EQUAL(psImage->szPVType,"C") )
-        eDataType = GDT_CFloat32;
-    /* ERO : note I'm not sure if CFloat64 can be transmitted as NBPP is only 2 characters */
-    else
-    {
-        eDataType = GDT_Unknown;
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Unsupported combination of PVTYPE(%s) and NBPP(%d).",
-                  psImage->szPVType, psImage->nBitsPerSample );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Work out block size. If the image is all one big block we       */
-/*      handle via the scanline access API.                             */
-/* -------------------------------------------------------------------- */
-    if( psImage->nBlocksPerRow == 1 
-        && psImage->nBlocksPerColumn == 1
-        && psImage->nBitsPerSample >= 8
-        && EQUAL(psImage->szIC,"NC") )
-    {
-        nBlockXSize = psImage->nBlockWidth;
-        nBlockYSize = 1;
-    }
-    else
-    {
-        nBlockXSize = psImage->nBlockWidth;
-        nBlockYSize = psImage->nBlockHeight;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have a color table?                                       */
-/* -------------------------------------------------------------------- */
-    poColorTable = NITFMakeColorTable(psImage,
-                                      psBandInfo);
-
-    if( psImage->nBitsPerSample == 1 
-    ||  psImage->nBitsPerSample == 3
-    ||  psImage->nBitsPerSample == 5
-    ||  psImage->nBitsPerSample == 6
-    ||  psImage->nBitsPerSample == 7
-    ||  psImage->nBitsPerSample == 12 )
-        SetMetadataItem( "NBITS", CPLString().Printf("%d", psImage->nBitsPerSample), "IMAGE_STRUCTURE" );
-
-    pUnpackData = 0;
-    if (psImage->nBitsPerSample == 3
-    ||  psImage->nBitsPerSample == 5
-    ||  psImage->nBitsPerSample == 6
-    ||  psImage->nBitsPerSample == 7)
-      pUnpackData = new GByte[((nBlockXSize*nBlockYSize+7)/8)*8];
-}
-
-/************************************************************************/
-/*                          ~NITFRasterBand()                           */
-/************************************************************************/
-
-NITFRasterBand::~NITFRasterBand()
-
-{
-    if( poColorTable != NULL )
-        delete poColorTable;
-
-    delete[] pUnpackData;
-}
-
-/************************************************************************/
-/*                             IReadBlock()                             */
-/************************************************************************/
-
-CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                   void * pImage )
-
-{
-    int  nBlockResult;
-    NITFDataset *poGDS = (NITFDataset *) poDS;
-
-/* -------------------------------------------------------------------- */
-/*      Special case for JPEG blocks.                                   */
-/* -------------------------------------------------------------------- */
-    if( EQUAL(psImage->szIC,"C3") || EQUAL(psImage->szIC,"M3") )
-    {
-        CPLErr eErr = poGDS->ReadJPEGBlock( nBlockXOff, nBlockYOff );
-        int nBlockBandSize = psImage->nBlockWidth*psImage->nBlockHeight*
-                             (GDALGetDataTypeSize(eDataType)/8);
-
-        if( eErr != CE_None )
-            return eErr;
-
-        memcpy( pImage, 
-                poGDS->pabyJPEGBlock + (nBand - 1) * nBlockBandSize, 
-                nBlockBandSize );
-
-        return eErr;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the line/block                                             */
-/* -------------------------------------------------------------------- */
-    if( nBlockYSize == 1 )
-    {
-        nBlockResult = 
-            NITFReadImageLine(psImage, nBlockYOff, nBand, pImage);
-    }
-    else
-    {
-        nBlockResult = 
-            NITFReadImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
-    }
-
-    if( nBlockResult == BLKREAD_OK )
-    {
-        if( psImage->nBitsPerSample % 8 )
-            Unpack((GByte*)pImage);
-
-        return CE_None;
-    }
-
-    if( nBlockResult == BLKREAD_FAIL )
-        return CE_Failure;
-
-/* -------------------------------------------------------------------- */
-/*      If we got a null/missing block, try to fill it in with the      */
-/*      nodata value.  It seems this only really works properly for     */
-/*      8bit.                                                           */
-/* -------------------------------------------------------------------- */
-    if( psImage->bNoDataSet )
-        memset( pImage, psImage->nNoDataValue, 
-                psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
-    else
-        memset( pImage, 0, 
-                psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                            IWriteBlock()                             */
-/************************************************************************/
-
-CPLErr NITFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                    void * pImage )
-    
-{
-    int  nBlockResult;
-
-/* -------------------------------------------------------------------- */
-/*      Write the line/block                                            */
-/* -------------------------------------------------------------------- */
-    if( nBlockYSize == 1 )
-    {
-        nBlockResult = 
-            NITFWriteImageLine(psImage, nBlockYOff, nBand, pImage);
-    }
-    else
-    {
-        nBlockResult = 
-            NITFWriteImageBlock(psImage, nBlockXOff, nBlockYOff, nBand,pImage);
-    }
-
-    if( nBlockResult == BLKREAD_OK )
-        return CE_None;
-    else
-        return CE_Failure;
-}
-
-/************************************************************************/
-/*                           GetNoDataValue()                           */
-/************************************************************************/
-
-double NITFRasterBand::GetNoDataValue( int *pbSuccess )
-
-{
-    if( pbSuccess != NULL )
-        *pbSuccess = psImage->bNoDataSet;
-
-    if( psImage->bNoDataSet )
-        return psImage->nNoDataValue;
-    else
-        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
-}
-
-/************************************************************************/
-/*                       GetColorInterpretation()                       */
-/************************************************************************/
-
-GDALColorInterp NITFRasterBand::GetColorInterpretation()
-
-{
-    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
-
-    if( poColorTable != NULL )
-        return GCI_PaletteIndex;
-    
-    if( EQUAL(psBandInfo->szIREPBAND,"R") )
-        return GCI_RedBand;
-    if( EQUAL(psBandInfo->szIREPBAND,"G") )
-        return GCI_GreenBand;
-    if( EQUAL(psBandInfo->szIREPBAND,"B") )
-        return GCI_BlueBand;
-    if( EQUAL(psBandInfo->szIREPBAND,"M") )
-        return GCI_GrayIndex;
-    if( EQUAL(psBandInfo->szIREPBAND,"Y") )
-        return GCI_YCbCr_YBand;
-    if( EQUAL(psBandInfo->szIREPBAND,"Cb") )
-        return GCI_YCbCr_CbBand;
-    if( EQUAL(psBandInfo->szIREPBAND,"Cr") )
-        return GCI_YCbCr_CrBand;
-
-    return GCI_Undefined;
-}
-
-/************************************************************************/
-/*                     NITFSetColorInterpretation()                     */
-/************************************************************************/
-
-static CPLErr NITFSetColorInterpretation( NITFImage *psImage, 
-                                          int nBand,
-                                          GDALColorInterp eInterp )
-
-{
-    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
-    const char *pszREP = NULL;
-    GUIntBig nOffset;
-
-    if( eInterp == GCI_RedBand )
-        pszREP = "R";
-    else if( eInterp == GCI_GreenBand )
-        pszREP = "G";
-    else if( eInterp == GCI_BlueBand )
-        pszREP = "B";
-    else if( eInterp == GCI_GrayIndex )
-        pszREP = "M";
-    else if( eInterp == GCI_YCbCr_YBand )
-        pszREP = "Y";
-    else if( eInterp == GCI_YCbCr_CbBand )
-        pszREP = "Cb";
-    else if( eInterp == GCI_YCbCr_CrBand )
-        pszREP = "Cr";
-    else if( eInterp == GCI_Undefined )
-        return CE_None;
-
-    if( pszREP == NULL )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "Requested color interpretation (%s) not supported in NITF.",
-                  GDALGetColorInterpretationName( eInterp ) );
-        return CE_Failure;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Where does this go in the file?                                 */
-/* -------------------------------------------------------------------- */
-    strcpy( psBandInfo->szIREPBAND, pszREP );
-    nOffset = NITFIHFieldOffset( psImage, "IREPBAND" );
-
-    if( nOffset != 0 )
-        nOffset += (nBand - 1) * 13;
-    
-/* -------------------------------------------------------------------- */
-/*      write it (space padded).                                        */
-/* -------------------------------------------------------------------- */
-    char szPadded[4];
-    strcpy( szPadded, pszREP );
-    strcat( szPadded, " " );
-    
-    if( nOffset != 0 )
-    {
-        if( VSIFSeekL( psImage->psFile->fp, nOffset, SEEK_SET ) != 0 
-            || VSIFWriteL( (void *) szPadded, 1, 2, psImage->psFile->fp ) != 2 )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "IO failure writing new IREPBAND value to NITF file." );
-            return CE_Failure;
-        }
-    }
-    
-    return CE_None;
-}
-
-/************************************************************************/
-/*                       SetColorInterpretation()                       */
-/************************************************************************/
-
-CPLErr NITFRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
-
-{
-    return NITFSetColorInterpretation( psImage, nBand, eInterp );
-}
-
-/************************************************************************/
-/*                           GetColorTable()                            */
-/************************************************************************/
-
-GDALColorTable *NITFRasterBand::GetColorTable()
-
-{
-    return poColorTable;
-}
-
-/************************************************************************/
-/*                           SetColorTable()                            */
-/************************************************************************/
-
-CPLErr NITFRasterBand::SetColorTable( GDALColorTable *poNewCT )
-
-{
-    NITFDataset *poGDS = (NITFDataset *) poDS;
-    if( poGDS->bInLoadXML )
-        return GDALPamRasterBand::SetColorTable(poNewCT);
-        
-    if( poNewCT == NULL )
-        return CE_Failure;
-
-    GByte abyNITFLUT[768];
-    int   i;
-    int   nCount = MIN(256,poNewCT->GetColorEntryCount());
-
-    memset( abyNITFLUT, 0, 768 );
-    for( i = 0; i < nCount; i++ )
-    {
-        GDALColorEntry sEntry;
-
-        poNewCT->GetColorEntryAsRGB( i, &sEntry );
-        abyNITFLUT[i    ] = (GByte) sEntry.c1;
-        abyNITFLUT[i+256] = (GByte) sEntry.c2;
-        abyNITFLUT[i+512] = (GByte) sEntry.c3;
-    }
-
-    if( NITFWriteLUT( psImage, nBand, nCount, abyNITFLUT ) )
-        return CE_None;
-    else
-        return CE_Failure;
-}
-
-/************************************************************************/
-/*                           Unpack()                                   */
-/************************************************************************/
-
-void NITFRasterBand::Unpack( GByte* pData )
-{
-  long n = nBlockXSize*nBlockYSize;
-  long i;
-  long k;
-
-  GByte abyTempData[7] = {0, 0, 0, 0, 0, 0, 0};
-  const GByte* pDataSrc = pData;
-  if (n < psImage->nBitsPerSample &&
-      psImage->nBitsPerSample < 8)
-  {
-      memcpy(abyTempData, pData, n);
-      pDataSrc = abyTempData;
-  }
-
-  switch (psImage->nBitsPerSample)
-  {
-    case 1:
-    {
-      // unpack 1-bit in-place in reverse
-      for (i = n; --i >= 0; )
-        pData[i] = (pData[i>>3] & (0x80 >> (i&7))) != 0;
-       
-      break;
-    }
-    case 2:
-    {
-      static const int s_Shift2[] = {6, 4, 2, 0};
-      // unpack 2-bit in-place in reverse
-      for (i = n; --i >= 0; )
-        pData[i] = (pData[i>>2] >> (GByte)s_Shift2[i&3]) & 0x03;
-       
-      break;
-    }
-    case 4:
-    {
-      static const int s_Shift4[] = {4, 0};
-      // unpack 4-bit in-place in reverse
-      for (i = n; --i >= 0; )
-        pData[i] = (pData[i>>1] >> (GByte)s_Shift4[i&1]) & 0x0f;
-       
-      break;
-    }
-    case 3:
-    {
-      // unpacks 8 pixels (3 bytes) at time
-      for (i = 0, k = 0; i < n; i += 8, k += 3)
-      {
-        pUnpackData[i+0] = ((pDataSrc[k+0] >> 5));
-        pUnpackData[i+1] = ((pDataSrc[k+0] >> 2) & 0x07);
-        pUnpackData[i+2] = ((pDataSrc[k+0] << 1) & 0x07) | (pDataSrc[k+1] >> 7);
-        pUnpackData[i+3] = ((pDataSrc[k+1] >> 4) & 0x07);
-        pUnpackData[i+4] = ((pDataSrc[k+1] >> 1) & 0x07);
-        pUnpackData[i+5] = ((pDataSrc[k+1] << 2) & 0x07) | (pDataSrc[k+2] >> 6);
-        pUnpackData[i+6] = ((pDataSrc[k+2] >> 3) & 0x07);
-        pUnpackData[i+7] = ((pDataSrc[k+2]) & 0x7);
-      }
-
-      memcpy(pData, pUnpackData, n);
-      break;
-    }
-    case 5:
-    {
-      // unpacks 8 pixels (5 bytes) at time
-      for (i = 0, k = 0; i < n; i += 8, k += 5)
-      {
-        pUnpackData[i+0] = ((pDataSrc[k+0] >> 3));
-        pUnpackData[i+1] = ((pDataSrc[k+0] << 2) & 0x1f) | (pDataSrc[k+1] >> 6);
-        pUnpackData[i+2] = ((pDataSrc[k+1] >> 1) & 0x1f);
-        pUnpackData[i+3] = ((pDataSrc[k+1] << 4) & 0x1f) | (pDataSrc[k+2] >> 4);
-        pUnpackData[i+4] = ((pDataSrc[k+2] << 1) & 0x1f) | (pDataSrc[k+3] >> 7);
-        pUnpackData[i+5] = ((pDataSrc[k+3] >> 2) & 0x1f);
-        pUnpackData[i+6] = ((pDataSrc[k+3] << 3) & 0x1f) | (pDataSrc[k+4] >> 5);
-        pUnpackData[i+7] = ((pDataSrc[k+4]) & 0x1f);
-      }
-
-      memcpy(pData, pUnpackData, n);
-      break;
-    }
-    case 6:
-    {
-      // unpacks 4 pixels (3 bytes) at time
-      for (i = 0, k = 0; i < n; i += 4, k += 3)
-      {
-        pUnpackData[i+0] = ((pDataSrc[k+0] >> 2));
-        pUnpackData[i+1] = ((pDataSrc[k+0] << 4) & 0x3f) | (pDataSrc[k+1] >> 4);
-        pUnpackData[i+2] = ((pDataSrc[k+1] << 2) & 0x3f) | (pDataSrc[k+2] >> 6);
-        pUnpackData[i+3] = ((pDataSrc[k+2]) & 0x3f);
-      }
-
-      memcpy(pData, pUnpackData, n);
-      break;
-    }
-    case 7:
-    {
-      // unpacks 8 pixels (7 bytes) at time
-      for (i = 0, k = 0; i < n; i += 8, k += 7)
-      {
-        pUnpackData[i+0] = ((pDataSrc[k+0] >> 1));
-        pUnpackData[i+1] = ((pDataSrc[k+0] << 6) & 0x7f) | (pDataSrc[k+1] >> 2);
-        pUnpackData[i+2] = ((pDataSrc[k+1] << 5) & 0x7f) | (pDataSrc[k+2] >> 3) ;
-        pUnpackData[i+3] = ((pDataSrc[k+2] << 4) & 0x7f) | (pDataSrc[k+3] >> 4);
-        pUnpackData[i+4] = ((pDataSrc[k+3] << 3) & 0x7f) | (pDataSrc[k+4] >> 5);
-        pUnpackData[i+5] = ((pDataSrc[k+4] << 2) & 0x7f) | (pDataSrc[k+5] >> 6);
-        pUnpackData[i+6] = ((pDataSrc[k+5] << 1) & 0x7f) | (pDataSrc[k+6] >> 7);
-        pUnpackData[i+7] = ((pDataSrc[k+6]) & 0x7f);
-      }
-
-      memcpy(pData, pUnpackData, n);
-      break;
-    }
-    case 12:
-    {
-      GByte*   pabyImage = (GByte  *)pData;
-      GUInt16* panImage  = (GUInt16*)pData;
-      for (i = n; --i >= 0; )
-      {
-        long iOffset = i*3 / 2;
-        if (i % 2 == 0)
-          panImage[i] = pabyImage[iOffset] + (pabyImage[iOffset+1] & 0xf0) * 16;
-        else
-          panImage[i] = (pabyImage[iOffset]   & 0x0f) * 16
-                      + (pabyImage[iOffset+1] & 0xf0) / 16
-                      + (pabyImage[iOffset+1] & 0x0f) * 256;
-      }
-
-      break;
-    }
-  }
-}
-
-/************************************************************************/
-/* ==================================================================== */
-/*                       NITFWrapperRasterBand                          */
-/* ==================================================================== */
-/************************************************************************/
-
-/* This class is used to wrap bands from JPEG or JPEG2000 datasets in */
-/* bands of the NITF dataset. Previously a trick was applied in the */
-/* relevant drivers to define a SetColorInterpretation() method and */
-/* to make sure they keep the proper pointer to their "natural" dataset */
-/* This trick is no longer necessary with the NITFWrapperRasterBand */
-/* We just override the few specific methods where we want that */
-/* the NITFWrapperRasterBand behaviour differs from the JPEG/JPEG2000 one */
-
-class NITFWrapperRasterBand : public GDALProxyRasterBand
-{
-  GDALRasterBand* poBaseBand;
-  GDALColorTable* poColorTable;
-  GDALColorInterp eInterp;
-
-  protected:
-    /* Pure virtual method of the GDALProxyRasterBand */
-    virtual GDALRasterBand* RefUnderlyingRasterBand();
-
-  public:
-                   NITFWrapperRasterBand( NITFDataset * poDS,
-                                          GDALRasterBand* poBaseBand,
-                                          int nBand);
-                  ~NITFWrapperRasterBand();
-    
-    /* Methods from GDALRasterBand we want to override */
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr          SetColorInterpretation( GDALColorInterp );
-    
-    virtual GDALColorTable *GetColorTable();
-
-    /* Specific method */
-    void                    SetColorTableFromNITFBandInfo(); 
-};
-
-/************************************************************************/
-/*                      NITFWrapperRasterBand()                         */
-/************************************************************************/
-
-NITFWrapperRasterBand::NITFWrapperRasterBand( NITFDataset * poDS,
-                                              GDALRasterBand* poBaseBand,
-                                              int nBand)
-{
-    this->poDS = poDS;
-    this->nBand = nBand;
-    this->poBaseBand = poBaseBand;
-    eDataType = poBaseBand->GetRasterDataType();
-    poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    poColorTable = NULL;
-    eInterp = poBaseBand->GetColorInterpretation();
-}
-
-/************************************************************************/
-/*                      ~NITFWrapperRasterBand()                        */
-/************************************************************************/
-
-NITFWrapperRasterBand::~NITFWrapperRasterBand()
-{
-    if( poColorTable != NULL )
-        delete poColorTable;
-}
-
-/************************************************************************/
-/*                     RefUnderlyingRasterBand()                        */
-/************************************************************************/
-
-/* We don't need ref-counting. Just return the base band */
-GDALRasterBand* NITFWrapperRasterBand::RefUnderlyingRasterBand()
-{
-	return poBaseBand;
-}
-
-/************************************************************************/
-/*                            GetColorTable()                           */
-/************************************************************************/
-
-GDALColorTable *NITFWrapperRasterBand::GetColorTable()
-{
-    return poColorTable;
-}
-
-/************************************************************************/
-/*                 SetColorTableFromNITFBandInfo()                      */
-/************************************************************************/
-
-void NITFWrapperRasterBand::SetColorTableFromNITFBandInfo()
-{
-    NITFDataset* poGDS = (NITFDataset* )poDS;
-    poColorTable = NITFMakeColorTable(poGDS->psImage,
-                                      poGDS->psImage->pasBandInfo + nBand - 1);
-}
-
-/************************************************************************/
-/*                        GetColorInterpretation()                      */
-/************************************************************************/
-
-GDALColorInterp NITFWrapperRasterBand::GetColorInterpretation()
-{
-    return eInterp;
-}
-
-/************************************************************************/
-/*                        SetColorInterpretation()                      */
-/************************************************************************/
-
-CPLErr NITFWrapperRasterBand::SetColorInterpretation( GDALColorInterp eInterp)
-{
-    this->eInterp = eInterp;
-    return CE_None;
-}
+#ifdef ESRI_BUILD
+static void SetBandMetadata( NITFImage *psImage, GDALRasterBand *poBand, int nBand );
+#endif
 
 /************************************************************************/
 /* ==================================================================== */
@@ -921,8 +103,31 @@ NITFDataset::NITFDataset()
 NITFDataset::~NITFDataset()
 
 {
+    CloseDependentDatasets();
+
+/* -------------------------------------------------------------------- */
+/*      Free datastructures.                                            */
+/* -------------------------------------------------------------------- */
+    CPLFree( pszProjection );
+
+    GDALDeinitGCPs( nGCPCount, pasGCPList );
+    CPLFree( pasGCPList );
+    CPLFree( pszGCPProjection );
+
+    CPLFree( panJPEGBlockOffset );
+    CPLFree( pabyJPEGBlock );
+}
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int NITFDataset::CloseDependentDatasets()
+{
     FlushCache();
 
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
 /* -------------------------------------------------------------------- */
 /*      If we have been writing to a JPEG2000 file, check if the        */
 /*      color interpretations were set.  If so, apply the settings      */
@@ -954,21 +159,14 @@ NITFDataset::~NITFDataset()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Free datastructures.                                            */
-/* -------------------------------------------------------------------- */
-    CPLFree( pszProjection );
-
-    GDALDeinitGCPs( nGCPCount, pasGCPList );
-    CPLFree( pasGCPList );
-    CPLFree( pszGCPProjection );
-
-/* -------------------------------------------------------------------- */
 /*      If we have a jpeg2000 output file, make sure it gets closed     */
 /*      and flushed out.                                                */
 /* -------------------------------------------------------------------- */
     if( poJ2KDataset != NULL )
     {
         GDALClose( (GDALDatasetH) poJ2KDataset );
+        poJ2KDataset = NULL;
+        bHasDroppedRef = TRUE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -984,6 +182,8 @@ NITFDataset::~NITFDataset()
                               "C8" );
     }
 
+    bJP2Writing = FALSE;
+
 /* -------------------------------------------------------------------- */
 /*      If we have a jpeg output file, make sure it gets closed         */
 /*      and flushed out.                                                */
@@ -991,11 +191,10 @@ NITFDataset::~NITFDataset()
     if( poJPEGDataset != NULL )
     {
         GDALClose( (GDALDatasetH) poJPEGDataset );
+        poJPEGDataset = NULL;
+        bHasDroppedRef = TRUE;
     }
 
-    CPLFree( panJPEGBlockOffset );
-    CPLFree( pabyJPEGBlock );
-
 /* -------------------------------------------------------------------- */
 /*      If the dataset was opened by Create(), we may need to write     */
 /*      the CGM and TEXT segments                                       */
@@ -1004,7 +203,25 @@ NITFDataset::~NITFDataset()
     NITFWriteTextSegments( GetDescription(), papszTextMDToWrite );
 
     CSLDestroy(papszTextMDToWrite);
+    papszTextMDToWrite = NULL;
     CSLDestroy(papszCgmMDToWrite);
+    papszCgmMDToWrite = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Destroy the raster bands if they exist.                         */
+/* We must do it now since the rasterbands can be NITFWrapperRasterBand */
+/* that derive from the GDALProxyRasterBand object, which keeps         */
+/* a reference on the JPEG/JP2K dataset, so any later call to           */
+/* FlushCache() would result in FlushCache() being called on a          */
+/* already destroyed object                                             */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       delete papoBands[iBand];
+    }
+    nBands = 0;
+
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -1029,6 +246,165 @@ void NITFDataset::FlushCache()
     GDALPamDataset::FlushCache();
 }
 
+#ifdef ESRI_BUILD
+
+/************************************************************************/
+/*                           ExtractEsriMD()                            */
+/*                                                                      */
+/*      Extracts ESRI-specific required meta data from metadata         */
+/*      string list papszStrList.                                       */
+/************************************************************************/
+
+static char **ExtractEsriMD( char **papszMD )
+{
+    char **papszEsriMD = NULL;
+
+    if( papszMD )
+    {
+        // These are the current generic ESRI metadata.
+        const char *const pEsriMDAcquisitionDate   = "ESRI_MD_ACQUISITION_DATE";
+        const char *const pEsriMDAngleToNorth      = "ESRI_MD_ANGLE_TO_NORTH";
+        const char *const pEsriMDCircularError     = "ESRI_MD_CE";
+        const char *const pEsriMDDataType          = "ESRI_MD_DATA_TYPE";
+        const char *const pEsriMDIsCloudCover      = "ESRI_MD_ISCLOUDCOVER";
+        const char *const pEsriMDLinearError       = "ESRI_MD_LE";
+        const char *const pEsriMDOffNaDir          = "ESRI_MD_OFF_NADIR";
+        const char *const pEsriMDPercentCloudCover = "ESRI_MD_PERCENT_CLOUD_COVER";
+        const char *const pEsriMDProductName       = "ESRI_MD_PRODUCT_NAME";
+        const char *const pEsriMDSensorAzimuth     = "ESRI_MD_SENSOR_AZIMUTH";
+        const char *const pEsriMDSensorElevation   = "ESRI_MD_SENSOR_ELEVATION";
+        const char *const pEsriMDSensorName        = "ESRI_MD_SENSOR_NAME";
+        const char *const pEsriMDSunAzimuth        = "ESRI_MD_SUN_AZIMUTH";
+        const char *const pEsriMDSunElevation      = "ESRI_MD_SUN_ELEVATION";
+
+        char         szField[11];
+        const char  *pCCImageSegment = CSLFetchNameValue( papszMD, "NITF_IID1" );
+        std::string  ccSegment("false");
+
+        if( ( pCCImageSegment != NULL ) && ( strlen(pCCImageSegment) <= 10 ) )
+        {
+            szField[0] = '\0';
+            strncpy( szField, pCCImageSegment, strlen(pCCImageSegment) );
+            szField[strlen(pCCImageSegment)] = '\0';
+
+            // Trim white off tag.
+            while( ( strlen(szField) > 0 ) && ( szField[strlen(szField)-1] == ' ' ) )
+                szField[strlen(szField)-1] = '\0';
+
+            if ((strlen(szField) == 2) && (EQUALN(szField, "CC", 2))) ccSegment.assign("true");
+        }
+
+        const char *pAcquisitionDate   = CSLFetchNameValue( papszMD, "NITF_FDT" );
+        const char *pAngleToNorth      = CSLFetchNameValue( papszMD, "NITF_CSEXRA_ANGLE_TO_NORTH" );
+        const char *pCircularError     = CSLFetchNameValue( papszMD, "NITF_CSEXRA_CIRCL_ERR" );      // Unit in feet.
+        const char *pLinearError       = CSLFetchNameValue( papszMD, "NITF_CSEXRA_LINEAR_ERR" );     // Unit in feet.
+        const char *pPercentCloudCover = CSLFetchNameValue( papszMD, "NITF_PIAIMC_CLOUDCVR" );
+        const char *pProductName       = CSLFetchNameValue( papszMD, "NITF_CSDIDA_PRODUCT_ID" );
+        const char *pSensorName        = CSLFetchNameValue( papszMD, "NITF_PIAIMC_SENSNAME" );
+        const char *pSunAzimuth        = CSLFetchNameValue( papszMD, "NITF_CSEXRA_SUN_AZIMUTH" );
+        const char *pSunElevation      = CSLFetchNameValue( papszMD, "NITF_CSEXRA_SUN_ELEVATION" );
+
+        // Get ESRI_MD_DATA_TYPE.
+        const char *pDataType        = NULL;
+        const char *pImgSegFieldICAT = CSLFetchNameValue( papszMD, "NITF_ICAT" );
+
+        if( ( pImgSegFieldICAT != NULL ) && ( EQUALN(pImgSegFieldICAT, "DTEM", 4) ) )
+            pDataType = "Elevation";
+        else
+            pDataType = "Generic";
+
+        if( pAngleToNorth == NULL )
+            pAngleToNorth = CSLFetchNameValue( papszMD, "NITF_USE00A_ANGLE_TO_NORTH" );
+
+        // Percent cloud cover == 999 means that the information is not available.
+        if( (pPercentCloudCover != NULL) &&  (EQUALN(pPercentCloudCover, "999", 3)) )
+            pPercentCloudCover = NULL;
+
+        pAngleToNorth = CSLFetchNameValue( papszMD, "NITF_USE00A_ANGLE_TO_NORTH" );
+
+        if( pSunAzimuth == NULL )
+            pSunAzimuth = CSLFetchNameValue( papszMD, "NITF_USE00A_SUN_AZ" );
+
+        if( pSunElevation == NULL )
+            pSunElevation = CSLFetchNameValue( papszMD, "NITF_USE00A_SUN_EL" );
+
+        // CSLAddNameValue will not add the key/value pair if the value is NULL.
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDAcquisitionDate,   pAcquisitionDate );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDAngleToNorth,      pAngleToNorth );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDCircularError,     pCircularError );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDDataType,          pDataType );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDIsCloudCover,      ccSegment.c_str() );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDLinearError,       pLinearError );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDProductName,       pProductName );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDPercentCloudCover, pPercentCloudCover );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDSensorName,        pSensorName );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDSunAzimuth,        pSunAzimuth );
+        papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDSunElevation,      pSunElevation );
+    }
+
+    return (papszEsriMD);
+}
+
+/************************************************************************/
+/*                          SetBandMetadata()                           */
+/************************************************************************/
+
+static void SetBandMetadata( NITFImage *psImage, GDALRasterBand *poBand, int nBand )
+{
+    if( (psImage != NULL) && (poBand != NULL) && (nBand > 0) )
+    {
+        NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
+
+        if( psBandInfo != NULL )
+        {
+            // Set metadata BandName, WavelengthMax and WavelengthMin.
+
+            if ( psBandInfo->szIREPBAND != NULL )
+            {
+                if( EQUAL(psBandInfo->szIREPBAND,"B") )
+                {
+                    poBand->SetMetadataItem( "BandName", "Blue" );
+                    poBand->SetMetadataItem( "WavelengthMax", psBandInfo->szISUBCAT );
+                    poBand->SetMetadataItem( "WavelengthMin", psBandInfo->szISUBCAT );
+                }
+                else if( EQUAL(psBandInfo->szIREPBAND,"G") )
+                {
+                    poBand->SetMetadataItem( "BandName", "Green" );
+                    poBand->SetMetadataItem( "WavelengthMax", psBandInfo->szISUBCAT );
+                    poBand->SetMetadataItem( "WavelengthMin", psBandInfo->szISUBCAT );
+                }
+                else if( EQUAL(psBandInfo->szIREPBAND,"R") )
+                {
+                    poBand->SetMetadataItem( "BandName", "Red" );
+                    poBand->SetMetadataItem( "WavelengthMax", psBandInfo->szISUBCAT );
+                    poBand->SetMetadataItem( "WavelengthMin", psBandInfo->szISUBCAT );
+                }
+                else if( EQUAL(psBandInfo->szIREPBAND,"N") )
+                {
+                    poBand->SetMetadataItem( "BandName", "NearInfrared" );
+                    poBand->SetMetadataItem( "WavelengthMax", psBandInfo->szISUBCAT );
+                    poBand->SetMetadataItem( "WavelengthMin", psBandInfo->szISUBCAT );
+                }
+                else if( ( EQUAL(psBandInfo->szIREPBAND,"M") ) || ( ( psImage->szIREP != NULL ) && ( EQUAL(psImage->szIREP,"MONO") ) ) )
+                {
+                    poBand->SetMetadataItem( "BandName", "Panchromatic" );
+                }
+                else
+                {
+                    if( ( psImage->szICAT != NULL ) && ( EQUAL(psImage->szICAT,"IR") ) )
+                    {
+                        poBand->SetMetadataItem( "BandName", "Infrared" );
+                        poBand->SetMetadataItem( "WavelengthMax", psBandInfo->szISUBCAT );
+                        poBand->SetMetadataItem( "WavelengthMin", psBandInfo->szISUBCAT );
+                    }
+                }
+            }
+        }
+    }
+}
+
+#endif /* def ESRI_BUILD */
+
 /************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
@@ -1045,6 +421,15 @@ int NITFDataset::Identify( GDALOpenInfo * poOpenInfo )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
+/*      Avoid that on Windows, JPEG_SUBFILE:x,y,z,data/../tmp/foo.ntf   */
+/*      to be recognized by the NITF driver, because                    */
+/*      'JPEG_SUBFILE:x,y,z,data' is considered as a (valid) directory  */
+/*      and thus the whole filename is evaluated as tmp/foo.ntf         */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszFilename,"JPEG_SUBFILE:",13) )
+        return FALSE;
+        
+/* -------------------------------------------------------------------- */
 /*	First we check to see if the file has the expected header	*/
 /*	bytes.								*/    
 /* -------------------------------------------------------------------- */
@@ -1073,10 +458,10 @@ int NITFDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo )
 {
-    return Open(poOpenInfo, NULL, FALSE);
+    return OpenInternal(poOpenInfo, NULL, FALSE);
 }
 
-GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
+GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
                                 GDALDataset *poWritableJ2KDataset,
                                 int bOpenForCreate)
 
@@ -1184,6 +569,11 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
         poDS->nRasterXSize = 1;
         poDS->nRasterYSize = 1;
     }
+        
+    /* Can be set to NO to avoid opening the underlying JPEG2000/JPEG */
+    /* stream. Might speed up operations when just metadata is needed */
+    int bOpenUnderlyingDS = CSLTestBoolean(
+            CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES"));
 
 /* -------------------------------------------------------------------- */
 /*      If the image is JPEG2000 (C8) compressed, we will need to       */
@@ -1197,7 +587,7 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
     if( psImage )
         nUsableBands = psImage->nBands;
 
-    if( psImage != NULL && EQUAL(psImage->szIC,"C8") )
+    if( bOpenUnderlyingDS && psImage != NULL && EQUAL(psImage->szIC,"C8") )
     {
         CPLString osDSName;
 
@@ -1218,15 +608,25 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
             /* to be opened by a random driver, and also to make sure that */
             /* a future new JPEG2000 compatible driver derives from GDALPamDataset */
             static const char * const apszDrivers[] = { "JP2KAK", "JP2ECW", "JP2MRSID",
-                                          "JPEG2000", "JP2OPENJPEG", NULL };
+                                                        "JPEG2000", "JP2OPENJPEG", NULL };
             poDS->poJ2KDataset = (GDALPamDataset *)
-                        GDALOpenInternal( osDSName, GA_ReadOnly, apszDrivers);
+                GDALOpenInternal( osDSName, GA_ReadOnly, apszDrivers);
 
             if( poDS->poJ2KDataset == NULL )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Unable to open JPEG2000 image within NITF file.\n"
-                          "Is the JP2KAK driver available?" );
+                int bFoundJPEG2000Driver = FALSE;
+                for(int iDriver=0;apszDrivers[iDriver]!=NULL;iDriver++)
+                {
+                    if (GDALGetDriverByName(apszDrivers[iDriver]) != NULL)
+                        bFoundJPEG2000Driver = TRUE;
+                }
+
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Unable to open JPEG2000 image within NITF file.\n%s\n%s",
+                         (!bFoundJPEG2000Driver) ?
+                            "No JPEG2000 capable driver (JP2KAK, JP2ECW, JP2MRSID, JP2OPENJPEG, etc...) is available." :
+                            "One or several JPEG2000 capable drivers are available but the datastream could not be opened successfully.",
+                         "You can define the NITF_OPEN_UNDERLYING_DS configuration option to NO, in order to just get the metadata.");
                 delete poDS;
                 return NULL;
             }
@@ -1284,7 +684,7 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
 /*      If the image is JPEG (C3) compressed, we will need to open      */
 /*      the image data as a JPEG dataset.                               */
 /* -------------------------------------------------------------------- */
-    else if( psImage != NULL
+    else if( bOpenUnderlyingDS && psImage != NULL
              && EQUAL(psImage->szIC,"C3") 
              && psImage->nBlocksPerRow == 1
              && psImage->nBlocksPerColumn == 1 )
@@ -1307,9 +707,13 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
         poDS->poJPEGDataset = (GDALPamDataset*) GDALOpen(osDSName,GA_ReadOnly);
         if( poDS->poJPEGDataset == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to open JPEG image within NITF file.\n"
-                      "Is the JPEG driver available?" );
+            int bFoundJPEGDriver = GDALGetDriverByName("JPEG") != NULL;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "Unable to open JPEG image within NITF file.\n%s\n%s",
+                     (!bFoundJPEGDriver) ?
+                        "The JPEG driver is not available." :
+                        "The JPEG driver is available but the datastream could not be opened successfully.",
+                     "You can define the NITF_OPEN_UNDERLYING_DS configuration option to NO, in order to just get the metadata.");
             delete poDS;
             return NULL;
         }
@@ -1352,6 +756,11 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
         {
             GDALRasterBand* poBaseBand =
                 poBaseDS->GetRasterBand(iBand+1);
+
+#ifdef ESRI_BUILD
+            SetBandMetadata( psImage, poBaseBand, iBand+1 );
+#endif
+
             NITFWrapperRasterBand* poBand =
                 new NITFWrapperRasterBand(poDS, poBaseBand, iBand+1 );
                 
@@ -1393,6 +802,11 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
                 delete poDS;
                 return NULL;
             }
+
+#ifdef ESRI_BUILD
+            SetBandMetadata( psImage, poBand, iBand+1 );
+#endif
+
             poDS->SetBand( iBand+1, poBand );
         }
     }
@@ -1663,6 +1077,16 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Do we have RPCs?                                                */
+/* -------------------------------------------------------------------- */
+    int            bHasRPC00 = FALSE;
+    NITFRPC00BInfo sRPCInfo;
+    memset(&sRPCInfo, 0, sizeof(sRPCInfo)); /* To avoid warnings from not clever compilers */
+
+    if( psImage && NITFReadRPC00B( psImage, &sRPCInfo ) && sRPCInfo.SUCCESS )
+        bHasRPC00 = TRUE;
+        
+/* -------------------------------------------------------------------- */
 /*      Do we have IGEOLO data that can be treated as a                 */
 /*      geotransform?  Our approach should support images in an         */
 /*      affine rotated frame of reference.                              */
@@ -1711,6 +1135,22 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
 
         psGCPs[3].dfGCPX		= psImage->dfLLX;
         psGCPs[3].dfGCPY		= psImage->dfLLY;
+
+/* -------------------------------------------------------------------- */
+/*      ESRI desires to use the RPCs to produce a denser and more       */
+/*      accurate set of GCPs in this case.  Details are unclear at      */
+/*      this time.                                                      */
+/* -------------------------------------------------------------------- */
+#ifdef ESRI_BUILD
+        if( bHasRPC00
+            &&  ( (psImage->chICORDS == 'G') || (psImage->chICORDS == 'C') ) )
+        {
+            if( nGCPCount == 4 )
+                NITFDensifyGCPs( &psGCPs, &nGCPCount );
+
+            NITFUpdateGCPsWithRPC( &sRPCInfo, psGCPs, &nGCPCount );
+        }
+#endif /* def ESRI_BUILD */
     }
 
 /* -------------------------------------------------------------------- */
@@ -1735,7 +1175,7 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
               || psImage->dfLRX != 0 || psImage->dfLLX != 0)
              && psImage->chICORDS != ' ' && 
              ( poDS->bGotGeoTransform == FALSE ) &&
-             nGCPCount == 4 )
+             nGCPCount >= 4 )
     {
         CPLDebug( "GDAL", 
                   "NITFDataset::Open() wasn't able to derive a first order\n"
@@ -1782,7 +1222,7 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
 /*      Do we have metadata.                                            */
 /* -------------------------------------------------------------------- */
     char **papszMergedMD;
-    char **papszUSE00A_MD;
+    char **papszTRE_MD;
 
     // File and Image level metadata.
     papszMergedMD = CSLDuplicate( poDS->psFile->papszMetadata );
@@ -1837,36 +1277,31 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
                                  psImage->szIMAG );
         }
 
-        // USE00A 
-        papszUSE00A_MD = NITFReadUSE00A( psImage );
-        if( papszUSE00A_MD != NULL )
-        {
-            papszMergedMD = CSLInsertStrings( papszMergedMD, 
-                                              CSLCount( papszUSE00A_MD ),
-                                              papszUSE00A_MD );
-            CSLDestroy( papszUSE00A_MD );
-        }
-        
+        papszMergedMD = NITFGenericMetadataRead(papszMergedMD, psFile, psImage, NULL);
+
         // BLOCKA 
-        papszUSE00A_MD = NITFReadBLOCKA( psImage );
-        if( papszUSE00A_MD != NULL )
+        papszTRE_MD = NITFReadBLOCKA( psImage );
+        if( papszTRE_MD != NULL )
         {
             papszMergedMD = CSLInsertStrings( papszMergedMD, 
-                                              CSLCount( papszUSE00A_MD ),
-                                              papszUSE00A_MD );
-            CSLDestroy( papszUSE00A_MD );
-        }
-        
-        papszUSE00A_MD = NITFReadSTDIDC( psImage );
-        if( papszUSE00A_MD != NULL )
-        {
-            papszMergedMD = CSLInsertStrings( papszMergedMD, 
-                                              CSLCount( papszUSE00A_MD ),
-                                              papszUSE00A_MD );
-            CSLDestroy( papszUSE00A_MD );
+                                              CSLCount( papszTRE_MD ),
+                                              papszTRE_MD );
+            CSLDestroy( papszTRE_MD );
         }
     }
         
+#ifdef ESRI_BUILD
+    // Extract ESRI generic metadata.
+    char **papszESRI_MD = ExtractEsriMD( papszMergedMD );
+    if( papszESRI_MD != NULL )
+    {
+        papszMergedMD = CSLInsertStrings( papszMergedMD, 
+                                          CSLCount( papszESRI_MD ),
+                                          papszESRI_MD );
+        CSLDestroy( papszESRI_MD );
+    }
+#endif
+
     poDS->SetMetadata( papszMergedMD );
     CSLDestroy( papszMergedMD );
 
@@ -1897,10 +1332,7 @@ GDALDataset *NITFDataset::Open( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Do we have RPC info.                                            */
 /* -------------------------------------------------------------------- */
-    NITFRPC00BInfo sRPCInfo;
-
-    if( psImage
-        && NITFReadRPC00B( psImage, &sRPCInfo ) && sRPCInfo.SUCCESS )
+    if( psImage && bHasRPC00 )
     {
         char szValue[1280];
         int  i;
@@ -2515,136 +1947,518 @@ CPLErr NITFDataset::IRasterIO( GDALRWFlag eRWFlag,
 }
 
 
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr NITFDataset::GetGeoTransform( double *padfGeoTransform )
+
+{
+    memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
+
+    if( bGotGeoTransform )
+        return CE_None;
+    else
+        return GDALPamDataset::GetGeoTransform( padfGeoTransform );
+}
+
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr NITFDataset::SetGeoTransform( double *padfGeoTransform )
+
+{
+    double dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY, 
+           dfIGEOLOLRX, dfIGEOLOLRY, dfIGEOLOLLX, dfIGEOLOLLY;
+
+    bGotGeoTransform = TRUE;
+    /* Valgrind would complain because SetGeoTransform() is called */
+    /* from SetProjection() with adfGeoTransform as argument */
+    if (adfGeoTransform != padfGeoTransform)
+        memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
+
+    dfIGEOLOULX = padfGeoTransform[0] + 0.5 * padfGeoTransform[1] 
+                                      + 0.5 * padfGeoTransform[2];
+    dfIGEOLOULY = padfGeoTransform[3] + 0.5 * padfGeoTransform[4] 
+                                      + 0.5 * padfGeoTransform[5];
+    dfIGEOLOURX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1);
+    dfIGEOLOURY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1);
+    dfIGEOLOLRX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1)
+                              + padfGeoTransform[2] * (nRasterYSize - 1);
+    dfIGEOLOLRY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1)
+                              + padfGeoTransform[5] * (nRasterYSize - 1);
+    dfIGEOLOLLX = dfIGEOLOULX + padfGeoTransform[2] * (nRasterYSize - 1);
+    dfIGEOLOLLY = dfIGEOLOULY + padfGeoTransform[5] * (nRasterYSize - 1);
+
+    if( NITFWriteIGEOLO( psImage, psImage->chICORDS, 
+                         psImage->nZone, 
+                         dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY, 
+                         dfIGEOLOLRX, dfIGEOLOLRY, dfIGEOLOLLX, dfIGEOLOLLY ) )
+        return CE_None;
+    else
+        return GDALPamDataset::SetGeoTransform( padfGeoTransform );
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *NITFDataset::GetProjectionRef()
+
+{
+    if( bGotGeoTransform )
+        return pszProjection;
+    else
+        return GDALPamDataset::GetProjectionRef();
+}
+
+/************************************************************************/
+/*                            SetProjection()                           */
+/************************************************************************/
+
+CPLErr NITFDataset::SetProjection(const char* _pszProjection)
+
+{
+    int    bNorth;
+    OGRSpatialReference oSRS, oSRS_WGS84;
+    char *pszWKT = (char *) _pszProjection;
+
+    if( pszWKT != NULL )
+        oSRS.importFromWkt( &pszWKT );
+    else
+        return CE_Failure;
+
+    oSRS_WGS84.SetWellKnownGeogCS( "WGS84" );
+    if ( oSRS.IsSameGeogCS(&oSRS_WGS84) == FALSE)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "NITF only supports WGS84 geographic and UTM projections.\n");
+        return CE_Failure;
+    }
+
+    if( oSRS.IsGeographic() && oSRS.GetPrimeMeridian() == 0.0)
+    {
+        if (psImage->chICORDS != 'G' && psImage->chICORDS != 'D')
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "NITF file should have been created with creation option 'ICORDS=G' (or 'ICORDS=D').\n");
+            return CE_Failure;
+        }
+    }
+    else if( oSRS.GetUTMZone( &bNorth ) > 0)
+    {
+        if (bNorth && psImage->chICORDS != 'N')
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "NITF file should have been created with creation option 'ICORDS=N'.\n");
+            return CE_Failure;
+        }
+        else if (!bNorth && psImage->chICORDS != 'S')
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "NITF file should have been created with creation option 'ICORDS=S'.\n");
+            return CE_Failure;
+        }
+
+        psImage->nZone = oSRS.GetUTMZone( NULL );
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "NITF only supports WGS84 geographic and UTM projections.\n");
+        return CE_Failure;
+    }
+
+    CPLFree(pszProjection);
+    pszProjection = CPLStrdup(_pszProjection);
+
+    if (bGotGeoTransform)
+        SetGeoTransform(adfGeoTransform);
+
+    return CE_None;
+}
+
+#ifdef ESRI_BUILD
+/************************************************************************/
+/*                       InitializeNITFDESMetadata()                    */
+/************************************************************************/
+
+void NITFDataset::InitializeNITFDESMetadata()
+{
+    static const char   *pszDESMetadataDomain       = "NITF_DES_METADATA";
+    static const char   *pszDESsDomain              = "NITF_DES";
+    static const char   *pszMDXmlDataContentDESDATA = "NITF_DES_XML_DATA_CONTENT_DESDATA";
+    static const char   *pszXmlDataContent          = "XML_DATA_CONTENT";
+    static const int     idxXmlDataContentDESDATA   = 973;
+    static const int     sizeXmlDataContent         = (int)strlen(pszXmlDataContent);
+
+    char **ppszDESMetadataList = oSpecialMD.GetMetadata( pszDESMetadataDomain );
+
+    if( ppszDESMetadataList != NULL ) return;
+
+    char **ppszDESsList = this->GetMetadata( pszDESsDomain );
+
+    if( ppszDESsList == NULL ) return;
+
+    bool          foundXmlDataContent = false;
+    char         *pachNITFDES         = NULL;
+
+    // Set metadata "NITF_DES_XML_DATA_CONTENT_DESDATA".
+    // NOTE: There should only be one instance of XML_DATA_CONTENT DES.
+
+    while( ((pachNITFDES = *ppszDESsList) != NULL) && (!foundXmlDataContent) )
+    {
+        // The data stream has been Base64 encoded, need to decode it.
+        // NOTE: The actual length of the DES data stream is appended at the beginning of the encoded
+        //       data and is separated by a space.
+
+        const char* pszSpace = strchr(pachNITFDES, ' ');
+
+        char* pszData = NULL;
+        int   nDataLen = 0;
+        if( pszSpace )
+        {
+            pszData = CPLStrdup( pszSpace+1 );
+            nDataLen = CPLBase64DecodeInPlace((GByte*)pszData);
+            pszData[nDataLen] = 0;
+        }
+
+        if ( nDataLen > 2 + sizeXmlDataContent && EQUALN(pszData, "DE", 2) )
+        {
+            // Check to see if this is a XML_DATA_CONTENT DES.
+            if ( EQUALN(pszData + 2, pszXmlDataContent, sizeXmlDataContent) &&
+                 nDataLen > idxXmlDataContentDESDATA )
+            {
+                foundXmlDataContent = true;
+
+                // Get the value of the DESDATA field and set metadata "NITF_DES_XML_DATA_CONTENT_DESDATA".
+                const char* pszXML = pszData + idxXmlDataContentDESDATA;
+
+                // Set the metadata.
+                oSpecialMD.SetMetadataItem( pszMDXmlDataContentDESDATA, pszXML, pszDESMetadataDomain );
+            }
+        }
+
+        CPLFree(pszData);
+
+        pachNITFDES   = NULL;
+        ppszDESsList += 1;
+    }
+}
+
+
+/************************************************************************/
+/*                       InitializeNITFDESs()                           */
+/************************************************************************/
+
+void NITFDataset::InitializeNITFDESs()
+{
+    static const char *pszDESsDomain = "NITF_DES";
+
+    char **ppszDESsList = oSpecialMD.GetMetadata( pszDESsDomain );
+
+    if( ppszDESsList != NULL ) return;
+
+/* -------------------------------------------------------------------- */
+/*  Go through all the segments and process all DES segments.           */
+/* -------------------------------------------------------------------- */
+
+    char               *pachDESData  = NULL;
+    int                 nDESDataSize = 0;
+    std::string         encodedDESData("");
+    CPLStringList       aosList;
+
+    for( int iSegment = 0; iSegment < psFile->nSegmentCount; iSegment++ )
+    {
+        NITFSegmentInfo *psSegInfo = psFile->pasSegmentInfo + iSegment;
+
+        if( EQUAL(psSegInfo->szSegmentType,"DE") )
+        {
+            nDESDataSize = psSegInfo->nSegmentHeaderSize + psSegInfo->nSegmentSize;
+            pachDESData  = (char*) VSIMalloc( nDESDataSize + 1 );
+
+            if (pachDESData == NULL)
+            {
+                CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory for DES segment" );
+                return;
+            }
+
+            if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
+                          SEEK_SET ) != 0
+                || (int)VSIFReadL( pachDESData, 1, nDESDataSize,
+                             psFile->fp ) != nDESDataSize )
+            {
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Failed to read %d byte DES subheader from " CPL_FRMT_GUIB ".",
+                          nDESDataSize,
+                          psSegInfo->nSegmentHeaderStart );
+                CPLFree( pachDESData );
+                return;
+            }
+
+            pachDESData[nDESDataSize] = '\0';
+
+/* -------------------------------------------------------------------- */
+/*          Accumulate all the DES segments.                            */
+/* -------------------------------------------------------------------- */
+
+            char* pszBase64 = CPLBase64Encode( nDESDataSize, (const GByte *)pachDESData );
+            encodedDESData = pszBase64;
+            CPLFree(pszBase64);
+
+            CPLFree( pachDESData );
+            pachDESData = NULL;
+
+            if( encodedDESData.empty() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Failed to encode DES subheader data!");
+                return;
+            }
+
+            // The length of the DES subheader data plus a space is append to the beginning of the encoded
+            // string so that we can recover the actual length of the image subheader when we decode it.
+
+            char buffer[20];
+
+            sprintf(buffer, "%d", nDESDataSize);
+
+            std::string desSubheaderStr(buffer);
+            desSubheaderStr.append(" ");
+            desSubheaderStr.append(encodedDESData);
+
+            aosList.AddString(desSubheaderStr.c_str() );
+        }
+    }
+
+    if (aosList.size() > 0)
+        oSpecialMD.SetMetadata( aosList.List(), pszDESsDomain );
+}
+
+/************************************************************************/
+/*                       InitializeNITFTREs()                           */
+/************************************************************************/
+
+void NITFDataset::InitializeNITFTREs()
+{
+    static const char *pszFileHeaderTREsDomain   = "NITF_FILE_HEADER_TRES";
+    static const char *pszImageSegmentTREsDomain = "NITF_IMAGE_SEGMENT_TRES";
+
+    char **ppszFileHeaderTREsList   = oSpecialMD.GetMetadata( pszFileHeaderTREsDomain );
+    char **ppszImageSegmentTREsList = oSpecialMD.GetMetadata( pszImageSegmentTREsDomain );
+
+    if( (ppszFileHeaderTREsList != NULL) && (ppszImageSegmentTREsList != NULL ) ) return;
+
+/* -------------------------------------------------------------------- */
+/*      Loop over TRE sources (file and image).                         */
+/* -------------------------------------------------------------------- */
+
+    for( int nTRESrc = 0; nTRESrc < 2; nTRESrc++ )
+    {
+        int                 nTREBytes  = 0;
+        char               *pszTREData = NULL;
+        const char         *pszTREsDomain = NULL;
+        CPLStringList       aosList;
+
+/* -------------------------------------------------------------------- */
+/*      Extract file header or image segment TREs.                      */
+/* -------------------------------------------------------------------- */
+
+        if( nTRESrc == 0 )
+        {
+            if( ppszFileHeaderTREsList != NULL ) continue;
+
+            nTREBytes     = psFile->nTREBytes;
+            pszTREData    = psFile->pachTRE;
+            pszTREsDomain = pszFileHeaderTREsDomain;
+        }
+        else
+        {
+            if( ppszImageSegmentTREsList != NULL ) continue;
+
+            if( psImage )
+            {
+                nTREBytes     = psImage->nTREBytes;
+                pszTREData    = psImage->pachTRE;
+                pszTREsDomain = pszImageSegmentTREsDomain;
+            }
+            else
+            {
+                nTREBytes  = 0;
+                pszTREData = NULL;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Loop over TREs.                                                 */
+/* -------------------------------------------------------------------- */
+
+        while( nTREBytes >= 11 )
+        {
+            char szTemp[100];
+            char szTag[7];
+            char *pszEscapedData = NULL;
+            int nThisTRESize = atoi(NITFGetField(szTemp, pszTREData, 6, 5 ));
+
+            if (nThisTRESize < 0)
+            {
+                NITFGetField(szTemp, pszTREData, 0, 6 );
+                CPLError(CE_Failure, CPLE_AppDefined, "Invalid size (%d) for TRE %s",
+                        nThisTRESize, szTemp);
+                return;
+            }
+
+            if (nThisTRESize > nTREBytes - 11)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Not enough bytes in TRE");
+                return;
+            }
+
+            strncpy( szTag, pszTREData, 6 );
+            szTag[6] = '\0';
 
-CPLErr NITFDataset::GetGeoTransform( double *padfGeoTransform )
+            // trim white off tag.
+            while( strlen(szTag) > 0 && szTag[strlen(szTag)-1] == ' ' )
+                szTag[strlen(szTag)-1] = '\0';
 
-{
-    memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
+            // escape data.
+            pszEscapedData = CPLEscapeString( pszTREData + 6,
+                                              nThisTRESize + 5,
+                                              CPLES_BackslashQuotable );
 
-    if( bGotGeoTransform )
-        return CE_None;
-    else
-        return GDALPamDataset::GetGeoTransform( padfGeoTransform );
+            char * pszLine = (char *) CPLMalloc( strlen(szTag)+strlen(pszEscapedData)+2 );
+            sprintf( pszLine, "%s=%s", szTag, pszEscapedData );
+            aosList.AddString(pszLine);
+            CPLFree(pszLine);
+            pszLine        = NULL;
+
+            CPLFree( pszEscapedData );
+            pszEscapedData = NULL;
+
+            nTREBytes  -= (nThisTRESize + 11);
+            pszTREData += (nThisTRESize + 11);
+        }
+
+        if (aosList.size() > 0)
+            oSpecialMD.SetMetadata( aosList.List(), pszTREsDomain );
+    }
 }
+#endif
 
 /************************************************************************/
-/*                          SetGeoTransform()                           */
+/*                       InitializeNITFMetadata()                        */
 /************************************************************************/
 
-CPLErr NITFDataset::SetGeoTransform( double *padfGeoTransform )
+void NITFDataset::InitializeNITFMetadata()
 
 {
-    double dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY, 
-           dfIGEOLOLRX, dfIGEOLOLRY, dfIGEOLOLLX, dfIGEOLOLLY;
+    static const char *pszDomainName            = "NITF_METADATA";
+    static const char *pszTagNITFFileHeader     = "NITFFileHeader";
+    static const char *pszTagNITFImageSubheader = "NITFImageSubheader";
 
-    bGotGeoTransform = TRUE;
-    /* Valgrind would complain because SetGeoTransform() is called */
-    /* from SetProjection() with adfGeoTransform as argument */
-    if (adfGeoTransform != padfGeoTransform)
-        memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
+    if( oSpecialMD.GetMetadata( pszDomainName ) != NULL )
+        return;
 
-    dfIGEOLOULX = padfGeoTransform[0] + 0.5 * padfGeoTransform[1] 
-                                      + 0.5 * padfGeoTransform[2];
-    dfIGEOLOULY = padfGeoTransform[3] + 0.5 * padfGeoTransform[4] 
-                                      + 0.5 * padfGeoTransform[5];
-    dfIGEOLOURX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1);
-    dfIGEOLOURY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1);
-    dfIGEOLOLRX = dfIGEOLOULX + padfGeoTransform[1] * (nRasterXSize - 1)
-                              + padfGeoTransform[2] * (nRasterYSize - 1);
-    dfIGEOLOLRY = dfIGEOLOULY + padfGeoTransform[4] * (nRasterXSize - 1)
-                              + padfGeoTransform[5] * (nRasterYSize - 1);
-    dfIGEOLOLLX = dfIGEOLOULX + padfGeoTransform[2] * (nRasterYSize - 1);
-    dfIGEOLOLLY = dfIGEOLOULY + padfGeoTransform[5] * (nRasterYSize - 1);
+    // nHeaderLenOffset is the number of bytes to skip from the beginning of the NITF file header
+    // in order to get to the field HL (NITF file header length).
 
-    if( NITFWriteIGEOLO( psImage, psImage->chICORDS, 
-                         psImage->nZone, 
-                         dfIGEOLOULX, dfIGEOLOULY, dfIGEOLOURX, dfIGEOLOURY, 
-                         dfIGEOLOLRX, dfIGEOLOLRY, dfIGEOLOLLX, dfIGEOLOLLY ) )
-        return CE_None;
-    else
-        return GDALPamDataset::SetGeoTransform( padfGeoTransform );
-}
+    int nHeaderLen       = 0;
+    int nHeaderLenOffset = 0;
 
-/************************************************************************/
-/*                          GetProjectionRef()                          */
-/************************************************************************/
+    // Get the NITF file header length.
 
-const char *NITFDataset::GetProjectionRef()
+    if( psFile->pachHeader != NULL )
+    {
+        if ( (strncmp(psFile->pachHeader, "NITF02.10", 9) == 0) || (strncmp(psFile->pachHeader, "NSIF01.00", 9) == 0) )
+            nHeaderLenOffset = 354;
+        else if ( (strncmp(psFile->pachHeader, "NITF01.10", 9) == 0) || (strncmp(psFile->pachHeader, "NITF02.00", 9) == 0) )
+            nHeaderLenOffset = ( strncmp((psFile->pachHeader+280), "999998", 6 ) == 0 ) ? 394 : 354;
+    }
 
-{
-    if( bGotGeoTransform )
-        return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
-}
+    char fieldHL[7];
 
-/************************************************************************/
-/*                            SetProjection()                           */
-/************************************************************************/
+    if( nHeaderLenOffset > 0 )
+    {
+        char *pszFieldHL = psFile->pachHeader + nHeaderLenOffset;
 
-CPLErr NITFDataset::SetProjection(const char* _pszProjection)
+        memcpy(fieldHL, pszFieldHL, 6);
+        fieldHL[6] = '\0';
+        nHeaderLen = atoi(fieldHL);
+    }
 
-{
-    int    bNorth;
-    OGRSpatialReference oSRS, oSRS_WGS84;
-    char *pszWKT = (char *) _pszProjection;
+    if( nHeaderLen <= 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Zero length NITF file header!");
+        return;
+    }
 
-    if( pszWKT != NULL )
-        oSRS.importFromWkt( &pszWKT );
-    else
-        return CE_Failure;
+    char *encodedHeader = CPLBase64Encode(nHeaderLen, 
+                                          (GByte*)psFile->pachHeader);
 
-    oSRS_WGS84.SetWellKnownGeogCS( "WGS84" );
-    if ( oSRS.IsSameGeogCS(&oSRS_WGS84) == FALSE)
+    if (encodedHeader == NULL || strlen(encodedHeader) == 0 )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "NITF only supports WGS84 geographic and UTM projections.\n");
-        return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, 
+                 "Failed to encode NITF file header!");
+        return;
     }
 
-    if( oSRS.IsGeographic() && oSRS.GetPrimeMeridian() == 0.0)
+    // The length of the NITF file header plus a space is append to the beginning of the encoded string so
+    // that we can recover the length of the NITF file header when we decode it without having to pull it
+    // out the HL field again.
+
+    std::string nitfFileheaderStr(fieldHL);
+    nitfFileheaderStr.append(" ");
+    nitfFileheaderStr.append(encodedHeader);
+
+    CPLFree( encodedHeader );
+
+    oSpecialMD.SetMetadataItem( pszTagNITFFileHeader, nitfFileheaderStr.c_str(), pszDomainName );
+
+    // Get the image subheader length.
+
+    int nImageSubheaderLen = 0;
+    
+    for( int i = 0; i < psFile->nSegmentCount; ++i )
     {
-        if (psImage->chICORDS != 'G' && psImage->chICORDS != 'D')
+        if (strncmp(psFile->pasSegmentInfo[i].szSegmentType, "IM", 2) == 0)
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "NITF file should have been created with creation option 'ICORDS=G' (or 'ICORDS=D').\n");
-            return CE_Failure;
+            nImageSubheaderLen = psFile->pasSegmentInfo[i].nSegmentHeaderSize;
+            break;
         }
     }
-    else if( oSRS.GetUTMZone( &bNorth ) > 0)
+
+    if( nImageSubheaderLen < 0 )
     {
-        if (bNorth && psImage->chICORDS != 'N')
-        {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "NITF file should have been created with creation option 'ICORDS=N'.\n");
-            return CE_Failure;
-        }
-        else if (!bNorth && psImage->chICORDS != 'S')
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid length NITF image subheader!");
+        return;
+    }
+
+    if( nImageSubheaderLen > 0 )
+    {
+        char *encodedImageSubheader = CPLBase64Encode(nImageSubheaderLen,(GByte*) psImage->pachHeader);
+    
+        if( encodedImageSubheader == NULL || strlen(encodedImageSubheader) ==0 )
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "NITF file should have been created with creation option 'ICORDS=S'.\n");
-            return CE_Failure;
+            CPLError(CE_Failure, CPLE_AppDefined, 
+                     "Failed to encode image subheader!");
+            return;
         }
 
-        psImage->nZone = oSRS.GetUTMZone( NULL );
-    }
-    else
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "NITF only supports WGS84 geographic and UTM projections.\n");
-        return CE_Failure;
-    }
+        // The length of the image subheader plus a space is append to the beginning of the encoded string so
+        // that we can recover the actual length of the image subheader when we decode it.
+      
+        char buffer[20];
 
-    CPLFree(pszProjection);
-    pszProjection = CPLStrdup(_pszProjection);
+        sprintf(buffer, "%d", nImageSubheaderLen);
 
-    if (bGotGeoTransform)
-        SetGeoTransform(adfGeoTransform);
+        std::string imageSubheaderStr(buffer);
+        imageSubheaderStr.append(" ");
+        imageSubheaderStr.append(encodedImageSubheader);
 
-    return CE_None;
+        CPLFree( encodedImageSubheader );
+
+        oSpecialMD.SetMetadataItem( pszTagNITFImageSubheader, imageSubheaderStr.c_str(), pszDomainName );
+    }
 }
 
 /************************************************************************/
@@ -2852,6 +2666,8 @@ void NITFDataset::InitializeTREMetadata()
     if( oSpecialMD.GetMetadata( "TRE" ) != NULL )
         return;
 
+    CPLXMLNode* psTresNode = CPLCreateXMLNode(NULL, CXT_Element, "tres");
+
 /* -------------------------------------------------------------------- */
 /*      Loop over TRE sources (file and image).                         */
 /* -------------------------------------------------------------------- */
@@ -2911,7 +2727,15 @@ void NITFDataset::InitializeTREMetadata()
             // trim white off tag. 
             while( strlen(szTag) > 0 && szTag[strlen(szTag)-1] == ' ' )
                 szTag[strlen(szTag)-1] = '\0';
-            
+
+            CPLXMLNode* psTreNode = NITFCreateXMLTre(psFile, szTag, pszTREData + 11,nThisTRESize);
+            if (psTreNode)
+            {
+                CPLCreateXMLNode(CPLCreateXMLNode(psTreNode, CXT_Attribute, "location"),
+                                 CXT_Text, nTRESrc == 0 ? "file" : "image");
+                CPLAddXMLChild(psTresNode, psTreNode);
+            }
+
             // escape data. 
             pszEscapedData = CPLEscapeString( pszTREData + 11,
                                               nThisTRESize,
@@ -2922,7 +2746,15 @@ void NITFDataset::InitializeTREMetadata()
                 return;
             }
 
-            oSpecialMD.SetMetadataItem( szTag, pszEscapedData, "TRE" );
+            char szUniqueTag[32];
+            strcpy(szUniqueTag, szTag);
+            int nCountUnique = 2;
+            while(oSpecialMD.GetMetadataItem( szUniqueTag, "TRE") != NULL)
+            {
+                sprintf(szUniqueTag, "%s_%d", szTag, nCountUnique);
+                nCountUnique ++;
+            }
+            oSpecialMD.SetMetadataItem( szUniqueTag, pszEscapedData, "TRE" );
             CPLFree( pszEscapedData );
             
             nTREBytes -= (nThisTRESize + 11);
@@ -2967,7 +2799,24 @@ void NITFDataset::InitializeTREMetadata()
             while( strlen(szTREName) > 0 && szTREName[strlen(szTREName)-1] == ' ' )
                 szTREName[strlen(szTREName)-1] = '\0';
 
-            oSpecialMD.SetMetadataItem( szTREName, pszEscapedData, "TRE" );
+            CPLXMLNode* psTreNode = NITFCreateXMLTre(psFile, szTREName, pabyTREData,nThisTRESize);
+            if (psTreNode)
+            {
+                const char* pszDESID = CSLFetchNameValue(psDES->papszMetadata, "NITF_DESID");
+                CPLCreateXMLNode(CPLCreateXMLNode(psTreNode, CXT_Attribute, "location"),
+                                 CXT_Text, pszDESID ? CPLSPrintf("des %s", pszDESID) : "des");
+                CPLAddXMLChild(psTresNode, psTreNode);
+            }
+
+            char szUniqueTag[32];
+            strcpy(szUniqueTag, szTREName);
+            int nCountUnique = 2;
+            while(oSpecialMD.GetMetadataItem( szUniqueTag, "TRE") != NULL)
+            {
+                sprintf(szUniqueTag, "%s_%d", szTREName, nCountUnique);
+                nCountUnique ++;
+            }
+            oSpecialMD.SetMetadataItem( szUniqueTag, pszEscapedData, "TRE" );
 
             CPLFree(pszEscapedData);
 
@@ -2978,6 +2827,17 @@ void NITFDataset::InitializeTREMetadata()
 
         NITFDESDeaccess(psDES);
     }
+
+    if (psTresNode->psChild != NULL)
+    {
+        char* pszXML = CPLSerializeXMLTree(psTresNode);
+        char* apszMD[2];
+        apszMD[0] = pszXML;
+        apszMD[1] = NULL;
+        oSpecialMD.SetMetadata( apszMD, "xml:TRE" );
+        CPLFree(pszXML);
+    }
+    CPLDestroyXMLNode(psTresNode);
 }
 
 /************************************************************************/
@@ -2987,6 +2847,52 @@ void NITFDataset::InitializeTREMetadata()
 char **NITFDataset::GetMetadata( const char * pszDomain )
 
 {
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_METADATA") )
+    {
+        // InitializeNITFMetadata retrieves the NITF file header and all image segment file headers. (NOTE: The returned strings are base64-encoded).
+
+        InitializeNITFMetadata();
+        return oSpecialMD.GetMetadata( pszDomain );
+    }
+
+#ifdef ESRI_BUILD
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_DES") )
+    {
+        // InitializeNITFDESs retrieves all the DES file headers (NOTE: The returned strings are base64-encoded).
+
+        InitializeNITFDESs();
+        return oSpecialMD.GetMetadata( pszDomain );
+    }
+
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_DES_METADATA") )
+    {
+        // InitializeNITFDESs retrieves all the DES file headers (NOTE: The returned strings are base64-encoded).
+
+        InitializeNITFDESMetadata();
+        return oSpecialMD.GetMetadata( pszDomain );
+    }
+
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_FILE_HEADER_TRES") )
+    {
+        // InitializeNITFTREs retrieves all the TREs that are resides in the NITF file header and all the
+        // TREs that are resides in the current image segment.
+        // NOTE: the returned strings are backslash-escaped
+
+        InitializeNITFTREs();
+        return oSpecialMD.GetMetadata( pszDomain );
+    }
+
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_IMAGE_SEGMENT_TRES") )
+    {
+        // InitializeNITFTREs retrieves all the TREs that are resides in the NITF file header and all the
+        // TREs that are resides in the current image segment.
+        // NOTE: the returned strings are backslash-escaped
+
+        InitializeNITFTREs();
+        return oSpecialMD.GetMetadata( pszDomain );
+    }
+#endif
+
     if( pszDomain != NULL && EQUAL(pszDomain,"CGM") )
     {
         InitializeCGMMetadata();
@@ -3005,6 +2911,12 @@ char **NITFDataset::GetMetadata( const char * pszDomain )
         return oSpecialMD.GetMetadata( pszDomain );
     }
 
+    if( pszDomain != NULL && EQUAL(pszDomain,"xml:TRE") )
+    {
+        InitializeTREMetadata();
+        return oSpecialMD.GetMetadata( pszDomain );
+    }
+
     return GDALPamDataset::GetMetadata( pszDomain );
 }
 
@@ -3016,6 +2928,44 @@ const char *NITFDataset::GetMetadataItem(const char * pszName,
                                          const char * pszDomain )
 
 {
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_METADATA") )
+    {
+        // InitializeNITFMetadata retrieves the NITF file header and all image segment file headers. (NOTE: The returned strings are base64-encoded).
+
+        InitializeNITFMetadata();
+        return oSpecialMD.GetMetadataItem( pszName, pszDomain );
+    }
+
+#ifdef ESRI_BUILD
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_DES_METADATA") )
+    {
+        // InitializeNITFDESs retrieves all the DES file headers (NOTE: The returned strings are base64-encoded).
+
+        InitializeNITFDESMetadata();
+        return oSpecialMD.GetMetadataItem( pszName, pszDomain );
+    }
+
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_FILE_HEADER_TRES") )
+    {
+        // InitializeNITFTREs retrieves all the TREs that are resides in the NITF file header and all the
+        // TREs that are resides in the current image segment.
+        // NOTE: the returned strings are backslash-escaped
+
+        InitializeNITFTREs();
+        return oSpecialMD.GetMetadataItem( pszName, pszDomain );
+    }
+
+    if( pszDomain != NULL && EQUAL(pszDomain,"NITF_IMAGE_SEGMENT_TRES") )
+    {
+        // InitializeNITFTREs retrieves all the TREs that are resides in the NITF file header and all the
+        // TREs that are resides in the current image segment.
+        // NOTE: the returned strings are backslash-escaped
+
+        InitializeNITFTREs();
+        return oSpecialMD.GetMetadataItem( pszName, pszDomain );
+    }
+#endif
+
     if( pszDomain != NULL && EQUAL(pszDomain,"CGM") )
     {
         InitializeCGMMetadata();
@@ -3102,7 +3052,7 @@ int NITFDataset::CheckForRSets( const char *pszNITFFilename )
         if ( isR0File )
         {
           osTarget = pszNITFFilename;
-          osTarget[osTarget.size()-1] = ('0' + i );
+          osTarget[osTarget.size()-1] = (char) ('0' + i );
         }
         else
           osTarget.Printf( "%s.r%d", pszNITFFilename, i );
@@ -3533,6 +3483,57 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
 }
 
 /************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **NITFDataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+/* -------------------------------------------------------------------- */
+/*      Check for .imd file.                                            */
+/* -------------------------------------------------------------------- */
+    papszFileList = AddFile( papszFileList, "IMD", "imd" );
+
+/* -------------------------------------------------------------------- */
+/*      Check for .rpb file.                                            */
+/* -------------------------------------------------------------------- */
+    papszFileList = AddFile( papszFileList, "RPB", "rpb" );
+
+/* -------------------------------------------------------------------- */
+/*      Check for other files.                                          */
+/* -------------------------------------------------------------------- */
+    papszFileList = AddFile( papszFileList, "ATT", "att" );
+    papszFileList = AddFile( papszFileList, "EPH", "eph" );
+    papszFileList = AddFile( papszFileList, "GEO", "geo" );
+    papszFileList = AddFile( papszFileList, "XML", "xml" );
+
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                              AddFile()                               */
+/*                                                                      */
+/*      Helper method for GetFileList()                                 */
+/************************************************************************/
+char **NITFDataset::AddFile(char **papszFileList, const char* EXTENSION, const char* extension)
+{
+    VSIStatBufL sStatBuf;
+    CPLString osTarget = CPLResetExtension( osNITFFilename, EXTENSION );
+    if( VSIStatL( osTarget, &sStatBuf ) == 0 )
+        papszFileList = CSLAddString( papszFileList, osTarget );
+    else
+    {
+        osTarget = CPLResetExtension( osNITFFilename, extension );
+        if( VSIStatL( osTarget, &sStatBuf ) == 0 )
+            papszFileList = CSLAddString( papszFileList, osTarget );
+    }
+
+    return papszFileList;
+}
+
+/************************************************************************/
 /*                         GDALToNITFDataType()                         */
 /************************************************************************/
 
@@ -3789,7 +3790,7 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 
         CPLString osDSName;
 
-        osDSName.Printf("J2K_SUBFILE:" CPL_FRMT_GUIB ",%d,%s", nImageOffset, -1, pszFilename);
+        osDSName.Printf("/vsisubfile/" CPL_FRMT_GUIB "_%d,%s", nImageOffset, -1, pszFilename);
 
         NITFClose( psFile );
 
@@ -3812,7 +3813,7 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
     NITFDataset* poDS = (NITFDataset*)
-            NITFDataset::Open(&oOpenInfo, poWritableJ2KDataset, TRUE);
+            NITFDataset::OpenInternal(&oOpenInfo, poWritableJ2KDataset, TRUE);
     if (poDS)
     {
         poDS->papszTextMDToWrite = papszTextMD;
@@ -3870,7 +3871,8 @@ NITFDataset::NITFCreateCopy(
         {
             poJ2KDriver = 
                 GetGDALDriverManager()->GetDriverByName( "JP2ECW" );
-            if( poJ2KDriver == NULL )
+            if( poJ2KDriver == NULL || 
+                poJ2KDriver->GetMetadataItem( GDAL_DCAP_CREATECOPY, NULL ) == NULL )
             {
                 /* Try with Jasper as an alternate driver */
                 poJ2KDriver = 
@@ -3878,6 +3880,12 @@ NITFDataset::NITFCreateCopy(
             }
             if( poJ2KDriver == NULL )
             {
+                /* Try with JP2KAK as an alternate driver */
+                poJ2KDriver = 
+                    GetGDALDriverManager()->GetDriverByName( "JP2KAK" );
+            }
+            if( poJ2KDriver == NULL )
+            {
                 CPLError( 
                     CE_Failure, CPLE_AppDefined, 
                     "Unable to write JPEG2000 compressed NITF file.\n"
@@ -4242,20 +4250,12 @@ NITFDataset::NITFCreateCopy(
         GUIntBig nImageOffset = psFile->pasSegmentInfo[0].nSegmentStart;
         CPLString osDSName;
 
-        if (EQUAL(poJ2KDriver->GetDescription(), "JP2ECW"))
-        {
-            osDSName.Printf( "J2K_SUBFILE:" CPL_FRMT_GUIB ",%d,%s", nImageOffset, -1,
-                             pszFilename );
-        }
-        else
-        {
-            /* Jasper case */
-            osDSName.Printf( "/vsisubfile/" CPL_FRMT_GUIB "_%d,%s", nImageOffset, -1,
-                             pszFilename );
-        }
-                             
         NITFClose( psFile );
 
+        osDSName.Printf( "/vsisubfile/" CPL_FRMT_GUIB "_%d,%s", 
+                         nImageOffset, -1,
+                         pszFilename );
+                             
         if (EQUAL(poJ2KDriver->GetDescription(), "JP2ECW"))
         {
             char** papszJP2Options = NITFJP2Options(papszOptions);
@@ -4505,9 +4505,9 @@ static void NITFPatchImageLength( const char *pszFilename,
     VSIFWriteL( (void *) osLen.c_str(), 1, 10, fpVSIL );
 
 /* -------------------------------------------------------------------- */
-/*      Update COMRAT, the compression rate variable.  It is a bit      */
-/*      hard to know right here whether we have an IGEOLO segment,      */
-/*      so the COMRAT will either be at offset 778 or 838.              */
+/*      Update COMRAT, the compression rate variable.  We have to       */
+/*      take into account the presence of graphic and text segments,    */
+/*      the optional presence of IGEOLO and ICOM to find its position.  */
 /* -------------------------------------------------------------------- */
     char szICBuf[2];
     char achNUM[4]; // buffer for segment size.  3 digits plus null character
@@ -4532,18 +4532,23 @@ static void NITFPatchImageLength( const char *pszFilename,
 
     int nAdditionalOffset = nGS * 10 + nTS * 9;
 
-    // 779-2 is the offset for IC without taking into account of the size
-    // changes as the result of additional text and graphics segments.
-    // 839-2 is the offset if IGOLO exist.
-
-    VSIFSeekL( fpVSIL, 779 -2 + nAdditionalOffset , SEEK_SET );
+    /* Read ICORDS */
+    VSIFSeekL( fpVSIL, 775 + nAdditionalOffset , SEEK_SET );
+    char chICORDS;
+    VSIFReadL( &chICORDS, 1, 1, fpVSIL );
+    if (chICORDS != ' ')
+        VSIFSeekL( fpVSIL, 60, SEEK_CUR); /* skip IGEOLO */
+
+    /* Read NICOM */
+    char achNICOM[2];
+    VSIFReadL( achNICOM, 1, 1, fpVSIL );
+    achNICOM[1] = 0;
+    int nNICOM = atoi(achNICOM);
+    VSIFSeekL( fpVSIL, nNICOM * 80, SEEK_CUR); /* skip comments */
+
+    /* Read IC */
     VSIFReadL( szICBuf, 2, 1, fpVSIL );
-    if( !EQUALN(szICBuf,pszIC,2) )
-    {
-        VSIFSeekL( fpVSIL, 839 -2 + nAdditionalOffset, SEEK_SET );
-        VSIFReadL( szICBuf, 2, 1, fpVSIL );
-    }
-    
+
     /* The following line works around a "feature" of *BSD libc (at least PC-BSD 7.1) */
     /* that makes the position of the file offset unreliable when executing a */
     /* "seek, read and write" sequence. After the read(), the file offset seen by */
@@ -5209,13 +5214,13 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
     nOffset ++;
 
     /* Number of image blocks per row */
-    nUInt16 = nNBPR;
+    nUInt16 = (GUInt16) nNBPR;
     CPL_MSBPTR16(&nUInt16);
     memcpy(abyAPP6 + nOffset, &nUInt16, sizeof(nUInt16));
     nOffset += sizeof(nUInt16);
 
     /* Number of image blocks per column */
-    nUInt16 = nNBPC;
+    nUInt16 = (GUInt16) nNBPC;
     CPL_MSBPTR16(&nUInt16);
     memcpy(abyAPP6 + nOffset, &nUInt16, sizeof(nUInt16));
     nOffset += sizeof(nUInt16);
@@ -5484,6 +5489,8 @@ void GDALRegister_NITF()
 "       <Value>NSIF01.00</Value>"
 "   </Option>"
 "   <Option name='IREP' type='string' description='Set to RGB/LUT to reserve space for a color table for each output band. (Only needed for Create() method, not CreateCopy())'/>"
+"   <Option name='IREPBAND' type='string' description='Comma separated list of band IREPBANDs in band order'/>"
+"   <Option name='ISUBCAT' type='string' description='Comma separated list of band ISUBCATs in band order'/>" 
 "   <Option name='LUT_SIZE' type='integer' description='Set to control the size of pseudocolor tables for RGB/LUT bands' default='256'/>"
 "   <Option name='BLOCKXSIZE' type='int' description='Set the block width'/>"
 "   <Option name='BLOCKYSIZE' type='int' description='Set the block height'/>"
diff --git a/frmts/nitf/nitfdataset.h b/frmts/nitf/nitfdataset.h
new file mode 100644
index 0000000..6d3d343
--- /dev/null
+++ b/frmts/nitf/nitfdataset.h
@@ -0,0 +1,342 @@
+/******************************************************************************
+ * $Id: nitfdataset.h 22840 2011-07-30 21:33:22Z rouault $
+ *
+ * Project:  NITF Read/Write Translator
+ * Purpose:  GDALDataset/GDALRasterBand declarations.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam
+ *
+ * Portions Copyright (c) Her majesty the Queen in right of Canada as
+ * represented by the Minister of National Defence, 2006.
+ *
+ * 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_pam.h"
+#include "nitflib.h"
+#include "ogr_spatialref.h"
+#include "gdal_proxy.h"
+#include <map>
+
+CPLErr NITFSetColorInterpretation( NITFImage *psImage, 
+                                   int nBand,
+                                   GDALColorInterp eInterp );
+
+/* Unused in normal builds. Caller code in nitfdataset.cpp is protected by #ifdef ESRI_BUILD */
+#ifdef ESRI_BUILD
+/* -------------------------------------------------------------------- */
+/*      Functions in nitf_gcprpc.cpp.                                   */
+/* -------------------------------------------------------------------- */
+
+void NITFDensifyGCPs( GDAL_GCP **psGCPs, int *pnGCPCount );
+void NITFUpdateGCPsWithRPC( NITFRPC00BInfo *psRPCInfo,
+                            GDAL_GCP       *psGCPs,
+                            int            *pnGCPCount );
+#endif
+
+/************************************************************************/
+/* ==================================================================== */
+/*				NITFDataset				*/
+/* ==================================================================== */
+/************************************************************************/
+
+class NITFRasterBand;
+class NITFWrapperRasterBand;
+
+class NITFDataset : public GDALPamDataset
+{
+    friend class NITFRasterBand;
+    friend class NITFWrapperRasterBand;
+
+    NITFFile    *psFile;
+    NITFImage   *psImage;
+
+    GDALPamDataset *poJ2KDataset;
+    int         bJP2Writing;
+
+    GDALPamDataset *poJPEGDataset;
+
+    int         bGotGeoTransform;
+    double      adfGeoTransform[6];
+
+    char        *pszProjection;
+
+    int         nGCPCount;
+    GDAL_GCP    *pasGCPList;
+    char        *pszGCPProjection;
+
+    GDALMultiDomainMetadata oSpecialMD;
+
+#ifdef ESRI_BUILD
+    void         InitializeNITFDESMetadata();
+    void         InitializeNITFDESs();
+    void         InitializeNITFTREs();
+#endif
+    void         InitializeNITFMetadata();
+    void         InitializeCGMMetadata();
+    void         InitializeTextMetadata();
+    void         InitializeTREMetadata();
+
+    GIntBig     *panJPEGBlockOffset;
+    GByte       *pabyJPEGBlock;
+    int          nQLevel;
+
+    int          ScanJPEGQLevel( GUIntBig *pnDataStart );
+    CPLErr       ScanJPEGBlocks( void );
+    CPLErr       ReadJPEGBlock( int, int );
+    void         CheckGeoSDEInfo();
+    char**       AddFile(char **papszFileList, const char* EXTENSION, const char* extension);
+
+    int          nIMIndex;
+    CPLString    osNITFFilename;
+
+    CPLString    osRSetVRT;
+    int          CheckForRSets( const char *pszFilename );
+
+    char       **papszTextMDToWrite;
+    char       **papszCgmMDToWrite;
+    
+    int          bInLoadXML;
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
+  public:
+                 NITFDataset();
+                 ~NITFDataset();
+
+    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
+                               int nBufXSize, int nBufYSize, 
+                               GDALDataType eDT, 
+                               int nBandCount, int *panBandList,
+                               char **papszOptions );
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              int, int *, int, int, int );
+
+    virtual const char *GetProjectionRef(void);
+    virtual CPLErr SetProjection( const char * );
+    virtual CPLErr GetGeoTransform( double * );
+    virtual CPLErr SetGeoTransform( double * );
+
+    virtual int    GetGCPCount();
+    virtual const char *GetGCPProjection();
+    virtual const GDAL_GCP *GetGCPs();
+    virtual char **GetFileList(void);
+
+    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain = "" );
+    virtual void   FlushCache();
+    virtual CPLErr IBuildOverviews( const char *, int, int *,
+                                    int, int *, GDALProgressFunc, void * );
+
+    static int          Identify( GDALOpenInfo * );
+    static GDALDataset *OpenInternal( GDALOpenInfo *, GDALDataset *poWritableJ2KDataset,
+                              int bOpenForCreate);
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *
+    NITFCreateCopy( const char *pszFilename, GDALDataset *poSrcDS,
+                    int bStrict, char **papszOptions, 
+                    GDALProgressFunc pfnProgress, void * pProgressData );
+    static GDALDataset *
+             NITFDatasetCreate( const char *pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char **papszOptions );
+
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            NITFRasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class NITFRasterBand : public GDALPamRasterBand
+{
+    friend class NITFDataset;
+
+    NITFImage   *psImage;
+
+    GDALColorTable *poColorTable;
+
+    GByte       *pUnpackData;
+
+    int          bScanlineAccess;
+
+  public:
+                   NITFRasterBand( NITFDataset *, int );
+                  ~NITFRasterBand();
+
+    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IWriteBlock( int, int, void * );
+
+    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr SetColorInterpretation( GDALColorInterp );
+    virtual GDALColorTable *GetColorTable();
+    virtual CPLErr SetColorTable( GDALColorTable * ); 
+    virtual double GetNoDataValue( int *pbSuccess = NULL );
+
+    void Unpack(GByte* pData);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        NITFProxyPamRasterBand                        */
+/* ==================================================================== */
+/************************************************************************/
+
+/* This class is potentially of general interest and could be moved to gdal_proxy.h */
+/* We don't proxy all methods. Generally speaking, the getters go to PAM first and */
+/* then to the underlying band if no value exist in PAM. The setters aren't */
+/* overriden, so they go to PAM */
+
+class NITFProxyPamRasterBand : public GDALPamRasterBand
+{
+    private:
+        std::map<CPLString, char**> oMDMap;
+
+    protected:
+        virtual GDALRasterBand* RefUnderlyingRasterBand() = 0;
+        virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand);
+
+        virtual CPLErr IReadBlock( int, int, void * );
+        virtual CPLErr IWriteBlock( int, int, void * );
+        virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                                void *, int, int, GDALDataType,
+                                int, int );
+
+    public:
+                         ~NITFProxyPamRasterBand();
+
+        virtual char      **GetMetadata( const char * pszDomain = ""  );
+        /*virtual CPLErr      SetMetadata( char ** papszMetadata,
+                                        const char * pszDomain = ""  );*/
+        virtual const char *GetMetadataItem( const char * pszName,
+                                            const char * pszDomain = "" );
+        /*virtual CPLErr      SetMetadataItem( const char * pszName,
+                                            const char * pszValue,
+                                            const char * pszDomain = "" );*/
+        virtual CPLErr FlushCache();
+        /*virtual char **GetCategoryNames();*/
+        virtual double GetNoDataValue( int *pbSuccess = NULL );
+        virtual double GetMinimum( int *pbSuccess = NULL );
+        virtual double GetMaximum(int *pbSuccess = NULL );
+        /*virtual double GetOffset( int *pbSuccess = NULL );
+        virtual double GetScale( int *pbSuccess = NULL );*/
+        /*virtual const char *GetUnitType();*/
+        virtual GDALColorInterp GetColorInterpretation();
+        virtual GDALColorTable *GetColorTable();
+        virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0);
+
+        /*
+        virtual CPLErr SetCategoryNames( char ** );
+        virtual CPLErr SetNoDataValue( double );
+        virtual CPLErr SetColorTable( GDALColorTable * );
+        virtual CPLErr SetColorInterpretation( GDALColorInterp );
+        virtual CPLErr SetOffset( double );
+        virtual CPLErr SetScale( double );
+        virtual CPLErr SetUnitType( const char * );
+        */
+
+        virtual CPLErr GetStatistics( int bApproxOK, int bForce,
+                                    double *pdfMin, double *pdfMax,
+                                    double *pdfMean, double *padfStdDev );
+        virtual CPLErr ComputeStatistics( int bApproxOK,
+                                        double *pdfMin, double *pdfMax,
+                                        double *pdfMean, double *pdfStdDev,
+                                        GDALProgressFunc, void *pProgressData );
+        /*virtual CPLErr SetStatistics( double dfMin, double dfMax,
+                                    double dfMean, double dfStdDev );*/
+        virtual CPLErr ComputeRasterMinMax( int, double* );
+
+        virtual int HasArbitraryOverviews();
+        virtual int GetOverviewCount();
+        virtual GDALRasterBand *GetOverview(int);
+        virtual GDALRasterBand *GetRasterSampleOverview( int );
+        virtual CPLErr BuildOverviews( const char *, int, int *,
+                                    GDALProgressFunc, void * );
+
+        virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
+                                int nBufXSize, int nBufYSize,
+                                GDALDataType eDT, char **papszOptions );
+
+        /*virtual CPLErr  GetHistogram( double dfMin, double dfMax,
+                            int nBuckets, int * panHistogram,
+                            int bIncludeOutOfRange, int bApproxOK,
+                            GDALProgressFunc, void *pProgressData );
+
+        virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                            int *pnBuckets, int ** ppanHistogram,
+                                            int bForce,
+                                            GDALProgressFunc, void *pProgressData);
+        virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
+                                            int nBuckets, int *panHistogram );*/
+
+        /*virtual const GDALRasterAttributeTable *GetDefaultRAT();
+        virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );*/
+
+        virtual GDALRasterBand *GetMaskBand();
+        virtual int             GetMaskFlags();
+        virtual CPLErr          CreateMaskBand( int nFlags );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                       NITFWrapperRasterBand                          */
+/* ==================================================================== */
+/************************************************************************/
+
+/* This class is used to wrap bands from JPEG or JPEG2000 datasets in */
+/* bands of the NITF dataset. Previously a trick was applied in the */
+/* relevant drivers to define a SetColorInterpretation() method and */
+/* to make sure they keep the proper pointer to their "natural" dataset */
+/* This trick is no longer necessary with the NITFWrapperRasterBand */
+/* We just override the few specific methods where we want that */
+/* the NITFWrapperRasterBand behaviour differs from the JPEG/JPEG2000 one */
+
+class NITFWrapperRasterBand : public NITFProxyPamRasterBand
+{
+  GDALRasterBand* poBaseBand;
+  GDALColorTable* poColorTable;
+  GDALColorInterp eInterp;
+
+  protected:
+    /* Pure virtual method of the NITFProxyPamRasterBand */
+    virtual GDALRasterBand* RefUnderlyingRasterBand();
+
+  public:
+                   NITFWrapperRasterBand( NITFDataset * poDS,
+                                          GDALRasterBand* poBaseBand,
+                                          int nBand);
+                  ~NITFWrapperRasterBand();
+    
+    /* Methods from GDALRasterBand we want to override */
+    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr          SetColorInterpretation( GDALColorInterp );
+    
+    virtual GDALColorTable *GetColorTable();
+
+    /* Specific method */
+    void                    SetColorTableFromNITFBandInfo(); 
+};
+
diff --git a/frmts/nitf/nitfdes.c b/frmts/nitf/nitfdes.c
index 28740d1..489d30b 100644
--- a/frmts/nitf/nitfdes.c
+++ b/frmts/nitf/nitfdes.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdes.c 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: nitfdes.c 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for implementation of DE segments.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfdes.c 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: nitfdes.c 23033 2011-09-03 18:46:11Z rouault $");
 
 /************************************************************************/
 /*                          NITFDESAccess()                             */
@@ -46,7 +46,6 @@ NITFDES *NITFDESAccess( NITFFile *psFile, int iSegment )
     char      *pachHeader;
     NITFSegmentInfo *psSegInfo;
     char       szDESID[26];
-    char       szTemp[128];
     int        nOffset;
     int        bHasDESOFLW;
     int        nDESSHL;
@@ -189,8 +188,8 @@ retry:
         return NULL;
     }
 
-    nDESSHL = atoi(NITFGetField( szTemp, pachHeader, nOffset, 4));
-    nOffset += 4;
+    GetMD( 4, DESSHL );
+    nDESSHL = atoi(CSLFetchNameValue( psDES->papszMetadata, "NITF_DESSHL" ) );
 
     if (nDESSHL < 0)
     {
@@ -228,6 +227,40 @@ retry:
         GetMD(  3, SHAPE3_NAME );
         GetMD(  6, SHAPE3_START );
     }
+    else if (EQUALN(szDESID, "XML_DATA_CONTENT", strlen("XML_DATA_CONTENT")))
+    {
+        /* TODO : handle nDESSHL = 0005 and 0283 */
+        if (nDESSHL >= 5)
+        {
+            GetMD( 5, DESCRC );
+            if (nDESSHL >= 283)
+            {
+                GetMD( 8, DESSHFT );
+                GetMD( 20, DESSHDT );
+                GetMD( 40, DESSHRP );
+                GetMD( 60, DESSHSI );
+                GetMD( 10, DESSHSV );
+                GetMD( 20, DESSHSD );
+                GetMD( 120, DESSHTN );
+                if (nDESSHL >= 773)
+                {
+                    GetMD( 125, DESSHLPG );
+                    GetMD( 25, DESSHLPT );
+                    GetMD( 20, DESSHLI );
+                    GetMD( 120, DESSHLIN );
+                    GetMD( 200, DESSHABS );
+                }
+            }
+        }
+    }
+    else if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")) && nDESSHL == 52)
+    {
+        GetMD( 12, ATT_TYPE );
+        GetMD( 14, DT_ATT );
+        GetMD( 8, DATE_ATT );
+        GetMD( 13, T0_ATT );
+        GetMD( 5, NUM_ATT );
+    }
     else if (nDESSHL > 0)
         GetMD(  nDESSHL, DESSHF );
 
@@ -242,6 +275,72 @@ retry:
                                                 pszEscapedDESDATA );
         CPLFree(pszEscapedDESDATA);
     }
+    else
+    {
+        char* pachData = (char*)VSIMalloc((size_t)psSegInfo->nSegmentSize);
+        if (pachData == NULL )
+        {
+            CPLDebug("NITF", "Cannot allocate " CPL_FRMT_GUIB " bytes DES data",
+                     psSegInfo->nSegmentSize);
+        }
+        else if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart,
+                    SEEK_SET ) != 0
+            || VSIFReadL( pachData, 1, (size_t)psSegInfo->nSegmentSize,
+                        psFile->fp ) != psSegInfo->nSegmentSize )
+        {
+            CPLDebug("NITF",
+                    "Failed to read " CPL_FRMT_GUIB" bytes DES data from " CPL_FRMT_GUIB ".",
+                    psSegInfo->nSegmentSize,
+                    psSegInfo->nSegmentStart );
+        }
+        else
+        {
+            char* pszEscapedDESDATA =
+                    CPLEscapeString( pachData,
+                                    (int)psSegInfo->nSegmentSize,
+                                    CPLES_BackslashQuotable );
+            psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
+                                                    "NITF_DESDATA",
+                                                    pszEscapedDESDATA );
+            CPLFree(pszEscapedDESDATA);
+        }
+
+#ifdef notdef
+        /* Disabled because might generate a huge amount of elements */
+        if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")))
+        {
+            int nNumAtt = atoi(CSLFetchNameValueDef(psDES->papszMetadata, "NITF_NUM_ATT", "0"));
+            if (nNumAtt * 8 * 4 == psSegInfo->nSegmentSize)
+            {
+                int nMDSize = CSLCount(psDES->papszMetadata);
+                char** papszMD = (char**)VSIRealloc(psDES->papszMetadata, (nMDSize + nNumAtt * 4 + 1) * sizeof(char*));
+                if (papszMD)
+                {
+                    int i, j;
+                    const GByte* pachDataIter = pachData;
+
+                    psDES->papszMetadata = papszMD;
+                    for(i=0;i<nNumAtt;i++)
+                    {
+                        char szAttrNameValue[64+1+256+1];
+                        double dfVal;
+                        for(j=0;j<4;j++)
+                        {
+                            memcpy(&dfVal, pachDataIter, 8);
+                            CPL_MSBPTR64(&dfVal);
+                            pachDataIter += 8;
+                            sprintf(szAttrNameValue, "NITF_ATT_Q%d_%d=%.16g", j+1, i, dfVal);
+                            papszMD[nMDSize + i * 4 + j] = CPLStrdup(szAttrNameValue);
+                        }
+                    }
+                    papszMD[nMDSize + nNumAtt * 4] = NULL;
+                }
+            }
+        }
+#endif
+
+        CPLFree(pachData);
+    }
 
     return psDES;
 }
diff --git a/frmts/nitf/nitffile.c b/frmts/nitf/nitffile.c
index ba8826e..0989d24 100644
--- a/frmts/nitf/nitffile.c
+++ b/frmts/nitf/nitffile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitffile.c 21305 2010-12-22 17:22:53Z rouault $
+ * $Id: nitffile.c 23492 2011-12-07 20:50:52Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for opening NITF file, populating NITFFile
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitffile.c 21305 2010-12-22 17:22:53Z rouault $");
+CPL_CVSID("$Id: nitffile.c 23492 2011-12-07 20:50:52Z rouault $");
 
 static int NITFWriteBLOCKA( VSILFILE* fp, vsi_l_offset nOffsetUDIDL,
                             vsi_l_offset nOffsetTRE, 
@@ -466,6 +466,10 @@ void NITFClose( NITFFile *psFile )
     CPLFree( psFile->pachHeader );
     CSLDestroy( psFile->papszMetadata );
     CPLFree( psFile->pachTRE );
+
+    if (psFile->psNITFSpecNode)
+        CPLDestroyXMLNode(psFile->psNITFSpecNode);
+
     CPLFree( psFile );
 }
 
@@ -623,6 +627,50 @@ int NITFCreate( const char *pszFilename,
             * ((GIntBig) nPixels *nLines)
             * nBands;
     }
+    else if (EQUAL(pszIC, "NC") &&
+             nPixels > 8192 && nNPPBH == nPixels)
+    {
+        /* See MIL-STD-2500-C, paragraph 5.4.2.2-d */
+        nNBPR = 1;
+        nNPPBH = 0;
+        nNBPC = (nLines + nNPPBV - 1) / nNPPBV;
+
+        if ( nNBPC > 9999 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to create file %s,\n"
+                      "Too many blocks : %d x %d",
+                     pszFilename, nNBPR, nNBPC);
+            return FALSE;
+        }
+
+        nImageSize =
+            ((nBitsPerSample)/8)
+            * ((GIntBig) nPixels * (nNBPC * nNPPBV))
+            * nBands;
+    }
+    else if (EQUAL(pszIC, "NC") &&
+             nLines > 8192 && nNPPBV == nLines)
+    {
+        /* See MIL-STD-2500-C, paragraph 5.4.2.2-d */
+        nNBPC = 1;
+        nNPPBV = 0;
+        nNBPR = (nPixels + nNPPBH - 1) / nNPPBH;
+
+        if ( nNBPR > 9999 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to create file %s,\n"
+                      "Too many blocks : %d x %d",
+                     pszFilename, nNBPR, nNBPC);
+            return FALSE;
+        }
+
+        nImageSize =
+            ((nBitsPerSample)/8)
+            * ((GIntBig) nLines * (nNBPR * nNPPBH))
+            * nBands;
+    }
     else
     {
         if( nNPPBH <= 0 || nNPPBV <= 0 ||
@@ -823,6 +871,30 @@ int NITFCreate( const char *pszFilename,
 /* -------------------------------------------------------------------- */
   for(iIM=0;iIM<nIM;iIM++)
   {
+    char** papszIREPBANDTokens = NULL;
+    char** papszISUBCATTokens = NULL;
+
+    if( CSLFetchNameValue(papszOptions,"IREPBAND") != NULL )
+    {
+        papszIREPBANDTokens = CSLTokenizeStringComplex(
+            CSLFetchNameValue(papszOptions,"IREPBAND"), ",", 0, 0 );
+        if( papszIREPBANDTokens != NULL && CSLCount( papszIREPBANDTokens ) != nBands)
+        {
+            CSLDestroy(  papszIREPBANDTokens );
+            papszIREPBANDTokens = NULL;
+        }
+    }
+    if( CSLFetchNameValue(papszOptions,"ISUBCAT") != NULL )
+    {
+        papszISUBCATTokens = CSLTokenizeStringComplex(
+            CSLFetchNameValue(papszOptions,"ISUBCAT"), ",", 0, 0 );
+        if( papszISUBCATTokens != NULL && CSLCount( papszISUBCATTokens ) != nBands)
+        {
+            CSLDestroy( papszISUBCATTokens );
+            papszISUBCATTokens = NULL;
+        }
+    }
+
     VSIFSeekL(fp, nCur, SEEK_SET);
 
     PLACE (nCur+  0, IM           , "IM"                           );
@@ -920,7 +992,18 @@ int NITFCreate( const char *pszFilename,
     {
         const char *pszIREPBAND = "M";
 
-        if( EQUAL(pszIREP,"RGB/LUT") )
+        if( papszIREPBANDTokens != NULL )
+        {
+            if (strlen(papszIREPBANDTokens[iBand]) > 2)
+            {
+                papszIREPBANDTokens[iBand][2] = '\0';
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Truncating IREPBAND[%d] to '%s'",
+                         iBand + 1, papszIREPBANDTokens[iBand]);
+            }
+            pszIREPBAND = papszIREPBANDTokens[iBand];
+        }
+        else if( EQUAL(pszIREP,"RGB/LUT") )
             pszIREPBAND = "LU";
         else if( EQUAL(pszIREP,"RGB") )
         {
@@ -942,7 +1025,21 @@ int NITFCreate( const char *pszFilename,
         }
 
         PLACE(nCur+nOffset+ 0, IREPBANDn, pszIREPBAND                 );
-//      PLACE(nCur+nOffset+ 2, ISUBCATn, ""                           );
+
+        if( papszISUBCATTokens != NULL )
+        {
+            if (strlen(papszISUBCATTokens[iBand]) > 6)
+            {
+                papszISUBCATTokens[iBand][6] = '\0';
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Truncating ISUBCAT[%d] to '%s'",
+                         iBand + 1, papszISUBCATTokens[iBand]);
+            }
+            PLACE(nCur+nOffset+ 2, ISUBCATn, papszISUBCATTokens[iBand] );
+        }
+//      else
+//          PLACE(nCur+nOffset+ 2, ISUBCATn, ""                           );
+
         PLACE(nCur+nOffset+ 8, IFCn  , "N"                            );
 //      PLACE(nCur+nOffset+ 9, IMFLTn, ""                             );
 
@@ -977,6 +1074,9 @@ int NITFCreate( const char *pszFilename,
         }
     }
 
+    CSLDestroy(papszIREPBANDTokens);
+    CSLDestroy(papszISUBCATTokens);
+
 /* -------------------------------------------------------------------- */
 /*      Remainder of image header info.                                 */
 /* -------------------------------------------------------------------- */
@@ -1201,7 +1301,7 @@ static int NITFWriteTREsFromOptions(
         }
         
         pszTREName = CPLStrdup(papszOptions[iOption]+nTREPrefixLen);
-        pszTREName[pszSpace - (papszOptions[iOption]+nTREPrefixLen)] = '\0';
+        pszTREName[MIN(6, pszSpace - (papszOptions[iOption]+nTREPrefixLen))] = '\0';
         pszEscapedContents = pszSpace + 1;
 
         pszUnescapedContents = 
@@ -1872,3 +1972,778 @@ int NITFReconcileAttachments( NITFFile *psFile )
     else
         return NITFReconcileAttachments( psFile );
 }
+
+/************************************************************************/
+/*                        NITFFindValFromEnd()                          */
+/************************************************************************/
+
+static const char* NITFFindValFromEnd(char** papszMD,
+                                      int nMDSize,
+                                      const char* pszVar,
+                                      const char* pszDefault)
+{
+    int nVarLen = strlen(pszVar);
+    int nIter = nMDSize-1;
+    for(;nIter >= 0;nIter--)
+    {
+        if (strncmp(papszMD[nIter], pszVar, nVarLen) == 0 &&
+            papszMD[nIter][nVarLen] == '=')
+            return papszMD[nIter] + nVarLen + 1;
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                  NITFGenericMetadataReadTREInternal()                */
+/************************************************************************/
+
+static char** NITFGenericMetadataReadTREInternal(char **papszMD,
+                                                 int* pnMDSize,
+                                                 int* pnMDAlloc,
+                                                 CPLXMLNode* psOutXMLNode,
+                                                 const char* pszTREName,
+                                                 const char *pachTRE,
+                                                 int nTRESize,
+                                                 CPLXMLNode* psTreNode,
+                                                 int *pnTreOffset,
+                                                 const char* pszMDPrefix,
+                                                 int *pbError)
+{
+    CPLXMLNode* psIter;
+    for(psIter = psTreNode->psChild;
+        psIter != NULL && *pbError == FALSE;
+        psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element &&
+            psIter->pszValue != NULL &&
+            strcmp(psIter->pszValue, "field") == 0)
+        {
+            const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
+            const char* pszLongName = CPLGetXMLValue(psIter, "longname", NULL);
+            const char* pszLength = CPLGetXMLValue(psIter, "length", NULL);
+            int nLength = -1;
+            if (pszLength != NULL)
+                nLength = atoi(pszLength);
+            else
+            {
+                const char* pszLengthVar = CPLGetXMLValue(psIter, "length_var", NULL);
+                if (pszLengthVar != NULL)
+                {
+                    char** papszMDIter = papszMD;
+                    while(papszMDIter != NULL && *papszMDIter != NULL)
+                    {
+                        if (strstr(*papszMDIter, pszLengthVar) != NULL)
+                        {
+                            const char* pszEqual = strchr(*papszMDIter, '=');
+                            if (pszEqual != NULL)
+                            {
+                                nLength = atoi(pszEqual + 1);
+                                break;
+                            }
+                        }
+                        papszMDIter ++;
+                    }
+                }
+            }
+            if (pszName != NULL && nLength > 0)
+            {
+                char* pszMDItemName;
+                char** papszTmp = NULL;
+
+                if (*pnTreOffset + nLength > nTRESize)
+                {
+                    *pbError = TRUE;
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "Not enough bytes when reading %s TRE "
+                              "(at least %d needed, only %d available)",
+                              pszTREName, *pnTreOffset + nLength, nTRESize );
+                    break;
+                }
+
+                pszMDItemName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, pszName));
+
+                NITFExtractMetadata( &papszTmp, pachTRE, *pnTreOffset,
+                                     nLength, pszMDItemName );
+                if (*pnMDSize + 1 >= *pnMDAlloc)
+                {
+                    *pnMDAlloc = (*pnMDAlloc * 4 / 3) + 32;
+                    papszMD = (char**)CPLRealloc(papszMD, *pnMDAlloc * sizeof(char**));
+                }
+                papszMD[*pnMDSize] = papszTmp[0];
+                papszMD[(*pnMDSize) + 1] = NULL;
+                (*pnMDSize) ++;
+                papszTmp[0] = NULL;
+                CPLFree(papszTmp);
+
+                if (psOutXMLNode != NULL)
+                {
+                    const char* pszVal = strchr(papszMD[(*pnMDSize) - 1], '=') + 1;
+                    CPLXMLNode* psFieldNode;
+                    CPLXMLNode* psNameNode;
+                    CPLXMLNode* psValueNode;
+
+                    CPLAssert(pszVal != NULL);
+                    psFieldNode =
+                        CPLCreateXMLNode(psOutXMLNode, CXT_Element, "field");
+                    psNameNode =
+                        CPLCreateXMLNode(psFieldNode, CXT_Attribute, "name");
+                    psValueNode =
+                        CPLCreateXMLNode(psFieldNode, CXT_Attribute, "value");
+                    CPLCreateXMLNode(psNameNode, CXT_Text,
+                       (pszName[0] || pszLongName == NULL) ? pszName : pszLongName);
+                    CPLCreateXMLNode(psValueNode, CXT_Text, pszVal);
+                }
+
+                CPLFree(pszMDItemName);
+
+                *pnTreOffset += nLength;
+            }
+            else if (nLength > 0)
+            {
+                *pnTreOffset += nLength;
+            }
+            else
+            {
+                *pbError = TRUE;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Invalid item construct in %s TRE in XML ressource",
+                          pszTREName );
+                break;
+            }
+        }
+        else if (psIter->eType == CXT_Element &&
+                 psIter->pszValue != NULL &&
+                 strcmp(psIter->pszValue, "loop") == 0)
+        {
+            const char* pszCounter = CPLGetXMLValue(psIter, "counter", NULL);
+            const char* pszIterations = CPLGetXMLValue(psIter, "iterations", NULL);
+            const char* pszFormula = CPLGetXMLValue(psIter, "formula", NULL);
+            const char* pszMDSubPrefix = CPLGetXMLValue(psIter, "md_prefix", NULL);
+            int nIterations = -1;
+
+            if (pszCounter != NULL)
+            {
+                char* pszMDItemName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, pszCounter));
+                nIterations = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
+                CPLFree(pszMDItemName);
+                if (nIterations < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, pszCounter );
+                    *pbError = TRUE;
+                    break;
+                }
+            }
+            else if (pszIterations != NULL)
+            {
+                nIterations = atoi(pszIterations);
+            }
+            else if (pszFormula != NULL &&
+                     strcmp(pszFormula, "(NPART+1)*(NPART)/2") == 0)
+            {
+                char* pszMDItemName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "NPART"));
+                int NPART = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
+                CPLFree(pszMDItemName);
+                if (NPART < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, "NPART" );
+                    *pbError = TRUE;
+                    break;
+                }
+                nIterations = NPART * (NPART + 1) / 2;
+            }
+            else if (pszFormula != NULL &&
+                     strcmp(pszFormula, "(NUMOPG+1)*(NUMOPG)/2") == 0)
+            {
+                char* pszMDItemName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "NUMOPG"));
+                int NUMOPG = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
+                CPLFree(pszMDItemName);
+                if (NUMOPG < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, "NUMOPG" );
+                    *pbError = TRUE;
+                    break;
+                }
+                nIterations = NUMOPG * (NUMOPG + 1) / 2;
+            }
+            else if (pszFormula != NULL &&
+                     strcmp(pszFormula, "NPAR*NPARO") == 0)
+            {
+                char* pszMDNPARName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "NPAR"));
+                int NPAR = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPARName, "-1"));
+                char* pszMDNPAROName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "NPARO"));
+                int NPARO= atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPAROName, "-1"));
+                CPLFree(pszMDNPARName);
+                CPLFree(pszMDNPAROName);
+                if (NPAR < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, "NPAR" );
+                    *pbError = TRUE;
+                    break;
+                }
+                if (NPARO < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, "NPAR0" );
+                    *pbError = TRUE;
+                    break;
+                }
+                nIterations = NPAR*NPARO;
+            }
+            else if (pszFormula != NULL &&
+                     strcmp(pszFormula, "NPLN-1") == 0)
+            {
+                char* pszMDItemName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "NPLN"));
+                int NPLN = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, "-1"));
+                CPLFree(pszMDItemName);
+                if (NPLN < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, "NPLN" );
+                    *pbError = TRUE;
+                    break;
+                }
+                nIterations = NPLN-1;
+            }
+            else if (pszFormula != NULL &&
+                     strcmp(pszFormula, "NXPTS*NYPTS") == 0)
+            {
+                char* pszMDNPARName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "NXPTS"));
+                int NXPTS = atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPARName, "-1"));
+                char* pszMDNPAROName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "NYPTS"));
+                int NYPTS= atoi(NITFFindValFromEnd(papszMD, *pnMDSize, pszMDNPAROName, "-1"));
+                CPLFree(pszMDNPARName);
+                CPLFree(pszMDNPAROName);
+                if (NXPTS < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, "NXPTS" );
+                    *pbError = TRUE;
+                    break;
+                }
+                if (NYPTS < 0)
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Invalid loop construct in %s TRE in XML ressource : "
+                            "invalid 'counter' %s",
+                            pszTREName, "NYPTS" );
+                    *pbError = TRUE;
+                    break;
+                }
+                nIterations = NXPTS*NYPTS;
+            }
+            else
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Invalid loop construct in %s TRE in XML ressource : "
+                          "missing or invalid 'counter' or 'iterations' or 'formula'",
+                          pszTREName );
+                *pbError = TRUE;
+                break;
+            }
+
+            if (nIterations > 0)
+            {
+                int iIter;
+                const char* pszPercent;
+                int bHasValidPercentD = FALSE;
+                CPLXMLNode* psRepeatedNode = NULL;
+                CPLXMLNode* psLastChild = NULL;
+
+                /* Check that md_prefix has one and only %XXXXd pattern */
+                if (pszMDSubPrefix != NULL &&
+                    (pszPercent = strchr(pszMDSubPrefix, '%')) != NULL &&
+                    strchr(pszPercent+1,'%') == NULL)
+                {
+                    const char* pszIter = pszPercent + 1;
+                    while(*pszIter != '\0')
+                    {
+                        if (*pszIter >= '0' && *pszIter <= '9')
+                            pszIter ++;
+                        else if (*pszIter == 'd')
+                        {
+                            bHasValidPercentD = atoi(pszPercent + 1) <= 10;
+                            break;
+                        }
+                        else
+                            break;
+                    }
+                }
+
+                if (psOutXMLNode != NULL)
+                {
+                    CPLXMLNode* psNumberNode;
+                    CPLXMLNode* psNameNode;
+                    const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
+                    psRepeatedNode = CPLCreateXMLNode(psOutXMLNode, CXT_Element, "repeated");
+                    if (pszName)
+                    {
+                        psNameNode = CPLCreateXMLNode(psRepeatedNode, CXT_Attribute, "name");
+                        CPLCreateXMLNode(psNameNode, CXT_Text, pszName);
+                    }
+                    psNumberNode = CPLCreateXMLNode(psRepeatedNode, CXT_Attribute, "number");
+                    CPLCreateXMLNode(psNumberNode, CXT_Text, CPLSPrintf("%d", nIterations));
+
+                    psLastChild = psRepeatedNode->psChild;
+                    while(psLastChild->psNext != NULL)
+                        psLastChild = psLastChild->psNext;
+                }
+
+                for(iIter = 0; iIter < nIterations && *pbError == FALSE; iIter++)
+                {
+                    char* pszMDNewPrefix = NULL;
+                    CPLXMLNode* psGroupNode = NULL;
+                    if (pszMDSubPrefix != NULL)
+                    {
+                        if (bHasValidPercentD)
+                        {
+                            char* szTmp = (char*)CPLMalloc(
+                                            strlen(pszMDSubPrefix) + 10 + 1);
+                            sprintf(szTmp, pszMDSubPrefix, iIter + 1);
+                            pszMDNewPrefix = CPLStrdup(CPLSPrintf("%s%s",
+                                                       pszMDPrefix, szTmp));
+                            CPLFree(szTmp);
+                        }
+                        else
+                            pszMDNewPrefix = CPLStrdup(CPLSPrintf("%s%s%04d_",
+                                      pszMDPrefix, pszMDSubPrefix, iIter + 1));
+                    }
+                    else
+                        pszMDNewPrefix = CPLStrdup(CPLSPrintf("%s%04d_",
+                                                   pszMDPrefix, iIter + 1));
+
+                    if (psRepeatedNode != NULL)
+                    {
+                        CPLXMLNode* psIndexNode;
+                        psGroupNode = CPLCreateXMLNode(NULL, CXT_Element, "group");
+                        CPLAssert(psLastChild->psNext == NULL);
+                        psLastChild->psNext = psGroupNode;
+                        psLastChild = psGroupNode;
+                        psIndexNode = CPLCreateXMLNode(psGroupNode, CXT_Attribute, "index");
+                        CPLCreateXMLNode(psIndexNode, CXT_Text, CPLSPrintf("%d", iIter));
+                    }
+
+                    papszMD = NITFGenericMetadataReadTREInternal(papszMD,
+                                                                 pnMDSize,
+                                                                 pnMDAlloc,
+                                                                 psGroupNode,
+                                                                 pszTREName,
+                                                                 pachTRE,
+                                                                 nTRESize,
+                                                                 psIter,
+                                                                 pnTreOffset,
+                                                                 pszMDNewPrefix,
+                                                                 pbError);
+                    CPLFree(pszMDNewPrefix);
+                }
+            }
+        }
+        else if (psIter->eType == CXT_Element &&
+                 psIter->pszValue != NULL &&
+                 strcmp(psIter->pszValue, "if") == 0)
+        {
+            const char* pszCond = CPLGetXMLValue(psIter, "cond", NULL);
+            const char* pszEqual = NULL;
+            if (pszCond != NULL && strcmp(pszCond, "QSS!=U AND QOD!=Y") == 0)
+            {
+                char* pszQSSName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "QSS"));
+                char* pszQODName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, "QOD"));
+                const char* pszQSSVal = NITFFindValFromEnd(papszMD, *pnMDSize, pszQSSName, NULL);
+                const char* pszQODVal = NITFFindValFromEnd(papszMD, *pnMDSize, pszQODName, NULL);
+                if (pszQSSVal == NULL)
+                {
+                    CPLDebug("NITF", "Cannot find if cond variable %s", "QSS");
+                }
+                else if (pszQODVal == NULL)
+                {
+                    CPLDebug("NITF", "Cannot find if cond variable %s", "QOD");
+                }
+                else if (strcmp(pszQSSVal, "U") != 0 && strcmp(pszQODVal, "Y") != 0)
+                {
+                    papszMD = NITFGenericMetadataReadTREInternal(papszMD,
+                                                                 pnMDSize,
+                                                                 pnMDAlloc,
+                                                                 psOutXMLNode,
+                                                                 pszTREName,
+                                                                 pachTRE,
+                                                                 nTRESize,
+                                                                 psIter,
+                                                                 pnTreOffset,
+                                                                 pszMDPrefix,
+                                                                 pbError);
+                }
+                CPLFree(pszQSSName);
+                CPLFree(pszQODName);
+            }
+            else if (pszCond != NULL && (pszEqual = strchr(pszCond, '=')) != NULL)
+            {
+                char* pszCondVar = (char*)CPLMalloc(pszEqual - pszCond + 1);
+                const char* pszCondExpectedVal = pszEqual + 1;
+                char* pszMDItemName;
+                const char* pszCondVal;
+                int bTestEqual = TRUE;
+                memcpy(pszCondVar, pszCond, pszEqual - pszCond);
+                if (pszEqual - pszCond > 1 && pszCondVar[pszEqual - pszCond - 1] == '!')
+                {
+                    bTestEqual = FALSE;
+                    pszCondVar[pszEqual - pszCond - 1] = '\0';
+                }
+                pszCondVar[pszEqual - pszCond] = '\0';
+                pszMDItemName = CPLStrdup(
+                            CPLSPrintf("%s%s", pszMDPrefix, pszCondVar));
+                pszCondVal = NITFFindValFromEnd(papszMD, *pnMDSize, pszMDItemName, NULL);
+                if (pszCondVal == NULL)
+                {
+                    CPLDebug("NITF", "Cannot find if cond variable %s",
+                             pszMDItemName);
+                }
+                else if ((bTestEqual && strcmp(pszCondVal, pszCondExpectedVal) == 0) ||
+                         (!bTestEqual && strcmp(pszCondVal, pszCondExpectedVal) != 0))
+                {
+                    papszMD = NITFGenericMetadataReadTREInternal(papszMD,
+                                                                 pnMDSize,
+                                                                 pnMDAlloc,
+                                                                 psOutXMLNode,
+                                                                 pszTREName,
+                                                                 pachTRE,
+                                                                 nTRESize,
+                                                                 psIter,
+                                                                 pnTreOffset,
+                                                                 pszMDPrefix,
+                                                                 pbError);
+                }
+                CPLFree(pszMDItemName);
+                CPLFree(pszCondVar);
+            }
+            else
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Invalid if construct in %s TRE in XML ressource : "
+                          "missing or invalid 'cond' attribute",
+                          pszTREName );
+                *pbError = TRUE;
+                break;
+            }
+        }
+        else if (psIter->eType == CXT_Element &&
+                 psIter->pszValue != NULL &&
+                 strcmp(psIter->pszValue, "if_remaining_bytes") == 0)
+        {
+            if (*pnTreOffset < nTRESize)
+            {
+                papszMD = NITFGenericMetadataReadTREInternal(papszMD,
+                                                             pnMDSize,
+                                                             pnMDAlloc,
+                                                             psOutXMLNode,
+                                                             pszTREName,
+                                                             pachTRE,
+                                                             nTRESize,
+                                                             psIter,
+                                                             pnTreOffset,
+                                                             pszMDPrefix,
+                                                             pbError);
+        }
+        }
+        else
+        {
+            //CPLDebug("NITF", "Unknown element : %s", psIter->pszValue ? psIter->pszValue : "null");
+        }
+    }
+    return papszMD;
+}
+
+/************************************************************************/
+/*                      NITFGenericMetadataReadTRE()                    */
+/************************************************************************/
+
+static
+char **NITFGenericMetadataReadTRE(char **papszMD,
+                                  const char* pszTREName,
+                                  const char *pachTRE,
+                                  int nTRESize,
+                                  CPLXMLNode* psTreNode)
+{
+    int nTreLength, nTreMinLength = -1, nTreMaxLength = -1;
+    int bError = FALSE;
+    int nTreOffset = 0;
+    const char* pszMDPrefix;
+    int nMDSize, nMDAlloc;
+
+    nTreLength = atoi(CPLGetXMLValue(psTreNode, "length", "-1"));
+    nTreMinLength = atoi(CPLGetXMLValue(psTreNode, "minlength", "-1"));
+    nTreMaxLength = atoi(CPLGetXMLValue(psTreNode, "maxlength", "-1"));
+
+    if( (nTreLength > 0 && nTRESize != nTreLength) ||
+        (nTreMinLength > 0 && nTRESize < nTreMinLength) )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "%s TRE wrong size, ignoring.", pszTREName );
+        return papszMD;
+    }
+
+    pszMDPrefix = CPLGetXMLValue(psTreNode, "md_prefix", "");
+
+    nMDSize = nMDAlloc = CSLCount(papszMD);
+
+    papszMD = NITFGenericMetadataReadTREInternal(papszMD,
+                                                 &nMDSize,
+                                                 &nMDAlloc,
+                                                 NULL,
+                                                 pszTREName,
+                                                 pachTRE,
+                                                 nTRESize,
+                                                 psTreNode,
+                                                 &nTreOffset,
+                                                 pszMDPrefix,
+                                                 &bError);
+
+    if (bError == FALSE && nTreLength > 0 && nTreOffset != nTreLength)
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Inconsistant declaration of %s TRE",
+                  pszTREName );
+    }
+    if (nTreOffset < nTRESize)
+        CPLDebug("NITF", "%d remaining bytes at end of %s TRE",
+                 nTRESize -nTreOffset, pszTREName);
+
+    return papszMD;
+}
+
+
+/************************************************************************/
+/*                           NITFLoadXMLSpec()                          */
+/************************************************************************/
+
+#define NITF_SPEC_FILE "nitf_spec.xml"
+
+static CPLXMLNode* NITFLoadXMLSpec(NITFFile* psFile)
+{
+
+    if (psFile->psNITFSpecNode == NULL)
+    {
+        const char* pszXMLDescFilename = CPLFindFile("gdal", NITF_SPEC_FILE);
+        if (pszXMLDescFilename == NULL)
+        {
+            CPLDebug("NITF", "Cannot find XML file : %s", NITF_SPEC_FILE);
+            return NULL;
+        }
+        psFile->psNITFSpecNode = CPLParseXMLFile(pszXMLDescFilename);
+        if (psFile->psNITFSpecNode == NULL)
+        {
+            CPLDebug("NITF", "Invalid XML file : %s", pszXMLDescFilename);
+            return NULL;
+        }
+    }
+
+    return psFile->psNITFSpecNode;
+}
+
+/************************************************************************/
+/*                      NITFFindTREXMLDescFromName()                    */
+/************************************************************************/
+
+static CPLXMLNode* NITFFindTREXMLDescFromName(NITFFile* psFile,
+                                              const char* pszTREName)
+{
+    CPLXMLNode* psTreeNode;
+    CPLXMLNode* psTresNode;
+    CPLXMLNode* psIter;
+
+    psTreeNode = NITFLoadXMLSpec(psFile);
+    if (psTreeNode == NULL)
+        return NULL;
+
+    psTresNode = CPLGetXMLNode(psTreeNode, "=tres");
+    if (psTresNode == NULL)
+    {
+        CPLDebug("NITF", "Cannot find <tres> root element");
+        return NULL;
+    }
+
+    for(psIter = psTresNode->psChild;psIter != NULL;psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element &&
+            psIter->pszValue != NULL &&
+            strcmp(psIter->pszValue, "tre") == 0)
+        {
+            const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
+            if (pszName != NULL && strcmp(pszName, pszTREName) == 0)
+            {
+                return psIter;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                         NITFCreateXMLTre()                           */
+/************************************************************************/
+
+CPLXMLNode* NITFCreateXMLTre(NITFFile* psFile,
+                             const char* pszTREName,
+                             const char *pachTRE,
+                             int nTRESize)
+{
+    int nTreLength, nTreMinLength = -1, nTreMaxLength = -1;
+    int bError = FALSE;
+    int nTreOffset = 0;
+    CPLXMLNode* psTreNode;
+    CPLXMLNode* psOutXMLNode = NULL;
+    int nMDSize = 0, nMDAlloc = 0;
+
+    psTreNode = NITFFindTREXMLDescFromName(psFile, pszTREName);
+    if (psTreNode == NULL)
+    {
+        if (!(EQUALN(pszTREName, "RPF", 3) || strcmp(pszTREName, "XXXXXX") == 0))
+        {
+            CPLDebug("NITF", "Cannot find definition of TRE %s in %s",
+                    pszTREName, NITF_SPEC_FILE);
+        }
+        return NULL;
+    }
+
+    nTreLength = atoi(CPLGetXMLValue(psTreNode, "length", "-1"));
+    nTreMinLength = atoi(CPLGetXMLValue(psTreNode, "minlength", "-1"));
+    nTreMaxLength = atoi(CPLGetXMLValue(psTreNode, "maxlength", "-1"));
+
+    if( (nTreLength > 0 && nTRESize != nTreLength) ||
+        (nTreMinLength > 0 && nTRESize < nTreMinLength) )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "%s TRE wrong size, ignoring.", pszTREName );
+        return NULL;
+    }
+
+    psOutXMLNode = CPLCreateXMLNode(NULL, CXT_Element, "tre");
+    CPLCreateXMLNode(CPLCreateXMLNode(psOutXMLNode, CXT_Attribute, "name"),
+                     CXT_Text, pszTREName);
+
+    CSLDestroy(NITFGenericMetadataReadTREInternal(NULL,
+                                                  &nMDSize,
+                                                  &nMDAlloc,
+                                                  psOutXMLNode,
+                                                  pszTREName,
+                                                  pachTRE,
+                                                  nTRESize,
+                                                  psTreNode,
+                                                  &nTreOffset,
+                                                  "",
+                                                  &bError));
+
+    if (bError == FALSE && nTreLength > 0 && nTreOffset != nTreLength)
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Inconsistant declaration of %s TRE",
+                  pszTREName );
+    }
+    if (nTreOffset < nTRESize)
+        CPLDebug("NITF", "%d remaining bytes at end of %s TRE",
+                 nTRESize -nTreOffset, pszTREName);
+
+    return psOutXMLNode;
+}
+
+/************************************************************************/
+/*                        NITFGenericMetadataRead()                     */
+/*                                                                      */
+/* Add metadata from TREs of file and image objects in the papszMD list */
+/* pszSpecificTRE can be NULL, in which case all TREs listed in         */
+/* data/nitf_resources.xml that have md_prefix defined will be looked   */
+/* for. If not NULL, only the specified one will be looked for.         */
+/************************************************************************/
+
+char **NITFGenericMetadataRead( char **papszMD,
+                                NITFFile* psFile,
+                                NITFImage *psImage,
+                                const char* pszSpecificTREName)
+{
+    CPLXMLNode* psTreeNode = NULL;
+    CPLXMLNode* psTresNode = NULL;
+    CPLXMLNode* psIter = NULL;
+
+    if (psFile == NULL && psImage == NULL)
+        return papszMD;
+
+    psTreeNode = NITFLoadXMLSpec(psFile ? psFile : psImage->psFile);
+    if (psTreeNode == NULL)
+        return papszMD;
+
+    psTresNode = CPLGetXMLNode(psTreeNode, "=tres");
+    if (psTresNode == NULL)
+    {
+        CPLDebug("NITF", "Cannot find <tres> root element");
+        return papszMD;
+    }
+
+    for(psIter = psTresNode->psChild;psIter!=NULL;psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element &&
+            psIter->pszValue != NULL &&
+            strcmp(psIter->pszValue, "tre") == 0)
+        {
+            const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
+            const char* pszMDPrefix = CPLGetXMLValue(psIter, "md_prefix", NULL);
+            if (pszName != NULL && ((pszSpecificTREName == NULL && pszMDPrefix != NULL) ||
+                                    (pszSpecificTREName != NULL && strcmp(pszName, pszSpecificTREName) == 0)))
+            {
+                if (psFile != NULL)
+                {
+                    const char *pachTRE = NULL;
+                    int  nTRESize = 0;
+
+                    pachTRE = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes,
+                                           pszName, &nTRESize);
+                    if( pachTRE != NULL )
+                        papszMD = NITFGenericMetadataReadTRE(
+                                  papszMD, pszName, pachTRE, nTRESize, psIter);
+                }
+                if (psImage != NULL)
+                {
+                    const char *pachTRE = NULL;
+                    int  nTRESize = 0;
+
+                    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes,
+                                           pszName, &nTRESize);
+                    if( pachTRE != NULL )
+                       papszMD = NITFGenericMetadataReadTRE(
+                                  papszMD, pszName, pachTRE, nTRESize, psIter);
+                }
+                if (pszSpecificTREName)
+                    break;
+            }
+        }
+    }
+
+    return papszMD;
+}
diff --git a/frmts/nitf/nitfimage.c b/frmts/nitf/nitfimage.c
index 4e1e0bc..6683050 100644
--- a/frmts/nitf/nitfimage.c
+++ b/frmts/nitf/nitfimage.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfimage.c 22076 2011-03-30 15:00:46Z warmerdam $
+ * $Id: nitfimage.c 22843 2011-07-31 23:22:42Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for implementation of most NITFImage 
@@ -35,8 +35,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfimage.c 22076 2011-03-30 15:00:46Z warmerdam $");
+CPL_CVSID("$Id: nitfimage.c 22843 2011-07-31 23:22:42Z rouault $");
 
+static int NITFReadIMRFCA( NITFImage *psImage, NITFRPC00BInfo *psRPC );
 static char *NITFTrimWhite( char * );
 #ifdef CPL_LSB
 static void NITFSwapWords( NITFImage *psImage, void *pData, int nWordCount );
@@ -632,7 +633,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
 
         if( nExtendedTREBytes > 3 )
         {
-            if( (int)psSegInfo->nSegmentHeaderSize <
+            if( (int)psSegInfo->nSegmentHeaderSize < 
                             nOffset + nExtendedTREBytes )
                 GOTO_header_too_small();
 
@@ -1245,7 +1246,7 @@ int NITFReadImageBlock( NITFImage *psImage, int nBlockX, int nBlockY,
         /* read all the data needed to get our requested band-block */
         if( psImage->nBitsPerSample != psImage->nWordSize * 8 )
         {
-            if( psImage->chIMODE == 'S' )
+            if( psImage->chIMODE == 'S' || (psImage->chIMODE == 'B' && psImage->nBands == 1) )
             {
                 nWrkBufSize = ((psImage->nBlockWidth * psImage->nBlockHeight * psImage->nBitsPerSample) + 7) / 8;
                 if( VSIFSeekL( psImage->psFile->fp, psImage->panBlockStart[iFullBlock], SEEK_SET ) != 0 
@@ -1569,7 +1570,7 @@ int NITFReadImageLine( NITFImage *psImage, int nLine, int nBand, void *pData )
 
     if( psImage->nBlocksPerRow != 1 || psImage->nBlocksPerColumn != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "Scanline access not supported on tiled NITF files." );
         return BLKREAD_FAIL;
     }
@@ -2148,6 +2149,30 @@ static void NITFSwapWords( NITFImage *psImage, void *pData, int nWordCount )
 #endif /* def CPL_LSB */
 
 /************************************************************************/
+/*                           NITFReadCSEXRA()                           */
+/*                                                                      */
+/*      Read a CSEXRA TRE and return contents as metadata strings.      */
+/************************************************************************/
+
+char **NITFReadCSEXRA( NITFImage *psImage )
+
+{
+    return NITFGenericMetadataRead(NULL, NULL, psImage, "CSEXRA");
+}
+
+/************************************************************************/
+/*                           NITFReadPIAIMC()                           */
+/*                                                                      */
+/*      Read a PIAIMC TRE and return contents as metadata strings.      */
+/************************************************************************/
+
+char **NITFReadPIAIMC( NITFImage *psImage )
+
+{
+    return NITFGenericMetadataRead(NULL, NULL, psImage, "PIAIMC");
+}
+
+/************************************************************************/
 /*                           NITFReadRPC00B()                           */
 /*                                                                      */
 /*      Read an RPC00A or RPC00B structure if the TRE is available.     */
@@ -2184,7 +2209,9 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 
     if( pachTRE == NULL )
     {
-        return FALSE;
+        /* No RPC00 tag. Check to see if we have the IMASDA and IMRFCA 
+           tags (DPPDB data) before returning. */
+        return NITFReadIMRFCA( psImage, psRPC );
     }
 
     if (nTRESize < 801 + 19*12 + 12)
@@ -2338,66 +2365,7 @@ int NITFReadICHIPB( NITFImage *psImage, NITFICHIPBInfo *psICHIP )
 char **NITFReadUSE00A( NITFImage *psImage )
 
 {
-    const char *pachTRE;
-    int  nTRESize;
-    char **papszMD = NULL;
-    int nRemainingBytes;
-
-
-/* -------------------------------------------------------------------- */
-/*      Do we have the TRE?                                             */
-/* -------------------------------------------------------------------- */
-    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, 
-                           "USE00A", &nTRESize );
-
-    if( pachTRE == NULL )
-        return NULL;
-
-    if( nTRESize != 107 )
-    {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "USE00A TRE wrong size, ignoring." );
-        return NULL;
-    }
-
-    nRemainingBytes = psImage->nTREBytes - (pachTRE - psImage->pachTRE);
-    if (nRemainingBytes < 107)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                "Cannot read USE00A TRE. Not enough bytes");
-        return FALSE;
-    }
-/* -------------------------------------------------------------------- */
-/*      Parse out field values.                                         */
-/* -------------------------------------------------------------------- */
-    NITFExtractMetadata( &papszMD, pachTRE,   0,   3, 
-                         "NITF_USE00A_ANGLE_TO_NORTH" );
-    NITFExtractMetadata( &papszMD, pachTRE,   3,   5, 
-                         "NITF_USE00A_MEAN_GSD" );
-    /* reserved: 1 */
-    NITFExtractMetadata( &papszMD, pachTRE,   9,   5, 
-                         "NITF_USE00A_DYNAMIC_RANGE" );
-    /* reserved: 3+1+3 */
-    NITFExtractMetadata( &papszMD, pachTRE,  21,   5, 
-                         "NITF_USE00A_OBL_ANG" );
-    NITFExtractMetadata( &papszMD, pachTRE,  26,   6, 
-                         "NITF_USE00A_ROLL_ANG" );
-    /* reserved: 12+15+4+1+3+1+1 = 37 */
-    NITFExtractMetadata( &papszMD, pachTRE,  69,   2, 
-                         "NITF_USE00A_N_REF" );
-    NITFExtractMetadata( &papszMD, pachTRE,  71,   5, 
-                         "NITF_USE00A_REV_NUM" );
-    NITFExtractMetadata( &papszMD, pachTRE,  76,   3, 
-                         "NITF_USE00A_N_SEG" );
-    NITFExtractMetadata( &papszMD, pachTRE,  79,   6, 
-                         "NITF_USE00A_MAX_LP_SEG" );
-    /* reserved: 6+6 */
-    NITFExtractMetadata( &papszMD, pachTRE,  97,   5, 
-                         "NITF_USE00A_SUN_EL" );
-    NITFExtractMetadata( &papszMD, pachTRE, 102,   5, 
-                         "NITF_USE00A_SUN_AZ" );
-
-    return papszMD;
+    return NITFGenericMetadataRead(NULL, NULL, psImage, "USE00A");
 }
 
 /************************************************************************/
@@ -3270,7 +3238,7 @@ static void NITFLoadLocationTable( NITFImage *psImage )
                     double adfTarget[8];
 
                     VSIFSeekL( psImage->psFile->fp, psImage->pasLocations[i].nLocOffset,
-                              SEEK_SET );
+                               SEEK_SET );
                     VSIFReadL( adfTarget, 8, 8, psImage->psFile->fp );
                     for( i = 0; i < 8; i++ )
                         CPL_MSBPTR64( (adfTarget + i) );
@@ -3314,7 +3282,7 @@ static void NITFLoadLocationTable( NITFImage *psImage )
             else
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                        "Ignoring NITF RPF Location table since it seems to be corrupt." );
+                          "Ignoring NITF RPF Location table since it seems to be corrupt." );
                 CPLFree( psImage->pasLocations );
                 psImage->pasLocations = NULL;
                 psImage->nLocCount = 0;
@@ -3420,63 +3388,7 @@ static int NITFLoadVQTables( NITFImage *psImage, int bTryGuessingOffset )
 char **NITFReadSTDIDC( NITFImage *psImage )
 
 {
-    const char *pachTRE;
-    int  nTRESize;
-    char **papszMD = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Do we have the TRE?                                             */
-/* -------------------------------------------------------------------- */
-    pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, 
-                           "STDIDC", &nTRESize );
-
-    if( pachTRE == NULL )
-        return NULL;
-
-    if( nTRESize != 89 )
-    {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "STDIDC TRE wrong size, ignoring." );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Parse out field values.                                         */
-/* -------------------------------------------------------------------- */
-    NITFExtractMetadata( &papszMD, pachTRE,   0,  14, 
-                         "NITF_STDIDC_ACQUISITION_DATE" );
-    NITFExtractMetadata( &papszMD, pachTRE,  14,  14, 
-                         "NITF_STDIDC_MISSION" );
-    NITFExtractMetadata( &papszMD, pachTRE,  28,   2, 
-                         "NITF_STDIDC_PASS" );
-    NITFExtractMetadata( &papszMD, pachTRE,  30,   3, 
-                         "NITF_STDIDC_OP_NUM" );
-    NITFExtractMetadata( &papszMD, pachTRE,  33,   2, 
-                         "NITF_STDIDC_START_SEGMENT" );
-    NITFExtractMetadata( &papszMD, pachTRE,  35,   2, 
-                         "NITF_STDIDC_REPRO_NUM" );
-    NITFExtractMetadata( &papszMD, pachTRE,  37,   3, 
-                         "NITF_STDIDC_REPLAY_REGEN" );
-    /* reserved: 1 */
-    NITFExtractMetadata( &papszMD, pachTRE,  41,   3, 
-                         "NITF_STDIDC_START_COLUMN" );
-    NITFExtractMetadata( &papszMD, pachTRE,  44,   5, 
-                         "NITF_STDIDC_START_ROW" );
-    NITFExtractMetadata( &papszMD, pachTRE,  49,   2, 
-                         "NITF_STDIDC_END_SEGMENT" );
-    NITFExtractMetadata( &papszMD, pachTRE,  51,   3, 
-                         "NITF_STDIDC_END_COLUMN" );
-    NITFExtractMetadata( &papszMD, pachTRE,  54,   5, 
-                         "NITF_STDIDC_END_ROW" );
-    NITFExtractMetadata( &papszMD, pachTRE,  59,   2, 
-                         "NITF_STDIDC_COUNTRY" );
-    NITFExtractMetadata( &papszMD, pachTRE,  61,   4, 
-                         "NITF_STDIDC_WAC" );
-    NITFExtractMetadata( &papszMD, pachTRE,  65,  11, 
-                         "NITF_STDIDC_LOCATION" );
-    /* reserved: 5+8 */
-
-    return papszMD;
+    return NITFGenericMetadataRead(NULL, NULL, psImage, "STDIDC");
 }
 
 /************************************************************************/
@@ -3836,3 +3748,82 @@ static void NITFPossibleIGEOLOReorientation( NITFImage *psImage )
                   "IGEOLO corners have been reoriented by NITFPossibleIGEOLOReorientation()." );
     }
 }
+
+/************************************************************************/
+/*                           NITFReadIMRFCA()                           */
+/*                                                                      */
+/*      Read DPPDB IMRFCA TRE (and the associated IMASDA TRE) if it is  */
+/*      available. IMRFCA RPC coefficients are remapped into RPC00B     */
+/*      organization.                                                   */
+/************************************************************************/
+int NITFReadIMRFCA( NITFImage *psImage, NITFRPC00BInfo *psRPC )
+{
+    char        szTemp[100];
+    const char *pachTreIMASDA   = NULL;
+    const char *pachTreIMRFCA   = NULL;
+    double      dfTolerance     = 1.0e-10;
+    int         count           = 0;
+    int         nTreIMASDASize  = 0;
+    int         nTreIMRFCASize = 0;
+
+    if( (psImage == NULL) || (psRPC == NULL) ) return FALSE;
+
+    /* Check to see if we have the IMASDA and IMRFCA tag (DPPDB data). */
+
+    pachTreIMASDA = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, "IMASDA", &nTreIMASDASize );
+    pachTreIMRFCA = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes, "IMRFCA", &nTreIMRFCASize );
+
+    if ( (pachTreIMASDA == NULL) || (pachTreIMRFCA == NULL) ) return FALSE;
+
+    if( nTreIMASDASize < 242 || nTreIMRFCASize < 1760 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot read DPPDB IMASDA/IMRFCA TREs; not enough bytes." );
+
+        return FALSE;
+    }
+
+    /* Parse out the field values. */
+
+    /* Set the errors to 0.0 for now. */
+
+    psRPC->ERR_BIAS = 0.0;
+    psRPC->ERR_RAND = 0.0;
+    
+    psRPC->LONG_OFF     = atof( NITFGetField(szTemp, pachTreIMASDA, 0,   22) );
+    psRPC->LAT_OFF      = atof( NITFGetField(szTemp, pachTreIMASDA, 22,  22) );
+    psRPC->HEIGHT_OFF   = atof( NITFGetField(szTemp, pachTreIMASDA, 44,  22) );
+    psRPC->LONG_SCALE   = atof( NITFGetField(szTemp, pachTreIMASDA, 66,  22) );
+    psRPC->LAT_SCALE    = atof( NITFGetField(szTemp, pachTreIMASDA, 88,  22) );
+    psRPC->HEIGHT_SCALE = atof( NITFGetField(szTemp, pachTreIMASDA, 110, 22) );
+    psRPC->SAMP_OFF     = atof( NITFGetField(szTemp, pachTreIMASDA, 132, 22) );
+    psRPC->LINE_OFF     = atof( NITFGetField(szTemp, pachTreIMASDA, 154, 22) );
+    psRPC->SAMP_SCALE   = atof( NITFGetField(szTemp, pachTreIMASDA, 176, 22) );
+    psRPC->LINE_SCALE   = atof( NITFGetField(szTemp, pachTreIMASDA, 198, 22) );
+
+    if (psRPC->HEIGHT_SCALE == 0.0 ) psRPC->HEIGHT_SCALE = dfTolerance;
+    if (psRPC->LAT_SCALE    == 0.0 ) psRPC->LAT_SCALE    = dfTolerance;
+    if (psRPC->LINE_SCALE   == 0.0 ) psRPC->LINE_SCALE   = dfTolerance;
+    if (psRPC->LONG_SCALE   == 0.0 ) psRPC->LONG_SCALE   = dfTolerance;
+    if (psRPC->SAMP_SCALE   == 0.0 ) psRPC->SAMP_SCALE   = dfTolerance;
+
+    psRPC->HEIGHT_SCALE = 1.0/psRPC->HEIGHT_SCALE;
+    psRPC->LAT_SCALE    = 1.0/psRPC->LAT_SCALE;
+    psRPC->LINE_SCALE   = 1.0/psRPC->LINE_SCALE;
+    psRPC->LONG_SCALE   = 1.0/psRPC->LONG_SCALE;
+    psRPC->SAMP_SCALE   = 1.0/psRPC->SAMP_SCALE;
+
+    /* Parse out the RPC coefficients. */
+
+    for( count = 0; count < 20; ++count )
+    {
+        psRPC->LINE_NUM_COEFF[count] = atof( NITFGetField(szTemp, pachTreIMRFCA, count*22,     22) );
+        psRPC->LINE_DEN_COEFF[count] = atof( NITFGetField(szTemp, pachTreIMRFCA, 440+count*22, 22) );
+
+        psRPC->SAMP_NUM_COEFF[count] = atof( NITFGetField(szTemp, pachTreIMRFCA, 880+count*22,  22) );
+        psRPC->SAMP_DEN_COEFF[count] = atof( NITFGetField(szTemp, pachTreIMRFCA, 1320+count*22, 22) );
+    }
+
+    psRPC->SUCCESS = 1;
+
+    return TRUE;
+}
diff --git a/frmts/nitf/nitflib.h b/frmts/nitf/nitflib.h
index 97c9fc8..469e7cc 100644
--- a/frmts/nitf/nitflib.h
+++ b/frmts/nitf/nitflib.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitflib.h 21059 2010-11-03 14:18:58Z dron $
+ * $Id: nitflib.h 22843 2011-07-31 23:22:42Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Main GDAL independent include file for NITF support.  
@@ -33,6 +33,7 @@
 #include "cpl_port.h"
 #include "cpl_error.h"
 #include "cpl_vsi.h"
+#include "cpl_minixml.h"
 
 CPL_C_START
 
@@ -69,6 +70,8 @@ typedef struct {
     char    *pachTRE;
 
     char    **papszMetadata;
+
+    CPLXMLNode *psNITFSpecNode;
     
 } NITFFile;
 
@@ -105,7 +108,7 @@ typedef struct {
 
 } NITFBandInfo;
 
-typedef struct {
+typedef struct { 
     GUInt16 nLocId;
     GUInt32 nLocOffset;
     GUInt32 nLocSize;
@@ -214,6 +217,8 @@ int       CPL_DLL  NITFWriteIGEOLO( NITFImage *psImage, char chICORDS,
                                     double dfURX, double dfURY,
                                     double dfLRX, double dfLRY,
                                     double dfLLX, double dfLLY );
+char      CPL_DLL **NITFReadCSEXRA( NITFImage *psImage );
+char      CPL_DLL **NITFReadPIAIMC( NITFImage *psImage );
 char      CPL_DLL **NITFReadUSE00A( NITFImage *psImage );
 char      CPL_DLL **NITFReadSTDIDC( NITFImage *psImage );
 char      CPL_DLL **NITFReadBLOCKA( NITFImage *psImage );
@@ -387,6 +392,20 @@ typedef struct
 /** Return not freeable (maybe NULL if no matching) */
 const NITFSeries CPL_DLL *NITFGetSeriesInfo(const char* pszFilename);
 
+/* -------------------------------------------------------------------- */
+/*                           Internal use                               */
+/* -------------------------------------------------------------------- */
+
+char **NITFGenericMetadataRead(char **papszMD,
+                               NITFFile* psFile,
+                               NITFImage *psImage,
+                               const char* pszSpecificTREName);
+
+CPLXMLNode* NITFCreateXMLTre(NITFFile* psFile,
+                             const char* pszTREName,
+                             const char *pachTRE,
+                             int nTRESize);
+
 CPL_C_END
 
 #endif /* ndef NITFLIB_H_INCLUDED */
diff --git a/frmts/nitf/nitfrasterband.cpp b/frmts/nitf/nitfrasterband.cpp
new file mode 100644
index 0000000..6983214
--- /dev/null
+++ b/frmts/nitf/nitfrasterband.cpp
@@ -0,0 +1,967 @@
+/******************************************************************************
+ * $Id: nitfrasterband.cpp 22851 2011-08-01 19:01:18Z rouault $
+ *
+ * Project:  NITF Read/Write Translator
+ * Purpose:  NITFRasterBand (and related proxy band) implementations.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam
+ *
+ * Portions Copyright (c) Her majesty the Queen in right of Canada as
+ * represented by the Minister of National Defence, 2006.
+ *
+ * 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 "nitfdataset.h"
+#include "cpl_string.h"
+#include "cpl_csv.h"
+
+CPL_CVSID("$Id: nitfrasterband.cpp 22851 2011-08-01 19:01:18Z rouault $");
+
+/************************************************************************/
+/*                       NITFMakeColorTable()                           */
+/************************************************************************/
+
+static GDALColorTable* NITFMakeColorTable(NITFImage* psImage, NITFBandInfo *psBandInfo)
+{
+    GDALColorTable* poColorTable = NULL;
+
+    if( psBandInfo->nSignificantLUTEntries > 0 )
+    {
+        int  iColor;
+
+        poColorTable = new GDALColorTable();
+
+        for( iColor = 0; iColor < psBandInfo->nSignificantLUTEntries; iColor++)
+        {
+            GDALColorEntry sEntry;
+
+            sEntry.c1 = psBandInfo->pabyLUT[  0 + iColor];
+            sEntry.c2 = psBandInfo->pabyLUT[256 + iColor];
+            sEntry.c3 = psBandInfo->pabyLUT[512 + iColor];
+            sEntry.c4 = 255;
+
+            poColorTable->SetColorEntry( iColor, &sEntry );
+        }
+
+        if (psImage->bNoDataSet)
+        {
+            GDALColorEntry sEntry;
+            sEntry.c1 = sEntry.c2 = sEntry.c3 = sEntry.c4 = 0;
+            poColorTable->SetColorEntry( psImage->nNoDataValue, &sEntry );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      We create a color table for 1 bit data too...                   */
+/* -------------------------------------------------------------------- */
+    if( poColorTable == NULL && psImage->nBitsPerSample == 1 )
+    {
+        GDALColorEntry sEntry;
+
+        poColorTable = new GDALColorTable();
+
+        sEntry.c1 = 0;
+        sEntry.c2 = 0;
+        sEntry.c3 = 0;
+        sEntry.c4 = 255;
+        poColorTable->SetColorEntry( 0, &sEntry );
+
+        sEntry.c1 = 255;
+        sEntry.c2 = 255;
+        sEntry.c3 = 255;
+        sEntry.c4 = 255;
+        poColorTable->SetColorEntry( 1, &sEntry );
+    }
+    
+    return poColorTable;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        NITFProxyPamRasterBand                        */
+/* ==================================================================== */
+/************************************************************************/
+
+NITFProxyPamRasterBand::~NITFProxyPamRasterBand()
+{
+    std::map<CPLString, char**>::iterator oIter = oMDMap.begin();
+    while(oIter != oMDMap.end())
+    {
+        CSLDestroy(oIter->second);
+        oIter ++;
+    }
+}
+
+
+#define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, argParams) \
+retType NITFProxyPamRasterBand::methodName argList \
+{ \
+    retType ret; \
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
+    if (_poSrcBand) \
+    { \
+        ret = _poSrcBand->methodName argParams; \
+        UnrefUnderlyingRasterBand(_poSrcBand); \
+    } \
+    else \
+    { \
+        ret = retErrValue; \
+    } \
+    return ret; \
+}
+
+
+#define RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(retType, retErrValue, methodName, underlyingMethodName, argList, argParams) \
+retType NITFProxyPamRasterBand::methodName argList \
+{ \
+    retType ret; \
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
+    if (_poSrcBand) \
+    { \
+        ret = _poSrcBand->underlyingMethodName argParams; \
+        UnrefUnderlyingRasterBand(_poSrcBand); \
+    } \
+    else \
+    { \
+        ret = retErrValue; \
+    } \
+    return ret; \
+}
+
+char      **NITFProxyPamRasterBand::GetMetadata( const char * pszDomain  )
+{
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
+    if (_poSrcBand)
+    {
+        /* Let's merge metadata of PAM and the underlying band */
+        /* PAM metadata should override underlying band metadata */
+        char** papszMD = CSLDuplicate(_poSrcBand->GetMetadata( pszDomain ));
+        papszMD = CSLMerge( papszMD, GDALPamRasterBand::GetMetadata(pszDomain) );
+
+        if (pszDomain == NULL)
+            pszDomain = "";
+
+        std::map<CPLString, char**>::iterator oIter = oMDMap.find(pszDomain);
+        if (oIter != oMDMap.end())
+            CSLDestroy(oIter->second);
+        oMDMap[pszDomain] = papszMD;
+        UnrefUnderlyingRasterBand(_poSrcBand);
+
+        return papszMD;
+    }
+
+    return GDALPamRasterBand::GetMetadata(pszDomain);
+}
+
+
+const char *NITFProxyPamRasterBand::GetMetadataItem( const char * pszName,
+                                                     const char * pszDomain )
+{
+    const char* pszRet = GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
+    if (pszRet)
+        return pszRet;
+
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
+    if (_poSrcBand)
+    {
+        pszRet = _poSrcBand->GetMetadataItem( pszName, pszDomain );
+        UnrefUnderlyingRasterBand(_poSrcBand);
+    }
+
+    return pszRet;
+}
+
+CPLErr NITFProxyPamRasterBand::GetStatistics( int bApproxOK, int bForce,
+                                      double *pdfMin, double *pdfMax,
+                                      double *pdfMean, double *pdfStdDev )
+{
+    CPLErr ret;
+
+/* -------------------------------------------------------------------- */
+/*      Do we already have metadata items for the requested values?     */
+/* -------------------------------------------------------------------- */
+    if( (pdfMin == NULL || GetMetadataItem("STATISTICS_MINIMUM") != NULL)
+     && (pdfMax == NULL || GetMetadataItem("STATISTICS_MAXIMUM") != NULL)
+     && (pdfMean == NULL || GetMetadataItem("STATISTICS_MEAN") != NULL)
+     && (pdfStdDev == NULL || GetMetadataItem("STATISTICS_STDDEV") != NULL) )
+    {
+        return GDALPamRasterBand::GetStatistics( bApproxOK, bForce,
+                                                 pdfMin, pdfMax,
+                                                 pdfMean, pdfStdDev);
+    }
+
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
+    if (_poSrcBand)
+    {
+        ret = _poSrcBand->GetStatistics( bApproxOK, bForce,
+                                         pdfMin, pdfMax, pdfMean, pdfStdDev);
+        if (ret == CE_None)
+        {
+            /* Report underlying statistics at PAM level */
+            SetMetadataItem("STATISTICS_MINIMUM",
+                            _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
+            SetMetadataItem("STATISTICS_MAXIMUM",
+                            _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
+            SetMetadataItem("STATISTICS_MEAN",
+                            _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
+            SetMetadataItem("STATISTICS_STDDEV",
+                            _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
+        }
+        UnrefUnderlyingRasterBand(_poSrcBand);
+    }
+    else
+    {
+        ret = CE_Failure;
+    }
+    return ret;
+}
+
+CPLErr NITFProxyPamRasterBand::ComputeStatistics( int bApproxOK,
+                                        double *pdfMin, double *pdfMax,
+                                        double *pdfMean, double *pdfStdDev,
+                                        GDALProgressFunc pfn, void *pProgressData )
+{
+    CPLErr ret;
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
+    if (_poSrcBand)
+    {
+        ret = _poSrcBand->ComputeStatistics( bApproxOK, pdfMin, pdfMax,
+                                             pdfMean, pdfStdDev,
+                                             pfn, pProgressData);
+        if (ret == CE_None)
+        {
+            /* Report underlying statistics at PAM level */
+            SetMetadataItem("STATISTICS_MINIMUM",
+                            _poSrcBand->GetMetadataItem("STATISTICS_MINIMUM"));
+            SetMetadataItem("STATISTICS_MAXIMUM",
+                            _poSrcBand->GetMetadataItem("STATISTICS_MAXIMUM"));
+            SetMetadataItem("STATISTICS_MEAN",
+                            _poSrcBand->GetMetadataItem("STATISTICS_MEAN"));
+            SetMetadataItem("STATISTICS_STDDEV",
+                            _poSrcBand->GetMetadataItem("STATISTICS_STDDEV"));
+        }
+        UnrefUnderlyingRasterBand(_poSrcBand);
+    }
+    else
+    {
+        ret = CE_Failure;
+    }
+    return ret;
+}
+
+
+#define RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(methodName) \
+double NITFProxyPamRasterBand::methodName( int *pbSuccess ) \
+{ \
+    int bSuccess = FALSE; \
+    double dfRet = GDALPamRasterBand::methodName(&bSuccess); \
+    if (bSuccess) \
+    { \
+        if (pbSuccess) \
+            *pbSuccess = TRUE; \
+        return dfRet; \
+    } \
+    GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand(); \
+    if (_poSrcBand) \
+    { \
+        dfRet = _poSrcBand->methodName( pbSuccess ); \
+        UnrefUnderlyingRasterBand(_poSrcBand); \
+    } \
+    else \
+    { \
+        dfRet = 0; \
+    } \
+    return dfRet; \
+}
+
+RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetNoDataValue)
+RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMinimum)
+RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(GetMaximum)
+
+RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IReadBlock, ReadBlock,
+                                ( int nXBlockOff, int nYBlockOff, void* pImage),
+                                (nXBlockOff, nYBlockOff, pImage) )
+RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IWriteBlock, WriteBlock,
+                                ( int nXBlockOff, int nYBlockOff, void* pImage),
+                                (nXBlockOff, nYBlockOff, pImage) )
+RB_PROXY_METHOD_WITH_RET_AND_CALL_OTHER_METHOD(CPLErr, CE_Failure, IRasterIO, RasterIO,
+                        ( GDALRWFlag eRWFlag,
+                                int nXOff, int nYOff, int nXSize, int nYSize,
+                                void * pData, int nBufXSize, int nBufYSize,
+                                GDALDataType eBufType,
+                                int nPixelSpace,
+                                int nLineSpace ),
+                        (eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                pData, nBufXSize, nBufYSize, eBufType,
+                                nPixelSpace, nLineSpace ) )
+
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, FlushCache, (), ())
+
+RB_PROXY_METHOD_WITH_RET(GDALColorInterp, GCI_Undefined, GetColorInterpretation, (), ())
+RB_PROXY_METHOD_WITH_RET(GDALColorTable*, NULL, GetColorTable, (), ())
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, Fill,
+                        (double dfRealValue, double dfImaginaryValue),
+                        (dfRealValue, dfImaginaryValue))
+
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeRasterMinMax,
+                        ( int arg1, double* arg2 ), (arg1, arg2))
+
+RB_PROXY_METHOD_WITH_RET(int, 0, HasArbitraryOverviews, (), ())
+RB_PROXY_METHOD_WITH_RET(int, 0,  GetOverviewCount, (), ())
+RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL,  GetOverview, (int arg1), (arg1))
+RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL,  GetRasterSampleOverview,
+                        (int arg1), (arg1))
+
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, BuildOverviews,
+                        (const char * arg1, int arg2, int *arg3,
+                        GDALProgressFunc arg4, void * arg5),
+                        (arg1, arg2, arg3, arg4, arg5))
+
+RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
+                        ( int nXOff, int nYOff, int nXSize, int nYSize,
+                        int nBufXSize, int nBufYSize,
+                        GDALDataType eDT, char **papszOptions ),
+                        (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, papszOptions))
+
+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))
+
+
+/************************************************************************/
+/*                 UnrefUnderlyingRasterBand()                        */
+/************************************************************************/
+
+void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand)
+{
+}
+
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            NITFRasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                           NITFRasterBand()                           */
+/************************************************************************/
+
+NITFRasterBand::NITFRasterBand( NITFDataset *poDS, int nBand )
+
+{
+    NITFBandInfo *psBandInfo = poDS->psImage->pasBandInfo + nBand - 1;
+
+    this->poDS = poDS;
+    this->nBand = nBand;
+
+    this->eAccess = poDS->eAccess;
+    this->psImage = poDS->psImage;
+
+/* -------------------------------------------------------------------- */
+/*      Translate data type(s).                                         */
+/* -------------------------------------------------------------------- */
+    if( psImage->nBitsPerSample <= 8 )
+        eDataType = GDT_Byte;
+    else if( psImage->nBitsPerSample == 16 
+             && EQUAL(psImage->szPVType,"SI") )
+        eDataType = GDT_Int16;
+    else if( psImage->nBitsPerSample == 16 )
+        eDataType = GDT_UInt16;
+    else if( psImage->nBitsPerSample == 12 )
+        eDataType = GDT_UInt16;
+    else if( psImage->nBitsPerSample == 32 
+             && EQUAL(psImage->szPVType,"SI") )
+        eDataType = GDT_Int32;
+    else if( psImage->nBitsPerSample == 32 
+             && EQUAL(psImage->szPVType,"R") )
+        eDataType = GDT_Float32;
+    else if( psImage->nBitsPerSample == 32 )
+        eDataType = GDT_UInt32;
+    else if( psImage->nBitsPerSample == 64 
+             && EQUAL(psImage->szPVType,"R") )
+        eDataType = GDT_Float64;
+    else if( psImage->nBitsPerSample == 64
+              && EQUAL(psImage->szPVType,"C") )
+        eDataType = GDT_CFloat32;
+    /* ERO : note I'm not sure if CFloat64 can be transmitted as NBPP is only 2 characters */
+    else
+    {
+        int bOpenUnderlyingDS = CSLTestBoolean(
+                CPLGetConfigOption("NITF_OPEN_UNDERLYING_DS", "YES"));
+        if (!bOpenUnderlyingDS && psImage->nBitsPerSample > 8 && psImage->nBitsPerSample < 16)
+        {
+            if (EQUAL(psImage->szPVType,"SI"))
+                eDataType = GDT_Int16;
+            else
+                eDataType = GDT_UInt16;
+        }
+        else
+        {
+            eDataType = GDT_Unknown;
+            CPLError( CE_Warning, CPLE_AppDefined,
+                    "Unsupported combination of PVTYPE(%s) and NBPP(%d).",
+                    psImage->szPVType, psImage->nBitsPerSample );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Work out block size. If the image is all one big block we       */
+/*      handle via the scanline access API.                             */
+/* -------------------------------------------------------------------- */
+    if( psImage->nBlocksPerRow == 1 
+        && psImage->nBlocksPerColumn == 1
+        && psImage->nBitsPerSample >= 8
+        && EQUAL(psImage->szIC,"NC") )
+    {
+        bScanlineAccess = TRUE;
+        nBlockXSize = psImage->nBlockWidth;
+        nBlockYSize = 1;
+    }
+    else
+    {
+        bScanlineAccess = FALSE;
+        nBlockXSize = psImage->nBlockWidth;
+        nBlockYSize = psImage->nBlockHeight;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a color table?                                       */
+/* -------------------------------------------------------------------- */
+    poColorTable = NITFMakeColorTable(psImage,
+                                      psBandInfo);
+
+    if( psImage->nBitsPerSample == 1 
+    ||  psImage->nBitsPerSample == 3
+    ||  psImage->nBitsPerSample == 5
+    ||  psImage->nBitsPerSample == 6
+    ||  psImage->nBitsPerSample == 7
+    ||  psImage->nBitsPerSample == 12 )
+        SetMetadataItem( "NBITS", CPLString().Printf("%d", psImage->nBitsPerSample), "IMAGE_STRUCTURE" );
+
+    pUnpackData = 0;
+    if (psImage->nBitsPerSample == 3
+    ||  psImage->nBitsPerSample == 5
+    ||  psImage->nBitsPerSample == 6
+    ||  psImage->nBitsPerSample == 7)
+      pUnpackData = new GByte[((nBlockXSize*nBlockYSize+7)/8)*8];
+}
+
+/************************************************************************/
+/*                          ~NITFRasterBand()                           */
+/************************************************************************/
+
+NITFRasterBand::~NITFRasterBand()
+
+{
+    if( poColorTable != NULL )
+        delete poColorTable;
+
+    delete[] pUnpackData;
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr NITFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                   void * pImage )
+
+{
+    int  nBlockResult;
+    NITFDataset *poGDS = (NITFDataset *) poDS;
+
+/* -------------------------------------------------------------------- */
+/*      Special case for JPEG blocks.                                   */
+/* -------------------------------------------------------------------- */
+    if( EQUAL(psImage->szIC,"C3") || EQUAL(psImage->szIC,"M3") )
+    {
+        CPLErr eErr = poGDS->ReadJPEGBlock( nBlockXOff, nBlockYOff );
+        int nBlockBandSize = psImage->nBlockWidth*psImage->nBlockHeight*
+                             (GDALGetDataTypeSize(eDataType)/8);
+
+        if( eErr != CE_None )
+            return eErr;
+
+        memcpy( pImage, 
+                poGDS->pabyJPEGBlock + (nBand - 1) * nBlockBandSize, 
+                nBlockBandSize );
+
+        return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the line/block                                             */
+/* -------------------------------------------------------------------- */
+    if( bScanlineAccess )
+    {
+        nBlockResult = 
+            NITFReadImageLine(psImage, nBlockYOff, nBand, pImage);
+    }
+    else
+    {
+        nBlockResult = 
+            NITFReadImageBlock(psImage, nBlockXOff, nBlockYOff, nBand, pImage);
+    }
+
+    if( nBlockResult == BLKREAD_OK )
+    {
+        if( psImage->nBitsPerSample % 8 )
+            Unpack((GByte*)pImage);
+
+        return CE_None;
+    }
+
+    if( nBlockResult == BLKREAD_FAIL )
+        return CE_Failure;
+
+/* -------------------------------------------------------------------- */
+/*      If we got a null/missing block, try to fill it in with the      */
+/*      nodata value.  It seems this only really works properly for     */
+/*      8bit.                                                           */
+/* -------------------------------------------------------------------- */
+    if( psImage->bNoDataSet )
+        memset( pImage, psImage->nNoDataValue, 
+                psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
+    else
+        memset( pImage, 0, 
+                psImage->nWordSize*psImage->nBlockWidth*psImage->nBlockHeight);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            IWriteBlock()                             */
+/************************************************************************/
+
+CPLErr NITFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
+                                    void * pImage )
+    
+{
+    int  nBlockResult;
+
+/* -------------------------------------------------------------------- */
+/*      Write the line/block                                            */
+/* -------------------------------------------------------------------- */
+    if( bScanlineAccess )
+    {
+        nBlockResult = 
+            NITFWriteImageLine(psImage, nBlockYOff, nBand, pImage);
+    }
+    else
+    {
+        nBlockResult = 
+            NITFWriteImageBlock(psImage, nBlockXOff, nBlockYOff, nBand,pImage);
+    }
+
+    if( nBlockResult == BLKREAD_OK )
+        return CE_None;
+    else
+        return CE_Failure;
+}
+
+/************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
+
+double NITFRasterBand::GetNoDataValue( int *pbSuccess )
+
+{
+    if( pbSuccess != NULL )
+        *pbSuccess = psImage->bNoDataSet;
+
+    if( psImage->bNoDataSet )
+        return psImage->nNoDataValue;
+    else
+        return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+}
+
+/************************************************************************/
+/*                       GetColorInterpretation()                       */
+/************************************************************************/
+
+GDALColorInterp NITFRasterBand::GetColorInterpretation()
+
+{
+    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
+
+    if( poColorTable != NULL )
+        return GCI_PaletteIndex;
+    
+    if( EQUAL(psBandInfo->szIREPBAND,"R") )
+        return GCI_RedBand;
+    if( EQUAL(psBandInfo->szIREPBAND,"G") )
+        return GCI_GreenBand;
+    if( EQUAL(psBandInfo->szIREPBAND,"B") )
+        return GCI_BlueBand;
+    if( EQUAL(psBandInfo->szIREPBAND,"M") )
+        return GCI_GrayIndex;
+    if( EQUAL(psBandInfo->szIREPBAND,"Y") )
+        return GCI_YCbCr_YBand;
+    if( EQUAL(psBandInfo->szIREPBAND,"Cb") )
+        return GCI_YCbCr_CbBand;
+    if( EQUAL(psBandInfo->szIREPBAND,"Cr") )
+        return GCI_YCbCr_CrBand;
+
+    return GCI_Undefined;
+}
+
+/************************************************************************/
+/*                     NITFSetColorInterpretation()                     */
+/************************************************************************/
+
+CPLErr NITFSetColorInterpretation( NITFImage *psImage, 
+                                   int nBand,
+                                   GDALColorInterp eInterp )
+    
+{
+    NITFBandInfo *psBandInfo = psImage->pasBandInfo + nBand - 1;
+    const char *pszREP = NULL;
+    GUIntBig nOffset;
+
+    if( eInterp == GCI_RedBand )
+        pszREP = "R";
+    else if( eInterp == GCI_GreenBand )
+        pszREP = "G";
+    else if( eInterp == GCI_BlueBand )
+        pszREP = "B";
+    else if( eInterp == GCI_GrayIndex )
+        pszREP = "M";
+    else if( eInterp == GCI_YCbCr_YBand )
+        pszREP = "Y";
+    else if( eInterp == GCI_YCbCr_CbBand )
+        pszREP = "Cb";
+    else if( eInterp == GCI_YCbCr_CrBand )
+        pszREP = "Cr";
+    else if( eInterp == GCI_Undefined )
+        return CE_None;
+
+    if( pszREP == NULL )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported, 
+                  "Requested color interpretation (%s) not supported in NITF.",
+                  GDALGetColorInterpretationName( eInterp ) );
+        return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Where does this go in the file?                                 */
+/* -------------------------------------------------------------------- */
+    strcpy( psBandInfo->szIREPBAND, pszREP );
+    nOffset = NITFIHFieldOffset( psImage, "IREPBAND" );
+
+    if( nOffset != 0 )
+        nOffset += (nBand - 1) * 13;
+    
+/* -------------------------------------------------------------------- */
+/*      write it (space padded).                                        */
+/* -------------------------------------------------------------------- */
+    char szPadded[4];
+    strcpy( szPadded, pszREP );
+    strcat( szPadded, " " );
+    
+    if( nOffset != 0 )
+    {
+        if( VSIFSeekL( psImage->psFile->fp, nOffset, SEEK_SET ) != 0 
+            || VSIFWriteL( (void *) szPadded, 1, 2, psImage->psFile->fp ) != 2 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "IO failure writing new IREPBAND value to NITF file." );
+            return CE_Failure;
+        }
+    }
+    
+    return CE_None;
+}
+
+/************************************************************************/
+/*                       SetColorInterpretation()                       */
+/************************************************************************/
+
+CPLErr NITFRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
+
+{
+    return NITFSetColorInterpretation( psImage, nBand, eInterp );
+}
+
+/************************************************************************/
+/*                           GetColorTable()                            */
+/************************************************************************/
+
+GDALColorTable *NITFRasterBand::GetColorTable()
+
+{
+    return poColorTable;
+}
+
+/************************************************************************/
+/*                           SetColorTable()                            */
+/************************************************************************/
+
+CPLErr NITFRasterBand::SetColorTable( GDALColorTable *poNewCT )
+
+{
+    NITFDataset *poGDS = (NITFDataset *) poDS;
+    if( poGDS->bInLoadXML )
+        return GDALPamRasterBand::SetColorTable(poNewCT);
+        
+    if( poNewCT == NULL )
+        return CE_Failure;
+
+    GByte abyNITFLUT[768];
+    int   i;
+    int   nCount = MIN(256,poNewCT->GetColorEntryCount());
+
+    memset( abyNITFLUT, 0, 768 );
+    for( i = 0; i < nCount; i++ )
+    {
+        GDALColorEntry sEntry;
+
+        poNewCT->GetColorEntryAsRGB( i, &sEntry );
+        abyNITFLUT[i    ] = (GByte) sEntry.c1;
+        abyNITFLUT[i+256] = (GByte) sEntry.c2;
+        abyNITFLUT[i+512] = (GByte) sEntry.c3;
+    }
+
+    if( NITFWriteLUT( psImage, nBand, nCount, abyNITFLUT ) )
+        return CE_None;
+    else
+        return CE_Failure;
+}
+
+/************************************************************************/
+/*                           Unpack()                                   */
+/************************************************************************/
+
+void NITFRasterBand::Unpack( GByte* pData )
+{
+  long n = nBlockXSize*nBlockYSize;
+  long i;
+  long k;
+
+  GByte abyTempData[7] = {0, 0, 0, 0, 0, 0, 0};
+  const GByte* pDataSrc = pData;
+  if (n < psImage->nBitsPerSample &&
+      psImage->nBitsPerSample < 8)
+  {
+      memcpy(abyTempData, pData, n);
+      pDataSrc = abyTempData;
+  }
+
+  switch (psImage->nBitsPerSample)
+  {
+    case 1:
+    {
+      // unpack 1-bit in-place in reverse
+      for (i = n; --i >= 0; )
+        pData[i] = (pData[i>>3] & (0x80 >> (i&7))) != 0;
+       
+      break;
+    }
+    case 2:
+    {
+      static const int s_Shift2[] = {6, 4, 2, 0};
+      // unpack 2-bit in-place in reverse
+      for (i = n; --i >= 0; )
+        pData[i] = (pData[i>>2] >> (GByte)s_Shift2[i&3]) & 0x03;
+       
+      break;
+    }
+    case 4:
+    {
+      static const int s_Shift4[] = {4, 0};
+      // unpack 4-bit in-place in reverse
+      for (i = n; --i >= 0; )
+        pData[i] = (pData[i>>1] >> (GByte)s_Shift4[i&1]) & 0x0f;
+       
+      break;
+    }
+    case 3:
+    {
+      // unpacks 8 pixels (3 bytes) at time
+      for (i = 0, k = 0; i < n; i += 8, k += 3)
+      {
+        pUnpackData[i+0] = ((pDataSrc[k+0] >> 5));
+        pUnpackData[i+1] = ((pDataSrc[k+0] >> 2) & 0x07);
+        pUnpackData[i+2] = ((pDataSrc[k+0] << 1) & 0x07) | (pDataSrc[k+1] >> 7);
+        pUnpackData[i+3] = ((pDataSrc[k+1] >> 4) & 0x07);
+        pUnpackData[i+4] = ((pDataSrc[k+1] >> 1) & 0x07);
+        pUnpackData[i+5] = ((pDataSrc[k+1] << 2) & 0x07) | (pDataSrc[k+2] >> 6);
+        pUnpackData[i+6] = ((pDataSrc[k+2] >> 3) & 0x07);
+        pUnpackData[i+7] = ((pDataSrc[k+2]) & 0x7);
+      }
+
+      memcpy(pData, pUnpackData, n);
+      break;
+    }
+    case 5:
+    {
+      // unpacks 8 pixels (5 bytes) at time
+      for (i = 0, k = 0; i < n; i += 8, k += 5)
+      {
+        pUnpackData[i+0] = ((pDataSrc[k+0] >> 3));
+        pUnpackData[i+1] = ((pDataSrc[k+0] << 2) & 0x1f) | (pDataSrc[k+1] >> 6);
+        pUnpackData[i+2] = ((pDataSrc[k+1] >> 1) & 0x1f);
+        pUnpackData[i+3] = ((pDataSrc[k+1] << 4) & 0x1f) | (pDataSrc[k+2] >> 4);
+        pUnpackData[i+4] = ((pDataSrc[k+2] << 1) & 0x1f) | (pDataSrc[k+3] >> 7);
+        pUnpackData[i+5] = ((pDataSrc[k+3] >> 2) & 0x1f);
+        pUnpackData[i+6] = ((pDataSrc[k+3] << 3) & 0x1f) | (pDataSrc[k+4] >> 5);
+        pUnpackData[i+7] = ((pDataSrc[k+4]) & 0x1f);
+      }
+
+      memcpy(pData, pUnpackData, n);
+      break;
+    }
+    case 6:
+    {
+      // unpacks 4 pixels (3 bytes) at time
+      for (i = 0, k = 0; i < n; i += 4, k += 3)
+      {
+        pUnpackData[i+0] = ((pDataSrc[k+0] >> 2));
+        pUnpackData[i+1] = ((pDataSrc[k+0] << 4) & 0x3f) | (pDataSrc[k+1] >> 4);
+        pUnpackData[i+2] = ((pDataSrc[k+1] << 2) & 0x3f) | (pDataSrc[k+2] >> 6);
+        pUnpackData[i+3] = ((pDataSrc[k+2]) & 0x3f);
+      }
+
+      memcpy(pData, pUnpackData, n);
+      break;
+    }
+    case 7:
+    {
+      // unpacks 8 pixels (7 bytes) at time
+      for (i = 0, k = 0; i < n; i += 8, k += 7)
+      {
+        pUnpackData[i+0] = ((pDataSrc[k+0] >> 1));
+        pUnpackData[i+1] = ((pDataSrc[k+0] << 6) & 0x7f) | (pDataSrc[k+1] >> 2);
+        pUnpackData[i+2] = ((pDataSrc[k+1] << 5) & 0x7f) | (pDataSrc[k+2] >> 3) ;
+        pUnpackData[i+3] = ((pDataSrc[k+2] << 4) & 0x7f) | (pDataSrc[k+3] >> 4);
+        pUnpackData[i+4] = ((pDataSrc[k+3] << 3) & 0x7f) | (pDataSrc[k+4] >> 5);
+        pUnpackData[i+5] = ((pDataSrc[k+4] << 2) & 0x7f) | (pDataSrc[k+5] >> 6);
+        pUnpackData[i+6] = ((pDataSrc[k+5] << 1) & 0x7f) | (pDataSrc[k+6] >> 7);
+        pUnpackData[i+7] = ((pDataSrc[k+6]) & 0x7f);
+      }
+
+      memcpy(pData, pUnpackData, n);
+      break;
+    }
+    case 12:
+    {
+      GByte*   pabyImage = (GByte  *)pData;
+      GUInt16* panImage  = (GUInt16*)pData;
+      for (i = n; --i >= 0; )
+      {
+        long iOffset = i*3 / 2;
+        if (i % 2 == 0)
+          panImage[i] = pabyImage[iOffset] + (pabyImage[iOffset+1] & 0xf0) * 16;
+        else
+          panImage[i] = (pabyImage[iOffset]   & 0x0f) * 16
+                      + (pabyImage[iOffset+1] & 0xf0) / 16
+                      + (pabyImage[iOffset+1] & 0x0f) * 256;
+      }
+
+      break;
+    }
+  }
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                       NITFWrapperRasterBand                          */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                      NITFWrapperRasterBand()                         */
+/************************************************************************/
+
+NITFWrapperRasterBand::NITFWrapperRasterBand( NITFDataset * poDS,
+                                              GDALRasterBand* poBaseBand,
+                                              int nBand)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    this->poBaseBand = poBaseBand;
+    eDataType = poBaseBand->GetRasterDataType();
+    poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    poColorTable = NULL;
+    eInterp = poBaseBand->GetColorInterpretation();
+}
+
+/************************************************************************/
+/*                      ~NITFWrapperRasterBand()                        */
+/************************************************************************/
+
+NITFWrapperRasterBand::~NITFWrapperRasterBand()
+{
+    if( poColorTable != NULL )
+        delete poColorTable;
+}
+
+/************************************************************************/
+/*                     RefUnderlyingRasterBand()                        */
+/************************************************************************/
+
+/* We don't need ref-counting. Just return the base band */
+GDALRasterBand* NITFWrapperRasterBand::RefUnderlyingRasterBand()
+{
+    return poBaseBand;
+}
+
+/************************************************************************/
+/*                            GetColorTable()                           */
+/************************************************************************/
+
+GDALColorTable *NITFWrapperRasterBand::GetColorTable()
+{
+    return poColorTable;
+}
+
+/************************************************************************/
+/*                 SetColorTableFromNITFBandInfo()                      */
+/************************************************************************/
+
+void NITFWrapperRasterBand::SetColorTableFromNITFBandInfo()
+{
+    NITFDataset* poGDS = (NITFDataset* )poDS;
+    poColorTable = NITFMakeColorTable(poGDS->psImage,
+                                      poGDS->psImage->pasBandInfo + nBand - 1);
+}
+
+/************************************************************************/
+/*                        GetColorInterpretation()                      */
+/************************************************************************/
+
+GDALColorInterp NITFWrapperRasterBand::GetColorInterpretation()
+{
+    return eInterp;
+}
+
+/************************************************************************/
+/*                        SetColorInterpretation()                      */
+/************************************************************************/
+
+CPLErr NITFWrapperRasterBand::SetColorInterpretation( GDALColorInterp eInterp)
+{
+    this->eInterp = eInterp;
+    return CE_None;
+}
+
diff --git a/frmts/nitf/nitfwritejpeg.cpp b/frmts/nitf/nitfwritejpeg.cpp
index ff963e6..ae90c06 100644
--- a/frmts/nitf/nitfwritejpeg.cpp
+++ b/frmts/nitf/nitfwritejpeg.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfwritejpeg.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: nitfwritejpeg.cpp 21951 2011-03-12 22:02:07Z warmerdam $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GDALDataset/GDALRasterBand implementation on top of "nitflib".
diff --git a/frmts/nitf/rpftoclib.h b/frmts/nitf/rpftoclib.h
index 02910d1..1faafea 100644
--- a/frmts/nitf/rpftoclib.h
+++ b/frmts/nitf/rpftoclib.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rpftoclib.h rouault $
+ * $Id: rpftoclib.h 21951 2011-03-12 22:02:07Z warmerdam $
  *
  * Project:  RPF A.TOC read Library
  * Purpose:  Main GDAL independent include file for RPF TOC support.  
diff --git a/frmts/northwood/grcdataset.cpp b/frmts/northwood/grcdataset.cpp
index 84deda5..17c5e2a 100644
--- a/frmts/northwood/grcdataset.cpp
+++ b/frmts/northwood/grcdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grcdataset.cpp 18354 2009-12-20 10:42:15Z rouault $
+ * $Id: grcdataset.cpp 23059 2011-09-05 17:30:20Z rouault $
  *
  * Project:  GRC Reader
  * Purpose:  GDAL driver for Northwood Classified Format
@@ -53,7 +53,7 @@ class NWT_GRCDataset : public GDALPamDataset
   friend class NWT_GRCRasterBand;
 
   private:
-    FILE * fp;
+    VSILFILE * fp;
     GByte abyHeader[1024];
     NWT_GRID *pGrd;
     char **papszCategories;
@@ -67,6 +67,7 @@ class NWT_GRCDataset : public GDALPamDataset
     ~NWT_GRCDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * poOpenInfo );
 
     CPLErr GetGeoTransform( double *padfTransform );
     const char *GetProjectionRef();
@@ -234,8 +235,8 @@ CPLErr NWT_GRCRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if( nBand == 1 )
     {                            //grc's are just one band of indices
-        VSIFSeek( poGDS->fp, 1024 + nRecordSize * nBlockYOff, SEEK_SET );
-        VSIFRead( pImage, 1, nRecordSize, poGDS->fp );
+        VSIFSeekL( poGDS->fp, 1024 + nRecordSize * nBlockYOff, SEEK_SET );
+        VSIFReadL( pImage, 1, nRecordSize, poGDS->fp );
     }
     else
     {
@@ -297,7 +298,7 @@ CPLErr NWT_GRCRasterBand::SetScale( double dfNewValue )
 /************************************************************************/
 NWT_GRCDataset::NWT_GRCDataset()
 {
-    poColorTable = new GDALColorTable();
+    poColorTable = NULL;
     papszCategories = NULL;
     pszProjection = NULL;
 }
@@ -308,8 +309,7 @@ NWT_GRCDataset::NWT_GRCDataset()
 /************************************************************************/
 NWT_GRCDataset::~NWT_GRCDataset()
 {
-    if( poColorTable )
-        delete poColorTable;
+    delete poColorTable;
     CSLDestroy( papszCategories );
 
     FlushCache();
@@ -317,14 +317,9 @@ NWT_GRCDataset::~NWT_GRCDataset()
     nwtCloseGrid( pGrd );
 
     if( fp != NULL )
-        VSIFClose( fp );
+        VSIFCloseL( fp );
 
-    if( pszProjection != NULL )
-    {
-        CPLFree( pszProjection );
-    }
-    /*if( poCT != NULL )
-        delete poCT;*/
+    CPLFree( pszProjection );
 }
 
 /************************************************************************/
@@ -364,22 +359,34 @@ const char *NWT_GRCDataset::GetProjectionRef()
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                              Identify()                              */
 /************************************************************************/
 
-GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
+int NWT_GRCDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
 /* -------------------------------------------------------------------- */
 /*  Look for the header                                                 */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
-        return NULL;
+    if( poOpenInfo->nHeaderBytes < 50 )
+        return FALSE;
 
     if( poOpenInfo->pabyHeader[0] != 'H' ||
         poOpenInfo->pabyHeader[1] != 'G' ||
         poOpenInfo->pabyHeader[2] != 'P' ||
         poOpenInfo->pabyHeader[3] != 'C' ||
         poOpenInfo->pabyHeader[4] != '8' )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    if( !Identify(poOpenInfo) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -389,14 +396,18 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS = new NWT_GRCDataset();
 
-    poDS->fp = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
+    poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (poDS->fp == NULL)
+    {
+        delete poDS;
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    VSIFSeek( poDS->fp, 0, SEEK_SET );
-    VSIFRead( poDS->abyHeader, 1, 1024, poDS->fp );
+    VSIFSeekL( poDS->fp, 0, SEEK_SET );
+    VSIFReadL( poDS->abyHeader, 1, 1024, poDS->fp );
     poDS->pGrd = (NWT_GRID *) malloc( sizeof (NWT_GRID) );
 
     poDS->pGrd->fp = poDS->fp;
@@ -423,6 +434,11 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return (poDS);
 }
 
@@ -446,8 +462,10 @@ GDALRegister_NWT_GRC()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                  "frmt_various.html#northwood_grc" );
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grc" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = NWT_GRCDataset::Open;
+        poDriver->pfnIdentify = NWT_GRCDataset::Identify;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/northwood/grddataset.cpp b/frmts/northwood/grddataset.cpp
index f435d79..9ab781a 100644
--- a/frmts/northwood/grddataset.cpp
+++ b/frmts/northwood/grddataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: grddataset.cpp 18354 2009-12-20 10:42:15Z rouault $
+ * $Id: grddataset.cpp 23597 2011-12-18 23:29:48Z rouault $
  *
  * Project:  GRD Reader
  * Purpose:  GDAL driver for Northwood Grid Format
@@ -52,7 +52,7 @@ class NWT_GRDDataset:public GDALPamDataset
 {
   friend class NWT_GRDRasterBand;
 
-    FILE *fp;
+    VSILFILE *fp;
     GByte abyHeader[1024];
     NWT_GRID *pGrd;
     NWT_RGB ColorMap[4096];
@@ -63,6 +63,7 @@ class NWT_GRDDataset:public GDALPamDataset
     ~NWT_GRDDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
 
     CPLErr GetGeoTransform( double *padfTransform );
     const char *GetProjectionRef();
@@ -89,6 +90,8 @@ class NWT_GRDRasterBand:public GDALPamRasterBand
     virtual CPLErr IReadBlock( int, int, void * );
     virtual double GetNoDataValue( int *pbSuccess );
 
+    /* FIXME. I don't believe it is correct to advertize offset and */
+    /* scale because IReadBlock() already apply them. */
     virtual double GetOffset( int *pbSuccess = NULL );
     virtual CPLErr SetOffset( double dfNewValue );
     virtual double GetScale( int *pbSuccess = NULL );
@@ -135,10 +138,20 @@ NWT_GRDRasterBand::NWT_GRDRasterBand( NWT_GRDDataset * poDS, int nBand )
 
 double NWT_GRDRasterBand::GetNoDataValue( int *pbSuccess )
 {
-    if( pbSuccess != NULL )
-        *pbSuccess = TRUE;
+    if (nBand == 4)
+    {
+        if( pbSuccess != NULL )
+            *pbSuccess = TRUE;
 
-    return 0;                    //Northwood grid 0 is always null
+        return (float)-1.e37;
+    }
+    else
+    {
+        if( pbSuccess != NULL )
+            *pbSuccess = FALSE;
+
+        return 0;
+    }
 }
 
 GDALColorInterp NWT_GRDRasterBand::GetColorInterpretation()
@@ -167,10 +180,10 @@ CPLErr NWT_GRDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *pIma
     int i;
     unsigned short raw1;
 
-    VSIFSeek( poGDS->fp, 1024 + nRecordSize * nBlockYOff, SEEK_SET );
+    VSIFSeekL( poGDS->fp, 1024 + nRecordSize * nBlockYOff, SEEK_SET );
 
     pszRecord = (char *) CPLMalloc( nRecordSize );
-    VSIFRead( pszRecord, 1, nRecordSize, poGDS->fp );
+    VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp );
 
     if( nBand == 4 )                //Z values
     {
@@ -180,11 +193,11 @@ CPLErr NWT_GRDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *pIma
             CPL_LSBPTR16(&raw1);
             if( raw1 == 0 )
             {
-                ((float *)pImage)[i] = -1.e37;    // null value
+                ((float *)pImage)[i] = (float)-1.e37;    // null value
             }
             else
             {
-                ((float *)pImage)[i] = dfOffset + ((raw1 - 1) * dfScale);
+                ((float *)pImage)[i] = (float) (dfOffset + ((raw1 - 1) * dfScale));
             }
         }
     }
@@ -296,7 +309,7 @@ NWT_GRDDataset::~NWT_GRDDataset()
     nwtCloseGrid( pGrd );
 
     if( fp != NULL )
-        VSIFClose( fp );
+        VSIFCloseL( fp );
 
     if( pszProjection != NULL )
     {
@@ -343,21 +356,34 @@ const char *NWT_GRDDataset::GetProjectionRef()
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                              Identify()                              */
 /************************************************************************/
-GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
+
+int NWT_GRDDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
 /* -------------------------------------------------------------------- */
 /*  Look for the header                                                 */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
-        return NULL;
+    if( poOpenInfo->nHeaderBytes < 50 )
+        return FALSE;
 
     if( poOpenInfo->pabyHeader[0] != 'H' ||
         poOpenInfo->pabyHeader[1] != 'G' ||
         poOpenInfo->pabyHeader[2] != 'P' ||
-        poOpenInfo->pabyHeader[3] != 'C' || poOpenInfo->pabyHeader[4] != '1' )
-    return NULL;
+        poOpenInfo->pabyHeader[3] != 'C' ||
+        poOpenInfo->pabyHeader[4] != '1' )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    if( !Identify(poOpenInfo) )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
@@ -366,15 +392,22 @@ GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS = new NWT_GRDDataset();
 
-    poDS->fp = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
+    poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (poDS->fp == NULL)
+    {
+        delete poDS;
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    VSIFSeek( poDS->fp, 0, SEEK_SET );
-    VSIFRead( poDS->abyHeader, 1, 1024, poDS->fp );
+    VSIFSeekL( poDS->fp, 0, SEEK_SET );
+    VSIFReadL( poDS->abyHeader, 1, 1024, poDS->fp );
     poDS->pGrd = (NWT_GRID *) malloc(sizeof(NWT_GRID));
+
+    poDS->pGrd->fp = poDS->fp;
+
     if (!nwt_ParseHeader( poDS->pGrd, (char *) poDS->abyHeader ) ||
         !GDALCheckDatasetDimensions(poDS->pGrd->nXSide, poDS->pGrd->nYSide) )
     {
@@ -403,6 +436,11 @@ GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return (poDS);
 }
 
@@ -423,8 +461,10 @@ void GDALRegister_NWT_GRD()
                                  "Northwood Numeric Grid Format .grd/.tab" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#grd");
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = NWT_GRDDataset::Open;
+        poDriver->pfnIdentify = NWT_GRDDataset::Identify;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/northwood/northwood.cpp b/frmts/northwood/northwood.cpp
index 6e118d8..cab48ed 100644
--- a/frmts/northwood/northwood.cpp
+++ b/frmts/northwood/northwood.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: northwood.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: northwood.cpp 23577 2011-12-15 19:45:36Z rouault $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Format basic implementation
@@ -141,7 +141,7 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
     if (pGrd->iNumColorInflections > 32)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Corrupt header");
-        pGrd->iNumColorInflections = i;
+        pGrd->iNumColorInflections = (unsigned short)i;
         return FALSE;
     }
     
@@ -183,11 +183,11 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
 
     if( pGrd->cFormat & 0x80 )        // if is GRC load the Dictionary
     {
-        fseek( pGrd->fp,
+        VSIFSeekL( pGrd->fp,
                1024 + (pGrd->nXSide * pGrd->nYSide) * pGrd->nBitsPerPixel / 8,
                SEEK_SET );
 
-        if( !fread( &usTmp, 2, 1, pGrd->fp) )
+        if( !VSIFReadL( &usTmp, 2, 1, pGrd->fp) )
             return FALSE;
         CPL_LSBPTR16(&usTmp);
         pGrd->stClassDict =
@@ -206,7 +206,7 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
         {
             pGrd->stClassDict->stClassifedItem[usTmp] =
               (NWT_CLASSIFIED_ITEM *) calloc( sizeof(NWT_CLASSIFIED_ITEM), 1 );
-            if( !fread( &cTmp, 9, 1, pGrd->fp ) )
+            if( !VSIFReadL( &cTmp, 9, 1, pGrd->fp ) )
                 return FALSE;
             memcpy( (void *) &pGrd->stClassDict->
                     stClassifedItem[usTmp]->usPixVal, (void *) &cTmp[0], 2 );
@@ -228,7 +228,7 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
             if ( pGrd->stClassDict->stClassifedItem[usTmp]->usLen > 256)
                 return FALSE;
 
-            if( !fread( &pGrd->stClassDict->stClassifedItem[usTmp]->szClassName,
+            if( !VSIFReadL( &pGrd->stClassDict->stClassifedItem[usTmp]->szClassName,
                         pGrd->stClassDict->stClassifedItem[usTmp]->usLen,
                         1, pGrd->fp ) )
                 return FALSE;
@@ -294,7 +294,7 @@ int nwt_LoadColors( NWT_RGB * pMap, int mapSize, NWT_GRID * pGrd )
             {
                 // then we must be between i and i-1
                 linearColor( &sColor, &pGrd->stInflection[i - 1],
-                                      &pGrd->stInflection[i], pGrd->fZMin );
+                                      &pGrd->stInflection[i], pGrd->fZMax );
                 index = mapSize - 1;
                 createIP( index, sColor.r, sColor.g, sColor.b, pMap,
                            &nWarkerMark );
@@ -410,15 +410,15 @@ NWT_GRID *nwtOpenGrid( char *filename )
 {
     NWT_GRID *pGrd;
     char nwtHeader[1024];
-    FILE *fp;
+    VSILFILE *fp;
 
-    if( (fp = fopen( filename, "rb" )) == NULL )
+    if( (fp = VSIFOpenL( filename, "rb" )) == NULL )
     {
         fprintf( stderr, "\nCan't open %s\n", filename );
         return NULL;
     }
 
-    if( !fread( nwtHeader, 1024, 1, fp ) )
+    if( !VSIFReadL( nwtHeader, 1024, 1, fp ) )
         return NULL;
 
     if( nwtHeader[0] != 'H' ||
@@ -464,7 +464,7 @@ void nwtCloseGrid( NWT_GRID * pGrd )
         free( pGrd->stClassDict );
     }
     if( pGrd->fp )
-        fclose( pGrd->fp );
+        VSIFCloseL( pGrd->fp );
     free( pGrd );
         return;
 }
@@ -574,8 +574,8 @@ HLS RGBtoHLS( NWT_RGB rgb )
     B = rgb.b;
 
     /* calculate lightness */
-    cMax = MAX( MAX(R,G), B );
-    cMin = MIN( MIN(R,G), B );
+    cMax = (unsigned char) MAX( MAX(R,G), B );
+    cMin = (unsigned char) MIN( MIN(R,G), B );
     hls.l = (((cMax + cMin) * HLSMAX) + RGBMAX) / (2 * RGBMAX);
 
     if( cMax == cMin )
@@ -647,7 +647,7 @@ NWT_RGB HLStoRGB( HLS hls )
 
     if( hls.s == 0 )
     {                            /* achromatic case */
-        rgb.r = rgb.g = rgb.b = (hls.l * RGBMAX) / HLSMAX;
+        rgb.r = rgb.g = rgb.b = (unsigned char) ((hls.l * RGBMAX) / HLSMAX);
         if( hls.h != UNDEFINED )
         {
             /* ERROR */
@@ -663,12 +663,9 @@ NWT_RGB HLStoRGB( HLS hls )
         Magic1 = 2 * hls.l - Magic2;
 
         /* get RGB, change units from HLSMAX to RGBMAX */
-        rgb.r = (HueToRGB (Magic1, Magic2, hls.h + (HLSMAX / 3)) * RGBMAX +
-                 (HLSMAX / 2)) / HLSMAX;
-        rgb.g = (HueToRGB (Magic1, Magic2, hls.h) * RGBMAX + (HLSMAX / 2)) /
-                  HLSMAX;
-        rgb.b = (HueToRGB (Magic1, Magic2, hls.h - (HLSMAX / 3)) * RGBMAX +
-                 (HLSMAX / 2)) / HLSMAX;
+        rgb.r = (unsigned char) ((HueToRGB (Magic1, Magic2, hls.h + (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
+        rgb.g = (unsigned char) ((HueToRGB (Magic1, Magic2, hls.h) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
+        rgb.b = (unsigned char) ((HueToRGB (Magic1, Magic2, hls.h - (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX);
     }
 
     return rgb;
diff --git a/frmts/northwood/northwood.h b/frmts/northwood/northwood.h
index b0d5bfe..8ef16cb 100644
--- a/frmts/northwood/northwood.h
+++ b/frmts/northwood/northwood.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: northwood.h 18090 2009-11-23 22:47:06Z rouault $
+ * $Id: northwood.h 21898 2011-03-06 14:27:52Z rouault $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Technologies Grid format declarations
@@ -27,8 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
+#ifdef NOT_GDAL
 #include <stdio.h>
+#define VSILFILE    FILE
+#define VSIFOpenL   fopen
+#define VSIFCloseL  fclose
+#define VSIFSeekL   fseek
+#define VSIFReadL   fread
+#else
+#include "cpl_vsi.h"
+#endif
 
 #ifndef MAX
 #define MAX(a, b) (a > b ? a : b)
@@ -91,7 +99,7 @@ typedef struct
 typedef struct
 {
     char szFileName[256];
-    FILE *fp;
+    VSILFILE *fp;
     float fVersion;
     unsigned char cFormat;        //0x00 16 bit, 0x01 32 bit, 0x80 8 bit classifed, 0x81 16 bit classified
     unsigned int nBitsPerPixel;
diff --git a/frmts/openjpeg/frmt_jp2openjpeg.html b/frmts/openjpeg/frmt_jp2openjpeg.html
index 6b283b5..fee9b87 100644
--- a/frmts/openjpeg/frmt_jp2openjpeg.html
+++ b/frmts/openjpeg/frmt_jp2openjpeg.html
@@ -19,6 +19,9 @@ in comparison with the JPEG2000 driver based on Jasper library.</p>
 
 <p>The v2 branch also adds the capability to use the VSI Virtual File API, so the driver is able to read JPEG2000 compressed NITF files.</p>
 
+<p>Starting with GDAL 1.9.0, XMP metadata can be extracted from JPEG2000 files, and will be
+stored as XML raw content in the xml:XMP metadata domain.</p>
+
 <p>In creation, the driver doesn't support writing GeoJP2 nor GMLJP2.</p>
 
 <h2>Creation Options</h2>
diff --git a/frmts/openjpeg/openjpegdataset.cpp b/frmts/openjpeg/openjpegdataset.cpp
index 7e17cb5..9a68d99 100644
--- a/frmts/openjpeg/openjpegdataset.cpp
+++ b/frmts/openjpeg/openjpegdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: openjpegdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: openjpegdataset.cpp 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  JPEG2000 driver based on OpenJPEG library
  * Purpose:  JPEG2000 driver based on OpenJPEG library
@@ -44,7 +44,7 @@
 #include "cpl_string.h"
 #include "gdaljp2metadata.h"
 
-CPL_CVSID("$Id: openjpegdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: openjpegdataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
 
 /************************************************************************/
 /*                  JP2OpenJPEGDataset_ErrorCallback()                  */
@@ -121,12 +121,12 @@ static GDAL_OPENJPEG_BOOL JP2OpenJPEGDataset_Seek(OPJ_SIZE_T nBytes, void * pUse
 
 static OPJ_SIZE_T JP2OpenJPEGDataset_Skip(OPJ_SIZE_T nBytes, void * pUserData)
 {
-    int nOffset = VSIFTellL((VSILFILE*)pUserData) + nBytes;
+    vsi_l_offset nOffset = VSIFTellL((VSILFILE*)pUserData);
+    nOffset += nBytes;
 #ifdef DEBUG
-    CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Skip(%d -> %d)", nBytes, nOffset);
+    CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Skip(%d -> " CPL_FRMT_GUIB ")",
+             nBytes, (GUIntBig)nOffset);
 #endif
-    if (nOffset < 0)
-        return -1;
     VSIFSeekL((VSILFILE*)pUserData, nOffset, SEEK_SET);
     return nBytes;
 }
@@ -154,6 +154,7 @@ class JP2OpenJPEGDataset : public GDALPamDataset
 
     int         bLoadingOtherBands;
     int         bIs420;
+    OPJ_BYTE *  pFullBuffer;
 
   public:
                 JP2OpenJPEGDataset();
@@ -230,7 +231,7 @@ static CPL_INLINE GByte CLAMP_0_255(int val)
     else if (val > 255)
         return 255;
     else
-        return val;
+        return (GByte)val;
 }
 
 static void CopySrcToDst(int nWidthToRead, int nHeightToRead,
@@ -251,11 +252,11 @@ static void CopySrcToDst(int nWidthToRead, int nHeightToRead,
                 int Cb = pSrc[nHeightToRead * nWidthToRead + ((j/2) * (nWidthToRead/2) + i/2) ];
                 int Cr = pSrc[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * (nWidthToRead/2) + i/2) ];
                 if (nBand == 1)
-                    pDst[j * nBlockXSize + i] = CLAMP_0_255(Y + 1.402 * (Cr - 128));
+                    pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.402 * (Cr - 128)));
                 else if (nBand == 2)
-                    pDst[j * nBlockXSize + i] = CLAMP_0_255(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128));
+                    pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
                 else
-                    pDst[j * nBlockXSize + i] = CLAMP_0_255(Y + 1.772 * (Cb - 128));
+                    pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.772 * (Cb - 128)));
             }
         }
     }
@@ -286,6 +287,15 @@ CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     int nWidthToRead = MIN(nBlockXSize, poGDS->nRasterXSize - nBlockXOff * nBlockXSize);
     int nHeightToRead = MIN(nBlockYSize, poGDS->nRasterYSize - nBlockYOff * nBlockYSize);
+
+    if (poGDS->pFullBuffer)
+    {
+        CopySrcToDst(nWidthToRead, nHeightToRead, poGDS->pFullBuffer,
+                     nBlockXSize, nBlockYSize, nDataTypeSize, pImage,
+                     nBand, poGDS->bIs420);
+        return CE_None;
+    }
+
     if (nWidthToRead != nBlockXSize || nHeightToRead != nBlockYSize)
     {
         memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
@@ -423,7 +433,8 @@ CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                  nBand, poGDS->bIs420);
 
     /* Let's cache other bands */
-    if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands)
+    if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands &&
+        poGDS->nBands * nWidthToRead * nHeightToRead * nDataTypeSize <= GDALGetCacheMax64())
     {
         int iOtherBand;
 
@@ -457,7 +468,15 @@ CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         poGDS->bLoadingOtherBands = FALSE;
     }
 
-    CPLFree(pTempBuffer);
+    if (nBlockXSize == nRasterXSize && nBlockYSize == nRasterYSize &&
+        poGDS->nBands * nWidthToRead * nHeightToRead * nDataTypeSize > GDALGetCacheMax64())
+    {
+        poGDS->pFullBuffer = pTempBuffer;
+    }
+    else
+    {
+        CPLFree(pTempBuffer);
+    }
 
     opj_end_decompress(pCodec,pStream);
     opj_stream_destroy(pStream);
@@ -525,6 +544,7 @@ JP2OpenJPEGDataset::JP2OpenJPEGDataset()
     eCodecFormat = CODEC_UNKNOWN;
     eColorSpace = CLRSPC_UNKNOWN;
     bIs420 = FALSE;
+    pFullBuffer = NULL;
 }
 
 /************************************************************************/
@@ -545,6 +565,7 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
     }
     if( fp != NULL )
         VSIFCloseL( fp );
+    VSIFree(pFullBuffer);
 }
 
 /************************************************************************/
@@ -554,7 +575,10 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
 const char *JP2OpenJPEGDataset::GetProjectionRef()
 
 {
-    return( pszProjection );
+    if ( pszProjection && pszProjection[0] != 0 )
+        return( pszProjection );
+    else
+        return GDALPamDataset::GetProjectionRef();
 }
 
 /************************************************************************/
@@ -569,7 +593,7 @@ CPLErr JP2OpenJPEGDataset::GetGeoTransform( double * padfTransform )
         return CE_None;
     }
     else
-        return CE_Failure;
+        return GDALPamDataset::GetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
@@ -579,7 +603,10 @@ CPLErr JP2OpenJPEGDataset::GetGeoTransform( double * padfTransform )
 int JP2OpenJPEGDataset::GetGCPCount()
 
 {
-    return nGCPCount;
+    if( nGCPCount > 0 )
+        return nGCPCount;
+    else
+        return GDALPamDataset::GetGCPCount();
 }
 
 /************************************************************************/
@@ -592,7 +619,7 @@ const char *JP2OpenJPEGDataset::GetGCPProjection()
     if( nGCPCount > 0 )
         return pszProjection;
     else
-        return "";
+        return GDALPamDataset::GetGCPProjection();
 }
 
 /************************************************************************/
@@ -602,7 +629,10 @@ const char *JP2OpenJPEGDataset::GetGCPProjection()
 const GDAL_GCP *JP2OpenJPEGDataset::GetGCPs()
 
 {
-    return pasGCPList;
+    if( nGCPCount > 0 )
+        return pasGCPList;
+    else
+        return GDALPamDataset::GetGCPs();
 }
 
 /************************************************************************/
@@ -836,6 +866,13 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
             GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
     }
 
+    if (oJP2Geo.pszXMPMetadata)
+    {
+        char *apszMDList[2];
+        apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
+        apszMDList[1] = NULL;
+        poDS->SetMetadata(apszMDList, "xml:XMP");
+    }
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -1012,7 +1049,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         parameters.csty |= 0x04;
     parameters.cp_disto_alloc = 1;
     parameters.tcp_numlayers = 1;
-    parameters.tcp_rates[0] = dfRate;
+    parameters.tcp_rates[0] = (float) dfRate;
     parameters.cp_tx0 = 0;
     parameters.cp_ty0 = 0;
     parameters.tile_size_on = TRUE;
@@ -1184,12 +1221,12 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                             int R = pTempBuffer[j*nWidthToRead+i];
                             int G = pTempBuffer[nHeightToRead*nWidthToRead + j*nWidthToRead+i];
                             int B = pTempBuffer[2*nHeightToRead*nWidthToRead + j*nWidthToRead+i];
-                            int Y = 0.299 * R + 0.587 * G + 0.114 * B;
-                            int Cb = CLAMP_0_255(-0.1687 * R - 0.3313 * G + 0.5 * B  + 128);
-                            int Cr = CLAMP_0_255(0.5 * R - 0.4187 * G - 0.0813 * B  + 128);
-                            pYUV420Buffer[j*nWidthToRead+i] = Y;
-                            pYUV420Buffer[nHeightToRead * nWidthToRead + ((j/2) * ((nWidthToRead)/2) + i/2) ] = Cb;
-                            pYUV420Buffer[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * ((nWidthToRead)/2) + i/2) ] = Cr;
+                            int Y = (int) (0.299 * R + 0.587 * G + 0.114 * B);
+                            int Cb = CLAMP_0_255((int) (-0.1687 * R - 0.3313 * G + 0.5 * B  + 128));
+                            int Cr = CLAMP_0_255((int) (0.5 * R - 0.4187 * G - 0.0813 * B  + 128));
+                            pYUV420Buffer[j*nWidthToRead+i] = (GByte) Y;
+                            pYUV420Buffer[nHeightToRead * nWidthToRead + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cb;
+                            pYUV420Buffer[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cr;
                         }
                     }
 
@@ -1298,11 +1335,11 @@ void GDALRegister_JP2OpenJPEG()
 "       <Value>JP2</Value>"
 "       <Value>J2K</Value>"
 "   </Option>"
-"   <Option name='QUALITY' type='float' description='Quality. 0-100' default=25/>"
+"   <Option name='QUALITY' type='float' description='Quality. 0-100' default='25'/>"
 "   <Option name='REVERSIBLE' type='boolean' description='True if the compression is reversible' default='false'/>"
-"   <Option name='RESOLUTIONS' type='int' description='Number of resolutions. 1-7' default=6/>"
-"   <Option name='BLOCKXSIZE' type='int' description='Tile Width' default=1024/>"
-"   <Option name='BLOCKYSIZE' type='int' description='Tile Height' default=1024/>"
+"   <Option name='RESOLUTIONS' type='int' description='Number of resolutions. 1-7' default='6'/>"
+"   <Option name='BLOCKXSIZE' type='int' description='Tile Width' default='1024'/>"
+"   <Option name='BLOCKYSIZE' type='int' description='Tile Height' default='1024'/>"
 "   <Option name='PROGRESSION' type='string-select' default='LRCP'>"
 "       <Value>LRCP</Value>"
 "       <Value>RLCP</Value>"
diff --git a/frmts/ozi/ozidataset.cpp b/frmts/ozi/ozidataset.cpp
index bbf961e..9c75271 100644
--- a/frmts/ozi/ozidataset.cpp
+++ b/frmts/ozi/ozidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ozidataset.cpp 21424 2011-01-06 21:26:25Z rouault $
+ * $Id: ozidataset.cpp 21930 2011-03-11 13:27:22Z dron $
  *
  * Project:   OZF2 and OZFx3 binary files driver
  * Purpose:  GDALDataset driver for OZF2 and OZFx3 binary files.
@@ -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 21424 2011-01-06 21:26:25Z rouault $");
+CPL_CVSID("$Id: ozidataset.cpp 21930 2011-03-11 13:27:22Z dron $");
 
 CPL_C_START
 void    GDALRegister_OZI(void);
@@ -142,7 +142,7 @@ static int ReadInt(GByte**pptr)
     return nVal;
 }
 
-static int ReadShort(GByte**pptr)
+static short ReadShort(GByte**pptr)
 {
     short nVal;
     memcpy(&nVal, *pptr, 2);
@@ -155,16 +155,16 @@ static int ReadInt(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
 {
     int nVal;
     VSIFReadL(&nVal, 1, 4, fp);
-    if (bOzi3) OZIDecrypt(&nVal, 4, nKeyInit);
+    if (bOzi3) OZIDecrypt(&nVal, 4, (GByte) nKeyInit);
     CPL_LSBPTR32(&nVal);
     return nVal;
 }
 
-static int ReadShort(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
+static short ReadShort(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
 {
     short nVal;
     VSIFReadL(&nVal, 1, 2, fp);
-    if (bOzi3) OZIDecrypt(&nVal, 2, nKeyInit);
+    if (bOzi3) OZIDecrypt(&nVal, 2, (GByte) nKeyInit);
     CPL_LSBPTR16(&nVal);
     return nVal;
 }
@@ -806,7 +806,7 @@ void GDALRegister_OZI()
 
         poDriver->SetDescription( "OZI" );
         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "OZI" );
+                                   "OziExplorer Image File" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                    "frmt_ozi.html" );
 
diff --git a/frmts/pcidsk/GNUmakefile b/frmts/pcidsk/GNUmakefile
index 0e3e4d7..cccdf32 100644
--- a/frmts/pcidsk/GNUmakefile
+++ b/frmts/pcidsk/GNUmakefile
@@ -46,7 +46,13 @@ SDKOBJ 	=	\
 	cpcidskgcp2segment.o \
 	cpcidskbitmap.o \
 	cpcidsk_tex.o \
-	cpcidskapmodel.o
+	cpcidskapmodel.o \
+	clinksegment.o \
+	cpcidsktoutinmodel.o \
+	cpcidskbinarysegment.o \
+	cpcidsk_array.o \
+	cpcidskephemerissegment.o \
+	cpcidskads40model.o 
 
 else
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(PCIDSK_INCLUDE) $(CPPFLAGS)
diff --git a/frmts/pcidsk/frmt_pcidsk.html b/frmts/pcidsk/frmt_pcidsk.html
index c524684..311d177 100644
--- a/frmts/pcidsk/frmt_pcidsk.html
+++ b/frmts/pcidsk/frmt_pcidsk.html
@@ -10,54 +10,20 @@
 PCIDSK database file used by PCI EASI/PACE software for image analysis.
 It is supported for reading, and writing by GDAL.  All pixel data types, and
 data organizations (pixel interleaved, band interleaved, file interleaved
-and tiled) should be supported, but compressed PCIDSK files are not 
-supported.  Currently LUT and PCT segments are ignored.  Overall file, 
+and tiled) should be supported.  
+Currently LUT segments are ignored, but PCT segments should be treated 
+as associated with the bands.  Overall file, 
 and band specific metadata should be correctly associated with the image
 or bands.<P>
 
 Georeferencing is supported though there may be some limitations
-in support of datums and ellipsoids.   If GCP segments are present, the
-first will be used, and the rest ignored.<p>
+in support of datums and ellipsoids.   GCP segments are ignored.
+RPC segments will be returned as GDAL style RPC metadata.<p>
 
 Internal overview (pyramid) images will also be correctly read though newly
 requested overviews will be built externally as an .ovr file.<p>
 
-Vector segments are not supported by GDAL or OGR at this time. <p>
-
-<h2>Metadata</h2>
-
-Dataset:<p>
-
-<ul>
-	<li> <b>SOFTWARE</b>: Identifies the software system, and its
-	current version, that generated the PCIDSK database.<p>
-
-	<li> <b>FILE_ID</b>: Descriptive field identifying the file. Usually
-	supplied by the user at file creation time.<p>
-
-	<li> <b>GENERATING_FACILITY</b>: Descriptive field used to identify
-	which facility or institution produced this file.<p>
-
-	<li> <b>DESCRIPTION1</b>, <b>DESCRIPTION2</b>: Descriptive fields,
-	usually supplied by the user at file creation time, identifying the
-	contents of the file.<p>
-
-	<li> <b>DATE_OF_CREATION</b>, <b>DATE_OF_UPDATE</b>: Dates and times
-	of the file creation and last update. Formatted as 'hh:mmdd-mmm-yy'.<p>
-
-	<li> <b>GENERATING_FACILITY</b>: Descriptive field used to identify
-	which facility or institution produced this file.<p>
-</ul>
-
-Band:<p>
-<ul>
-	<li> <b>DATE_OF_CREATION</b>, <b>DATE_OF_UPDATE</b>: Dates and times
-	of the file creation and last update. Formatted as 'hh:mmdd-mmm-yy'.<p>
-
-	<li> <b>UNITS</b>: Data measurement units.<p>
-
-	<li> <b>HISTORYn</b> (<b>n</b>=1--8): Image channel history records.<p>
-</ul>
+Vector segments are supported by the OGR PCIDSK driver.<p>
 
 <h2>Creation Options</h2>
 
@@ -65,22 +31,24 @@ Note that PCIDSK files are always produced pixel interleaved, even though
 other organizations are supported for read.<p>
 
 <ul>
-	<li> <b>FILEDESC1="description"</b>, <b>FILEDESC2="description"</b>:
-	The first and second lines of descriptive text identifying the file,
-	each one should be maximum 64 character in size.<p>
-
-	<li> <b>BANDDESCn="description"</b>: Text (maximum 64 character in
-	size) describing contents of the specified band <B>n</B>. If no
-	description for band supplied by user, "Image band n" string will
-	be used by default. Band numbers start from 1.<p>
+
+<li> <b>INTERLEAVING=PIXEL/BAND/FILE/TILED</b>: sets the interleaving for
+the file raster data.  <p>
+
+<li> <b>COMPRESSION=NONE/RLE/JPEG</b>: Sets the compression to use.  Values 
+other than NONE (the default) may only be used with TILED interleaving.
+If JPEG is select it may include a quality value between 1 and 100 - eg. COMPRESSION=JPEG40.<p>
+
+<li> <b>TILESIZE=n</b>: When INTERLEAVING is TILED, the tilesize may be selected
+with this parameter - the default is 127 for 127x127.<p>
 </ul>
 
 <h2>See Also:</h2>
 
 <ul>
-<li> Implemented as <tt>gdal/frmts/pcidsk/pcidskdataset.cpp</tt>.<p>
+<li> Implemented as <tt>gdal/frmts/pcidsk/pcidskdataset2.cpp</tt>.<p>
 
-<li> <a href="">PCIDSK SDK</a>, including PCIDSK Database Reference Manual.<p>
+<li> <a href="http://home.gdal.org/projects/pcidsk/index.html">PCIDSK SDK</a><p>
 
 </ul>
 
diff --git a/frmts/pcidsk/makefile.vc b/frmts/pcidsk/makefile.vc
index 2448a7b..c5cd3d9 100644
--- a/frmts/pcidsk/makefile.vc
+++ b/frmts/pcidsk/makefile.vc
@@ -34,6 +34,7 @@ OBJ	=	pcidskdataset2.obj vsi_pcidsk_io.obj gdal_edb.obj \
 	sdk\core\pcidsk_pubutils.obj \
 	sdk\core\pcidsk_utils.obj \
 	sdk\core\sysvirtualfile.obj \
+	sdk\core\clinksegment.obj \
 	sdk\segment\cpcidskgeoref.obj \
 	sdk\segment\cpcidskpct.obj \
 	sdk\segment\cpcidsksegment.obj \
@@ -47,7 +48,12 @@ OBJ	=	pcidskdataset2.obj vsi_pcidsk_io.obj gdal_edb.obj \
 	sdk\segment\cpcidskgcp2segment.obj \
 	sdk\segment\cpcidskbitmap.obj \
 	sdk\segment\cpcidsk_tex.obj \
-	sdk\segment\cpcidskapmodel.obj
+	sdk\segment\cpcidskapmodel.obj \
+	sdk\segment\cpcidsktoutinmodel.obj \
+	sdk\segment\cpcidskbinarysegment.obj \
+	sdk\segment\cpcidsk_array.obj \
+	sdk\segment\cpcidskephemerissegment.obj \
+	sdk\segment\cpcidskads40model.obj
 	
 !ENDIF
             
diff --git a/frmts/pcidsk/pcidskdataset2.cpp b/frmts/pcidsk/pcidskdataset2.cpp
index e1d49df..ee5bbfb 100644
--- a/frmts/pcidsk/pcidskdataset2.cpp
+++ b/frmts/pcidsk/pcidskdataset2.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcidskdataset2.cpp 21466 2011-01-12 20:17:59Z warmerdam $
+ * $Id: pcidskdataset2.cpp 23650 2011-12-28 20:59:01Z rouault $
  *
  * Project:  PCIDSK Database File
  * Purpose:  Read/write PCIDSK Database File used by the PCI software, using
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: pcidskdataset2.cpp 21466 2011-01-12 20:17:59Z warmerdam $");
+CPL_CVSID("$Id: pcidskdataset2.cpp 23650 2011-12-28 20:59:01Z rouault $");
 
 using namespace PCIDSK;
 
@@ -63,11 +63,14 @@ class PCIDSK2Dataset : public GDALPamDataset
 
     static int           Identify( GDALOpenInfo * );
     static GDALDataset  *Open( GDALOpenInfo * );
+    static GDALDataset  *LLOpen( const char *pszFilename, PCIDSK::PCIDSKFile *,
+                                 GDALAccess eAccess );
     static GDALDataset  *Create( const char * pszFilename,
                                  int nXSize, int nYSize, int nBands,
                                  GDALDataType eType,
                                  char **papszParmList );
 
+    char              **GetFileList(void);
     CPLErr              GetGeoTransform( double * padfTransform );
     CPLErr              SetGeoTransform( double * );
     const char         *GetProjectionRef();
@@ -106,6 +109,8 @@ class PCIDSK2Band : public GDALPamRasterBand
     bool        bCheckedForColorTable;
     int         nPCTSegNumber;
 
+    char      **papszCategoryNames;
+
     void        Initialize();
 
   public:
@@ -123,11 +128,14 @@ class PCIDSK2Band : public GDALPamRasterBand
     virtual GDALColorTable *GetColorTable();
     virtual CPLErr SetColorTable( GDALColorTable * ); 
 
+    virtual void        SetDescription( const char * );
+
     CPLErr              SetMetadata( char **, const char * );
     char              **GetMetadata( const char* );
     CPLErr              SetMetadataItem(const char*,const char*,const char*);
     const char         *GetMetadataItem( const char*, const char*);
 
+    virtual char      **GetCategoryNames();
 };
 
 /************************************************************************/
@@ -162,7 +170,7 @@ PCIDSK2Band::PCIDSK2Band( PCIDSK2Dataset *poDS,
 
     if( !EQUALN(poChannel->GetDescription().c_str(),
                 "Contents Not Specified",20) )
-        SetDescription( poChannel->GetDescription().c_str() );
+        GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
 
 /* -------------------------------------------------------------------- */
 /*      Do we have overviews?                                           */
@@ -197,7 +205,10 @@ PCIDSK2Band::PCIDSK2Band( PCIDSKChannel *poChannel )
     if( poChannel->GetType() == CHN_BIT )
     {
         SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
-        SetDescription( poChannel->GetDescription().c_str() );
+
+        if( !EQUALN(poChannel->GetDescription().c_str(),
+                    "Contents Not Specified",20) )
+            GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
     }
 }
 
@@ -217,6 +228,8 @@ void PCIDSK2Band::Initialize()
     bCheckedForColorTable = false;
     poColorTable = NULL;
     nPCTSegNumber = -1;
+
+    papszCategoryNames = NULL;
 }
 
 /************************************************************************/
@@ -232,11 +245,106 @@ PCIDSK2Band::~PCIDSK2Band()
         apoOverviews.pop_back();
     }
     CSLDestroy( papszLastMDListValue );
+    CSLDestroy( papszCategoryNames );
 
     delete poColorTable;
 }
 
 /************************************************************************/
+/*                           SetDescription()                           */
+/************************************************************************/
+
+void PCIDSK2Band::SetDescription( const char *pszDescription )
+
+{
+    try 
+    {
+        poChannel->SetDescription( pszDescription );
+
+        if( !EQUALN(poChannel->GetDescription().c_str(),
+                    "Contents Not Specified",20) )
+            GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
+    }
+    catch( PCIDSKException ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", ex.what() );
+    }
+}
+
+/************************************************************************/
+/*                          GetCategoryNames()                          */
+/*                                                                      */
+/*      Offer category names from Class_*_ metadata.                    */
+/************************************************************************/
+
+char **PCIDSK2Band::GetCategoryNames()
+
+{
+    // already scanned?
+    if( papszCategoryNames != NULL )
+        return papszCategoryNames;
+
+    try 
+    {
+        std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
+        size_t i;
+        int nClassCount = 0;
+        static const int nMaxClasses = 10000;
+        papszCategoryNames = (char **) CPLCalloc(nMaxClasses+1, sizeof(char*));
+        
+        for( i=0; i < aosMDKeys.size(); i++ )
+        {
+            CPLString osKey = aosMDKeys[i];
+
+            // is this a "Class_n_name" keyword?
+
+            if( !EQUALN(osKey,"Class_",6) )
+                continue;
+
+            if( !EQUAL(osKey.c_str() + osKey.size() - 5, "_name") )
+                continue;
+
+            // Ignore unreasonable class values.
+            int iClass = atoi(osKey.c_str() + 6);
+
+            if( iClass < 0 || iClass > 10000 )
+                continue;
+
+            // Fetch the name.
+            CPLString osName  = poChannel->GetMetadataValue(osKey);
+            
+            // do we need to put in place dummy class names for missing values?
+            if( iClass >= nClassCount )
+            {
+                while( iClass >= nClassCount )
+                {
+                    papszCategoryNames[nClassCount++] = CPLStrdup("");
+                    papszCategoryNames[nClassCount] = NULL;
+                }
+            }
+
+            // Replace target category name.
+            CPLFree( papszCategoryNames[iClass] );
+            papszCategoryNames[iClass] = NULL;
+
+            papszCategoryNames[iClass] = CPLStrdup(osName);
+        }
+        
+        if( nClassCount == 0 )
+            return GDALPamRasterBand::GetCategoryNames();
+        else
+            return papszCategoryNames;
+    }
+    catch( PCIDSKException ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", ex.what() );
+        return NULL;
+    }
+}
+
+/************************************************************************/
 /*                         CheckForColorTable()                         */
 /************************************************************************/
 
@@ -250,6 +358,9 @@ bool PCIDSK2Band::CheckForColorTable()
 
     try 
     {
+/* -------------------------------------------------------------------- */
+/*      Try to find an appropriate PCT segment to use.                  */
+/* -------------------------------------------------------------------- */
         std::string osDefaultPCT = poChannel->GetMetadataValue("DEFAULT_PCT_REF");
         PCIDSKSegment *poPCTSeg = NULL;
 
@@ -295,6 +406,59 @@ bool PCIDSK2Band::CheckForColorTable()
                 poColorTable->SetColorEntry( i, &sEntry );
             }
         }
+
+/* -------------------------------------------------------------------- */
+/*      If we did not find an appropriate PCT segment, check for        */
+/*      Class_n color data from which to construct a color table.       */
+/* -------------------------------------------------------------------- */
+        std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
+        size_t i;
+        
+        for( i=0; i < aosMDKeys.size(); i++ )
+        {
+            CPLString osKey = aosMDKeys[i];
+
+            // is this a "Class_n_name" keyword?
+
+            if( !EQUALN(osKey,"Class_",6) )
+                continue;
+
+            if( !EQUAL(osKey.c_str() + osKey.size() - 6, "_Color") )
+                continue;
+
+            // Ignore unreasonable class values.
+            int iClass = atoi(osKey.c_str() + 6);
+
+            if( iClass < 0 || iClass > 10000 )
+                continue;
+
+            // Fetch and parse the RGB value "(RGB:red green blue)"
+            CPLString osRGB  = poChannel->GetMetadataValue(osKey);
+            int nRed, nGreen, nBlue;
+
+            if( !EQUALN(osRGB,"(RGB:",5) )
+                continue;
+
+            if( sscanf( osRGB.c_str() + 5, "%d %d %d", 
+                        &nRed, &nGreen, &nBlue ) != 3 )
+                continue;
+
+            // we have an entry - apply to the color table.
+            GDALColorEntry sEntry;
+
+            sEntry.c1 = (short) nRed;
+            sEntry.c2 = (short) nGreen;
+            sEntry.c3 = (short) nBlue;
+            sEntry.c4 = 255;
+
+            if( poColorTable == NULL )
+            {
+                CPLDebug( "PCIDSK", "Using Class_n_Color metadata for color table." );
+                poColorTable = new GDALColorTable();
+            }
+
+            poColorTable->SetColorEntry( iClass, &sEntry );
+        }
     }
     catch( PCIDSKException ex )
     {
@@ -383,9 +547,9 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
             GDALColorEntry sEntry;
 
             poCT->GetColorEntryAsRGB( i, &sEntry );
-            abyPCT[256 * 0 + i] = sEntry.c1;
-            abyPCT[256 * 1 + i] = sEntry.c2;
-            abyPCT[256 * 2 + i] = sEntry.c3;
+            abyPCT[256 * 0 + i] = (unsigned char) sEntry.c1;
+            abyPCT[256 * 1 + i] = (unsigned char) sEntry.c2;
+            abyPCT[256 * 2 + i] = (unsigned char) sEntry.c3;
         }
 
         PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>( 
@@ -740,6 +904,47 @@ PCIDSK2Dataset::~PCIDSK2Dataset()
 }
 
 /************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **PCIDSK2Dataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+    CPLString osBaseDir = CPLGetPath( GetDescription() );
+
+    try 
+    {
+        for( int nChan = 1; nChan <= poFile->GetChannels(); nChan++ )
+        {
+            PCIDSKChannel *poChannel = poFile->GetChannel( nChan );
+            CPLString osChanFilename;
+            uint64 image_offset, pixel_offset, line_offset;
+            bool little_endian;
+
+            poChannel->GetChanInfo( osChanFilename, image_offset, 
+                                    pixel_offset, line_offset, little_endian );
+
+            if( osChanFilename != "" )
+            {
+                papszFileList = 
+                    CSLAddString( papszFileList, 
+                                  CPLProjectRelativeFilename( osBaseDir, 
+                                                              osChanFilename ) );
+            }
+        }
+    
+        return papszFileList;
+    }
+    catch( PCIDSKException ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", ex.what() );
+        return papszFileList;
+    }
+}
+
+/************************************************************************/
 /*                             ProcessRPC()                             */
 /************************************************************************/
 
@@ -1384,10 +1589,13 @@ CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s", ex.what() );
+            CPLFree( panNewOverviewList );
             return CE_Failure;
         }
     }
 
+    CPLFree( panNewOverviewList );
+    panNewOverviewList = NULL;
 
     int iBand;
     for( iBand = 0; iBand < nListBands; iBand++ )
@@ -1450,6 +1658,8 @@ CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
         }
     }
 
+    CPLFree(papoOverviewBands);
+
     return eErr;
 }
 
@@ -1527,7 +1737,47 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
                       poOpenInfo->pszFilename );
             return NULL;
         }
-                               
+
+        /* Check if this is a vector-only PCIDSK file */
+        if( poFile->GetChannels() == 0 &&
+            poFile->GetSegment( PCIDSK::SEG_VEC, "" ) != NULL )
+        {
+            delete poFile;
+            return NULL;
+        }
+
+        return LLOpen( poOpenInfo->pszFilename, poFile, poOpenInfo->eAccess );
+    }
+/* -------------------------------------------------------------------- */
+/*      Trap exceptions.                                                */
+/* -------------------------------------------------------------------- */
+    catch( PCIDSKException ex )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", ex.what() );
+        return NULL;
+    }
+    catch( ... )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "PCIDSK::Create() failed, unexpected exception." );
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                               LLOpen()                               */
+/*                                                                      */
+/*      Low level variant of open that takes the preexisting            */
+/*      PCIDSKFile.                                                     */
+/************************************************************************/
+
+GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename, 
+                                     PCIDSK::PCIDSKFile *poFile,
+                                     GDALAccess eAccess )
+
+{
+    try {
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
@@ -1536,7 +1786,7 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
         poDS = new PCIDSK2Dataset();
 
         poDS->poFile = poFile;
-        poDS->eAccess = poOpenInfo->eAccess;
+        poDS->eAccess = eAccess;
         poDS->nRasterXSize = poFile->GetWidth();
         poDS->nRasterYSize = poFile->GetHeight();
 
@@ -1560,6 +1810,14 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
         for( iBand = 0; iBand < poFile->GetChannels(); iBand++ )
         {
+            PCIDSKChannel* poChannel = poFile->GetChannel( iBand + 1 );
+            if (poChannel->GetBlockWidth() <= 0 ||
+                poChannel->GetBlockHeight() <= 0)
+            {
+                delete poDS;
+                return NULL;
+            }
+
             poDS->SetBand( iBand+1, new PCIDSK2Band( poDS, poFile, iBand+1 ));
         }
 
@@ -1574,6 +1832,12 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
         {
             PCIDSKChannel *poChannel = 
                 dynamic_cast<PCIDSKChannel*>( poBitSeg );
+            if (poChannel->GetBlockWidth() <= 0 ||
+                poChannel->GetBlockHeight() <= 0)
+            {
+                delete poDS;
+                return NULL;
+            }
 
             poDS->SetBand( poDS->GetRasterCount()+1, 
                            new PCIDSK2Band( poChannel ) );
@@ -1589,13 +1853,13 @@ GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
-        poDS->SetDescription( poOpenInfo->pszFilename );
+        poDS->SetDescription( pszFilename );
         poDS->TryLoadXML();
 
 /* -------------------------------------------------------------------- */
 /*      Open overviews.                                                 */
 /* -------------------------------------------------------------------- */
-        poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+        poDS->oOvManager.Initialize( poDS, pszFilename );
         
         return( poDS );
     }
@@ -1681,11 +1945,26 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
         poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands, 
                                  &(aeChanTypes[0]), osOptions, 
                                  PCIDSK2GetInterfaces() );
-        delete poFile;
 
-        // TODO: should we ensure this driver gets used?
+/* -------------------------------------------------------------------- */
+/*      Apply band descriptions, if provided as creation options.       */
+/* -------------------------------------------------------------------- */
+        size_t i;
+
+        for( i = 0; papszParmList != NULL && papszParmList[i] != NULL; i++ )
+        {
+            if( EQUALN(papszParmList[i],"BANDDESC",8) )
+            {
+                int nBand = atoi(papszParmList[i] + 8 );
+                const char *pszDescription = strstr(papszParmList[i],"=");
+                if( pszDescription && nBand > 0 && nBand <= nBands )
+                {
+                    poFile->GetChannel(nBand)->SetDescription( pszDescription+1 );
+                }
+            }
+        }
 
-        return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+        return LLOpen( pszFilename, poFile, GA_Update );
     }
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions.                                                */
diff --git a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp
index 6b7f266..049c482 100644
--- a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.cpp
@@ -37,10 +37,12 @@
 #include "pcidsk_file.h"
 #include "core/pcidsk_utils.h"
 #include "core/cpcidskfile.h"
+#include "core/clinksegment.h"
 #include "channel/cbandinterleavedchannel.h"
 #include <cassert>
 #include <cstring>
 #include <cstdio>
+#include <cstdlib>
 
 using namespace PCIDSK;
 
@@ -82,8 +84,15 @@ CBandInterleavedChannel::CBandInterleavedChannel( PCIDSKBuffer &image_header,
 /* -------------------------------------------------------------------- */
     image_header.Get(64,64,filename);
 
+    filename = MassageLink( filename );
+
     if( filename.length() == 0 )
         file->GetIODetails( &io_handle_p, &io_mutex_p );
+
+    else
+        filename = MergeRelativePath( file->GetInterfaces()->io,
+                                      file->GetFilename(), 
+                                      filename );
 }
 
 /************************************************************************/
@@ -140,7 +149,8 @@ int CBandInterleavedChannel::ReadBlock( int block_index, void *buffer,
 /*      Get file access handles if we don't already have them.          */
 /* -------------------------------------------------------------------- */
     if( io_handle_p == NULL )
-        file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str() );
+        file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str(),
+                            file->GetUpdatable() );
 
 /* -------------------------------------------------------------------- */
 /*      If the imagery is packed, we can read directly into the         */
@@ -213,7 +223,8 @@ int CBandInterleavedChannel::WriteBlock( int block_index, void *buffer )
 /*      Get file access handles if we don't already have them.          */
 /* -------------------------------------------------------------------- */
     if( io_handle_p == NULL )
-        file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str() );
+        file->GetIODetails( &io_handle_p, &io_mutex_p, filename.c_str(),
+                            file->GetUpdatable() );
 
 /* -------------------------------------------------------------------- */
 /*      If the imagery is packed, we can read directly into the         */
@@ -272,3 +283,193 @@ int CBandInterleavedChannel::WriteBlock( int block_index, void *buffer )
     return 1;
 }
 
+/************************************************************************/
+/*                            GetChanInfo()                             */
+/************************************************************************/
+void CBandInterleavedChannel
+::GetChanInfo( std::string &filename_ret, uint64 &image_offset, 
+               uint64 &pixel_offset, uint64 &line_offset, 
+               bool &little_endian ) const
+
+{
+    image_offset = start_byte;
+    pixel_offset = this->pixel_offset;
+    line_offset = this->line_offset;
+    little_endian = (byte_order == 'S');
+
+/* -------------------------------------------------------------------- */
+/*      We fetch the filename from the header since it will be the      */
+/*      "clean" version without any paths.                              */
+/* -------------------------------------------------------------------- */
+    PCIDSKBuffer ih(64);
+    file->ReadFromFile( ih.buffer, ih_offset+64, 64 );
+
+    ih.Get(0,64,filename_ret);
+    filename_ret = MassageLink( filename_ret );
+}
+
+/************************************************************************/
+/*                            SetChanInfo()                             */
+/************************************************************************/
+
+void CBandInterleavedChannel
+::SetChanInfo( std::string filename, uint64 image_offset, 
+               uint64 pixel_offset, uint64 line_offset, 
+               bool little_endian )
+
+{
+    if( ih_offset == 0 )
+        ThrowPCIDSKException( "No Image Header available for this channel." );
+
+/* -------------------------------------------------------------------- */
+/*      Fetch the existing image header.                                */
+/* -------------------------------------------------------------------- */
+    PCIDSKBuffer ih(1024);
+
+    file->ReadFromFile( ih.buffer, ih_offset, 1024 );
+
+/* -------------------------------------------------------------------- */
+/*      If the linked filename is too long to fit in the 64             */
+/*      character IHi.2 field, then we need to use a link segment to    */
+/*      store the filename.                                             */
+/* -------------------------------------------------------------------- */
+    std::string IHi2_filename;
+    
+    if( filename.size() > 64 )
+    {
+        int link_segment;
+        
+        ih.Get( 64, 64, IHi2_filename );
+                
+        if( IHi2_filename.substr(0,3) == "LNK" )
+        {
+            link_segment = std::atoi( IHi2_filename.c_str() + 4 );
+        }
+        else
+        {
+            char link_filename[64];
+           
+            link_segment = 
+                file->CreateSegment( "Link    ", 
+                                     "Long external channel filename link.", 
+                                     SEG_SYS, 1 );
+
+            sprintf( link_filename, "LNK %4d", link_segment );
+            IHi2_filename = link_filename;
+        }
+
+        CLinkSegment *link = 
+            dynamic_cast<CLinkSegment*>( file->GetSegment( link_segment ) );
+        
+        if( link != NULL )
+        {
+            link->SetPath( filename );
+            link->Synchronize();
+        }
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      If we used to have a link segment but no longer need it, we     */
+/*      need to delete the link segment.                                */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        ih.Get( 64, 64, IHi2_filename );
+                
+        if( IHi2_filename.substr(0,3) == "LNK" )
+        {
+            int link_segment = std::atoi( IHi2_filename.c_str() + 4 );
+
+            file->DeleteSegment( link_segment );
+        }
+        
+        IHi2_filename = filename;
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      Update the image header.                                        */
+/* -------------------------------------------------------------------- */
+    // IHi.2
+    ih.Put( IHi2_filename.c_str(), 64, 64 );
+
+    // IHi.6.1
+    ih.Put( image_offset, 168, 16 );
+
+    // IHi.6.2
+    ih.Put( pixel_offset, 184, 8 );
+
+    // IHi.6.3
+    ih.Put( line_offset, 192, 8 );
+
+    // IHi.6.5
+    if( little_endian )
+        ih.Put( "S", 201, 1 );
+    else
+        ih.Put( "N", 201, 1 );
+
+    file->WriteToFile( ih.buffer, ih_offset, 1024 );
+
+/* -------------------------------------------------------------------- */
+/*      Update local configuration.                                     */
+/* -------------------------------------------------------------------- */
+    this->filename = MergeRelativePath( file->GetInterfaces()->io,
+                                        file->GetFilename(), 
+                                        filename );
+
+    start_byte = image_offset;
+    this->pixel_offset = pixel_offset;
+    this->line_offset = line_offset;
+    
+    if( little_endian )
+        byte_order = 'S';
+    else
+        byte_order = 'N';
+
+/* -------------------------------------------------------------------- */
+/*      Determine if we need byte swapping.                             */
+/* -------------------------------------------------------------------- */
+    unsigned short test_value = 1;
+
+    if( ((uint8 *) &test_value)[0] == 1 )
+        needs_swap = (byte_order != 'S');
+    else
+        needs_swap = (byte_order == 'S');
+    
+    if( pixel_type == CHN_8U )
+        needs_swap = 0;
+}
+
+/************************************************************************/
+/*                            MassageLink()                             */
+/*                                                                      */
+/*      Return the filename after applying translation of long          */
+/*      linked filenames using a link segment.                          */
+/************************************************************************/
+
+std::string CBandInterleavedChannel::MassageLink( std::string filename_in ) const
+
+{
+    if (filename_in.find("LNK") == 0)
+    {
+        std::string seg_str(filename_in, 4, 4);
+        unsigned int seg_num = std::atoi(seg_str.c_str());
+        
+        if (seg_num == 0)
+        {
+            throw PCIDSKException("Unable to find link segment. Link name: %s",
+                                  filename_in.c_str());
+        }
+        
+        CLinkSegment* link_seg = 
+            dynamic_cast<CLinkSegment*>(file->GetSegment(seg_num));
+        if (link_seg == NULL)
+        {
+            throw PCIDSKException("Failed to get Link Information Segment.");
+        }
+        
+        filename_in = link_seg->GetPath();
+    }
+
+    return filename_in;
+}
+
diff --git a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
index 070b482..92d4efb 100644
--- a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
+++ b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
@@ -63,6 +63,14 @@ namespace PCIDSK
             int xoff=-1, int yoff=-1,
             int xsize=-1, int ysize=-1 );
         virtual int WriteBlock( int block_index, void *buffer );
+
+        virtual void GetChanInfo( std::string &filename, uint64 &image_offset, 
+                                  uint64 &pixel_offset, uint64 &line_offset, 
+                                  bool &little_endian ) const;
+        virtual void SetChanInfo( std::string filename, uint64 image_offset, 
+                                  uint64 pixel_offset, uint64 line_offset, 
+                                  bool little_endian );
+
     private:
     // raw file layout - internal or external
         uint64    start_byte;
@@ -73,6 +81,8 @@ namespace PCIDSK
 
         void     **io_handle_p;
         Mutex    **io_mutex_p;
+
+        std::string MassageLink( std::string ) const;
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/channel/cexternalchannel.cpp b/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
index ae5d100..32654af 100644
--- a/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
@@ -38,6 +38,7 @@
 #include "core/pcidsk_utils.h"
 #include "core/cpcidskfile.h"
 #include "channel/cexternalchannel.h"
+#include "core/clinksegment.h"
 #include <cassert>
 #include <cstring>
 #include <cstdio>
@@ -72,6 +73,10 @@ CExternalChannel::CExternalChannel( PCIDSKBuffer &image_header,
 
     echannel = atoi(image_header.Get( 282, 8 ));
 
+    if (echannel == 0) {
+        echannel = channelnum;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Establish the file we will be accessing.                        */
 /* -------------------------------------------------------------------- */
@@ -636,3 +641,144 @@ int CExternalChannel::WriteBlock( int block_index, void *buffer )
     return 1;
 }
 
+/************************************************************************/
+/*                            GetEChanInfo()                            */
+/************************************************************************/
+void CExternalChannel::GetEChanInfo( std::string &filename, int &echannel,
+                                     int &exoff, int &eyoff, 
+                                     int &exsize, int &eysize ) const
+
+{
+    echannel = this->echannel;
+    exoff = this->exoff;
+    eyoff = this->eyoff;
+    exsize = this->exsize;
+    eysize = this->eysize;
+    filename = this->filename;
+}
+
+/************************************************************************/
+/*                            SetEChanInfo()                            */
+/************************************************************************/
+
+void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
+                                     int exoff, int eyoff, 
+                                     int exsize, int eysize )
+
+{
+    if( ih_offset == 0 )
+        ThrowPCIDSKException( "No Image Header available for this channel." );
+
+/* -------------------------------------------------------------------- */
+/*      Fetch the existing image header.                                */
+/* -------------------------------------------------------------------- */
+    PCIDSKBuffer ih(1024);
+
+    file->ReadFromFile( ih.buffer, ih_offset, 1024 );
+
+/* -------------------------------------------------------------------- */
+/*      If the linked filename is too long to fit in the 64             */
+/*      character IHi.2 field, then we need to use a link segment to    */
+/*      store the filename.                                             */
+/* -------------------------------------------------------------------- */
+    std::string IHi2_filename;
+    
+    if( filename.size() > 64 )
+    {
+        int link_segment;
+        
+        ih.Get( 64, 64, IHi2_filename );
+                
+        if( IHi2_filename.substr(0,3) == "LNK" )
+        {
+            link_segment = std::atoi( IHi2_filename.c_str() + 4 );
+        }
+        else
+        {
+            char link_filename[64];
+           
+            link_segment = 
+                file->CreateSegment( "Link    ", 
+                                     "Long external channel filename link.", 
+                                     SEG_SYS, 1 );
+
+            sprintf( link_filename, "LNK %4d", link_segment );
+            IHi2_filename = link_filename;
+        }
+
+        CLinkSegment *link = 
+            dynamic_cast<CLinkSegment*>( file->GetSegment( link_segment ) );
+        
+        if( link != NULL )
+        {
+            link->SetPath( filename );
+            link->Synchronize();
+        }
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      If we used to have a link segment but no longer need it, we     */
+/*      need to delete the link segment.                                */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        ih.Get( 64, 64, IHi2_filename );
+                
+        if( IHi2_filename.substr(0,3) == "LNK" )
+        {
+            int link_segment = std::atoi( IHi2_filename.c_str() + 4 );
+
+            file->DeleteSegment( link_segment );
+        }
+        
+        IHi2_filename = filename;
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      Update the image header.                                        */
+/* -------------------------------------------------------------------- */
+    // IHi.2
+    ih.Put( IHi2_filename.c_str(), 64, 64 );
+
+    // IHi.6.1
+    ih.Put( "", 168, 16 );
+
+    // IHi.6.2
+    ih.Put( "", 184, 8 );
+
+    // IHi.6.3
+    ih.Put( "", 192, 8 );
+
+    // IHi.6.5
+    ih.Put( "", 201, 1 );
+
+    // IHi.6.7
+    ih.Put( exoff, 250, 8 );
+
+    // IHi.6.8
+    ih.Put( eyoff, 258, 8 );
+
+    // IHi.6.9
+    ih.Put( exsize, 266, 8 );
+
+    // IHi.6.10
+    ih.Put( eysize, 274, 8 );
+
+    // IHi.6.11
+    ih.Put( echannel, 282, 8 );
+
+    file->WriteToFile( ih.buffer, ih_offset, 1024 );
+
+/* -------------------------------------------------------------------- */
+/*      Update local configuration.                                     */
+/* -------------------------------------------------------------------- */
+    this->filename = MergeRelativePath( file->GetInterfaces()->io,
+                                        file->GetFilename(), 
+                                        filename );
+
+    this->exoff = exoff;
+    this->eyoff = eyoff;
+    this->exsize = exsize;
+    this->eysize = eysize;
+    this->echannel = echannel;
+}
diff --git a/frmts/pcidsk/sdk/channel/cexternalchannel.h b/frmts/pcidsk/sdk/channel/cexternalchannel.h
index f8a41f1..00ab9e6 100644
--- a/frmts/pcidsk/sdk/channel/cexternalchannel.h
+++ b/frmts/pcidsk/sdk/channel/cexternalchannel.h
@@ -65,6 +65,12 @@ namespace PCIDSK
             int xsize=-1, int ysize=-1 );
         virtual int WriteBlock( int block_index, void *buffer );
 
+        virtual void GetEChanInfo( std::string &filename, int &echannel,
+                                   int &exoff, int &eyoff, 
+                                   int &exsize, int &eysize ) const;
+        virtual void SetEChanInfo( std::string filename, int echannel,
+                                   int exoff, int eyoff, 
+                                   int exsize, int eysize );
     private:
         int      exoff;
         int      eyoff;
@@ -81,7 +87,7 @@ namespace PCIDSK
 
         void     AccessDB() const;
 
-        std::string filename;
+        mutable std::string filename;
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp b/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp
index a0f0b4f..30e3f6c 100644
--- a/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cpcidskchannel.cpp
@@ -344,7 +344,6 @@ std::string CPCIDSKChannel::GetDescription()
     ih_1.Get(0,64,ret);
 
     return ret;
-
 }
 
 /************************************************************************/
@@ -461,3 +460,58 @@ void CPCIDSKChannel::PushHistory( const std::string &app,
 
     SetHistoryEntries( history_entries );
 }
+
+/************************************************************************/
+/*                            GetChanInfo()                             */
+/************************************************************************/
+void CPCIDSKChannel::GetChanInfo( std::string &filename, uint64 &image_offset, 
+                                  uint64 &pixel_offset, uint64 &line_offset, 
+                                  bool &little_endian ) const
+
+{
+    image_offset = 0;
+    pixel_offset = 0;
+    line_offset = 0;
+    little_endian = true;
+    filename = "";
+}
+
+/************************************************************************/
+/*                            SetChanInfo()                             */
+/************************************************************************/
+
+void CPCIDSKChannel::SetChanInfo( std::string filename, uint64 image_offset, 
+                                  uint64 pixel_offset, uint64 line_offset, 
+                                  bool little_endian )
+
+{
+    ThrowPCIDSKException( "Attempt to SetChanInfo() on a channel that is not FILE interleaved." );
+}
+
+/************************************************************************/
+/*                            GetEChanInfo()                            */
+/************************************************************************/
+void CPCIDSKChannel::GetEChanInfo( std::string &filename, int &echannel,
+                                   int &exoff, int &eyoff, 
+                                   int &exsize, int &eysize ) const
+
+{
+    echannel = 0;
+    exoff = 0;
+    eyoff = 0;
+    exsize = 0;
+    eysize = 0;
+    filename = "";
+}
+
+/************************************************************************/
+/*                            SetEChanInfo()                            */
+/************************************************************************/
+
+void CPCIDSKChannel::SetEChanInfo( std::string filename, int echannel,
+                                   int exoff, int eyoff, 
+                                   int exsize, int eysize )
+
+{
+    ThrowPCIDSKException( "Attempt to SetEChanInfo() on a channel that is not FILE interleaved." );
+}
diff --git a/frmts/pcidsk/sdk/channel/cpcidskchannel.h b/frmts/pcidsk/sdk/channel/cpcidskchannel.h
index 20b052f..308ca77 100644
--- a/frmts/pcidsk/sdk/channel/cpcidskchannel.h
+++ b/frmts/pcidsk/sdk/channel/cpcidskchannel.h
@@ -92,6 +92,19 @@ namespace PCIDSK
         virtual void PushHistory(const std::string &app,
                                  const std::string &message);
 
+        virtual void GetChanInfo( std::string &filename, uint64 &image_offset, 
+                                  uint64 &pixel_offset, uint64 &line_offset, 
+                                  bool &little_endian ) const;
+        virtual void SetChanInfo( std::string filename, uint64 image_offset, 
+                                  uint64 pixel_offset, uint64 line_offset, 
+                                  bool little_endian );
+        virtual void GetEChanInfo( std::string &filename, int &echannel,
+                                   int &exoff, int &eyoff, 
+                                   int &exsize, int &eysize ) const;
+        virtual void SetEChanInfo( std::string filename, int echannel,
+                                   int exoff, int eyoff, 
+                                   int exsize, int eysize );
+
     // Just for CPCIDSKFile.
         void      InvalidateOverviewInfo();
 
diff --git a/frmts/pcidsk/sdk/channel/ctiledchannel.cpp b/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
index cf21bc5..4bd0c31 100644
--- a/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
@@ -56,9 +56,6 @@ CTiledChannel::CTiledChannel( PCIDSKBuffer &image_header,
         : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
 
 {
-    tile_info_dirty = false;
-    tile_info_loaded = false;
-
 /* -------------------------------------------------------------------- */
 /*      Establish the virtual file we will be accessing.                */
 /* -------------------------------------------------------------------- */
@@ -141,6 +138,23 @@ void CTiledChannel::EstablishAccess() const
     }
 
 /* -------------------------------------------------------------------- */
+/*      Compute information on the tiles.                               */
+/* -------------------------------------------------------------------- */
+    tiles_per_row = (width + block_width - 1) / block_width;
+    tiles_per_col = (height + block_height - 1) / block_height;
+    tile_count = tiles_per_row * tiles_per_col;
+
+/* -------------------------------------------------------------------- */
+/*      Resize our tile info cache.                                     */
+/* -------------------------------------------------------------------- */
+    int tile_block_info_count = 
+        (tile_count + tile_block_size - 1) / tile_block_size;
+
+    tile_offsets.resize( tile_block_info_count );
+    tile_sizes.resize( tile_block_info_count );
+    tile_info_dirty.resize( tile_block_info_count, false );
+
+/* -------------------------------------------------------------------- */
 /*      Establish byte swapping.  Tiled data files are always big       */
 /*      endian, regardless of what the headers might imply.             */
 /* -------------------------------------------------------------------- */
@@ -153,40 +167,136 @@ void CTiledChannel::EstablishAccess() const
 }
 
 /************************************************************************/
-/*                        EstablishTileAccess()                         */
+/*                         LoadTileInfoBlock()                          */
 /************************************************************************/
 
-void CTiledChannel::EstablishTileAccess() const
+void CTiledChannel::LoadTileInfoBlock( int block )
 
 {
-    if( tile_info_loaded )
-        return;
-
-    EstablishAccess();
+    assert( tile_offsets[block].size() == 0 );
 
 /* -------------------------------------------------------------------- */
-/*      Extract the tile map                                            */
+/*      How many tiles in this block?                                   */
 /* -------------------------------------------------------------------- */
-    int tiles_per_row = (width + block_width - 1) / block_width;
-    int tiles_per_col = (height + block_height - 1) / block_height;
-    int tile_count = tiles_per_row * tiles_per_col;
-    int i;
+    int tiles_in_block = tile_block_size;
 
-    tile_offsets.resize( tile_count );
-    tile_sizes.resize( tile_count );
+    if( block * tile_block_size + tiles_in_block > tile_count )
+        tiles_in_block = tile_count - block * tile_block_size;
 
-    PCIDSKBuffer tmap( tile_count * 20 );
+/* -------------------------------------------------------------------- */
+/*      Resize the vectors for this block.                              */
+/* -------------------------------------------------------------------- */
+    tile_offsets[block].resize( tiles_in_block );
+    tile_sizes[block].resize( tiles_in_block );
 
-    vfile->ReadFromFile( tmap.buffer, 128, tile_count*20 );
+/* -------------------------------------------------------------------- */
+/*      Read the offset and size data from disk.                        */
+/* -------------------------------------------------------------------- */
+    PCIDSKBuffer offset_map( tiles_in_block * 12 + 1 );
+    PCIDSKBuffer size_map( tiles_in_block * 8 + 1 );
+
+    vfile->ReadFromFile( offset_map.buffer, 
+                         128 + block * tile_block_size * 12, 
+                         tiles_in_block * 12 );
+    vfile->ReadFromFile( size_map.buffer, 
+                         128 + tile_count * 12 + block * tile_block_size * 8,
+                         tiles_in_block * 8 );
     
-    for( i = 0; i < tile_count; i++ )
+    for( int i = 0; i < tiles_in_block; i++ )
     {
-        tile_offsets[i] = tmap.GetUInt64( i*12 + 0, 12 );
-        tile_sizes[i] = tmap.GetInt( tile_count*12 + i*8, 8 );
+        char chSaved;
+        char *target = offset_map.buffer + i*12;
+
+        chSaved = target[12];
+        target[12] = '\0';
+        tile_offsets[block][i] = atouint64(target);
+        target[12] = chSaved;
+
+        target = size_map.buffer + i*8;
+        chSaved = target[8];
+        target[8] = '\0';
+        tile_sizes[block][i] = atoi(target);
+        target[8] = chSaved;
     }
+}
 
-    tile_info_loaded = true;
-    tile_info_dirty = false;
+/************************************************************************/
+/*                         SaveTileInfoBlock()                          */
+/************************************************************************/
+
+void CTiledChannel::SaveTileInfoBlock( int block )
+
+{
+    assert( tile_offsets[block].size() != 0 );
+    int tiles_in_block = tile_offsets[block].size();
+
+/* -------------------------------------------------------------------- */
+/*      Write the offset and size data to disk.                         */
+/* -------------------------------------------------------------------- */
+    PCIDSKBuffer offset_map( tiles_in_block * 12 + 1 );
+    PCIDSKBuffer size_map( tiles_in_block * 8 + 1 );
+
+    for( int i = 0; i < tiles_in_block; i++ )
+    {
+        if( tile_offsets[block][i] == (uint64) -1 
+            || tile_offsets[block][i] == 0 )
+            offset_map.Put( -1, i*12, 12 );
+        else
+            offset_map.Put( tile_offsets[block][i], i*12, 12 );
+
+        size_map.Put( tile_sizes[block][i], i*8, 8 );
+    }
+
+    vfile->WriteToFile( offset_map.buffer, 
+                        128 + block * tile_block_size * 12, 
+                        tiles_in_block * 12 );
+    vfile->WriteToFile( size_map.buffer, 
+                        128 + tile_count * 12 + block * tile_block_size * 8,
+                        tiles_in_block * 8 );
+
+    tile_info_dirty[block] = false;
+}
+
+/************************************************************************/
+/*                            GetTileInfo()                             */
+/*                                                                      */
+/*      Fetch the tile offset and size for the indicated tile.          */
+/************************************************************************/
+
+void CTiledChannel::GetTileInfo( int tile_index, uint64 &offset, int &size )
+
+{
+    int block = tile_index / tile_block_size;
+    int index_within_block = tile_index - block * tile_block_size;
+
+    if( tile_offsets[block].size() == 0 )
+        LoadTileInfoBlock( block );
+
+    offset = tile_offsets[block][index_within_block];
+    size = tile_sizes[block][index_within_block];
+}
+
+/************************************************************************/
+/*                            SetTileInfo()                             */
+/************************************************************************/
+
+void CTiledChannel::SetTileInfo( int tile_index, uint64 offset, int size )
+
+{
+    int block = tile_index / tile_block_size;
+    int index_within_block = tile_index - block * tile_block_size;
+
+    if( tile_offsets[block].size() == 0 )
+        LoadTileInfoBlock( block );
+
+    if( offset != tile_offsets[block][index_within_block]
+        || size != tile_sizes[block][index_within_block] )
+    {
+        tile_offsets[block][index_within_block] = offset;
+        tile_sizes[block][index_within_block] = size;
+        
+        tile_info_dirty[block] = true;
+    }
 }
 
 /************************************************************************/
@@ -198,26 +308,17 @@ void CTiledChannel::EstablishTileAccess() const
 void CTiledChannel::Synchronize()
 
 {
-    if( !tile_info_dirty )
+    if( tile_info_dirty.size() == 0 )
         return;
 
-    int tiles_per_row = (width + block_width - 1) / block_width;
-    int tiles_per_col = (height + block_height - 1) / block_height;
-    int tile_count = tiles_per_row * tiles_per_col;
     int i;
 
-    PCIDSKBuffer tmap( tile_count * 20 );
-
-    for( i = 0; i < tile_count; i++ )
+    for( i = 0; i < (int) tile_info_dirty.size(); i++ )
     {
-        if( tile_offsets[i] == (uint64) -1 || tile_offsets[i] == 0 )
-            tmap.Put( -1, i*12 + 0, 12 );
-        else
-            tmap.Put( tile_offsets[i], i*12 + 0, 12 );
-        tmap.Put( tile_sizes[i], tile_count*12 + i*8, 8 );
+        if( tile_info_dirty[i] )
+            SaveTileInfoBlock( i );
     }
 
-    vfile->WriteToFile( tmap.buffer, 128, tile_count*20 );
     vfile->Synchronize();
 }
 
@@ -230,9 +331,6 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
                               int xsize, int ysize )
 
 {
-    if( !tile_info_loaded )
-        EstablishTileAccess();
-
     int pixel_size = DataTypeSize(GetType());
 
 /* -------------------------------------------------------------------- */
@@ -257,7 +355,7 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
             xoff, yoff, xsize, ysize );
     }
 
-    if( block_index < 0 || block_index >= (int) tile_offsets.size() )
+    if( block_index < 0 || block_index >= tile_count )
     {
         ThrowPCIDSKException( "Requested non-existant block (%d)", 
                               block_index );
@@ -266,7 +364,12 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
 /* -------------------------------------------------------------------- */
 /*      Does this tile exist?  If not return a zeroed buffer.           */
 /* -------------------------------------------------------------------- */
-    if( tile_sizes[block_index] == 0 )
+    uint64 tile_offset;
+    int    tile_size;
+
+    GetTileInfo( block_index, tile_offset, tile_size );
+
+    if( tile_size == 0 )
     {
         memset( buffer, 0, GetBlockWidth() * GetBlockHeight() * pixel_size );
         return 1;
@@ -278,12 +381,11 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
 /* -------------------------------------------------------------------- */
     if( xoff == 0 && xsize == GetBlockWidth() 
         && yoff == 0 && ysize == GetBlockHeight() 
-        && tile_sizes[block_index] == xsize * ysize * pixel_size 
+        && tile_size == xsize * ysize * pixel_size 
         && compression == "NONE" )
     {
-        vfile->ReadFromFile( buffer, 
-                             tile_offsets[block_index], 
-                             tile_sizes[block_index] );
+        vfile->ReadFromFile( buffer, tile_offset, tile_size );
+
         // Do byte swapping if needed.
         if( needs_swap )
             SwapPixels( buffer, pixel_type, xsize * ysize );
@@ -303,7 +405,7 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
         {
             vfile->ReadFromFile( ((uint8 *) buffer) 
                                  + iy * xsize * pixel_size,
-                                 tile_offsets[block_index] 
+                                 tile_offset 
                                  + ((iy+yoff)*block_width + xoff) * pixel_size,
                                  xsize * pixel_size );
         }
@@ -318,12 +420,10 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
 /* -------------------------------------------------------------------- */
 /*      Load the whole compressed data into a working buffer.           */
 /* -------------------------------------------------------------------- */
-    PCIDSKBuffer oCompressedData( tile_sizes[block_index] );
+    PCIDSKBuffer oCompressedData( tile_size );
     PCIDSKBuffer oUncompressedData( pixel_size * block_width * block_height );
 
-    vfile->ReadFromFile( oCompressedData.buffer, 
-                         tile_offsets[block_index], 
-                         tile_sizes[block_index] );
+    vfile->ReadFromFile( oCompressedData.buffer, tile_offset, tile_size );
     
 /* -------------------------------------------------------------------- */
 /*      Handle decompression.                                           */
@@ -405,9 +505,6 @@ bool CTiledChannel::IsTileEmpty(void *buffer) const
 int CTiledChannel::WriteBlock( int block_index, void *buffer )
 
 {
-    if( !tile_info_loaded )
-        EstablishTileAccess();
-
     if( !file->GetUpdatable() )
         throw PCIDSKException( "File not open for update in WriteBlock()" );
 
@@ -416,26 +513,32 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
     int pixel_size = DataTypeSize(GetType());
     int pixel_count = GetBlockWidth() * GetBlockHeight();
 
-    if( block_index < 0 || block_index >= (int) tile_offsets.size() )
+    if( block_index < 0 || block_index >= tile_count )
     {
         ThrowPCIDSKException( "Requested non-existant block (%d)", 
                               block_index );
     }
 
 /* -------------------------------------------------------------------- */
+/*      Fetch existing tile offset and size.                            */
+/* -------------------------------------------------------------------- */
+    uint64 tile_offset;
+    int    tile_size;
+
+    GetTileInfo( block_index, tile_offset, tile_size );
+
+/* -------------------------------------------------------------------- */
 /*      The simpliest case it an uncompressed direct and complete       */
 /*      tile read into the destination buffer.                          */
 /* -------------------------------------------------------------------- */
     if( compression == "NONE" 
-        && tile_sizes[block_index] == pixel_count * pixel_size )
+        && tile_size == pixel_count * pixel_size )
     {
         // Do byte swapping if needed.
         if( needs_swap )
             SwapPixels( buffer, pixel_type, pixel_count );
 
-        vfile->WriteToFile( buffer, 
-                            tile_offsets[block_index], 
-                            tile_sizes[block_index] );
+        vfile->WriteToFile( buffer, tile_offset, tile_size );
 
         if( needs_swap )
             SwapPixels( buffer, pixel_type, pixel_count );
@@ -443,7 +546,7 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
         return 1;
     }
 
-    if ((int)tile_offsets[block_index] == -1)
+    if ((int64)tile_offset == -1)
     {
         // Check if the tile is empty. If it is, we can skip writing it,
         // unless the tile is already dirty.
@@ -491,12 +594,12 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
 /* -------------------------------------------------------------------- */
 /*      If this fits in the existing space, just write it directly.     */
 /* -------------------------------------------------------------------- */
-    if( oCompressedData.buffer_size <= tile_sizes[block_index] )
+    if( oCompressedData.buffer_size <= tile_size )
     {
-        vfile->WriteToFile( oCompressedData.buffer,
-                            tile_offsets[block_index], 
-                            oCompressedData.buffer_size );
-        tile_sizes[block_index] = oCompressedData.buffer_size;
+        vfile->WriteToFile( oCompressedData.buffer, tile_offset, tile_size );
+
+        tile_size = oCompressedData.buffer_size;
+        SetTileInfo( block_index, tile_offset, tile_size );
     }
 
 /* -------------------------------------------------------------------- */
@@ -509,13 +612,9 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
         vfile->WriteToFile( oCompressedData.buffer, 
                             new_offset, oCompressedData.buffer_size );
 
-        tile_offsets[block_index] = new_offset;
-        tile_sizes[block_index] = oCompressedData.buffer_size;
-
+        SetTileInfo( block_index, new_offset, oCompressedData.buffer_size );
     }
 
-    tile_info_dirty = true;
-
     return 1;
 }
 
@@ -708,7 +807,7 @@ void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
                 if( oCompressedData.buffer_size < dst_offset + pixel_size+1 )
                     oCompressedData.SetSize( oCompressedData.buffer_size*2+100);
 
-                oCompressedData.buffer[dst_offset++] = count+128;
+                oCompressedData.buffer[dst_offset++] = (char) (count+128);
 
                 for( i = 0; i < pixel_size; i++ )
                     oCompressedData.buffer[dst_offset++] = src[src_offset+i];
@@ -759,7 +858,7 @@ void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
                    < dst_offset + count*pixel_size+1 )
                 oCompressedData.SetSize( oCompressedData.buffer_size*2+100 );
 
-            oCompressedData.buffer[dst_offset++] = count;
+            oCompressedData.buffer[dst_offset++] = (char) count;
             memcpy( oCompressedData.buffer + dst_offset, 
                     src + src_offset, 
                     count * pixel_size );
diff --git a/frmts/pcidsk/sdk/channel/ctiledchannel.h b/frmts/pcidsk/sdk/channel/ctiledchannel.h
index a6ee9f8..8263ffc 100644
--- a/frmts/pcidsk/sdk/channel/ctiledchannel.h
+++ b/frmts/pcidsk/sdk/channel/ctiledchannel.h
@@ -74,18 +74,13 @@ namespace PCIDSK
         
     private:
         int                      image;
-
-        mutable SysVirtualFile          *vfile;
-
-        mutable std::string              compression;
-
-        mutable std::vector<uint64>      tile_offsets;
-        mutable std::vector<int>         tile_sizes;
-        mutable bool                     tile_info_loaded;
-        mutable bool                     tile_info_dirty;
-
+        mutable int              tile_count;
+        mutable int              tiles_per_row;
+        mutable int              tiles_per_col;
+        mutable SysVirtualFile  *vfile;
+        mutable std::string      compression;
+        
         void                     EstablishAccess() const;
-        void                     EstablishTileAccess() const;
         void                     RLEDecompressBlock( PCIDSKBuffer &oCompressed,
                                                      PCIDSKBuffer &oDecompressed );
         void                     RLECompressBlock( PCIDSKBuffer &oUncompressed,
@@ -97,6 +92,18 @@ namespace PCIDSK
 
         bool                     IsTileEmpty(void* buffer) const;
 
+        // managed paged list of tile offsets and sizes.
+        void                     GetTileInfo( int tile_index,
+                                              uint64 &offset, int &size );
+        void                     SetTileInfo( int tile_index,
+                                              uint64 offset, int size );
+        void                     LoadTileInfoBlock( int tile_info_block );
+        void                     SaveTileInfoBlock( int tile_info_block );
+
+        static const int                           tile_block_size = 4096;
+        mutable std::vector< std::vector<uint64> > tile_offsets;
+        mutable std::vector< std::vector<int> >    tile_sizes;
+        mutable std::vector<bool>                  tile_info_dirty;
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/core/clinksegment.cpp b/frmts/pcidsk/sdk/core/clinksegment.cpp
new file mode 100644
index 0000000..02627e5
--- /dev/null
+++ b/frmts/pcidsk/sdk/core/clinksegment.cpp
@@ -0,0 +1,130 @@
+/******************************************************************************
+ *
+ * Purpose:  Implementation of the CLinkSegment class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 "core/clinksegment.h"
+#include "segment/cpcidsksegment.h"
+#include "core/pcidsk_utils.h"
+#include "pcidsk_exception.h"
+
+#include <vector>
+#include <string>
+#include <cassert>
+#include <cstring>
+#include <algorithm>
+#include <functional>
+
+using namespace PCIDSK;
+
+CLinkSegment::CLinkSegment(PCIDSKFile *file, 
+                           int segment,
+                           const char *segment_pointer) :
+    CPCIDSKSegment(file, segment, segment_pointer), 
+    loaded_(false), modified_(false)
+{
+    Load();
+}
+
+
+CLinkSegment::~CLinkSegment()
+{
+}
+
+// Load the contents of the segment
+void CLinkSegment::Load()
+{
+    // Check if we've already loaded the segment into memory
+    if (loaded_) {
+        return;
+    }
+    
+    assert(data_size - 1024 == 1 * 512);
+    
+    seg_data.SetSize(data_size - 1024); // should be 1 * 512
+    
+    ReadFromFile(seg_data.buffer, 0, data_size - 1024);
+    
+    if (std::strncmp(seg_data.buffer, "SysLinkF", 8)) 
+    {
+        seg_data.Put("SysLinkF",0,8);
+        return;
+    }
+    
+    path = std::string(&seg_data.buffer[8]);
+    std::string::reverse_iterator first_non_space = 
+        std::find_if(path.rbegin(), path.rend(), 
+                     std::bind2nd(std::not_equal_to<char>(), ' '));
+
+    *(--first_non_space) = '\0';
+
+    
+    // We've now loaded the structure up with data. Mark it as being loaded 
+    // properly.
+    loaded_ = true;
+    
+}
+
+void CLinkSegment::Write(void)
+{
+    //We are not writing if nothing was loaded.
+    if (!modified_) {
+        return;
+    }
+      
+    seg_data.Put("SysLinkF",0,8);
+    seg_data.Put(path.c_str(), 8, path.size(), true);
+
+    WriteToFile(seg_data.buffer, 0, data_size-1024);
+    modified_ = false;
+}
+
+std::string CLinkSegment::GetPath(void) const
+{
+    return path;
+}
+
+void CLinkSegment::SetPath(const std::string& oPath)
+{
+    if(oPath.size() < 504)
+    {
+        path = oPath;
+        modified_ = true;
+    }
+    else
+    {
+        throw PCIDSKException("The size of the path cannot be"
+                              " bigger than 504 characters.");
+    }
+}
+
+void CLinkSegment::Synchronize()
+{
+    if(modified_)
+    {
+        this->Write();
+    }
+}
+
diff --git a/frmts/pcidsk/sdk/core/clinksegment.h b/frmts/pcidsk/sdk/core/clinksegment.h
new file mode 100644
index 0000000..03448de
--- /dev/null
+++ b/frmts/pcidsk/sdk/core/clinksegment.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * Purpose: Support for reading and manipulating PCIDSK link info Segments
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
+#define __INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
+
+#include "segment/cpcidsksegment.h"
+#include "pcidsk_buffer.h"
+ 
+namespace PCIDSK {
+    class PCIDSKFile;
+    
+    class CLinkSegment : public CPCIDSKSegment
+    {
+    public:
+        CLinkSegment(PCIDSKFile *file, int segment,const char *segment_pointer);
+        ~CLinkSegment();
+        
+        // Get path
+        std::string GetPath(void) const;
+        // Set path
+        void SetPath(const std::string& oPath);
+
+        //synchronize the segment on disk.
+        void Synchronize();
+    private:
+        // Helper housekeeping functions
+        void Load();
+        void Write();
+
+        bool loaded_;
+        bool modified_;
+        PCIDSKBuffer seg_data;
+        std::string path;
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_SEGMENT_CLINKSEGMENT_H
diff --git a/frmts/pcidsk/sdk/core/cpcidskfile.cpp b/frmts/pcidsk/sdk/core/cpcidskfile.cpp
index 1b24d8e..28ab9a2 100644
--- a/frmts/pcidsk/sdk/core/cpcidskfile.cpp
+++ b/frmts/pcidsk/sdk/core/cpcidskfile.cpp
@@ -48,7 +48,13 @@
 #include "segment/cpcidskgcp2segment.h"
 #include "segment/cpcidskbitmap.h"
 #include "segment/cpcidsk_tex.h"
+#include "segment/cpcidsk_array.h"
 #include "segment/cpcidskapmodel.h"
+#include "segment/cpcidskads40model.h"
+#include "segment/cpcidsktoutinmodel.h"
+#include "segment/cpcidskpolymodel.h"
+#include "segment/cpcidskbinarysegment.h"
+#include "core/clinksegment.h"
 
 #include <cassert>
 #include <cstdlib>
@@ -218,7 +224,6 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int segment )
         return NULL;
 
     const char *segment_pointer = segment_pointers.buffer + (segment-1) * 32;
-
     if( segment_pointer[0] != 'A' && segment_pointer[0] != 'L' )
         return NULL;
 
@@ -261,6 +266,8 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int segment )
             segobj = new SysBlockMap( this, segment, segment_pointer );
         else if( strncmp(segment_pointer + 4, "METADATA",8) == 0 )
             segobj = new MetadataSegment( this, segment, segment_pointer );
+        else if (strncmp(segment_pointer + 4, "Link    ", 8) == 0)
+            segobj = new CLinkSegment(this, segment, segment_pointer);
         else
             segobj = new CPCIDSKSegment( this, segment, segment_pointer );
 
@@ -268,15 +275,50 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int segment )
         
       case SEG_GCP2:
         segobj = new CPCIDSKGCP2Segment(this, segment, segment_pointer);
+        break;
     
+      case SEG_ORB:
+        segobj = new CPCIDSKEphemerisSegment(this, segment, segment_pointer);
+        break;
+
+      case SEG_ARR:
+        segobj = new CPCIDSK_ARRAY(this, segment, segment_pointer);
+        break;
+
       case SEG_BIN:
         if (!strncmp(segment_pointer + 4, "RFMODEL ", 8))
+        {
             segobj = new CPCIDSKRPCModelSegment( this, segment, segment_pointer );
-        else if (!strncmp(segment_pointer + 4, "APMODEL ", 8)) {
+        }
+        else if (!strncmp(segment_pointer + 4, "APMODEL ", 8)) 
+        {
             segobj = new CPCIDSKAPModelSegment(this, segment, segment_pointer);
         }
+        else if (!strncmp(segment_pointer + 4, "ADSMODEL", 8)) 
+        {
+            segobj = new CPCIDSKADS40ModelSegment(this, segment, segment_pointer);
+        }
+        else if (!strncmp(segment_pointer + 4, "POLYMDL ", 8)) 
+        {
+            segobj = new CPCIDSKBinarySegment(this, segment, segment_pointer);
+        }
+        else if (!strncmp(segment_pointer + 4, "TPSMODEL", 8)) 
+        {
+            segobj = new CPCIDSKGCP2Segment(this, segment, segment_pointer);
+        }
+        else if (!strncmp(segment_pointer + 4, "MODEL   ", 8)) 
+        {
+            segobj = new CPCIDSKToutinModelSegment(this, segment, segment_pointer);
+        }
+        else if (!strncmp(segment_pointer + 4, "MMSPB   ", 8)) 
+        {
+            segobj = new CPCIDSKBinarySegment(this, segment, segment_pointer);
+        }
+        else if (!strncmp(segment_pointer + 4, "MMADS   ", 8)) 
+        {
+            segobj = new CPCIDSKBinarySegment(this, segment, segment_pointer);
+        }
         break;
-        
     }
     
     if (segobj == NULL)
@@ -302,7 +344,12 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int type, std::string name,
 
     name += "        "; // white space pad name.
 
-    sprintf( type_str, "%03d", type );
+    //we want the 3 less significant digit only in case type is too big
+    // Note : that happen with SEG_VEC_TABLE that is equal to 65652 in GDB.
+    //see function BuildChildrenLayer in jtfile.cpp, the call on GDBSegNext
+    //in the loop on gasTypeTable can create issue in PCIDSKSegNext 
+    //(in pcic/gdbfrtms/pcidskopen.cpp)
+    sprintf( type_str, "%03d", (type % 1000) );
 
     for( i = previous; i < segment_count; i++ )
     {
@@ -314,6 +361,9 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int type, std::string name,
             && strncmp(segment_pointers.buffer+i*32+4,name.c_str(),8) != 0 )
             continue;
 
+        // Ignore deleted segments.
+        if (*(segment_pointers.buffer + i * 32 + 0) == 'D') continue;
+
         return GetSegment(i+1);
     }
 
@@ -695,7 +745,9 @@ bool CPCIDSKFile::GetEDBFileDetails( EDBFile** file_p,
         try {
             new_file.file = interfaces.OpenEDB( filename, "r+" );
             new_file.writable = true;
-        } catch( PCIDSK::PCIDSKException ex ) {}
+        } 
+        catch( PCIDSK::PCIDSKException ex ) {}
+        catch( std::exception ex ) {}
     }
 
     if( new_file.file == NULL )
@@ -726,7 +778,8 @@ bool CPCIDSKFile::GetEDBFileDetails( EDBFile** file_p,
 
 void CPCIDSKFile::GetIODetails( void ***io_handle_pp, 
                                 Mutex ***io_mutex_pp, 
-                                std::string filename )
+                                std::string filename,
+                                bool writable )
 
 {
     *io_handle_pp = NULL;
@@ -749,7 +802,8 @@ void CPCIDSKFile::GetIODetails( void ***io_handle_pp,
 
     for( i = 0; i < file_list.size(); i++ )
     {
-        if( file_list[i].filename == filename )
+        if( file_list[i].filename == filename
+            && (!writable || file_list[i].writable) )
         {
             *io_handle_pp = &(file_list[i].io_handle);
             *io_mutex_pp = &(file_list[i].io_mutex);
@@ -763,7 +817,11 @@ void CPCIDSKFile::GetIODetails( void ***io_handle_pp,
 /* -------------------------------------------------------------------- */
     ProtectedFile new_file;
     
-    new_file.io_handle = interfaces.io->Open( filename, "r" );
+    if( writable )
+        new_file.io_handle = interfaces.io->Open( filename, "r+" );
+    else
+        new_file.io_handle = interfaces.io->Open( filename, "r" );
+        
     if( new_file.io_handle == NULL )
         ThrowPCIDSKException( "Unable to open file '%s'.", 
                               filename.c_str() );
@@ -774,6 +832,7 @@ void CPCIDSKFile::GetIODetails( void ***io_handle_pp,
 /* -------------------------------------------------------------------- */
     new_file.io_mutex = interfaces.CreateMutex();
     new_file.filename = filename;
+    new_file.writable = writable;
 
     file_list.push_back( new_file );
 
diff --git a/frmts/pcidsk/sdk/core/cpcidskfile.h b/frmts/pcidsk/sdk/core/cpcidskfile.h
index c050fe5..af5af91 100644
--- a/frmts/pcidsk/sdk/core/cpcidskfile.h
+++ b/frmts/pcidsk/sdk/core/cpcidskfile.h
@@ -77,7 +77,7 @@ namespace PCIDSK
         bool      GetUpdatable() const { return updatable; } 
         uint64    GetFileSize() const { return file_size; }
 
-    // the following are only for pixel interleaved IO
+        // the following are only for pixel interleaved IO
         int       GetPixelGroupSize() const { return pixel_group_size; }
         void     *ReadAndLockBlock( int block_index, int xoff=-1, int xsize=-1 );
         void      UnlockBlock( bool mark_dirty = false );
@@ -87,8 +87,10 @@ namespace PCIDSK
         void      WriteToFile( const void *buffer, uint64 offset, uint64 size );
         void      ReadFromFile( void *buffer, uint64 offset, uint64 size );
 
+        std::string GetFilename() const { return base_filename; }
+
         void      GetIODetails( void ***io_handle_pp, Mutex ***io_mutex_pp,
-            std::string filename = "" );
+                                std::string filename="", bool writable=false );
 
         bool      GetEDBFileDetails( EDBFile** file_p, Mutex **io_mutex_p,
                                      std::string filename );
diff --git a/frmts/pcidsk/sdk/core/pcidsk_utils.cpp b/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
index 1fa2d6b..97c4420 100644
--- a/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
+++ b/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
@@ -35,9 +35,14 @@
 #include <cctype>
 #include <cstdio>
 #include <cmath>
+#include <iostream>
 
 using namespace PCIDSK;
 
+#if defined(_MSC_VER) && (_MSC_VER < 1500)
+#  define vsnprintf _vsnprintf
+#endif
+
 /************************************************************************/
 /*                         GetCurrentDateTime()                         */
 /************************************************************************/
@@ -91,7 +96,7 @@ std::string &PCIDSK::UCaseStr( std::string &target )
     for( unsigned int i = 0; i < target.size(); i++ )
     {
         if( islower(target[i]) )
-            target[i] = toupper(target[i]);
+            target[i] = (char) toupper(target[i]);
     }
     
     return target;
@@ -320,16 +325,14 @@ int PCIDSK::pci_strcasecmp( const char *string1, const char *string2 )
         char c2 = string2[i];
 
         if( islower(c1) )
-            c1 = toupper(c1);
+            c1 = (char) toupper(c1);
         if( islower(c2) )
-            c2 = toupper(c2);
+            c2 = (char) toupper(c2);
 
         if( c1 < c2 )
             return -1;
         else if( c1 > c2 )
             return 1;
-        else 
-            return 0;
     }
 
     if( string1[i] == '\0' && string2[i] == '\0' )
@@ -362,9 +365,9 @@ int PCIDSK::pci_strncasecmp( const char *string1, const char *string2, int len )
         char c2 = string2[i];
 
         if( islower(c1) )
-            c1 = toupper(c1);
+            c1 = (char) toupper(c1);
         if( islower(c2) )
-            c2 = toupper(c2);
+            c2 = (char) toupper(c2);
 
         if( c1 < c2 )
             return -1;
@@ -552,3 +555,134 @@ std::string PCIDSK::MergeRelativePath( const PCIDSK::IOInterfaces *io_interfaces
         return src_filename;
     }
 }
+
+
+/************************************************************************/
+/*                            DefaultDebug()                            */
+/*                                                                      */
+/*      Default implementation of the Debug() output interface.         */
+/************************************************************************/
+
+void PCIDSK::DefaultDebug( const char * message )
+
+{
+    static bool initialized = false;
+    static bool enabled = false;
+    
+    if( !initialized )
+    {
+        if( getenv( "PCIDSK_DEBUG" ) != NULL )
+            enabled = true;
+
+        initialized = true;
+    }
+
+    if( enabled )
+        std::cerr << message;
+}
+
+/************************************************************************/
+/*                               vDebug()                               */
+/*                                                                      */
+/*      Helper function for Debug().                                    */
+/************************************************************************/
+
+static void vDebug( void (*pfnDebug)(const char *),
+                    const char *fmt, std::va_list args )
+
+{
+    std::string message;
+
+/* -------------------------------------------------------------------- */
+/*      This implementation for platforms without vsnprintf() will      */
+/*      just plain fail if the formatted contents are too large.        */
+/* -------------------------------------------------------------------- */
+#if defined(MISSING_VSNPRINTF)
+    char *pszBuffer = (char *) malloc(30000);
+    if( vsprintf( pszBuffer, fmt, args) > 29998 )
+    {
+        message = "PCIDSK::Debug() ... buffer overrun.";
+    }
+    else
+        message = pszBuffer;
+
+    free( pszBuffer );
+
+/* -------------------------------------------------------------------- */
+/*      This should grow a big enough buffer to hold any formatted      */
+/*      result.                                                         */
+/* -------------------------------------------------------------------- */
+#else
+    char szModestBuffer[500];
+    int nPR;
+    va_list wrk_args;
+
+#ifdef va_copy
+    va_copy( wrk_args, args );
+#else
+    wrk_args = args;
+#endif
+    
+    nPR = vsnprintf( szModestBuffer, sizeof(szModestBuffer), fmt, 
+                     wrk_args );
+    if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
+    {
+        int nWorkBufferSize = 2000;
+        char *pszWorkBuffer = (char *) malloc(nWorkBufferSize);
+
+#ifdef va_copy
+        va_end( wrk_args );
+        va_copy( wrk_args, args );
+#else
+        wrk_args = args;
+#endif
+        while( (nPR=vsnprintf( pszWorkBuffer, nWorkBufferSize, fmt, wrk_args))
+               >= nWorkBufferSize-1 
+               || nPR == -1 )
+        {
+            nWorkBufferSize *= 4;
+            pszWorkBuffer = (char *) realloc(pszWorkBuffer, 
+                                             nWorkBufferSize );
+#ifdef va_copy
+            va_end( wrk_args );
+            va_copy( wrk_args, args );
+#else
+            wrk_args = args;
+#endif
+        }
+        message = pszWorkBuffer;
+        free( pszWorkBuffer );
+    }
+    else
+    {
+        message = szModestBuffer;
+    }
+    va_end( wrk_args );
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Forward the message.                                            */
+/* -------------------------------------------------------------------- */
+    pfnDebug( message.c_str() );
+}
+
+/************************************************************************/
+/*                               Debug()                                */
+/*                                                                      */
+/*      Function to write output to a debug stream if one is            */
+/*      enabled.  This is intended to be widely called in the           */
+/*      library.                                                        */
+/************************************************************************/
+
+void PCIDSK::Debug( void (*pfnDebug)(const char *), const char *fmt, ... )
+
+{
+    if( pfnDebug == NULL )
+        return;
+
+    std::va_list args;
+
+    va_start( args, fmt );
+    vDebug( pfnDebug, fmt, args );
+    va_end( args );
+}
diff --git a/frmts/pcidsk/sdk/core/pcidsk_utils.h b/frmts/pcidsk/sdk/core/pcidsk_utils.h
index 720a926..2f553db 100644
--- a/frmts/pcidsk/sdk/core/pcidsk_utils.h
+++ b/frmts/pcidsk/sdk/core/pcidsk_utils.h
@@ -74,6 +74,10 @@ namespace PCIDSK
     void LibJPEG_CompressBlock(
         uint8 *src_data, int src_bytes, uint8 *dst_data, int &dst_bytes,
         int xsize, int ysize, eChanType pixel_type, int quality );
+
+    void                DefaultDebug( const char * );
+    void                Debug( void (*)(const char *), const char *fmt, ... );
+
 } // end namespace PCIDSK
 
 #endif // __INCLUDE_CORE_PCIDSK_UTILS_H
diff --git a/frmts/pcidsk/sdk/core/pcidskbuffer.cpp b/frmts/pcidsk/sdk/core/pcidskbuffer.cpp
index 9ebcdbd..2922422 100644
--- a/frmts/pcidsk/sdk/core/pcidskbuffer.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskbuffer.cpp
@@ -33,6 +33,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <cstdio>
+#include <sstream>
 
 using namespace PCIDSK;
 
@@ -193,14 +194,20 @@ double PCIDSKBuffer::GetDouble( int offset, int size ) const
             value_str[i] = 'E';
     }
 
-    return atof(value_str.c_str());
+    std::stringstream oStream;
+    oStream << value_str;
+    double dValue = 0.0;
+    oStream >> dValue;
+
+    return dValue;
+//    return atof(value_str.c_str());
 }
 
 /************************************************************************/
 /*                                Put()                                 */
 /************************************************************************/
 
-void PCIDSKBuffer::Put( const char *value, int offset, int size )
+void PCIDSKBuffer::Put( const char *value, int offset, int size, bool null_term )
 
 {
     if( offset + size > buffer_size )
@@ -214,6 +221,21 @@ void PCIDSKBuffer::Put( const char *value, int offset, int size )
         memset( buffer + offset, ' ', size );
 
     memcpy( buffer + offset, value, v_size );
+
+    if (null_term)
+    {
+        *(buffer + offset + v_size) = '\0';
+    }
+}
+
+/************************************************************************/
+/*                            PutBin(double)                            */
+/************************************************************************/
+
+void PCIDSKBuffer::PutBin(double value, int offset)
+{
+    const char* pszValue = (const char*)&value;
+    memcpy( buffer + offset, pszValue, 8 );
 }
 
 /************************************************************************/
diff --git a/frmts/pcidsk/sdk/core/pcidskcreate.cpp b/frmts/pcidsk/sdk/core/pcidskcreate.cpp
index 019ffa0..12a85c7 100644
--- a/frmts/pcidsk/sdk/core/pcidskcreate.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskcreate.cpp
@@ -52,7 +52,7 @@ using namespace PCIDSK;
  * @param channel_count the number of channels to create.
  * @param channel_types an array of types for all the channels, or NULL for
  * all CHN_8U channels.
- * @param option creation options (interleaving, etc)
+ * @param options creation options (interleaving, etc)
  * @param interfaces Either NULL to use default interfaces, or a pointer
  * to a populated interfaces object. 
  *
@@ -86,9 +86,11 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
 /* -------------------------------------------------------------------- */
 /*      Validate parameters.                                            */
 /* -------------------------------------------------------------------- */
-    const char *interleaving;
+    const char *interleaving = NULL;
     std::string compression = "NONE";
     bool nozero = false;
+    bool nocreate = false;
+    bool externallink = false;
     int  blocksize = 127;
 
     UCaseStr( options );
@@ -103,7 +105,16 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
         ParseTileFormat( options, blocksize, compression );
     }
     else if( strncmp(options.c_str(),"FILE",4) == 0 )
+    {
+        if( strncmp(options.c_str(),"FILENOCREATE",12) == 0 )
+            nocreate = true;
+        else if( strncmp(options.c_str(),"FILELINK",8) == 0 )
+        {
+            nocreate = true;
+            externallink = true;
+        }
         interleaving = "FILE";
+    }
     else
         ThrowPCIDSKException( "PCIDSK::Create() options '%s' not recognised.", 
                               options.c_str() );
@@ -146,7 +157,7 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
 /*      Establish some key file layout information.                     */
 /* ==================================================================== */
     int image_header_start = 1;                    // in blocks
-    uint64 image_data_start, image_data_size;      // in blocks
+    uint64 image_data_start, image_data_size=0;    // in blocks
     uint64 segment_ptr_start, segment_ptr_size=64; // in blocks
     int pixel_group_size, line_size;               // in bytes
     int image_header_count = channel_count;
@@ -342,6 +353,15 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
     if( strncmp(interleaving,"FILE",4) == 0 )
         ih.Put( "<unintialized>", 64, 64 );
     
+    if( externallink )
+    {
+        // IHi.6.7 - IHi.6.10
+        ih.Put( 0, 250, 8 ); 
+        ih.Put( 0, 258, 8 );
+        ih.Put( pixels, 266, 8 );
+        ih.Put( lines, 274, 8 );
+    }
+
     // IHi.3 - Creation time and date.
     ih.Put( current_time, 128, 16 );
 
@@ -424,11 +444,25 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
 /* -------------------------------------------------------------------- */
     if( strncmp(options.c_str(),"TILED",5) == 0 )
     {
-        file->SetMetadataValue( "_DBLayout", options );
-
+        file->SetMetadataValue( "_DBLayout", options ); 
+
+        // For sizing the SysBMDir we want an approximate size of the
+        // the imagery.
+        uint64 rough_image_size = 
+            (channels[0] + // CHN_8U
+             channels[1] * DataTypeSize(CHN_16U) + 
+             channels[2] * DataTypeSize(CHN_16S) + 
+             channels[3] * DataTypeSize(CHN_32R) +
+             channels[4] * DataTypeSize(CHN_C16U) +
+             channels[5] * DataTypeSize(CHN_C16S) +
+             channels[6] * DataTypeSize(CHN_C32R)) 
+            * (pixels * (uint64) lines);
+        uint64 sysbmdir_size = ((rough_image_size / 8192) * 28) / 512;
+
+        sysbmdir_size = (int) (sysbmdir_size * 1.1 + 100);
         int segment = file->CreateSegment( "SysBMDir", 
                                            "System Block Map Directory - Do not modify.",
-                                           SEG_SYS, 0 );
+                                           SEG_SYS, sysbmdir_size );
         
         SysBlockMap *bm = 
             dynamic_cast<SysBlockMap *>(file->GetSegment( segment ));
@@ -441,5 +475,53 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
         }
     }
 
+/* -------------------------------------------------------------------- */
+/*      If we have a non-tiled FILE interleaved file, should we         */
+/*      create external band files now?                                 */
+/* -------------------------------------------------------------------- */
+    if( strncmp(interleaving,"FILE",4) == 0 
+        && strncmp(options.c_str(),"TILED",5) != 0 
+        && !nocreate )
+    {
+        for( chan_index = 0; chan_index < channel_count; chan_index++ )
+        {
+            PCIDSKChannel *channel = file->GetChannel( chan_index + 1 );
+            int pixel_size = DataTypeSize(channel->GetType());
+
+            // build a band filename that uses the basename of the PCIDSK
+            // file, and adds ".nnn" based on the band. 
+            std::string band_filename = filename;
+            char ext[5];
+            sprintf( ext, ".%03d", chan_index+1 );
+            
+            size_t last_dot = band_filename.find_last_of(".");
+            if( last_dot != std::string::npos 
+                && (band_filename.find_last_of("/\\:") == std::string::npos
+                    || band_filename.find_last_of("/\\:") < last_dot) )
+            {
+                band_filename.resize( last_dot );
+            }
+
+            band_filename += ext;
+
+            // Now build a version without a path. 
+            std::string relative_band_filename;
+            size_t path_div = band_filename.find_last_of( "/\\:" );
+            if( path_div == std::string::npos )
+                relative_band_filename = band_filename;
+            else
+                relative_band_filename = band_filename.c_str() + path_div + 1;
+            
+            // create the file - ought we write the whole file?
+            void *band_io_handle = interfaces->io->Open( band_filename, "w" );
+            interfaces->io->Write( "\0", 1, 1, band_io_handle );
+            interfaces->io->Close( band_io_handle );
+
+            // Set the channel header information.
+            channel->SetChanInfo( relative_band_filename, 0, pixel_size, 
+                                  pixel_size * pixels, true );
+        }
+    }
+
     return file;
 }
diff --git a/frmts/pcidsk/sdk/core/pcidskinterfaces.cpp b/frmts/pcidsk/sdk/core/pcidskinterfaces.cpp
index 207212d..a557025 100644
--- a/frmts/pcidsk/sdk/core/pcidskinterfaces.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskinterfaces.cpp
@@ -46,6 +46,7 @@ PCIDSKInterfaces::PCIDSKInterfaces()
     io = GetDefaultIOInterfaces();
     OpenEDB = DefaultOpenEDB;
     CreateMutex = DefaultCreateMutex;
+    Debug = DefaultDebug;
 
 #if defined(HAVE_LIBJPEG)
     JPEGDecompressBlock = LibJPEG_DecompressBlock;
@@ -54,6 +55,7 @@ PCIDSKInterfaces::PCIDSKInterfaces()
     JPEGDecompressBlock = NULL;
     JPEGCompressBlock = NULL;
 #endif
+    
 }
 
 /**
diff --git a/frmts/pcidsk/sdk/core/protectedfile.h b/frmts/pcidsk/sdk/core/protectedfile.h
index a393101..c8c4406 100644
--- a/frmts/pcidsk/sdk/core/protectedfile.h
+++ b/frmts/pcidsk/sdk/core/protectedfile.h
@@ -36,6 +36,7 @@ namespace PCIDSK
     struct ProtectedFile
     {
         std::string     filename;
+        bool            writable;
         void           *io_handle;
         Mutex          *io_mutex;
     };
diff --git a/frmts/pcidsk/sdk/core/sysvirtualfile.cpp b/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
index ec3cf7b..a149019 100644
--- a/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
+++ b/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
@@ -39,8 +39,10 @@
 #include "pcidsk_types.h"
 #include "pcidsk_buffer.h"
 #include "pcidsk_exception.h"
+#include "pcidsk_utils.h"
 #include "core/sysvirtualfile.h"
 #include "core/cpcidskfile.h"
+#include "core/mutexholder.h"
 #include "segment/sysblockmap.h"
 #include <cassert>
 #include <cstring>
@@ -63,6 +65,9 @@ SysVirtualFile::SysVirtualFile( CPCIDSKFile *file, int start_block,
                                 int image_index )
 
 {
+    io_handle = NULL;
+    io_mutex = NULL;
+
     file_length = image_length;
     this->file = file;
     this->sysblockmap = sysblockmap;
@@ -74,6 +79,9 @@ SysVirtualFile::SysVirtualFile( CPCIDSKFile *file, int start_block,
     last_bm_index = -1;
 
     next_bm_entry_to_load = start_block;
+
+    regular_blocks = false;
+    blocks_loaded = 0;
 }
 
 /************************************************************************/
@@ -97,6 +105,110 @@ void SysVirtualFile::Synchronize()
 }
 
 /************************************************************************/
+/*                          GetBlockSegment()                           */
+/************************************************************************/
+
+uint16 SysVirtualFile::GetBlockSegment( int requested_block )
+
+{
+    if( requested_block < 0 )
+        ThrowPCIDSKException( "SysVirtualFile::GetBlockSegment(%d) - illegal request.",
+                              requested_block );
+
+    if( requested_block >= blocks_loaded )
+        LoadBMEntrysTo( requested_block );
+
+    if( regular_blocks )
+        // regular blocks are all in one segment.
+        return xblock_segment[0];
+    else
+        return xblock_segment[requested_block];
+}
+
+/************************************************************************/
+/*                       GetBlockIndexInSegment()                       */
+/************************************************************************/
+
+int SysVirtualFile::GetBlockIndexInSegment( int requested_block )
+
+{
+    if( requested_block < 0 )
+        ThrowPCIDSKException( "SysVirtualFile::GetBlockIndexInSegment(%d) - illegal request.",
+                              requested_block );
+
+    if( requested_block >= blocks_loaded )
+        LoadBMEntrysTo( requested_block );
+
+    if( regular_blocks )
+        // regular blocks all follow the first block in order.
+        return xblock_index[0] + requested_block;
+    else
+        return xblock_index[requested_block];
+}
+
+
+/************************************************************************/
+/*                            SetBlockInfo()                            */
+/************************************************************************/
+
+void SysVirtualFile::SetBlockInfo( int requested_block,
+                                   uint16 new_block_segment, 
+                                   int new_block_index )
+
+{
+    if( requested_block < 0 )
+        ThrowPCIDSKException( "SysVirtualFile::SetBlockSegment(%d) - illegal request.",
+                              requested_block );
+
+    // this should always be the case.
+    assert( requested_block == blocks_loaded );
+
+    // Initialization case.
+    if( requested_block == 0 && blocks_loaded == 0 )
+    {
+        xblock_segment.push_back( new_block_segment );
+        xblock_index.push_back( new_block_index );
+        blocks_loaded = 1;
+        return;
+    }
+
+    if( !regular_blocks )
+    {
+        xblock_segment.push_back( new_block_segment );
+        xblock_index.push_back( new_block_index );
+        blocks_loaded++;
+        return;
+    }
+
+    // Are things still regular?
+    if( new_block_segment == xblock_segment[0]
+        && new_block_index == xblock_index[0] + requested_block )
+    {
+        blocks_loaded++;
+        return;
+    }
+
+    // Ah, we see they are now irregular.  We need to build up the
+    // segment/index arrays and proceed to populate them. 
+    Debug( file->GetInterfaces()->Debug, 
+           "SysVirtualFile - Discovered stream is irregulr.  %d/%d follows %d/%d at block %d.\n",
+           new_block_segment, new_block_index,
+           xblock_segment[0], xblock_index[0], 
+           requested_block );
+           
+    regular_blocks = false;
+    while( (int) xblock_segment.size() < blocks_loaded )
+    {
+        xblock_segment.push_back( xblock_segment[0] );
+        xblock_index.push_back( xblock_index[xblock_index.size()-1]+1 );
+    }
+
+    xblock_segment.push_back( new_block_segment );
+    xblock_index.push_back( new_block_index );
+    blocks_loaded++;
+}
+
+/************************************************************************/
 /*                            WriteToFile()                             */
 /************************************************************************/
 
@@ -106,6 +218,11 @@ SysVirtualFile::WriteToFile( const void *buffer, uint64 offset, uint64 size )
 {
     uint64 buffer_offset = 0;
 
+    if(io_handle == NULL || io_mutex == NULL)
+        file->GetIODetails( &io_handle, &io_mutex );
+
+    MutexHolder oMutex(*io_mutex);
+
     while( buffer_offset < size )
     {
         int request_block = (int) ((offset + buffer_offset) / block_size);
@@ -149,6 +266,11 @@ SysVirtualFile::WriteToFile( const void *buffer, uint64 offset, uint64 size )
 void SysVirtualFile::ReadFromFile( void *buffer, uint64 offset, uint64 size )
 
 {
+    if(io_handle == NULL || io_mutex == NULL)
+        file->GetIODetails( &io_handle, &io_mutex );
+
+    MutexHolder oMutex(*io_mutex);
+
     uint64 buffer_offset = 0;
 #if 0
     printf("Requesting region at %llu of size %llu\n", offset, size);
@@ -167,10 +289,6 @@ void SysVirtualFile::ReadFromFile( void *buffer, uint64 offset, uint64 size )
             LoadBlock( request_block );
             if( amount_to_copy > (int) (size - buffer_offset) )
                 amount_to_copy = (int) (size - buffer_offset);
-#if 0
-            printf("Requested block: %d Offset: %d copying %d bytes\n",
-                request_block, offset_in_block, amount_to_copy);
-#endif
             memcpy( ((uint8 *) buffer) + buffer_offset,
                     block_data + offset_in_block, amount_to_copy );
         } else {
@@ -178,11 +296,6 @@ void SysVirtualFile::ReadFromFile( void *buffer, uint64 offset, uint64 size )
             // of full blocks we need to load
             int num_full_blocks = (int) ((size - buffer_offset)/block_size);
             
-#if 0
-            printf("Attempting a coalesced read of %d blocks (from %d) in buffer at %d\n", 
-                num_full_blocks, request_block, buffer_offset);
-#endif
-
             LoadBlocks(request_block, num_full_blocks, ((uint8*)buffer) + buffer_offset);
             amount_to_copy = num_full_blocks * block_size;
         }
@@ -216,7 +329,7 @@ void SysVirtualFile::LoadBlock( int requested_block )
 /* -------------------------------------------------------------------- */
 /*      Does this block exist in the virtual file?                      */
 /* -------------------------------------------------------------------- */
-    if( requested_block < 0 || requested_block >= (int) block_index.size() )
+    if( requested_block < 0 || requested_block >= blocks_loaded )
         ThrowPCIDSKException( "SysVirtualFile::LoadBlock(%d) - block out of range.",
                               requested_block );
 
@@ -230,10 +343,10 @@ void SysVirtualFile::LoadBlock( int requested_block )
 /* -------------------------------------------------------------------- */
     LoadBMEntrysTo( requested_block );
     PCIDSKSegment *data_seg_obj =
-        file->GetSegment( block_segment[requested_block] );
+        file->GetSegment( GetBlockSegment( requested_block ) );
 
     data_seg_obj->ReadFromFile( block_data,
-                                block_size * (uint64) block_index[requested_block],
+                                block_size * (uint64) GetBlockIndexInSegment( requested_block ),
                                 block_size );
 
     loaded_block = requested_block;
@@ -249,11 +362,16 @@ void SysVirtualFile::LoadBlock( int requested_block )
 void SysVirtualFile::FlushDirtyBlock(void)
 {
     if (loaded_block_dirty) {
+        if(io_handle == NULL || io_mutex == NULL)
+            file->GetIODetails( &io_handle, &io_mutex );
+
+        MutexHolder oMutex(*io_mutex);
+
         PCIDSKSegment *data_seg_obj =
-            file->GetSegment( block_segment[loaded_block] );
+            file->GetSegment( GetBlockSegment( loaded_block ) );
         
         data_seg_obj->WriteToFile( block_data,
-                                   block_size * (uint64) block_index[loaded_block],
+                                   block_size * (uint64) GetBlockIndexInSegment( loaded_block ),
                                    block_size );
         loaded_block_dirty = false;
     }
@@ -266,14 +384,19 @@ void SysVirtualFile::GrowVirtualFile(std::ptrdiff_t requested_block)
 {
     LoadBMEntrysTo( requested_block );
 
-    if( requested_block == (int) block_index.size() )
+    if( requested_block == blocks_loaded )
     {
+        if(io_handle == NULL || io_mutex == NULL)
+            file->GetIODetails( &io_handle, &io_mutex );
+
+        MutexHolder oMutex(*io_mutex);
+
         int new_seg;
+        int offset;
 
-        block_index.push_back( 
-            sysblockmap->GrowVirtualFile( image_index,
-                                          last_bm_index, new_seg ) );
-        block_segment.push_back( (uint16) new_seg );
+        offset = 
+            sysblockmap->GrowVirtualFile( image_index, last_bm_index, new_seg);
+        SetBlockInfo( requested_block, (uint16) new_seg, offset );
     }
 }
 
@@ -290,6 +413,11 @@ void SysVirtualFile::WriteBlocks(int first_block,
                                  int block_count,
                                  void* const buffer)
 {
+    if(io_handle == NULL || io_mutex == NULL)
+        file->GetIODetails( &io_handle, &io_mutex );
+
+    MutexHolder oMutex(*io_mutex);
+
     FlushDirtyBlock();
     // Iterate through all the blocks to be written, first, then
     // grow the virtual file
@@ -305,21 +433,21 @@ void SysVirtualFile::WriteBlocks(int first_block,
     while (blocks_written < (std::size_t) block_count) {
         LoadBMEntrysTo( current_first_block+1 );
 
-        unsigned int cur_segment = block_segment[current_first_block];
+        unsigned int cur_segment = GetBlockSegment( current_first_block );
         unsigned int cur_block = current_first_block;
         while (cur_block < (unsigned int)block_count + first_block &&
-            (unsigned int)block_segment[cur_block + 1] == cur_segment)
+               (unsigned int) GetBlockSegment(cur_block + 1) == cur_segment)
         {
             cur_block++;
             LoadBMEntrysTo( current_first_block+1 );
         }
         
         // Find largest span of contiguous blocks we can write
-        uint64 write_start = block_index[current_first_block];
+        uint64 write_start = GetBlockIndexInSegment(current_first_block);
         uint64 write_cur = write_start * block_size;
         unsigned int count_to_write = 1;
         while (write_cur + block_size ==
-            (uint64)block_index[count_to_write + current_first_block - 1] * block_size &&
+               (uint64)GetBlockIndexInSegment(count_to_write + current_first_block - 1) * block_size &&
             count_to_write < (cur_block - current_first_block))
         {
             write_cur += block_size;
@@ -355,7 +483,13 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
                                 int requested_block_count,
                                 void* const buffer)
 {
+    if(io_handle == NULL || io_mutex == NULL)
+        file->GetIODetails( &io_handle, &io_mutex );
+
+    MutexHolder oMutex(*io_mutex);
+
     FlushDirtyBlock();
+
     unsigned int blocks_read = 0;
     unsigned int current_start = requested_block_start;
     
@@ -364,11 +498,11 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
     while (blocks_read < (unsigned int)requested_block_count) {
         // Coalesce blocks that are in the same segment
         LoadBMEntrysTo( current_start+1 );
-        unsigned int cur_segment = block_segment[current_start]; // segment of current
+        unsigned int cur_segment = GetBlockSegment(current_start); // segment of current
                 // first block
         unsigned int cur_block = current_start; // starting block ID
         while (cur_block < (unsigned int)requested_block_count + requested_block_start &&
-            block_segment[cur_block + 1] == cur_segment) {
+               GetBlockSegment(cur_block + 1) == cur_segment) {
             // this block is in the same segment as the previous one we
             // wanted to read.
             cur_block++;
@@ -377,11 +511,11 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
         
         // now attempt to determine if the region of blocks (from current_start
         // to cur_block are contiguous
-        uint64 read_start = block_index[current_start];
+        uint64 read_start = GetBlockIndexInSegment(current_start);
         uint64 read_cur = read_start * block_size;
         unsigned int count_to_read = 1; // we'll read at least one block
         while (read_cur + block_size ==
-            (uint64)block_index[count_to_read + current_start] * block_size && // compare count of blocks * offset with stored offset
+               (uint64)GetBlockIndexInSegment(count_to_read + current_start) * block_size && // compare count of blocks * offset with stored offset
             count_to_read < (cur_block - current_start) ) // make sure we don't try to read more blocks than we determined fell in
                                                             // this segment
         {
@@ -390,13 +524,11 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
         }
 
 #if 0
-
         // Check if we need to grow the virtual file for each of these blocks
         for (unsigned int i = 0 ; i < count_to_read; i++) {
             GrowVirtualFile(i + current_start);
         }
         
-        
         printf("Coalescing the read of %d blocks\n", count_to_read);
 #endif
 
@@ -440,7 +572,7 @@ void SysVirtualFile::LoadBMEntrysTo( int target_index )
         target_index += 200 - (target_index%200);
     }
     
-    while( (target_index == -1 || (int) block_segment.size() <= target_index) 
+    while( (target_index == -1 || blocks_loaded <= target_index ) 
            && next_bm_entry_to_load != -1 )
     {
         uint16 segment;
@@ -451,13 +583,7 @@ void SysVirtualFile::LoadBMEntrysTo( int target_index )
             sysblockmap->GetNextBlockMapEntry( 
                 next_bm_entry_to_load, segment, block );
 
-        block_segment.push_back( segment );
-        block_index.push_back( block );
-#if 0
-        printf( "<block[%d] = %d/%d/%d/%d>\n", 
-                block_index.size()-1, segment, block,
-                last_bm_index, next_bm_entry_to_load );
-#endif
+        SetBlockInfo( blocks_loaded, segment, block );
     }
 }
 
diff --git a/frmts/pcidsk/sdk/core/sysvirtualfile.h b/frmts/pcidsk/sdk/core/sysvirtualfile.h
index e1713ca..5a0e5e9 100644
--- a/frmts/pcidsk/sdk/core/sysvirtualfile.h
+++ b/frmts/pcidsk/sdk/core/sysvirtualfile.h
@@ -39,6 +39,7 @@
 #define __INCLUDE_CORE_SYSVIRTUALFILE_H
 
 #include "pcidsk_buffer.h"
+#include "pcidsk_mutex.h"
 
 #include <vector>
 
@@ -70,13 +71,18 @@ namespace PCIDSK
     
     private:
         CPCIDSKFile           *file;
+        void                 **io_handle;
+        Mutex                **io_mutex;
+
         SysBlockMap           *sysblockmap;
         int                    image_index;
 
         uint64                 file_length;
 
-        std::vector<uint16>    block_segment;
-        std::vector<int>       block_index;
+        bool                   regular_blocks;
+        int                    blocks_loaded;
+        std::vector<uint16>    xblock_segment;
+        std::vector<int>       xblock_index;
         int                    next_bm_entry_to_load;
 
         int                    loaded_block;
@@ -85,6 +91,13 @@ namespace PCIDSK
 
         int                    last_bm_index;
 
+        uint16                 GetBlockSegment( int requested_block );
+        int                    GetBlockIndexInSegment( int requested_block );
+
+        void                   SetBlockInfo( int requested_block,
+                                             uint16 new_block_segment,
+                                             int new_block_index );
+
         void                   LoadBlock( int requested_block );
         void                   LoadBlocks( int requested_block_start,
                                            int requested_block_count,
diff --git a/frmts/pcidsk/sdk/pcidsk_ads40.h b/frmts/pcidsk/sdk/pcidsk_ads40.h
new file mode 100644
index 0000000..ea5ef12
--- /dev/null
+++ b/frmts/pcidsk/sdk/pcidsk_ads40.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ * Purpose: Interface representing access to a PCIDSK ADS40 Segment
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_PCIDSK_ADS40_H
+#define __INCLUDE_PCIDSK_PCIDSK_ADS40_H
+
+#include <vector>
+#include <string>
+
+namespace PCIDSK {
+//! Interface to PCIDSK RPC segment.
+    class PCIDSKADS40Segment 
+    {
+    public:
+        // Get path
+        virtual std::string GetPath(void) const = 0;
+        // Set path
+        virtual void SetPath(const std::string& oPath) = 0;
+        
+        // Virtual destructor
+        virtual ~PCIDSKADS40Segment() {}
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_PCIDSK_ADS40_H
diff --git a/frmts/pcidsk/sdk/pcidsk_array.h b/frmts/pcidsk/sdk/pcidsk_array.h
new file mode 100644
index 0000000..abc6428
--- /dev/null
+++ b/frmts/pcidsk/sdk/pcidsk_array.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * Purpose:  PCIDSK ARRAY segment interface class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2010
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_ARRAY_H
+#define __INCLUDE_PCIDSK_ARRAY_H
+
+#include <string>
+#include <vector>
+
+namespace PCIDSK
+{
+/************************************************************************/
+/*                              PCIDSK_ARRAY                            */
+/************************************************************************/
+
+//! Interface to PCIDSK text segment.
+
+    class PCIDSK_DLL PCIDSK_ARRAY
+    {
+    public:
+        virtual	~PCIDSK_ARRAY() {}
+
+        //ARRAY functions
+        virtual	unsigned char GetDimensionCount() const =0;
+        virtual	void SetDimensionCount(unsigned char nDim) =0;
+        virtual	const std::vector<unsigned int>& GetSizes() const =0;
+        virtual	void SetSizes(const std::vector<unsigned int>& oSizes) =0;
+        virtual	const std::vector<double>& GetArray() const =0;
+        virtual	void SetArray(const std::vector<double>& oArray) =0;
+    };
+} // end namespace PCIDSK
+
+#endif // __INCLUDE_PCIDSK_ARRAY_H
diff --git a/frmts/pcidsk/sdk/pcidsk_binary.h b/frmts/pcidsk/sdk/pcidsk_binary.h
new file mode 100644
index 0000000..8646a14
--- /dev/null
+++ b/frmts/pcidsk/sdk/pcidsk_binary.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * Purpose: Interface representing access to a PCIDSK Binary Segment
+ * 
+ ******************************************************************************
+ * Copyright (c) 2010
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_PCIDSK_BINARY_H
+#define __INCLUDE_PCIDSK_PCIDSK_BINARY_H
+
+namespace PCIDSK {
+//! Interface to PCIDSK Binary segment.
+    class PCIDSKBinarySegment 
+    {
+    public:
+        virtual const char* GetBuffer(void) const = 0;
+        virtual unsigned int GetBufferSize(void) const = 0;
+        virtual void SetBuffer(const char* pabyBuf, 
+            unsigned int nBufSize) = 0;
+
+        // Virtual destructor
+        virtual ~PCIDSKBinarySegment() {}
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_PCIDSK_BINARY_H
diff --git a/frmts/pcidsk/sdk/pcidsk_buffer.h b/frmts/pcidsk/sdk/pcidsk_buffer.h
index 11b4816..58c200b 100644
--- a/frmts/pcidsk/sdk/pcidsk_buffer.h
+++ b/frmts/pcidsk/sdk/pcidsk_buffer.h
@@ -61,11 +61,15 @@ namespace PCIDSK
         int64       GetInt64( int offset, int size ) const;
         uint64      GetUInt64( int offset, int size ) const;
 
-        void        Put( const char *value,  int offset, int size );
+        void        Put( const char *value,  int offset, int size, bool null_term = false );
         void        Put( uint64 value, int offset, int size );
         void        Put( double value, int offset, int size, const char *fmt=NULL );
         void        Put( int value, int offset, int size ) 
             { Put( (uint64) value, offset, size ); }
+        void        Put( unsigned int value, int offset, int size ) 
+            { Put( (uint64) value, offset, size ); }
+
+        void        PutBin(double value, int offset);
 
         void        SetSize( int size );
         
diff --git a/frmts/pcidsk/sdk/pcidsk_channel.h b/frmts/pcidsk/sdk/pcidsk_channel.h
index 4666c76..dd841b8 100644
--- a/frmts/pcidsk/sdk/pcidsk_channel.h
+++ b/frmts/pcidsk/sdk/pcidsk_channel.h
@@ -73,6 +73,22 @@ namespace PCIDSK
         virtual void SetHistoryEntries( const std::vector<std::string> &entries ) = 0;
         virtual void PushHistory(const std::string &app,
                                  const std::string &message) = 0;
+
+        // Only applicable to FILE interleaved raw channels.
+        virtual void GetChanInfo( std::string &filename, uint64 &image_offset, 
+                                  uint64 &pixel_offset, uint64 &line_offset, 
+                                  bool &little_endian ) const = 0;
+        virtual void SetChanInfo( std::string filename, uint64 image_offset, 
+                                  uint64 pixel_offset, uint64 line_offset, 
+                                  bool little_endian ) = 0;
+
+        // Only applicable to CExternalChannels
+        virtual void GetEChanInfo( std::string &filename, int &echannel,
+                                   int &exoff, int &eyoff, 
+                                   int &exsize, int &eysize ) const = 0;
+        virtual void SetEChanInfo( std::string filename, int echannel,
+                                   int exoff, int eyoff, 
+                                   int exsize, int eysize ) = 0;
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/pcidsk_config.h b/frmts/pcidsk/sdk/pcidsk_config.h
index d41d968..2c97fdd 100644
--- a/frmts/pcidsk/sdk/pcidsk_config.h
+++ b/frmts/pcidsk/sdk/pcidsk_config.h
@@ -31,6 +31,8 @@
 namespace PCIDSK {
 
     typedef unsigned char  uint8;
+
+#ifndef _PCI_TYPES
     typedef int            int32;
     typedef unsigned int   uint32;
     typedef short          int16;
@@ -44,6 +46,8 @@ namespace PCIDSK {
     typedef unsigned long long uint64;
 #endif
 
+#endif // _PCI_TYPES
+
 }
 
 #ifdef _MSC_VER
diff --git a/frmts/pcidsk/sdk/pcidsk_ephemeris.h b/frmts/pcidsk/sdk/pcidsk_ephemeris.h
new file mode 100644
index 0000000..7f11c22
--- /dev/null
+++ b/frmts/pcidsk/sdk/pcidsk_ephemeris.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ * Purpose: Interface representing access to a PCIDSK Ephemeris segment
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
+#define __INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
+
+#include <vector>
+#include <string>
+#include "segment/orbitstructures.h"
+
+namespace PCIDSK {
+//! Interface to PCIDSK RPC segment.
+    class PCIDSKEphemerisSegment 
+    {
+    public:
+ 
+        // Virtual destructor
+        virtual ~PCIDSKEphemerisSegment() {}
+
+        virtual const EphemerisSeg_t& GetEphemeris() const=0;
+        virtual void SetEphemeris(const EphemerisSeg_t& oEph) =0;
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_PCIDSK_EPHEMERIS_H
diff --git a/frmts/pcidsk/sdk/pcidsk_file.h b/frmts/pcidsk/sdk/pcidsk_file.h
index 361e1a3..e4e3ad7 100644
--- a/frmts/pcidsk/sdk/pcidsk_file.h
+++ b/frmts/pcidsk/sdk/pcidsk_file.h
@@ -80,7 +80,7 @@ namespace PCIDSK
         virtual void ReadFromFile( void *buffer, uint64 offset, uint64 size ) = 0;
 
         virtual void GetIODetails( void ***io_handle_pp, Mutex ***io_mutex_pp,
-            std::string filename = "" ) = 0;
+                                   std::string filename="", bool writable=false ) = 0;
 
         virtual std::string GetMetadataValue( const std::string& key ) = 0;
         virtual void SetMetadataValue( const std::string& key, const std::string& value ) = 0;
diff --git a/frmts/pcidsk/sdk/pcidsk_gcp.h b/frmts/pcidsk/sdk/pcidsk_gcp.h
index 16d7290..8e9b9c0 100644
--- a/frmts/pcidsk/sdk/pcidsk_gcp.h
+++ b/frmts/pcidsk/sdk/pcidsk_gcp.h
@@ -1,3 +1,30 @@
+/******************************************************************************
+ *
+ * Purpose: Declaration of the PCIDSK::GCP class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_SRC_GCP_H
 #define __INCLUDE_PCIDSK_SRC_GCP_H
 
@@ -22,7 +49,8 @@ namespace PCIDSK {
         GCP(double x, double y, double z,
             double line, double pix,
             std::string const& gcp_id,
-            std::string const& map_units, // TODO: Add ProjParms?
+            std::string const& map_units, 
+            std::string const& proj_parms = "",
             double xerr = 0.0, double yerr = 0.0, double zerr = 0.0,
             double line_err = 0.0, double pix_err = 0.0)
         {
@@ -39,12 +67,15 @@ namespace PCIDSK {
             
             raster_error_[1] = line_err;
             raster_error_[0] = pix_err;
+
+            std::memset(gcp_id_, ' ', 64);
             
             std::strncpy(gcp_id_, gcp_id.c_str(),
                          gcp_id.size() > 64 ? 64 : gcp_id.size());
-            gcp_id_[64] = '\0';
+            gcp_id_[gcp_id.size() > 64 ? 64 : gcp_id.size()] = '\0';
             
             this->map_units_ = map_units;
+            this->proj_parms_ = proj_parms;
             
             elevation_unit_ = EMetres;
             elevation_datum_ = EEllipsoidal;
@@ -114,8 +145,11 @@ namespace PCIDSK {
         double GetLine() const { return raster_point_[1]; }
         double GetLineErr() const { return raster_error_[1]; }
         
-        std::string const& GetMapUnits(void) const { return map_units_; }
-        void SetMapUnits(std::string const& map_units) { map_units_ = map_units; }
+        void GetMapUnits(std::string& map_units, std::string& proj_parms) const 
+        { map_units = map_units_; proj_parms = proj_parms_;}
+        void SetMapUnits(std::string const& map_units,
+            std::string const& proj_parms) { map_units_ = map_units; 
+                                             proj_parms_ = proj_parms;}
         
         const char* GetIDString(void) const { return gcp_id_; }
     private:
@@ -136,6 +170,7 @@ namespace PCIDSK {
             raster_error_[1] = gcp.raster_error_[1];
             
             this->map_units_ = gcp.map_units_;
+            this->proj_parms_ = gcp.proj_parms_;
             this->iscp_ = gcp.iscp_;
             
             std::strncpy(this->gcp_id_, gcp.gcp_id_, 64);
@@ -160,7 +195,8 @@ namespace PCIDSK {
         
         char gcp_id_[65];
         
-        std::string map_units_;
+        std::string map_units_; ///< PCI mapunits string
+        std::string proj_parms_;  ///< PCI projection parameters string
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/pcidsk_interfaces.h b/frmts/pcidsk/sdk/pcidsk_interfaces.h
index 7212ff8..843adec 100644
--- a/frmts/pcidsk/sdk/pcidsk_interfaces.h
+++ b/frmts/pcidsk/sdk/pcidsk_interfaces.h
@@ -58,6 +58,7 @@ namespace PCIDSK
             ( uint8 *src_data, int src_bytes, uint8 *dst_data, int &dst_bytes,
               int xsize, int ysize, eChanType pixel_type, int quality );
 
+        void              (*Debug)( const char * );
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/pcidsk_poly.h b/frmts/pcidsk/sdk/pcidsk_poly.h
new file mode 100644
index 0000000..a0d579a
--- /dev/null
+++ b/frmts/pcidsk/sdk/pcidsk_poly.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * Purpose: Interface representing access to a PCIDSK Polynomial Segment
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_PCIDSK_POLY_H
+#define __INCLUDE_PCIDSK_PCIDSK_POLY_H
+
+#include <vector>
+#include <string>
+
+namespace PCIDSK {
+//! Interface to PCIDSK Polynomial segment.
+    class PCIDSKPolySegment 
+    {
+    public:
+        //Get the coefficients
+        virtual std::vector<double> GetXForwardCoefficients() const=0;
+        virtual std::vector<double> GetYForwardCoefficients() const=0;
+        virtual std::vector<double> GetXBackwardCoefficients() const=0;
+        virtual std::vector<double> GetYBackwardCoefficients() const=0;
+
+        //Set the coefficients
+        virtual void SetCoefficients(const std::vector<double>& oXForward,
+                                     const std::vector<double>& oYForward,
+                                     const std::vector<double>& oXBackward,
+                                     const std::vector<double>& oYBackward) =0;
+
+        // Get the number of lines
+        virtual unsigned int GetLines() const=0;
+        // Get the number of pixels
+        virtual unsigned int GetPixels() const=0;
+        // Set the number of lines/pixels
+        virtual void SetRasterSize(unsigned int nLines,unsigned int nPixels) =0;
+
+        // Get the Geosys String
+        virtual std::string GetGeosysString() const=0;
+        // Set the Geosys string
+        virtual void SetGeosysString(const std::string& oGeosys) =0;
+
+        //Get the projection informations
+        virtual std::vector<double> GetProjParmInfo() const=0;
+        //Set the projection informations
+        virtual void SetProjParmInfo(const std::vector<double>& oInfo) =0;
+
+        // Virtual destructor
+        virtual ~PCIDSKPolySegment() {}
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_PCIDSK_POLY_H
diff --git a/frmts/pcidsk/sdk/pcidsk_rpc.h b/frmts/pcidsk/sdk/pcidsk_rpc.h
index 446b37c..4be9514 100644
--- a/frmts/pcidsk/sdk/pcidsk_rpc.h
+++ b/frmts/pcidsk/sdk/pcidsk_rpc.h
@@ -98,6 +98,10 @@ namespace PCIDSK {
         // Set the number of lines/pixels
         virtual void SetRasterSize(const unsigned int lines, const unsigned int pixels) = 0;
         
+        // Set/get the downsample factor
+        virtual void SetDownsample(const unsigned int downsample) = 0;
+        virtual unsigned int GetDownsample(void) const = 0;
+
         // TODO: Setting/getting detailed projection params (just GCTP params?)
 
         // Virtual destructor
diff --git a/frmts/pcidsk/sdk/pcidsk_segment.h b/frmts/pcidsk/sdk/pcidsk_segment.h
index f307e10..9aa500e 100644
--- a/frmts/pcidsk/sdk/pcidsk_segment.h
+++ b/frmts/pcidsk/sdk/pcidsk_segment.h
@@ -39,7 +39,7 @@ namespace PCIDSK
 /*                            PCIDSKSegment                             */
 /************************************************************************/
 
-//! Public tnterface for the PCIDSK Segment Type
+//! Public interface for the PCIDSK Segment Type
 
     class PCIDSKSegment 
     {
diff --git a/frmts/pcidsk/sdk/pcidsk_toutin.h b/frmts/pcidsk/sdk/pcidsk_toutin.h
new file mode 100644
index 0000000..b9cc200
--- /dev/null
+++ b/frmts/pcidsk/sdk/pcidsk_toutin.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ * Purpose: Interface representing access to a PCIDSK Toutin Segment
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
+#define __INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
+
+#include <vector>
+#include <string>
+#include "segment/toutinstructures.h"
+
+namespace PCIDSK {
+//! Interface to PCIDSK RPC segment.
+    class PCIDSKToutinSegment 
+    {
+    public:
+ 
+        // Virtual destructor
+        virtual ~PCIDSKToutinSegment() {}
+
+        virtual SRITInfo_t GetInfo() const =0;
+        virtual void SetInfo(const SRITInfo_t& poInfo) =0;
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_PCIDSK_TOUTIN_H
diff --git a/frmts/pcidsk/sdk/port/io_win32.cpp b/frmts/pcidsk/sdk/port/io_win32.cpp
index 977e95b..d24c93d 100644
--- a/frmts/pcidsk/sdk/port/io_win32.cpp
+++ b/frmts/pcidsk/sdk/port/io_win32.cpp
@@ -1,326 +1,329 @@
-/******************************************************************************
- *
- * Purpose:  Implementation of IO interface using Win32 API.
- * 
- ******************************************************************************
- * Copyright (c) 2009
- * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
- *
- * 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 "pcidsk_io.h"
-#include "pcidsk_exception.h"
-#include <windows.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <io.h>
-#include <fcntl.h>
-#include <direct.h>
-
-using namespace PCIDSK;
-
-class Win32IOInterface : public IOInterfaces
-{
-    virtual void   *Open( std::string filename, std::string access ) const;
-    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const;
-    virtual uint64  Tell( void *io_handle ) const;
-    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
-    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
-    virtual int     Eof( void *io_handle ) const;
-    virtual int     Flush( void *io_handle ) const;
-    virtual int     Close( void *io_handle ) const;
-
-    const char     *LastError() const;
-};
-
-typedef struct {
-    HANDLE hFile;
-    uint64 offset;
-} FileInfo;
-
-/************************************************************************/
-/*                       GetDefaultIOInterfaces()                       */
-/************************************************************************/
-
-const IOInterfaces *PCIDSK::GetDefaultIOInterfaces()
-{
-    static Win32IOInterface singleton_win32_interface;
-
-    return &singleton_win32_interface;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-void *
-Win32IOInterface::Open( std::string filename, std::string access ) const
-
-{
-    DWORD dwDesiredAccess, dwCreationDisposition, dwFlagsAndAttributes;
-    HANDLE hFile;
-
-    if( strchr(access.c_str(),'+') != NULL || strchr(access.c_str(),'w') != 0 )
-        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
-    else
-        dwDesiredAccess = GENERIC_READ;
-
-    if( strstr(access.c_str(), "w") != NULL )
-        dwCreationDisposition = CREATE_ALWAYS;
-    else
-        dwCreationDisposition = OPEN_EXISTING;
-
-    dwFlagsAndAttributes = (dwDesiredAccess == GENERIC_READ) ? 
-                FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL, 
-    
-    hFile = CreateFileA(filename.c_str(), dwDesiredAccess, 
-                        FILE_SHARE_READ | FILE_SHARE_WRITE, 
-                        NULL, dwCreationDisposition,  dwFlagsAndAttributes, NULL);
-
-    if( hFile == INVALID_HANDLE_VALUE )
-    {
-        ThrowPCIDSKException( "Open(%s,%s) failed:\n%s", 
-                              filename.c_str(), access.c_str(), LastError() );
-    }
-    
-    FileInfo *fi = new FileInfo();
-    fi->hFile = hFile;
-    fi->offset = 0;
-
-    return fi;
-}
-
-/************************************************************************/
-/*                                Seek()                                */
-/************************************************************************/
-
-uint64 
-Win32IOInterface::Seek( void *io_handle, uint64 offset, int whence ) const
-
-{
-    FileInfo *fi = (FileInfo *) io_handle;
-    uint32       dwMoveMethod, dwMoveHigh;
-    uint32       nMoveLow;
-    LARGE_INTEGER li;
-
-    // seeks that do nothing are still surprisingly expensive with MSVCRT.
-    // try and short circuit if possible.
-    if( whence == SEEK_SET && offset == fi->offset )
-        return 0;
-
-    switch(whence)
-    {
-        case SEEK_CUR:
-            dwMoveMethod = FILE_CURRENT;
-            break;
-        case SEEK_END:
-            dwMoveMethod = FILE_END;
-            break;
-        case SEEK_SET:
-        default:
-            dwMoveMethod = FILE_BEGIN;
-            break;
-    }
-
-    li.QuadPart = offset;
-    nMoveLow = li.LowPart;
-    dwMoveHigh = li.HighPart;
-
-    SetLastError( 0 );
-    SetFilePointer(fi->hFile, (LONG) nMoveLow, (PLONG)&dwMoveHigh,
-                   dwMoveMethod);
-
-    if( GetLastError() != NO_ERROR )
-    {
-#ifdef notdef
-        LPVOID      lpMsgBuf = NULL;
-        
-        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                       | FORMAT_MESSAGE_FROM_SYSTEM
-                       | FORMAT_MESSAGE_IGNORE_INSERTS,
-                       NULL, GetLastError(), 
-                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
-                       (LPTSTR) &lpMsgBuf, 0, NULL );
- 
-        printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf );
-        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n", 
-                (GUInt32) nOffset, nMoveLow, dwMoveHigh );
-#endif
-        ThrowPCIDSKException( "Seek(%d,%d): %s", 
-                              (int) offset, whence, 
-                              LastError() );
-        return -1;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Update our offset.                                              */
-/* -------------------------------------------------------------------- */
-    if( whence == SEEK_SET )
-        fi->offset = offset;
-    else if( whence == SEEK_END )
-    {
-        LARGE_INTEGER   li;
-
-        li.HighPart = 0;
-        li.LowPart = SetFilePointer( fi->hFile, 0, (PLONG) &(li.HighPart), 
-                                     FILE_CURRENT );
-        fi->offset = li.QuadPart;
-    }
-    else if( whence == SEEK_CUR )
-        fi->offset += offset;
-
-    return 0;
-}
-
-/************************************************************************/
-/*                                Tell()                                */
-/************************************************************************/
-
-uint64 Win32IOInterface::Tell( void *io_handle ) const
-
-{
-    FileInfo *fi = (FileInfo *) io_handle;
-
-    return fi->offset;
-}
-
-/************************************************************************/
-/*                                Read()                                */
-/************************************************************************/
-
-uint64 Win32IOInterface::Read( void *buffer, uint64 size, uint64 nmemb, 
-                               void *io_handle ) const
-
-{
-    FileInfo *fi = (FileInfo *) io_handle;
-
-    errno = 0;
-
-    DWORD       dwSizeRead;
-    size_t      result;
-
-    if( !ReadFile(fi->hFile, buffer, (DWORD)(size*nmemb), &dwSizeRead, NULL) )
-    {
-        result = 0;
-    }
-    else if( size == 0 )
-        result = 0;
-    else
-        result = (size_t) (dwSizeRead / size);
-
-    if( errno != 0 && result == 0 && nmemb != 0 )
-        ThrowPCIDSKException( "Read(%d): %s", 
-                              (int) size * nmemb,
-                              LastError() );
-
-    fi->offset += size*result;
-
-    return result;
-}
-
-/************************************************************************/
-/*                               Write()                                */
-/************************************************************************/
-
-uint64 Win32IOInterface::Write( const void *buffer, uint64 size, uint64 nmemb, 
-                                void *io_handle ) const
-
-{
-    FileInfo *fi = (FileInfo *) io_handle;
-
-    errno = 0;
-
-    DWORD       dwSizeRead;
-    size_t      result;
-
-    if( !WriteFile(fi->hFile, buffer, (DWORD)(size*nmemb), &dwSizeRead, NULL) )
-    {
-        result = 0;
-    }
-    else if( size == 0 )
-        result = 0;
-    else
-        result = (size_t) (dwSizeRead / size);
-
-    if( errno != 0 && result == 0 && nmemb != 0 )
-        ThrowPCIDSKException( "Write(%d): %s", 
-                                   (int) size * nmemb,
-                                   LastError() );
-
-    fi->offset += size*result;
-
-    return result;
-}
-
-/************************************************************************/
-/*                                Eof()                                 */
-/************************************************************************/
-
-int Win32IOInterface::Eof( void *io_handle ) const
-
-{
-    FileInfo *fi = (FileInfo *) io_handle;
-    uint64       nCur, nEnd;
-
-    nCur = Tell( io_handle );
-    Seek( io_handle, 0, SEEK_END );
-    nEnd = Tell( io_handle );
-    Seek( io_handle, nCur, SEEK_SET );
-
-    return (nCur == nEnd);
-}
-
-/************************************************************************/
-/*                               Flush()                                */
-/************************************************************************/
-
-int Win32IOInterface::Flush( void *io_handle ) const
-
-{
-    FileInfo *fi = (FileInfo *) io_handle;
-
-    FlushFileBuffers( fi->hFile );
-
-    return 0;
-}
-
-/************************************************************************/
-/*                               Close()                                */
-/************************************************************************/
-
-int Win32IOInterface::Close( void *io_handle ) const
-
-{
-    FileInfo *fi = (FileInfo *) io_handle;
-
-    return CloseHandle( fi->hFile ) ? 0 : -1;
-}
-
-/************************************************************************/
-/*                             LastError()                              */
-/*                                                                      */
-/*      Return a string representation of the last error.               */
-/************************************************************************/
-
-const char *Win32IOInterface::LastError() const
-
-{
-    return "";
-}
+/******************************************************************************
+ *
+ * Purpose:  Implementation of IO interface using Win32 API.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 "pcidsk_io.h"
+#include "pcidsk_exception.h"
+#include <windows.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <fcntl.h>
+#include <direct.h>
+
+using namespace PCIDSK;
+
+class Win32IOInterface : public IOInterfaces
+{
+    virtual void   *Open( std::string filename, std::string access ) const;
+    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const;
+    virtual uint64  Tell( void *io_handle ) const;
+    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
+    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
+    virtual int     Eof( void *io_handle ) const;
+    virtual int     Flush( void *io_handle ) const;
+    virtual int     Close( void *io_handle ) const;
+
+    const char     *LastError() const;
+};
+
+typedef struct {
+    HANDLE hFile;
+    uint64 offset;
+} FileInfo;
+
+/************************************************************************/
+/*                       GetDefaultIOInterfaces()                       */
+/************************************************************************/
+
+const IOInterfaces *PCIDSK::GetDefaultIOInterfaces()
+{
+    static Win32IOInterface singleton_win32_interface;
+
+    return &singleton_win32_interface;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+void *
+Win32IOInterface::Open( std::string filename, std::string access ) const
+
+{
+    DWORD dwDesiredAccess, dwCreationDisposition, dwFlagsAndAttributes;
+    HANDLE hFile;
+
+    if( strchr(access.c_str(),'+') != NULL || strchr(access.c_str(),'w') != 0 )
+        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+    else
+        dwDesiredAccess = GENERIC_READ;
+
+    if( strstr(access.c_str(), "w") != NULL )
+        dwCreationDisposition = CREATE_ALWAYS;
+    else
+        dwCreationDisposition = OPEN_EXISTING;
+
+    dwFlagsAndAttributes = (dwDesiredAccess == GENERIC_READ) ? 
+                FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL, 
+    
+    hFile = CreateFileA(filename.c_str(), dwDesiredAccess, 
+                        FILE_SHARE_READ | FILE_SHARE_WRITE, 
+                        NULL, dwCreationDisposition,  dwFlagsAndAttributes, NULL);
+
+    if( hFile == INVALID_HANDLE_VALUE )
+    {
+        ThrowPCIDSKException( "Open(%s,%s) failed:\n%s", 
+                              filename.c_str(), access.c_str(), LastError() );
+    }
+    
+    FileInfo *fi = new FileInfo();
+    fi->hFile = hFile;
+    fi->offset = 0;
+
+    return fi;
+}
+
+/************************************************************************/
+/*                                Seek()                                */
+/************************************************************************/
+
+uint64 
+Win32IOInterface::Seek( void *io_handle, uint64 offset, int whence ) const
+
+{
+    FileInfo *fi = (FileInfo *) io_handle;
+    uint32       dwMoveMethod, dwMoveHigh;
+    uint32       nMoveLow;
+    LARGE_INTEGER li;
+
+    // seeks that do nothing are still surprisingly expensive with MSVCRT.
+    // try and short circuit if possible.
+    if( whence == SEEK_SET && offset == fi->offset )
+        return 0;
+
+    switch(whence)
+    {
+        case SEEK_CUR:
+            dwMoveMethod = FILE_CURRENT;
+            break;
+        case SEEK_END:
+            dwMoveMethod = FILE_END;
+            break;
+        case SEEK_SET:
+        default:
+            dwMoveMethod = FILE_BEGIN;
+            break;
+    }
+
+    li.QuadPart = offset;
+    nMoveLow = li.LowPart;
+    dwMoveHigh = li.HighPart;
+
+    SetLastError( 0 );
+    SetFilePointer(fi->hFile, (LONG) nMoveLow, (PLONG)&dwMoveHigh,
+                   dwMoveMethod);
+
+    if( GetLastError() != NO_ERROR )
+    {
+#ifdef notdef
+        LPVOID      lpMsgBuf = NULL;
+        
+        FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER 
+                       | FORMAT_MESSAGE_FROM_SYSTEM
+                       | FORMAT_MESSAGE_IGNORE_INSERTS,
+                       NULL, GetLastError(), 
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
+                       (LPTSTR) &lpMsgBuf, 0, NULL );
+ 
+        printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf );
+        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n", 
+                (GUInt32) nOffset, nMoveLow, dwMoveHigh );
+#endif
+        ThrowPCIDSKException( "Seek(%d,%d): %s (%d)", 
+                              (int) offset, whence, 
+                              LastError(), GetLastError() );
+        return -1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Update our offset.                                              */
+/* -------------------------------------------------------------------- */
+    if( whence == SEEK_SET )
+        fi->offset = offset;
+    else if( whence == SEEK_END )
+    {
+        LARGE_INTEGER   li;
+
+        li.HighPart = 0;
+        li.LowPart = SetFilePointer( fi->hFile, 0, (PLONG) &(li.HighPart), 
+                                     FILE_CURRENT );
+        fi->offset = li.QuadPart;
+    }
+    else if( whence == SEEK_CUR )
+        fi->offset += offset;
+
+    return 0;
+}
+
+/************************************************************************/
+/*                                Tell()                                */
+/************************************************************************/
+
+uint64 Win32IOInterface::Tell( void *io_handle ) const
+
+{
+    FileInfo *fi = (FileInfo *) io_handle;
+
+    return fi->offset;
+}
+
+/************************************************************************/
+/*                                Read()                                */
+/************************************************************************/
+
+uint64 Win32IOInterface::Read( void *buffer, uint64 size, uint64 nmemb, 
+                               void *io_handle ) const
+
+{
+    FileInfo *fi = (FileInfo *) io_handle;
+
+    errno = 0;
+
+    DWORD       dwSizeRead;
+    size_t      result;
+
+    if( !ReadFile(fi->hFile, buffer, (DWORD)(size*nmemb), &dwSizeRead, NULL) )
+    {
+        result = 0;
+    }
+    else if( size == 0 )
+        result = 0;
+    else
+        result = (size_t) (dwSizeRead / size);
+
+    if( errno != 0 && result == 0 && nmemb != 0 )
+        ThrowPCIDSKException( "Read(%d): %s", 
+                              (int) size * nmemb,
+                              LastError() );
+
+    fi->offset += size*result;
+
+    return result;
+}
+
+/************************************************************************/
+/*                               Write()                                */
+/************************************************************************/
+
+uint64 Win32IOInterface::Write( const void *buffer, uint64 size, uint64 nmemb, 
+                                void *io_handle ) const
+
+{
+    FileInfo *fi = (FileInfo *) io_handle;
+
+    errno = 0;
+
+    DWORD       dwSizeRead;
+    size_t      result;
+
+    if( !WriteFile(fi->hFile, buffer, (DWORD)(size*nmemb), &dwSizeRead, NULL) )
+    {
+        result = 0;
+    }
+    else if( size == 0 )
+        result = 0;
+    else
+        result = (size_t) (dwSizeRead / size);
+
+    if( errno != 0 && result == 0 && nmemb != 0 )
+        ThrowPCIDSKException( "Write(%d): %s", 
+                                   (int) size * nmemb,
+                                   LastError() );
+
+    fi->offset += size*result;
+
+    return result;
+}
+
+/************************************************************************/
+/*                                Eof()                                 */
+/************************************************************************/
+
+int Win32IOInterface::Eof( void *io_handle ) const
+
+{
+    FileInfo *fi = (FileInfo *) io_handle;
+    uint64       nCur, nEnd;
+
+    nCur = Tell( io_handle );
+    Seek( io_handle, 0, SEEK_END );
+    nEnd = Tell( io_handle );
+    Seek( io_handle, nCur, SEEK_SET );
+
+    return (nCur == nEnd);
+}
+
+/************************************************************************/
+/*                               Flush()                                */
+/************************************************************************/
+
+int Win32IOInterface::Flush( void *io_handle ) const
+
+{
+    FileInfo *fi = (FileInfo *) io_handle;
+
+    FlushFileBuffers( fi->hFile );
+
+    return 0;
+}
+
+/************************************************************************/
+/*                               Close()                                */
+/************************************************************************/
+
+int Win32IOInterface::Close( void *io_handle ) const
+
+{
+    FileInfo *fi = (FileInfo *) io_handle;
+
+    int result = CloseHandle( fi->hFile ) ? 0 : -1;
+    delete fi;
+
+    return result;
+}
+
+/************************************************************************/
+/*                             LastError()                              */
+/*                                                                      */
+/*      Return a string representation of the last error.               */
+/************************************************************************/
+
+const char *Win32IOInterface::LastError() const
+
+{
+    return "";
+}
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp b/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
new file mode 100644
index 0000000..40e7d8f
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
@@ -0,0 +1,334 @@
+/******************************************************************************
+ *
+ * Purpose:  Implementation of the CPCIDSK_TEX class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2010
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 "pcidsk_exception.h"
+#include "segment/cpcidsk_array.h"
+#include "core/cpcidskfile.h"
+#include <cstring>
+#include <sstream>
+#include <cassert>
+#include "core/pcidsk_utils.h"
+
+using namespace PCIDSK;
+
+/************************************************************************/
+/*                            CPCIDSK_ARRAY()                           */
+/************************************************************************/
+
+CPCIDSK_ARRAY::CPCIDSK_ARRAY( PCIDSKFile *file, int segment,
+                              const char *segment_pointer )
+        : CPCIDSKSegment( file, segment, segment_pointer ),
+        loaded_(false),mbModified(false)
+{
+    MAX_DIMENSIONS = 8;
+    Load();
+}
+
+/************************************************************************/
+/*                            ~CPCIDSK_ARRAY                            */
+/************************************************************************/
+
+CPCIDSK_ARRAY::~CPCIDSK_ARRAY()
+
+{
+}
+
+/**
+ * Load the contents of the segment
+ */
+void CPCIDSK_ARRAY::Load()
+{
+    // Check if we've already loaded the segment into memory
+    if (loaded_) {
+        return;
+    }
+
+    PCIDSKBuffer& seg_header = this->GetHeader();
+    seg_data.SetSize(GetContentSize());
+    ReadFromFile(seg_data.buffer, 0, seg_data.buffer_size);
+
+    if(std::strncmp(seg_header.buffer+160, "64R     ", 8))
+    {
+        seg_header.Put("64R     ",160,8);
+        loaded_ = true;
+        return ;
+    }
+
+    int nDimension = seg_header.GetInt(160+8,8);
+    if(nDimension < 1 || nDimension > MAX_DIMENSIONS)
+    {
+        std::stringstream oStream;
+        oStream << "Invalid array dimension " << nDimension;
+        oStream << " stored in the segment.";
+        std::string oMsg = oStream.str();
+        throw PCIDSKException(oMsg.c_str());
+    }
+    mnDimension = static_cast<unsigned char>(nDimension);
+
+    moSizes.clear();
+    for( int i = 0; i < mnDimension; i++ )
+    {
+        int nSize = seg_header.GetInt(160+24 + i*8,8);
+        if(nSize < 1)
+        {
+            std::stringstream oStream;
+            oStream << "Invalid size " << nSize << " for dimension " << i+1;
+            std::string oMsg = oStream.str();
+            throw PCIDSKException(oMsg.c_str());
+        }
+		moSizes.push_back( nSize );
+    }
+
+    //calculate the total number of elements in the array.
+    unsigned int nElements = 1;
+    for(unsigned int i=0 ; i < moSizes.size() ; i++)
+    {
+        nElements *= moSizes[i];
+    }
+    
+    for( unsigned int i = 0; i < nElements; i++ )
+    {
+        const double* pdValue = (const double*)seg_data.Get(i*8,8);
+        char uValue[8];
+        std::memcpy(uValue,pdValue,8);
+        SwapData(uValue,8,1);
+        double dValue = *((double*)uValue);
+        moArray.push_back(dValue);
+    }
+
+    //PCIDSK doesn't have support for headers.
+
+    // We've now loaded the structure up with data. Mark it as being loaded 
+    // properly.
+    loaded_ = true;
+    
+}
+
+/**
+ * Write the segment on disk
+ */
+void CPCIDSK_ARRAY::Write(void)
+{
+    //We are not writing if nothing was loaded.
+    if (!loaded_) {
+        return;
+    }
+
+    PCIDSKBuffer& seg_header = this->GetHeader();
+    int nBlocks = (moArray.size()*8 + 511)/512 ;
+    unsigned int nSizeBuffer = (nBlocks)*512 ;
+    //64 values can be put into 512 bytes.
+    unsigned int nRest = nBlocks*64 - moArray.size();
+
+    seg_data.SetSize(nSizeBuffer);
+
+    seg_header.Put("64R     ",160,8);
+    seg_header.Put((int)mnDimension,160+8,8);
+
+    for( int i = 0; i < mnDimension; i++ )
+    {
+        int nSize = static_cast<int>(moSizes[i]);
+        seg_header.Put(nSize,160+24 + i*8,8);
+    }
+
+    for( unsigned int i = 0; i < moArray.size(); i++ )
+    {
+        double dValue = moArray[i];
+        SwapData(&dValue,8,1);
+        seg_data.PutBin(dValue,i*8);
+    }
+
+    //set the end of the buffer to 0.
+    for( unsigned int i=0 ; i < nRest ; i++)
+    {
+        seg_data.Put(0.0,(moArray.size()+i)*8,8,"%22.14f");
+    }
+
+    WriteToFile(seg_data.buffer,0,seg_data.buffer_size);
+
+    mbModified = false;
+}
+
+/**
+ * Synchronize the segement, if it was modified then
+ * write it into disk.
+ */
+void CPCIDSK_ARRAY::Synchronize()
+{
+    if(mbModified)
+    {
+        this->Write();
+        //write the modified header
+        file->WriteToFile( header.buffer, data_offset, 1024 );
+    }
+}
+
+/**
+ * This function returns the number of dimension in the array.
+ * an array segment can have minimum 1 dimension and maximum
+ * 8 dimension.
+ *
+ * @return the dimension of the array in [1,8]
+ */
+unsigned char CPCIDSK_ARRAY::GetDimensionCount() const 
+{
+    return mnDimension;
+}
+
+/**
+ * This function set the dimension of the array. the dimension
+ * must be in [1,8] or a pci::Exception is thrown.
+ *
+ * @param nDim number of dimension, should be in [1,8]
+ */
+void CPCIDSK_ARRAY::SetDimensionCount(unsigned char nDim) 
+{
+    if(nDim < 1 || nDim > 8)
+    {
+        throw PCIDSKException("An array cannot have a "
+            "dimension bigger than 8 or smaller than 1.");
+    }
+    mnDimension = nDim;
+    mbModified = true;
+}
+
+/**
+ * Get the number of element that can be put in each of the dimension
+ * of the array. the size of the return vector is GetDimensionCount().
+ *
+ * @return the size of each dimension.
+ */
+const std::vector<unsigned int>& CPCIDSK_ARRAY::GetSizes() const 
+{
+    return moSizes;
+}
+
+/**
+ * Set the size of each dimension. If the size of the array is bigger
+ * or smaller than GetDimensionCount(), then a pci::Exception is thrown
+ * if one of the sizes is 0, then a pci::Exception is thrown.
+ *
+ * @param oSizes the size of each dimension 
+ */
+void CPCIDSK_ARRAY::SetSizes(const std::vector<unsigned int>& oSizes) 
+{
+    if(oSizes.size() != GetDimensionCount())
+    {
+        throw PCIDSKException("You need to specify the sizes"
+            " for each dimension of the array");
+    }
+
+    for( unsigned int i=0 ; i < oSizes.size() ; i++)
+    {
+        if(oSizes[i] == 0)
+        {
+            throw PCIDSKException("You cannot define the size of a dimension to 0.");
+        }
+    }
+    moSizes = oSizes;
+    mbModified = true;
+}
+
+/**
+ * Get the array in a vector. the size of this vector is
+ * GetSize()[0]*GetSize()[2]*...*GetSize()[GetDimensionCount()-1].
+ * value are stored in the following order inside this vector:
+ * ViDj = Value i of Dimension j
+ * n = size of dimension 1
+ * p = size of dimension 2
+ * h = size of dimension k
+ *
+ * V1D1 ... VnD1 V1D2 ... VpD2 ... V1Dk ... VhDk 
+ *
+ * @return the array.
+ */
+const std::vector<double>& CPCIDSK_ARRAY::GetArray() const 
+{
+    return moArray;
+}
+
+/**
+ * Set the array in the segment. the size of this vector is
+ * GetSize()[0]*GetSize()[2]*...*GetSize()[GetDimensionCount()-1].
+ * value are stored in the following order inside this vector:
+ * ViDj = Value i of Dimension j
+ * n = size of dimension 1
+ * p = size of dimension 2
+ * h = size of dimension k
+ *
+ * V1D1 ... VnD1 V1D2 ... VpD2 ... V1Dk ... VhDk 
+ *
+ * If the size of oArray doesn't match the sizes and dimensions
+ * then a pci::Exception is thrown.
+ *
+ * @param oArray the array.
+ */
+void CPCIDSK_ARRAY::SetArray(const std::vector<double>& oArray) 
+{
+    unsigned int nLength = 1;
+    for( unsigned int i=0 ; i < moSizes.size() ; i++)
+    {
+        nLength *= moSizes[i];
+    }
+
+    if(nLength != oArray.size())
+    {
+        throw PCIDSKException("the size of this array doesn't match "
+            "the size specified in GetSizes(). See documentation for"
+            " more information.");
+    }
+    moArray = oArray;
+    mbModified = true;
+}
+
+/**
+ * Get the headers of this array. If no headers has be specified, then
+ * this function return an empty vector.
+ * the size of this vector should be equal to the size of the first dimension
+ * returned by GetSize()[0]
+ *
+ * @return the headers.
+ */
+const std::vector<std::string>&  CPCIDSK_ARRAY::GetHeaders() const 
+{
+    return moHeaders;
+}
+
+/**
+ * Set the headers of this array. An empty vector can be specified to clear
+ * the headers in the segment.
+ * the size of this vector should be equal to the size of the first dimension
+ * returned by GetSize()[0]. If it is not the case, a pci::Exception is thrown.
+ *
+ * @param oHeaders the headers.
+ */
+void CPCIDSK_ARRAY::SetHeaders(const std::vector<std::string>& oHeaders) 
+{
+    moHeaders = oHeaders;
+    mbModified = true;
+}
+
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_array.h b/frmts/pcidsk/sdk/segment/cpcidsk_array.h
new file mode 100644
index 0000000..0618066
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_array.h
@@ -0,0 +1,90 @@
+/******************************************************************************
+ *
+ * Purpose:  Declaration of the CPCIDSK_ARRAY class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2010
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_SEGMENT_PCIDSK_ARRAY_H
+#define __INCLUDE_SEGMENT_PCIDSK_ARRAY_H
+
+#include "pcidsk_config.h"
+#include "pcidsk_types.h"
+#include "pcidsk_array.h"
+#include "pcidsk_buffer.h"
+#include "segment/cpcidsksegment.h"
+
+#include <string>
+
+namespace PCIDSK
+{
+    class PCIDSKFile;
+    
+    /************************************************************************/
+    /*                            CPCIDSK_ARRAY                             */
+    /************************************************************************/
+
+    class CPCIDSK_ARRAY : public CPCIDSKSegment, 
+                          public PCIDSK_ARRAY
+    {
+    public:
+        CPCIDSK_ARRAY( PCIDSKFile *file, int segment,const char *segment_pointer);
+
+        virtual     ~CPCIDSK_ARRAY();
+
+        // CPCIDSK_ARRAY
+        unsigned char GetDimensionCount() const ;
+        void SetDimensionCount(unsigned char nDim) ;
+        const std::vector<unsigned int>& GetSizes() const ;
+        void SetSizes(const std::vector<unsigned int>& oSizes) ;
+        const std::vector<double>& GetArray() const ;
+        void SetArray(const std::vector<double>& oArray) ;
+
+        //synchronize the segment on disk.
+        void Synchronize();
+    private:
+
+        //Headers are not supported by PCIDSK, we keep the function
+        //private here in case we want to add the feature
+        //in the future.
+        const std::vector<std::string>&  GetHeaders() const ;
+        void SetHeaders(const std::vector<std::string>& oHeaders) ; 
+        
+        // Helper housekeeping functions
+        void Load();
+        void Write();
+
+        //members
+        PCIDSKBuffer seg_data;
+        bool loaded_;
+        bool mbModified;
+        unsigned char MAX_DIMENSIONS;
+
+        //Array information
+        std::vector<std::string> moHeaders;
+        unsigned char mnDimension;
+        std::vector<unsigned int> moSizes;
+        std::vector<double> moArray;
+    };
+} // end namespace PCIDSK
+
+#endif // __INCLUDE_SEGMENT_PCIDSK_ARRAY_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskads40model.cpp b/frmts/pcidsk/sdk/segment/cpcidskads40model.cpp
new file mode 100644
index 0000000..5c92189
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidskads40model.cpp
@@ -0,0 +1,147 @@
+/******************************************************************************
+ *
+ * Purpose:  Implementation of the CPCIDSKADS40ModelSegment class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 "pcidsk_ads40.h"
+#include "segment/cpcidsksegment.h"
+#include "core/pcidsk_utils.h"
+#include "pcidsk_exception.h"
+#include "segment/cpcidskads40model.h"
+
+#include <vector>
+#include <string>
+#include <cassert>
+#include <cstring>
+
+using namespace PCIDSK;
+
+// Struct to store details of the RPC model
+struct CPCIDSKADS40ModelSegment::PCIDSKADS40Info
+{
+    std::string path;
+    
+    // The raw segment data
+    PCIDSKBuffer seg_data;
+};
+
+CPCIDSKADS40ModelSegment::CPCIDSKADS40ModelSegment(PCIDSKFile *file, 
+                                                   int segment,
+                                                   const char *segment_pointer) :
+    CPCIDSKSegment(file, segment, segment_pointer), 
+    pimpl_(new CPCIDSKADS40ModelSegment::PCIDSKADS40Info), 
+    loaded_(false),mbModified(false)
+{
+    Load();
+}
+
+
+CPCIDSKADS40ModelSegment::~CPCIDSKADS40ModelSegment()
+{
+    delete pimpl_;
+}
+
+// Load the contents of the segment
+void CPCIDSKADS40ModelSegment::Load()
+{
+    // Check if we've already loaded the segment into memory
+    if (loaded_) {
+        return;
+    }
+    
+    assert(data_size - 1024 == 1 * 512);
+    
+    pimpl_->seg_data.SetSize(data_size - 1024); // should be 1 * 512
+    
+    ReadFromFile(pimpl_->seg_data.buffer, 0, data_size - 1024);
+    
+    // The ADS40 Model Segment is defined as follows:
+    // ADs40 Segment: 1 512-byte blocks
+    
+    // Block 1:
+    // Bytes   0-7: 'ADS40  '
+    // Byte    8-512: the path
+    
+    if (std::strncmp(pimpl_->seg_data.buffer, "ADS40   ", 8)) 
+    {
+        pimpl_->seg_data.Put("ADS40   ",0,8);
+        return;
+        // Something has gone terribly wrong!
+        /*throw PCIDSKException("A segment that was previously identified as an RFMODEL "
+            "segment does not contain the appropriate data. Found: [%s]", 
+            std::string(pimpl_->seg_data.buffer, 8).c_str());*/
+    }
+    
+    pimpl_->path = std::string(&pimpl_->seg_data.buffer[8]);
+    
+    // We've now loaded the structure up with data. Mark it as being loaded 
+    // properly.
+    loaded_ = true;
+    
+}
+
+void CPCIDSKADS40ModelSegment::Write(void)
+{
+    //We are not writing if nothing was loaded.
+    if (!loaded_) {
+        return;
+    }
+      
+    pimpl_->seg_data.Put("ADS40   ",0,8);
+    pimpl_->seg_data.Put(pimpl_->path.c_str(),8,pimpl_->path.size());
+
+    WriteToFile(pimpl_->seg_data.buffer,0,data_size-1024);
+    mbModified = false;
+}
+
+// Get sensor name
+std::string CPCIDSKADS40ModelSegment::GetPath(void) const
+{
+    return pimpl_->path;
+}
+
+// Set sensor name
+void CPCIDSKADS40ModelSegment::SetPath(const std::string& oPath)
+{
+    if(oPath.size() < 504)
+    {
+        pimpl_->path = oPath;
+        mbModified = true;
+    }
+    else
+    {
+        throw PCIDSKException("The size of the path cannot be"
+                              " bigger than 504 characters.");
+    }
+}
+
+void CPCIDSKADS40ModelSegment::Synchronize()
+{
+    if(mbModified)
+    {
+        this->Write();
+    }
+}
+
diff --git a/frmts/pcidsk/sdk/segment/cpcidskads40model.h b/frmts/pcidsk/sdk/segment/cpcidskads40model.h
new file mode 100644
index 0000000..5d2987c
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidskads40model.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * Purpose: Support for reading and manipulating PCIDSK ADS40 Segments
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
+#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
+ 
+#include "pcidsk_ads40.h"
+#include "segment/cpcidsksegment.h"
+ 
+namespace PCIDSK {
+    class PCIDSKFile;
+    
+    class CPCIDSKADS40ModelSegment : public PCIDSKADS40Segment,
+                                     public CPCIDSKSegment
+    {
+    public:
+        CPCIDSKADS40ModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer);
+        ~CPCIDSKADS40ModelSegment();
+        
+        // Get path
+        std::string GetPath(void) const;
+        // Set path
+        void SetPath(const std::string& oPath);
+
+        //synchronize the segment on disk.
+        void Synchronize();
+    private:
+        // Helper housekeeping functions
+        void Load();
+        void Write();
+        
+        struct PCIDSKADS40Info;
+        PCIDSKADS40Info *pimpl_;
+        bool loaded_;
+        bool mbModified;
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKADS40MODEL_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
index 47b3d39..e31f6ea 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
@@ -30,6 +30,8 @@
 
 #include <utility>
 #include <vector>
+#include <string>
+#include <sstream>
 #include <cassert>
 #include <cstring>
 
@@ -321,7 +323,7 @@ namespace {
         map_units.clear();
         utm_units.clear();
     /* -------------------------------------------------------------------- */
-    /*	Read the header block						*/
+    /*	Read the header block						    */
     /* -------------------------------------------------------------------- */
     
         if(strncmp(buf.buffer,"APMODEL ",8))
@@ -332,14 +334,14 @@ namespace {
         }
 
     /* -------------------------------------------------------------------- */
-    /*      Allocate the APModel.                                         	*/
+    /*      Allocate the APModel.                                           */
     /* -------------------------------------------------------------------- */
 
-        if (!std::strncmp(&buf.buffer[22],"DS",2))
-    	    downsample = buf.GetInt(22, 3);
+        downsample = buf.GetInt(24, 3);
+        if (0 >= downsample) downsample = 0;
 
     /* -------------------------------------------------------------------- */
-    /*      Read the values							*/
+    /*      Read the values					            */
     /* -------------------------------------------------------------------- */
         pixels = buf.GetInt(0 * 22 + 512, 22);
         lines = buf.GetInt(1 * 22 + 512, 22);
@@ -468,9 +470,27 @@ namespace {
             buf.Get(512 * 4, 3, utm_units);
         }
 
-        //ProjParms2Info(szTmp, APModel->sProjection);
         // Parse the Proj Params
-    
+        proj_parms.clear();
+
+        if (*buf.Get(512 * 4 + 256, 1) == '\0')
+        {
+            for (std::size_t i = 0; i < 18; i++)
+            {
+                proj_parms.push_back(0.0);
+            }
+        }
+        else
+        {
+            std::stringstream proj_stream(std::string(buf.Get(512 * 4 + 256, 256)));
+
+            for (std::size_t i = 0; i < 18; i++)
+            {
+                double parm;
+                proj_stream >> parm;
+                proj_parms.push_back(parm);
+            }
+        }
     }
 } // end anonymous namespace
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp
new file mode 100644
index 0000000..567eaed
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.cpp
@@ -0,0 +1,135 @@
+/******************************************************************************
+ *
+ * Purpose:  Implementation of the CPCIDSKBinarySegment class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2010
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 "segment/cpcidskbinarysegment.h"
+#include "segment/cpcidsksegment.h"
+#include "core/pcidsk_utils.h"
+#include "pcidsk_exception.h"
+#include "core/pcidsk_utils.h"
+
+#include <vector>
+#include <string>
+#include <cassert>
+#include <cstring>
+
+using namespace PCIDSK;
+
+/**
+ * Binary Segment constructor
+ * @param[in,out] file the PCIDSK file
+ * @param[in] segment the segment index
+ * @param[in] segment_pointer the segement pointer
+ * @param[in] bLoad true to load the segment, else false (default true)
+ */
+CPCIDSKBinarySegment::CPCIDSKBinarySegment(PCIDSKFile *file, 
+                                           int segment,
+                                           const char *segment_pointer,
+                                           bool bLoad) :
+    CPCIDSKSegment(file, segment, segment_pointer),
+    loaded_(false),mbModified(false)
+{
+    if (true == bLoad)
+    {
+        Load();
+    }
+    return;
+}// Initializer constructor
+
+
+CPCIDSKBinarySegment::~CPCIDSKBinarySegment()
+{
+}
+
+/**
+ * Load the contents of the segment
+ */
+void CPCIDSKBinarySegment::Load()
+{
+    // Check if we've already loaded the segment into memory
+    if (loaded_) {
+        return;
+    }
+
+    seg_data.SetSize((int)data_size - 1024);
+    
+    ReadFromFile(seg_data.buffer, 0, data_size - 1024);
+    
+    // Mark it as being loaded properly.
+    loaded_ = true;
+    
+}
+
+/**
+ * Write the segment on disk
+ */
+void CPCIDSKBinarySegment::Write(void)
+{
+    //We are not writing if nothing was loaded.
+    if (!loaded_) {
+        return;
+    }
+
+    WriteToFile(seg_data.buffer, 0, seg_data.buffer_size);
+
+    mbModified = false;
+}
+
+/**
+ * Synchronize the segement, if it was modified then
+ * write it into disk.
+ */
+void CPCIDSKBinarySegment::Synchronize()
+{
+    if(mbModified)
+    {
+        this->Write();
+    }
+}
+
+void
+CPCIDSKBinarySegment::SetBuffer(const char* pabyBuf, 
+                                unsigned int nBufSize)
+{
+    // Round the buffer size up to the next multiple of 512.
+    int nNumBlocks = nBufSize / 512 + ((0 == nBufSize % 512) ? 0 : 1);
+    unsigned int nAllocBufSize = 512 * nNumBlocks;
+
+    seg_data.SetSize((int)nAllocBufSize);
+    data_size = nAllocBufSize + 1024; // Incl. header
+
+    memcpy(seg_data.buffer, pabyBuf, nBufSize);
+
+    // Fill unused data at end with zeroes.
+    if (nBufSize < nAllocBufSize)
+    {
+        memset(seg_data.buffer + nBufSize, 0, 
+            nAllocBufSize - nBufSize);
+    }
+    mbModified = true;
+
+    return;
+}// SetBuffer
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
new file mode 100644
index 0000000..f3d9ce5
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * Purpose: Support for reading and manipulating general PCIDSK Binary Segments
+ * 
+ ******************************************************************************
+ * Copyright (c) 2010
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
+#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
+ 
+#include "pcidsk_binary.h"
+#include "segment/cpcidsksegment.h"
+
+namespace PCIDSK {
+    class PCIDSKFile;
+
+    class CPCIDSKBinarySegment : public PCIDSKBinarySegment,
+        public CPCIDSKSegment
+    {
+    public:
+        CPCIDSKBinarySegment(PCIDSKFile *file, int segment,
+            const char *segment_pointer, bool bLoad=true);
+        ~CPCIDSKBinarySegment();
+
+        const char* GetBuffer(void) const
+        {
+            return seg_data.buffer;
+        }
+
+        unsigned int GetBufferSize(void) const
+        {
+            return seg_data.buffer_size;
+        }
+        void SetBuffer(const char* pabyBuf, 
+            unsigned int nBufSize);
+
+        //synchronize the segment on disk.
+        void Synchronize();
+    private:
+        
+        // Helper housekeeping functions
+        void Load();
+        void Write();
+
+    //functions to read/write binary information
+    protected:
+        // The raw segment data
+        PCIDSKBuffer seg_data;
+        bool loaded_;
+        bool mbModified;
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKBINARY_SEG_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp b/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp
index 7d7bb1b..1796007 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskbitmap.cpp
@@ -479,4 +479,57 @@ void CPCIDSKBitmap::PushHistory( const std::string &app,
     CPCIDSKSegment::PushHistory( app, message );
 }
                                  
+/************************************************************************/
+/*                            GetChanInfo()                             */
+/************************************************************************/
+void CPCIDSKBitmap::GetChanInfo( std::string &filename, uint64 &image_offset, 
+                                 uint64 &pixel_offset, uint64 &line_offset, 
+                                 bool &little_endian ) const
+
+{
+    image_offset = 0;
+    pixel_offset = 0;
+    line_offset = 0;
+    little_endian = true;
+    filename = "";
+}
+
+/************************************************************************/
+/*                            SetChanInfo()                             */
+/************************************************************************/
+
+void CPCIDSKBitmap::SetChanInfo( std::string filename, uint64 image_offset, 
+                                  uint64 pixel_offset, uint64 line_offset, 
+                                  bool little_endian )
+
+{
+    ThrowPCIDSKException( "Attempt to SetChanInfo() on a bitmap." );
+}
 
+/************************************************************************/
+/*                            GetEChanInfo()                            */
+/************************************************************************/
+void CPCIDSKBitmap::GetEChanInfo( std::string &filename, int &echannel,
+                                  int &exoff, int &eyoff, 
+                                  int &exsize, int &eysize ) const
+    
+{
+    echannel = 0;
+    exoff = 0;
+    eyoff = 0;
+    exsize = 0;
+    eysize = 0;
+    filename = "";
+}
+
+/************************************************************************/
+/*                            SetEChanInfo()                            */
+/************************************************************************/
+
+void CPCIDSKBitmap::SetEChanInfo( std::string filename, int echannel,
+                                  int exoff, int eyoff, 
+                                  int exsize, int eysize )
+
+{
+    ThrowPCIDSKException( "Attempt to SetEChanInfo() on a bitmap." );
+}
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbitmap.h b/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
index f54faa7..826125b 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
@@ -85,6 +85,19 @@ namespace PCIDSK
         virtual void PushHistory(const std::string &app,
                                  const std::string &message);
 
+        virtual void GetChanInfo( std::string &filename, uint64 &image_offset, 
+                                  uint64 &pixel_offset, uint64 &line_offset, 
+                                  bool &little_endian ) const;
+        virtual void SetChanInfo( std::string filename, uint64 image_offset, 
+                                  uint64 pixel_offset, uint64 line_offset, 
+                                  bool little_endian );
+        virtual void GetEChanInfo( std::string &filename, int &echannel,
+                                   int &exoff, int &eyoff, 
+                                   int &exsize, int &eysize ) const;
+        virtual void SetEChanInfo( std::string filename, int echannel,
+                                   int exoff, int eyoff, 
+                                   int exsize, int eysize );
+
     private:
         bool      loaded;
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
new file mode 100644
index 0000000..5b0e3da
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
@@ -0,0 +1,1398 @@
+/******************************************************************************
+ *
+ * Purpose:  Implementation of the CPCIDSKEphemerisSegment class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 "segment/cpcidsksegment.h"
+#include "core/pcidsk_utils.h"
+#include "segment/cpcidskephemerissegment.h"
+#include "pcidsk_exception.h"
+#include "core/pcidsk_utils.h"
+
+#include <vector>
+#include <string>
+#include <cassert>
+#include <cstring>
+
+using namespace PCIDSK;
+
+namespace
+{
+    /** 
+     * Function to get the minimum value of two values.
+     * 
+     * @param a The first value.
+     * @param b The second value.
+     * 
+     * @return The minimum value of the two specified values.
+     */
+    int MinFunction(int a,int b) 
+    {
+        return (a<b)?a:b;
+    }
+}
+
+/**
+ * Ephemeris Segment constructor
+ * @param file the PCIDSK file
+ * @param segment the segment index
+ * @param segment_pointer the segement pointer
+ * @param bLoad true to load the segment, else false (default true)
+ */
+CPCIDSKEphemerisSegment::CPCIDSKEphemerisSegment(PCIDSKFile *file, 
+                                                   int segment,
+                                                   const char *segment_pointer,
+                                                   bool bLoad) :
+    CPCIDSKSegment(file, segment, segment_pointer),
+    loaded_(false),mbModified(false)
+{
+    mpoEphemeris = NULL;
+    if(bLoad)
+    {
+        Load();
+    }
+}
+
+
+CPCIDSKEphemerisSegment::~CPCIDSKEphemerisSegment()
+{
+    delete mpoEphemeris;
+}
+
+/**
+ * Load the contents of the segment
+ */
+void CPCIDSKEphemerisSegment::Load()
+{
+    // Check if we've already loaded the segment into memory
+    if (loaded_) {
+        return;
+    }
+
+    seg_data.SetSize((int)data_size - 1024);
+    
+    ReadFromFile(seg_data.buffer, 0, data_size - 1024);
+
+    // We test the name of the binary segment before starting to read 
+    // the buffer.
+    if (std::strncmp(seg_data.buffer, "ORBIT   ", 8)) 
+    {
+        seg_data.Put("ORBIT   ",0,8);
+        loaded_ = true;
+        return ;
+    }
+    
+    mpoEphemeris = BinaryToEphemeris(0);
+
+    // We've now loaded the structure up with data. Mark it as being loaded 
+    // properly.
+    loaded_ = true;
+    
+}
+
+/**
+ * Write the segment on disk
+ */
+void CPCIDSKEphemerisSegment::Write(void)
+{
+    //We are not writing if nothing was loaded.
+    if (!loaded_) {
+        return;
+    }
+
+    seg_data.Put("ORBIT   ",0,8);
+
+    EphemerisToBinary( mpoEphemeris, 0);
+    WriteToFile(seg_data.buffer,0,seg_data.buffer_size);
+
+    mbModified = false;
+}
+
+/**
+ * Synchronize the segement, if it was modified then
+ * write it into disk.
+ */
+void CPCIDSKEphemerisSegment::Synchronize()
+{
+    if(mbModified)
+    {
+        this->Write();
+    }
+}
+
+/************************************************************************/
+/*			ConvertDeg()					*/
+/************************************************************************/
+/**									
+ * if mode is 0, convert angle from 0 to 360 to 0 to 180 and 0 to -180 
+ * if mode is 1, convert angle from 0 to 180 and 0 to -180 to 0 to 360 
+ *
+ * @param degree the degree
+ * @param mode  the mode
+ */
+double CPCIDSKEphemerisSegment::ConvertDeg(double degree, int mode)
+{
+    double result;
+
+    if (mode == 0)
+    {
+/* -------------------------------------------------------------------- */
+/*	degree is in range of 0 to 360					*/
+/* -------------------------------------------------------------------- */
+	if (degree > 180)
+	    result = degree - 360;
+	else
+	    result = degree;
+    }
+    else
+    {
+/* -------------------------------------------------------------------- */
+/*	degree is in range of 0 to 180 and 0 to -180			*/
+/* -------------------------------------------------------------------- */
+	if (degree < 0)
+	    result = 360 + degree;
+	else
+	    result = degree;
+	
+    }
+    return (result);
+}
+
+/************************************************************************/
+/*		      ReadAvhrrEphemerisSegment()                       */
+/************************************************************************/
+/**                                                                      
+ *  Read the contents of blocks 9, 11, and onwards from the orbit	
+ *  segment into the EphemerisSeg_t structure.	
+ * @param nStartBlock where to start to read in the buffer
+ * @param psEphSegRec the structure to populate with information.
+ */   
+void 
+CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
+                                         EphemerisSeg_t *psEphSegRec)
+{
+    int  nBlock = 0, nLine = 0;
+    int nPos = 0;
+    AvhrrSeg_t *as = NULL;
+
+    int nDataLength = seg_data.buffer_size;
+/* -------------------------------------------------------------------- */
+/*  Allocate the AVHRR segment portion of EphemerisSeg_t.		*/
+/* -------------------------------------------------------------------- */
+    psEphSegRec->AvhrrSeg = new AvhrrSeg_t();
+    as = psEphSegRec->AvhrrSeg;
+
+/* -------------------------------------------------------------------- */
+/*  Read in the Nineth Block which contains general info + ephemeris	*/
+/*  info as well.							*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 8*512;
+    
+    as->szImageFormat = seg_data.Get(nPos, 16);
+    as->nImageXSize = seg_data.GetInt(nPos+16, 16);
+    as->nImageYSize = seg_data.GetInt(nPos+32, 16);
+
+    
+    if ( std::strncmp(seg_data.Get(nPos+48,9), "ASCENDING", 9)==0 )
+        as->bIsAscending = true;
+    else
+        as->bIsAscending = false;
+    if ( std::strncmp(seg_data.Get(nPos+64,7), "ROTATED", 7)==0 )
+        as->bIsImageRotated = true;
+    else
+        as->bIsImageRotated = false;
+
+    as->szOrbitNumber = seg_data.Get(nPos+80, 16);
+    as->szAscendDescendNodeFlag = seg_data.Get(nPos+96,16);
+    as->szEpochYearAndDay = seg_data.Get(nPos+112,16);
+    as->szEpochTimeWithinDay = seg_data.Get(nPos+128,16);
+    as->szTimeDiffStationSatelliteMsec = seg_data.Get(nPos+144,16);
+    as->szActualSensorScanRate = seg_data.Get(nPos+160,16);
+    as->szIdentOfOrbitInfoSource = seg_data.Get(nPos+176,16);
+    as->szInternationalDesignator = seg_data.Get(nPos+192,16);
+    as->szOrbitNumAtEpoch = seg_data.Get(nPos+208,16);
+    as->szJulianDayAscendNode = seg_data.Get(nPos+224,16);
+    as->szEpochYear = seg_data.Get(nPos+240,16);
+    as->szEpochMonth = seg_data.Get(nPos+256,16);
+    as->szEpochDay = seg_data.Get(nPos+272,16);
+    as->szEpochHour = seg_data.Get(nPos+288,16);
+    as->szEpochMinute = seg_data.Get(nPos+304,16);
+    as->szEpochSecond = seg_data.Get(nPos+320,16);
+    as->szPointOfAriesDegrees = seg_data.Get(nPos+336,16);
+    as->szAnomalisticPeriod = seg_data.Get(nPos+352,16);
+    as->szNodalPeriod = seg_data.Get(nPos+368,16);
+    as->szEccentricity = seg_data.Get(nPos+384,16);
+    as->szArgumentOfPerigee = seg_data.Get(nPos+400,16);
+    as->szRAAN = seg_data.Get(nPos+416,16);
+    as->szInclination = seg_data.Get(nPos+432,16);
+    as->szMeanAnomaly = seg_data.Get(nPos+448,16);
+    as->szSemiMajorAxis = seg_data.Get(nPos+464,16);
+                                                                      
+/* -------------------------------------------------------------------- */
+/*  Skip the 10th block which is reserved for future use.		*/
+/* -------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------- */
+/*  Read in the 11th block, which contains indexing info.               */
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*10;
+    
+    as->nRecordSize             = seg_data.GetInt(nPos,    16);
+    as->nBlockSize              = seg_data.GetInt(nPos+16, 16);
+    as->nNumRecordsPerBlock     = seg_data.GetInt(nPos+32, 16);
+    as->nNumBlocks              = seg_data.GetInt(nPos+48, 16);
+    as->nNumScanlineRecords     = seg_data.GetInt(nPos+64, 16);
+    
+/* -------------------------------------------------------------------- */
+/*  Allocate the scanline records.                                      */
+/* -------------------------------------------------------------------- */
+    if ( as->nNumScanlineRecords == 0 )
+        return;
+
+/* -------------------------------------------------------------------- */
+/*  Now read the 12th block and onward.                                 */
+/* -------------------------------------------------------------------- */
+    nBlock = 12;
+
+    if ( as->nNumRecordsPerBlock == 0 )
+	return;
+
+    for(nLine = 0; nLine < as->nNumScanlineRecords;
+                   nLine += as->nNumRecordsPerBlock)
+    {
+        int nNumRecords = MinFunction(as->nNumRecordsPerBlock,
+                                      as->nNumScanlineRecords - nLine);
+        nPos = nStartBlock + 512*(nBlock-1);
+	if( nDataLength < 512*nBlock )
+	{
+	    break;
+	}
+     
+        for(int i = 0; i < nNumRecords; ++i)
+        {
+            AvhrrLine_t sLine;
+            ReadAvhrrScanlineRecord(nPos+i*80, &sLine);
+            as->Line.push_back(sLine);
+        }
+
+        ++nBlock;
+    }
+}
+
+/************************************************************************/
+/*		        ReadAvhrrScanlineRecord()                       */
+/************************************************************************/
+/**                                                                      
+ *  Read from a byte buffer in order to set a scanline record.     
+ * @param pbyBuf the buffer that contains the record to read.
+ * @param psScanlineRecord the record to read.
+ */
+void 
+CPCIDSKEphemerisSegment::ReadAvhrrScanlineRecord(int nPos,
+                                           AvhrrLine_t *psScanlineRecord)
+{
+    int i;
+    AvhrrLine_t *sr = psScanlineRecord;
+
+    sr->nScanLineNum = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos,4));
+    sr->nStartScanTimeGMTMsec = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+4,4));
+
+    for(i = 0; i < 10; ++i)
+        sr->abyScanLineQuality[i] = seg_data.GetInt(nPos+8+i,1);
+
+    for(i = 0; i < 5; ++i)
+    {
+        sr->aabyBadBandIndicators[i][0] = seg_data.GetInt(nPos+18+2*i,1);
+        sr->aabyBadBandIndicators[i][1] = seg_data.GetInt(nPos+18+2*i+1,1);
+    }
+
+    for(i = 0; i < 8; ++i)
+        sr->abySatelliteTimeCode[i] = seg_data.GetInt(nPos+28+i,1);
+
+    for(i = 0; i < 3; ++i)
+        sr->anTargetTempData[i] = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+36+i*4,4));
+    for(i = 0; i < 3; ++i)
+        sr->anTargetScanData[i] = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+48+i*4,4));
+    for(i = 0; i < 5; ++i)
+        sr->anSpaceScanData[i]  = ReadAvhrrInt32((unsigned char*)seg_data.Get(nPos+60+i*4,4));
+}
+
+/************************************************************************/
+/*			   ReadAvhrrInt32()                             */
+/************************************************************************/
+/**                                                                      
+ * Read an integer from a given buffer of at least 4 bytes. 
+ * @param pbyBuf the buffer that contains the value.
+ * @return the value
+ */
+int 
+CPCIDSKEphemerisSegment::ReadAvhrrInt32(unsigned char* pbyBuf)
+{
+    int nValue = 0;
+    unsigned char* b = pbyBuf;
+    nValue = (int)((b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3]);
+
+    return( nValue );
+}
+
+/************************************************************************/
+/*		      WriteAvhrrEphemerisSegment()                      */
+/************************************************************************/
+/**                                                                      
+ *  Write the contents of blocks 9, 10, and onwards to the orbit	
+ *  segment from fields in the EphemerisSeg_t structure.
+ * @param nStartBlock where to start to write the information in the buffer
+ * @param psEphSegRec the information to write.
+ */
+void 
+CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
+                                           EphemerisSeg_t *psEphSegRec)
+{
+    int  nBlock = 0, nLine = 0;
+    int nPos = 0;
+/* -------------------------------------------------------------------- */
+/*  Check that the AvhrrSeg is not NULL.				*/
+/* -------------------------------------------------------------------- */
+    AvhrrSeg_t *as = NULL;
+    as = psEphSegRec->AvhrrSeg;
+
+    if ( as == NULL)
+    {
+	throw PCIDSKException("The AvhrrSeg is NULL.");
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Realloc the data buffer large enough to hold all the AVHRR      */
+/*      information, and zero it.                                       */
+/* -------------------------------------------------------------------- */
+    int nToAdd = 512 *
+        (((as->nNumScanlineRecords + as->nNumRecordsPerBlock-1) /
+                   as->nNumRecordsPerBlock)
+        +4);
+    seg_data.SetSize(seg_data.buffer_size + nToAdd);
+
+    nPos = nStartBlock;
+    memset(seg_data.buffer+nPos,' ',nToAdd);
+
+/* -------------------------------------------------------------------- */
+/*  Write the first avhrr Block.					*/
+/* -------------------------------------------------------------------- */
+
+    seg_data.Put(as->szImageFormat.c_str(),nPos,16);
+
+    seg_data.Put(as->nImageXSize,nPos+16,16);
+    seg_data.Put(as->nImageYSize,nPos+32,16);
+
+    if ( as->bIsAscending )
+        seg_data.Put("ASCENDING",nPos+48,9);
+    else
+        seg_data.Put("DESCENDING",nPos+48,10);
+
+    if ( as->bIsImageRotated )
+        seg_data.Put("ROTATED",nPos+64,7);
+    else
+        seg_data.Put("NOT ROTATED",nPos+64,11);
+              
+    seg_data.Put(as->szOrbitNumber.c_str(),nPos+80,16);
+    seg_data.Put(as->szAscendDescendNodeFlag.c_str(),nPos+96,16,true);
+    seg_data.Put(as->szEpochYearAndDay.c_str(),nPos+112,16,true);
+    seg_data.Put(as->szEpochTimeWithinDay.c_str(),nPos+128,16,true);
+    seg_data.Put(as->szTimeDiffStationSatelliteMsec.c_str(),nPos+144,16,true);
+    seg_data.Put(as->szActualSensorScanRate.c_str(),nPos+160,16,true);
+    seg_data.Put(as->szIdentOfOrbitInfoSource.c_str(),nPos+176,16,true);
+    seg_data.Put(as->szInternationalDesignator.c_str(),nPos+192,16,true);
+    seg_data.Put(as->szOrbitNumAtEpoch.c_str(),nPos+208,16,true);
+    seg_data.Put(as->szJulianDayAscendNode.c_str(),nPos+224,16,true);
+    seg_data.Put(as->szEpochYear.c_str(),nPos+240,16,true);
+    seg_data.Put(as->szEpochMonth.c_str(),nPos+256,16,true);
+    seg_data.Put(as->szEpochDay.c_str(),nPos+272,16,true);
+    seg_data.Put(as->szEpochHour.c_str(),nPos+288,16,true);
+    seg_data.Put(as->szEpochMinute.c_str(),nPos+304,16,true);
+    seg_data.Put(as->szEpochSecond.c_str(),nPos+320,16,true);
+    seg_data.Put(as->szPointOfAriesDegrees.c_str(),nPos+336,16,true);
+    seg_data.Put(as->szAnomalisticPeriod.c_str(),nPos+352,16,true);
+    seg_data.Put(as->szNodalPeriod.c_str(),nPos+368,16,true);
+    seg_data.Put(as->szEccentricity.c_str(), nPos+384,16,true);
+    seg_data.Put(as->szArgumentOfPerigee.c_str(),nPos+400,16,true);
+    seg_data.Put(as->szRAAN.c_str(),nPos+416,16,true);
+    seg_data.Put(as->szInclination.c_str(),nPos+432,16,true);
+    seg_data.Put(as->szMeanAnomaly.c_str(),nPos+448,16,true);
+    seg_data.Put(as->szSemiMajorAxis.c_str(),nPos+464,16,true);
+   
+/* -------------------------------------------------------------------- */
+/*  second avhrr block is all zeros.					*/
+/* -------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------- */
+/*  Write the 3rd avhrr Block.                                          */
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*2;
+    
+    seg_data.Put(as->nRecordSize,nPos,16);
+    seg_data.Put(as->nBlockSize,nPos+16,16);
+    seg_data.Put(as->nNumRecordsPerBlock,nPos+32,16);
+    seg_data.Put(as->nNumBlocks,nPos+48,16);
+    seg_data.Put(as->nNumScanlineRecords,nPos+64,16);
+
+/* -------------------------------------------------------------------- */
+/*  Write the fourth avhrr block onwards.                               */
+/* -------------------------------------------------------------------- */
+    if ( as->Line.size() == 0 )
+	return;
+
+    nBlock = 4;
+
+    if ( as->nNumRecordsPerBlock == 0 )
+	return;
+
+    for(nLine = 0; nLine < as->nNumScanlineRecords;
+                   nLine += as->nNumRecordsPerBlock)
+    {
+        int nNumRecords = MinFunction(as->nNumRecordsPerBlock,
+                                      as->nNumScanlineRecords - nLine);
+        nPos = nStartBlock + (nBlock-1) * 512;
+
+        for(int i = 0; i < nNumRecords; ++i)
+        {
+            WriteAvhrrScanlineRecord(&(as->Line[nLine+i]), nPos + i*80);
+        }
+
+        ++nBlock;
+    }
+}
+
+/************************************************************************/
+/*  		   WriteAvhrrScanlineRecord()                           */
+/************************************************************************/
+/**                                                                      
+ * Write a scanline record to a byte buffer.  
+ * @param psScanlineRecord the record to write
+ * @param pbyBuf the buffer to write.
+ */
+void 
+CPCIDSKEphemerisSegment::WriteAvhrrScanlineRecord(
+                                         AvhrrLine_t *psScanlineRecord,
+                                         int nPos)
+{
+    int i;
+    AvhrrLine_t *sr = psScanlineRecord;
+    unsigned char* b = (unsigned char*)&(seg_data.buffer[nPos]);
+
+    WriteAvhrrInt32(sr->nScanLineNum, b);
+    WriteAvhrrInt32(sr->nStartScanTimeGMTMsec, b+4);
+
+    for(i=0 ; i < 10 ; i++)
+        seg_data.Put(sr->abyScanLineQuality[i],nPos+8+i,1);
+
+    for(i = 0; i < 5; ++i)
+    {
+        seg_data.Put(sr->aabyBadBandIndicators[i][0],nPos+18+i*2,1);
+        seg_data.Put(sr->aabyBadBandIndicators[i][1],nPos+18+i*2+1,1);
+    }
+
+    for(i=0 ; i < 8 ; i++)
+        seg_data.Put(sr->abySatelliteTimeCode[i],nPos+28+i,1);
+
+    for(i = 0; i < 3; ++i)
+        WriteAvhrrInt32(sr->anTargetTempData[i], b+(36+i*4));
+    for(i = 0; i < 3; ++i)
+        WriteAvhrrInt32(sr->anTargetScanData[i], b+(48+i*4));
+    for(i = 0; i < 5; ++i)
+        WriteAvhrrInt32(sr->anSpaceScanData[i],  b+(60+i*4));
+
+}
+ 
+/************************************************************************/
+/*			   WriteAvhrrInt32()                            */
+/************************************************************************/
+/**                                                                      
+ * Write an integer into a given buffer of at least 4 bytes.            
+ * @param nValue the value to write
+ * @param pbyBuf the buffer to write into.
+ */
+void CPCIDSKEphemerisSegment::WriteAvhrrInt32(int nValue, 
+                                              unsigned char* pbyBuf)
+{
+    pbyBuf[0] = ((nValue & 0xff000000) >> 24);
+    pbyBuf[1] = ((nValue & 0x00ff0000) >> 16);
+    pbyBuf[2] = ((nValue & 0x0000ff00) >> 8);
+    pbyBuf[3] =  (nValue & 0x000000ff);
+}
+
+
+/************************************************************************/
+/*                        BinaryToEphemeris()                           */
+/************************************************************************/
+/**
+ * Read binary information from a binary buffer to create an 
+ * EphemerisSeg_t structure. The caller is responsible to free the memory
+ * of the returned structure with delete.
+ *
+ * @param nStartBlock where to start read the orbit info into the buffer.
+ * @return the orbbit information 
+ */
+EphemerisSeg_t *
+CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
+
+{
+    EphemerisSeg_t *segment;
+    int		i;
+    int nPos = nStartBlock;
+
+    segment = new EphemerisSeg_t();
+    
+/* -------------------------------------------------------------------- */
+/*	Process first block.						*/
+/* -------------------------------------------------------------------- */
+    
+    segment->SatelliteDesc = seg_data.Get(nPos+8,32);  
+    segment->SceneID = seg_data.Get(nPos+40, 32);
+
+/* -------------------------------------------------------------------- */
+/*	Process the second block.					*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512;
+
+    segment->SatelliteSensor = seg_data.Get(nPos, 16);
+    for (i=0; i<16; i++)
+    {
+        if (segment->SatelliteSensor[i] == ' ')
+        {
+            segment->SatelliteSensor = segment->SatelliteSensor.substr(0,i);
+            break;
+        }
+    }
+
+    segment->SensorNo = seg_data.Get(nPos+22, 2);
+    segment->DateImageTaken = seg_data.Get(nPos+44, 22);
+
+    if (seg_data.buffer[nPos+66] == 'Y' || 
+        seg_data.buffer[nPos+66] == 'y')
+        segment->SupSegExist = true;
+    else
+        segment->SupSegExist = false;
+    segment->FieldOfView = seg_data.GetDouble(nPos+88, 22); 
+    segment->ViewAngle = seg_data.GetDouble(nPos+110, 22);
+    segment->NumColCentre = seg_data.GetDouble(nPos+132, 22);
+    segment->RadialSpeed = seg_data.GetDouble(nPos+154, 22);
+    segment->Eccentricity = seg_data.GetDouble(nPos+176, 22);
+    segment->Height = seg_data.GetDouble(nPos+198, 22);
+    segment->Inclination = seg_data.GetDouble(nPos+220, 22);
+    segment->TimeInterval = seg_data.GetDouble(nPos+242, 22);
+    segment->NumLineCentre = seg_data.GetDouble(nPos+264, 22);
+    segment->LongCentre = seg_data.GetDouble(nPos+286, 22);
+    segment->AngularSpd = seg_data.GetDouble(nPos+308, 22);		
+    segment->AscNodeLong = seg_data.GetDouble(nPos+330, 22);
+    segment->ArgPerigee = seg_data.GetDouble(nPos+352, 22);
+    segment->LatCentre = seg_data.GetDouble(nPos+374, 22);
+    segment->EarthSatelliteDist = seg_data.GetDouble(nPos+396, 22);
+    segment->NominalPitch = seg_data.GetDouble(nPos+418, 22);
+    segment->TimeAtCentre = seg_data.GetDouble(nPos+440, 22);
+    segment->SatelliteArg = seg_data.GetDouble(nPos+462, 22);
+    segment->bDescending = true;
+    if (seg_data.buffer[nPos+484] == 'A')
+        segment->bDescending = false;
+
+/* -------------------------------------------------------------------- */
+/*	Process the third block.					*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 2*512;
+
+    segment->XCentre = seg_data.GetDouble(nPos, 22);
+    segment->YCentre = seg_data.GetDouble(nPos+22, 22);
+    segment->UtmXCentre = seg_data.GetDouble(nPos+44, 22);
+    segment->UtmYCentre = seg_data.GetDouble(nPos+66, 22);
+    segment->PixelRes = seg_data.GetDouble(nPos+88, 22);
+    segment->LineRes = seg_data.GetDouble(nPos+110, 22);
+    if (seg_data.buffer[nPos+132] == 'Y' || 
+        seg_data.buffer[nPos+132] == 'y')
+        segment->CornerAvail = true;
+    else
+        segment->CornerAvail = false;
+    segment->MapUnit = seg_data.Get(nPos+133, 16);
+
+    segment->XUL = seg_data.GetDouble(nPos+149, 22);
+    segment->YUL = seg_data.GetDouble(nPos+171, 22);
+    segment->XUR = seg_data.GetDouble(nPos+193, 22);
+    segment->YUR = seg_data.GetDouble(nPos+215, 22);
+    segment->XLR = seg_data.GetDouble(nPos+237, 22);
+    segment->YLR = seg_data.GetDouble(nPos+259, 22);
+    segment->XLL = seg_data.GetDouble(nPos+281, 22);
+    segment->YLL = seg_data.GetDouble(nPos+303, 22);
+    segment->UtmXUL = seg_data.GetDouble(nPos+325, 22);
+    segment->UtmYUL = seg_data.GetDouble(nPos+347, 22);
+    segment->UtmXUR = seg_data.GetDouble(nPos+369, 22);
+    segment->UtmYUR = seg_data.GetDouble(nPos+391, 22);
+    segment->UtmXLR = seg_data.GetDouble(nPos+413, 22);
+    segment->UtmYLR = seg_data.GetDouble(nPos+435, 22);
+    segment->UtmXLL = seg_data.GetDouble(nPos+457, 22);
+    segment->UtmYLL = seg_data.GetDouble(nPos+479, 22);
+    
+/* -------------------------------------------------------------------- */
+/*      Process the 4th block (Corner lat/long coordinates)             */
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 3*512;
+
+    segment->LongCentreDeg = seg_data.GetDouble(nPos, 16);
+    segment->LatCentreDeg = seg_data.GetDouble(nPos+16, 16);
+    segment->LongUL =  seg_data.GetDouble(nPos+32, 16);
+    segment->LatUL = seg_data.GetDouble(nPos+48, 16);
+    segment->LongUR =  seg_data.GetDouble(nPos+64, 16);
+    segment->LatUR = seg_data.GetDouble(nPos+80, 16);
+    segment->LongLR = seg_data.GetDouble(nPos+96, 16);
+    segment->LatLR = seg_data.GetDouble(nPos+112, 16);
+    segment->LongLL = seg_data.GetDouble(nPos+128, 16);
+    segment->LatLL = seg_data.GetDouble(nPos+144, 16);
+    segment->HtCentre = seg_data.GetDouble(nPos+160, 16);
+    segment->HtUL = seg_data.GetDouble(nPos+176, 16);
+    segment->HtUR = seg_data.GetDouble(nPos+192, 16);
+    segment->HtLR = seg_data.GetDouble(nPos+208, 16);
+    segment->HtLL = seg_data.GetDouble(nPos+224, 16);
+
+/* -------------------------------------------------------------------- */
+/*      Process the 5th block.                                          */
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*4;
+
+    segment->ImageRecordLength = seg_data.GetInt(nPos, 16);
+    segment->NumberImageLine = seg_data.GetInt(nPos+16, 16);
+    segment->NumberBytePerPixel = seg_data.GetInt(nPos+32, 16);
+    segment->NumberSamplePerLine = seg_data.GetInt(nPos+48, 16);
+    segment->NumberPrefixBytes = seg_data.GetInt(nPos+64, 16);
+    segment->NumberSuffixBytes = seg_data.GetInt(nPos+80, 16);
+
+/* -------------------------------------------------------------------- */
+/*      Process the 6th and 7th block.                                  */
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 5*512;
+
+    segment->SPNCoeff = 0;
+
+    if(std::strncmp(seg_data.Get(nPos,8), "SPOT1BOD", 8)==0 ||
+       std::strncmp(seg_data.Get(nPos,8), "SPOT1BNW", 8)==0)
+    {
+        segment->SPNCoeff = seg_data.GetInt(nPos+22, 22);
+        for (i=0; i<20; i++)   
+        {
+            segment->SPCoeff1B[i] = 
+                seg_data.GetDouble(nPos+(i+2)*22, 22);
+        }
+
+        if (std::strncmp(seg_data.Get(nPos,8), "SPOT1BNW", 8)==0)
+        {
+            nPos = nStartBlock + 6*512;
+
+            for (i=0; i<19; i++)   
+            {
+                segment->SPCoeff1B[i+20] = 
+                    seg_data.GetDouble(nPos+i*22, 22);
+            }
+            segment->SPCoeffSg[0] = seg_data.GetInt(nPos+418, 8);
+            segment->SPCoeffSg[1] = seg_data.GetInt(nPos+426, 8);
+            segment->SPCoeffSg[2] = seg_data.GetInt(nPos+434, 8);
+            segment->SPCoeffSg[3] = seg_data.GetInt(nPos+442, 8);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*	6th and 7th block of ORBIT segment are blank.			*/
+/*	Read in the 8th block.						*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 7*512;
+    
+    if (std::strncmp(seg_data.Get(nPos,8), "ATTITUDE", 8)==0)
+        segment->Type = OrbAttitude;
+    else if (std::strncmp(seg_data.Get(nPos,8), "RADAR   ", 8)==0)
+        segment->Type = OrbLatLong;
+    else if (std::strncmp(seg_data.Get(nPos,8), "AVHRR   ", 8)==0)
+        segment->Type = OrbAvhrr;
+    else if (std::strncmp(seg_data.Get(nPos,8), "NO_DATA ", 8)==0)
+        segment->Type = OrbNone;
+    else
+        throw PCIDSKException("Invalid Orbit type found: [%s]", 
+                              seg_data.Get(nPos,8));
+
+/* -------------------------------------------------------------------- */
+/*	Orbit segment is a Satellite Attitude Segment(ATTITUDE) only	*/
+/*	for SPOT 1A.							*/
+/* -------------------------------------------------------------------- */
+    if (segment->Type == OrbAttitude)
+    {
+        AttitudeSeg_t 	*AttitudeSeg;
+        int		nBlock, nData;
+
+        AttitudeSeg = segment->AttitudeSeg = new AttitudeSeg_t();  
+	
+/* -------------------------------------------------------------------- */
+/*	Read in the 9th block.						*/
+/* -------------------------------------------------------------------- */
+        nPos = nStartBlock + 512*8;
+        
+        AttitudeSeg->Roll = seg_data.GetDouble(nPos, 22);
+        AttitudeSeg->Pitch = seg_data.GetDouble(nPos+22, 22);
+        AttitudeSeg->Yaw = seg_data.GetDouble(nPos+44, 22);
+        AttitudeSeg->NumberOfLine = seg_data.GetInt(nPos+88, 22);
+        if (AttitudeSeg->NumberOfLine % ATT_SEG_LINE_PER_BLOCK != 0)
+            AttitudeSeg->NumberBlockData = 1 + 
+                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
+        else
+            AttitudeSeg->NumberBlockData =  
+                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
+
+/* -------------------------------------------------------------------- */
+/*	Read in the line required.					*/
+/* -------------------------------------------------------------------- */
+        for (nBlock=0, nData=0; nBlock<AttitudeSeg->NumberBlockData; 
+             nBlock++)
+        {
+/* -------------------------------------------------------------------- */
+/*	Read in 10+nBlock th block as required.				*/
+/* -------------------------------------------------------------------- */
+            nPos = nStartBlock + 512*(9+nBlock);
+
+/* -------------------------------------------------------------------- */
+/*	Fill in the lines as required.					*/
+/* -------------------------------------------------------------------- */
+            for (i=0; 
+                 i<ATT_SEG_LINE_PER_BLOCK 
+		     && nData < AttitudeSeg->NumberOfLine; 
+                 i++, nData++)
+            {
+                AttitudeLine_t oAttitudeLine;
+                oAttitudeLine.ChangeInAttitude
+                    = seg_data.GetDouble(nPos+i*44, 22);
+                oAttitudeLine.ChangeEarthSatelliteDist
+                    = seg_data.GetDouble(nPos+i*44+22, 22);
+                AttitudeSeg->Line.push_back(oAttitudeLine);
+            }
+        }
+
+        if (nData != AttitudeSeg->NumberOfLine)
+        {
+            throw PCIDSKException("Number of data line read (%d) "
+                     "does not matches with what is specified in "
+                     "the segment (%d).\n", nData, 
+                     AttitudeSeg->NumberOfLine);
+        }
+    }
+/* -------------------------------------------------------------------- */
+/*	Radar segment (LATLONG)						*/
+/* -------------------------------------------------------------------- */
+    else if (segment->Type == OrbLatLong)
+    {
+        RadarSeg_t *RadarSeg;
+        int	nBlock, nData;
+
+        RadarSeg = segment->RadarSeg = new RadarSeg_t(); 
+/* -------------------------------------------------------------------- */
+/*	Read in the 9th block.						*/
+/* -------------------------------------------------------------------- */
+        nPos = nStartBlock + 512*8;
+
+        RadarSeg->Identifier = seg_data.Get(nPos, 16);
+        RadarSeg->Facility = seg_data.Get(nPos+16, 16);
+        RadarSeg->Ellipsoid = seg_data.Get(nPos+32, 16);
+
+        RadarSeg->EquatorialRadius = seg_data.GetDouble(nPos+48, 16);
+        RadarSeg->PolarRadius = seg_data.GetDouble(nPos+64, 16); 
+        RadarSeg->IncidenceAngle = seg_data.GetDouble(nPos+80, 16);
+        RadarSeg->LineSpacing = seg_data.GetDouble(nPos+96, 16);
+        RadarSeg->PixelSpacing = seg_data.GetDouble(nPos+112, 16);
+        RadarSeg->ClockAngle = seg_data.GetDouble(nPos+128, 16);
+
+/* -------------------------------------------------------------------- */
+/*	Read in the 10th block.						*/
+/* -------------------------------------------------------------------- */
+        nPos = nStartBlock + 9*512;
+
+        RadarSeg->NumberBlockData = seg_data.GetInt(nPos, 8);
+        RadarSeg->NumberData = seg_data.GetInt(nPos+8, 8);
+
+/* -------------------------------------------------------------------- */
+/* 	Read in the 11-th through 11+RadarSeg->NumberBlockData th block	*/
+/*	for the ancillary data present.					*/
+/* -------------------------------------------------------------------- */
+        for (nBlock = 0, nData = 0; 
+             nBlock < RadarSeg->NumberBlockData; nBlock++)
+        {
+/* -------------------------------------------------------------------- */
+/*	Read in one block of data.					*/
+/* -------------------------------------------------------------------- */
+            nPos = nStartBlock + 512*(10+nBlock);
+
+            for (i=0; 
+                 i<ANC_DATA_PER_BLK &&  nData < RadarSeg->NumberData; 
+                 i++, nData++)
+            {
+                int	offset;
+                char	*currentindex;
+                void	*currentptr;
+                double	tmp;
+                int32	tmpInt;
+                const double million = 1000000.0;
+                
+/* -------------------------------------------------------------------- */
+/*	Reading in one ancillary data at a time.			*/
+/* -------------------------------------------------------------------- */
+                AncillaryData_t oData;
+                offset = i*ANC_DATA_SIZE;
+
+                currentindex = (char *)seg_data.Get(nPos+offset,4);
+                currentptr = (char *) currentindex; 
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr);
+                oData.SlantRangeFstPixel = tmpInt; 
+
+                currentindex = (char *)seg_data.Get(nPos+offset+4,4); 
+                currentptr = (char *) currentindex;
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr); 
+                oData.SlantRangeLastPixel = tmpInt; 
+
+                currentindex = (char *)seg_data.Get(nPos+offset+8,4);
+                currentptr = (char *) currentindex;
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr); 
+                tmp = (double) tmpInt / million;
+                oData.FstPixelLat
+                    = (float) ConvertDeg(tmp, 0);
+
+                currentindex = (char *)seg_data.Get(nPos+offset+12,4);
+                currentptr = (char *) currentindex;
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr); 
+                tmp = (double) tmpInt / million;
+                oData.MidPixelLat 
+                    = (float) ConvertDeg(tmp, 0);
+
+                currentindex = (char *)seg_data.Get(nPos+offset+16,4);
+                currentptr = (char *) currentindex;
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr); 
+                tmp = (double) tmpInt / million;
+                oData.LstPixelLat
+                    = (float) ConvertDeg(tmp, 0);
+
+                currentindex = (char *)seg_data.Get(nPos+offset+20,4);
+                currentptr = (char *) currentindex;
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr); 
+                tmp = (double) tmpInt / million;
+                oData.FstPixelLong
+                    = (float) ConvertDeg(tmp, 0);
+
+                currentindex = (char *)seg_data.Get(nPos+offset+24,4);
+                currentptr = (char *) currentindex; 
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr); 
+                tmp = (double) tmpInt / million;
+                oData.MidPixelLong
+                    = (float) ConvertDeg(tmp, 0);
+
+                currentindex = (char *)seg_data.Get(nPos+offset+28,4);
+                currentptr = (char *) currentindex;
+                SwapData(currentptr,4,1);
+                tmpInt = *((int32 *) currentptr); 
+                tmp = (double) tmpInt / million;
+                oData.LstPixelLong
+                    = (float) ConvertDeg(tmp, 0);
+
+                RadarSeg->Line.push_back(oData);
+            }
+        }
+
+        if (RadarSeg->NumberData != nData)
+        {
+            throw PCIDSKException("Number "
+		     "of data lines read (%d) does not match with"
+                     "\nwhat is specified in segment (%d).\n", nData, 
+                     RadarSeg->NumberData);
+        }
+    }
+/* -------------------------------------------------------------------- */
+/*	AVHRR segment 							*/
+/* -------------------------------------------------------------------- */
+    else if (segment->Type == OrbAvhrr)
+    {
+        ReadAvhrrEphemerisSegment( nStartBlock, segment);
+    }
+
+    return segment;
+}
+
+/************************************************************************/
+/*                        EphemerisToBinary()                           */
+/************************************************************************/
+/**
+ * Write an Orbit segment information into a binary buffer of size 4096.
+ * The caller is responsible to free this memory with delete [].
+ *
+ * @param psOrbit the orbit information to write into the binary
+ * @param nStartBlock where to start writing in the buffer.
+ */
+void
+CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
+                                              int nStartBlock )
+
+{
+    int		i,j;
+
+/* -------------------------------------------------------------------- */
+/*      The binary data must be at least 8 blocks (4096 bytes) long     */
+/*      for the common information.                                     */
+/* -------------------------------------------------------------------- */
+    seg_data.SetSize(nStartBlock+4096);
+    memset(seg_data.buffer+nStartBlock,' ',4096);
+
+    int nPos = nStartBlock;
+
+/* -------------------------------------------------------------------- */
+/*	Write the first block						*/
+/* -------------------------------------------------------------------- */
+
+    seg_data.Put("ORBIT   ",nPos,8);
+    seg_data.Put(psOrbit->SatelliteDesc.c_str(), nPos+8,32,true);
+    seg_data.Put(psOrbit->SceneID.c_str(), nPos+40,32,true);
+
+/* -------------------------------------------------------------------- */
+/*	Write the second block						*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 1*512;
+    
+    seg_data.Put(psOrbit->SatelliteSensor.c_str(), nPos,16);
+    seg_data.Put(psOrbit->SensorNo.c_str(),nPos+22,2,true);
+    seg_data.Put(psOrbit->DateImageTaken.c_str(), nPos+44,22,true);
+
+    if (psOrbit->SupSegExist)
+        seg_data.Put("Y",nPos+66,1);
+    else
+        seg_data.Put("N",nPos+66,1);
+
+    seg_data.Put(psOrbit->FieldOfView,nPos+88,22,"%22.14f");
+    seg_data.Put(psOrbit->ViewAngle,nPos+110,22,"%22.14f");
+    seg_data.Put(psOrbit->NumColCentre,nPos+132,22,"%22.14f");
+    seg_data.Put(psOrbit->RadialSpeed,nPos+154,22,"%22.14f");
+    seg_data.Put(psOrbit->Eccentricity,nPos+176,22,"%22.14f");
+    seg_data.Put(psOrbit->Height,nPos+198,22,"%22.14f");
+    seg_data.Put(psOrbit->Inclination,nPos+220,22,"%22.14f");
+    seg_data.Put(psOrbit->TimeInterval,nPos+242,22,"%22.14f");
+    seg_data.Put(psOrbit->NumLineCentre,nPos+264,22,"%22.14f");
+    seg_data.Put(psOrbit->LongCentre,nPos+286,22,"%22.14f");
+    seg_data.Put(psOrbit->AngularSpd,nPos+308,22,"%22.14f");
+    seg_data.Put(psOrbit->AscNodeLong,nPos+330,22,"%22.14f");
+    seg_data.Put(psOrbit->ArgPerigee,nPos+352,22,"%22.14f");
+    seg_data.Put(psOrbit->LatCentre,nPos+374,22,"%22.14f");
+    seg_data.Put(psOrbit->EarthSatelliteDist,nPos+396,22,"%22.14f");
+    seg_data.Put(psOrbit->NominalPitch,nPos+418,22,"%22.14f");
+    seg_data.Put(psOrbit->TimeAtCentre,nPos+440,22,"%22.14f");
+    seg_data.Put(psOrbit->SatelliteArg,nPos+462,22,"%22.14f");
+
+    if (psOrbit->bDescending)
+        seg_data.Put("DESCENDING",nPos+484,10);
+    else
+        seg_data.Put("ASCENDING ",nPos+484,10);
+
+/* -------------------------------------------------------------------- */
+/*	Write the third block						*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*2;
+
+    seg_data.Put(psOrbit->XCentre,nPos,22,"%22.14f");
+    seg_data.Put(psOrbit->YCentre,nPos+22,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmXCentre,nPos+44,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmYCentre,nPos+66,22,"%22.14f");
+    seg_data.Put(psOrbit->PixelRes,nPos+88,22,"%22.14f");
+    seg_data.Put(psOrbit->LineRes,nPos+110,22,"%22.14f");
+
+    if (psOrbit->CornerAvail == true)
+        seg_data.Put("Y",nPos+132,1);
+    else
+        seg_data.Put("N",nPos+132,1);
+
+    seg_data.Put(psOrbit->MapUnit.c_str(),nPos+133,16,true);
+
+    seg_data.Put(psOrbit->XUL,nPos+149,22,"%22.14f");
+    seg_data.Put(psOrbit->YUL,nPos+171,22,"%22.14f");
+    seg_data.Put(psOrbit->XUR,nPos+193,22,"%22.14f");
+    seg_data.Put(psOrbit->YUR,nPos+215,22,"%22.14f");
+    seg_data.Put(psOrbit->XLR,nPos+237,22,"%22.14f");
+    seg_data.Put(psOrbit->YLR,nPos+259,22,"%22.14f");
+    seg_data.Put(psOrbit->XLL,nPos+281,22,"%22.14f");
+    seg_data.Put(psOrbit->YLL,nPos+303,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmXUL,nPos+325,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmYUL,nPos+347,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmXUR,nPos+369,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmYUR,nPos+391,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmXLR,nPos+413,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmYLR,nPos+435,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmXLL,nPos+457,22,"%22.14f");
+    seg_data.Put(psOrbit->UtmYLL,nPos+479,22,"%22.14f");
+
+/* -------------------------------------------------------------------- */
+/*	Write the fourth block						*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*3;
+    
+    seg_data.Put(psOrbit->LongCentreDeg,nPos,22,"%16.7f");
+    seg_data.Put(psOrbit->LatCentreDeg,nPos+16,22,"%16.7f");
+    seg_data.Put(psOrbit->LongUL,nPos+32,22,"%16.7f");
+    seg_data.Put(psOrbit->LatUL,nPos+48,22,"%16.7f");
+    seg_data.Put(psOrbit->LongUR,nPos+64,22,"%16.7f");
+    seg_data.Put(psOrbit->LatUR,nPos+80,22,"%16.7f");
+    seg_data.Put(psOrbit->LongLR,nPos+96,22,"%16.7f");
+    seg_data.Put(psOrbit->LatLR,nPos+112,22,"%16.7f");
+    seg_data.Put(psOrbit->LongLL,nPos+128,22,"%16.7f");
+    seg_data.Put(psOrbit->LatLL,nPos+144,22,"%16.7f");
+    seg_data.Put(psOrbit->HtCentre,nPos+160,22,"%16.7f");
+    seg_data.Put(psOrbit->HtUL,nPos+176,22,"%16.7f");
+    seg_data.Put(psOrbit->HtUR,nPos+192,22,"%16.7f");
+    seg_data.Put(psOrbit->HtLR,nPos+208,22,"%16.7f");
+    seg_data.Put(psOrbit->HtLL,nPos+224,22,"%16.7f");
+
+/* -------------------------------------------------------------------- */
+/*	Write the fifth block						*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*4;
+
+    seg_data.Put(psOrbit->ImageRecordLength,nPos,16);
+    seg_data.Put(psOrbit->NumberImageLine,nPos+16,16);
+    seg_data.Put(psOrbit->NumberBytePerPixel,nPos+32,16);
+    seg_data.Put(psOrbit->NumberSamplePerLine,nPos+48,16);
+    seg_data.Put(psOrbit->NumberPrefixBytes,nPos+64,16);
+    seg_data.Put(psOrbit->NumberSuffixBytes,nPos+80,16);
+
+/* -------------------------------------------------------------------- */
+/*	Write the sixth and seventh block (blanks)			*/
+/*	For SPOT it is not blank					*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*5;
+
+    if (psOrbit->SPNCoeff > 0)
+    {
+        if (psOrbit->SPNCoeff == 20)
+	{
+            seg_data.Put("SPOT1BOD",nPos,8);
+            seg_data.Put(psOrbit->SPNCoeff,nPos+22,22);
+
+	    j = 44;
+	    for (i=0; i<20; i++)
+	    {
+                seg_data.Put(psOrbit->SPCoeff1B[i],
+                                     nPos+j,22,"%22.14f");
+		j += 22;
+	    }
+	}
+	else
+	{
+            seg_data.Put("SPOT1BNW",nPos,8);
+            seg_data.Put(psOrbit->SPNCoeff,nPos+22,22);
+
+	    j = 44;
+            for (i=0; i<20; i++)
+            {
+                seg_data.Put(psOrbit->SPCoeff1B[i],
+                                     nPos+j,22,"%22.14f");
+                j += 22;
+            }
+
+            nPos = nStartBlock + 512*6;
+
+            j = 0;
+            for (i=20; i<39; i++)
+            {
+                seg_data.Put(psOrbit->SPCoeff1B[i],
+                                     nPos+j,22,"%22.14f");
+                j += 22;
+            }
+
+            seg_data.Put(psOrbit->SPCoeffSg[0],nPos+418,8);
+            seg_data.Put(psOrbit->SPCoeffSg[1],nPos+426,8);
+            seg_data.Put(psOrbit->SPCoeffSg[2],nPos+434,8);
+            seg_data.Put(psOrbit->SPCoeffSg[3],nPos+442,8);
+        }
+    } 
+
+/* -------------------------------------------------------------------- */
+/*	Write the eighth block.						*/
+/* -------------------------------------------------------------------- */
+    nPos = nStartBlock + 512*7;
+    
+    if (psOrbit->Type == OrbAttitude)
+        seg_data.Put("ATTITUDE",nPos,8);
+    else if (psOrbit->Type == OrbLatLong)
+        seg_data.Put("RADAR   ",nPos,8);
+    else if (psOrbit->Type == OrbAvhrr)
+        seg_data.Put("AVHRR   ",nPos,8);
+    else if (psOrbit->Type == OrbNone)
+        seg_data.Put("NO_DATA ",nPos,8);
+    else
+    {
+        throw PCIDSKException("Invalid Orbit type."); 
+    }
+
+/* ==================================================================== */
+/*	Orbit segment is a Satellite Attitude Segment(ATTITUDE) only	*/
+/*	for SPOT 1A.							*/
+/* ==================================================================== */
+    if (psOrbit->Type == OrbAttitude)
+    {
+        AttitudeSeg_t *AttitudeSeg;
+        int		nBlock, nData;
+
+        AttitudeSeg = psOrbit->AttitudeSeg;
+
+        if (AttitudeSeg == NULL)
+        {
+            throw PCIDSKException("The AttitudeSeg is NULL.");
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Add one block                                                   */
+/* -------------------------------------------------------------------- */
+        seg_data.SetSize(seg_data.buffer_size + 512);
+            
+        nPos = nStartBlock + 512*8;
+        memset(seg_data.buffer+nPos,' ',512);
+            
+/* -------------------------------------------------------------------- */
+/*	Write the nineth block.						*/
+/* -------------------------------------------------------------------- */
+
+        seg_data.Put(AttitudeSeg->Roll,nPos,22,"%22.14f");
+        seg_data.Put(AttitudeSeg->Pitch,nPos+22,22,"%22.14f");
+        seg_data.Put(AttitudeSeg->Yaw,nPos+44,22,"%22.14f");
+
+        if (AttitudeSeg->NumberOfLine % ATT_SEG_LINE_PER_BLOCK != 0)
+            AttitudeSeg->NumberBlockData = 1 + 
+                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
+        else
+            AttitudeSeg->NumberBlockData =  
+                AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
+
+        seg_data.Put(AttitudeSeg->NumberBlockData,nPos+66,22);
+        seg_data.Put(AttitudeSeg->NumberOfLine,nPos+88,22);
+
+/* -------------------------------------------------------------------- */
+/*      Add NumberBlockData blocks to array.                            */
+/* -------------------------------------------------------------------- */
+        seg_data.SetSize(seg_data.buffer_size + 
+                                 512 * AttitudeSeg->NumberBlockData);
+            
+        nPos = nStartBlock + 512*9;
+        memset(seg_data.buffer+nPos,' ',
+               512 * AttitudeSeg->NumberBlockData);
+            
+/* -------------------------------------------------------------------- */
+/*	Write out the line required.					*/
+/* -------------------------------------------------------------------- */
+        for (nBlock=0, nData=0; nBlock<AttitudeSeg->NumberBlockData; 
+             nBlock++)
+        {
+            int		i;
+            nPos = nStartBlock + 512*(nBlock + 9);
+
+/* -------------------------------------------------------------------- */
+/*	Fill in buffer as required.					*/
+/* -------------------------------------------------------------------- */
+            for (i=0; 
+                 i<ATT_SEG_LINE_PER_BLOCK 
+		     && nData < AttitudeSeg->NumberOfLine; 
+                 i++, nData++)
+            {
+                seg_data.Put(
+                    AttitudeSeg->Line[nData].ChangeInAttitude,
+                    nPos+i*44,22,"%22.14f");
+                seg_data.Put(
+                    AttitudeSeg->Line[nData].ChangeEarthSatelliteDist,
+                    nPos+i*44+22,22,"%22.14f");
+            }
+        }
+
+        if (nData != AttitudeSeg->NumberOfLine)
+        {
+            throw PCIDSKException("Number of data line written"
+		    " (%d) does not match with\nwhat is specified "
+		    " in the segment (%d).\n", 
+		    nData, AttitudeSeg->NumberOfLine);
+        }
+    }
+
+/* ==================================================================== */
+/*	Radar segment (LATLONG)						*/
+/* ==================================================================== */
+    else if (psOrbit->Type == OrbLatLong)
+    {
+        RadarSeg_t *RadarSeg;
+        int	   i, nBlock, nData;
+
+        RadarSeg = psOrbit->RadarSeg;
+
+        if (RadarSeg == NULL)
+        {
+            throw PCIDSKException("The RadarSeg is NULL.");
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Add two blocks.                                                 */
+/* -------------------------------------------------------------------- */
+        seg_data.SetSize(seg_data.buffer_size + 512*2);
+            
+        nPos = nStartBlock + 512*8;
+        memset(seg_data.buffer+nPos,' ', 512*2);
+            
+/* -------------------------------------------------------------------- */
+/*	Write out the nineth block.					*/
+/* -------------------------------------------------------------------- */
+
+        seg_data.Put(RadarSeg->Identifier.c_str(), nPos,16);
+        seg_data.Put(RadarSeg->Facility.c_str(), nPos+16,16);
+        seg_data.Put(RadarSeg->Ellipsoid.c_str(), nPos+32,16);
+
+        seg_data.Put(RadarSeg->EquatorialRadius,nPos+48,16,"%16.7f");
+        seg_data.Put(RadarSeg->PolarRadius,nPos+64,16,"%16.7f");
+        seg_data.Put(RadarSeg->IncidenceAngle,nPos+80,16,"%16.7f");
+        seg_data.Put(RadarSeg->LineSpacing,nPos+96,16,"%16.7f");
+        seg_data.Put(RadarSeg->PixelSpacing,nPos+112,16,"%16.7f");
+        seg_data.Put(RadarSeg->ClockAngle,nPos+128,16,"%16.7f");
+
+/* -------------------------------------------------------------------- */
+/*	Write out the tenth block.					*/
+/* -------------------------------------------------------------------- */
+        nPos = nStartBlock + 512*9;
+
+        seg_data.Put(RadarSeg->NumberBlockData,nPos,8);
+        seg_data.Put(RadarSeg->NumberData,nPos+8,8);
+
+/* -------------------------------------------------------------------- */
+/*      Make room for all the following per-line data.                  */
+/* -------------------------------------------------------------------- */
+        seg_data.SetSize(seg_data.buffer_size + 
+                                 512 * RadarSeg->NumberBlockData);
+            
+        nPos = nStartBlock + 512*10;
+        memset(seg_data.buffer+nPos,' ', 
+               512 * RadarSeg->NumberBlockData);
+        
+/* -------------------------------------------------------------------- */
+/* 	Write out the 11-th through 11+psOrbit->NumberBlockData  block	*/
+/*	for the ancillary data present.					*/
+/* -------------------------------------------------------------------- */
+        for (nBlock = 0, nData = 0; 
+             nBlock < RadarSeg->NumberBlockData; nBlock++)
+        {
+            for (i=0; 
+                 i<ANC_DATA_PER_BLK &&  nData < RadarSeg->NumberData;
+                 i++, nData++)
+            {
+                int		offset;
+                char		*currentptr, *currentindex;
+                double		tmp, tmpDouble;
+                const double million = 1000000.0;
+                int32		tmpInt;
+                
+/* -------------------------------------------------------------------- */
+/*	Point to correct block						*/
+/* -------------------------------------------------------------------- */
+                nPos = nStartBlock + 512*(10+nBlock);
+            
+/* -------------------------------------------------------------------- */
+/*	Writing out one ancillary data at a time.			*/
+/* -------------------------------------------------------------------- */
+                offset = i*ANC_DATA_SIZE;
+
+                currentptr = 
+                    (char *) &(RadarSeg->Line[nData].SlantRangeFstPixel); 
+                SwapData(currentptr,4,1);
+                currentindex = &(seg_data.buffer[nPos+offset]);
+                std::memcpy((void *) currentindex,currentptr, 4); 
+
+                currentptr =
+                    (char *) &(RadarSeg->Line[nData].SlantRangeLastPixel);
+                SwapData(currentptr,4,1);
+                currentindex += 4; 
+                std::memcpy((void *) currentindex,currentptr, 4);
+
+                tmp = ConvertDeg(RadarSeg->Line[nData].FstPixelLat, 1);
+                tmpDouble =  tmp * million;
+                tmpInt = (int32) tmpDouble;
+                currentptr = (char *) &tmpInt;
+                SwapData(currentptr,4,1);
+                currentindex += 4; 
+                std::memcpy((void *) currentindex,currentptr, 4);
+
+                tmp = ConvertDeg(RadarSeg->Line[nData].MidPixelLat, 1);
+                tmpDouble =  tmp * million; 
+                tmpInt = (int32) tmpDouble;
+                currentptr = (char *) &tmpInt;
+                SwapData(currentptr,4,1);
+                currentindex += 4;
+                std::memcpy((void *) currentindex,currentptr, 4);
+
+                tmp = ConvertDeg(RadarSeg->Line[nData].LstPixelLat, 1);
+                tmpDouble =  tmp * million;
+                tmpInt = (int32) tmpDouble;
+                currentptr = (char *) &tmpInt;
+                SwapData(currentptr,4,1);
+                currentindex += 4;
+                std::memcpy((void *) currentindex,currentptr, 4);
+
+                tmp = ConvertDeg(RadarSeg->Line[nData].FstPixelLong, 1);
+                tmpDouble =  tmp * million;
+                tmpInt = (int32) tmpDouble;
+                currentptr = (char *) &tmpInt;
+                SwapData(currentptr,4,1);
+                currentindex += 4;
+                std::memcpy((void *) currentindex,currentptr, 4);
+
+                tmp = ConvertDeg(RadarSeg->Line[nData].MidPixelLong, 1);
+                tmpDouble = tmp * million;
+                tmpInt = (int32) tmpDouble;
+                currentptr = (char *) &tmpInt;
+                SwapData(currentptr,4,1);
+                currentindex += 4;
+                std::memcpy((void *) currentindex,currentptr, 4);
+
+                tmp = ConvertDeg(RadarSeg->Line[nData].LstPixelLong, 1);
+                tmpDouble =  tmp * million;
+                tmpInt = (int32) tmpDouble;
+                currentptr = (char *) &tmpInt;
+                SwapData(currentptr,4,1);
+                currentindex += 4;
+                std::memcpy((void *) currentindex,currentptr, 4);
+            }
+        }
+    }
+
+/* ==================================================================== */
+/*	AVHRR segment 							*/
+/* ==================================================================== */
+    else if ( psOrbit->Type == OrbAvhrr &&
+              psOrbit->AvhrrSeg->nNumRecordsPerBlock > 0 )
+    {
+        WriteAvhrrEphemerisSegment(nStartBlock + 8*512 , psOrbit);
+    }
+}
+
+
diff --git a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
new file mode 100644
index 0000000..bd9bacf
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
@@ -0,0 +1,87 @@
+/******************************************************************************
+ *
+ * Purpose: Support for reading and manipulating PCIDSK Ephemeris Segments
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
+#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
+ 
+#include "pcidsk_ephemeris.h"
+#include "segment/cpcidsksegment.h"
+
+namespace PCIDSK {
+    class PCIDSKFile;
+
+    class CPCIDSKEphemerisSegment : public PCIDSKEphemerisSegment,
+                                    public CPCIDSKSegment
+    {
+    public:
+        CPCIDSKEphemerisSegment(PCIDSKFile *file, int segment,const char *segment_pointer,bool bLoad=true);
+        ~CPCIDSKEphemerisSegment();
+
+        const EphemerisSeg_t& GetEphemeris() const
+        {
+            return *mpoEphemeris;
+        };
+        void SetEphemeris(const EphemerisSeg_t& oEph)
+        {
+            if(mpoEphemeris)
+            {
+                delete mpoEphemeris;
+            }
+            mpoEphemeris = new EphemerisSeg_t(oEph);
+            mbModified = true;
+        };
+
+        //synchronize the segment on disk.
+        void Synchronize();
+    private:
+        
+        // Helper housekeeping functions
+        void Load();
+        void Write();
+
+        EphemerisSeg_t* mpoEphemeris;
+    //functions to read/write binary information
+    protected:
+        // The raw segment data
+        PCIDSKBuffer seg_data;
+        bool loaded_;
+        bool mbModified;
+        void ReadAvhrrEphemerisSegment(int, 
+                                       EphemerisSeg_t *);
+        void ReadAvhrrScanlineRecord(int nPos,
+                                     AvhrrLine_t *psScanlineRecord);
+        int  ReadAvhrrInt32(unsigned char* pbyBuf);
+        void WriteAvhrrEphemerisSegment(int , EphemerisSeg_t *);
+        void WriteAvhrrScanlineRecord(AvhrrLine_t *psScanlineRecord,
+                                      int nPos);
+        void WriteAvhrrInt32(int nValue, unsigned char* pbyBuf);
+        EphemerisSeg_t *BinaryToEphemeris( int nStartBlock );
+        void EphemerisToBinary( EphemerisSeg_t *, int );
+        double ConvertDeg(double degree, int mode);  
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKEPHEMERIS_SEG_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
index 6a2bd09..2b4720e 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
@@ -42,7 +42,8 @@ struct CPCIDSKGCP2Segment::PCIDSKGCP2SegInfo
     unsigned int num_gcps;
     PCIDSKBuffer seg_data;
     
-    std::string map_units;
+    std::string map_units;   ///< PCI mapunits string
+    std::string proj_parms;  ///< Additional projection parameters
     unsigned int num_proj;
     bool changed;
 };
@@ -70,7 +71,7 @@ void CPCIDSKGCP2Segment::Load()
     
     // Read the the segment in. The first block has information about
     // the structure of the GCP segment (how many, the projection, etc.)
-    pimpl_->seg_data.SetSize( (int) (data_size - 1024) );
+    pimpl_->seg_data.SetSize(data_size - 1024);
     ReadFromFile(pimpl_->seg_data.buffer, 0, data_size - 1024);
     
     // check for 'GCP2    ' in the first 8 bytes
@@ -79,6 +80,7 @@ void CPCIDSKGCP2Segment::Load()
         // write it out and return
         pimpl_->changed = true;
         pimpl_->map_units = "LAT/LONG D000";
+        pimpl_->proj_parms = "";
         pimpl_->num_gcps = 0;
         loaded_ = true;
         return;
@@ -99,6 +101,9 @@ void CPCIDSKGCP2Segment::Load()
     // Extract the map units string:
     pimpl_->map_units = std::string(pimpl_->seg_data.buffer + 24, 16);
     
+    // Extract the projection parameters string
+    pimpl_->proj_parms = std::string(pimpl_->seg_data.buffer + 256, 256);
+    
     // Get the number of alternative projections (should be 0!)
     pimpl_->num_proj = pimpl_->seg_data.GetInt(40, 8);
     if (pimpl_->num_proj != 0) {
@@ -133,10 +138,11 @@ void CPCIDSKGCP2Segment::Load()
         double x_err = pimpl_->seg_data.GetDouble(offset + 122, 14);
         double y_err = pimpl_->seg_data.GetDouble(offset + 136, 14);
         
-        std::string gcp_id(pimpl_->seg_data.buffer + 192, 64);
+        std::string gcp_id(pimpl_->seg_data.buffer + offset + 192, 64);
         
         PCIDSK::GCP gcp(x, y, elev,
                         line, pixel, gcp_id, pimpl_->map_units, 
+                        pimpl_->proj_parms,
                         x_err, y_err, elev_err,
                         line_err, pix_err);
         gcp.SetElevationUnit(elev_unit);
@@ -182,13 +188,13 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
     int num_blocks = (pimpl_->num_gcps + 1) / 2;
     
     // This will have to change when we have proper projections support
-    if (pimpl_->gcps.size() > 0 &&
-        pimpl_->map_units != pimpl_->gcps[0].GetMapUnits()) {
-        pimpl_->map_units = pimpl_->gcps[0].GetMapUnits();
+
+    if (pimpl_->gcps.size() > 0)
+    {
+        pimpl_->gcps[0].GetMapUnits(pimpl_->map_units, 
+            pimpl_->proj_parms);
     }
     
-    data_size = num_blocks * 512 + 1024;
-    
     pimpl_->seg_data.SetSize(num_blocks * 512 + 512);
     
     // Write out the first few fields
@@ -197,6 +203,7 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
     pimpl_->seg_data.Put((int)pimpl_->gcps.size(), 16, 8);
     pimpl_->seg_data.Put(pimpl_->map_units.c_str(), 24, 16);
     pimpl_->seg_data.Put((int)0, 40, 8);
+    pimpl_->seg_data.Put(pimpl_->proj_parms.c_str(), 256, 256);
     
     // Time to write GCPs out:
     std::vector<PCIDSK::GCP>::const_iterator iter =
@@ -215,9 +222,9 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
         pimpl_->seg_data.Put("0", offset + 1, 5);
         
         // Start writing out the GCP values
-        pimpl_->seg_data.Put((*iter).GetPixel(), offset + 6, 14);
-        pimpl_->seg_data.Put((*iter).GetLine(), offset + 20, 14);
-        pimpl_->seg_data.Put((*iter).GetZ(), offset + 34, 12);
+        pimpl_->seg_data.Put((*iter).GetPixel(), offset + 6, 14, "%14.4f");
+        pimpl_->seg_data.Put((*iter).GetLine(), offset + 20, 14, "%14.4f");
+        pimpl_->seg_data.Put((*iter).GetZ(), offset + 34, 12, "%12.4f");
         
         GCP::EElevationUnit unit;
         GCP::EElevationDatum datum;
@@ -250,10 +257,7 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
             datum_c[0] = 'M';
             break;
         }
-
-		unit_c[1] = '\0';
-		datum_c[1] = '\0';
-        
+      
         unit_c[1] = '\0';
         datum_c[1] = '\0';
         
@@ -261,14 +265,14 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
         pimpl_->seg_data.Put(unit_c, offset + 46, 1);
         pimpl_->seg_data.Put(datum_c, offset + 47, 1);
         
-        pimpl_->seg_data.Put((*iter).GetX(), offset + 48, 22);
-        pimpl_->seg_data.Put((*iter).GetY(), offset + 70, 22);
-        pimpl_->seg_data.Put((*iter).GetPixelErr(), offset + 92, 10);
-        pimpl_->seg_data.Put((*iter).GetLineErr(), offset + 102, 10);
-        pimpl_->seg_data.Put((*iter).GetZErr(), offset + 112, 10);
-        pimpl_->seg_data.Put((*iter).GetXErr(), offset + 122, 14);
-        pimpl_->seg_data.Put((*iter).GetYErr(), offset + 136, 14);
-        pimpl_->seg_data.Put((*iter).GetIDString(), offset + 192, 64);
+        pimpl_->seg_data.Put((*iter).GetX(), offset + 48, 22, "%22.14e");
+        pimpl_->seg_data.Put((*iter).GetY(), offset + 70, 22, "%22.14e");
+        pimpl_->seg_data.Put((*iter).GetPixelErr(), offset + 92, 10, "%10.4f");
+        pimpl_->seg_data.Put((*iter).GetLineErr(), offset + 102, 10, "%10.4f");
+        pimpl_->seg_data.Put((*iter).GetZErr(), offset + 112, 10, "%10.4f");
+        pimpl_->seg_data.Put((*iter).GetXErr(), offset + 122, 14, "%14.4e");
+        pimpl_->seg_data.Put((*iter).GetYErr(), offset + 136, 14, "%14.4e");
+        pimpl_->seg_data.Put((*iter).GetIDString(), offset + 192, 64, true );
         
         id++;
         iter++;
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp b/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
index 1303f76..671b1ed 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
@@ -155,6 +155,8 @@ void CPCIDSKGeoref::Load()
         ThrowPCIDSKException( "Unexpected GEO segment type: %s", 
                               seg_data.Get(0,16) );
     }
+
+    loaded = true;
 }
 
 /************************************************************************/
@@ -997,7 +999,8 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 /* -------------------------------------------------------------------- */
 /*	Projection 0: Geographic (no projection)			*/
 /* -------------------------------------------------------------------- */
-    if( strncmp(geosys_clean.c_str(),"LONG ",5) == 0 )
+    if( strncmp(geosys_clean.c_str(),"LON",3) == 0 
+        || strncmp(geosys_clean.c_str(),"LAT",3) == 0 )
     {
         gsys = 0;
         UnitsCode = GCTP_UNIT_DEGREE;
diff --git a/frmts/pcidsk/sdk/segment/cpcidskpct.cpp b/frmts/pcidsk/sdk/segment/cpcidskpct.cpp
index 65ebd53..722fff0 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskpct.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskpct.cpp
@@ -68,9 +68,9 @@ void CPCIDSK_PCT::ReadPCT( unsigned char pct[768] )
     int i;
     for( i = 0; i < 256; i++ )
     {
-        pct[  0+i] = seg_data.GetInt(   0+i*4, 4 );
-        pct[256+i] = seg_data.GetInt(1024+i*4, 4 );
-        pct[512+i] = seg_data.GetInt(2048+i*4, 4 );
+        pct[  0+i] = (unsigned char) seg_data.GetInt(   0+i*4, 4 );
+        pct[256+i] = (unsigned char) seg_data.GetInt(1024+i*4, 4 );
+        pct[512+i] = (unsigned char) seg_data.GetInt(2048+i*4, 4 );
     }
 }
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h b/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
new file mode 100644
index 0000000..f68230c
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * Purpose: Support for reading and manipulating PCIDSK Polynomial Segments
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
+#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
+ 
+#include "pcidsk_poly.h"
+#include "segment/cpcidsksegment.h"
+ 
+namespace PCIDSK {
+    class PCIDSKFile;
+    
+    class CPCIDSKPolyModelSegment : public PCIDSKPolySegment,
+                                     public CPCIDSKSegment
+    {
+    public:
+        CPCIDSKPolyModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer);
+        ~CPCIDSKPolyModelSegment();
+        
+        std::vector<double> GetXForwardCoefficients() const;
+        std::vector<double> GetYForwardCoefficients() const;
+        std::vector<double> GetXBackwardCoefficients() const;
+        std::vector<double> GetYBackwardCoefficients() const;
+
+        void SetCoefficients(const std::vector<double>& oXForward,
+                             const std::vector<double>& oYForward,
+                             const std::vector<double>& oXBackward,
+                             const std::vector<double>& oYBackward) ;
+
+        unsigned int GetLines() const;
+        unsigned int GetPixels() const;
+        void SetRasterSize(unsigned int nLines,unsigned int nPixels) ;
+
+        std::string GetGeosysString() const;
+        void SetGeosysString(const std::string& oGeosys) ;
+
+        std::vector<double> GetProjParmInfo() const;
+        void SetProjParmInfo(const std::vector<double>& oInfo) ;
+
+        //synchronize the segment on disk.
+        void Synchronize();
+    private:
+        // Helper housekeeping functions
+        void Load();
+        void Write();
+        
+        struct PCIDSKPolyInfo;
+        PCIDSKPolyInfo *pimpl_;
+        bool loaded_;
+        bool mbModified;
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKPOLYMODEL_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp
index 109b023..9b7f669 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.cpp
@@ -87,7 +87,7 @@ struct CPCIDSKRPCModelSegment::PCIDSKRPCInfo
 
 CPCIDSKRPCModelSegment::CPCIDSKRPCModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer) :
     CPCIDSKSegment(file, segment, segment_pointer), pimpl_(new CPCIDSKRPCModelSegment::PCIDSKRPCInfo), 
-    loaded_(false)
+    loaded_(false),mbModified(false)
 {
     Load();
 }
@@ -124,24 +124,42 @@ void CPCIDSKRPCModelSegment::Load()
     // Bytes 30-35: 'SENSOR'
     // Bytes    36: Sensor Name (NULL terminated)
     
-    if (std::strncmp(pimpl_->seg_data.buffer, "RFMODEL ", 8)) {
+    if (std::strncmp(pimpl_->seg_data.buffer, "RFMODEL ", 8)) 
+    {
+        pimpl_->seg_data.Put("RFMODEL",0,8);
+        pimpl_->userrpc = false;
+        pimpl_->adjusted = false;
+        pimpl_->seg_data.Put("DS",22,2);
+        pimpl_->downsample = 1;
+        pimpl_->seg_data.Put("SENSOR",30,6);
+        pimpl_->num_coeffs = 20;
+        loaded_ = true;
+        return;
         // Something has gone terribly wrong!
-        throw PCIDSKException("A segment that was previously identified as an RFMODEL "
+        /*throw PCIDSKException("A segment that was previously identified as an RFMODEL "
             "segment does not contain the appropriate data. Found: [%s]", 
-            std::string(pimpl_->seg_data.buffer, 8).c_str());
+            std::string(pimpl_->seg_data.buffer, 8).c_str());*/
     }
     
     // Determine if this is user-provided
-    pimpl_->userrpc = pimpl_->seg_data.buffer[8] == 0 ? true : false;
+    pimpl_->userrpc = pimpl_->seg_data.buffer[8] == '1' ? true : false;
     
     // Check for the DS characters
     pimpl_->downsample = 1;
-    if (!std::strncmp(&pimpl_->seg_data.buffer[22], "DS", 2)) {
+    if (!std::strncmp(&pimpl_->seg_data.buffer[22], "DS", 2)) 
+    {
         // Read the downsample factor
         pimpl_->downsample = pimpl_->seg_data.GetInt(24, 3);
     }
     
-    // I don't know what 2ND means yet.
+    //This is requiered if writting with PCIDSKIO 
+    //and reading with GDBIO (probably because of legacy issue)
+    // see Bugzilla 255 and 254.
+    bool bSecond = false;
+    if (!std::strncmp(&pimpl_->seg_data.buffer[27], "2ND", 3)) 
+    {
+        bSecond = true;
+    }
     
     // Sensor name:
     if (!std::strncmp(&pimpl_->seg_data.buffer[30], "SENSOR", 6)) {
@@ -166,39 +184,109 @@ void CPCIDSKRPCModelSegment::Load()
     // Bytes 222-243: line scale
     // Bytes 244-375: Adjusted X coefficients (5 * 22 bytes)
     // Bytes 376-507: Adjusted Y coefficients (5 * 22 bytes)
-    
-    pimpl_->num_coeffs = pimpl_->seg_data.GetInt(512, 4);
-    
-    if (pimpl_->num_coeffs * 22 > 512) {
-        // this segment is malformed. Throw an exception.
-        throw PCIDSKException("RFMODEL segment coefficient count requires more "
-            "than one block to store. There is an error in this segment. The "
-            "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
-    }
-    
-    pimpl_->lines = pimpl_->seg_data.GetInt(512 + 4, 10);
-    pimpl_->pixels = pimpl_->seg_data.GetInt(512 + 14, 10);
-    pimpl_->x_off = pimpl_->seg_data.GetDouble(512 + 24, 22);
-    pimpl_->x_scale = pimpl_->seg_data.GetDouble(512 + 46, 22);
-    pimpl_->y_off = pimpl_->seg_data.GetDouble(512 + 68, 22);
-    pimpl_->y_scale = pimpl_->seg_data.GetDouble(512 + 90, 22);
-    pimpl_->z_off = pimpl_->seg_data.GetDouble(512 + 112, 22);
-    pimpl_->z_scale = pimpl_->seg_data.GetDouble(512 + 134, 22);
-    pimpl_->pix_off = pimpl_->seg_data.GetDouble(512 + 156, 22);
-    pimpl_->pix_scale = pimpl_->seg_data.GetDouble(512 + 178, 22);
-    pimpl_->line_off = pimpl_->seg_data.GetDouble(512 + 200, 22);
-    pimpl_->line_scale = pimpl_->seg_data.GetDouble(512 + 222, 22);
-    
-    // Read in adjusted X coefficients
-    for (unsigned int i = 0; i <= 5; i++) {
-        double tmp = pimpl_->seg_data.GetDouble(512 + 244 + (i * 22), 22);
-        pimpl_->x_adj.push_back(tmp);
+    // if bSecond is false, then the coefficient are stored
+    // at others positions
+    // every value takes 22 bytes.
+    
+    if(bSecond)
+    {
+        pimpl_->num_coeffs = pimpl_->seg_data.GetInt(512, 4);
+
+        if (pimpl_->num_coeffs * 22 > 512) {
+            // this segment is malformed. Throw an exception.
+            throw PCIDSKException("RFMODEL segment coefficient count requires more "
+                "than one block to store. There is an error in this segment. The "
+                "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
+        }
+
+        pimpl_->lines = pimpl_->seg_data.GetInt(512 + 4, 10);
+        pimpl_->pixels = pimpl_->seg_data.GetInt(512 + 14, 10);
+        pimpl_->x_off = pimpl_->seg_data.GetDouble(512 + 24, 22);
+        pimpl_->x_scale = pimpl_->seg_data.GetDouble(512 + 46, 22);
+        pimpl_->y_off = pimpl_->seg_data.GetDouble(512 + 68, 22);
+        pimpl_->y_scale = pimpl_->seg_data.GetDouble(512 + 90, 22);
+        pimpl_->z_off = pimpl_->seg_data.GetDouble(512 + 112, 22);
+        pimpl_->z_scale = pimpl_->seg_data.GetDouble(512 + 134, 22);
+        pimpl_->pix_off = pimpl_->seg_data.GetDouble(512 + 156, 22);
+        pimpl_->pix_scale = pimpl_->seg_data.GetDouble(512 + 178, 22);
+        pimpl_->line_off = pimpl_->seg_data.GetDouble(512 + 200, 22);
+        pimpl_->line_scale = pimpl_->seg_data.GetDouble(512 + 222, 22);
+
+        pimpl_->adjusted = false;
+        // Read in adjusted X coefficients
+        for (unsigned int i = 0; i <= 5; i++) 
+        {
+            double tmp = pimpl_->seg_data.GetDouble(512 + 244 + (i * 22), 22);
+            pimpl_->x_adj.push_back(tmp);
+            if (0.0 != tmp)
+            {
+                pimpl_->adjusted = true;
+            }
+        }
+
+        // Read in adjusted Y coefficients
+        for (unsigned int i = 0; i <= 5; i++) 
+        {
+            double tmp = pimpl_->seg_data.GetDouble(512 + 376 + (i * 22), 22);
+            pimpl_->y_adj.push_back(tmp);
+            if (0.0 != tmp)
+            {
+                pimpl_->adjusted = true;
+            }
+        }
     }
-    
-    // Read in adjusted Y coefficients
-    for (unsigned int i = 0; i <= 5; i++) {
-        double tmp = pimpl_->seg_data.GetDouble(512 + 376 + (i * 22), 22);
-        pimpl_->y_adj.push_back(tmp);
+    else
+    {
+        pimpl_->num_coeffs = pimpl_->seg_data.GetInt(512, 22);
+
+        if (pimpl_->num_coeffs * 22 > 512) {
+            // this segment is malformed. Throw an exception.
+            throw PCIDSKException("RFMODEL segment coefficient count requires more "
+                "than one block to store. There is an error in this segment. The "
+                "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
+        }
+
+        pimpl_->lines = pimpl_->seg_data.GetInt(512 + 22, 22);
+        pimpl_->pixels = pimpl_->seg_data.GetInt(512 + 2*22,22);
+        pimpl_->x_off = pimpl_->seg_data.GetDouble(512 + 3*22, 22);
+        pimpl_->x_scale = pimpl_->seg_data.GetDouble(512 + 4*22, 22);
+        pimpl_->y_off = pimpl_->seg_data.GetDouble(512 + 5*22, 22);
+        pimpl_->y_scale = pimpl_->seg_data.GetDouble(512 + 6*22, 22);
+        pimpl_->z_off = pimpl_->seg_data.GetDouble(512 + 7*22, 22);
+        pimpl_->z_scale = pimpl_->seg_data.GetDouble(512 + 8*22, 22);
+        pimpl_->pix_off = pimpl_->seg_data.GetDouble(512 + 9*22, 22);
+        pimpl_->pix_scale = pimpl_->seg_data.GetDouble(512 + 10*22, 22);
+        pimpl_->line_off = pimpl_->seg_data.GetDouble(512 + 11*22, 22);
+        pimpl_->line_scale = pimpl_->seg_data.GetDouble(512 + 12*22, 22);
+
+        pimpl_->adjusted = false;
+        // Read in adjusted X coefficients
+        for (unsigned int i = 0; i <= 3; i++) 
+        {
+            double tmp = pimpl_->seg_data.GetDouble(512 + 12*22 + (i * 22), 22);
+            pimpl_->x_adj.push_back(tmp);
+            if (0.0 != tmp)
+            {
+                pimpl_->adjusted = true;
+            }
+        }
+        pimpl_->x_adj.push_back(0.0);
+        pimpl_->x_adj.push_back(0.0);
+        pimpl_->x_adj.push_back(0.0);
+
+        // Read in adjusted Y coefficients
+        for (unsigned int i = 0; i <= 3; i++) 
+        {
+            double tmp = pimpl_->seg_data.GetDouble(512 + 16*22 + (i * 22), 22);
+            pimpl_->y_adj.push_back(tmp);
+            if (0.0 != tmp)
+            {
+                pimpl_->adjusted = true;
+            }
+        }
+        pimpl_->y_adj.push_back(0.0);
+        pimpl_->y_adj.push_back(0.0);
+        pimpl_->y_adj.push_back(0.0);
     }
     
     // Block 3:
@@ -242,7 +330,138 @@ void CPCIDSKRPCModelSegment::Load()
 
 void CPCIDSKRPCModelSegment::Write(void)
 {
+    //We are not writing if nothing was loaded.
+    if (!loaded_) {
+        return;
+    }
+      
+    // The RPC Model Segment is defined as follows:
+    // RFMODEL Segment: 7 512-byte blocks
+    
+    // Block 1:
+    // Bytes   0-7: 'RFMODEL '
+    // Byte      8: User Provided RPC (1: user-provided, 0: computed from GCPs)
+    // Bytes 22-23: 'DS' 
+    // Bytes 24-26: Downsample factor used during Epipolar Generation
+    // Bytes 27-29: '2ND' -- no clue what this means
+    // Bytes 30-35: 'SENSOR'
+    // Bytes    36: Sensor Name (NULL terminated)
+    pimpl_->seg_data.Put("RFMODEL",0,8);
+    
+    // Determine if this is user-provided
+    pimpl_->seg_data.buffer[8] = pimpl_->userrpc ? '1' : '0';
+    
+    // Check for the DS characters
+    pimpl_->seg_data.Put("DS",22,2);
+    pimpl_->seg_data.Put(pimpl_->downsample,24,3);
+
+    //This is requiered if writting with PCIDSKIO 
+    //and reading with GDBIO (probably because of legacy issue)
+    // see Bugzilla 255 and 254.
+    pimpl_->seg_data.Put("2ND",27,3);
+
+    // Sensor name:
+    pimpl_->seg_data.Put("SENSOR",30,6);
+    pimpl_->seg_data.Put(pimpl_->sensor_name.c_str(),36,pimpl_->sensor_name.size());
+  
+    // Block 2:
+    // Bytes     0-3: Number of coefficients
+    // Bytes    4-13: Number of pixels
+    // Bytes   14-23: Number of lines
+    // Bytes   24-45: Longitude offset
+    // Bytes   46-67: Longitude scale
+    // Bytes   68-89: Latitude Offset
+    // Bytes  90-111: Latitude Scale
+    // Bytes 112-133: Height offset
+    // Bytes 134-155: Height scale
+    // Bytes 156-177: Sample offset
+    // Bytes 178-199: Sample scale
+    // Bytes 200-221: Line offset
+    // Bytes 222-243: line scale
+    // Bytes 244-375: Adjusted X coefficients (5 * 22 bytes)
+    // Bytes 376-507: Adjusted Y coefficients (5 * 22 bytes)
+
+    if (pimpl_->num_coeffs * 22 > 512) {
+        // this segment is malformed. Throw an exception.
+        throw PCIDSKException("RFMODEL segment coefficient count requires more "
+            "than one block to store. There is an error in this segment. The "
+            "number of coefficients according to the segment is %d.", pimpl_->num_coeffs);
+    }
+    
+    pimpl_->seg_data.Put(pimpl_->num_coeffs,512, 4);
+    
+    pimpl_->seg_data.Put(pimpl_->lines,512 + 4, 10);
+    pimpl_->seg_data.Put(pimpl_->pixels,512 + 14, 10);
+    pimpl_->seg_data.Put(pimpl_->x_off,512 + 24, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->x_scale,512 + 46, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->y_off,512 + 68, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->y_scale,512 + 90, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->z_off,512 + 112, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->z_scale,512 + 134, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->pix_off,512 + 156, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->pix_scale,512 + 178, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->line_off,512 + 200, 22,"%22.14f");
+    pimpl_->seg_data.Put(pimpl_->line_scale,512 + 222, 22,"%22.14f");
+    
+    // Read in adjusted X coefficients
+    for (unsigned int i = 0; i <= 5; i++) 
+    {
+        pimpl_->seg_data.Put(pimpl_->x_adj[i],512 + 244 + (i * 22), 22,"%22.14f");
+        if(pimpl_->x_adj[i] != 0.0)
+        {
+            pimpl_->adjusted = true;
+        }
+    }
+    
+    // Read in adjusted Y coefficients
+    for (unsigned int i = 0; i <= 5; i++) 
+    {
+        pimpl_->seg_data.Put(pimpl_->y_adj[i],512 + 376 + (i * 22), 22,"%22.14f");
+        if(pimpl_->y_adj[i] != 0.0)
+        {
+            pimpl_->adjusted = true;
+        }
+    }
     
+    // Block 3:
+    // Block 3 contains the numerator coefficients for the pixel rational polynomial
+    // Number of Coefficients * 22 bytes
+    for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) 
+    {
+        pimpl_->seg_data.Put(pimpl_->pixel_num[i],2 * 512 + (i * 22), 22,"%22.14f");
+    }
+    
+    // Block 4:
+    // Block 4 contains the denominator coefficients for the pixel rational polynomial
+    // Number of Coefficients * 22 bytes
+    for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) 
+    {
+        pimpl_->seg_data.Put(pimpl_->pixel_denom[i],3 * 512 + (i * 22), 22,"%22.14f");
+    }
+    
+    // Block 5:
+    // Block 5 contains the numerator coefficients for the line rational polynomial
+    // Number of Coefficients * 22 bytes
+    for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) 
+    {
+        pimpl_->seg_data.Put(pimpl_->line_num[i],4 * 512 + (i * 22), 22,"%22.14f");
+    }
+    
+    // Block 6:
+    // Block 6 contains the denominator coefficients for the line rational polynomial
+    // Number of Coefficients * 22 bytes
+    for (unsigned int i = 0; i < pimpl_->num_coeffs; i++) 
+    {
+        pimpl_->seg_data.Put(pimpl_->line_denom[i],5 * 512 + (i * 22), 22,"%22.14f");
+    }
+    
+    // Block 7:
+    // Bytes    0-15: MapUnits string
+    // Bytes 256-511: ProjInfo_t, serialized
+    pimpl_->seg_data.Put(pimpl_->map_units.c_str(),6 * 512, 16);
+   
+    WriteToFile(pimpl_->seg_data.buffer,0,data_size-1024);
+    mbModified = false;
 }
 
 std::vector<double> CPCIDSKRPCModelSegment::GetXNumerator(void) const
@@ -280,6 +499,7 @@ void CPCIDSKRPCModelSegment::SetCoefficients(
     pimpl_->pixel_denom = xdenom;   
     pimpl_->line_num = ynum;
     pimpl_->line_denom = ydenom;
+    mbModified = true;
 }
     
 // Get the RPC offset/scale Coefficients
@@ -326,6 +546,7 @@ void CPCIDSKRPCModelSegment::SetRPCTranslationCoeffs(
     pimpl_->line_off = lineoffset;
     pimpl_->line_scale = linescale;
 
+    mbModified = true;
 }
 
 // Get the adjusted X values
@@ -346,11 +567,13 @@ void CPCIDSKRPCModelSegment::SetAdjCoordValues(const std::vector<double>& xcoord
 {
     if (xcoord.size() != 6 || ycoord.size() != 6) {
         throw PCIDSKException("X and Y adjusted coordinates must have "
-            "length 5.");
+            "length 6.");
     }
     
     pimpl_->x_adj = xcoord;
     pimpl_->y_adj = ycoord;
+
+    mbModified = true;
 }
 
 // Get whether or not this is a user-generated RPC model
@@ -363,6 +586,7 @@ bool CPCIDSKRPCModelSegment::IsUserGenerated(void) const
 void CPCIDSKRPCModelSegment::SetUserGenerated(bool usergen)
 {
     pimpl_->userrpc = usergen;
+    mbModified = true;
 }
 
 // Get whether the model has been adjusted
@@ -375,6 +599,7 @@ bool CPCIDSKRPCModelSegment::IsNominalModel(void) const
 void CPCIDSKRPCModelSegment::SetIsNominalModel(bool nominal)
 {
     pimpl_->adjusted = !nominal;
+    mbModified = true;
 }
 
 // Get sensor name
@@ -387,6 +612,7 @@ std::string CPCIDSKRPCModelSegment::GetSensorName(void) const
 void CPCIDSKRPCModelSegment::SetSensorName(const std::string& name)
 {
     pimpl_->sensor_name = name;
+    mbModified = true;
 }
 
 // Output projection information of RPC Model
@@ -404,6 +630,7 @@ void CPCIDSKRPCModelSegment::SetGeosysString(const std::string& geosys)
             "16 characters to be valid.");
     }
     pimpl_->map_units = geosys;
+    mbModified = true;
 }
 
 // Get number of lines
@@ -425,4 +652,29 @@ void CPCIDSKRPCModelSegment::SetRasterSize(const unsigned int lines, const unsig
     
     pimpl_->lines = lines;
     pimpl_->pixels = pixels;
+    mbModified = true;
 }
+
+void CPCIDSKRPCModelSegment::SetDownsample(const unsigned int downsample)
+{
+    if (downsample == 0) {
+        throw PCIDSKException("Invalid downsample factor provided: %u", downsample);
+    }
+    
+    pimpl_->downsample = downsample;
+    mbModified = true;
+}
+
+unsigned int CPCIDSKRPCModelSegment::GetDownsample(void) const
+{
+    return pimpl_->downsample;
+}
+
+void CPCIDSKRPCModelSegment::Synchronize()
+{
+    if(mbModified)
+    {
+        this->Write();
+    }
+}
+
diff --git a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
index d4e910c..224eb4b 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
@@ -103,6 +103,15 @@ namespace PCIDSK {
         
         // Set the number of lines/pixels
         void SetRasterSize(const unsigned int lines, const unsigned int pixels);
+
+        // Set the downsample factor
+        void SetDownsample(const unsigned int downsample);
+
+        // Get the downsample factor
+        unsigned int GetDownsample(void) const;
+
+        //synchronize the segment on disk.
+        void Synchronize();
     private:
         // Helper housekeeping functions
         void Load();
@@ -111,6 +120,7 @@ namespace PCIDSK {
         struct PCIDSKRPCInfo;
         PCIDSKRPCInfo *pimpl_;
         bool loaded_;
+        bool mbModified;
     };
 }
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
new file mode 100644
index 0000000..8d9eba7
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
@@ -0,0 +1,892 @@
+/******************************************************************************
+ *
+ * Purpose:  Implementation of the CPCIDSKToutinModelSegment class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 "segment/cpcidsksegment.h"
+#include "core/pcidsk_utils.h"
+#include "segment/cpcidsktoutinmodel.h"
+#include "pcidsk_exception.h"
+#include "core/pcidsk_utils.h"
+
+#include <vector>
+#include <string>
+#include <cassert>
+#include <cstring>
+
+using namespace PCIDSK;
+
+namespace
+{
+    /** 
+     * Function to get the minimum value of two values.
+     * 
+     * @param a The first value.
+     * @param b The second value.
+     * 
+     * @return The minimum value of the two specified values.
+     */
+    int MinFunction(int a,int b) 
+    {
+        return (a<b)?a:b;
+    }
+}
+
+CPCIDSKToutinModelSegment::CPCIDSKToutinModelSegment(PCIDSKFile *file, 
+                                                   int segment,
+                                                   const char *segment_pointer) :
+    CPCIDSKEphemerisSegment(file, segment, segment_pointer,false)
+{
+    loaded_ = false;
+    mbModified = false;
+    mpoInfo = NULL;
+    Load();
+}
+
+
+CPCIDSKToutinModelSegment::~CPCIDSKToutinModelSegment()
+{
+    delete mpoInfo;
+}
+
+/**
+ * Get the SRITInfo_t structure from read from the segment.
+ * @return the Toutin information structure.
+ */
+SRITInfo_t CPCIDSKToutinModelSegment::GetInfo() const
+{
+    return (*mpoInfo);
+}
+
+/**
+ * Set the toutin information in the segment. The segment will be tag
+ * as modified and will be synchronize on disk with the next call to 
+ * the function synchronize.
+ * @param oInfo the toutin information.
+ */
+void CPCIDSKToutinModelSegment::SetInfo(const SRITInfo_t& oInfo)
+{
+    if(&oInfo == mpoInfo)
+    {
+        return ;
+    }
+    if(mpoInfo)
+    {
+        delete mpoInfo;
+    }
+
+    mpoInfo = new SRITInfo_t(oInfo);
+    mbModified = true;
+}
+
+/**
+ * Load the contents of the segment
+ */
+void CPCIDSKToutinModelSegment::Load()
+{
+    // Check if we've already loaded the segment into memory
+    if (loaded_) {
+        return;
+    }
+
+    seg_data.SetSize((int)data_size - 1024);
+    
+    ReadFromFile(seg_data.buffer, 0, data_size - 1024);
+    
+    SRITInfo_t* poInfo = BinaryToSRITInfo();
+
+    mpoInfo = poInfo;
+    
+    // We've now loaded the structure up with data. Mark it as being loaded 
+    // properly.
+    loaded_ = true;
+    
+}
+
+/**
+ * Write the segment on disk
+ */
+void CPCIDSKToutinModelSegment::Write(void)
+{
+    //We are not writing if nothing was loaded.
+    if (!loaded_) {
+        return;
+    }
+
+    SRITInfoToBinary(mpoInfo);
+
+    WriteToFile(seg_data.buffer,0,seg_data.buffer_size);
+
+    mbModified = false;
+}
+
+/**
+ * Synchronize the segement, if it was modified then
+ * write it into disk.
+ */
+void CPCIDSKToutinModelSegment::Synchronize()
+{
+    if(mbModified)
+    {
+        this->Write();
+    }
+}
+
+/************************************************************************/
+/*                           BinaryToSRITInfo()                         */
+/************************************************************************/
+/**
+  * Translate a block of binary data into a SRIT segment. the caller is 
+  * responsible to free the returned memory with delete.
+  *
+  * @return Rational Satellite Model structure.
+  */
+SRITInfo_t *
+CPCIDSKToutinModelSegment::BinaryToSRITInfo()
+{
+    int		i,j,k,l;
+    SRITInfo_t 	*SRITModel;
+    bool	bVersion9;
+
+/* -------------------------------------------------------------------- */
+/*	Read the header block						*/
+/* -------------------------------------------------------------------- */    
+    // We test the name of the binary segment before starting to read 
+    // the buffer.
+    if (std::strncmp(seg_data.buffer, "MODEL   ", 8)) 
+    {
+        seg_data.Put("MODEL   ",0,8);
+        return NULL;
+        // Something has gone terribly wrong!
+        /*throw PCIDSKException("A segment that was previously "
+            "identified as an RFMODEL "
+            "segment does not contain the appropriate data. Found: [%s]", 
+            std::string(seg_data.buffer, 8).c_str());*/
+    }
+
+    bVersion9 = false;
+    int nVersion = seg_data.GetInt(8,1);
+    if (nVersion == 9)
+    {
+	bVersion9 = true;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Allocate the SRITModel.                                         */
+/* -------------------------------------------------------------------- */
+    SRITModel = new SRITInfo_t();
+    
+    SRITModel->GCPMeanHtFlag = 0;
+    SRITModel->nDownSample = 1;
+    if(std::strncmp(seg_data.Get(22,2) , "DS", 2)==0)
+    {
+	SRITModel->nDownSample = seg_data.GetInt(24,3); 
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the Block 1                                                */
+/* -------------------------------------------------------------------- */
+    
+    SRITModel->N0x2        = seg_data.GetDouble(512,22);
+    SRITModel->aa          = seg_data.GetDouble(512+22,22);
+    SRITModel->SmALPHA     = seg_data.GetDouble(512+44,22);
+    SRITModel->bb          = seg_data.GetDouble(512+66,22);
+    SRITModel->C0          = seg_data.GetDouble(512+88,22);
+    SRITModel->cc          = seg_data.GetDouble(512+110,22);
+    SRITModel->COS_KHI     = seg_data.GetDouble(512+132,22);
+    SRITModel->DELTA_GAMMA = seg_data.GetDouble(512+154,22);
+    SRITModel->GAMMA       = seg_data.GetDouble(512+176,22);
+    SRITModel->K_1         = seg_data.GetDouble(512+198,22);
+    SRITModel->L0          = seg_data.GetDouble(512+220,22);
+    SRITModel->P           = seg_data.GetDouble(512+242,22);
+    SRITModel->Q           = seg_data.GetDouble(512+264,22);
+    SRITModel->TAU         = seg_data.GetDouble(512+286,22);
+    SRITModel->THETA       = seg_data.GetDouble(512+308,22);
+    SRITModel->THETA_SEC   = seg_data.GetDouble(512+330,22);
+    SRITModel->X0          = seg_data.GetDouble(512+352,22);
+    SRITModel->Y0          = seg_data.GetDouble(512+374,22);
+    SRITModel->delh        = seg_data.GetDouble(512+396,22);
+    SRITModel->COEF_Y2     = seg_data.GetDouble(512+418,22);
+
+    if (bVersion9)
+    {
+        SRITModel->delT        = seg_data.GetDouble(512+440,22);
+        SRITModel->delL        = seg_data.GetDouble(512+462,22);
+        SRITModel->delTau      = seg_data.GetDouble(512+484,22);
+    }
+    else
+    {
+        SRITModel->delT   = 0.0;
+        SRITModel->delL   = 0.0;
+        SRITModel->delTau = 0.0;
+    }
+                                                                  
+/* -------------------------------------------------------------------- */
+/*	Read the GCP information in Block 2     			*/
+/* -------------------------------------------------------------------- */
+
+    SRITModel->nGCPCount       = seg_data.GetInt(2*512,10); 
+    SRITModel->nEphemerisSegNo = seg_data.GetInt(2*512+10,10); 
+    SRITModel->nAttitudeFlag   = seg_data.GetInt(2*512+20,10); 
+    SRITModel->GCPUnit = seg_data.Get(2*512+30,16);
+
+    SRITModel->dfGCPMeanHt = seg_data.GetDouble(2*512+50,22); 
+    SRITModel->dfGCPMinHt  = seg_data.GetDouble(2*512+72,22);
+    SRITModel->dfGCPMaxHt  = seg_data.GetDouble(2*512+94,22);
+
+/* -------------------------------------------------------------------- */
+/*      Initialize a simple GeoTransform.                               */
+/* -------------------------------------------------------------------- */
+
+    SRITModel->utmunit = seg_data.Get(2*512+225,16);
+
+    if (std::strcmp(seg_data.Get(2*512+245,8),"ProjInfo")==0)
+    {
+        SRITModel->oProjectionInfo = seg_data.Get(2*512+255,256);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the GCPs							*/
+/* -------------------------------------------------------------------- */
+    l = 0;
+    k = 4;
+    for (j=0; j<SRITModel->nGCPCount; j++)
+    {
+        SRITModel->nGCPIds[j] = 
+            seg_data.GetInt((k-1)*512+10*l,5);  
+        SRITModel->nPixel[j]  = 
+            seg_data.GetInt((k-1)*512+10*(l+1),5);  
+        SRITModel->nLine[j]   = 
+            seg_data.GetInt((k-1)*512+10*(l+1)+5,5);  
+        SRITModel->dfElev[j]  = 
+            seg_data.GetInt((k-1)*512+10*(l+2),10);  
+        l+=3;
+     
+        if (l<50)
+            continue;
+     
+        k++;
+        l = 0;
+    }
+     
+/* -------------------------------------------------------------------- */
+/*      Call BinaryToEphemeris to get the orbital data		        */
+/* -------------------------------------------------------------------- */
+    SRITModel->OrbitPtr =
+        BinaryToEphemeris( 512*21 );
+    
+/* -------------------------------------------------------------------- */
+/*      Pass the sensor back to SRITModel				*/
+/* -------------------------------------------------------------------- */
+    SRITModel->Sensor = SRITModel->OrbitPtr->SatelliteSensor;
+
+/* -------------------------------------------------------------------- */
+/*      Assign nSensor value						*/
+/* -------------------------------------------------------------------- */
+
+    SRITModel->nSensor = GetSensor (SRITModel->OrbitPtr);
+    SRITModel->nModel  = GetModel (SRITModel->nSensor);
+
+    if( SRITModel->nSensor == -999)
+    {
+        throw PCIDSKException("Invalid Sensor : %s.",
+                              SRITModel->OrbitPtr->SatelliteSensor.c_str());
+    }
+    if( SRITModel->nModel == -999)
+    {
+	throw PCIDSKException("Invalid Model from sensor number: %d.",
+                              SRITModel->nSensor);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get the attitude data for SPOT					*/
+/* -------------------------------------------------------------------- */
+    if (SRITModel->OrbitPtr->AttitudeSeg != NULL ||
+        SRITModel->OrbitPtr->RadarSeg != NULL)
+    {
+        if (SRITModel->OrbitPtr->Type == OrbAttitude)
+        {
+            int  ndata;
+            AttitudeSeg_t *attitudeSeg
+                = SRITModel->OrbitPtr->AttitudeSeg;
+
+	    ndata = SRITModel->OrbitPtr->AttitudeSeg->NumberOfLine;
+       
+            for (i=0; i<ndata; i++)
+            {
+                SRITModel->Hdeltat.push_back(
+                    attitudeSeg->Line[i].ChangeInAttitude);
+                SRITModel->Qdeltar.push_back(
+                    attitudeSeg->Line[i].ChangeEarthSatelliteDist);
+            }
+        }
+    }
+    else
+    {
+        SRITModel->Qdeltar.clear();
+        SRITModel->Hdeltat.clear();
+    }
+
+    return SRITModel;
+}
+
+/************************************************************************/
+/*                           SRITInfoToBinary()                         */
+/************************************************************************/
+/**
+  * Translate a SRITInfo_t into binary data.
+  * Translate a SRITInfo_t into the corresponding block of          
+  * binary data.  This function is expected to be used by           
+  * ranslators such as iisopen.c (VISTA) so that our satellite     
+  * models can be converted into some opaque serialized form.       
+  * Translate a RFInfo_t into the corresponding block of binary data. 
+  *
+  * @param  SRITModel	     Satellite Model structure.
+  * @param  pnBinaryLength	Length of binary data.
+  * @return Binary data for a  Satellite Model structure.
+  */
+void
+CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
+
+{
+    int		i,j,k,l;
+    double	dfminht,dfmaxht,dfmeanht;
+    int nPos = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Create the data array.                                          */
+/* -------------------------------------------------------------------- */
+    seg_data.SetSize(512 * 21);
+
+    //clean the buffer
+    memset( seg_data.buffer , ' ', 512 * 21 );
+    
+/* -------------------------------------------------------------------- */
+/*	Initialize the header.						*/
+/* -------------------------------------------------------------------- */
+    nPos = 512*0;
+    seg_data.Put("MODEL   9.0",0,nPos+11);
+
+    seg_data.Put("DS",nPos+22,2);
+    seg_data.Put(SRITModel->nDownSample,nPos+24,3);
+
+/* -------------------------------------------------------------------- */
+/*      Write the model results to second segment                       */
+/* -------------------------------------------------------------------- */
+    nPos = 512*1;
+    
+    seg_data.Put(SRITModel->N0x2,nPos,22,"%22.14f");
+    seg_data.Put(SRITModel->aa,nPos+22,22,"%22.14f");
+    seg_data.Put(SRITModel->SmALPHA,nPos+22*2,22,"%22.14f");
+    seg_data.Put(SRITModel->bb,nPos+22*3,22,"%22.14f");
+    seg_data.Put(SRITModel->C0,nPos+22*4,22,"%22.14f");
+    seg_data.Put(SRITModel->cc,nPos+22*5,22,"%22.14f");
+    seg_data.Put(SRITModel->COS_KHI,nPos+22*6,22,"%22.14f");
+    seg_data.Put(SRITModel->DELTA_GAMMA,nPos+22*7,22,"%22.14f");
+    seg_data.Put(SRITModel->GAMMA,nPos+22*8,22,"%22.14f");
+    seg_data.Put(SRITModel->K_1,nPos+22*9,22,"%22.14f");
+    seg_data.Put(SRITModel->L0,nPos+22*10,22,"%22.14f");
+    seg_data.Put(SRITModel->P,nPos+22*11,22,"%22.14f");
+    seg_data.Put(SRITModel->Q,nPos+22*12,22,"%22.14f");
+    seg_data.Put(SRITModel->TAU,nPos+22*13,22,"%22.14f");
+    seg_data.Put(SRITModel->THETA,nPos+22*14,22,"%22.14f");
+    seg_data.Put(SRITModel->THETA_SEC,nPos+22*15,22,"%22.14f");
+    seg_data.Put(SRITModel->X0,nPos+22*16,22,"%22.14f");
+    seg_data.Put(SRITModel->Y0,nPos+22*17,22,"%22.14f");
+    seg_data.Put(SRITModel->delh,nPos+22*18,22,"%22.14f");
+    seg_data.Put(SRITModel->COEF_Y2,nPos+22*19,22,"%22.14f");
+    seg_data.Put(SRITModel->delT,nPos+22*20,22,"%22.14f");
+    seg_data.Put(SRITModel->delL,nPos+22*21,22,"%22.14f");
+    seg_data.Put(SRITModel->delTau,nPos+22*22,22,"%22.14f");
+
+/* -------------------------------------------------------------------- */
+/*      Find the min and max height					*/
+/* -------------------------------------------------------------------- */
+    nPos = 2*512;
+
+    if (SRITModel->nGCPCount != 0)
+    {
+        dfminht = 1.e38;
+        dfmaxht = -1.e38;
+        for (i=0; i<SRITModel->nGCPCount; i++)
+        {
+            if (SRITModel->dfElev[i] > dfmaxht)
+                dfmaxht = SRITModel->dfElev[i];
+            if (SRITModel->dfElev[i] < dfminht)
+                dfminht = SRITModel->dfElev[i];
+        }
+    }
+    else
+    {
+	dfminht = SRITModel->dfGCPMinHt;
+	dfmaxht = 0;
+    }
+
+    dfmeanht = (dfminht + dfmaxht)/2.;
+
+    seg_data.Put(SRITModel->nGCPCount,nPos,10);
+    seg_data.Put("2",nPos+10,1);
+    seg_data.Put("0",nPos+20,1);
+
+    if (SRITModel->OrbitPtr->AttitudeSeg != NULL ||
+        SRITModel->OrbitPtr->RadarSeg != NULL ||
+        SRITModel->OrbitPtr->AvhrrSeg != NULL )
+    {
+        if (SRITModel->OrbitPtr->Type == OrbAttitude) 
+	{
+	    if (SRITModel->OrbitPtr->AttitudeSeg->NumberOfLine != 0)
+                seg_data.Put("3",nPos+20,1);
+	}
+    }
+	
+    seg_data.Put(SRITModel->GCPUnit.c_str(),nPos+30,16);
+    seg_data.Put("M",nPos+49,1);
+
+    seg_data.Put(dfmeanht,nPos+50,22,"%22.14f");
+    seg_data.Put(dfminht,nPos+72,22,"%22.14f");
+    seg_data.Put(dfmaxht,nPos+94,22,"%22.14f");
+
+    seg_data.Put("NEWGCP",nPos+116,6);
+
+/* -------------------------------------------------------------------- */
+/*      Write the projection parameter if necessary			*/
+/* -------------------------------------------------------------------- */
+
+    seg_data.Put(SRITModel->utmunit.c_str(),nPos+225,16);
+
+    if(SRITModel->oProjectionInfo.size() > 0)
+    {
+        seg_data.Put("ProjInfo: ",nPos+245,10);
+        seg_data.Put(SRITModel->oProjectionInfo.c_str(),
+                             nPos+255,256);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write the GCP to third segment                                  */
+/* -------------------------------------------------------------------- */
+    nPos = 3*512;
+
+    l = 0;
+    k = 3;
+    for (j=0; j<SRITModel->nGCPCount; j++)
+    {
+        if (j > 255)
+	    break;
+
+        seg_data.Put(SRITModel->nGCPIds[j],nPos+10*l,5);
+        seg_data.Put((int)(SRITModel->nPixel[j]+0.5),
+                             nPos+10*(l+1),5);
+        seg_data.Put((int)(SRITModel->nLine[j]+0.5),
+                             nPos+10*(l+1)+5,5);
+        seg_data.Put((int)SRITModel->dfElev[j],nPos+10*(l+2),10);
+
+        l+=3;
+     
+        if (l<50)
+            continue;
+     
+        k++;
+        nPos = 512*k;
+        l = 0;
+    }
+
+/* -------------------------------------------------------------------- */
+/*	Add the serialized form of the EphemerisSeg_t.			*/
+/* -------------------------------------------------------------------- */
+    EphemerisToBinary( SRITModel->OrbitPtr , 512*21 );
+}
+
+/**
+ * Get the sensor enum from the orbit segment.
+ * @param OrbitPtr the orbit segment
+ * @return the sensor type.
+ */
+int  CPCIDSKToutinModelSegment::GetSensor( EphemerisSeg_t *OrbitPtr)
+{
+    int  nSensor;
+
+    nSensor = -999;
+
+    if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"AVHRR",5))
+        nSensor = AVHRR;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"PLA",3))
+        nSensor = PLA_1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MLA",3))
+        nSensor = MLA_1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ASTER",5))
+        nSensor = ASTER;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SAR",3))
+    {
+        nSensor = SAR;
+        if (OrbitPtr->PixelRes == 6.25)
+            nSensor = RSAT_FIN;
+    }
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-1",6))
+        nSensor = LISS_1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-2",6))
+        nSensor = LISS_2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-3",6))
+        nSensor = LISS_3;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L3-L2",10))
+        nSensor = LISS_L3_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L3",7))
+        nSensor = LISS_L3;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L4-L2",10))
+        nSensor = LISS_L4_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-L4",7))
+        nSensor = LISS_L4;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-P3-L2",10))
+        nSensor = LISS_P3_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-P3",7))
+        nSensor = LISS_P3;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-W3-L2",10))
+        nSensor = LISS_W3_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-W3",7))
+        nSensor = LISS_W3;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-M3",7))
+        nSensor = LISS_M3;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-AWF-L2",11))
+        nSensor = LISS_AWF_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"LISS-AWF",8))
+        nSensor = LISS_AWF;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"EOC",3))
+        nSensor = EOC;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"IRS",3))
+        nSensor = IRS_1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"TM",2))
+    {
+        nSensor = TM;
+        if (OrbitPtr->PixelRes == 15)
+            nSensor = ETM;
+    }
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ETM",3))
+        nSensor = ETM;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"IKO",3))
+    {
+        nSensor = IKO_PAN;
+        if (OrbitPtr->PixelRes == 4)
+            nSensor = IKO_MULTI;
+    }
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ORBVIEW",7))
+    {
+        nSensor = ORBVIEW_PAN;
+        if (OrbitPtr->PixelRes == 4)
+            nSensor = ORBVIEW_MULTI;
+    }
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV",2))
+    {
+        if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_PAN_BASIC",13))
+            nSensor = OV3_PAN_BASIC;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_PAN_GEO",11))
+            nSensor = OV3_PAN_GEO;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_MULTI_BASIC",15))
+            nSensor = OV3_MULTI_BASIC;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV3_MULTI_GEO",13))
+            nSensor = OV3_MULTI_GEO;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_PAN_BASIC",13))
+            nSensor = OV5_PAN_BASIC;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_PAN_GEO",11))
+            nSensor = OV5_PAN_GEO;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_MULTI_BASIC",15))
+            nSensor = OV5_MULTI_BASIC;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"OV5_MULTI_GEO",13))
+            nSensor = OV5_MULTI_GEO;
+    }
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_PAN_STD",13))
+        nSensor = QBIRD_PAN_STD; 	// this checking must go first
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_PAN_STH",13))
+        nSensor = QBIRD_PAN_STH;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_PAN",9))
+        nSensor = QBIRD_PAN;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_MULTI_STD",15))
+        nSensor = QBIRD_MULTI_STD;	// this checking must go first
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_MULTI_STH",15))
+        nSensor = QBIRD_MULTI_STH;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"QBIRD_MULTI",11))
+        nSensor = QBIRD_MULTI;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW1_PAN_STD",14) ||
+        EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_PAN_STD",13))
+        nSensor = WVIEW_PAN_STD; 	// this checking must go first
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW1_PAN",10) ||
+        EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_PAN",9))
+        nSensor = WVIEW_PAN;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_MULTI_STD",15))
+        nSensor = WVIEW_MULTI_STD;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"WVIEW_MULTI",11))
+        nSensor = WVIEW_MULTI;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT",8))
+    {
+        if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_PAN_L2",15))
+            nSensor = FORMOSAT_PAN_L2;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_MULTIL2",16))
+            nSensor = FORMOSAT_MULTIL2;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_PAN",12))
+            nSensor = FORMOSAT_PAN;
+        else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"FORMOSAT_MULTI",14))
+            nSensor = FORMOSAT_MULTI;
+    }
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_PAN_2_5",13))
+        nSensor = SPOT5_PAN_2_5;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_PAN_5",11))
+        nSensor = SPOT5_PAN_5;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_HRS",9))
+        nSensor = SPOT5_HRS;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"SPOT5_MULTI",11))
+        nSensor = SPOT5_MULTI;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MERIS_FR",8))
+        nSensor = MERIS_FR;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MERIS_RR",8))
+        nSensor = MERIS_RR;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MERIS_LR",8))
+        nSensor = MERIS_LR;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ASAR",4))
+        nSensor = ASAR;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"EROS",4))
+        nSensor = EROS;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MODIS_1000",10))
+        nSensor = MODIS_1000;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MODIS_500",9))
+        nSensor = MODIS_500;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"MODIS_250",9))
+        nSensor = MODIS_250;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_HRC_L2",12))
+        nSensor = CBERS_HRC_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_HRC",9))
+        nSensor = CBERS_HRC;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_CCD_L2",12))
+        nSensor = CBERS_CCD_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_CCD",9))
+        nSensor = CBERS_CCD;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_80_L2",15))
+        nSensor = CBERS_IRM_80_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_80",12))
+        nSensor = CBERS_IRM_80;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_160_L2",16))
+        nSensor = CBERS_IRM_160_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_IRM_160",13))
+        nSensor = CBERS_IRM_160;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_WFI_L2",12))
+        nSensor = CBERS_WFI_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CBERS_WFI",9))
+        nSensor = CBERS_WFI;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CARTOSAT1_L1",12))
+        nSensor = CARTOSAT1_L1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"CARTOSAT1_L2",12))
+        nSensor = CARTOSAT1_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"DMC_1R",6))
+        nSensor = DMC_1R;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"DMC_1T",6))
+        nSensor = DMC_1T;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_PRISM_L1",13))
+        nSensor = ALOS_PRISM_L1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_PRISM_L2",13))
+        nSensor = ALOS_PRISM_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_AVNIR_L1",13))
+        nSensor = ALOS_AVNIR_L1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"ALOS_AVNIR_L2",13))
+        nSensor = ALOS_AVNIR_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"PALSAR",6))
+        nSensor = PALSAR;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"KOMPSAT2_PAN",12))
+        nSensor = KOMPSAT2_PAN;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"KOMPSAT2_MULTI",14))
+        nSensor = KOMPSAT2_MULTI;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"TERRASAR",8))
+        nSensor = TERRASAR;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"RAPIDEYE",8))
+        nSensor = RAPIDEYE_L1B;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_PAN_L1",12))
+        nSensor = THEOS_PAN_L1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_PAN_L2",12))
+        nSensor = THEOS_PAN_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_MS_L1",11))
+        nSensor = THEOS_MS_L1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"THEOS_MS_L2",11))
+        nSensor = THEOS_MS_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_500_L1",12))
+        nSensor = GOSAT_500_L1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_500_L2",12))
+        nSensor = GOSAT_500_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_1500_L1",13))
+        nSensor = GOSAT_1500_L1;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"GOSAT_1500_L2",13))
+        nSensor = GOSAT_1500_L2;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"HJ_CCD_1A",9))
+        nSensor = HJ_CCD_1A;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"HJ_CCD_1B",5))
+        nSensor = HJ_CCD_1B;
+    else if (EQUALN(OrbitPtr->SatelliteSensor.c_str(),"NEW",3))
+        nSensor = NEW;
+    else
+    {
+        throw PCIDSKException("Invalid Sensor %s",
+            OrbitPtr->SatelliteSensor.c_str());
+    }
+
+    return (nSensor);
+}
+/**
+ * Get the model of a sensor
+ * @param nSensor the sensor
+ * @return the model
+ */
+int CPCIDSKToutinModelSegment::GetModel( int nSensor )
+{
+    int  nModel;
+
+    nModel = -999;
+
+    switch (nSensor)
+    {
+    case PLA_1:
+    case PLA_2:
+    case PLA_3:
+    case PLA_4:
+    case MLA_1:
+    case MLA_2:
+    case MLA_3:
+    case MLA_4:
+    case NEW:
+        nModel = SRITModele;
+        break;
+
+    case ASTER:
+    case CBERS_CCD:
+    case CBERS_IRM_80:
+    case CBERS_IRM_160:
+    case CBERS_WFI:
+    case IRS_1:
+    case LISS_AWF:
+    case LISS_1:
+    case LISS_2:
+    case LISS_3:
+    case LISS_L3:
+    case LISS_L4:
+    case LISS_P3:
+    case LISS_W3:
+    case LISS_M3:
+    case EOC:
+    case SPOT5_PAN_5:
+    case SPOT5_HRS:
+    case SPOT5_MULTI:
+    case MERIS_FR:
+    case MERIS_RR:
+    case MERIS_LR:
+    case MODIS_1000:
+    case MODIS_500:
+    case MODIS_250:
+    case ALOS_AVNIR_L1:
+    case ALOS_AVNIR_L2:
+    case RAPIDEYE_L1B:
+    case THEOS_PAN_L1:
+    case THEOS_MS_L1:
+    case GOSAT_500_L1:
+    case GOSAT_1500_L1:
+    case HJ_CCD_1A:
+        nModel = SRITModele1A;
+        break;
+
+    case TM:
+    case ETM:
+    case LISS_P3_L2:
+    case LISS_L3_L2:
+    case LISS_W3_L2:
+    case LISS_L4_L2:
+    case LISS_AWF_L2:
+    case CBERS_IRM_80_L2:
+    case CBERS_IRM_160_L2:
+    case CBERS_WFI_L2:
+    case CBERS_CCD_L2:
+    case CBERS_HRC_L2:
+    case DMC_1R:
+    case DMC_1T:
+    case ALOS_PRISM_L2:
+    case THEOS_PAN_L2:
+    case THEOS_MS_L2:
+    case GOSAT_500_L2:
+    case GOSAT_1500_L2:
+    case HJ_CCD_1B:
+        nModel = SRITModele1B;
+        break;
+
+    case SAR:
+    case RSAT_FIN:
+    case RSAT_STD:
+    case ERS_1:
+    case ERS_2:
+    case ASAR:
+    case QBIRD_PAN_STD:
+    case QBIRD_MULTI_STD:
+    case WVIEW_PAN_STD:
+    case WVIEW_MULTI_STD:
+    case IKO_PAN:
+    case IKO_MULTI:
+    case CARTOSAT1_L2:
+    case PALSAR:
+    case FORMOSAT_PAN_L2:
+    case FORMOSAT_MULTIL2:
+    case TERRASAR:
+    case OV3_PAN_GEO:
+    case OV3_MULTI_GEO:
+    case OV5_PAN_GEO:
+    case OV5_MULTI_GEO:
+        nModel = SRITModeleSAR;
+        break;
+
+    case ORBVIEW_PAN:
+    case ORBVIEW_MULTI:
+    case QBIRD_PAN:
+    case QBIRD_MULTI:
+    case WVIEW_PAN:
+    case WVIEW_MULTI:
+    case SPOT5_PAN_2_5:
+    case CARTOSAT1_L1:
+    case ALOS_PRISM_L1:
+    case KOMPSAT2_PAN:
+    case KOMPSAT2_MULTI:
+    case CBERS_HRC:
+    case OV3_PAN_BASIC:
+    case OV3_MULTI_BASIC:
+    case OV5_PAN_BASIC:
+    case OV5_MULTI_BASIC:
+        nModel = SRITModele1AHR;
+        break;
+
+    case EROS:
+    case QBIRD_PAN_STH:
+    case QBIRD_MULTI_STH:
+    case FORMOSAT_PAN:
+    case FORMOSAT_MULTI:
+        nModel = SRITModeleEros;
+        break;
+
+    default:
+        throw PCIDSKException("Invalid sensor type.");
+        break;
+    }
+
+    return (nModel);
+}
+
diff --git a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
new file mode 100644
index 0000000..436d837
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
@@ -0,0 +1,68 @@
+/******************************************************************************
+ *
+ * Purpose: Support for reading and manipulating PCIDSK Toutin Segments
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
+#define __INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
+ 
+#include "pcidsk_toutin.h"
+#include "segment/cpcidsksegment.h"
+#include "segment/cpcidskephemerissegment.h"
+
+namespace PCIDSK {
+    class PCIDSKFile;
+
+    class CPCIDSKToutinModelSegment : public PCIDSKToutinSegment,
+                                      public CPCIDSKEphemerisSegment
+    {
+    public:
+        CPCIDSKToutinModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer);
+        ~CPCIDSKToutinModelSegment();
+
+        SRITInfo_t GetInfo() const;
+        void SetInfo(const SRITInfo_t& poInfo);
+
+        //synchronize the segment on disk.
+        void Synchronize();
+    private:
+        
+        // Helper housekeeping functions
+        void Load();
+        void Write();
+
+    //functions to read/write binary information
+    private:
+        //Toutin informations.
+        SRITInfo_t* mpoInfo;
+
+        SRITInfo_t *BinaryToSRITInfo();
+        void SRITInfoToBinary( SRITInfo_t *SRITModel);
+
+        int GetSensor( EphemerisSeg_t *OrbitPtr);
+        int GetModel( int nSensor );
+    };
+}
+
+#endif // __INCLUDE_PCIDSK_SEGMENT_PCIDSKTOUTINMODEL_H
diff --git a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
index 2b587be..8c29289 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
@@ -406,9 +406,9 @@ char *CPCIDSKVectorSegment::GetData( int section, uint32 offset,
 /* -------------------------------------------------------------------- */
 /*      Select the section to act on.                                   */
 /* -------------------------------------------------------------------- */
-    PCIDSKBuffer *pbuf;
-    uint32       *pbuf_offset;
-    bool         *pbuf_dirty;
+    PCIDSKBuffer *pbuf = NULL;
+    uint32       *pbuf_offset = NULL;
+    bool         *pbuf_dirty = NULL;
 
     if( section == sec_raw )
     {
@@ -540,9 +540,9 @@ void CPCIDSKVectorSegment::FlushDataBuffer( int section )
 /* -------------------------------------------------------------------- */
 /*      Select the section to act on.                                   */
 /* -------------------------------------------------------------------- */
-    PCIDSKBuffer *pbuf;
-    uint32       *pbuf_offset;
-    bool         *pbuf_dirty;
+    PCIDSKBuffer *pbuf = NULL;
+    uint32       *pbuf_offset = NULL;
+    bool         *pbuf_dirty = NULL;
 
     if( section == sec_raw )
     {
diff --git a/frmts/pcidsk/sdk/segment/orbitstructures.h b/frmts/pcidsk/sdk/segment/orbitstructures.h
new file mode 100644
index 0000000..3bdf8ac
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/orbitstructures.h
@@ -0,0 +1,845 @@
+/******************************************************************************
+ *
+ * Purpose: Support for storing and manipulating Orbit information
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_ORBIT_INFORMATION_H
+#define __INCLUDE_PCIDSK_ORBIT_INFORMATION_H
+
+#include <string>
+#include <vector>
+
+namespace PCIDSK
+{
+/* -------------------------------------------------------------------- */
+/*	Structure for ephemeris segment (ORBIT segment, type 160).	*/
+/* -------------------------------------------------------------------- */
+#define EPHEMERIS_BLK		8
+#define EPHEMERIS_RADAR_BLK     10
+#define EPHEMERIS_ATT_BLK	9
+/* -------------------------------------------------------------------- */
+/*	Structure for Satellite Radar segment.				*/
+/* -------------------------------------------------------------------- */
+#define ANC_DATA_PER_BLK	16
+#define ANC_DATA_SIZE		32
+    /**
+     * Ancillary data structure.
+     */
+    struct AncillaryData_t
+    {
+        /**
+         * Default constrcutor
+         */
+        AncillaryData_t()
+        {
+        }
+        /**
+         * Copy constructor
+         * @param oAD the ancillary data to copy
+         */
+        AncillaryData_t(const AncillaryData_t& oAD)
+        {
+            Copy(oAD);
+        }
+
+        /**
+         * assignement operator
+         * @param oAD the ancillary data to assign
+         */
+        AncillaryData_t& operator=(const AncillaryData_t& oAD)
+        {
+            Copy(oAD);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oAD the ancillary data to copy
+         */
+        void Copy(const AncillaryData_t& oAD)
+        {
+            if(this == &oAD)
+            {
+                return;
+            }
+            SlantRangeFstPixel = oAD.SlantRangeFstPixel;	
+            SlantRangeLastPixel = oAD.SlantRangeLastPixel;	
+            FstPixelLat = oAD.FstPixelLat;		
+            MidPixelLat = oAD.MidPixelLat;		
+            LstPixelLat = oAD.LstPixelLat;		
+            FstPixelLong = oAD.FstPixelLong;		
+            MidPixelLong = oAD.MidPixelLong;		
+            LstPixelLong = oAD.LstPixelLong;	
+        }
+
+        int   SlantRangeFstPixel;	/* Slant Range to First Pixel (m)	     */
+        int   SlantRangeLastPixel;	/* Slant Range to Last Pixel (m)	     */
+        float FstPixelLat;		/* First Pixel Latitude (millionths degrees) */
+        float MidPixelLat;		/* Mid Pixel Latitude (millionths degrees)   */
+        float LstPixelLat;		/* Last Pixel Latitude (millionths degrees)  */
+        float FstPixelLong;		/* First Pixel Longitude (millionths degrees)*/
+        float MidPixelLong;		/* Mid Pixel Longitude (millionths degrees)  */
+        float LstPixelLong;		/* Last Pixel Longitude (millionths degrees) */
+    } ;
+
+    /**
+     * Radar segment information
+     */
+    struct RadarSeg_t
+    {
+        /**
+         * Default constrcutor
+         */
+        RadarSeg_t()
+        {
+        }
+        /**
+         * Copy constructor
+         * @param oRS the radar segment to copy
+         */
+        RadarSeg_t(const RadarSeg_t& oRS)
+        {
+            Copy(oRS);
+        }
+
+        /**
+         * assignement operator
+         * @param oRS the radar segment to assign
+         */
+        RadarSeg_t& operator=(const RadarSeg_t& oRS)
+        {
+            Copy(oRS);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oRS the radar segment to copy
+         */
+        void Copy(const RadarSeg_t& oRS)
+        {
+            if(this == &oRS)
+            {
+                return;
+            }
+            Identifier = oRS.Identifier;	
+            Facility = oRS.Facility;	
+            Ellipsoid = oRS.Ellipsoid;	
+            EquatorialRadius = oRS.EquatorialRadius;    
+            PolarRadius = oRS.PolarRadius;		
+            IncidenceAngle = oRS.IncidenceAngle;	
+            PixelSpacing = oRS.PixelSpacing;	
+            LineSpacing = oRS.LineSpacing;		
+            ClockAngle = oRS.ClockAngle;		
+
+            NumberBlockData = oRS.NumberBlockData;	
+            NumberData = oRS.NumberData;		
+
+            Line = oRS.Line;	
+        }
+
+        std::string   Identifier; /* Product identifier */
+        std::string   Facility;	/* Processing facility */
+        std::string   Ellipsoid; /* Ellipsoid designator */
+        double EquatorialRadius; /* Equatorial radius of earth */
+        double PolarRadius; /* Polar radius of earth */
+        double IncidenceAngle; /* Incidence angle */
+        double PixelSpacing; /* Nominal pixel spacing in metre */
+        double LineSpacing; /* Nominal line spacing in metre */
+        double ClockAngle; /* Clock angle in degree */
+
+        int    NumberBlockData;	/* Number of blocks of ancillary data */
+        int  NumberData; /* Number of ancillary data */
+
+        std::vector<AncillaryData_t> Line; /* Pointer to ancillary line */
+    } ;
+
+/* -------------------------------------------------------------------- */
+/*	Structure for Satellite attitude segment.			*/
+/* -------------------------------------------------------------------- */
+#define ATT_SEG_BLK		604
+#define ATT_SEG_MAX_LINE	6000
+#define ATT_SEG_LINE_PER_BLOCK  10
+
+    /**
+     * Attitude line information
+     */
+    struct AttitudeLine_t
+    {
+        /**
+         * Default constrcutor
+         */
+        AttitudeLine_t()
+        {
+        }
+        /**
+         * Copy constructor
+         * @param oAL the attitude line to copy
+         */
+        AttitudeLine_t(const AttitudeLine_t& oAL)
+        {
+            Copy(oAL);
+        }
+
+        /**
+         * assignement operator
+         * @param oAL the attitude line to assign
+         */
+        AttitudeLine_t& operator=(const AttitudeLine_t& oAL)
+        {
+            Copy(oAL);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oAL the attitude line to copy
+         */
+        void Copy(const AttitudeLine_t& oAL)
+        {
+            if(this == &oAL)
+            {
+                return;
+            }
+            ChangeInAttitude = oAL.ChangeInAttitude;
+            ChangeEarthSatelliteDist = oAL.ChangeEarthSatelliteDist;
+        }
+
+        double ChangeInAttitude; /* Change in satellite attiutde (D22.16) */
+        double ChangeEarthSatelliteDist; /* Change in earth-satellite distance
+                                         (D22.16) */
+    } ;
+
+    /**
+     * Attitude segment information
+     */
+    struct AttitudeSeg_t
+    {
+        /**
+         * Default constrcutor
+         */
+        AttitudeSeg_t()
+        {
+        }
+        /**
+         * Copy constructor
+         * @param oAS the attitude segment to copy
+         */
+        AttitudeSeg_t(const AttitudeSeg_t& oAS)
+        {
+            Copy(oAS);
+        }
+
+        /**
+         * assignement operator
+         * @param oAS the avhrr segment to assign
+         */
+        AttitudeSeg_t& operator=(const AttitudeSeg_t& oAS)
+        {
+            Copy(oAS);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oAS the avhrr segment to copy
+         */
+        void Copy(const AttitudeSeg_t& oAS)
+        {
+            if(this == &oAS)
+            {
+                return;
+            }
+            Roll = oAS.Roll;
+            Pitch = oAS.Pitch;
+            Yaw = oAS.Yaw;
+            NumberOfLine = oAS.NumberOfLine;
+            NumberBlockData = oAS.NumberBlockData;
+            Line = oAS.Line;
+        }
+
+        double Roll; /* Roll (D22.16) */
+        double Pitch; /* Pitch (D22.16) */
+        double Yaw; /* Yaw (D22.16) */
+        int  NumberOfLine; /* No. of Lines (I22) */
+
+        int NumberBlockData; /* No. of block of data. */
+        std::vector<AttitudeLine_t> Line;
+
+    } ;
+
+/* -------------------------------------------------------------------- */
+/*	AVHRR orbit segment. Composed of 11 blocks plus extra blocks	*/
+/*	for holding per-scanline information.				*/
+/* -------------------------------------------------------------------- */
+#define AVH_SEG_BASE_NUM_BLK	11
+
+    /**
+     * Avhrr line information
+     */
+    struct AvhrrLine_t
+    {
+        /**
+         * Default constrcutor
+         */
+        AvhrrLine_t()
+        {
+        }
+        /**
+         * Copy constructor
+         * @param oAL the avhrr line to copy
+         */
+        AvhrrLine_t(const AvhrrLine_t& oAL)
+        {
+            Copy(oAL);
+        }
+
+        /**
+         * assignement operator
+         * @param oAL the avhrr line to assign
+         */
+        AvhrrLine_t& operator=(const AvhrrLine_t& oAL)
+        {
+            Copy(oAL);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oAL the avhrr line to copy
+         */
+        void Copy(const AvhrrLine_t& oAL)
+        {
+            if(this == &oAL)
+            {
+                return;
+            }
+            nScanLineNum = oAL.nScanLineNum;
+            nStartScanTimeGMTMsec = oAL.nStartScanTimeGMTMsec;
+            for(int i=0 ; i < 10 ; i++)
+                abyScanLineQuality[i] = oAL.abyScanLineQuality[i];
+            for(int i=0 ; i < 5 ; i++)
+            {
+                aabyBadBandIndicators[i][0] = oAL.aabyBadBandIndicators[i][0];
+                aabyBadBandIndicators[i][1] = oAL.aabyBadBandIndicators[i][1];
+                anSpaceScanData[i] = oAL.anSpaceScanData[i];
+            }
+            for(int i=0 ; i < 8 ; i++)
+                abySatelliteTimeCode[i] = oAL.abySatelliteTimeCode[i];
+            for(int i=0 ; i < 3 ; i++)
+            {
+                anTargetTempData[i] = oAL.anTargetTempData[i];
+                anTargetScanData[i] = oAL.anTargetScanData[i];
+            }
+        }
+
+        /* For geocoding */
+        int   nScanLineNum;
+        int   nStartScanTimeGMTMsec;
+        unsigned char abyScanLineQuality[10];
+        unsigned char aabyBadBandIndicators[5][2];
+        unsigned char abySatelliteTimeCode[8];
+
+        /* For thermal/IR calibration */
+        int   anTargetTempData[3];
+        int   anTargetScanData[3];
+        int   anSpaceScanData[5];
+
+    } ;
+
+    /**
+     * Avhrr segment information.
+     */
+    struct AvhrrSeg_t
+    {
+        /**
+         * Default constrcutor
+         */
+        AvhrrSeg_t()
+        {
+        }
+        /**
+         * Copy constructor
+         * @param oAS the avhrr segment to copy
+         */
+        AvhrrSeg_t(const AvhrrSeg_t& oAS)
+        {
+            Copy(oAS);
+        }
+
+        /**
+         * assignement operator
+         * @param oAS the avhrr segment to assign
+         */
+        AvhrrSeg_t& operator=(const AvhrrSeg_t& oAS)
+        {
+            Copy(oAS);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oAS the avhrr segment to copy
+         */
+        void Copy(const AvhrrSeg_t& oAS)
+        {
+            if(this == &oAS)
+            {
+                return;
+            }
+            szImageFormat = oAS.szImageFormat;
+            nImageXSize = oAS.nImageXSize;
+            nImageYSize = oAS.nImageYSize;
+            bIsAscending = oAS.bIsAscending;
+            bIsImageRotated = oAS.bIsImageRotated;
+            szOrbitNumber = oAS.szOrbitNumber;
+            szAscendDescendNodeFlag = oAS.szAscendDescendNodeFlag;
+            szEpochYearAndDay = oAS.szEpochYearAndDay;
+            szEpochTimeWithinDay = oAS.szEpochTimeWithinDay;
+            szTimeDiffStationSatelliteMsec = oAS.szTimeDiffStationSatelliteMsec;
+            szActualSensorScanRate = oAS.szActualSensorScanRate;
+            szIdentOfOrbitInfoSource = oAS.szIdentOfOrbitInfoSource;
+            szInternationalDesignator = oAS.szInternationalDesignator;
+            szOrbitNumAtEpoch = oAS.szOrbitNumAtEpoch;
+            szJulianDayAscendNode = oAS.szJulianDayAscendNode;
+            szEpochYear = oAS.szEpochYear;
+            szEpochMonth = oAS.szEpochMonth;
+            szEpochDay = oAS.szEpochDay;
+            szEpochHour = oAS.szEpochHour;
+            szEpochMinute = oAS.szEpochMinute;
+            szEpochSecond = oAS.szEpochSecond;
+            szPointOfAriesDegrees = oAS.szPointOfAriesDegrees;
+            szAnomalisticPeriod = oAS.szAnomalisticPeriod;
+            szNodalPeriod = oAS.szNodalPeriod;
+            szEccentricity = oAS.szEccentricity;
+            szArgumentOfPerigee = oAS.szArgumentOfPerigee;
+            szRAAN = oAS.szRAAN;
+            szInclination = oAS.szInclination;
+            szMeanAnomaly = oAS.szMeanAnomaly;
+            szSemiMajorAxis = oAS.szSemiMajorAxis;
+            nRecordSize = oAS.nRecordSize;
+            nBlockSize = oAS.nBlockSize;
+            nNumRecordsPerBlock = oAS.nNumRecordsPerBlock;
+            nNumBlocks = oAS.nNumBlocks;
+            nNumScanlineRecords = oAS.nNumScanlineRecords;
+            Line = oAS.Line;
+        }
+
+        /* Nineth Block Part 1 - General/header information */
+        std::string  szImageFormat;
+        int   nImageXSize;
+        int   nImageYSize;
+        bool bIsAscending;
+        bool bIsImageRotated;
+
+        /* Nineth Block Part 2 - Ephemeris information */
+        std::string  szOrbitNumber;
+        std::string  szAscendDescendNodeFlag;
+        std::string  szEpochYearAndDay;
+        std::string  szEpochTimeWithinDay;
+        std::string  szTimeDiffStationSatelliteMsec;
+        std::string  szActualSensorScanRate;
+        std::string  szIdentOfOrbitInfoSource;
+        std::string  szInternationalDesignator;
+        std::string  szOrbitNumAtEpoch;
+        std::string  szJulianDayAscendNode;
+        std::string  szEpochYear;
+        std::string  szEpochMonth;
+        std::string  szEpochDay;
+        std::string  szEpochHour;
+        std::string  szEpochMinute;
+        std::string  szEpochSecond;
+        std::string  szPointOfAriesDegrees;
+        std::string  szAnomalisticPeriod;
+        std::string  szNodalPeriod;
+        std::string  szEccentricity;
+        std::string  szArgumentOfPerigee;
+        std::string  szRAAN;
+        std::string  szInclination;
+        std::string  szMeanAnomaly;
+        std::string  szSemiMajorAxis;
+
+        /* 10th Block - Empty, reserved for future use */
+
+        /* 11th Block - Needed for indexing 12th block onwards */
+        int   nRecordSize;
+        int   nBlockSize;
+        int   nNumRecordsPerBlock;
+        int   nNumBlocks;
+        int   nNumScanlineRecords;
+
+        /* 12th Block and onwards - Per-scanline records */
+        std::vector<AvhrrLine_t> Line;
+
+    } ;
+
+    /**
+     * Possible orbit types.
+     */
+    typedef enum 
+    { 
+        OrbNone, 
+        OrbAttitude, 
+        OrbLatLong, 
+        OrbAvhrr 
+    } OrbitType;
+
+    /**
+     * Ephemeris segment structure
+     */
+    struct EphemerisSeg_t
+    {
+        /**
+         * Default constrcutor
+         */
+        EphemerisSeg_t()
+        {
+            AttitudeSeg = NULL;
+            RadarSeg = NULL;
+            AvhrrSeg = NULL;
+        }
+
+        /**
+         * Destructor
+         */
+        ~EphemerisSeg_t()
+        {
+            delete AttitudeSeg;
+            delete RadarSeg;
+            delete AvhrrSeg;
+        }
+
+        /**
+         * Copy constructor
+         * @param oES the ephemeris segment to copy
+         */
+        EphemerisSeg_t(const EphemerisSeg_t& oES)
+        {
+            AttitudeSeg = NULL;
+            RadarSeg = NULL;
+            AvhrrSeg = NULL;
+            Copy(oES);
+        }
+
+        /**
+         * assignement operator
+         * @param oES the ephemeris segment to assign
+         */
+        EphemerisSeg_t& operator=(const EphemerisSeg_t& oES)
+        {
+            Copy(oES);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oES the ephemeris segment to copy
+         */
+        void Copy(const EphemerisSeg_t& oES)
+        {
+            if(this == &oES)
+            {
+                return;
+            }
+            delete AttitudeSeg;
+            delete RadarSeg;
+            delete AvhrrSeg;
+            AttitudeSeg = NULL;
+            RadarSeg = NULL;
+            AvhrrSeg = NULL;
+            if(oES.AttitudeSeg)
+                AttitudeSeg = new AttitudeSeg_t(*oES.AttitudeSeg);
+            if(oES.RadarSeg)
+                RadarSeg = new RadarSeg_t(*oES.RadarSeg);
+            if(oES.AvhrrSeg)
+                AvhrrSeg = new AvhrrSeg_t(*oES.AvhrrSeg);
+
+            for(int i =0 ; i <39 ; i++)
+                SPCoeff1B[i] = oES.SPCoeff1B[i];
+            for(int i =0 ; i <4 ; i++)
+                SPCoeffSg[i] = oES.SPCoeffSg[i];
+
+            SatelliteDesc = oES.SatelliteDesc;
+            SceneID = oES.SceneID;
+            SatelliteSensor = oES.SatelliteSensor;
+            SensorNo = oES.SensorNo;
+            DateImageTaken = oES.DateImageTaken;
+            SupSegExist = oES.SupSegExist;
+            FieldOfView = oES.FieldOfView;
+            ViewAngle = oES.ViewAngle;
+            NumColCentre = oES.NumColCentre;
+            RadialSpeed = oES.RadialSpeed;
+            Eccentricity = oES.Eccentricity;
+            Height = oES.Height;
+            Inclination = oES.Inclination;
+            TimeInterval = oES.TimeInterval;
+            NumLineCentre = oES.NumLineCentre;
+            LongCentre = oES.LongCentre;
+            AngularSpd = oES.AngularSpd;
+            AscNodeLong = oES.AscNodeLong;
+            ArgPerigee = oES.ArgPerigee;
+            LatCentre = oES.LatCentre;
+            EarthSatelliteDist = oES.EarthSatelliteDist;
+            NominalPitch = oES.NominalPitch;
+            TimeAtCentre = oES.TimeAtCentre;
+            SatelliteArg = oES.SatelliteArg;
+            XCentre = oES.XCentre;
+            YCentre = oES.YCentre;
+            UtmYCentre = oES.UtmYCentre;
+            UtmXCentre = oES.UtmXCentre;
+            PixelRes = oES.PixelRes;
+            LineRes = oES.LineRes;
+            CornerAvail = oES.CornerAvail;
+            MapUnit = oES.MapUnit;
+            XUL = oES.XUL;
+            YUL = oES.YUL;
+            XUR = oES.XUR;
+            YUR = oES.YUR;
+            XLR = oES.XLR;
+            YLR = oES.YLR;
+            XLL = oES.XLL;
+            YLL = oES.YLL;
+            UtmYUL = oES.UtmYUL;
+            UtmXUL = oES.UtmXUL;
+            UtmYUR = oES.UtmYUR;
+            UtmXUR = oES.UtmXUR;
+            UtmYLR = oES.UtmYLR;
+            UtmXLR = oES.UtmXLR;
+            UtmYLL = oES.UtmYLL;
+            UtmXLL = oES.UtmXLL;
+            LatCentreDeg = oES.LatCentreDeg;
+            LongCentreDeg = oES.LongCentreDeg;
+            LatUL = oES.LatUL;
+            LongUL = oES.LongUL;
+            LatUR = oES.LatUR;
+            LongUR = oES.LongUR;
+            LatLR = oES.LatLR;
+            LongLR = oES.LongLR;
+            LatLL = oES.LatLL;
+            LongLL = oES.LongLL;
+            HtCentre = oES.HtCentre;
+            HtUL = oES.HtUL;
+            HtUR = oES.HtUR;
+            HtLR = oES.HtLR;
+            HtLL = oES.HtLL;
+            ImageRecordLength = oES.ImageRecordLength;
+            NumberImageLine = oES.NumberImageLine;
+            NumberBytePerPixel = oES.NumberBytePerPixel;
+            NumberSamplePerLine = oES.NumberSamplePerLine;
+            NumberPrefixBytes = oES.NumberPrefixBytes;
+            NumberSuffixBytes = oES.NumberSuffixBytes;
+            SPNCoeff = oES.SPNCoeff;
+            bDescending = oES.bDescending;
+            Type = oES.Type;
+        }
+
+        /// Satellite description
+        std::string SatelliteDesc;
+        /// Scene ID
+        std::string SceneID;
+
+        /// Satellite sensor
+        std::string SatelliteSensor;
+        /// Satellite sensor no.
+        std::string SensorNo;		
+        /// Date of image taken
+        std::string DateImageTaken;
+        /// Flag to indicate supplemental segment
+        bool SupSegExist;
+        /// Scanner field of view (ALPHA)
+        double FieldOfView;
+        /// Viewing angle (BETA)
+        double ViewAngle;
+        /// Number of column at center (C0)
+        double NumColCentre;
+        /// Radial speed (DELIRO)
+        double RadialSpeed;
+        /// Eccentricity (ES)
+        double Eccentricity;
+        /// Height (H0)
+        double Height;
+        /// Inclination (I)
+        double Inclination;
+        /// Time interval (K)
+        double TimeInterval;
+        /// Number of line at center (L0)
+        double NumLineCentre;
+        /// Longitude of center (LAMBDA)
+        double LongCentre;
+        /// Angular speed (N)
+        double AngularSpd;
+        /// Ascending node Longitude (OMEGA-MAJ)
+        double AscNodeLong; 
+        /// Argument Perigee (OMEGA-MIN)
+        double ArgPerigee;
+        /// Latitude of center (PHI)
+        double LatCentre;
+        /// Earth Satellite distance (RHO)
+        double EarthSatelliteDist;
+        /// Nominal pitch (T)
+        double NominalPitch;
+        /// Time at centre (T0)
+        double TimeAtCentre;
+        /// Satellite argument (WP)
+        double SatelliteArg;
+
+        /// Scene center pixel coordinate
+        double XCentre;
+        /// Scene center line coordinate
+        double YCentre;
+        /// Scene centre UTM northing
+        double UtmYCentre;
+        /// Scene centre UTM easting
+        double UtmXCentre;
+        /// Pixel resolution in x direction
+        double PixelRes;
+        /// Pixel resolution in y direction
+        double LineRes;
+        /// Flag to tell corner coordinate available
+        bool CornerAvail;
+        /// Map units
+        std::string MapUnit;
+        /// Pixel coordinate of upper left corner
+        double XUL;
+        /// Line coordinate of upper left corner
+        double YUL;
+        /// Pixel coordinate of upper right corner
+        double XUR;
+        /// Line coordinate of upper right corner
+        double YUR;
+        /// Pixel coordinate of lower right corner
+        double XLR;
+        /// Line coordinate of lower right corner
+        double YLR;
+        /// Pixel coordinate of lower left corner
+        double XLL;
+        /// Line coordinate of lower left corner
+        double YLL;
+        /// UTM Northing of upper left corner
+        double UtmYUL;
+        /// UTM Easting of upper left corner
+        double UtmXUL;
+        /// UTM Northing of upper right corner
+        double UtmYUR;
+        /// UTM Easting of upper right corner
+        double UtmXUR;
+        /// UTM Northing of lower right corner
+        double UtmYLR;
+        /// UTM Easting of lower right corner
+        double UtmXLR;
+        /// Utm Northing of lower left corner
+        double UtmYLL;
+        /// Utm Easting of lower left corner
+        double UtmXLL;
+
+        /// Scene centre latitude (deg)
+        double LatCentreDeg;
+        /// Scene centre longitude (deg)
+        double LongCentreDeg;
+        /// Upper left latitude (deg)
+        double LatUL;
+        /// Upper left longitude (deg)
+        double LongUL;
+        /// Upper right latitude (deg)
+        double LatUR;
+        /// Upper right longitude (deg)
+        double LongUR;
+        /// Lower right latitude (deg)
+        double LatLR;
+        /// Lower right longitude (deg)
+        double LongLR;
+        /// Lower left latitude (deg)
+        double LatLL;
+        /// Lower left longitude (deg)
+        double LongLL;
+        /// Centre Height (m)
+        double HtCentre;
+        /// UL Height (m)
+        double HtUL;
+        /// UR Height (m)
+        double HtUR;
+        /// LR Height (m)
+        double HtLR;
+        /// LL Height (m)
+        double HtLL;
+
+        /// SPOT 1B coefficients
+        double SPCoeff1B[39];
+        /// SPOT 1B segment coefficients
+        int    SPCoeffSg[4];
+
+        /// Image record length
+        int	   ImageRecordLength;
+        /// Number of image line
+        int	   NumberImageLine;
+        /// Number of bytes per pixel
+        int	   NumberBytePerPixel;
+        /// Number of samples per line
+        int	   NumberSamplePerLine;
+        /// Number of prefix bytes
+        int    NumberPrefixBytes;
+        /// Number of suffix bytes
+        int	   NumberSuffixBytes;
+        /// Number of coefficients for SPOT 1B
+        int	   SPNCoeff;
+
+        /// Flag to indicate ascending or descending
+        bool  bDescending;
+
+        /// Orbit type: None, LatLong, Attitude, Avhrr
+        OrbitType   Type;
+        AttitudeSeg_t *AttitudeSeg;
+        RadarSeg_t    *RadarSeg;
+        AvhrrSeg_t    *AvhrrSeg;
+    };
+
+    /**
+     * List of sensor type
+     */
+    typedef enum {PLA_1, MLA_1, PLA_2, MLA_2, PLA_3, MLA_3, PLA_4, MLA_4,
+		ASTER, SAR, LISS_1, LISS_2, LISS_3, LISS_L3, LISS_L3_L2,
+		LISS_L4, LISS_L4_L2, LISS_P3, LISS_P3_L2, LISS_W3, LISS_W3_L2,
+		LISS_AWF, LISS_AWF_L2, LISS_M3, EOC, IRS_1, RSAT_FIN, 
+		RSAT_STD, ERS_1, ERS_2, TM, ETM, IKO_PAN, IKO_MULTI, 
+		ORBVIEW_PAN, ORBVIEW_MULTI, OV3_PAN_BASIC, OV3_PAN_GEO, 
+		OV3_MULTI_BASIC, OV3_MULTI_GEO, OV5_PAN_BASIC, OV5_PAN_GEO, 
+		OV5_MULTI_BASIC, OV5_MULTI_GEO, QBIRD_PAN, QBIRD_PAN_STD, 
+		QBIRD_PAN_STH, QBIRD_MULTI, QBIRD_MULTI_STD, QBIRD_MULTI_STH, 
+		FORMOSAT_PAN, FORMOSAT_MULTI, FORMOSAT_PAN_L2,
+		FORMOSAT_MULTIL2, SPOT5_PAN_2_5, SPOT5_PAN_5, SPOT5_HRS,
+		SPOT5_MULTI, MERIS_FR, MERIS_RR, MERIS_LR, ASAR, EROS, 
+		MODIS_250, MODIS_500, MODIS_1000, CBERS_HRC, CBERS_HRC_L2,
+		CBERS_CCD, CBERS_CCD_L2, CBERS_IRM_80, CBERS_IRM_80_L2, 
+	        CBERS_IRM_160, CBERS_IRM_160_L2, CBERS_WFI, CBERS_WFI_L2, 
+	 	CARTOSAT1_L1, CARTOSAT1_L2, ALOS_PRISM_L1, ALOS_PRISM_L2, 
+		ALOS_AVNIR_L1, ALOS_AVNIR_L2, PALSAR, DMC_1R, DMC_1T, 
+		KOMPSAT2_PAN, KOMPSAT2_MULTI, TERRASAR, WVIEW_PAN,
+		WVIEW_PAN_STD, WVIEW_MULTI, WVIEW_MULTI_STD,
+		RAPIDEYE_L1B, THEOS_PAN_L1, THEOS_PAN_L2,
+		THEOS_MS_L1, THEOS_MS_L2, 
+		GOSAT_500_L1, GOSAT_500_L2, GOSAT_1500_L1, GOSAT_1500_L2, 
+		HJ_CCD_1A, HJ_CCD_1B, NEW, AVHRR} TypeDeCapteur;
+}
+
+#endif // __INCLUDE_PCIDSK_ORBIT_INFORMATION_H
diff --git a/frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h b/frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h
new file mode 100644
index 0000000..360e9c7
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/pcidsksegmentbuilder.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ * Purpose: Interface. Builder class for constructing a related PCIDSK segment
+ *          class.
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
+#define __INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
+
+namespace PCIDSK
+{
+    class PCIDSKSegment;
+    class PCIDSKFile;
+
+    /**
+     * PCIDSK Abstract Builder class. Given a segment pointer, constructs
+     * an instance of a given PCIDSKSegment implementor. Typically an instance
+     * of this will be registered with the PCIDSK Segment Factory.
+     */
+    struct IPCIDSKSegmentBuilder
+    {
+        // TODO: Determine required arguments for a segment to be constructed
+        virtual PCIDSKSegment *BuildSegment(PCIDSKFile *poFile, 
+            unsigned int nSegmentID, const char *psSegmentPointer) = 0;
+        
+        // Get a list of segments that this builder can handle
+        virtual std::vector<std::string> GetSupportedSegments(void) const = 0;
+        
+        // Get a copyright string
+        virtual std::string GetVendorString(void) const = 0;
+        
+        // Get a name string
+        virtual std::string GetSegmentBuilderName(void) const = 0;
+        
+        // Virtual destructor
+        virtual ~IPCIDSKSegmentBuilder() {}
+    };
+
+}; // end namespace PCIDSK
+
+#endif // __INCLUDE_SEGMENT_PCIDSKSEGMENTBUILDER_H
diff --git a/frmts/pcidsk/sdk/segment/sysblockmap.cpp b/frmts/pcidsk/sdk/segment/sysblockmap.cpp
index ee2b3bc..9fa1b43 100644
--- a/frmts/pcidsk/sdk/segment/sysblockmap.cpp
+++ b/frmts/pcidsk/sdk/segment/sysblockmap.cpp
@@ -42,6 +42,7 @@
 #include <cassert>
 #include <vector>
 #include <cstring>
+#include <cstdlib>
 
 using namespace PCIDSK;
 
@@ -522,19 +523,29 @@ int SysBlockMap::GetNextBlockMapEntry( int bm_index,
 /*      Otherwise we read from disk and hope the io level buffering     */
 /*      is pretty good.                                                 */
 /* -------------------------------------------------------------------- */
-    PCIDSKBuffer bm_entry( 28 );
+    char bm_entry[29];
 
     if( full_loaded )
     {
-        memcpy( bm_entry.buffer, blockmap_data.buffer + bm_index * 28, 28 );
+        memcpy( bm_entry, blockmap_data.buffer + bm_index * 28, 28 );
     }
     else
     {
-        ReadFromFile( bm_entry.buffer, bm_index * 28 + 512, 28 );
+        ReadFromFile( bm_entry, bm_index * 28 + 512, 28 );
     }
     
-    segment = (uint16) bm_entry.GetInt( 0, 4 );
-    block_in_segment = bm_entry.GetInt( 4, 8 );
+/* -------------------------------------------------------------------- */
+/*      Parse the values as efficiently as we can.                      */
+/* -------------------------------------------------------------------- */
+    bm_entry[28] = '\0';
+
+    int next_block = atoi( bm_entry+20 );
+
+    bm_entry[12] = '\0';
+    block_in_segment = atoi(bm_entry+4);
+
+    bm_entry[4] = '\0';
+    segment = atoi(bm_entry);
     
-    return bm_entry.GetInt( 20, 8 );
+    return next_block;
 }
diff --git a/frmts/pcidsk/sdk/segment/toutinstructures.h b/frmts/pcidsk/sdk/segment/toutinstructures.h
new file mode 100644
index 0000000..35778a9
--- /dev/null
+++ b/frmts/pcidsk/sdk/segment/toutinstructures.h
@@ -0,0 +1,206 @@
+/******************************************************************************
+ *
+ * Purpose: Support for storing and manipulating Toutin information
+ * 
+ ******************************************************************************
+ * Copyright (c) 2009
+ * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
+ *
+ * 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 __INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
+#define __INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
+
+#include "segment/orbitstructures.h"
+
+namespace PCIDSK
+{
+/* -------------------------------------------------------------------- */
+/*      SRITInfo_t - Satellite Model structure.                         */
+/* -------------------------------------------------------------------- */
+#define AP_MDL   1
+#define SRIT_MDL 2
+#define RF_MDL   6
+#define RTCS_MDL 7
+#define ADS_MDL  9
+#define SRITModele 0
+#define SRITModele1A 1
+#define SRITModele1B 2
+#define SRITModeleSAR 3
+#define SRITModele1AHR 4
+#define SRITModeleEros 5
+
+#define MAX_SPOT_LINES 30000
+
+    /**
+     * the SRITInfo_t struct contains all information
+     * for the Toutin Math Model.
+     */
+    struct SRITInfo_t
+    {
+        /**
+         * default constructor
+         */
+        SRITInfo_t()
+        {
+            OrbitPtr = NULL;
+        }
+        /**
+         * destructor
+         */
+        ~SRITInfo_t()
+        {
+            delete OrbitPtr;
+        }
+
+        /**
+         * Copy constructor.
+         * @param oSI the SRITInfo_t to copy
+         */
+        SRITInfo_t(const SRITInfo_t& oSI)
+        {
+            OrbitPtr = NULL;
+            Copy(oSI);
+        }
+
+        /**
+         * Assignment operator
+         * @param oSI the SRITInfo_t to assign
+         */
+        SRITInfo_t& operator=(const SRITInfo_t& oSI)
+        {
+            Copy(oSI);
+            return *this;
+        }
+
+        /**
+         * Copy function
+         * @param oSI the SRITInfo_t to copy
+         */
+        void Copy(const SRITInfo_t& oSI)
+        {
+            if(this == &oSI)
+            {
+                return;
+            }
+            delete OrbitPtr;
+            OrbitPtr = NULL;
+            if(oSI.OrbitPtr)
+            {
+                OrbitPtr = new EphemerisSeg_t(*oSI.OrbitPtr);
+            }
+
+            for(int i=0 ; i<256 ; i++)
+            {
+                nGCPIds[i] = oSI.nGCPIds[i];
+                nPixel[i] = oSI.nPixel[i];
+                nLine[i] = oSI.nLine[i];
+                dfElev[i] = oSI.dfElev[i];
+            }
+
+            N0x2 = oSI.N0x2;
+            aa = oSI.aa;
+            SmALPHA = oSI.SmALPHA;
+            bb = oSI.bb;
+            C0 = oSI.C0;
+            cc = oSI.cc;
+            COS_KHI = oSI.COS_KHI;
+            DELTA_GAMMA = oSI.DELTA_GAMMA;
+            GAMMA = oSI.GAMMA;
+            K_1 = oSI.K_1;
+            L0 = oSI.L0;
+            P = oSI.P;
+            Q = oSI.Q;
+            TAU = oSI.TAU;
+            THETA = oSI.THETA;
+            THETA_SEC = oSI.THETA_SEC;
+            X0 = oSI.X0;
+            Y0 = oSI.Y0;
+            delh = oSI.delh;
+            COEF_Y2 = oSI.COEF_Y2;
+            delT = oSI.delT;
+            delL = oSI.delL;
+            delTau = oSI.delTau;
+            nDownSample = oSI.nDownSample;
+            nGCPCount = oSI.nGCPCount;
+            nEphemerisSegNo = oSI.nEphemerisSegNo;
+            nAttitudeFlag = oSI.nAttitudeFlag;
+            utmunit = oSI.utmunit;
+            GCPUnit = oSI.GCPUnit;
+            GCPMeanHtFlag = oSI.GCPMeanHtFlag;
+            dfGCPMeanHt = oSI.dfGCPMeanHt;
+            dfGCPMinHt = oSI.dfGCPMinHt;
+            dfGCPMaxHt = oSI.dfGCPMaxHt;
+            Qdeltar = oSI.Qdeltar;
+            Hdeltat = oSI.Hdeltat;
+            Sensor = oSI.Sensor;
+            nSensor = oSI.nSensor;
+            nModel = oSI.nModel;
+            RawToGeo = oSI.RawToGeo;
+            oProjectionInfo = oSI.oProjectionInfo;
+        }
+
+        double N0x2;
+        double aa;
+        double SmALPHA;
+        double bb;
+        double C0;
+        double cc;
+        double COS_KHI;
+        double DELTA_GAMMA;
+        double GAMMA;
+        double K_1;
+        double L0;
+        double P;
+        double Q;
+        double TAU;
+        double THETA;
+        double THETA_SEC;
+        double X0;
+        double Y0;
+        double delh;
+        double COEF_Y2;
+        double delT;
+        double delL;
+        double delTau;
+        int    nDownSample;
+        int    nGCPCount;
+        int    nEphemerisSegNo;
+        int    nAttitudeFlag;
+        std::string   utmunit;
+        std::string   GCPUnit;
+        char   GCPMeanHtFlag;
+        double dfGCPMeanHt;
+        double dfGCPMinHt;
+        double dfGCPMaxHt;
+        int    nGCPIds[256];
+        int    nPixel[256],nLine[256];
+        double dfElev[256];
+        std::vector<double> Qdeltar;
+        std::vector<double> Hdeltat;
+        std::string   Sensor;
+        int    nSensor;
+        int    nModel;
+        EphemerisSeg_t *OrbitPtr;
+        bool  RawToGeo;
+        std::string oProjectionInfo;
+    } ;
+}
+
+#endif // __INCLUDE_PCIDSK_TOUTIN_INFORMATION_H
diff --git a/frmts/pcidsk/vsi_pcidsk_io.cpp b/frmts/pcidsk/vsi_pcidsk_io.cpp
index 6228537..5b02d5f 100644
--- a/frmts/pcidsk/vsi_pcidsk_io.cpp
+++ b/frmts/pcidsk/vsi_pcidsk_io.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vsi_pcidsk_io.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: vsi_pcidsk_io.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  PCIDSK Database File
  * Purpose:  PCIDSK SDK compatiable io interface built on VSI.
@@ -31,7 +31,7 @@
 #include "cpl_multiproc.h"
 #include "pcidsk.h"
 
-CPL_CVSID("$Id: vsi_pcidsk_io.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: vsi_pcidsk_io.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 using namespace PCIDSK;
 
@@ -127,7 +127,7 @@ uint64 VSI_IOInterface::Read( void *buffer, uint64 size, uint64 nmemb,
 
     errno = 0;
 
-    uint64 result = VSIFReadL( buffer, size, nmemb, fp );
+    uint64 result = VSIFReadL( buffer, (size_t) size, (size_t) nmemb, fp );
 
     if( errno != 0 && result == 0 && nmemb != 0 )
         ThrowPCIDSKException( "Read(%d): %s", 
@@ -149,7 +149,7 @@ uint64 VSI_IOInterface::Write( const void *buffer, uint64 size, uint64 nmemb,
 
     errno = 0;
 
-    uint64 result = VSIFWriteL( buffer, size, nmemb, fp );
+    uint64 result = VSIFWriteL( buffer, (size_t) size, (size_t) nmemb, fp );
 
     if( errno != 0 && result == 0 && nmemb != 0 )
         ThrowPCIDSKException( "Write(%d): %s", 
diff --git a/frmts/pcraster/libcsf/legend.c b/frmts/pcraster/libcsf/legend.c
index 47f7884..b9fc472 100644
--- a/frmts/pcraster/libcsf/legend.c
+++ b/frmts/pcraster/libcsf/legend.c
@@ -13,7 +13,7 @@ static int NrLegendEntries(MAP *m)
 	int size = CsfAttributeSize(m, ATTR_ID_LEGEND_V2);
 	if (size == 0)
 	{
-		if ( (size = -CsfAttributeSize(m, ATTR_ID_LEGEND_V1)) != 0 )
+		if ( (size = -1 * CsfAttributeSize(m, ATTR_ID_LEGEND_V1)) != 0 )
 			size -= CSF_LEGEND_ENTRY_SIZE;
 	}
 	return size/CSF_LEGEND_ENTRY_SIZE;
diff --git a/frmts/pcraster/libcsf/makefile.vc b/frmts/pcraster/libcsf/makefile.vc
index 87deb44..0656d55 100644
--- a/frmts/pcraster/libcsf/makefile.vc
+++ b/frmts/pcraster/libcsf/makefile.vc
@@ -1,5 +1,5 @@
 GDAL_ROOT	=	..\..\..
-EXTRAFLAGS=-DUSE_IN_GDAL
+EXTRAFLAGS=-DUSE_IN_GDAL $(SOFTWARNFLAGS)
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
 
diff --git a/frmts/pcraster/pcrasterdataset.cpp b/frmts/pcraster/pcrasterdataset.cpp
index 412562c..f88a0fb 100644
--- a/frmts/pcraster/pcrasterdataset.cpp
+++ b/frmts/pcraster/pcrasterdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterdataset.cpp 16442 2009-03-01 16:46:45Z rouault $
+ * $Id: pcrasterdataset.cpp 22609 2011-06-28 21:01:48Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster CSF 2.0 raster file driver
@@ -30,7 +30,7 @@
 #include "gdal_pam.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: pcrasterdataset.cpp 16442 2009-03-01 16:46:45Z rouault $");
+CPL_CVSID("$Id: pcrasterdataset.cpp 22609 2011-06-28 21:01:48Z rouault $");
 
 #ifndef INCLUDED_PCRASTERDATASET
 #include "pcrasterdataset.h"
@@ -245,9 +245,10 @@ GDALDataset* PCRasterDataset::createCopy(
     // Get row from source.
     if(raster->RasterIO(GF_Read, 0, row, nrCols, 1, buffer, nrCols, 1,
          raster->GetRasterDataType(), 0, 0) != CE_None) {
-      free(buffer);
       CPLError(CE_Failure, CPLE_FileIO,
          "PCRaster driver: Error reading from source raster");
+      errorCode = CE_Failure;
+      break;
     }
 
     // Upon reading values are converted to the
@@ -267,9 +268,10 @@ GDALDataset* PCRasterDataset::createCopy(
     RputRow(map, row, buffer);
 
     if(!progress((row + 1) / (static_cast<double>(nrRows)), 0, progressData)) {
-      free(buffer);
       CPLError(CE_Failure, CPLE_UserInterrupt,
          "PCRaster driver: User terminated CreateCopy()");
+      errorCode = CE_Failure;
+      break;
     }
   }
 
diff --git a/frmts/pdf/GNUmakefile b/frmts/pdf/GNUmakefile
index ef7b4f2..f7678e1 100644
--- a/frmts/pdf/GNUmakefile
+++ b/frmts/pdf/GNUmakefile
@@ -1,8 +1,12 @@
 
-OBJ	=	pdfdataset.o pdfio.o
+OBJ	=	pdfdataset.o pdfio.o pdfobject.o
 
 include ../../GDALmake.opt
 
+ifeq ($(HAVE_POPPLER),yes)
+CPPFLAGS +=  -DUSE_POPPLER
+endif
+
 ifeq ($(POPPLER_HAS_OPTCONTENT),yes)
 CPPFLAGS +=  -DPOPPLER_HAS_OPTCONTENT
 endif
@@ -11,7 +15,7 @@ ifeq ($(POPPLER_BASE_STREAM_HAS_TWO_ARGS),yes)
 CPPFLAGS +=  -DPOPPLER_BASE_STREAM_HAS_TWO_ARGS
 endif
 
-CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(POPPLER_INC)
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(POPPLER_INC) $(PODOFO_INC)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/pdf/frmt_pdf.html b/frmts/pdf/frmt_pdf.html
index 0e54ad3..55edb5d 100644
--- a/frmts/pdf/frmt_pdf.html
+++ b/frmts/pdf/frmt_pdf.html
@@ -12,10 +12,17 @@
 GDAL supports reading Geospatial PDF documents, by extracting georeferencing information and rasterizing the data.
 Non-geospatial PDF documents will also be recognized by the driver.
 <p>
-GDAL must be compiled with libpoppler support, and libpoppler itself must have been configured with
+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.16.0.
+Successfully tested versions are poppler >= 0.12.X and <= 0.18.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
+getting the imagery, the pdftoppm utility that comes with the poppler distribution must be available in the system PATH.
+A temporary file will be generated in a directory determined by the following configuration options : CPL_TMPDIR,
+TMPDIR or TEMP (in that order). If none are defined, the current directory will be used.
+Successfully tested versions are libpodofo 0.8.4 and 0.9.1.
 <p>
 The driver supports reading georeferencing encoded in either of the 2 current existing ways : according to the OGC
 encoding best practice, or according to the Adobe Supplement to ISO 32000.
@@ -28,6 +35,9 @@ Multipage documents are exposed as subdatasets, one subdataset par page of the d
 The neatline (for OGC best practice) or the bounding box (Adobe style) will be reported as a NEATLINE metadata item,
 so that it can be later used as a cutline for the warping algorithm.
 <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>Restrictions</h2>
 
diff --git a/frmts/pdf/makefile.vc b/frmts/pdf/makefile.vc
index 3474ea6..d4dab14 100644
--- a/frmts/pdf/makefile.vc
+++ b/frmts/pdf/makefile.vc
@@ -1,11 +1,12 @@
 
-OBJ	=	pdfdataset.obj pdfio.obj
+OBJ	=	pdfdataset.obj pdfio.obj pdfobject.obj
 
 GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = $(POPPLER_CFLAGS) $(POPPLER_HAS_OPTCONTENT_FLAGS) $(POPPLER_BASE_STREAM_HAS_TWO_ARGS_FLAGS)
+!IFDEF POPPLER_ENABLED
+EXTRAFLAGS = $(POPPLER_CFLAGS) $(POPPLER_HAS_OPTCONTENT_FLAGS) $(POPPLER_BASE_STREAM_HAS_TWO_ARGS_FLAGS) -DUSE_POPPLER
 
 !IFDEF POPPLER_HAS_OPTCONTENT
 POPPLER_HAS_OPTCONTENT_FLAGS = -DPOPPLER_HAS_OPTCONTENT
@@ -15,6 +16,12 @@ POPPLER_HAS_OPTCONTENT_FLAGS = -DPOPPLER_HAS_OPTCONTENT
 POPPLER_BASE_STREAM_HAS_TWO_ARGS_FLAGS = -DPOPPLER_BASE_STREAM_HAS_TWO_ARGS
 !ENDIF
 
+!ELSE
+
+EXTRAFLAGS = $(PODOFO_CFLAGS) 
+
+!ENDIF
+
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
 
diff --git a/frmts/pdf/pdfdataset.cpp b/frmts/pdf/pdfdataset.cpp
index 9b79e48..d498f42 100644
--- a/frmts/pdf/pdfdataset.cpp
+++ b/frmts/pdf/pdfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfdataset.cpp 21379 2011-01-02 22:05:26Z rouault $
+ * $Id: pdfdataset.cpp 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -36,40 +36,22 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 #include "ogr_geometry.h"
-#include "pdfio.h"
-
-/* begin of poppler xpdf includes */
-#include <poppler/Object.h>
-
-#define private public /* Ugly! Page::pageObj is private but we need it... */
-#include <poppler/Page.h>
-#undef private
-
-#include <poppler/Dict.h>
 
-#define private public /* Ugly! Catalog::optContent is private but we need it... */
-#include <poppler/Catalog.h>
-#undef private
-
-#define private public  /* Ugly! PDFDoc::str is private but we need it... */
-#include <poppler/PDFDoc.h>
-#undef private
+#ifdef USE_POPPLER
+#include "pdfio.h"
+#endif
 
-#include <poppler/splash/SplashBitmap.h>
-#include <poppler/splash/Splash.h>
-#include <poppler/SplashOutputDev.h>
-#include <poppler/GlobalParams.h>
-#include <poppler/ErrorCodes.h>
-/* end of poppler xpdf includes */
+#include "pdfobject.h"
 
 /* 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 21379 2011-01-02 22:05:26Z rouault $");
+CPL_CVSID("$Id: pdfdataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
 
 CPL_C_START
 void    GDALRegister_PDF(void);
 CPL_C_END
 
+#ifdef USE_POPPLER
 
 /************************************************************************/
 /*                          ObjectAutoFree                              */
@@ -82,22 +64,23 @@ public:
     ~ObjectAutoFree() { free(); }
 };
 
+#endif
 
 /************************************************************************/
 /*                         Dump routines                                */
 /************************************************************************/
 
-static void DumpObject(FILE* f, Object& o, int nDepth = 0, int nDepthLimit = -1);
-static void DumpDict(FILE* f, Dict* poDict, int nDepth = 0, int nDepthLimit = -1);
-static void DumpArray(FILE* f, Array* poArray, int nDepth = 0, int nDepthLimit = -1);
-static void DumpObjectSimplified(FILE* f, Object& o);
+static void DumpObject(FILE* f, GDALPDFObject* poObj, int nDepth = 0, int nDepthLimit = -1);
+static void DumpDict(FILE* f, GDALPDFDictionary* poDict, int nDepth = 0, int nDepthLimit = -1);
+static void DumpArray(FILE* f, GDALPDFArray* poArray, int nDepth = 0, int nDepthLimit = -1);
+static void DumpObjectSimplified(FILE* f, GDALPDFObject* poObj);
 
-static void DumpArray(FILE* f, Array* poArray, int nDepth, int nDepthLimit)
+static void DumpArray(FILE* f, GDALPDFArray* poArray, int nDepth, int nDepthLimit)
 {
     if (nDepthLimit >= 0 && nDepth > nDepthLimit)
         return;
 
-    int nLength = poArray->getLength();
+    int nLength = poArray->GetLength();
     int i;
     CPLString osIndent;
     for(i=0;i<nDepth;i++)
@@ -105,45 +88,45 @@ static void DumpArray(FILE* f, Array* poArray, int nDepth, int nDepthLimit)
     for(i=0;i<nLength;i++)
     {
         fprintf(f, "%sItem[%d]:", osIndent.c_str(), i);
-        ObjectAutoFree oVal;
-        if (poArray->get(i, &oVal) != NULL)
+        GDALPDFObject* poObj = NULL;
+        if ((poObj = poArray->Get(i)) != NULL)
         {
-            if (oVal.getType() == objString ||
-                oVal.getType() == objInt ||
-                oVal.getType() == objReal ||
-                oVal.getType() == objName)
+            if (poObj->GetType() == PDFObjectType_String ||
+                poObj->GetType() == PDFObjectType_Int ||
+                poObj->GetType() == PDFObjectType_Real ||
+                poObj->GetType() == PDFObjectType_Name)
             {
                 fprintf(f, " ");
-                DumpObjectSimplified(f, oVal);
+                DumpObjectSimplified(f, poObj);
                 fprintf(f, "\n");
             }
             else
             {
                 fprintf(f, "\n");
-                DumpObject(f, oVal, nDepth+1, nDepthLimit);
+                DumpObject(f, poObj, nDepth+1, nDepthLimit);
             }
         }
     }
 }
 
-static void DumpObjectSimplified(FILE* f, Object& o)
+static void DumpObjectSimplified(FILE* f, GDALPDFObject* poObj)
 {
-    switch(o.getType())
+    switch(poObj->GetType())
     {
-        case objString:
-            fprintf(f, "%s (string)", o.getString()->getCString());
+        case PDFObjectType_String:
+            fprintf(f, "%s (string)", poObj->GetString().c_str());
             break;
 
-        case objInt:
-            fprintf(f, "%d (int)", o.getInt());
+        case PDFObjectType_Int:
+            fprintf(f, "%d (int)", poObj->GetInt());
             break;
 
-        case objReal:
-            fprintf(f, "%f (real)", o.getReal());
+        case PDFObjectType_Real:
+            fprintf(f, "%f (real)", poObj->GetReal());
             break;
 
-        case objName:
-            fprintf(f, "%s (name)", o.getName());
+        case PDFObjectType_Name:
+            fprintf(f, "%s (name)", poObj->GetName().c_str());
             break;
 
         default:
@@ -151,7 +134,7 @@ static void DumpObjectSimplified(FILE* f, Object& o)
     }
 }
 
-static void DumpObject(FILE* f, Object& o, int nDepth, int nDepthLimit)
+static void DumpObject(FILE* f, GDALPDFObject* poObj, int nDepth, int nDepthLimit)
 {
     if (nDepthLimit >= 0 && nDepth > nDepthLimit)
         return;
@@ -160,31 +143,23 @@ static void DumpObject(FILE* f, Object& o, int nDepth, int nDepthLimit)
     CPLString osIndent;
     for(i=0;i<nDepth;i++)
         osIndent += " ";
-    fprintf(f, "%sType = %s\n", osIndent.c_str(), o.getTypeName());
-    switch(o.getType())
+    fprintf(f, "%sType = %s\n", osIndent.c_str(), poObj->GetTypeName());
+    switch(poObj->GetType())
     {
-        case objArray:
-            DumpArray(f, o.getArray(), nDepth+1, nDepthLimit);
+        case PDFObjectType_Array:
+            DumpArray(f, poObj->GetArray(), nDepth+1, nDepthLimit);
             break;
 
-        case objDict:
-            DumpDict(f, o.getDict(), nDepth+1, nDepthLimit);
+        case PDFObjectType_Dictionary:
+            DumpDict(f, poObj->GetDictionary(), nDepth+1, nDepthLimit);
             break;
 
-        case objStream:
-        {
-            Dict* poDict = o.getStream()->getDict();
-            if (poDict)
-                DumpDict(f, poDict, nDepth+1, nDepthLimit);
-            break;
-        }
-
-        case objString:
-        case objInt:
-        case objReal:
-        case objName:
+        case PDFObjectType_String:
+        case PDFObjectType_Int:
+        case PDFObjectType_Real:
+        case PDFObjectType_Name:
             fprintf(f, "%s", osIndent.c_str());
-            DumpObjectSimplified(f, o);
+            DumpObjectSimplified(f, poObj);
             fprintf(f, "\n");
             break;
 
@@ -193,41 +168,43 @@ static void DumpObject(FILE* f, Object& o, int nDepth, int nDepthLimit)
     }
 }
 
-static void DumpDict(FILE* f, Dict* poDict, int nDepth, int nDepthLimit)
+static void DumpDict(FILE* f, GDALPDFDictionary* poDict, int nDepth, int nDepthLimit)
 {
     if (nDepthLimit >= 0 && nDepth > nDepthLimit)
         return;
 
-    int nLength = poDict->getLength();
+    std::map<CPLString, GDALPDFObject*>& oMap = poDict->GetValues();
+    std::map<CPLString, GDALPDFObject*>::iterator oIter = oMap.begin();
+    std::map<CPLString, GDALPDFObject*>::iterator oEnd = oMap.end();
     int i;
     CPLString osIndent;
     for(i=0;i<nDepth;i++)
         osIndent += " ";
-    for(i=0;i<nLength;i++)
+    for(i=0;oIter != oEnd;++oIter, i++)
     {
-        char* pszKey = poDict->getKey(i);
+        const char* pszKey = oIter->first.c_str();
         fprintf(f, "%sItem[%d] : %s", osIndent.c_str(), i, pszKey);
         if (strcmp(pszKey, "Parent") == 0)
         {
             fprintf(f, "\n");
             continue;
         }
-        ObjectAutoFree oVal;
-        if (poDict->getVal(i, &oVal) != NULL)
+        GDALPDFObject* poObj = oIter->second;
+        if (poObj != NULL)
         {
-            if (oVal.getType() == objString ||
-                oVal.getType() == objInt ||
-                oVal.getType() == objReal ||
-                oVal.getType() == objName)
+            if (poObj->GetType() == PDFObjectType_String ||
+                poObj->GetType() == PDFObjectType_Int ||
+                poObj->GetType() == PDFObjectType_Real ||
+                poObj->GetType() == PDFObjectType_Name)
             {
                 fprintf(f, " = ");
-                DumpObjectSimplified(f, oVal);
+                DumpObjectSimplified(f, poObj);
                 fprintf(f, "\n");
             }
             else
             {
                 fprintf(f, "\n");
-                DumpObject(f, oVal, nDepth+1, nDepthLimit);
+                DumpObject(f, poObj, nDepth+1, nDepthLimit);
             }
         }
     }
@@ -245,20 +222,24 @@ class PDFRasterBand;
 class PDFDataset : public GDALPamDataset
 {
     friend class PDFRasterBand;
+    CPLString    osFilename;
+    CPLString    osUserPwd;
     char        *pszWKT;
     double       dfDPI;
     double       adfCTM[6];
     double       adfGeoTransform[6];
     int          bGeoTransformValid;
+#ifdef USE_POPPLER
     PDFDoc*      poDoc;
+#endif
     int          iPage;
 
     double       dfMaxArea;
-    int          ParseLGIDictObject(Object& oLGIDict);
-    int          ParseLGIDictDictFirstPass(Dict* poLGIDict, int* pbIsLargestArea = NULL);
-    int          ParseLGIDictDictSecondPass(Dict* poLGIDict);
-    int          ParseProjDict(Dict* poProjDict);
-    int          ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHeight);
+    int          ParseLGIDictObject(GDALPDFObject* poLGIDict);
+    int          ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict, int* pbIsLargestArea = NULL);
+    int          ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict);
+    int          ParseProjDict(GDALPDFDictionary* poProjDict);
+    int          ParseVP(GDALPDFObject* poVP, double dfMediaBoxWidth, double dfMediaBoxHeight);
 
     int          bTried;
     GByte       *pabyData;
@@ -329,7 +310,6 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 {
     PDFDataset *poGDS = (PDFDataset *) poDS;
-
     if (poGDS->bTried == FALSE)
     {
         poGDS->bTried = TRUE;
@@ -337,6 +317,8 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         if (poGDS->pabyData == NULL)
             return CE_Failure;
 
+#ifdef USE_POPPLER
+
         /* poppler global variable */
         if (globalParams == NULL)
             globalParams = new GlobalParams();
@@ -406,6 +388,49 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             }
         }
         delete poSplashOut;
+
+#else
+        memset(poGDS->pabyData, 0, ((size_t)3) * nRasterXSize * nRasterYSize);
+
+        CPLString osTmpFilenamePrefix = CPLGenerateTempFilename("pdf");
+        CPLString osTmpFilename(CPLSPrintf("%s-%d.ppm",
+                                           osTmpFilenamePrefix.c_str(),
+                                           poGDS->iPage));
+
+        CPLString osCmd = CPLSPrintf("pdftoppm -r %f -f %d -l %d \"%s\" \"%s\"",
+                   poGDS->dfDPI, poGDS->iPage, poGDS->iPage,
+                   poGDS->osFilename.c_str(), osTmpFilenamePrefix.c_str());
+        if (poGDS->osUserPwd.size() != 0)
+        {
+            osCmd += " -upw \"";
+            osCmd += poGDS->osUserPwd;
+            osCmd += "\"";
+        }
+
+        CPLDebug("PDF", "Running '%s'", osCmd.c_str());
+        int nRet = system(osCmd.c_str());
+        if (nRet == 0)
+        {
+            GDALDataset* poDS = (GDALDataset*) GDALOpen(osTmpFilename, GA_ReadOnly);
+            if (poDS)
+            {
+                if (poDS->GetRasterCount() == 3)
+                {
+                    poDS->RasterIO(GF_Read, 0, 0,
+                                   poDS->GetRasterXSize(),
+                                   poDS->GetRasterYSize(),
+                                   poGDS->pabyData, nRasterXSize, nRasterYSize,
+                                   GDT_Byte, 3, NULL, 0, 0, 0);
+                }
+                delete poDS;
+            }
+        }
+        else
+        {
+            CPLDebug("PDF", "Ret code = %d", nRet);
+        }
+        VSIUnlink(osTmpFilename);
+#endif
     }
     if (poGDS->pabyData == NULL)
         return CE_Failure;
@@ -423,7 +448,9 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 PDFDataset::PDFDataset()
 {
+#ifdef USE_POPPLER
     poDoc = NULL;
+#endif
     pszWKT = NULL;
     dfMaxArea = 0;
     adfGeoTransform[0] = 0;
@@ -443,6 +470,7 @@ PDFDataset::PDFDataset()
 /*                           PDFFreeDoc()                               */
 /************************************************************************/
 
+#ifdef USE_POPPLER
 static void PDFFreeDoc(PDFDoc* poDoc)
 {
     if (poDoc)
@@ -455,6 +483,7 @@ static void PDFFreeDoc(PDFDoc* poDoc)
         delete poDoc;
     }
 }
+#endif
 
 /************************************************************************/
 /*                            ~PDFDataset()                            */
@@ -467,7 +496,9 @@ PDFDataset::~PDFDataset()
 
     delete poNeatLine;
 
+#ifdef USE_POPPLER
     PDFFreeDoc(poDoc);
+#endif
 }
 
 /************************************************************************/
@@ -489,6 +520,7 @@ int PDFDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                    PDFDatasetErrorFunction()                         */
 /************************************************************************/
 
+#ifdef USE_POPPLER
 static void PDFDatasetErrorFunction(int nPos, char *pszMsg, va_list args)
 {
     CPLString osError;
@@ -502,6 +534,7 @@ static void PDFDatasetErrorFunction(int nPos, char *pszMsg, va_list args)
 
     CPLError(CE_Failure, CPLE_AppDefined, "%s", osError.c_str());
 }
+#endif
 
 /************************************************************************/
 /*                                Open()                                */
@@ -533,6 +566,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
     else
         iPage = 1;
 
+#ifdef USE_POPPLER
     GooString* poUserPwd = NULL;
 
     /* Set custom error handler for poppler errors */
@@ -630,11 +664,112 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    Dict* poPageDict = oPageObj.getDict();
+    GDALPDFObjectPoppler oPageObjPoppler(&oPageObj, FALSE);
+    GDALPDFObject* poPageObj = &oPageObjPoppler;
+#else
+    PoDoFo::PdfError::EnableDebug( false );
+    PoDoFo::PdfError::EnableLogging( false );
+
+    PoDoFo::PdfMemDocument* poDoc = new PoDoFo::PdfMemDocument();
+    try
+    {
+        poDoc->Load(pszFilename);
+    }
+    catch(PoDoFo::PdfError& oError)
+    {
+        if (oError.GetError() == PoDoFo::ePdfError_InvalidPassword)
+        {
+            if (pszUserPwd)
+            {
+                if (EQUAL(pszUserPwd, "ASK_INTERACTIVE"))
+                {
+                    printf( "Enter password (will be echo'ed in the console): " );
+                    fgets( szPassword, sizeof(szPassword), stdin );
+                    szPassword[sizeof(szPassword)-1] = 0;
+                    char* sz10 = strchr(szPassword, '\n');
+                    if (sz10)
+                        *sz10 = 0;
+                    pszUserPwd = szPassword;
+                }
+
+                try
+                {
+                    poDoc->SetPassword(pszUserPwd);
+                }
+                catch(PoDoFo::PdfError& oError)
+                {
+                    if (oError.GetError() == PoDoFo::ePdfError_InvalidPassword)
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "Invalid password");
+                    }
+                    else
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s", oError.what());
+                    }
+                    delete poDoc;
+                    return NULL;
+                }
+                catch(...)
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF");
+                    delete poDoc;
+                    return NULL;
+                }
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                            "A password is needed. You can specify it through the PDF_USER_PWD "
+                            "configuration option (that can be set to ASK_INTERACTIVE)");
+                delete poDoc;
+                return NULL;
+            }
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s", oError.what());
+            delete poDoc;
+            return NULL;
+        }
+    }
+    catch(...)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF");
+        delete poDoc;
+        return NULL;
+    }
+
+    int nPages = poDoc->GetPageCount();
+    if (iPage < 1 || iPage > nPages)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid page number (%d/%d)",
+                 iPage, nPages);
+        delete poDoc;
+        return NULL;
+    }
+
+    PoDoFo::PdfPage* poPage = poDoc->GetPage(iPage - 1);
+    if ( poPage == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : invalid page");
+        delete poDoc;
+        return NULL;
+    }
+
+    PoDoFo::PdfObject* pObj = poPage->GetObject();
+    GDALPDFObjectPodofo oPageObjPodofo(pObj, poDoc->GetObjects());
+    GDALPDFObject* poPageObj = &oPageObjPodofo;
+#endif
+
+    GDALPDFDictionary* poPageDict = poPageObj->GetDictionary();
     if ( poPageDict == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : poPageDict == NULL");
+#ifdef USE_POPPLER
         PDFFreeDoc(poDoc);
+#else
+        delete poDoc;
+#endif
         return NULL;
     }
 
@@ -650,12 +785,13 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
             f = fopen(pszDumpObject, "wt");
         if (f == NULL)
             f = stderr;
-        DumpObject(f, oPageObj, 0 ,20);
+        DumpObject(f, poPageObj, 0 ,20);
         if (f != stderr)
             fclose(f);
     }
 
     PDFDataset* poDS = new PDFDataset();
+    poDS->osFilename = pszFilename;
 
     if ( nPages > 1 && !bOpenSubdataset )
     {
@@ -677,7 +813,10 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         CSLDestroy(papszSubDatasets);
     }
 
+#ifdef USE_POPPLER
     poDS->poDoc = poDoc;
+#endif
+    poDS->osUserPwd = pszUserPwd ? pszUserPwd : "";
     poDS->iPage = iPage;
     poDS->dfDPI = atof(CPLGetConfigOption("GDAL_PDF_DPI", "150"));
     if (poDS->dfDPI < 1 || poDS->dfDPI > 7200)
@@ -687,34 +826,51 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->dfDPI = 150;
     }
 
+#ifdef USE_POPPLER
     PDFRectangle* psMediaBox = poPage->getMediaBox();
     double dfX1 = psMediaBox->x1;
     double dfY1 = psMediaBox->y1;
     double dfX2 = psMediaBox->x2;
     double dfY2 = psMediaBox->y2;
+#else
+    PoDoFo::PdfRect oMediaBox = poPage->GetMediaBox();
+    double dfX1 = oMediaBox.GetLeft();
+    double dfY1 = oMediaBox.GetBottom();
+    double dfX2 = dfX1 + oMediaBox.GetWidth();
+    double dfY2 = dfY1 + oMediaBox.GetHeight();
+#endif
 
     double dfPixelPerPt = poDS->dfDPI / 72;
-    poDS->nRasterXSize = (dfX2 - dfX1) * dfPixelPerPt;
-    poDS->nRasterYSize = (dfY2 - dfY1) * dfPixelPerPt;
+    poDS->nRasterXSize = (int) ((dfX2 - dfX1) * dfPixelPerPt);
+    poDS->nRasterYSize = (int) ((dfY2 - dfY1) * dfPixelPerPt);
 
-    if ( poDoc->getPageRotate(iPage) == 90 ||
-         poDoc->getPageRotate(iPage) == 270 )
+#ifdef USE_POPPLER
+    double dfRotation = poDoc->getPageRotate(iPage);
+#else
+    double dfRotation = poPage->GetRotation();
+#endif
+    if ( dfRotation == 90 ||
+         dfRotation == 270 )
     {
+/* FIXME: the non poppler case should be implemented. This needs to rotate */
+/* the output of pdftoppm */
+#ifdef USE_POPPLER
         /* Wondering how it would work with a georeferenced image */
         /* Has only been tested with ungeoreferenced image */
         int nTmp = poDS->nRasterXSize;
         poDS->nRasterXSize = poDS->nRasterYSize;
         poDS->nRasterYSize = nTmp;
+#endif
     }
 
-    ObjectAutoFree oLGIDict;
-    ObjectAutoFree oVP;
+    GDALPDFObject* poLGIDict = NULL;
+    GDALPDFObject* poVP = NULL;
     int bIsOGCBP = FALSE;
-    if ( poPageDict->lookup((char*)"LGIDict",&oLGIDict) != NULL && !oLGIDict.isNull())
+    if ( (poLGIDict = poPageDict->Get("LGIDict")) != NULL )
     {
         /* Cf 08-139r2_GeoPDF_Encoding_Best_Practice_Version_2.2.pdf */
         CPLDebug("PDF", "OGC Encoding Best Practice style detected");
-        if (poDS->ParseLGIDictObject(oLGIDict))
+        if (poDS->ParseLGIDictObject(poLGIDict))
         {
             poDS->adfGeoTransform[0] = poDS->adfCTM[4] + poDS->adfCTM[0] * dfX1 + poDS->adfCTM[2] * dfY2;
             poDS->adfGeoTransform[1] = poDS->adfCTM[0] / dfPixelPerPt;
@@ -726,7 +882,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
             bIsOGCBP = TRUE;
         }
     }
-    else if ( poPageDict->lookup((char*)"VP",&oVP) != NULL && !oVP.isNull())
+    else if ( (poVP = poPageDict->Get("VP")) != NULL )
     {
         /* Cf adobe_supplement_iso32000.pdf */
         CPLDebug("PDF", "Adobe ISO32000 style Geospatial PDF perhaps ?");
@@ -734,7 +890,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             CPLDebug("PDF", "non null dfX1 or dfY1 values. untested case...");
         }
-        poDS->ParseVP(oVP, dfX2 - dfX1, dfY2 - dfY1);
+        poDS->ParseVP(poVP, dfX2 - dfX1, dfY2 - dfY1);
     }
     else
     {
@@ -769,6 +925,110 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLFree(pszNeatLineWkt);
     }
 
+
+#ifdef USE_POPPLER
+    int nXRefSize = poDoc->getXRef()->getNumObjects();
+    for(int i=0;i<nXRefSize;i++)
+    {
+        Object o;
+        poDoc->getXRef()->fetch(i, 0, &o);
+        if (o.isStream())
+        {
+            Dict* dict = o.getStream()->getDict();
+            if (dict)
+            {
+                Object oSubType, oType;
+                dict->lookup((char*)"Subtype", &oSubType);
+                dict->lookup((char*)"Type", &oType);
+                if (oType.getType() == objName &&
+                    strcmp(oType.getName(), "Metadata") == 0 &&
+                    oSubType.getType() == objName &&
+                    strcmp(oSubType.getName(), "XML") == 0)
+                {
+                    int nBufferAlloc = 4096;
+                    char* pszXMP = (char*) CPLMalloc(nBufferAlloc);
+                    Stream* poStream = o.getStream();
+                    poStream->reset();
+                    int j;
+                    for(j=0; ; j++)
+                    {
+                        const int ch = poStream->getChar();
+                        if (ch == EOF)
+                            break;
+                        if (j == nBufferAlloc - 2)
+                        {
+                            nBufferAlloc *= 2;
+                            pszXMP = (char*) CPLRealloc(pszXMP, nBufferAlloc);
+                        }
+                        pszXMP[j] = (char)ch;
+                    }
+                    pszXMP[j] = '\0';
+                    if (strncmp(pszXMP, "<?xpacket begin=", strlen("<?xpacket begin=")) == 0)
+                    {
+                        char *apszMDList[2];
+                        apszMDList[0] = pszXMP;
+                        apszMDList[1] = NULL;
+                        poDS->SetMetadata(apszMDList, "xml:XMP");
+                    }
+                    CPLFree(pszXMP);
+                }
+                oSubType.free();
+                oType.free();
+            }
+        }
+        o.free();
+    }
+#else
+    PoDoFo::TIVecObjects it = poDoc->GetObjects().begin();
+    for( ; it != poDoc->GetObjects().end(); ++it )
+    {
+        if( (*it)->HasStream() && (*it)->GetDataType() == PoDoFo::ePdfDataType_Dictionary)
+        {
+            PoDoFo::PdfDictionary& dict = (*it)->GetDictionary();
+            const PoDoFo::PdfObject* poType = dict.GetKey(PoDoFo::PdfName("Type"));
+            const PoDoFo::PdfObject* poSubType = dict.GetKey(PoDoFo::PdfName("Subtype"));
+            if (poType == NULL ||
+                poType->GetDataType() != PoDoFo::ePdfDataType_Name ||
+                poType->GetName().GetName().compare("Metadata") != 0 ||
+                poSubType == NULL || 
+                poSubType->GetDataType() != PoDoFo::ePdfDataType_Name ||
+                poSubType->GetName().GetName().compare("XML") != 0)
+                continue;
+
+            try
+            {
+                PoDoFo::PdfMemStream* pStream = dynamic_cast<PoDoFo::PdfMemStream*>((*it)->GetStream());
+                pStream->Uncompress();
+
+                const char* pszContent = pStream->Get();
+                int nLength = (int)pStream->GetLength();
+                if (pszContent != NULL && nLength > 15 &&
+                    strncmp(pszContent, "<?xpacket begin=", strlen("<?xpacket begin=")) == 0)
+                {
+                    char *apszMDList[2];
+                    apszMDList[0] = (char*) CPLMalloc(nLength + 1);
+                    memcpy(apszMDList[0], pszContent, nLength);
+                    apszMDList[0][nLength] = 0;
+                    apszMDList[1] = NULL;
+                    poDS->SetMetadata(apszMDList, "xml:XMP");
+                    CPLFree(apszMDList[0]);
+
+                    break;
+                }
+            }
+            catch( const PoDoFo::PdfError & e )
+            {
+                e.PrintErrorMsg();
+            }
+        }
+    }
+#endif
+
+
+#ifndef USE_POPPLER
+    delete poDoc;
+#endif
+
     int iBand;
     for(iBand = 1; iBand <= 3; iBand ++)
         poDS->SetBand(iBand, new PDFRasterBand(poDS, iBand));
@@ -790,19 +1050,20 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                       ParseLGIDictObject()                           */
 /************************************************************************/
 
-int PDFDataset::ParseLGIDictObject(Object& oLGIDict)
+int PDFDataset::ParseLGIDictObject(GDALPDFObject* poLGIDict)
 {
     int i;
     int bOK = FALSE;
-    if (oLGIDict.isArray())
+    if (poLGIDict->GetType() == PDFObjectType_Array)
     {
-        int nArrayLength = oLGIDict.arrayGetLength();
+        GDALPDFArray* poArray = poLGIDict->GetArray();
+        int nArrayLength = poArray->GetLength();
         int iMax = -1;
+        GDALPDFObject* poArrayElt;
         for (i=0; i<nArrayLength; i++)
         {
-            ObjectAutoFree oArrayElt;
-            if ( oLGIDict.arrayGet(i,&oArrayElt) == NULL ||
-                 !oArrayElt.isDict() )
+            if ( (poArrayElt = poArray->Get(i)) == NULL ||
+                 poArrayElt->GetType() != PDFObjectType_Dictionary )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "LGIDict[%d] is not a dictionary", i);
@@ -810,7 +1071,7 @@ int PDFDataset::ParseLGIDictObject(Object& oLGIDict)
             }
 
             int bIsLargestArea = FALSE;
-            ParseLGIDictDictFirstPass(oArrayElt.getDict(), &bIsLargestArea);
+            ParseLGIDictDictFirstPass(poArrayElt->GetDictionary(), &bIsLargestArea);
             if (bIsLargestArea)
                 iMax = i;
         }
@@ -818,44 +1079,43 @@ int PDFDataset::ParseLGIDictObject(Object& oLGIDict)
         if (iMax < 0)
             return FALSE;
 
-        ObjectAutoFree oArrayElt;
-        oLGIDict.arrayGet(iMax,&oArrayElt);
-        bOK = ParseLGIDictDictSecondPass(oArrayElt.getDict());
+        poArrayElt = poArray->Get(iMax);
+        bOK = ParseLGIDictDictSecondPass(poArrayElt->GetDictionary());
     }
-    else if (oLGIDict.isDict())
+    else if (poLGIDict->GetType() == PDFObjectType_Dictionary)
     {
-        bOK = ParseLGIDictDictFirstPass(oLGIDict.getDict()) &&
-              ParseLGIDictDictSecondPass(oLGIDict.getDict());
+        bOK = ParseLGIDictDictFirstPass(poLGIDict->GetDictionary()) &&
+              ParseLGIDictDictSecondPass(poLGIDict->GetDictionary());
     }
     else
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "LGIDict is of type %s", oLGIDict.getTypeName());
+                 "LGIDict is of type %s", poLGIDict->GetTypeName());
     }
 
     return bOK;
 }
 
 /************************************************************************/
-/*                            GetValue()                                */
+/*                            Get()                                */
 /************************************************************************/
 
-static double GetValue(Object& o, int nIndice = -1)
+static double Get(GDALPDFObject* poObj, int nIndice = -1)
 {
-    if (o.isArray() && nIndice >= 0)
+    if (poObj->GetType() == PDFObjectType_Array && nIndice >= 0)
     {
-        ObjectAutoFree oElt;
-        if (o.arrayGet(nIndice, &oElt) == NULL)
+        poObj = poObj->GetArray()->Get(nIndice);
+        if (poObj == NULL)
             return 0;
-        return GetValue(oElt);
+        return Get(poObj);
     }
-    else if (o.isInt())
-        return o.getInt();
-    else if (o.isReal())
-        return o.getReal();
-    else if (o.isString())
+    else if (poObj->GetType() == PDFObjectType_Int)
+        return poObj->GetInt();
+    else if (poObj->GetType() == PDFObjectType_Real)
+        return poObj->GetReal();
+    else if (poObj->GetType() == PDFObjectType_String)
     {
-        const char* pszStr = o.getString()->getCString();
+        const char* pszStr = poObj->GetString().c_str();
         int nLen = strlen(pszStr);
         /* cf Military_Installations_2008.pdf that has values like "96 0 0.0W" */
         char chLast = pszStr[nLen-1];
@@ -885,20 +1145,20 @@ static double GetValue(Object& o, int nIndice = -1)
     else
     {
         CPLError(CE_Warning, CPLE_AppDefined, "Unexpected type : %s",
-                 o.getTypeName());
+                 poObj->GetTypeName());
         return 0;
     }
 }
 
 /************************************************************************/
-/*                            GetValue()                                */
+/*                            Get()                                */
 /************************************************************************/
 
-static double GetValue(Dict* poDict, const char* pszName)
+static double Get(GDALPDFDictionary* poDict, const char* pszName)
 {
-    ObjectAutoFree o;
-    if (poDict->lookup((char*)pszName, &o) != NULL && !o.isNull())
-        return GetValue(o);
+    GDALPDFObject* poObj;
+    if ( (poObj = poDict->Get(pszName)) != NULL )
+        return Get(poObj);
     CPLError(CE_Failure, CPLE_AppDefined,
              "Cannot find parameter %s", pszName);
     return 0;
@@ -908,8 +1168,8 @@ static double GetValue(Dict* poDict, const char* pszName)
 /*                   ParseLGIDictDictFirstPass()                        */
 /************************************************************************/
 
-int PDFDataset::ParseLGIDictDictFirstPass(Dict* poLGIDict,
-                                             int* pbIsLargestArea)
+int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
+                                          int* pbIsLargestArea)
 {
     int i;
 
@@ -922,63 +1182,61 @@ int PDFDataset::ParseLGIDictDictFirstPass(Dict* poLGIDict,
 /* -------------------------------------------------------------------- */
 /*      Extract Type attribute                                          */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oType;
-    if (poLGIDict->lookup((char*)"Type",&oType) == NULL &&
-        !oType.isNull())
+    GDALPDFObject* poType;
+    if ((poType = poLGIDict->Get("Type")) == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Type of LGIDict object");
         return FALSE;
     }
 
-    if ( !oType.isName() )
+    if ( poType->GetType() != PDFObjectType_Name )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Invalid type for Type of LGIDict object");
         return FALSE;
     }
 
-    if ( strcmp(oType.getName(), "LGIDict") != 0 )
+    if ( strcmp(poType->GetName().c_str(), "LGIDict") != 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Invalid value for Type of LGIDict object : %s",
-                 oType.getName());
+                 poType->GetName().c_str());
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract Version attribute                                       */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oVersion;
-    if (poLGIDict->lookup((char*)"Version",&oVersion) == NULL &&
-        !oVersion.isNull())
+    GDALPDFObject* poVersion;
+    if ((poVersion = poLGIDict->Get("Version")) == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Version of LGIDict object");
         return FALSE;
     }
 
-    if (oVersion.isString())
+    if ( poVersion->GetType() != PDFObjectType_String )
     {
         /* OGC best practice is 2.1 */
         CPLDebug("PDF", "LGIDict Version : %s",
-                 oVersion.getString()->getCString());
+                 poVersion->GetString().c_str());
     }
-    else if (oVersion.isInt())
+    else if (poVersion->GetType() != PDFObjectType_Int)
     {
         /* Old TerraGo is 2 */
         CPLDebug("PDF", "LGIDict Version : %d",
-                 oVersion.getInt());
+                 poVersion->GetInt());
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract Neatline attribute                                      */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oNeatline;
-    if (poLGIDict->lookup((char*)"Neatline", &oNeatline) != NULL &&
-        oNeatline.isArray() )
+    GDALPDFObject* poNeatline;
+    if ((poNeatline = poLGIDict->Get("Neatline")) != NULL &&
+        poNeatline->GetType() == PDFObjectType_Array)
     {
-        int nLength = oNeatline.arrayGetLength();
+        int nLength = poNeatline->GetArray()->GetLength();
         if ( (nLength % 2) != 0 || nLength < 4 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -989,8 +1247,8 @@ int PDFDataset::ParseLGIDictDictFirstPass(Dict* poLGIDict,
         double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0;
         for(i=0;i<nLength;i+=2)
         {
-            double dfX = GetValue(oNeatline, i);
-            double dfY = GetValue(oNeatline, i + 1);
+            double dfX = Get(poNeatline, i);
+            double dfY = Get(poNeatline, i + 1);
             if (i == 0 || dfX < dfMinX) dfMinX = dfX;
             if (i == 0 || dfY < dfMinY) dfMinY = dfY;
             if (i == 0 || dfX > dfMaxX) dfMaxX = dfX;
@@ -1013,8 +1271,8 @@ int PDFDataset::ParseLGIDictDictFirstPass(Dict* poLGIDict,
         OGRLinearRing* poRing = new OGRLinearRing();
         for(i=0;i<nLength;i+=2)
         {
-            double dfX = GetValue(oNeatline, i);
-            double dfY = GetValue(oNeatline, i + 1);
+            double dfX = Get(poNeatline, i);
+            double dfY = Get(poNeatline, i + 1);
             poRing->addPoint(dfX, dfY);
         }
         poNeatLine->addRingDirectly(poRing);
@@ -1027,19 +1285,19 @@ int PDFDataset::ParseLGIDictDictFirstPass(Dict* poLGIDict,
 /*                  ParseLGIDictDictSecondPass()                        */
 /************************************************************************/
 
-int PDFDataset::ParseLGIDictDictSecondPass(Dict* poLGIDict)
+int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
 {
     int i;
 
 /* -------------------------------------------------------------------- */
 /*      Extract CTM attribute                                           */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oCTM;
+    GDALPDFObject* poCTM;
     int bHasCTM = FALSE;
-    if (poLGIDict->lookup((char*)"CTM", &oCTM) != NULL &&
-        oCTM.isArray())
+    if ((poCTM = poLGIDict->Get("CTM")) != NULL &&
+        poCTM->GetType() == PDFObjectType_Array)
     {
-        int nLength = oCTM.arrayGetLength();
+        int nLength = poCTM->GetArray()->GetLength();
         if ( nLength != 6 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1050,7 +1308,7 @@ int PDFDataset::ParseLGIDictDictSecondPass(Dict* poLGIDict)
         bHasCTM = TRUE;
         for(i=0;i<nLength;i++)
         {
-            adfCTM[i] = GetValue(oCTM, i);
+            adfCTM[i] = Get(poCTM, i);
             /* Nullify rotation terms that are significantly smaller than */
             /* scaling termes */
             if ((i == 1 || i == 2) && fabs(adfCTM[i]) < fabs(adfCTM[0]) * 1e-10)
@@ -1064,9 +1322,8 @@ int PDFDataset::ParseLGIDictDictSecondPass(Dict* poLGIDict)
 /* -------------------------------------------------------------------- */
     if (!bHasCTM)
     {
-        ObjectAutoFree oRegistration;
-        if (poLGIDict->lookup((char*)"Registration", &oRegistration) != NULL &&
-            !oRegistration.isNull())
+        GDALPDFObject* poRegistration;
+        if ((poRegistration = poLGIDict->Get("Registration")) != NULL)
         {
             /* TODO */
             CPLDebug("PDF", "Registration unhandled for now");
@@ -1082,22 +1339,22 @@ int PDFDataset::ParseLGIDictDictSecondPass(Dict* poLGIDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Projection attribute                                    */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oProjection;
-    if (poLGIDict->lookup((char*)"Projection", &oProjection) == NULL ||
-        !oProjection.isDict())
+    GDALPDFObject* poProjection;
+    if ((poProjection = poLGIDict->Get("Projection")) == NULL ||
+        poProjection->GetType() != PDFObjectType_Dictionary)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Could not find Projection");
         return FALSE;
     }
 
-    return ParseProjDict(oProjection.getDict());
+    return ParseProjDict(poProjection->GetDictionary());
 }
 
 /************************************************************************/
 /*                         ParseProjDict()                               */
 /************************************************************************/
 
-int PDFDataset::ParseProjDict(Dict* poProjDict)
+int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
 {
     if (poProjDict == NULL)
         return FALSE;
@@ -1106,27 +1363,26 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Type attribute                                          */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oType;
-    if (poProjDict->lookup((char*)"Type",&oType) == NULL &&
-        !oType.isNull())
+    GDALPDFObject* poType;
+    if ((poType = poProjDict->Get("Type")) == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Type of Projection object");
         return FALSE;
     }
 
-    if ( !oType.isName() )
+    if ( poType->GetType() != PDFObjectType_Name )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Invalid type for Type of Projection object");
         return FALSE;
     }
 
-    if ( strcmp(oType.getName(), "Projection") != 0 )
+    if ( strcmp(poType->GetName().c_str(), "Projection") != 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Invalid value for Type of Projection object : %s",
-                 oType.getName());
+                 poType->GetName().c_str());
         return FALSE;
     }
 
@@ -1137,13 +1393,12 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
     int bIsNAD83 = FALSE;
     int bIsNAD27 = FALSE;
 
-    ObjectAutoFree oDatum;
-    if (poProjDict->lookup((char*)"Datum",&oDatum) != NULL &&
-        !oDatum.isNull())
+    GDALPDFObject* poDatum;
+    if ((poDatum = poProjDict->Get("Datum")) != NULL)
     {
-        if (oDatum.isString())
+        if (poDatum->GetType() == PDFObjectType_String)
         {
-            char* pszDatum = oDatum.getString()->getCString();
+            const char* pszDatum = poDatum->GetString().c_str();
             CPLDebug("PDF", "Datum = %s", pszDatum);
             if (EQUAL(pszDatum, "WE") || EQUAL(pszDatum, "WGE"))
             {
@@ -1187,7 +1442,7 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
                                 6378137,298.257223563);
             }
         }
-        else if (oDatum.isDict())
+        else if (poDatum->GetType() == PDFObjectType_Dictionary)
         {
             /* TODO */
             CPLError(CE_Warning, CPLE_AppDefined,
@@ -1202,26 +1457,26 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Hemisphere attribute                                    */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oHemisphere;
     CPLString osHemisphere;
-    if (poProjDict->lookup((char*)"Hemisphere",&oHemisphere) != NULL &&
-        oHemisphere.isString())
+    GDALPDFObject* poHemisphere;
+    if ((poHemisphere = poProjDict->Get("Hemisphere")) != NULL &&
+        poHemisphere->GetType() == PDFObjectType_String)
     {
-        osHemisphere = oHemisphere.getString()->getCString();
+        osHemisphere = poHemisphere->GetString();
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract ProjectionType attribute                                */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oProjectionType;
-    if (poProjDict->lookup((char*)"ProjectionType",&oProjectionType) == NULL ||
-        !oProjectionType.isString())
+    GDALPDFObject* poProjectionType;
+    if ((poProjectionType = poProjDict->Get("ProjectionType")) == NULL ||
+        poProjectionType->GetType() != PDFObjectType_String)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find ProjectionType of Projection object");
         return FALSE;
     }
-    CPLString osProjectionType(oProjectionType.getString()->getCString());
+    CPLString osProjectionType(poProjectionType->GetString());
     CPLDebug("PDF", "Projection.ProjectionType = %s", osProjectionType.c_str());
 
     /* Unhandled: NONE, GEODETIC */
@@ -1235,7 +1490,7 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "UT")) /* UTM */
     {
-        int nZone = (int)GetValue(poProjDict, "Zone");
+        int nZone = (int)Get(poProjDict, "Zone");
         int bNorth = EQUAL(osHemisphere, "N");
         if (bIsWGS84)
             oSRS.importFromEPSG( ((bNorth) ? 32600 : 32700) + nZone );
@@ -1255,18 +1510,18 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "SPCS")) /* State Plane */
     {
-        int nZone = (int)GetValue(poProjDict, "Zone");
+        int nZone = (int)Get(poProjDict, "Zone");
         oSRS.SetStatePlane( nZone, bIsNAD83 );
     }
 
     else if (EQUAL(osProjectionType, "AC")) /* Albers Equal Area Conic */
     {
-        double dfStdP1 = GetValue(poProjDict, "StandardParallelOne");
-        double dfStdP2 = GetValue(poProjDict, "StandardParallelTwo");
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfStdP1 = Get(poProjDict, "StandardParallelOne");
+        double dfStdP2 = Get(poProjDict, "StandardParallelTwo");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetACEA( dfStdP1, dfStdP2,
                      dfCenterLat, dfCenterLong,
                      dfFalseEasting, dfFalseNorthing );
@@ -1274,90 +1529,90 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
  
     else if (EQUAL(osProjectionType, "AL")) /* Azimuthal Equidistant */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetAE(  dfCenterLat, dfCenterLong,
                      dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "BF")) /* Bonne */
     {
-        double dfStdP1 = GetValue(poProjDict, "OriginLatitude");
-        double dfCentralMeridian = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfStdP1 = Get(poProjDict, "OriginLatitude");
+        double dfCentralMeridian = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetBonne( dfStdP1, dfCentralMeridian,
                        dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "CS")) /* Cassini */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetCS(  dfCenterLat, dfCenterLong,
                      dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "LI")) /* Cylindrical Equal Area */
     {
-        double dfStdP1 = GetValue(poProjDict, "OriginLatitude");
-        double dfCentralMeridian = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfStdP1 = Get(poProjDict, "OriginLatitude");
+        double dfCentralMeridian = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetCEA( dfStdP1, dfCentralMeridian,
                      dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "EF")) /* Eckert IV */
     {
-        double dfCentralMeridian = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCentralMeridian = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetEckertIV( dfCentralMeridian,
                           dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "ED")) /* Eckert VI */
     {
-        double dfCentralMeridian = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCentralMeridian = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetEckertVI( dfCentralMeridian,
                           dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "CP")) /* Equidistant Cylindrical */
     {
-        double dfCenterLat = GetValue(poProjDict, "StandardParallel");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "StandardParallel");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetEquirectangular( dfCenterLat, dfCenterLong,
                                  dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "GN")) /* Gnomonic */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetGnomonic(dfCenterLat, dfCenterLong,
                          dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "LE")) /* Lambert Conformal Conic */
     {
-        double dfStdP1 = GetValue(poProjDict, "StandardParallelOne");
-        double dfStdP2 = GetValue(poProjDict, "StandardParallelTwo");
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfStdP1 = Get(poProjDict, "StandardParallelOne");
+        double dfStdP2 = Get(poProjDict, "StandardParallelTwo");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetLCC( dfStdP1, dfStdP2,
                      dfCenterLat, dfCenterLong,
                      dfFalseEasting, dfFalseNorthing );
@@ -1365,11 +1620,11 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "MC")) /* Mercator */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfScale = GetValue(poProjDict, "ScaleFactor");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfScale = Get(poProjDict, "ScaleFactor");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetMercator( dfCenterLat, dfCenterLong,
                           dfScale,
                           dfFalseEasting, dfFalseNorthing );
@@ -1378,18 +1633,18 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
     else if (EQUAL(osProjectionType, "MH")) /* Miller Cylindrical */
     {
         double dfCenterLat = 0 /* ? */;
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetMC( dfCenterLat, dfCenterLong,
                     dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "MP")) /* Mollweide */
     {
-        double dfCentralMeridian = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCentralMeridian = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetMollweide( dfCentralMeridian,
                            dfFalseEasting, dfFalseNorthing );
     }
@@ -1409,14 +1664,14 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "OC")) /* Oblique Mercator */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfLat1 = GetValue(poProjDict, "LatitudeOne");
-        double dfLong1 = GetValue(poProjDict, "LongitudeOne");
-        double dfLat2 = GetValue(poProjDict, "LatitudeTwo");
-        double dfLong2 = GetValue(poProjDict, "LongitudeTwo");
-        double dfScale = GetValue(poProjDict, "ScaleFactor");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfLat1 = Get(poProjDict, "LatitudeOne");
+        double dfLong1 = Get(poProjDict, "LongitudeOne");
+        double dfLat2 = Get(poProjDict, "LatitudeTwo");
+        double dfLong2 = Get(poProjDict, "LongitudeTwo");
+        double dfScale = Get(poProjDict, "ScaleFactor");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetHOM2PNO( dfCenterLat,
                          dfLat1, dfLong1,
                          dfLat2, dfLong2,
@@ -1427,21 +1682,21 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "OD")) /* Orthographic */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetOrthographic( dfCenterLat, dfCenterLong,
                            dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "PG")) /* Polar Stereographic */
     {
-        double dfCenterLat = GetValue(poProjDict, "LatitudeTrueScale");
-        double dfCenterLong = GetValue(poProjDict, "LongitudeDownFromPole");
+        double dfCenterLat = Get(poProjDict, "LatitudeTrueScale");
+        double dfCenterLong = Get(poProjDict, "LongitudeDownFromPole");
         double dfScale = 1.0;
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetPS( dfCenterLat, dfCenterLong,
                     dfScale,
                     dfFalseEasting, dfFalseNorthing);
@@ -1449,30 +1704,30 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "PH")) /* Polyconic */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetPolyconic( dfCenterLat, dfCenterLong,
                            dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "SA")) /* Sinusoidal */
     {
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetSinusoidal( dfCenterLong,
                            dfFalseEasting, dfFalseNorthing );
     }
 
     else if (EQUAL(osProjectionType, "SD")) /* Stereographic */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
         double dfScale = 1.0;
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetStereographic( dfCenterLat, dfCenterLong,
                                dfScale,
                                dfFalseEasting, dfFalseNorthing);
@@ -1480,11 +1735,11 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "TC")) /* Transverse Mercator */
     {
-        double dfCenterLat = GetValue(poProjDict, "OriginLatitude");
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfScale = GetValue(poProjDict, "ScaleFactor");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLat = Get(poProjDict, "OriginLatitude");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfScale = Get(poProjDict, "ScaleFactor");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         if (dfCenterLat == 0.0 && dfScale == 0.9996 && dfFalseEasting == 500000 &&
             (dfFalseNorthing == 0.0 || dfFalseNorthing == 10000000.0))
         {
@@ -1509,9 +1764,9 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 
     else if (EQUAL(osProjectionType, "VA")) /* Van der Grinten */
     {
-        double dfCenterLong = GetValue(poProjDict, "CentralMeridian");
-        double dfFalseEasting = GetValue(poProjDict, "FalseEasting");
-        double dfFalseNorthing = GetValue(poProjDict, "FalseNorthing");
+        double dfCenterLong = Get(poProjDict, "CentralMeridian");
+        double dfFalseEasting = Get(poProjDict, "FalseEasting");
+        double dfFalseNorthing = Get(poProjDict, "FalseNorthing");
         oSRS.SetVDG( dfCenterLong,
                      dfFalseEasting, dfFalseNorthing );
     }
@@ -1527,12 +1782,12 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Units attribute                                         */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oUnits;
     CPLString osUnits;
-    if (poProjDict->lookup((char*)"Units",&oUnits) != NULL &&
-        oUnits.isString())
+    GDALPDFObject* poUnits;
+    if ((poUnits = poProjDict->Get("Units")) != NULL &&
+        poUnits->GetType() == PDFObjectType_String)
     {
-        osUnits = oUnits.getString()->getCString();
+        osUnits = poUnits->GetString();
         CPLDebug("PDF", "Projection.Units = %s", osUnits.c_str());
 
         if (EQUAL(osUnits, "FT"))
@@ -1557,14 +1812,16 @@ int PDFDataset::ParseProjDict(Dict* poProjDict)
 /*                              ParseVP()                               */
 /************************************************************************/
 
-int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHeight)
+int PDFDataset::ParseVP(GDALPDFObject* poVP, double dfMediaBoxWidth, double dfMediaBoxHeight)
 {
     int i;
 
-    if (!oVP.isArray())
+    if (poVP->GetType() != PDFObjectType_Array)
         return FALSE;
 
-    int nLength = oVP.arrayGetLength();
+    GDALPDFArray* poVPArray = poVP->GetArray();
+
+    int nLength = poVPArray->GetLength();
     CPLDebug("PDF", "VP length = %d", nLength);
     if (nLength < 1)
         return FALSE;
@@ -1577,22 +1834,24 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
 
     for(i=0;i<nLength;i++)
     {
-        ObjectAutoFree oVPElt;
-        if ( !oVP.arrayGet(i,&oVPElt) || !oVPElt.isDict() )
+        GDALPDFObject* poVPElt = poVPArray->Get(i);
+        if (poVPElt == NULL || poVPElt->GetType() != PDFObjectType_Dictionary)
         {
             return FALSE;
         }
 
-        ObjectAutoFree oBBox;
-        if( !oVPElt.dictLookup((char*)"BBox",&oBBox) ||
-            !oBBox.isArray() )
+        GDALPDFDictionary* poVPEltDict = poVPElt->GetDictionary();
+
+        GDALPDFObject* poBBox;
+        if( (poBBox = poVPEltDict->Get("BBox")) == NULL ||
+            poBBox->GetType() != PDFObjectType_Array )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Cannot find Bbox object");
             return FALSE;
         }
 
-        int nBboxLength = oBBox.arrayGetLength();
+        int nBboxLength = poBBox->GetArray()->GetLength();
         if (nBboxLength != 4)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1601,10 +1860,10 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
         }
 
         double adfBBox[4];
-        adfBBox[0] = GetValue(oBBox, 0);
-        adfBBox[1] = GetValue(oBBox, 1);
-        adfBBox[2] = GetValue(oBBox, 2);
-        adfBBox[3] = GetValue(oBBox, 3);
+        adfBBox[0] = Get(poBBox, 0);
+        adfBBox[1] = Get(poBBox, 1);
+        adfBBox[2] = Get(poBBox, 2);
+        adfBBox[3] = Get(poBBox, 3);
         double dfArea = fabs(adfBBox[2] - adfBBox[0]) * fabs(adfBBox[3] - adfBBox[1]);
         if (dfArea > dfLargestArea)
         {
@@ -1619,22 +1878,24 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
     }
 
 
-    ObjectAutoFree oVPElt;
-    if ( !oVP.arrayGet(iLargest,&oVPElt) || !oVPElt.isDict() )
+    GDALPDFObject* poVPElt = poVPArray->Get(iLargest);
+    if (poVPElt == NULL || poVPElt->GetType() != PDFObjectType_Dictionary)
     {
         return FALSE;
     }
 
-    ObjectAutoFree oBBox;
-    if( !oVPElt.dictLookup((char*)"BBox",&oBBox) ||
-        !oBBox.isArray() )
+    GDALPDFDictionary* poVPEltDict = poVPElt->GetDictionary();
+
+    GDALPDFObject* poBBox;
+    if( (poBBox = poVPEltDict->Get("BBox")) == NULL ||
+        poBBox->GetType() != PDFObjectType_Array )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                 "Cannot find Bbox object");
         return FALSE;
     }
 
-    int nBboxLength = oBBox.arrayGetLength();
+    int nBboxLength = poBBox->GetArray()->GetLength();
     if (nBboxLength != 4)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -1642,36 +1903,38 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
         return FALSE;
     }
 
-    double dfULX = GetValue(oBBox, 0);
-    double dfULY = dfMediaBoxHeight - GetValue(oBBox, 1);
-    double dfLRX = GetValue(oBBox, 2);
-    double dfLRY = dfMediaBoxHeight - GetValue(oBBox, 3);
+    double dfULX = Get(poBBox, 0);
+    double dfULY = dfMediaBoxHeight - Get(poBBox, 1);
+    double dfLRX = Get(poBBox, 2);
+    double dfLRY = dfMediaBoxHeight - Get(poBBox, 3);
 
 /* -------------------------------------------------------------------- */
 /*      Extract Measure attribute                                       */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oMeasure;
-    if( !oVPElt.dictLookup((char*)"Measure",&oMeasure) ||
-        !oMeasure.isDict() )
+    GDALPDFObject* poMeasure;
+    if( (poMeasure = poVPEltDict->Get("Measure")) == NULL ||
+        poMeasure->GetType() != PDFObjectType_Dictionary )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Measure object");
         return FALSE;
     }
 
+    GDALPDFDictionary* poMeasureDict = poMeasure->GetDictionary();
+
 /* -------------------------------------------------------------------- */
 /*      Extract Subtype attribute                                       */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oSubtype;
-    if( !oMeasure.dictLookup((char*)"Subtype",&oSubtype) ||
-        !oSubtype.isName() )
+    GDALPDFObject* poSubtype;
+    if( (poSubtype = poMeasureDict->Get("Subtype")) == NULL ||
+        poSubtype->GetType() != PDFObjectType_Name )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Subtype object");
         return FALSE;
     }
 
-    CPLDebug("PDF", "Subtype = %s", oSubtype.getName());
+    CPLDebug("PDF", "Subtype = %s", poSubtype->GetName().c_str());
 
 /* -------------------------------------------------------------------- */
 /*      Extract Bounds attribute                                       */
@@ -1681,21 +1944,21 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
     /* has lgit:LPTS, lgit:GPTS and lgit:Bounds that have more precision than */
     /* LPTS, GPTS and Bounds. Use those ones */
 
-    ObjectAutoFree oBounds;
-    if( oMeasure.dictLookup((char*)"lgit:Bounds",&oBounds) &&
-        oBounds.isArray() )
+    GDALPDFObject* poBounds;
+    if( (poBounds = poMeasureDict->Get("lgit:Bounds")) != NULL &&
+        poBounds->GetType() == PDFObjectType_Array )
     {
         CPLDebug("PDF", "Using lgit:Bounds");
     }
-    else if( !oMeasure.dictLookup((char*)"Bounds",&oBounds) ||
-        !oBounds.isArray() )
+    else if( (poBounds = poMeasureDict->Get("Bounds")) == NULL ||
+              poBounds->GetType() != PDFObjectType_Array )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Bounds object");
         return FALSE;
     }
 
-    int nBoundsLength = oBounds.arrayGetLength();
+    int nBoundsLength = poBounds->GetArray()->GetLength();
     if (nBoundsLength != 8)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -1706,28 +1969,28 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
     double adfBounds[8];
     for(i=0;i<8;i++)
     {
-        adfBounds[i] = GetValue(oBounds, i);
+        adfBounds[i] = Get(poBounds, i);
         CPLDebug("PDF", "Bounds[%d] = %f", i, adfBounds[i]);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract GPTS attribute                                          */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oGPTS;
-    if( oMeasure.dictLookup((char*)"lgit:GPTS",&oGPTS) &&
-        oGPTS.isArray() )
+    GDALPDFObject* poGPTS;
+    if( (poGPTS = poMeasureDict->Get("lgit:GPTS")) != NULL &&
+        poGPTS->GetType() == PDFObjectType_Array )
     {
         CPLDebug("PDF", "Using lgit:GPTS");
     }
-    else if( !oMeasure.dictLookup((char*)"GPTS",&oGPTS) ||
-        !oGPTS.isArray() )
+    else if( (poGPTS = poMeasureDict->Get("GPTS")) == NULL ||
+              poGPTS->GetType() != PDFObjectType_Array )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find GPTS object");
         return FALSE;
     }
 
-    int nGPTSLength = oGPTS.arrayGetLength();
+    int nGPTSLength = poGPTS->GetArray()->GetLength();
     if (nGPTSLength != 8)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -1738,29 +2001,28 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
     double adfGPTS[8];
     for(i=0;i<8;i++)
     {
-        adfGPTS[i] = GetValue(oGPTS, i);
+        adfGPTS[i] = Get(poGPTS, i);
         CPLDebug("PDF", "GPTS[%d] = %.18f", i, adfGPTS[i]);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract LPTS attribute                                          */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oLPTS;
-
-    if( oMeasure.dictLookup((char*)"lgit:LPTS",&oLPTS) &&
-        oLPTS.isArray() )
+    GDALPDFObject* poLPTS;
+    if( (poLPTS = poMeasureDict->Get("lgit:LPTS")) != NULL &&
+        poLPTS->GetType() == PDFObjectType_Array )
     {
         CPLDebug("PDF", "Using lgit:LPTS");
     }
-    else if( !oMeasure.dictLookup((char*)"LPTS",&oLPTS) ||
-        !oLPTS.isArray() )
+    else if( (poLPTS = poMeasureDict->Get("LPTS")) == NULL ||
+              poLPTS->GetType() != PDFObjectType_Array )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find LPTS object");
         return FALSE;
     }
 
-    int nLPTSLength = oLPTS.arrayGetLength();
+    int nLPTSLength = poLPTS->GetArray()->GetLength();
     if (nLPTSLength != 8)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -1771,51 +2033,53 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
     double adfLPTS[8];
     for(i=0;i<8;i++)
     {
-        adfLPTS[i] = GetValue(oLPTS, i);
+        adfLPTS[i] = Get(poLPTS, i);
         CPLDebug("PDF", "LPTS[%d] = %f", i, adfLPTS[i]);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Extract GCS attribute                                           */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oGCS;
-    if( !oMeasure.dictLookup((char*)"GCS",&oGCS) ||
-        !oGCS.isDict() )
+    GDALPDFObject* poGCS;
+    if( (poGCS = poMeasureDict->Get("GCS")) == NULL ||
+        poGCS->GetType() != PDFObjectType_Dictionary )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find GCS object");
         return FALSE;
     }
 
+    GDALPDFDictionary* poGCSDict = poGCS->GetDictionary();
+
 /* -------------------------------------------------------------------- */
 /*      Extract GCS.Type attribute                                      */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oGCSType;
-    if( !oGCS.dictLookup((char*)"Type",&oGCSType) ||
-        !oGCSType.isName() )
+    GDALPDFObject* poGCSType;
+    if( (poGCSType = poGCSDict->Get("Type")) == NULL ||
+        poGCSType->GetType() != PDFObjectType_Name )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find GCS.Type object");
         return FALSE;
     }
 
-    CPLDebug("PDF", "GCS.Type = %s", oGCSType.getName());
+    CPLDebug("PDF", "GCS.Type = %s", poGCSType->GetName().c_str());
 
 /* -------------------------------------------------------------------- */
 /*      Extract GCS.WKT attribute                                      */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oGCSWKT;
-    if( !oGCS.dictLookup((char*)"WKT",&oGCSWKT) ||
-        !oGCSWKT.isString() )
+    GDALPDFObject* poGCSWKT;
+    if( (poGCSWKT = poGCSDict->Get("WKT")) == NULL ||
+        poGCSWKT->GetType() != PDFObjectType_String )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find GCS.WKT object");
         return FALSE;
     }
 
-    CPLDebug("PDF", "GCS.WKT = %s", oGCSWKT.getString()->getCString());
+    CPLDebug("PDF", "GCS.WKT = %s", poGCSWKT->GetString().c_str());
     CPLFree(pszWKT);
-    pszWKT = CPLStrdup(oGCSWKT.getString()->getCString());
+    pszWKT = CPLStrdup(poGCSWKT->GetString().c_str());
 
 /* -------------------------------------------------------------------- */
 /*      Compute geotransform                                            */
@@ -1925,9 +2189,9 @@ int PDFDataset::ParseVP(Object& oVP, double dfMediaBoxWidth, double dfMediaBoxHe
 /* -------------------------------------------------------------------- */
 /*      Extract PointData attribute                                     */
 /* -------------------------------------------------------------------- */
-    ObjectAutoFree oPointData;
-    if( oVPElt.dictLookup((char*)"PtData",&oPointData) &&
-        oPointData.isDict() )
+    GDALPDFObject* poPointData;
+    if( (poPointData = poVPEltDict->Get("PtData")) != NULL &&
+        poPointData->GetType() == PDFObjectType_Dictionary )
     {
         CPLDebug("PDF", "Found PointData");
     }
@@ -1981,7 +2245,9 @@ void GDALRegister_PDF()
                                    "frmt_pdf.html" );
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pdf" );
 
+#ifdef USE_POPPLER
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+#endif
 
         poDriver->pfnOpen = PDFDataset::Open;
         poDriver->pfnIdentify = PDFDataset::Identify;
diff --git a/frmts/pdf/pdfio.cpp b/frmts/pdf/pdfio.cpp
index f63c40a..4889e7b 100644
--- a/frmts/pdf/pdfio.cpp
+++ b/frmts/pdf/pdfio.cpp
@@ -27,6 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifdef USE_POPPLER
+
 /* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef bool GBool" */
 /* in include/poppler/goo/gtypes.h with the one defined in cpl_port.h */
 #define CPL_GBOOL_DEFINED
@@ -35,7 +37,7 @@
 
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: pdfio.cpp 21328 2010-12-29 17:34:21Z rouault $");
+CPL_CVSID("$Id: pdfio.cpp 22491 2011-06-03 16:04:53Z rouault $");
 
 /************************************************************************/
 /*                         VSIPDFFileStream()                           */
@@ -305,3 +307,5 @@ void VSIPDFFileStream::moveStart(int delta)
     VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
     nPosInBuffer = nBufferLength = -1;
 }
+
+#endif
diff --git a/frmts/pdf/pdfobject.cpp b/frmts/pdf/pdfobject.cpp
new file mode 100644
index 0000000..e439570
--- /dev/null
+++ b/frmts/pdf/pdfobject.cpp
@@ -0,0 +1,460 @@
+/******************************************************************************
+ * $Id: pdfobject.cpp 22503 2011-06-04 22:08:34Z 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
+ *
+ * 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.
+ ****************************************************************************/
+
+/* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef bool GBool" */
+/* in include/poppler/goo/gtypes.h with the one defined in cpl_port.h */
+#define CPL_GBOOL_DEFINED
+
+#include <vector>
+#include "pdfobject.h"
+
+CPL_CVSID("$Id: pdfobject.cpp 22503 2011-06-04 22:08:34Z rouault $");
+
+GDALPDFObject::~GDALPDFObject()
+{
+}
+
+GDALPDFDictionary::~GDALPDFDictionary()
+{
+}
+
+GDALPDFArray::~GDALPDFArray()
+{
+}
+
+#ifdef USE_POPPLER
+
+class GDALPDFDictionaryPoppler: public GDALPDFDictionary
+{
+    private:
+        Dict* m_poDict;
+        std::map<CPLString, GDALPDFObject*> m_map;
+
+    public:
+        GDALPDFDictionaryPoppler(Dict* poDict) : m_poDict(poDict) {}
+        virtual ~GDALPDFDictionaryPoppler();
+
+        virtual GDALPDFObject* Get(const char* pszKey);
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues();
+};
+
+class GDALPDFArrayPoppler : public GDALPDFArray
+{
+    private:
+        Array* m_poArray;
+        std::vector<GDALPDFObject*> m_v;
+
+    public:
+        GDALPDFArrayPoppler(Array* poArray) : m_poArray(poArray) {}
+        virtual ~GDALPDFArrayPoppler();
+
+        virtual int GetLength();
+        virtual GDALPDFObject* Get(int nIndex);
+};
+
+GDALPDFObjectPoppler::~GDALPDFObjectPoppler()
+{
+    m_po->free();
+    if (m_bDestroy)
+        delete m_po;
+    delete m_poDict;
+    delete m_poArray;
+}
+
+GDALPDFObjectType GDALPDFObjectPoppler::GetType()
+{
+    switch(m_po->getType())
+    {
+        case objInt:        return PDFObjectType_Int;
+        case objReal:       return PDFObjectType_Real;
+        case objString:     return PDFObjectType_String;
+        case objName:       return PDFObjectType_Name;
+        case objArray:      return PDFObjectType_Array;
+        case objDict:       return PDFObjectType_Dictionary;
+        case objStream:     return PDFObjectType_Dictionary;
+        default:            return PDFObjectType_Unknown;
+    }
+}
+
+const char* GDALPDFObjectPoppler::GetTypeName()
+{
+    return m_po->getTypeName();
+}
+
+int GDALPDFObjectPoppler::GetInt()
+{
+    if (GetType() == PDFObjectType_Int)
+        return m_po->getInt();
+    else
+        return 0;
+}
+
+double GDALPDFObjectPoppler::GetReal()
+{
+    if (GetType() == PDFObjectType_Real)
+        return m_po->getReal();
+    else
+        return 0.0;
+}
+
+const CPLString& GDALPDFObjectPoppler::GetString()
+{
+    if (GetType() == PDFObjectType_String)
+        return (osStr = m_po->getString()->getCString());
+    else
+        return (osStr = "");
+}
+
+const CPLString& GDALPDFObjectPoppler::GetName()
+{
+    if (GetType() == PDFObjectType_Name)
+        return (osStr = m_po->getName());
+    else
+        return (osStr = "");
+}
+
+GDALPDFDictionary* GDALPDFObjectPoppler::GetDictionary()
+{
+    if (GetType() != PDFObjectType_Dictionary)
+        return NULL;
+
+    if (m_poDict)
+        return m_poDict;
+
+    Dict* poDict = (m_po->getType() == objStream) ? m_po->getStream()->getDict() : m_po->getDict();
+    if (poDict == NULL)
+        return NULL;
+    m_poDict = new GDALPDFDictionaryPoppler(poDict);
+    return m_poDict;
+}
+
+GDALPDFArray* GDALPDFObjectPoppler::GetArray()
+{
+    if (GetType() != PDFObjectType_Array)
+        return NULL;
+
+    if (m_poArray)
+        return m_poArray;
+
+    Array* poArray = m_po->getArray();
+    if (poArray == NULL)
+        return NULL;
+    m_poArray = new GDALPDFArrayPoppler(poArray);
+    return m_poArray;
+}
+
+GDALPDFDictionaryPoppler::~GDALPDFDictionaryPoppler()
+{
+    std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.begin();
+    std::map<CPLString, GDALPDFObject*>::iterator oEnd = m_map.end();
+    for(; oIter != oEnd; ++oIter)
+        delete oIter->second;
+}
+
+GDALPDFObject* GDALPDFDictionaryPoppler::Get(const char* pszKey)
+{
+    std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
+    if (oIter != m_map.end())
+        return oIter->second;
+
+    Object* po = new Object;
+    if (m_poDict->lookup((char*)pszKey, po) && !po->isNull())
+    {
+         GDALPDFObjectPoppler* poObj = new GDALPDFObjectPoppler(po, TRUE);
+         m_map[pszKey] = poObj;
+         return poObj;
+    }
+    else
+    {
+        delete po;
+        return NULL;
+    }
+}
+
+std::map<CPLString, GDALPDFObject*>& GDALPDFDictionaryPoppler::GetValues()
+{
+    int i = 0;
+    int nLength = m_poDict->getLength();
+    for(i=0;i<nLength;i++)
+    {
+        Get((const char*)m_poDict->getKey(i));
+    }
+    return m_map;
+}
+
+GDALPDFArrayPoppler::~GDALPDFArrayPoppler()
+{
+    for(int i=0;i<(int)m_v.size();i++)
+    {
+        delete m_v[i];
+    }
+}
+
+int GDALPDFArrayPoppler::GetLength()
+{
+    return m_poArray->getLength();
+}
+
+GDALPDFObject* GDALPDFArrayPoppler::Get(int nIndex)
+{
+    if (nIndex < 0 || nIndex >= GetLength())
+        return NULL;
+
+    int nOldSize = (int)m_v.size();
+    if (nIndex >= nOldSize)
+    {
+        m_v.resize(nIndex+1);
+        for(int i=nOldSize;i<=nIndex;i++)
+        {
+            m_v[i] = NULL;
+        }
+    }
+
+    if (m_v[nIndex] != NULL)
+        return m_v[nIndex];
+
+    Object* po = new Object;
+    if (m_poArray->get(nIndex, po) && !po->isNull())
+    {
+        GDALPDFObjectPoppler* poObj = new GDALPDFObjectPoppler(po, TRUE);
+        m_v[nIndex] = poObj;
+        return poObj;
+    }
+    else
+    {
+        delete po;
+        return NULL;
+    }
+}
+
+#else
+
+class GDALPDFDictionaryPodofo: public GDALPDFDictionary
+{
+    private:
+        PoDoFo::PdfDictionary* m_poDict;
+        PoDoFo::PdfVecObjects& m_poObjects;
+        std::map<CPLString, GDALPDFObject*> m_map;
+
+    public:
+        GDALPDFDictionaryPodofo(PoDoFo::PdfDictionary* poDict, PoDoFo::PdfVecObjects& poObjects) : m_poDict(poDict), m_poObjects(poObjects) {}
+        virtual ~GDALPDFDictionaryPodofo();
+
+        virtual GDALPDFObject* Get(const char* pszKey);
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues();
+};
+
+class GDALPDFArrayPodofo : public GDALPDFArray
+{
+    private:
+        PoDoFo::PdfArray* m_poArray;
+        PoDoFo::PdfVecObjects& m_poObjects;
+        std::vector<GDALPDFObject*> m_v;
+
+    public:
+        GDALPDFArrayPodofo(PoDoFo::PdfArray* poArray, PoDoFo::PdfVecObjects& poObjects) : m_poArray(poArray), m_poObjects(poObjects) {}
+        virtual ~GDALPDFArrayPodofo();
+
+        virtual int GetLength();
+        virtual GDALPDFObject* Get(int nIndex);
+};
+
+GDALPDFObjectPodofo::GDALPDFObjectPodofo(PoDoFo::PdfObject* po, PoDoFo::PdfVecObjects& poObjects) :
+        m_po(po), m_poObjects(poObjects), m_poDict(NULL), m_poArray(NULL)
+{
+    if (m_po->GetDataType() == PoDoFo::ePdfDataType_Reference)
+    {
+        PoDoFo::PdfObject* poObj = m_poObjects.GetObject(m_po->GetReference());
+        if (poObj)
+            m_po = poObj;
+    }
+}
+
+GDALPDFObjectPodofo::~GDALPDFObjectPodofo()
+{
+    delete m_poDict;
+    delete m_poArray;
+}
+
+GDALPDFObjectType GDALPDFObjectPodofo::GetType()
+{
+    switch(m_po->GetDataType())
+    {
+        case PoDoFo::ePdfDataType_Bool:       return PDFObjectType_Int;
+        case PoDoFo::ePdfDataType_Number:     return PDFObjectType_Int;
+        case PoDoFo::ePdfDataType_Real:       return PDFObjectType_Real;
+        case PoDoFo::ePdfDataType_String:     return PDFObjectType_String;
+        case PoDoFo::ePdfDataType_Name:       return PDFObjectType_Name;
+        case PoDoFo::ePdfDataType_Array:      return PDFObjectType_Array;
+        case PoDoFo::ePdfDataType_Dictionary: return PDFObjectType_Dictionary;
+        default:                              return PDFObjectType_Unknown;
+    }
+}
+
+const char* GDALPDFObjectPodofo::GetTypeName()
+{
+    return m_po->GetDataTypeString();
+}
+
+int GDALPDFObjectPodofo::GetInt()
+{
+    if (m_po->GetDataType() == PoDoFo::ePdfDataType_Bool)
+        return m_po->GetBool();
+    else if (m_po->GetDataType() == PoDoFo::ePdfDataType_Number)
+        return (int)m_po->GetNumber();
+    else
+        return 0;
+}
+
+double GDALPDFObjectPodofo::GetReal()
+{
+    if (GetType() == PDFObjectType_Real)
+        return m_po->GetReal();
+    else
+        return 0.0;
+}
+
+const CPLString& GDALPDFObjectPodofo::GetString()
+{
+    if (GetType() == PDFObjectType_String)
+        return (osStr = m_po->GetString().GetStringUtf8());
+    else
+        return (osStr = "");
+}
+
+const CPLString&  GDALPDFObjectPodofo::GetName()
+{
+    if (GetType() == PDFObjectType_Name)
+        return (osStr = m_po->GetName().GetName());
+    else
+        return (osStr = "");
+}
+
+GDALPDFDictionary* GDALPDFObjectPodofo::GetDictionary()
+{
+    if (GetType() != PDFObjectType_Dictionary)
+        return NULL;
+
+    if (m_poDict)
+        return m_poDict;
+
+    m_poDict = new GDALPDFDictionaryPodofo(&m_po->GetDictionary(), m_poObjects);
+    return m_poDict;
+}
+
+GDALPDFArray* GDALPDFObjectPodofo::GetArray()
+{
+    if (GetType() != PDFObjectType_Array)
+        return NULL;
+
+    if (m_poArray)
+        return m_poArray;
+
+    m_poArray = new GDALPDFArrayPodofo(&m_po->GetArray(), m_poObjects);
+    return m_poArray;
+}
+
+GDALPDFDictionaryPodofo::~GDALPDFDictionaryPodofo()
+{
+    std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.begin();
+    std::map<CPLString, GDALPDFObject*>::iterator oEnd = m_map.end();
+    for(; oIter != oEnd; ++oIter)
+        delete oIter->second;
+}
+
+GDALPDFObject* GDALPDFDictionaryPodofo::Get(const char* pszKey)
+{
+    std::map<CPLString, GDALPDFObject*>::iterator oIter = m_map.find(pszKey);
+    if (oIter != m_map.end())
+        return oIter->second;
+
+    PoDoFo::PdfObject* poVal = m_poDict->GetKey(PoDoFo::PdfName(pszKey));
+    if (poVal)
+    {
+         GDALPDFObjectPodofo* poObj = new GDALPDFObjectPodofo(poVal, m_poObjects);
+         m_map[pszKey] = poObj;
+         return poObj;
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+std::map<CPLString, GDALPDFObject*>& GDALPDFDictionaryPodofo::GetValues()
+{
+    PoDoFo::TKeyMap::iterator oIter = m_poDict->GetKeys().begin();
+    PoDoFo::TKeyMap::iterator oEnd = m_poDict->GetKeys().end();
+    for( ; oIter != oEnd; ++oIter)
+    {
+        const char* pszKey = oIter->first.GetName().c_str();
+        Get(pszKey);
+    }
+
+    return m_map;
+}
+
+GDALPDFArrayPodofo::~GDALPDFArrayPodofo()
+{
+    for(int i=0;i<(int)m_v.size();i++)
+    {
+        delete m_v[i];
+    }
+}
+
+int GDALPDFArrayPodofo::GetLength()
+{
+    return (int)m_poArray->GetSize();
+}
+
+GDALPDFObject* GDALPDFArrayPodofo::Get(int nIndex)
+{
+    if (nIndex < 0 || nIndex >= GetLength())
+        return NULL;
+
+    int nOldSize = (int)m_v.size();
+    if (nIndex >= nOldSize)
+    {
+        m_v.resize(nIndex+1);
+        for(int i=nOldSize;i<=nIndex;i++)
+        {
+            m_v[i] = NULL;
+        }
+    }
+
+    if (m_v[nIndex] != NULL)
+        return m_v[nIndex];
+
+    PoDoFo::PdfObject& oVal = (*m_poArray)[nIndex];
+    GDALPDFObjectPodofo* poObj = new GDALPDFObjectPodofo(&oVal, m_poObjects);
+    m_v[nIndex] = poObj;
+    return poObj;
+}
+
+#endif
diff --git a/frmts/pdf/pdfobject.h b/frmts/pdf/pdfobject.h
new file mode 100644
index 0000000..5a9e1f8
--- /dev/null
+++ b/frmts/pdf/pdfobject.h
@@ -0,0 +1,171 @@
+/******************************************************************************
+ * $Id: pdfobject.h 22503 2011-06-04 22:08:34Z 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
+ *
+ * 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 PDFOBJECT_H_INCLUDED
+#define PDFOBJECT_H_INCLUDED
+
+#include "cpl_string.h"
+#include <map>
+
+#ifdef USE_POPPLER
+
+/* begin of poppler xpdf includes */
+#include <poppler/Object.h>
+
+#define private public /* Ugly! Page::pageObj is private but we need it... */
+#include <poppler/Page.h>
+#undef private
+
+#include <poppler/Dict.h>
+
+#define private public /* Ugly! Catalog::optContent is private but we need it... */
+#include <poppler/Catalog.h>
+#undef private
+
+#define private public  /* Ugly! PDFDoc::str is private but we need it... */
+#include <poppler/PDFDoc.h>
+#undef private
+
+#include <poppler/splash/SplashBitmap.h>
+#include <poppler/splash/Splash.h>
+#include <poppler/SplashOutputDev.h>
+#include <poppler/GlobalParams.h>
+#include <poppler/ErrorCodes.h>
+/* end of poppler xpdf includes */
+
+#else
+
+#include "podofo.h"
+
+#endif
+
+typedef enum
+{
+    PDFObjectType_Unknown,
+    PDFObjectType_Int,
+    PDFObjectType_Real,
+    PDFObjectType_String,
+    PDFObjectType_Name,
+    PDFObjectType_Array,
+    PDFObjectType_Dictionary
+} GDALPDFObjectType;
+
+class GDALPDFDictionary;
+class GDALPDFArray;
+
+class GDALPDFObject
+{
+    public:
+        virtual ~GDALPDFObject();
+
+        virtual GDALPDFObjectType GetType() = 0;
+        virtual const char*       GetTypeName() = 0;
+        virtual int               GetInt() = 0;
+        virtual double            GetReal() = 0;
+        virtual const CPLString&  GetString() = 0;
+        virtual const CPLString&  GetName() = 0;
+        virtual GDALPDFDictionary*  GetDictionary() = 0;
+        virtual GDALPDFArray*       GetArray() = 0;
+};
+
+class GDALPDFDictionary
+{
+    public:
+        virtual ~GDALPDFDictionary();
+
+        virtual GDALPDFObject* Get(const char* pszKey) = 0;
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues() = 0;
+
+};
+
+class GDALPDFArray
+{
+    public:
+        virtual ~GDALPDFArray();
+
+        virtual int GetLength() = 0;
+        virtual GDALPDFObject* Get(int nIndex) = 0;
+};
+
+
+#ifdef USE_POPPLER
+
+class GDALPDFObjectPoppler : public GDALPDFObject
+{
+    private:
+        Object* m_po;
+        int     m_bDestroy;
+        GDALPDFDictionary* m_poDict;
+        GDALPDFArray* m_poArray;
+        CPLString osStr;
+
+    public:
+        GDALPDFObjectPoppler(Object* po, int bDestroy) : m_po(po), m_bDestroy(bDestroy), m_poDict(NULL), m_poArray(NULL) {}
+
+        virtual ~GDALPDFObjectPoppler();
+
+        virtual GDALPDFObjectType GetType();
+        virtual const char*       GetTypeName();
+        virtual int               GetInt();
+        virtual double            GetReal();
+        virtual const CPLString&  GetString();
+        virtual const CPLString&  GetName();
+        virtual GDALPDFDictionary*  GetDictionary();
+        virtual GDALPDFArray*       GetArray();
+};
+
+#else
+
+class GDALPDFObjectPodofo : public GDALPDFObject
+{
+    private:
+        PoDoFo::PdfObject* m_po;
+        PoDoFo::PdfVecObjects& m_poObjects;
+        GDALPDFDictionary* m_poDict;
+        GDALPDFArray* m_poArray;
+        CPLString osStr;
+
+    public:
+        GDALPDFObjectPodofo(PoDoFo::PdfObject* po, PoDoFo::PdfVecObjects& poObjects);
+
+        virtual ~GDALPDFObjectPodofo();
+
+        virtual GDALPDFObjectType GetType();
+        virtual const char*       GetTypeName();
+        virtual int               GetInt();
+        virtual double            GetReal();
+        virtual const CPLString&  GetString();
+        virtual const CPLString&  GetName();
+        virtual GDALPDFDictionary*  GetDictionary();
+        virtual GDALPDFArray*       GetArray();
+};
+
+#endif
+
+#endif // PDFOBJECT_H_INCLUDED
diff --git a/frmts/pds/frmt_isis2.html b/frmts/pds/frmt_isis2.html
new file mode 100644
index 0000000..3d7a392
--- /dev/null
+++ b/frmts/pds/frmt_isis2.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+<title>ISIS2 -- USGS Astrogeology ISIS Cube (Version 2)</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ISIS2 -- USGS Astrogeology ISIS Cube (Version 2)</h1>
+
+ISIS2 is a format used by the USGS Planetary Cartography group
+to store and distribute planetary imagery data.  GDAL provides read
+and write access to ISIS2 formatted imagery data.<p>
+
+ISIS2 files often have the extension .cub, sometimes with an associated
+.lbl (label) file.  When a .lbl file exists it should be used as
+the dataset name rather than the .cub file.<p>
+
+In addition to support for most ISIS2 imagery configurations, this
+driver also reads georeferencing and coordinate system information
+as well as selected other header metadata.<p>
+
+Implementation of this driver was supported by the United States
+Geological Survey.<p>
+
+ISIS2 is part of a family of related formats including PDS and ISIS3.<p>
+
+<h2>Creation Issues</h2>
+
+Currently the ISIS2 writer writes a very minimal header with only the
+image structure information.  No coordinate system, georeferencing or
+other metadata is captured.<p>
+
+<h3>Creation Options</h3>
+
+<ul>
+
+<li><p><b>LABELING_METHOD=ATTACHED/DETACHED</b>: Determines whether the 
+header labelling should be in the same file as the imagery (the default - ATTACHED)
+or in a separate file (DETACHED).</p></li>
+<li><p><b>IMAGE_EXTENSION=<i>extension</i></b>: Set the extension used
+for detached image files, defaults to "cub".  Only used if LABELING_METHOD=DETACHED.</p></li>
+</ul>
+
+<h2>See Also:</h2>
+
+<ul>
+<li> Implemented as <tt>gdal/frmts/pds/isis2dataset.cpp</tt>.
+<li> <a href="frmt_pds.html">GDAL PDS Driver</a>
+<li> <a href="frmt_isis3.html">GDAL ISIS3 Driver</a>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/pds/frmt_isis3.html b/frmts/pds/frmt_isis3.html
new file mode 100644
index 0000000..e842aae
--- /dev/null
+++ b/frmts/pds/frmt_isis3.html
@@ -0,0 +1,37 @@
+<html>
+<head>
+<title>ISIS3 -- USGS Astrogeology ISIS Cube (Version 3)</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ISIS3 -- USGS Astrogeology ISIS Cube (Version 3)</h1>
+
+ISIS3 is a format used by the USGS Planetary Cartography group
+to store and distribute planetary imagery data.  GDAL provides 
+read-only access to ISIS3 formatted imagery data.<p>
+
+ISIS3 files often have the extension .cub, sometimes with an associated
+.lbl (label) file.  When a .lbl file exists it should be used as
+the dataset name rather than the .cub file.<p>
+
+In addition to support for most ISIS3 imagery configurations, this
+driver also reads georeferencing and coordinate system information
+as well as selected other header metadata.<p>
+
+Implementation of this driver was supported by the United States
+Geological Survey.<p>
+
+ISIS3 is part of a family of related formats including PDS and ISIS2.<p>
+
+
+<h2>See Also:</h2>
+
+<ul>
+<li> Implemented as <tt>gdal/frmts/pds/isis2dataset.cpp</tt>.
+<li> <a href="frmt_pds.html">GDAL PDS Driver</a>
+<li> <a href="frmt_isis2.html">GDAL ISIS2 Driver</a>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/pds/frmt_pds.html b/frmts/pds/frmt_pds.html
new file mode 100644
index 0000000..973cef5
--- /dev/null
+++ b/frmts/pds/frmt_pds.html
@@ -0,0 +1,44 @@
+<html>
+<head>
+<title>PDS -- Planetary Data System</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>PDS -- Planetary Data System</h1>
+
+PDS is a format used primarily by NASA to store and distribute 
+solar, lunar and planetary imagery data.  GDAL provides read-only
+access to PDS formatted imagery data.<p>
+
+PDS files often have the extension .img, sometimes with an associated
+.lbl (label) file.  When a .lbl file exists it should be used as
+the dataset name rather than the .img file.<p>
+
+In addition to support for most PDS imagery configurations, this
+driver also reads georeferencing and coordinate system information
+as well as selected other header metadata.<p>
+
+Implementation of this driver was supported by the United States
+Geological Survey.<p>
+
+Due to abiguitities in the PDS specification, the georeferencing of 
+some products is subtly or grossly incorrect.  There are configuration
+variables which may be set for these products to correct the interpretation
+of the georeferencing.  Some details are available in 
+<a href="http://trac.osgeo.org/gdal/ticket/3940">ticket #3940</a>.<p>
+
+
+PDS is part of a family of related formats including ISIS2 and ISIS3.<p>
+
+<h2>See Also:</h2>
+
+<ul>
+<li> Implemented as <tt>gdal/frmts/pds/pdsdataset.cpp</tt>.
+<li> <a href="http://pds.nasa.gov/">NASA Planetary Data System</a>
+<li> <a href="frmt_isis2.html">GDAL ISIS2 Driver</a>
+<li> <a href="frmt_isis3.html">GDAL ISIS3 Driver</a>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/pds/isis2dataset.cpp b/frmts/pds/isis2dataset.cpp
index 49f861e..ff9b0b5 100644
--- a/frmts/pds/isis2dataset.cpp
+++ b/frmts/pds/isis2dataset.cpp
@@ -1,10 +1,12 @@
 /******************************************************************************
- * $Id: isis2dataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: isis2dataset.cpp 23371 2011-11-13 14:24:00Z rouault $
  *
  * Project:  ISIS Version 2 Driver
  * Purpose:  Implementation of ISIS2Dataset
  * Author:   Trent Hare (thare at usgs.gov),
  *           Robert Soricone (rsoricone at usgs.gov)
+ *           Ludovic Mercier (ludovic.mercier at gmail.com) 
+ *           Frank Warmerdam (warmerdam at pobox.com)
  *
  * NOTE: Original code authored by Trent and Robert and placed in the public 
  * domain as per US government policy.  I have (within my rights) appropriated 
@@ -34,21 +36,20 @@
 
 #define NULL1 0
 #define NULL2 -32768
-//#define NULL3 0xFF7FFFFB //in hex
-//Same as ESRI_GRID_FLOAT_NO_DATA
-//#define NULL3 -340282346638528859811704183484516925440.0
 #define NULL3 -3.4028226550889044521e+38
 
 #ifndef PI
 #  define PI 3.1415926535897932384626433832795
 #endif
 
+#define RECORD_SIZE 512
+
 #include "rawdataset.h"
 #include "ogr_spatialref.h"
 #include "cpl_string.h" 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: isis2dataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: isis2dataset.cpp 23371 2011-11-13 14:24:00Z rouault $");
 
 CPL_C_START
 void	GDALRegister_ISIS2(void);
@@ -63,6 +64,7 @@ CPL_C_END
 class ISIS2Dataset : public RawDataset
 {
     VSILFILE	*fpImage;	// image data file.
+    CPLString    osExternalCube;
 
     NASAKeywordHandler  oKeywords;
   
@@ -87,14 +89,29 @@ class ISIS2Dataset : public RawDataset
 public:
     ISIS2Dataset();
     ~ISIS2Dataset();
-  
+
     virtual CPLErr GetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef(void);
   
+    virtual char **GetFileList();
+
+    static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
+
+    // Write related.
+    static int WriteRaster(CPLString osFilename, bool includeLabel, GUIntBig iRecord, GUIntBig iLabelRecords, GDALDataType eType, const char * pszInterleaving);
+
+    static int WriteLabel(CPLString osFilename, CPLString osRasterFile, CPLString sObjectTag, unsigned int nXSize, unsigned int nYSize, unsigned int nBands, GDALDataType eType,
+    						GUIntBig iRecords, const char * pszInterleaving, GUIntBig & iLabelRecords, bool bRelaunch=false);
+    static int WriteQUBE_Information(VSILFILE *fpLabel, unsigned int iLevel, unsigned int & nWritingBytes,
+                                     unsigned int nXSize, unsigned int nYSize, unsigned int nBands, GDALDataType eType, const char * pszInterleaving);
+
+    static unsigned int WriteKeyword(VSILFILE *fpLabel, unsigned int iLevel, CPLString key, CPLString value);
+    static unsigned int WriteFormatting(VSILFILE *fpLabel, CPLString data);
+    static GUIntBig RecordSizeCalculation(unsigned int nXSize, unsigned int nYSize, unsigned int nBands, GDALDataType eType );
 };
 
 /************************************************************************/
@@ -126,6 +143,23 @@ ISIS2Dataset::~ISIS2Dataset()
 }
 
 /************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **ISIS2Dataset::GetFileList()
+
+{
+    char **papszFileList = NULL;
+
+    papszFileList = GDALPamDataset::GetFileList();
+
+    if( strlen(osExternalCube) > 0 )
+        papszFileList = CSLAddString( papszFileList, osExternalCube );
+
+    return papszFileList;
+}
+
+/************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
@@ -157,16 +191,31 @@ CPLErr ISIS2Dataset::GetGeoTransform( double * padfTransform )
 }
 
 /************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+
+int ISIS2Dataset::Identify( GDALOpenInfo * poOpenInfo )
+{
+    if( poOpenInfo->pabyHeader == NULL )
+        return FALSE;
+
+    if( strstr((const char *)poOpenInfo->pabyHeader,"^QUBE") == NULL )
+        return FALSE;
+    else
+        return TRUE;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
 GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 {
 /* -------------------------------------------------------------------- */
-/*      Does this look like a CUBE dataset?                             */
+/*      Does this look like a CUBE or an IMAGE Primary Data Object?     */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->pabyHeader == NULL
-        || strstr((const char *)poOpenInfo->pabyHeader,"^QUBE") == NULL )
+    if( !Identify( poOpenInfo ) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -199,13 +248,35 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     // ^QUBE = "ui31s015.img" - which implies no label or skip value
 
     const char *pszQube = poDS->GetKeyword( "^QUBE" );
-    int nQube = atoi(pszQube);
-
-    if( pszQube[0] == '"' || pszQube[0] == '(' )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "ISIS2 driver does not support detached images." );
-        return NULL;
+    GUIntBig nQube = 0;
+    int bByteLocation = FALSE;
+    CPLString osTargetFile = poOpenInfo->pszFilename;
+
+    if( pszQube[0] == '"' )
+    { 
+        CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); 
+        CPLString osFilename = pszQube;
+        poDS->CleanString( osFilename ); 
+        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); 
+        poDS->osExternalCube = osTargetFile;
+    }
+    else if( pszQube[0] == '(' ) 
+    { 
+        CPLString osTPath = CPLGetPath(poOpenInfo->pszFilename); 
+        CPLString osFilename = poDS->GetKeywordSub("^QUBE",1,""); 
+        poDS->CleanString( osFilename ); 
+        osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL ); 
+        poDS->osExternalCube = osTargetFile;
+
+        nQube = atoi(poDS->GetKeywordSub("^QUBE",2,"1"));
+        if( strstr(poDS->GetKeywordSub("^QUBE",2,"1"),"<BYTES>") != NULL )
+            bByteLocation = true;
+    } 
+    else 
+    { 
+        nQube = atoi(pszQube);
+        if( strstr(pszQube,"<BYTES>") != NULL )
+            bByteLocation = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -217,7 +288,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     //image parameters
     int	nRows, nCols, nBands = 1;
-    int nSkipBytes = 0;
+    GUIntBig nSkipBytes = 0;
     int itype;
     int  s_ix, s_iy, s_iz; // check SUFFIX_ITEMS params.
     int record_bytes;
@@ -238,10 +309,10 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     double semi_major = 0.0;
     double semi_minor = 0.0;
     double iflattening = 0.0;
-    float center_lat = 0.0;
-    float center_lon = 0.0;
-    float first_std_parallel = 0.0;
-    float second_std_parallel = 0.0;
+    double center_lat = 0.0;
+    double center_lon = 0.0;
+    double first_std_parallel = 0.0;
+    double second_std_parallel = 0.0;
     VSILFILE	*fp;
 
     /* -------------------------------------------------------------------- */
@@ -258,6 +329,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
                   "*** ISIS 2 cube file has invalid SUFFIX_ITEMS parameters:\n"
                   "*** gdal isis2 driver requires (0, 0, 0), thus no sideplanes or backplanes\n"
                   "found: (%i, %i, %i)\n\n", s_ix, s_iy, s_iz );
+        delete poDS;
         return NULL;
     } 
 
@@ -280,6 +352,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     else {
         CPLError( CE_Failure, CPLE_OpenFailed, 
                   "%s layout not supported. Abort\n\n", value);
+        delete poDS;
         return NULL;
     }
 
@@ -291,11 +364,21 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     /***********   Grab Qube record bytes  **********/
     record_bytes = atoi(poDS->GetKeyword("RECORD_BYTES"));
 
-    if (nQube > 0)
+    if (nQube > 0 && bByteLocation )
+        nSkipBytes = (nQube - 1);
+    else if( nQube > 0 )
         nSkipBytes = (nQube - 1) * record_bytes;     
     else
         nSkipBytes = 0;     
      
+    /***********   Grab samples lines band ************/
+    CPLString osCoreItemType = poDS->GetKeyword( "QUBE.CORE_ITEM_TYPE" );
+    if( (EQUAL(osCoreItemType,"PC_INTEGER")) || 
+        (EQUAL(osCoreItemType,"PC_UNSIGNED_INTEGER")) || 
+        (EQUAL(osCoreItemType,"PC_REAL")) ) {
+        chByteOrder = 'I';
+    }
+    
     /********   Grab format type - isis2 only supports 8,16,32 *******/
     itype = atoi(poDS->GetKeyword("QUBE.CORE_ITEM_BYTES",""));
     switch(itype) {
@@ -305,8 +388,16 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         bNoDataSet = TRUE;
         break;
       case 2 :
-        eDataType = GDT_Int16;
-        dfNoData = NULL2;
+        if( strstr(osCoreItemType,"UNSIGNED") != NULL )
+        {
+            dfNoData = 0;
+            eDataType = GDT_UInt16;
+        }
+        else
+        {
+            dfNoData = NULL2;
+            eDataType = GDT_Int16;
+        }
         bNoDataSet = TRUE;
         break;
       case 4 :
@@ -314,6 +405,11 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         dfNoData = NULL3;
         bNoDataSet = TRUE;
         break;
+      case 8 :
+        eDataType = GDT_Float64;
+        dfNoData = NULL3;
+        bNoDataSet = TRUE;
+        break;
       default :
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Itype of %d is not supported in ISIS 2.",
@@ -322,14 +418,6 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    /***********   Grab samples lines band ************/
-    value = poDS->GetKeyword( "QUBE.CORE_ITEM_TYPE" );
-    if( (EQUAL(value,"PC_INTEGER")) || 
-        (EQUAL(value,"PC_UNSIGNED_INTEGER")) || 
-        (EQUAL(value,"PC_REAL")) ) {
-        chByteOrder = 'I';
-    }
-    
     /***********   Grab Cellsize ************/
     value = poDS->GetKeyword("QUBE.IMAGE_MAP_PROJECTION.MAP_SCALE");
     if (strlen(value) > 0 ) {
@@ -415,6 +503,9 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         oSRS.OGRSpatialReference::SetTM ( center_lat, center_lon, 1, 0, 0 );
     } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) {
         oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 );
+    } else if (EQUAL( map_proj_name, "") ) {
+        /* no projection */
+        bProjectionSet = FALSE;
     } else {
         CPLDebug( "ISIS2",
                   "Dataset projection %s is not supported. Continuing...",
@@ -523,6 +614,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( nRows < 1 || nCols < 1 || nBands < 1 )
     {
+        delete poDS;
         return NULL;
     }
 
@@ -537,15 +629,15 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     
     if( poOpenInfo->eAccess == GA_ReadOnly )
-        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+        poDS->fpImage = VSIFOpenL( osTargetFile, "rb" );
     else
-        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
+        poDS->fpImage = VSIFOpenL( osTargetFile, "r+b" );
 
     if( poDS->fpImage == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
                   "Failed to open %s with write permission.\n%s", 
-                  poOpenInfo->pszFilename, VSIStrerror( errno ) );
+                  osTargetFile.c_str(), VSIStrerror( errno ) );
         delete poDS;
         return NULL;
     }
@@ -751,27 +843,372 @@ void ISIS2Dataset::CleanString( CPLString &osInput )
 }
 
 /************************************************************************/
-/*                         GDALRegister_ISIS2()                         */
+/*                           Create()                                   */
 /************************************************************************/
+/**
+ * Hidden Creation Options:
+ * INTERLEAVE=BSQ/BIP/BIL: Force the generation specified type of interleaving.
+ *  BSQ --- band sequental (default),
+ *  BIP --- band interleaved by pixel,
+ *  BIL --- band interleaved by line.
+ * OBJECT=QUBE/IMAGE/SPECTRAL_QUBE, if null default is QUBE
+ */
+
+GDALDataset *ISIS2Dataset::Create(const char* pszFilename,
+                                  int nXSize, int nYSize, int nBands,
+                                  GDALDataType eType, char** papszParmList) {
+
+    /* Verify settings. In Isis 2 core pixel values can be represented in
+     * three different ways : 1, 2 4, or 8 Bytes */
+    if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_Float32
+        && eType != GDT_UInt16 && eType != GDT_Float64 ){
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The ISIS2 driver does not supporting creating files of type %s.",
+                 GDALGetDataTypeName( eType ) );
+        return NULL;
+    }
+
+    /*  (SAMPLE, LINE, BAND) - Band Sequential (BSQ) - default choice
+        (SAMPLE, BAND, LINE) - Band Interleaved by Line (BIL)
+        (BAND, SAMPLE, LINE) - Band Interleaved by Pixel (BIP) */
+    const char *pszInterleaving = "(SAMPLE,LINE,BAND)";
+    const char *pszInterleavingParam = CSLFetchNameValue( papszParmList, "INTERLEAVE" );
+    if ( pszInterleavingParam ) {
+        if ( EQUALN( pszInterleavingParam, "bip", 3 ) )
+            pszInterleaving = "(BAND,SAMPLE,LINE)";
+        else if ( EQUALN( pszInterleavingParam, "bil", 3 ) )
+            pszInterleaving = "(SAMPLE,BAND,LINE)";
+        else
+            pszInterleaving = "(SAMPLE,LINE,BAND)";
+    }
 
-void GDALRegister_ISIS2()
+    /* default labeling method is attached */
+    bool bAttachedLabelingMethod = true;
+    /* check if labeling method is set : check the all three first chars */
+    const char *pszLabelingMethod = CSLFetchNameValue( papszParmList, "LABELING_METHOD" );
+    if ( pszLabelingMethod ){
+        if ( EQUALN( pszLabelingMethod, "detached", 3 ) ){
+            bAttachedLabelingMethod = false;
+        }
+        if ( EQUALN( pszLabelingMethod, "attached", 3 ) ){
+            bAttachedLabelingMethod = true;
+        }
+    }
+
+    /*  set the label and data files */
+    CPLString osLabelFile, osRasterFile, osOutFile;
+    if( bAttachedLabelingMethod ) {
+        osLabelFile = "";
+        osRasterFile = pszFilename;
+        osOutFile = osRasterFile;
+    }
+    else
+    {
+        CPLString sExtension = "cub";
+        const char* pszExtension = CSLFetchNameValue( papszParmList, "IMAGE_EXTENSION" );
+        if( pszExtension ){
+            sExtension = pszExtension;
+        }
+
+        if( EQUAL(CPLGetExtension( pszFilename ), sExtension) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "IMAGE_EXTENSION (%s) cannot match LABEL file extension.",
+                      sExtension.c_str() );
+            return NULL;
+        }
+
+        osLabelFile = pszFilename;
+        osRasterFile = CPLResetExtension( osLabelFile, sExtension );
+        osOutFile = osLabelFile;
+    }
+
+    const char *pszObject = CSLFetchNameValue( papszParmList, "OBJECT" );
+    CPLString sObject = "QUBE"; // default choice
+    if (pszObject) {
+        if ( EQUAL( pszObject, "IMAGE") ){
+            sObject = "IMAGE";
+        }
+        if ( EQUAL( pszObject, "SPECTRAL_QUBE")){
+            sObject = "SPECTRAL_QUBE";
+        }
+    }
+
+    GUIntBig iRecords = ISIS2Dataset::RecordSizeCalculation(nXSize, nYSize, nBands, eType);
+    GUIntBig iLabelRecords(2);
+
+    CPLDebug("ISIS2","irecord = %i",static_cast<int>(iRecords));
+
+    if( bAttachedLabelingMethod ) 
+    {
+        ISIS2Dataset::WriteLabel(osRasterFile, "", sObject, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords, true);
+    }
+    else
+    {
+        ISIS2Dataset::WriteLabel(osLabelFile, osRasterFile, sObject, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords);
+    }
+
+    if( !ISIS2Dataset::WriteRaster(osRasterFile, bAttachedLabelingMethod, 
+                                   iRecords, iLabelRecords, eType, 
+                                   pszInterleaving) )
+        return NULL;
+
+    return (GDALDataset *) GDALOpen( osOutFile, GA_Update );
+}
+
+
+/************************************************************************/
+/*                            WriteRaster()                             */
+/************************************************************************/
+
+int ISIS2Dataset::WriteRaster(CPLString osFilename, bool includeLabel, GUIntBig iRecords, GUIntBig iLabelRecords, GDALDataType eType, const char * pszInterleaving) {
+    GUIntBig nSize;
+    GByte byZero(0);
+    CPLString pszAccess("wb");
+    if(includeLabel)
+        pszAccess = "ab";
+
+    VSILFILE *fpBin = VSIFOpenL( osFilename, pszAccess.c_str() );
+    if( fpBin == NULL ) {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to create %s:\n%s",
+                  osFilename.c_str(), VSIStrerror( errno ) );
+        return FALSE;
+    }
+
+    nSize = iRecords * RECORD_SIZE;
+    CPLDebug("ISIS2","nSize = %i", static_cast<int>(nSize));
+
+    if(includeLabel)
+        nSize = iLabelRecords * RECORD_SIZE + nSize;
+
+    // write last byte
+    if(VSIFSeekL( fpBin, nSize-1, SEEK_SET ) != 0 ||
+       VSIFWriteL( &byZero, 1, 1, fpBin ) != 1){
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to write %s:\n%s",
+                  osFilename.c_str(), VSIStrerror( errno ) );
+        VSIFCloseL( fpBin );
+        return FALSE;
+    }
+    VSIFCloseL( fpBin );
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       RecordSizeCalculation()                        */
+/************************************************************************/
+GUIntBig ISIS2Dataset::RecordSizeCalculation(unsigned int nXSize, unsigned int nYSize, unsigned int nBands, GDALDataType eType )
 
 {
-    GDALDriver	*poDriver;
+    GUIntBig n = nXSize * nYSize * nBands * (  GDALGetDataTypeSize(eType) / 8);
+    // size of pds file is a multiple of RECORD_SIZE Bytes.
+    CPLDebug("ISIS2","n = %i", static_cast<int>(n));
+    CPLDebug("ISIS2","RECORD SIZE = %i", RECORD_SIZE);
+    CPLDebug("ISIS2","nXSize = %i", nXSize);
+    CPLDebug("ISIS2","nYSize = %i", nYSize);
+    CPLDebug("ISIS2","nBands = %i", nBands);
+    CPLDebug("ISIS2","DataTypeSize = %i", GDALGetDataTypeSize(eType));
+    return (GUIntBig) ceil(static_cast<float>(n)/RECORD_SIZE);
+}
 
-    if( GDALGetDriverByName( "ISIS2" ) == NULL )
+/************************************************************************/
+/*                       WriteQUBE_Information()                        */
+/************************************************************************/
+
+int ISIS2Dataset::WriteQUBE_Information(
+    VSILFILE *fpLabel, unsigned int iLevel, unsigned int & nWritingBytes,
+    unsigned int nXSize,  unsigned int nYSize, unsigned int nBands, 
+    GDALDataType eType, const char * pszInterleaving)
+
+{
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "");
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "/* Qube structure */");
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "OBJECT", "QUBE");
+    iLevel++;
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "AXES", "3");
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "AXIS_NAME", pszInterleaving);
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "/* Core description */");
+
+    CPLDebug("ISIS2","%d,%d,%d",nXSize,nYSize,nBands);
+
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEMS",CPLString().Printf("(%d,%d,%d)",nXSize,nYSize,nBands));
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_NAME", "\"RAW DATA NUMBER\"");
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_UNIT", "\"N/A\"");
+    // TODO change for eType
+
+    if( eType == GDT_Byte ) 
     {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "ISIS2" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "USGS Astrogeology ISIS cube (Version 2)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#ISIS2" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_UNSIGNED_INTEGER");
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "1");
+    }
+    else if( eType == GDT_UInt16 ) 
+    {
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_UNSIGNED_INTEGER");
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "2");
+    }
+    else if( eType == GDT_Int16 ) 
+    {
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_INTEGER");
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "2");
+    }
+    else if( eType == GDT_Float32 )
+    {
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_REAL");
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "4");
+    }
+    else if( eType == GDT_Float64 )
+    {
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_TYPE", "PC_REAL");
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_ITEM_BYTES", "8");
+    }
+
+    // TODO add core null value
+
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_BASE", "0.0");
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "CORE_MULTIPLIER", "1.0");
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "/* Suffix description */");
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "SUFFIX_BYTES", "4");
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "SUFFIX_ITEMS", "( 0, 0, 0)");
+    iLevel--;
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "END_OBJECT", "QUBE");
+    
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             WriteLabel()                             */
+/*                                                                      */
+/*      osRasterFile : name of raster file but if it is empty we        */
+/*                     have only one file with an attached label        */
+/*      sObjectTag : QUBE, IMAGE or SPECTRAL_QUBE                       */
+/*      bRelaunch : flag to allow recursiv call                         */
+/************************************************************************/
+
+int ISIS2Dataset::WriteLabel(
+    CPLString osFilename, CPLString osRasterFile, CPLString sObjectTag,
+    unsigned int nXSize, unsigned int nYSize, unsigned int nBands, 
+    GDALDataType eType,
+    GUIntBig iRecords, const char * pszInterleaving, 
+    GUIntBig &iLabelRecords, bool bRelaunch)
 
-        poDriver->pfnOpen = ISIS2Dataset::Open;
+{
+    CPLDebug("ISIS2", "Write Label filename = %s, rasterfile = %s",osFilename.c_str(),osRasterFile.c_str());
+    bool bAttachedLabel = EQUAL(osRasterFile, "");
+
+    VSILFILE *fpLabel = VSIFOpenL( osFilename, "w" );
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
+    if( fpLabel == NULL ){
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to create %s:\n%s",
+                  osFilename.c_str(), VSIStrerror( errno ) );
+        return FALSE;
     }
+
+    unsigned int iLevel(0);
+    unsigned int nWritingBytes(0);
+
+    /* write common header */
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "PDS_VERSION_ID", "PDS3" );
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "");
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "/* File identification and structure */");
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "RECORD_TYPE", "FIXED_LENGTH" );
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "RECORD_BYTES", CPLString().Printf("%d",RECORD_SIZE));
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "FILE_RECORDS", CPLString().Printf(CPL_FRMT_GUIB,iRecords));
+    nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "LABEL_RECORDS", CPLString().Printf(CPL_FRMT_GUIB,iLabelRecords));
+    if(!bAttachedLabel){
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, "FILE_NAME", CPLGetFilename(osRasterFile));
+    }
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "");
+
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "/* Pointers to Data Objects */");
+
+    if(bAttachedLabel){
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, CPLString().Printf("^%s",sObjectTag.c_str()), CPLString().Printf(CPL_FRMT_GUIB,iLabelRecords+1));
+    }else{
+        nWritingBytes += ISIS2Dataset::WriteKeyword( fpLabel, iLevel, CPLString().Printf("^%s",sObjectTag.c_str()), CPLString().Printf("(\"%s\",1)",CPLGetFilename(osRasterFile)));
+    }
+
+    if(EQUAL(sObjectTag, "QUBE")){
+        ISIS2Dataset::WriteQUBE_Information(fpLabel, iLevel, nWritingBytes, nXSize, nYSize, nBands, eType, pszInterleaving);
+    }
+
+    nWritingBytes += ISIS2Dataset::WriteFormatting( fpLabel, "END");
+
+    // check if file record is correct
+    unsigned int q = nWritingBytes/RECORD_SIZE;
+    if( q <= iLabelRecords){
+        // correct we add space after the label end for complete from iLabelRecords
+        unsigned int nSpaceBytesToWrite = (unsigned int) (iLabelRecords * RECORD_SIZE - nWritingBytes);
+        VSIFPrintfL(fpLabel,"%*c", nSpaceBytesToWrite, ' ');
+    }else{
+        iLabelRecords = q+1;
+        ISIS2Dataset::WriteLabel(osFilename, osRasterFile, sObjectTag, nXSize, nYSize, nBands, eType, iRecords, pszInterleaving, iLabelRecords);
+    }
+    VSIFCloseL( fpLabel );
+  
+    return TRUE;
 }
+
+/************************************************************************/
+/*                            WriteKeyword()                            */
+/************************************************************************/
+
+    unsigned int ISIS2Dataset::WriteKeyword(
+        VSILFILE *fpLabel, unsigned int iLevel, CPLString key, CPLString value)
+
+    {
+        CPLString tab = "";
+        iLevel *= 4; // each struct is idented by 4 spaces
+        int ret = VSIFPrintfL(fpLabel,"%*s%s=%s\n", iLevel, tab.c_str(), key.c_str(), value.c_str());
+        return ret;
+    }
+
+/************************************************************************/
+/*                          WriteFormatting()                           */
+/************************************************************************/
+
+    unsigned int ISIS2Dataset::WriteFormatting(VSILFILE *fpLabel, CPLString data)
+
+    {
+        int ret = VSIFPrintfL(fpLabel,"%s\n", data.c_str());
+        return ret;
+    }
+
+/************************************************************************/
+/*                         GDALRegister_ISIS2()                         */
+/************************************************************************/
+
+    void GDALRegister_ISIS2()
+
+    {
+        GDALDriver	*poDriver;
+
+        if( GDALGetDriverByName( "ISIS2" ) == NULL )
+        {
+            poDriver = new GDALDriver();
+        
+            poDriver->SetDescription( "ISIS2" );
+            poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                       "USGS Astrogeology ISIS cube (Version 2)" );
+            poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_isis2.html" );
+            poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+            poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 UInt16 Float32 Float64");
+
+            poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
+"<CreationOptionList>\n"
+"   <Option name='LABELING_METHOD' type='string-select' default='ATTACHED'>\n"
+"     <Value>ATTACHED</Value>"
+"     <Value>DETACHED</Value>"
+"   </Option>"
+"   <Option name='IMAGE_EXTENSION' type='string' default='cub'/>\n"
+"</CreationOptionList>\n" );
+
+            poDriver->pfnIdentify = ISIS2Dataset::Identify;
+            poDriver->pfnOpen = ISIS2Dataset::Open;
+            poDriver->pfnCreate = ISIS2Dataset::Create;
+
+            GetGDALDriverManager()->RegisterDriver( poDriver );
+        }
+    }
diff --git a/frmts/pds/isis3dataset.cpp b/frmts/pds/isis3dataset.cpp
index d0ce24f..c70a117 100644
--- a/frmts/pds/isis3dataset.cpp
+++ b/frmts/pds/isis3dataset.cpp
@@ -401,10 +401,10 @@ GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
     double semi_major = 0.0;
     double semi_minor = 0.0;
     double iflattening = 0.0;
-    float center_lat = 0.0;
-    float center_lon = 0.0;
-    float first_std_parallel = 0.0;
-    float second_std_parallel = 0.0;
+    double center_lat = 0.0;
+    double center_lon = 0.0;
+    double first_std_parallel = 0.0;
+    double second_std_parallel = 0.0;
     double radLat, localRadius;
     VSILFILE	*fp;
 
@@ -913,7 +913,7 @@ void GDALRegister_ISIS3()
         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
                                    "USGS Astrogeology ISIS cube (Version 3)" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#ISIS3" );
+                                   "frmt_isis3.html" );
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = ISIS3Dataset::Open;
diff --git a/frmts/pds/nasakeywordhandler.cpp b/frmts/pds/nasakeywordhandler.cpp
index 56d65c7..2df6ca7 100644
--- a/frmts/pds/nasakeywordhandler.cpp
+++ b/frmts/pds/nasakeywordhandler.cpp
@@ -371,6 +371,15 @@ void NASAKeywordHandler::SkipWhite()
             }
 
             pszHeaderNext += 2;
+
+            // consume till end of line.
+            // reduce sensibility to a label error
+            while( *pszHeaderNext != '\0'
+            		&& *pszHeaderNext != 10
+            		&& *pszHeaderNext != 13 )
+            {
+            	pszHeaderNext++;
+            }
             continue;
         }
 
@@ -420,3 +429,12 @@ const char *NASAKeywordHandler::GetKeyword( const char *pszPath,
         return pszResult;
 }
 
+/************************************************************************/
+/*                             GetKeywordList()                         */
+/************************************************************************/
+ 
+char **NASAKeywordHandler::GetKeywordList()
+{
+    return papszKeywordList;
+}
+
diff --git a/frmts/pds/nasakeywordhandler.h b/frmts/pds/nasakeywordhandler.h
index 39da35d..75af271 100644
--- a/frmts/pds/nasakeywordhandler.h
+++ b/frmts/pds/nasakeywordhandler.h
@@ -23,4 +23,5 @@ public:
     int     Ingest( VSILFILE *fp, int nOffset );
 
     const char *GetKeyword( const char *pszPath, const char *pszDefault );
+    char **GetKeywordList();
 };
diff --git a/frmts/pds/pdsdataset.cpp b/frmts/pds/pdsdataset.cpp
index 4648de5..66e7c45 100644
--- a/frmts/pds/pdsdataset.cpp
+++ b/frmts/pds/pdsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdsdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: pdsdataset.cpp 23471 2011-12-05 20:37:37Z rouault $
  *
  * Project:  PDS Driver; Planetary Data System Format
  * Purpose:  Implementation of PDSDataset
@@ -46,7 +46,7 @@
 #include "cpl_string.h" 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: pdsdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: pdsdataset.cpp 23471 2011-12-05 20:37:37Z rouault $");
 
 CPL_C_START
 void	GDALRegister_PDS(void);
@@ -73,19 +73,22 @@ class PDSDataset : public RawDataset
     CPLString   osTempResult;
 
     void        ParseSRS();
-    int         ParseUncompressedImage();
     int         ParseCompressedImage();
+    int	        ParseImage( CPLString osPrefix = "" );
     void        CleanString( CPLString &osInput );
 
-    const char *GetKeyword( const char *pszPath, 
+    const char *GetKeyword( std::string osPath,
                             const char *pszDefault = "");
-    const char *GetKeywordSub( const char *pszPath, 
+    const char *GetKeywordSub( std::string osPath,
                                int iSubscript, 
                                const char *pszDefault = "");
     const char *GetKeywordUnit( const char *pszPath, 
                                int iSubscript, 
                                const char *pszDefault = "");
 
+  protected:
+    virtual int         CloseDependentDatasets();
+
 public:
     PDSDataset();
     ~PDSDataset();
@@ -137,8 +140,31 @@ PDSDataset::~PDSDataset()
     if( fpImage != NULL )
         VSIFCloseL( fpImage );
 
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int PDSDataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
     if( poCompressedDS )
+    {
+        bHasDroppedRef = TRUE;
         delete poCompressedDS;
+        poCompressedDS = NULL;
+    }
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       delete papoBands[iBand];
+    }
+    nBands = 0;
+
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -268,8 +294,8 @@ void PDSDataset::ParseSRS()
 
     value = GetKeyword("IMAGE_MAP_PROJECTION.MAP_SCALE");
     if (strlen(value) > 0 ) {
-        dfXDim = (float) atof(value);
-        dfYDim = (float) atof(value) * -1;
+        dfXDim = atof(value);
+        dfYDim = atof(value) * -1;
         
         CPLString unit = GetKeywordUnit("IMAGE_MAP_PROJECTION.MAP_SCALE",2); //KM
         //value = GetKeywordUnit("IMAGE_MAP_PROJECTION.MAP_SCALE",3); //PIXEL
@@ -287,24 +313,49 @@ void PDSDataset::ParseSRS()
         }            
     }
     
-    // Calculate upper left corner of pixel in meters from the upper left center pixel which
-    // should be correct for what is documented in the PDS manual
-    // It doesn't mean it will work perfectly for every PDS image, as they tend to be released in different ways.
-    // both dfULYMap, dfULXMap were update October 11, 2007 to correct 0.5 cellsize offset
+/* -------------------------------------------------------------------- */
+/*      Calculate upper left corner of pixel in meters from the         */
+/*      upper  left center pixel sample/line offsets.  It doesn't       */
+/*      mean the defaults will work for every PDS image, as these       */
+/*      values are used inconsistantly.  Thus we have included          */
+/*      conversion options to allow the user to override the            */
+/*      documented PDS3 default. Jan. 2011, for known mapping issues    */
+/*      see GDAL PDS page or mapping within ISIS3 source (USGS)         */
+/*      $ISIS3DATA/base/translations/pdsProjectionLineSampToXY.def      */
+/* -------------------------------------------------------------------- */
+   
+    // defaults should be correct for what is documented in the PDS3 standard
+    double   dfSampleOffset_Shift;
+    double   dfLineOffset_Shift;
+    double   dfSampleOffset_Mult;
+    double   dfLineOffset_Mult;
+
+    dfSampleOffset_Shift = 
+        atof(CPLGetConfigOption( "PDS_SampleProjOffset_Shift", "-0.5" ));
+    
+    dfLineOffset_Shift = 
+        atof(CPLGetConfigOption( "PDS_LineProjOffset_Shift", "-0.5" ));
+
+    dfSampleOffset_Mult =
+        atof(CPLGetConfigOption( "PDS_SampleProjOffset_Mult", "-1.0") );
+
+    dfLineOffset_Mult = 
+        atof( CPLGetConfigOption( "PDS_LineProjOffset_Mult", "1.0") );
+
     /***********   Grab LINE_PROJECTION_OFFSET ************/
     value = GetKeyword("IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET");
     if (strlen(value) > 0) {
-        yulcenter = (float) atof(value);
-        dfULYMap = ((yulcenter - 0.5) * dfYDim * -1); 
-        //notice dfYDim is negative here which is why it is negated again
+        yulcenter = atof(value);
+        dfULYMap = ((yulcenter + dfLineOffset_Shift) * -dfYDim * dfLineOffset_Mult);
+        //notice dfYDim is negative here which is why it is again negated here
     }
     /***********   Grab SAMPLE_PROJECTION_OFFSET ************/
     value = GetKeyword("IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET");
     if( strlen(value) > 0 ) {
-        xulcenter = (float) atof(value);
-        dfULXMap = ((xulcenter - 0.5) * dfXDim * -1);
+        xulcenter = atof(value);
+        dfULXMap = ((xulcenter + dfSampleOffset_Shift) * dfXDim * dfSampleOffset_Mult);
     }
-     
+
 /* ==================================================================== */
 /*      Get the coordinate system.                                      */
 /* ==================================================================== */
@@ -312,10 +363,10 @@ void PDSDataset::ParseSRS()
     double semi_major = 0.0;
     double semi_minor = 0.0;
     double iflattening = 0.0;
-    float center_lat = 0.0;
-    float center_lon = 0.0;
-    float first_std_parallel = 0.0;
-    float second_std_parallel = 0.0;
+    double center_lat = 0.0;
+    double center_lon = 0.0;
+    double first_std_parallel = 0.0;
+    double second_std_parallel = 0.0;
     OGRSpatialReference oSRS;
 
     /***********  Grab TARGET_NAME  ************/
@@ -564,11 +615,10 @@ void PDSDataset::ParseSRS()
 }
 
 /************************************************************************/
-/*                       ParseUncompressedImage()                       */
+/*                             ParseImage()                             */
 /************************************************************************/
 
-int PDSDataset::ParseUncompressedImage()
-
+int PDSDataset::ParseImage( CPLString osPrefix )
 {
 /* ------------------------------------------------------------------- */
 /*	We assume the user is pointing to the label (ie. .lbl) file.  	   */
@@ -583,7 +633,7 @@ int PDSDataset::ParseUncompressedImage()
     // ^IMAGE             = 10851 <BYTES>
     // ^SPECTRAL_QUBE = 5  for multi-band images
 
-    CPLString osImageKeyword = "^IMAGE";
+    CPLString osImageKeyword = osPrefix + "^IMAGE";
     CPLString osQube = GetKeyword( osImageKeyword, "" );
     CPLString osTargetFile = GetDescription();
 
@@ -625,7 +675,6 @@ int PDSDataset::ParseUncompressedImage()
     int nSkipBytes = 0;
     int itype;
     int record_bytes;
-    int	bNoDataSet = FALSE;
     char chByteOrder = 'M';  //default to MSB
     double dfNoData = 0.0;
  
@@ -636,7 +685,7 @@ int PDSDataset::ParseUncompressedImage()
     /* -------------------------------------------------------------------- */
     const char *value;
 
-    CPLString osEncodingType = GetKeyword( "IMAGE.ENCODING_TYPE", "N/A" );
+    CPLString osEncodingType = GetKeyword(osPrefix+"IMAGE.ENCODING_TYPE","N/A");
     CleanString(osEncodingType);
     if ( !EQUAL(osEncodingType.c_str(),"N/A") )
     {
@@ -657,30 +706,30 @@ int PDSDataset::ParseUncompressedImage()
     /** if not NULL then CORE_ITEMS keyword i.e. (234,322,2)  **/
     /***********************************************************/
     char szLayout[10] = "BSQ"; //default to band seq.
-    value = GetKeyword( "IMAGE.AXIS_NAME", "" );
+    value = GetKeyword( osPrefix+"IMAGE.AXIS_NAME", "" );
     if (EQUAL(value,"(SAMPLE,LINE,BAND)") ) {
         strcpy(szLayout,"BSQ");
-        nCols = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",1));
-        nRows = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",2));
-        nBands = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",3));
+        nCols = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",1));
+        nRows = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",2));
+        nBands = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",3));
     }
     else if (EQUAL(value,"(BAND,LINE,SAMPLE)") ) {
         strcpy(szLayout,"BIP");
-        nBands = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",1));
-        nRows = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",2));
-        nCols = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",3));
+        nBands = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",1));
+        nRows = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",2));
+        nCols = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",3));
     }
     else if (EQUAL(value,"(SAMPLE,BAND,LINE)") ) {
         strcpy(szLayout,"BIL");
-        nCols = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",1));
-        nBands = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",2));
-        nRows = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",3));
+        nCols = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",1));
+        nBands = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",2));
+        nRows = atoi(GetKeywordSub(osPrefix+"IMAGE.CORE_ITEMS",3));
     }
     else if ( EQUAL(value,"") ) {
         strcpy(szLayout,"BSQ");
-        nCols = atoi(GetKeyword("IMAGE.LINE_SAMPLES",""));
-        nRows = atoi(GetKeyword("IMAGE.LINES",""));
-        nBands = atoi(GetKeyword("IMAGE.BANDS","1"));        
+        nCols = atoi(GetKeyword(osPrefix+"IMAGE.LINE_SAMPLES",""));
+        nRows = atoi(GetKeyword(osPrefix+"IMAGE.LINES",""));
+        nBands = atoi(GetKeyword(osPrefix+"IMAGE.BANDS","1"));
     }
     else {
         CPLError( CE_Failure, CPLE_OpenFailed, 
@@ -689,9 +738,9 @@ int PDSDataset::ParseUncompressedImage()
     }
     
     /***********   Grab Qube record bytes  **********/
-    record_bytes = atoi(GetKeyword("IMAGE.RECORD_BYTES"));
+    record_bytes = atoi(GetKeyword(osPrefix+"IMAGE.RECORD_BYTES"));
     if (record_bytes == 0)
-        record_bytes = atoi(GetKeyword("RECORD_BYTES"));
+        record_bytes = atoi(GetKeyword(osPrefix+"RECORD_BYTES"));
 
     // this can happen with "record_type = undefined". 
     if( record_bytes == 0 )
@@ -711,11 +760,11 @@ int PDSDataset::ParseUncompressedImage()
     else
         nSkipBytes = 0;     
 
-    nSkipBytes += atoi(GetKeyword("IMAGE.LINE_PREFIX_BYTES",""));
+    nSkipBytes += atoi(GetKeyword(osPrefix+"IMAGE.LINE_PREFIX_BYTES",""));
     
     /***********   Grab SAMPLE_TYPE *****************/
     /** if keyword not found leave as "M" or "MSB" **/
-    CPLString osST = GetKeyword( "IMAGE.SAMPLE_TYPE" );
+    CPLString osST = GetKeyword( osPrefix+"IMAGE.SAMPLE_TYPE" );
     if( osST.size() >= 2 && osST[0] == '"' && osST[osST.size()-1] == '"' )
         osST = osST.substr( 1, osST.size() - 2 );
 
@@ -733,12 +782,11 @@ int PDSDataset::ParseUncompressedImage()
 
     /**** Grab format type - pds supports 1,2,4,8,16,32,64 (in theory) **/
     /**** I have only seen 8, 16, 32 (float) in released datasets      **/
-    itype = atoi(GetKeyword("IMAGE.SAMPLE_BITS",""));
+    itype = atoi(GetKeyword(osPrefix+"IMAGE.SAMPLE_BITS",""));
     switch(itype) {
       case 8 :
         eDataType = GDT_Byte;
         dfNoData = NULL1;
-        bNoDataSet = TRUE;
         break;
       case 16 :
         if( strstr(osST,"UNSIGNED") != NULL )
@@ -746,17 +794,14 @@ int PDSDataset::ParseUncompressedImage()
         else
             eDataType = GDT_Int16;
         dfNoData = NULL2;
-        bNoDataSet = TRUE;
         break;
       case 32 :
         eDataType = GDT_Float32;
         dfNoData = NULL3;
-        bNoDataSet = TRUE;
         break;
       case 64 :
         eDataType = GDT_Float64;
         dfNoData = NULL3;
-        bNoDataSet = TRUE;
         break;
       default :
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -766,6 +811,16 @@ int PDSDataset::ParseUncompressedImage()
     }
 
 /* -------------------------------------------------------------------- */
+/*      Is there a specific nodata value in the file? Either the        */
+/*      MISSING or MISSING_CONSTANT keywords are nodata.                */
+/* -------------------------------------------------------------------- */
+    if( GetKeyword( osPrefix+"IMAGE.MISSING", NULL ) != NULL )
+        dfNoData = CPLAtofM( GetKeyword( osPrefix+"IMAGE.MISSING", "" ) );
+
+    if( GetKeyword( osPrefix+"IMAGE.MISSING_CONSTANT", NULL ) != NULL )
+        dfNoData = CPLAtofM( GetKeyword( osPrefix+"IMAGE.MISSING_CONSTANT",""));
+
+/* -------------------------------------------------------------------- */
 /*      Did we get the required keywords?  If not we return with        */
 /*      this never having been considered to be a match. This isn't     */
 /*      an error!                                                       */
@@ -830,9 +885,9 @@ int PDSDataset::ParseUncompressedImage()
     else if( EQUAL(szLayout,"BSQ") )
     {
         nPixelOffset = nItemSize;
-        nBandOffset = nLineOffset * nRows;
         nLineOffset = ((nPixelOffset * nCols + record_bytes - 1)/record_bytes)
             * record_bytes;
+        nBandOffset = nLineOffset * nRows;
     }
     else /* assume BIL */
     {
@@ -847,7 +902,6 @@ int PDSDataset::ParseUncompressedImage()
 /* -------------------------------------------------------------------- */
     int i;
 
-    nBands = nBands;;
     for( i = 0; i < nBands; i++ )
     {
         RawRasterBand	*poBand;
@@ -865,10 +919,10 @@ int PDSDataset::ParseUncompressedImage()
 
         if( nBands == 1 )
         {
-            const char* pszMin = GetKeyword("IMAGE.MINIMUM", NULL);
-            const char* pszMax = GetKeyword("IMAGE.MAXIMUM", NULL);
-            const char* pszMean = GetKeyword("IMAGE.MEAN", NULL);
-            const char* pszStdDev= GetKeyword("IMAGE.STANDARD_DEVIATION", NULL);
+            const char* pszMin = GetKeyword(osPrefix+"IMAGE.MINIMUM", NULL);
+            const char* pszMax = GetKeyword(osPrefix+"IMAGE.MAXIMUM", NULL);
+            const char* pszMean = GetKeyword(osPrefix+"IMAGE.MEAN", NULL);
+            const char* pszStdDev= GetKeyword(osPrefix+"IMAGE.STANDARD_DEVIATION", NULL);
             if (pszMin != NULL && pszMax != NULL &&
                 pszMean != NULL && pszStdDev != NULL)
             {
@@ -879,16 +933,15 @@ int PDSDataset::ParseUncompressedImage()
             }
         }
         
-        if( bNoDataSet )
-            poBand->SetNoDataValue( dfNoData );
+        poBand->SetNoDataValue( dfNoData );
 
         SetBand( i+1, poBand );
 
         // Set offset/scale values at the PAM level.
         poBand->SetOffset( 
-            CPLAtofM(GetKeyword("IMAGE.OFFSET","0.0")));
+            CPLAtofM(GetKeyword(osPrefix+"IMAGE.OFFSET","0.0")));
         poBand->SetScale( 
-            CPLAtofM(GetKeyword("IMAGE.SCALING_FACTOR","1.0")));
+            CPLAtofM(GetKeyword(osPrefix+"IMAGE.SCALING_FACTOR","1.0")));
     }
 
     return TRUE;
@@ -1006,7 +1059,7 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
     VSIFCloseL( fpQube );
 
 /* -------------------------------------------------------------------- */
-/*      Is this a comprssed image with COMPRESSED_FILE subdomain?       */
+/*      Is this a compressed image with COMPRESSED_FILE subdomain?      */
 /*                                                                      */
 /*      The corresponding parse operations will read keywords,          */
 /*      establish bands and raster size.                                */
@@ -1023,7 +1076,13 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        if( !poDS->ParseUncompressedImage() )
+        CPLString osPrefix;
+    	CPLString osObject = poDS->GetKeyword( "UNCOMPRESSED_FILE.IMAGE.NAME", "");
+
+        if( osObject != "" )
+            osPrefix = "UNCOMPRESSED_FILE.";
+        
+        if( !poDS->ParseImage(osPrefix) )
         {
             delete poDS;
             return NULL;
@@ -1072,23 +1131,23 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                             GetKeyword()                             */
 /************************************************************************/
 
-const char *PDSDataset::GetKeyword( const char *pszPath, 
-                                      const char *pszDefault )
+const char *PDSDataset::GetKeyword( std::string osPath,
+                                    const char *pszDefault )
 
 {
-    return oKeywords.GetKeyword( pszPath, pszDefault );
+    return oKeywords.GetKeyword( osPath.c_str(), pszDefault );
 }
 
 /************************************************************************/
 /*                            GetKeywordSub()                           */
 /************************************************************************/
 
-const char *PDSDataset::GetKeywordSub( const char *pszPath, 
-                                         int iSubscript,
-                                         const char *pszDefault )
+const char *PDSDataset::GetKeywordSub( std::string osPath,
+                                       int iSubscript,
+                                       const char *pszDefault )
 
 {
-    const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
+    const char *pszResult = oKeywords.GetKeyword( osPath.c_str(), NULL );
     
     if( pszResult == NULL )
         return pszDefault;
@@ -1188,7 +1247,7 @@ void GDALRegister_PDS()
         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
                                    "NASA Planetary Data System" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#PDS" );
+                                   "frmt_pds.html" );
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = PDSDataset::Open;
diff --git a/frmts/png/libpng/LICENSE b/frmts/png/libpng/LICENSE
index e5561c2..0fa9cb7 100644
--- a/frmts/png/libpng/LICENSE
+++ b/frmts/png/libpng/LICENSE
@@ -10,7 +10,7 @@ this sentence.
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.2.44, June 26, 2010, are
+libpng versions 1.2.6, August 15, 2004, through 1.2.46, July 9, 2011, are
 Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
@@ -108,4 +108,4 @@ certification mark of the Open Source Initiative.
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-June 26, 2010
+July 9, 2011
diff --git a/frmts/png/libpng/README b/frmts/png/libpng/README
index 034191a..7fb0d95 100644
--- a/frmts/png/libpng/README
+++ b/frmts/png/libpng/README
@@ -4,14 +4,14 @@ $Id$
 Updating libpng in GDAL tree should follow update of zlib library in frmts/zlib.
 *****************
 
-libpng 1.2.44 is the official PNG reference library.
+libpng 1.2.46 is the official PNG reference library.
 It supports almost all PNG features, is extensible,
 and has been extensively tested for over 15 years.
 
 http://www.libpng.org
 
 
-GDAL changes
+GDAL changes (stored in libpng_gdal.patch)
 ------------
 
 * Make screwy MSPaint "zero chunks" only a warning, not error. See r18808 and #3416
diff --git a/frmts/png/libpng/libpng_gdal.patch b/frmts/png/libpng/libpng_gdal.patch
new file mode 100644
index 0000000..cc1134f
--- /dev/null
+++ b/frmts/png/libpng/libpng_gdal.patch
@@ -0,0 +1,22 @@
+--- /home/even/libpng-1.2.46/pngrutil.c	2011-07-09 12:30:23.000000000 +0200
++++ pngrutil.c	2011-07-29 19:52:18.831921846 +0200
+@@ -2404,7 +2404,8 @@
+ #endif
+         )
+ #endif
+-          png_chunk_error(png_ptr, "unknown critical chunk");
++          /* GDAL change : png_chunk_error -> png_chunk_warning */
++          png_chunk_warning(png_ptr, "unknown critical chunk");
+    }
+ 
+ #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+@@ -2488,7 +2489,8 @@
+    if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
+        isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
+    {
+-      png_chunk_error(png_ptr, "invalid chunk type");
++      /* GDAL change : png_chunk_error -> png_chunk_warning */
++      png_chunk_warning(png_ptr, "invalid chunk type");
+    }
+ }
+ 
diff --git a/frmts/png/libpng/png.c b/frmts/png/libpng/png.c
index 7ad9538..95ea40a 100644
--- a/frmts/png/libpng/png.c
+++ b/frmts/png/libpng/png.c
@@ -1,8 +1,8 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.2.43 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.46 [February 25, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -17,7 +17,7 @@
 #include "png.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef version_1_2_44 Your_png_h_is_not_version_1_2_44;
+typedef version_1_2_46 Your_png_h_is_not_version_1_2_46;
 
 /* Version information for C files.  This had better match the version
  * string defined in png.h.
@@ -724,14 +724,14 @@ png_get_copyright(png_structp png_ptr)
 #else
 #ifdef __STDC__
    return ((png_charp) PNG_STRING_NEWLINE \
-     "libpng version 1.2.44 - June 26, 2010" PNG_STRING_NEWLINE \
-     "Copyright (c) 1998-2010 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+     "libpng version 1.2.46 - July 9, 2011" PNG_STRING_NEWLINE \
+     "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE);
 #else
-      return ((png_charp) "libpng version 1.2.44 - June 26, 2010\
-      Copyright (c) 1998-2010 Glenn Randers-Pehrson\
+      return ((png_charp) "libpng version 1.2.46 - July 9, 2011\
+      Copyright (c) 1998-2011 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
 #endif
diff --git a/frmts/png/libpng/png.h b/frmts/png/libpng/png.h
index cc1915d..42e7013 100644
--- a/frmts/png/libpng/png.h
+++ b/frmts/png/libpng/png.h
@@ -1,7 +1,7 @@
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.2.44 - June 26, 2010
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * libpng version 1.2.46 - July 9, 2011
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -10,7 +10,7 @@
  * Authors and maintainers:
  *  libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *  libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *  libpng versions 0.97, January 1998, through 1.2.44 - June 26, 2010: Glenn
+ *  libpng versions 0.97, January 1998, through 1.2.46 - July 9, 2011: Glenn
  *  See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
@@ -231,7 +231,7 @@
  *    1.2.37beta01-03         13    10237  12.so.0.37[.0]
  *    1.2.37rc01              13    10237  12.so.0.37[.0]
  *    1.2.37                  13    10237  12.so.0.37[.0]
- *    1.2.45                  10    10045  12.so.0.45[.0]
+ *    1.0.45                  10    10045  12.so.0.45[.0]
  *    1.0.46                  10    10046  10.so.0.46[.0]
  *    1.2.38beta01            13    10238  12.so.0.38[.0]
  *    1.2.38rc01-03           13    10238  12.so.0.38[.0]
@@ -262,6 +262,14 @@
  *    1.2.44beta01-03         13    10244  12.so.0.44[.0]
  *    1.2.44rc01-03           13    10244  12.so.0.44[.0]
  *    1.2.44                  13    10244  12.so.0.44[.0]
+ *    1.2.45beta01-03         13    10245  12.so.0.45[.0]
+ *    1.0.55rc01              10    10055  10.so.0.55[.0]
+ *    1.2.45rc01              13    10245  12.so.0.45[.0]
+ *    1.0.55                  10    10055  10.so.0.55[.0]
+ *    1.2.45                  13    10245  12.so.0.45[.0]
+ *    1.2.46rc01-02           13    10246  12.so.0.46[.0]
+ *    1.0.56                  10    10056  10.so.0.56[.0]
+ *    1.2.46                  13    10246  12.so.0.46[.0]
  *
  *    Henceforth the source version will match the shared-library major
  *    and minor numbers; the shared-library major version number will be
@@ -293,8 +301,8 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.2.44, June 26, 2010, are
- * Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
+ * libpng versions 1.2.6, August 15, 2004, through 1.2.46, July 9, 2011, are
+ * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
  *
@@ -405,13 +413,13 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    June 26, 2010
+ *    July 9, 2011
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.2.44 are Y2K compliant.  It is my belief that earlier
+ *    upward through 1.2.46 are Y2K compliant.  It is my belief that earlier
  *    versions were also Y2K compliant.
  *
  *    Libpng only has three year fields.  One is a 2-byte unsigned integer
@@ -467,9 +475,9 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.2.44"
+#define PNG_LIBPNG_VER_STRING "1.2.46"
 #define PNG_HEADER_VERSION_STRING \
-   " libpng version 1.2.44 - June 26, 2010\n"
+   " libpng version 1.2.46 - July 9, 2011\n"
 
 #define PNG_LIBPNG_VER_SONUM   0
 #define PNG_LIBPNG_VER_DLLNUM  13
@@ -477,7 +485,7 @@
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   2
-#define PNG_LIBPNG_VER_RELEASE 44
+#define PNG_LIBPNG_VER_RELEASE 46
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  */
@@ -507,7 +515,7 @@
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10244 /* 1.2.44 */
+#define PNG_LIBPNG_VER 10246 /* 1.2.46 */
 
 #ifndef PNG_VERSION_INFO_ONLY
 /* Include the compression library's header */
@@ -1547,7 +1555,7 @@ struct png_struct_def
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef png_structp version_1_2_44;
+typedef png_structp version_1_2_46;
 
 typedef png_struct FAR * FAR * png_structpp;
 
diff --git a/frmts/png/libpng/pngconf.h b/frmts/png/libpng/pngconf.h
index defc16d..57293c3 100644
--- a/frmts/png/libpng/pngconf.h
+++ b/frmts/png/libpng/pngconf.h
@@ -1,8 +1,8 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.2.44 - June 26, 2010
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * libpng version 1.2.46 - July 9, 2011
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
diff --git a/frmts/png/libpng/pngerror.c b/frmts/png/libpng/pngerror.c
index 7bc98fb..025d52e 100644
--- a/frmts/png/libpng/pngerror.c
+++ b/frmts/png/libpng/pngerror.c
@@ -1,8 +1,8 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Last changed in libpng 1.2.41 [December 3, 2009]
- * Copyright (c) 1998-2009 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -87,12 +87,17 @@ png_error(png_structp png_ptr, png_const_charp error_message)
 void PNGAPI
 png_err(png_structp png_ptr)
 {
+   /* Prior to 1.2.45 the error_fn received a NULL pointer, expressed
+    * erroneously as '\0', instead of the empty string "".  This was
+    * apparently an error, introduced in libpng-1.2.20, and png_default_error
+    * will crash in this case.
+    */
    if (png_ptr != NULL && png_ptr->error_fn != NULL)
-      (*(png_ptr->error_fn))(png_ptr, '\0');
+      (*(png_ptr->error_fn))(png_ptr, "");
 
    /* If the custom handler doesn't exist, or if it returns,
       use the default handler, which will not return. */
-   png_default_error(png_ptr, '\0');
+   png_default_error(png_ptr, "");
 }
 #endif /* PNG_ERROR_TEXT_SUPPORTED */
 
@@ -181,8 +186,13 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
    {
       buffer[iout++] = ':';
       buffer[iout++] = ' ';
-      png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT);
-      buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0';
+
+      iin = 0;
+      while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
+         buffer[iout++] = error_message[iin++];
+
+      /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
+      buffer[iout] = '\0';
    }
 }
 
diff --git a/frmts/png/libpng/pngmem.c b/frmts/png/libpng/pngmem.c
index 91f2765..a18719b 100644
--- a/frmts/png/libpng/pngmem.c
+++ b/frmts/png/libpng/pngmem.c
@@ -442,7 +442,7 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
  * have the ability to do that.
  */
 
-png_voidp PNGAPI
+png_voidp /* PRIVATE */
 png_calloc(png_structp png_ptr, png_uint_32 size)
 {
    png_voidp ret;
diff --git a/frmts/png/libpng/pngrtran.c b/frmts/png/libpng/pngrtran.c
index af1aa8e..33703d4 100644
--- a/frmts/png/libpng/pngrtran.c
+++ b/frmts/png/libpng/pngrtran.c
@@ -1,8 +1,8 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.2.43 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -676,10 +676,21 @@ void PNGAPI
 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
    double green)
 {
-   int red_fixed = (int)((float)red*100000.0 + 0.5);
-   int green_fixed = (int)((float)green*100000.0 + 0.5);
+   int red_fixed, green_fixed;
    if (png_ptr == NULL)
       return;
+   if (red > 21474.83647 || red < -21474.83648 ||
+       green > 21474.83647 || green < -21474.83648)
+   {
+      png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
+      red_fixed = -1;
+      green_fixed = -1;
+   }
+   else
+   {
+      red_fixed = (int)((float)red*100000.0 + 0.5);
+      green_fixed = (int)((float)green*100000.0 + 0.5);
+   }
    png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
 }
 #endif
@@ -1196,8 +1207,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
    {
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       {
-         if (png_ptr->num_trans &&
-              (png_ptr->transformations & PNG_EXPAND_tRNS))
+         if (png_ptr->num_trans)
             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
          else
             info_ptr->color_type = PNG_COLOR_TYPE_RGB;
diff --git a/frmts/png/libpng/pngrutil.c b/frmts/png/libpng/pngrutil.c
index e35314a..5965b45 100644
--- a/frmts/png/libpng/pngrutil.c
+++ b/frmts/png/libpng/pngrutil.c
@@ -1,8 +1,8 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.2.44 [June 26, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -1812,6 +1812,14 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
+   /* Need unit type, width, \0, height: minimum 4 bytes */
+   else if (length < 4)
+   {
+      png_warning(png_ptr, "sCAL chunk too short");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
    png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
       length + 1);
    png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
diff --git a/frmts/png/libpng/pngwrite.c b/frmts/png/libpng/pngwrite.c
index e411e81..1d8c53f 100644
--- a/frmts/png/libpng/pngwrite.c
+++ b/frmts/png/libpng/pngwrite.c
@@ -1,8 +1,8 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Last changed in libpng 1.2.42 [January 3, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -295,6 +295,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
          if (keep != PNG_HANDLE_CHUNK_NEVER &&
             up->location && (up->location & PNG_HAVE_PLTE) &&
             !(up->location & PNG_HAVE_IDAT) &&
+            !(up->location & PNG_AFTER_IDAT) &&
             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
          {
diff --git a/frmts/png/pngdataset.cpp b/frmts/png/pngdataset.cpp
index 6e469d1..4b6c3a5 100644
--- a/frmts/png/pngdataset.cpp
+++ b/frmts/png/pngdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pngdataset.cpp 21526 2011-01-17 19:32:03Z rouault $
+ * $Id: pngdataset.cpp 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  PNG Driver
  * Purpose:  Implement GDAL PNG Support
@@ -49,7 +49,7 @@
 #include "cpl_string.h"
 #include <setjmp.h>
 
-CPL_CVSID("$Id: pngdataset.cpp 21526 2011-01-17 19:32:03Z rouault $");
+CPL_CVSID("$Id: pngdataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
 
 CPL_C_START
 void	GDALRegister_PNG(void);
@@ -64,6 +64,10 @@ CPL_C_END
 // at the same time. Do NOT use it unless you're ready to fix it
 //#define SUPPORT_CREATE
 
+// we believe it is ok to use setjmp() in this situation.
+#ifdef _MSC_VER
+#  pragma warning(disable:4611)
+#endif
 
 static void
 png_vsi_read_data(png_structp png_ptr, png_bytep data, png_size_t length);
@@ -107,20 +111,39 @@ class PNGDataset : public GDALPamDataset
 
 
     void        CollectMetadata();
+
+    int         bHasReadXMPMetadata;
+    void        CollectXMPMetadata();
+
     CPLErr      LoadScanline( int );
     CPLErr      LoadInterlacedChunk( int );
     void        Restart();
 
+    int         bHasTriedLoadWorldFile;
+    void        LoadWorldFile();
+    CPLString   osWldFilename;
+
   public:
                  PNGDataset();
                  ~PNGDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
+    static GDALDataset* CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
+
+    virtual char **GetFileList(void);
 
     virtual CPLErr GetGeoTransform( double * );
     virtual void FlushCache( void );
 
+    virtual char  **GetMetadata( const char * pszDomain = "" );
+    virtual const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain = "" );
+
     // semi-private.
     jmp_buf     sSetJmpContext;
 
@@ -227,13 +250,21 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     CPLErr      eErr;
     GByte       *pabyScanline;
     int         i, nPixelSize, nPixelOffset, nXSize = GetXSize();
-    
+
     CPLAssert( nBlockXOff == 0 );
 
     if( poGDS->nBitDepth == 16 )
         nPixelSize = 2;
     else
         nPixelSize = 1;
+
+
+    if (poGDS->fpImage == NULL)
+    {
+        memset( pImage, 0, nPixelSize * nXSize );
+        return CE_None;
+    }
+
     nPixelOffset = poGDS->nBands * nPixelSize;
 
 /* -------------------------------------------------------------------- */
@@ -277,7 +308,8 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         poBlock = 
             poGDS->GetRasterBand(iBand+1)->GetLockedBlockRef(nBlockXOff,nBlockYOff);
-        poBlock->DropLock();
+        if( poBlock != NULL )
+            poBlock->DropLock();
     }
 
     return CE_None;
@@ -383,6 +415,7 @@ double PNGRasterBand::GetNoDataValue( int *pbSuccess )
 PNGDataset::PNGDataset()
 
 {
+    fpImage = NULL;
     hPNG = NULL;
     psPNGInfo = NULL;
     pabyBuffer = NULL;
@@ -390,6 +423,7 @@ PNGDataset::PNGDataset()
     nBufferLines = 0;
     nLastLineRead = -1;
     poColorTable = NULL;
+    nBitDepth = 8;
 
     bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
@@ -398,6 +432,9 @@ PNGDataset::PNGDataset()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+
+    bHasTriedLoadWorldFile = FALSE;
+    bHasReadXMPMetadata = FALSE;
 }
 
 /************************************************************************/
@@ -426,6 +463,7 @@ PNGDataset::~PNGDataset()
 CPLErr PNGDataset::GetGeoTransform( double * padfTransform )
 
 {
+    LoadWorldFile();
 
     if( bGeoTransformValid )
     {
@@ -702,6 +740,120 @@ void PNGDataset::CollectMetadata()
 }
 
 /************************************************************************/
+/*                       CollectXMPMetadata()                           */
+/************************************************************************/
+
+/* See §2.1.5 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
+
+void PNGDataset::CollectXMPMetadata()
+
+{
+    if (fpImage == NULL || bHasReadXMPMetadata)
+        return;
+
+    /* Save current position to avoid disturbing PNG stream decoding */
+    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+
+    vsi_l_offset nOffset = 8;
+    VSIFSeekL( fpImage, nOffset, SEEK_SET );
+
+    /* Loop over chunks */
+    while(TRUE)
+    {
+        int nLength;
+        char pszChunkType[5];
+        int nCRC;
+
+        if (VSIFReadL( &nLength, 4, 1, fpImage ) != 1)
+            break;
+        nOffset += 4;
+        CPL_MSBPTR32(&nLength);
+        if (nLength <= 0)
+            break;
+        if (VSIFReadL( pszChunkType, 4, 1, fpImage ) != 1)
+            break;
+        nOffset += 4;
+        pszChunkType[4] = 0;
+
+        if (strcmp(pszChunkType, "iTXt") == 0 && nLength > 22)
+        {
+            char* pszContent = (char*)VSIMalloc(nLength + 1);
+            if (pszContent == NULL)
+                break;
+            if (VSIFReadL( pszContent, nLength, 1, fpImage) != 1)
+            {
+                VSIFree(pszContent);
+                break;
+            }
+            nOffset += nLength;
+            pszContent[nLength] = '\0';
+            if (memcmp(pszContent, "XML:com.adobe.xmp\0\0\0\0\0", 22) == 0)
+            {
+                /* Avoid setting the PAM dirty bit just for that */
+                int nOldPamFlags = nPamFlags;
+
+                char *apszMDList[2];
+                apszMDList[0] = pszContent + 22;
+                apszMDList[1] = NULL;
+                SetMetadata(apszMDList, "xml:XMP");
+
+                nPamFlags = nOldPamFlags;
+
+                VSIFree(pszContent);
+
+                break;
+            }
+            else
+            {
+                VSIFree(pszContent);
+            }
+        }
+        else
+        {
+            nOffset += nLength;
+            VSIFSeekL( fpImage, nOffset, SEEK_SET );
+        }
+
+        nOffset += 4;
+        if (VSIFReadL( &nCRC, 4, 1, fpImage ) != 1)
+            break;
+    }
+
+    VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+
+    bHasReadXMPMetadata = TRUE;
+}
+
+/************************************************************************/
+/*                           GetMetadata()                              */
+/************************************************************************/
+
+char  **PNGDataset::GetMetadata( const char * pszDomain )
+{
+    if (fpImage == NULL)
+        return NULL;
+    if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
+        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        CollectXMPMetadata();
+    return GDALPamDataset::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                       GetMetadataItem()                              */
+/************************************************************************/
+
+const char *PNGDataset::GetMetadataItem( const char * pszName,
+                                         const char * pszDomain )
+{
+    if (fpImage == NULL)
+        return NULL;
+    if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
+        (pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
+        CollectXMPMetadata();
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
 
@@ -936,6 +1088,8 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->CollectMetadata();
 
+    poDS->CollectXMPMetadata();
+
 /* -------------------------------------------------------------------- */
 /*      More metadata.                                                  */
 /* -------------------------------------------------------------------- */
@@ -948,7 +1102,7 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
-    poDS->TryLoadXML();
+    poDS->TryLoadXML( poOpenInfo->papszSiblingFiles );
 
 /* -------------------------------------------------------------------- */
 /*      Open overviews.                                                 */
@@ -956,27 +1110,64 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
                                  poOpenInfo->papszSiblingFiles );
 
-/* -------------------------------------------------------------------- */
-/*      Check for world file.                                           */
-/* -------------------------------------------------------------------- */
-    poDS->bGeoTransformValid = 
-        GDALReadWorldFile( poOpenInfo->pszFilename, NULL, 
-                           poDS->adfGeoTransform );
+    return poDS;
+}
 
-    if( !poDS->bGeoTransformValid )
-        poDS->bGeoTransformValid = 
-            GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
-                               poDS->adfGeoTransform );
+/************************************************************************/
+/*                        LoadWorldFile()                               */
+/************************************************************************/
 
-    return poDS;
+void PNGDataset::LoadWorldFile()
+{
+    if (bHasTriedLoadWorldFile)
+        return;
+    bHasTriedLoadWorldFile = TRUE;
+
+    char* pszWldFilename = NULL;
+    bGeoTransformValid =
+        GDALReadWorldFile2( GetDescription(), NULL,
+                            adfGeoTransform, oOvManager.GetSiblingFiles(),
+                            &pszWldFilename);
+
+    if( !bGeoTransformValid )
+        bGeoTransformValid =
+            GDALReadWorldFile2( GetDescription(), ".wld",
+                                adfGeoTransform, oOvManager.GetSiblingFiles(),
+                                &pszWldFilename);
+
+    if (pszWldFilename)
+    {
+        osWldFilename = pszWldFilename;
+        CPLFree(pszWldFilename);
+    }
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **PNGDataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+    LoadWorldFile();
+
+    if (osWldFilename.size() != 0 &&
+        CSLFindString(papszFileList, osWldFilename) == -1)
+    {
+        papszFileList = CSLAddString( papszFileList, osWldFilename );
+    }
+
+    return papszFileList;
 }
 
 /************************************************************************/
-/*                           PNGCreateCopy()                            */
+/*                             CreateCopy()                             */
 /************************************************************************/
 
-static GDALDataset *
-PNGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
+GDALDataset *
+PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
                int bStrict, char ** papszOptions, 
                GDALProgressFunc pfnProgress, void * pProgressData )
 
@@ -1292,12 +1483,28 @@ PNGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Re-open dataset, and copy any auxilary pam information.         */
 /* -------------------------------------------------------------------- */
-    PNGDataset *poDS = (PNGDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+    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 )
+    {
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+        return poDS;
+    }
 
-    return poDS;
+    CPLErrorReset();
+
+    PNGDataset* poPNG_DS = new PNGDataset();
+    poPNG_DS->nRasterXSize = nXSize;
+    poPNG_DS->nRasterYSize = nYSize;
+    poPNG_DS->nBitDepth = nBitDepth;
+    for(int i=0;i<nBands;i++)
+        poPNG_DS->SetBand( i+1, new PNGRasterBand( poPNG_DS, i+1) );
+    return poPNG_DS;
 }
 
 /************************************************************************/
@@ -1406,7 +1613,7 @@ void GDALRegister_PNG()
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = PNGDataset::Open;
-        poDriver->pfnCreateCopy = PNGCreateCopy;
+        poDriver->pfnCreateCopy = PNGDataset::CreateCopy;
         poDriver->pfnIdentify = PNGDataset::Identify;
 #ifdef SUPPORT_CREATE
         poDriver->pfnCreate = PNGDataset::Create;
diff --git a/frmts/postgisraster/postgisraster.h b/frmts/postgisraster/postgisraster.h
index 3bb62c4..ac36a02 100644
--- a/frmts/postgisraster/postgisraster.h
+++ b/frmts/postgisraster/postgisraster.h
@@ -1,9 +1,9 @@
 /******************************************************************************
  * File :    postgisraster.h
  * Project:  PostGIS Raster driver
- * Purpose:  Main header file for PostGIS Raster Driver 
+ * Purpose:  Main header file for PostGIS Raster Driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
- * 
+ *
  * Last changes: $Id: $
  *
  ******************************************************************************
@@ -29,6 +29,7 @@
  ******************************************************************************/
 #include "gdal_priv.h"
 #include "libpq-fe.h"
+#include <float.h>
 //#include "liblwgeom.h"
 
 // General defines
@@ -42,11 +43,15 @@
 
 #define POSTGIS_RASTER_VERSION         (GUInt16)0
 #define RASTER_HEADER_SIZE              61
-#define RASTER_BAND_HEADER_FIXED_SIZE   1  
+#define RASTER_BAND_HEADER_FIXED_SIZE   1
+
+#define BAND_SIZE(nodatasize, datasize) \
+        (RASTER_BAND_HEADER_FIXED_SIZE + nodatasize + datasize)
 
 #define GET_BAND_DATA(raster, nband, nodatasize, datasize) \
-    (raster + RASTER_HEADER_SIZE + ((RASTER_BAND_HEADER_FIXED_SIZE + nodatasize)\
-     * nband) + ((nband - 1) * datasize))
+    (raster + RASTER_HEADER_SIZE + nband * BAND_SIZE(nodatasize, datasize) - datasize)
+
+#define FLT_NEQ(x, y) (fabs(x - y) > FLT_EPSILON)
 
 
 /* Working modes */
@@ -85,6 +90,7 @@ private:
     int nSrid;
     PGconn* poConn;
     GBool bRegularBlocking;
+    GBool bAllTilesSnapToSameGrid;
     GBool bRegisteredInRasterColumns;
     char* pszSchema;
     char* pszTable;
@@ -94,6 +100,7 @@ private:
     int nMode;
     int nBlockXSize;
     int nBlockYSize;
+    GBool bBlocksCached;
     GBool SetRasterProperties(const char *);
     GBool BrowseDatabase(const char *, char *);
     GBool SetRasterBands();
@@ -108,6 +115,9 @@ public:
     CPLErr SetProjection(const char*);
     CPLErr SetGeoTransform(double *);
     CPLErr GetGeoTransform(double *);
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+        void *, int, int, GDALDataType, int, int *, int, int, int );
 };
 
 /******************************************************************************
@@ -124,14 +134,14 @@ private:
     char* pszTable;
     char* pszColumn;
     char* pszWhere;
-    PostGISRasterRasterBand ** papoOverviews; 
+    PostGISRasterRasterBand ** papoOverviews;
     void NullBlock(void *);
 
 public:
-    
-    PostGISRasterRasterBand(PostGISRasterDataset *poDS, int nBand, GDALDataType hDataType, 
-            double dfNodata, GBool bSignedByte, int nBitDepth, int nFactor, 
-            GBool bIsOffline, char * pszSchema = NULL, char * pszTable = NULL, 
+
+    PostGISRasterRasterBand(PostGISRasterDataset *poDS, int nBand, GDALDataType hDataType,
+            double dfNodata, GBool bSignedByte, int nBitDepth, int nFactor,
+            GBool bIsOffline, char * pszSchema = NULL, char * pszTable = NULL,
             char * pszColumn = NULL);
 
     virtual ~PostGISRasterRasterBand();
diff --git a/frmts/postgisraster/postgisrasterdataset.cpp b/frmts/postgisraster/postgisrasterdataset.cpp
index f8221b3..682718a 100644
--- a/frmts/postgisraster/postgisrasterdataset.cpp
+++ b/frmts/postgisraster/postgisrasterdataset.cpp
@@ -1,32 +1,32 @@
 /*************************************************************************
  * File :    postgisrasterdataset.cpp
  * Project:  PostGIS Raster driver
- * Purpose:  GDAL Dataset implementation for PostGIS Raster driver 
+ * Purpose:  GDAL Dataset implementation for PostGIS Raster driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
- * 
+ *
  * Last changes:
  * $Id:$
  *
  ************************************************************************
- * Copyright (c) 2010, Jorge Arevalo, jorge.arevalo at deimos-space.com
+ * Copyright (c) 2009 - 2011, Jorge Arevalo, jorge.arevalo at deimos-space.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 
+ * 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 
+ * 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.
  ************************************************************************/
 
@@ -71,12 +71,24 @@ PostGISRasterDataset::PostGISRasterDataset() {
     poDriver = NULL;
     nBlockXSize = 0;
     nBlockYSize = 0;
-    adfGeoTransform[0] = 0.0;     /* X Origin (top left corner) */
-    adfGeoTransform[1] = 1.0;     /* X Pixel size */
+    adfGeoTransform[0] = 0.0; /* X Origin (top left corner) */
+    adfGeoTransform[1] = 1.0; /* X Pixel size */
     adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;     /* Y Origin (top left corner) */
+    adfGeoTransform[3] = 0.0; /* Y Origin (top left corner) */
     adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;     /* Y Pixel Size */
+    adfGeoTransform[5] = 1.0; /* Y Pixel Size */
+    bBlocksCached = false;
+    bRegularBlocking = false;
+    bAllTilesSnapToSameGrid = 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.
+     **/
+
 }
 
 /************************
@@ -129,7 +141,6 @@ char * ReplaceSingleQuotes(const char * pszInput, int nLength) {
     return pszOutput;
 }
 
-
 /**************************************************************
  * \brief Replace the quotes by single quotes in the input string
  *
@@ -145,7 +156,7 @@ char * ReplaceQuotes(const char * pszInput, int nLength) {
 
     pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
 
-    for(i = 0; i < nLength; i++) {
+    for (i = 0; i < nLength; i++) {
         if (pszInput[i] == '"')
             pszOutput[i] = '\'';
         else
@@ -253,8 +264,7 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
 
         PQclear(poResult);
 
-    }
-        /**********************************************************************
+    }        /**********************************************************************
          * Fetch all the schema's raster tables and store them as subdatasets
          **********************************************************************/
     else {
@@ -314,33 +324,34 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
  * 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. 
+ * 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 
+ * 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 3 different cases:
  *	- If the result is only one row, we can gather the raster properties
  *	  from the returned object, regardless is a tile or a whole raster
- *	- If the result are several rows of a table, and the working mode is 
- *    ONE_RASTER_PER_TABLE, we assume all the rows are from the same raster 
- *    coverage. The rows are ordered by upper left y, upper left x, growing way, 
+ *	- If the result are several rows of a table, and the working mode is
+ *    ONE_RASTER_PER_TABLE, we assume all the rows are from the same raster
+ *    coverage. The rows are ordered by upper left y, upper left x, growing way,
  *    and we can get raster size from the first and last elements.
  *  - If 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. If you want only one of the raster rows,
  *    you must specify a where clause to restrict the number of rows returned.
  **************************************************************************/
-GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionString) {
+GBool PostGISRasterDataset::SetRasterProperties
+    (const char * pszValidConnectionString)
+{
     PGresult* poResult = NULL;
     CPLString osCommand;
     CPLString osCommand2;
     PGresult* poResult2 = NULL;
     int i = 0;
     int nTuples = 0;
-    int nRid = -1;
     GBool bRetValue = false;
     OGRSpatialReference * poSR = NULL;
     OGRGeometry* poGeom = NULL;
@@ -348,17 +359,28 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
     OGREnvelope* poE = NULL;
     char* pszExtent;
     char* pszProjectionRef;
+    int nTmpSrid = -1;
+    double dfTmpScaleX = 0.0;
+    double dfTmpScaleY = 0.0;
+    double dfTmpSkewX = 0.0;
+    double dfTmpSkewY = 0.0;
+    int nWidth = 0;
+    int nHeight = 0;
+    int nTmpWidth = 0;
+    int nTmpHeight = 0;
+
 
     /* Execute the query to fetch raster data from db */
     if (pszWhere == NULL) {
         osCommand.Printf("select (foo.md).*, foo.rid from (select rid, st_metadata(%s) as md \
                         from %s.%s) as foo", pszColumn, pszSchema, pszTable);
-    }
-    else {
+    } else {
         osCommand.Printf("select (foo.md).*, foo.rid from (select rid, st_metadata(%s) as md \
                         from %s.%s where %s) as foo", pszColumn, pszSchema, pszTable, pszWhere);
     }
 
+    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
+            "Query: %s", osCommand.c_str());
     poResult = PQexec(poConn, osCommand.c_str());
     if (
             poResult == NULL ||
@@ -394,35 +416,33 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
 
         /**
          * Not tiled dataset: The whole raster.
-         * TODO: This is a bad idea, but there're some problems getting one
-         * scanline per round (nBlockYSize = 1). Probably, the problem is in
-         * IReadBlock method. Review it and fix it.
+         * TODO: 'invent' a good block size.
          */
         nBlockXSize = nRasterXSize;
         nBlockYSize = nRasterYSize;
 
         bRetValue = true;
-    }
-    else {
+    } else {
         switch (nMode) {
                 /**
                  * Each row is a different raster. Create subdatasets, one per row
                  **/
 
             case ONE_RASTER_PER_ROW:
+                {
 
                 for (i = 0; i < nTuples; i++) {
-                    nRid = atoi(PQgetvalue(poResult, i, 10));
-        
+                    nSrid = atoi(PQgetvalue(poResult, i, 10));
+
                     papszSubdatasets = CSLSetNameValue(papszSubdatasets,
                             CPLSPrintf("SUBDATASET_%d_NAME", (i + 1)),
                             CPLSPrintf("PG:%s schema=%s table=%s column=%s where='rid = %d'",
-                            pszValidConnectionString, pszSchema, pszTable, pszColumn, nRid));
+                            pszValidConnectionString, pszSchema, pszTable, pszColumn, nSrid));
 
                     papszSubdatasets = CSLSetNameValue(papszSubdatasets,
                             CPLSPrintf("SUBDATASET_%d_DESC", (i + 1)),
                             CPLSPrintf("PostGIS Raster at %s.%s (%s), rid = %d", pszSchema,
-                            pszTable, pszColumn, nRid));
+                            pszTable, pszColumn, nSrid));
                 }
 
                 /* Not a single raster fetched */
@@ -430,28 +450,21 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
                 nRasterYSize = 0;
 
                 bRetValue = true;
+
+                }
                 break;
 
                 /************************************************************
-                 * All rows form a whole raster coverage. So, all rows must:
-                 *  - have the same srid
-                 *  - snap to the same grid
-                 * TODO: Work even if this requisites are  not complained. For
-                 * example, by:
-                 *  - Resampling all the rows to the grid of the first one
-                 *  - Providing a new grid alignment for all the rows, with a
-                 *    maximum of 6 parameters: ulx, uly, pixelsizex, pixelsizey,
-                 *    skewx, skewy or a minimum of 3 parameters: ulx, uly,
-                 *    pixelsize (x and y pixel sizes are equal and both skew are
-                 *    0).
-                 ************************************************************/
+                 * All rows form a whole raster coverage
+                ************************************************************/
             case ONE_RASTER_PER_TABLE:
+                {
 
                 /**
                  * Get the rest of raster properties from this object
                  */
                 nSrid = atoi(PQgetvalue(poResult, 0, 8));
-                    
+
                 nBands = atoi(PQgetvalue(poResult, 0, 9));
                 adfGeoTransform[0] = atof(PQgetvalue(poResult, 0, 0)); //upperleft x
                 adfGeoTransform[1] = atof(PQgetvalue(poResult, 0, 4)); //pixelsize x
@@ -459,12 +472,110 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
                 adfGeoTransform[3] = atof(PQgetvalue(poResult, 0, 1)); //upperleft y
                 adfGeoTransform[4] = atof(PQgetvalue(poResult, 0, 7)); //skew y
                 adfGeoTransform[5] = atof(PQgetvalue(poResult, 0, 5)); //pixelsize y
+                nWidth = atoi(PQgetvalue(poResult, 0, 2));
+                nHeight = atoi(PQgetvalue(poResult, 0, 3));
+
+                /**
+                 * Now check if all tiles have the same dimensions.
+                 *
+                 * NOTE: If bRegularBlocking is 'true', this is not checked.
+                 * It's user responsibility
+                 *
+                 * TODO: Find a good block size, that works in any situation.
+                 **/
+                if (!bRegularBlocking) 
+                {
+                    for(i = 1; i < nTuples; i++)
+                    {
+                        nTmpWidth = atoi(PQgetvalue(poResult, i, 2));
+                        nTmpHeight = atoi(PQgetvalue(poResult, i, 3));
+
+                        if (nWidth != nTmpWidth || nHeight != nTmpHeight)
+                        {
+                            // Not supported until the above TODO is implemented
+                            CPLError(CE_Failure, CPLE_AppDefined,
+                                "Error, the table %s.%s contains tiles with "
+                                "different size, and irregular blocking is "
+                                "not supported yet", pszSchema, pszTable);
+
+                            PQclear(poResult);
+                            return false;                             
+                        }
+                    }
+
+                    // Now, we can ensure this
+                    bRegularBlocking = true;
+                    nBlockXSize = nWidth;
+                    nBlockYSize = nHeight;
+                }
+
+                // The user ensures this...
+                else
+                {                                        
+                    nBlockXSize = nWidth;
+                    nBlockYSize = nHeight;
+                }
+
+                /**
+                 * Check all the raster tiles have the same srid and snap to the
+                 * same grid. If not, return an error
+                 *
+                 * NOTE: If bAllTilesSnapToSameGrid is 'true', this is not
+                 * checked. It's user responsibility.
+                 *
+                 * TODO: Work even if this requisites are  not complained. For
+                 * example, by:
+                 *  - Resampling all the rows to the grid of the first one
+                 *  - Providing a new grid alignment for all the rows, with a
+                 *    maximum of 6 parameters: ulx, uly, pixelsizex, pixelsizey,
+                 *    skewx, skewy or a minimum of 3 parameters: ulx, uly,
+                 *    pixelsize (x and y pixel sizes are equal and both skew are
+                 *    0).
+                 **/
+                if (!bAllTilesSnapToSameGrid)
+                {
+                    for(i = 1; i < nTuples; i++)
+                    {
+                        nTmpSrid = atoi(PQgetvalue(poResult, i, 8));
+                        dfTmpScaleX = atof(PQgetvalue(poResult, i, 4));
+                        dfTmpScaleY = atof(PQgetvalue(poResult, i, 5));
+                        dfTmpSkewX = atof(PQgetvalue(poResult, i, 6));
+                        dfTmpSkewY = atof(PQgetvalue(poResult, i, 7));
+
+                        if (nTmpSrid != nSrid ||
+                                FLT_NEQ(dfTmpScaleX, adfGeoTransform[1]) ||
+                                FLT_NEQ(dfTmpScaleY, adfGeoTransform[5]) ||
+                                FLT_NEQ(dfTmpSkewX, adfGeoTransform[2]) ||
+                                FLT_NEQ(dfTmpSkewY, adfGeoTransform[4]))
+                        {
+                            /**
+                             * In this mode, it is not allowed this situation,
+                             * unless while the above TODO is not implemented
+                             **/
+                            CPLError(CE_Failure, CPLE_AppDefined,
+                                "Error, the table %s.%s contains tiles with "
+                                "different SRID or snapping to different grids",
+                                pszSchema, pszTable);
+
+                            PQclear(poResult);
+                            return false;
+                        }
+                    }
+
+                    // Now, we can ensure this
+                    bAllTilesSnapToSameGrid = true;
+                }
+
+                /**
+                 * Now, if there's irregular blocking and/or the blocks don't
+                 * snap to the same grid or don't have the same srid, we should
+                 * fix these situations. Assuming that we don't return an error
+                 * in that cases, of course.
+                 **/
+
 
-                /* WARNING: Only valid in case of regular blocking */
-                nBlockXSize = atoi(PQgetvalue(poResult, 0, 2));
-                nBlockYSize = atoi(PQgetvalue(poResult, 0, 3));
-               
-                /** 
+
+                /**
                  * Get whole raster extent
                  **/
                 if (pszWhere == NULL)
@@ -473,7 +584,7 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
                 else
                     osCommand2.Printf("select st_astext(st_setsrid(st_extent(%s::geometry),%d)) from %s.%s where %s",
                         pszColumn, nSrid, pszSchema, pszTable, pszWhere);
-                
+
 
                 poResult2 = PQexec(poConn, osCommand2.c_str());
                 if (poResult2 == NULL ||
@@ -494,7 +605,7 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
 
                 /* Construct an OGR object with the raster extent */
                 pszExtent = PQgetvalue(poResult2, 0, 0);
-                
+
                 pszProjectionRef = (char*) GetProjectionRef();
                 poSR = new OGRSpatialReference(pszProjectionRef);
                 OgrErr = OGRGeometryFactory::createFromWkt(&pszExtent,
@@ -510,16 +621,11 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
                         PQclear(poResult);
 
                     return false;
-                }               
+                }
 
                 poE = new OGREnvelope();
                 poGeom->getEnvelope(poE);
 
-                nRasterXSize = (int)
-                        fabs(rint((poE->MaxX - poE->MinX) / adfGeoTransform[1]));
-                nRasterYSize = (int)
-                        fabs(rint((poE->MaxY - poE->MinY) / adfGeoTransform[5]));
-
                 /* Correction for upper left y coord*/
 
                 /**
@@ -530,30 +636,58 @@ GBool PostGISRasterDataset::SetRasterProperties(const char* pszValidConnectionSt
                  * is un upper-left corner. In this case, the upper left Y value
                  * will be MaxY from the envelope. Otherwise, it will be MinY.
                  **/
+                /*
                 adfGeoTransform[0] = poE->MinX;
                 if (adfGeoTransform[5] >= 0.0)
                     adfGeoTransform[3] = poE->MinY;
                 else
                     adfGeoTransform[3] = poE->MaxY;
+                */
+
+                /**
+                 * The raster size is the extent covered for all the raster's
+                 * columns
+                 **/
+                nRasterXSize = (int)
+                        fabs(rint((poE->MaxX - poE->MinX) / adfGeoTransform[1]));
+                nRasterYSize = (int)
+                        fabs(rint((poE->MaxY - poE->MinY) / adfGeoTransform[5]));
+
 
                 /* Free resources */
                 OGRGeometryFactory::destroyGeometry(poGeom);
-                delete poE;                                
+                delete poE;
                 delete poSR;
                 PQclear(poResult2);
 
                 bRetValue = true;
+
+                }
                 break;
 
                 /* TODO: take into account more cases, if applies */
             default:
+                {
                 CPLError(CE_Failure, CPLE_AppDefined,
                         "Error, incorrect working mode");
 
                 bRetValue = false;
+                }
         }
     }
 
+    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
+            "adfGeoTransform = {%f, %f, %f, %f, %f,%f}", adfGeoTransform[0],
+            adfGeoTransform[1], adfGeoTransform[2], adfGeoTransform[3],
+            adfGeoTransform[4], adfGeoTransform[5]);
+
+    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
+            "Raster size = (%d, %d)", nRasterXSize, nRasterYSize);
+
+
+    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::SetRasterProperties(): "
+            "Block dimensions = (%d x %d)", nBlockXSize, nBlockYSize);
+
     PQclear(poResult);
     return bRetValue;
 }
@@ -577,11 +711,10 @@ GBool PostGISRasterDataset::SetRasterBands() {
     for (iBand = 0; iBand < nBands; iBand++) {
         /* Create query to fetch metadata from db */
         if (pszWhere == NULL) {
-            osCommand.Printf("select (foo.md).* from (select" 
+            osCommand.Printf("select (foo.md).* from (select"
                     " distinct st_bandmetadata( %s, %d) as md from %s. %s) as foo",
                     pszColumn, iBand + 1, pszSchema, pszTable);
-        }
-        else {
+        } else {
 
             osCommand.Printf("select (foo.md).* from (select"
                     " distinct st_bandmetadata( %s, %d) as md from %s. %s where %s) as foo",
@@ -606,9 +739,15 @@ GBool PostGISRasterDataset::SetRasterBands() {
         /**
          * 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?
+         * 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 \
@@ -617,6 +756,7 @@ GBool PostGISRasterDataset::SetRasterBands() {
             PQclear(poResult);
             return false;
         }
+         */
 
 
         /* Get metadata and create raster band objects */
@@ -627,20 +767,16 @@ GBool PostGISRasterDataset::SetRasterBands() {
         if (EQUALN(pszDataType, "1BB", 3 * sizeof (char))) {
             hDataType = GDT_Byte;
             nBitDepth = 1;
-        }
-        else if (EQUALN(pszDataType, "2BUI", 4 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "2BUI", 4 * sizeof (char))) {
             hDataType = GDT_Byte;
             nBitDepth = 2;
-        }
-        else if (EQUALN(pszDataType, "4BUI", 4 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "4BUI", 4 * sizeof (char))) {
             hDataType = GDT_Byte;
             nBitDepth = 4;
-        }
-        else if (EQUALN(pszDataType, "8BUI", 4 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "8BUI", 4 * sizeof (char))) {
             hDataType = GDT_Byte;
             nBitDepth = 8;
-        }
-        else if (EQUALN(pszDataType, "8BSI", 4 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "8BSI", 4 * sizeof (char))) {
             hDataType = GDT_Byte;
             /**
              * To indicate the unsigned byte values between 128 and 255
@@ -652,28 +788,22 @@ GBool PostGISRasterDataset::SetRasterBands() {
         } else if (EQUALN(pszDataType, "16BSI", 5 * sizeof (char))) {
             hDataType = GDT_Int16;
             nBitDepth = 16;
-        }
-        else if (EQUALN(pszDataType, "16BUI", 5 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "16BUI", 5 * sizeof (char))) {
             hDataType = GDT_UInt16;
             nBitDepth = 16;
-        }
-        else if (EQUALN(pszDataType, "32BSI", 5 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "32BSI", 5 * sizeof (char))) {
             hDataType = GDT_Int32;
             nBitDepth = 32;
-        }
-        else if (EQUALN(pszDataType, "32BUI", 5 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "32BUI", 5 * sizeof (char))) {
             hDataType = GDT_UInt32;
             nBitDepth = 32;
-        }
-        else if (EQUALN(pszDataType, "32BF", 4 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "32BF", 4 * sizeof (char))) {
             hDataType = GDT_Float32;
             nBitDepth = 32;
-        }
-        else if (EQUALN(pszDataType, "64BF", 4 * sizeof (char))) {
+        } else if (EQUALN(pszDataType, "64BF", 4 * sizeof (char))) {
             hDataType = GDT_Float64;
             nBitDepth = 64;
-        }
-        else {
+        } else {
             hDataType = GDT_Byte;
             nBitDepth = 8;
         }
@@ -689,8 +819,408 @@ GBool PostGISRasterDataset::SetRasterBands() {
     return true;
 }
 
+/**
+ * Read/write a region of image data from multiple bands.
+ *
+ * This method allows reading a region of one or more PostGISRasterBands from
+ * this dataset into a buffer. The write support is still under development
+ *
+ * The function fetches all the raster data that intersects with the region
+ * provided, and store the data in the GDAL cache.
+ *
+ * TODO: This only works in case of regular blocking rasters. A more
+ * general approach to allow non-regular blocking rasters is under development.
+ *
+ * It automatically takes care of data type translation if the data type
+ * (eBufType) of the buffer is different than that of the
+ * PostGISRasterRasterBand.
+ *
+ * TODO: The method should take care of image decimation / replication if the
+ * buffer size (nBufXSize x nBufYSize) is different than the size of the region
+ * being accessed (nXSize x nYSize).
+ *
+ * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
+ * writing from various organization of buffers.
+ *
+ * @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 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.
+ *
+ * @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 pData data buffer. The
+ * pixel values will automatically be translated to/from the
+ * PostGISRasterRasterBand 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 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
+ * 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.
+ *
+ * @return CE_Failure if the access fails, otherwise CE_None.
+ */
+CPLErr PostGISRasterDataset::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)
+{
+    double adfTransform[6];
+    double adfProjWin[8];
+    int ulx, uly, lrx, lry;
+    CPLString osCommand;
+    PGresult* poResult = NULL;
+    int nTuples = 0;
+    int iTuplesIndex = 0;
+    GByte* pbyData = NULL;
+    int nWKBLength = 0;
+    int iBandIndex;
+    GDALRasterBlock * poBlock = NULL;
+    int iBlockXOff, iBlockYOff;
+    int nBandDataSize, nBandDataLength;
+    char * pBandData = NULL;
+    PostGISRasterRasterBand * poBand = NULL;
+    GByte * pabySrcBlock = NULL;
+    int nBlocksPerRow, nBlocksPerColumn;
+    char orderByY[4];
+    char orderByX[3];
+    int rid;
+
+
+    /**
+     * TODO: Write support not implemented yet
+     **/
+    if (eRWFlag == GF_Write)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "PostGIS Raster does not support writing");
+        return CE_Failure;
+    }
+
+    /**
+     * TODO: Data decimation / replication needed
+     */
+    if (nBufXSize != nXSize || nBufYSize != nYSize)
+    {
+        /**
+         * This will cause individual IReadBlock calls
+         *
+         */
+        return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                pData, nBufXSize, nBufYSize, eBufType, nBandCount,
+                panBandMap, nPixelSpace, nLineSpace, nBandSpace);
+    }
+        
+    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO: "
+            "nBandSpace = %d, nLineSpace = %d, nPixelSpace = %d",
+            nBandSpace, nLineSpace, nPixelSpace);
+
+    /**************************************************************************
+     * In the first call, we fetch the data from database and store it as
+     * 'blocks' in the cache.
+     *
+     * TODO: If the data is not cached, we must 'invent' a good block size, and
+     * divide the data in blocks. To get a proper block size, we should rewrite
+     * the GetBlockSize function at band level.
+     ***************************************************************************/
+    if (!bBlocksCached)
+    {
+        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO: "
+                "Buffer size = (%d, %d), Region size = (%d, %d)",
+                nBufXSize, nBufYSize, nXSize, nYSize);
+
+        /*******************************************************************
+         * Construct a projected window to intersect the band data
+         *******************************************************************/
+        GetGeoTransform(adfTransform);
+        ulx = nXOff;
+        uly = nYOff;
+        lrx = nXOff + nXSize;
+        lry = nYOff + nYSize;
+
+        /* Calculate the intersection polygon */
+        adfProjWin[0] = adfTransform[0] +
+            ulx * adfTransform[1] +
+            uly * adfTransform[2];
+
+        adfProjWin[1] = adfTransform[3] +
+            ulx * adfTransform[4] +
+            uly * adfTransform[5];
+
+        adfProjWin[2] = adfTransform[0] +
+            lrx * adfTransform[1] +
+            uly * adfTransform[2];
+
+        adfProjWin[3] = adfTransform[3] +
+            lrx * adfTransform[4] +
+            uly * adfTransform[5];
+
+        adfProjWin[4] = adfTransform[0] +
+            lrx * adfTransform[1] +
+            lry * adfTransform[2];
+
+        adfProjWin[5] = adfTransform[3] +
+            lrx * adfTransform[4] +
+            lry * adfTransform[5];
+
+        adfProjWin[6] = adfTransform[0] +
+            ulx * adfTransform[1] +
+            lry * adfTransform[2];
+
+        adfProjWin[7] = adfTransform[3] +
+            ulx * adfTransform[4] +
+            lry * adfTransform[5];
+
+
+        /* Construct order by for the query */
+        memset(orderByX, 0, 3);
+        memset(orderByY, 0, 4);
+
+        strcpy(orderByX, "asc");
+        if (nSrid == -1)
+            strcpy(orderByY, "asc"); // Y starts at 0 and grows
+        else
+            strcpy(orderByY, "desc");// Y starts at max and decreases
+ 
+
+        /*********************************************************************
+        * We first get the data from database (ordered from upper left pixel
+        * to lower right one)
+        *********************************************************************/
+        if (pszWhere == NULL)
+        {
+            osCommand.Printf("SELECT rid, %s, ST_ScaleX(%s), ST_SkewY(%s), "
+                "ST_SkewX(%s), ST_ScaleY(%s), ST_UpperLeftX(%s), "
+                "ST_UpperLeftY(%s), ST_Width(%s), ST_Height(%s) FROM %s.%s WHERE "
+                "ST_Intersects(%s, ST_PolygonFromText('POLYGON((%f %f, %f %f, %f %f"
+                ", %f %f, %f %f))', %d)) ORDER BY ST_UpperLeftY(%s) %s, "
+                "ST_UpperLeftX(%s) %s", pszColumn, pszColumn,
+                pszColumn, pszColumn, pszColumn, 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], nSrid, pszColumn, orderByY, pszColumn, orderByX);
+        }
+
+
+        else
+        {
+            osCommand.Printf("SELECT rid, %s ST_ScaleX(%s), ST_SkewY(%s), "
+                "ST_SkewX(%s), ST_ScaleY(%s), ST_UpperLeftX(%s), "
+                "ST_UpperLeftY(%s), ST_Width(%s), ST_Height(%s) FROM %s.%s WHERE %s AND "
+                "ST_Intersects(%s, ST_PolygonFromText('POLYGON((%f %f, %f %f, %f %f"
+                ", %f %f, %f %f))', %d)) ORDER BY ST_UpperLeftY(%s) %s, "
+                "ST_UpperLeftX(%s) %s", pszColumn, pszColumn,
+                pszColumn, pszColumn, pszColumn, pszColumn, pszColumn, pszColumn,
+                pszColumn,pszSchema, pszTable, pszWhere, pszColumn, adfProjWin[0],
+                adfProjWin[1], adfProjWin[2], adfProjWin[3], adfProjWin[4],
+                adfProjWin[5], adfProjWin[6], adfProjWin[7], adfProjWin[0],
+                adfProjWin[1], nSrid, pszColumn, orderByY, pszColumn, orderByX);
+        }
+
+        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): Query = %s",
+            osCommand.c_str());
+
+        poResult = PQexec(poConn, osCommand.c_str());
+        if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
+            PQntuples(poResult) <= 0)
+        {
+            if (poResult)
+                PQclear(poResult);
+
+            /**
+             * This will cause individual IReadBlock calls
+             *
+             */
+            return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                    pData, nBufXSize, nBufYSize, eBufType, nBandCount,
+                    panBandMap, nPixelSpace, nLineSpace, nBandSpace);
+        }
+
+        /**
+         * NOTE: In case of any of the raster columns have different SRID, the
+         * query will fail. So, if we don't fail, we can assume all the rows
+         * have the same SRID. We don't need to check it
+         **/
+
+
+        nTuples = PQntuples(poResult);
+        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): nTuples = %d",
+            nTuples);
+
+        CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): "
+            "Raster size = (%d, %d)", nRasterXSize, nRasterYSize);
+
+
+
+        /**************************************************************************
+         * This is the simplest case: all the rows have the same dimensions
+         * (regularly blocked raster)
+         *
+         * Now we'll cache each tuple as a data block. More accurately, we must
+         * access each tuple, get the band data, and store this data as a block. So,
+         * each tuple contains the data for nBands blocks (and nBandCount <=
+         * nBands)
+         *************************************************************************/
+        for(iBandIndex = 0; iBandIndex < nBandCount; iBandIndex++)
+        {
+            poBand = (PostGISRasterRasterBand *)GetRasterBand(iBandIndex + 1);
+
+            nBandDataSize = GDALGetDataTypeSize(poBand->eDataType) / 8;
+
+            nBandDataLength = poBand->nBlockXSize * poBand->nBlockYSize *
+                nBandDataSize;
+
+            CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): "
+                "Block size (%d, %d) for band %d", poBand->nBlockXSize,
+                poBand->nBlockYSize, poBand->nBand);
+
+            /* Enables block caching, if it wasn't enabled */
+            if (!poBand->InitBlockInfo())
+                continue;
+
+            /**
+             * This can be different from poBand->nBlocksPerRow and
+             * poBand->nBlocksPerColumn, if the region size is different than
+             * the raster size. So, we calculate these values for this case.
+             */
+            nBlocksPerRow =
+                    (nXSize + poBand->nBlockXSize - 1) / poBand->nBlockXSize;
+
+            nBlocksPerColumn =
+                    (nYSize + poBand->nBlockYSize - 1) / poBand->nBlockYSize;
+
+            CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): "
+                "Number of blocks: %dx%d", nBlocksPerRow, nBlocksPerColumn);
+
+            for(iBlockYOff = 0; iBlockYOff < nBlocksPerColumn;
+                    iBlockYOff++)
+            {
+                for(iBlockXOff = 0; iBlockXOff < nBlocksPerRow;
+                        iBlockXOff++)
+                {
+                    iTuplesIndex = (iBlockYOff * nBlocksPerRow) +
+                        iBlockXOff;
+
+                    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): "
+                            "iBlockXOff = %d, iBlockYOff = %d, "
+                            "iTuplesIndex = %d", iBlockXOff, iBlockYOff,
+                            iTuplesIndex);
+
+                    pbyData = CPLHexToBinary(PQgetvalue(poResult, iTuplesIndex,
+                            1), &nWKBLength);
+
+                    pBandData = (char *)GET_BAND_DATA(pbyData, poBand->nBand,
+                            nBandDataSize, nBandDataLength);
+
+                    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): "
+                        "Block data length for band %d: %d", poBand->nBand,
+                        nBandDataLength);
+
+                    CPLDebug("PostGIS_Raster", "PostGISRasterDataset::IRasterIO(): "
+                        "Block (%d, %d)", iBlockXOff, iBlockYOff);
+
+                    /* Create a new block */
+                    poBlock = new GDALRasterBlock(poBand, iBlockXOff,
+                            iBlockYOff);
+
+                    poBlock->AddLock();
+
+                    /* Allocate data space */
+                    if (poBlock->Internalize() != CE_None)
+                    {
+                        poBlock->DropLock();
+                        delete poBlock;
+                        continue;
+                    }
+
+                    /* Add the block to the block matrix */
+                    if (poBand->AdoptBlock(iBlockXOff, iBlockYOff, poBlock) !=
+                            CE_None)
+                    {
+                        poBlock->DropLock();
+                        delete poBlock;
+                        continue;
+                    }
+
+                    /**
+                     * Copy data to block
+                     *
+                     * TODO: Enable write mode too (mark the block as dirty and
+                     * create IWriteBlock in PostGISRasterRasterBand)
+                     */
+                    pabySrcBlock = (GByte *)poBlock->GetDataRef();
+
+                    if (poBand->eDataType == eBufType)
+                    {
+                        memcpy(pabySrcBlock, pBandData, nBandDataLength);
+                    }
+
+                    /**
+                     * As in GDALDataset class... expensive way of handling
+                     * single words
+                     */
+                    else
+                    {
+                        GDALCopyWords(pBandData, poBand->eDataType, 0,
+                                pabySrcBlock, eBufType, 0, 1);
+                    }
+
+                    poBlock->DropLock();
+
+                    CPLFree(pbyData);
+                    pbyData = NULL;
+                }
+
+            }
+
+        }
+
+        PQclear(poResult);
+        bBlocksCached = true;
+    }
+
+    /* Once the blocks are cached, we delegate in GDAL I/O system */
+    return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+            nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
+            nLineSpace, nBandSpace);
+}
+
 /******************************************************************************
- * \brief Open a connection with PostgreSQL. The connection string will have 
+ * \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>
@@ -726,9 +1256,9 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
             !EQUALN(poOpenInfo->pszFilename, "PG:", 3) ||
             (papszParams = ParseConnectionString(poOpenInfo->pszFilename)) == NULL) {
         /**
-         * 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 
+         * 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
          */
         return NULL;
@@ -744,7 +1274,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
                 "PostGIS Raster driver not registered");
         return NULL;
     }
-    */
+     */
 
     /***************************************************************
      * Now check existence of db, schema, table, column and where.
@@ -763,7 +1293,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
     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 */
             /*
@@ -771,15 +1301,14 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
                     " 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;
         }
 
         /* Remove the mode from connection string */
         papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
     }
-
-    /* Default mode */
+        /* Default mode */
     else
         nMode = ONE_RASTER_PER_ROW;
 
@@ -826,8 +1355,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
         }
-    }
-    else {
+    } else {
         pszTable = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
         /* Delete this pair from params array */
         papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
@@ -840,8 +1368,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         nPos = CSLFindName(papszParams, "column");
         if (nPos == -1) {
             pszColumn = CPLStrdup(DEFAULT_COLUMN);
-        }
-            /**
+        }            /**
              * Case 4: There's database, table and column name: Use the table to
              * create a dataset
              **/
@@ -855,8 +1382,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         nPos = CSLFindName(papszParams, "schema");
         if (nPos == -1) {
             pszSchema = CPLStrdup(DEFAULT_SCHEMA);
-        }
-        else {
+        } else {
             pszSchema = CPLStrdup(CPLParseNameValue(papszParams[nPos], NULL));
             /* Delete this pair from params array */
             papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
@@ -928,7 +1454,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
 
         return NULL;
     }
-    */
+     */
 
 
     /* Frees no longer needed memory */
@@ -940,10 +1466,9 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
      * TODO: Try to get connection from poDriver
      **/
     poConn = PQconnectdb(pszValidConnectionString);
-    if (poConn == NULL)
-    {
+    if (poConn == NULL) {
         CPLError(CE_Failure, CPLE_AppDefined,
-                "Couldn't establish a database connection");        
+                "Couldn't establish a database connection");
         if (pszSchema)
             CPLFree(pszSchema);
         if (pszTable)
@@ -954,9 +1479,9 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
             CPLFree(pszWhere);
 
         return NULL;
-        
+
     }
-    
+
     /* Check geometry type existence */
     poResult = PQexec(poConn, "SELECT oid FROM pg_type WHERE typname = 'geometry'");
     if (
@@ -977,7 +1502,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
             CPLFree(pszColumn);
         if (pszWhere)
             CPLFree(pszWhere);
-        
+
         PQfinish(poConn);
 
         //delete poDriver;
@@ -1074,7 +1599,10 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         poDS->pszColumn = pszColumn;
         poDS->pszWhere = pszWhere;
 
-        /* Fetch basic raster metadata from db */
+        /**
+         * Fetch basic raster metadata from db
+         **/
+
         if (!poDS->SetRasterProperties(pszValidConnectionString)) {
             CPLFree(pszValidConnectionString);
             delete poDS;
@@ -1087,7 +1615,7 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
             delete poDS;
             return NULL;
         }
-        
+
     }
 
     CPLFree(pszValidConnectionString);
@@ -1108,9 +1636,9 @@ char** PostGISRasterDataset::GetMetadata(const char *pszDomain) {
 }
 
 /*****************************************************
- * \brief Fetch the projection definition string 
- * for this dataset in OpenGIS WKT format. It should 
- * be suitable for use with the OGRSpatialReference 
+ * \brief Fetch the projection definition string
+ * for this dataset in OpenGIS WKT format. It should
+ * be suitable for use with the OGRSpatialReference
  * class.
  *****************************************************/
 const char* PostGISRasterDataset::GetProjectionRef() {
@@ -1148,8 +1676,7 @@ const char* PostGISRasterDataset::GetProjectionRef() {
  * \brief Set projection definition. The input string must
  * be in OGC WKT or PROJ.4 format
  **********************************************************/
-CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef)
-{
+CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
     VALIDATE_POINTER1(pszProjectionRef, "SetProjection", CE_Failure);
 
     CPLString osCommand;
@@ -1200,23 +1727,22 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef)
 
         return CE_None;
     }
-
-    // If not, proj4 text
+        // If not, proj4 text
     else {
         osCommand.Printf(
                 "SELECT srid FROM spatial_ref_sys where proj4text='%s'",
-            pszProjectionRef);
+                pszProjectionRef);
         poResult = PQexec(poConn, osCommand.c_str());
 
         if (poResult && PQresultStatus(poResult) == PGRES_TUPLES_OK
-            && PQntuples(poResult) > 0) {
+                && PQntuples(poResult) > 0) {
 
             nFetchedSrid = atoi(PQgetvalue(poResult, 0, 0));
 
             // update class attribute
             nSrid = nFetchedSrid;
 
-            // update raster_columns table            
+            // update raster_columns table
             osCommand.Printf("UPDATE raster_columns SET srid=%d WHERE \
                     r_table_name = '%s' AND r_column = '%s'",
                     nSrid, pszTable, pszColumn);
@@ -1234,7 +1760,6 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef)
 
             return CE_None;
         }
-
         else {
             CPLError(CE_Failure, CPLE_WrongFormat,
                     "Couldn't find WKT neither proj4 definition");
@@ -1278,6 +1803,7 @@ CPLErr PostGISRasterDataset::GetGeoTransform(double * padfTransform) {
 
 /************************************************************************/
 /*                          GDALRegister_PostGISRaster()                    */
+
 /************************************************************************/
 void GDALRegister_PostGISRaster() {
     GDALDriver *poDriver;
diff --git a/frmts/postgisraster/postgisrasterrasterband.cpp b/frmts/postgisraster/postgisrasterrasterband.cpp
index fc3f791..d64591c 100644
--- a/frmts/postgisraster/postgisrasterrasterband.cpp
+++ b/frmts/postgisraster/postgisrasterrasterband.cpp
@@ -8,7 +8,7 @@
  * $Id: $
  *
  ******************************************************************************
- * Copyright (c) 2010, Jorge Arevalo, jorgearevalo at gis4free.org
+ * Copyright (c) 2009 - 2011, Jorge Arevalo, jorge.arevalo at deimos-space.com
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -185,6 +185,8 @@ PostGISRasterRasterBand::PostGISRasterRasterBand(PostGISRasterDataset *poDS,
         nRasterYSize = (int) floor((double)poDS->GetRasterYSize() / nOverviewFactor);        
     }
 
+    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand constructor: Band "
+            "created (srid = %d)", poDS->nSrid);
 }
 
 /***********************************************
@@ -379,7 +381,7 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
     /* Get pixel and block size */
     nPixelSize = MAX(1,GDALGetDataTypeSize(eDataType)/8);
     GetBlockSize(&nNaturalBlockXSize, &nNaturalBlockYSize);
-
+    
     /* Get pixel,line coordinates of the block */
     /**
      * TODO: What if the georaster is rotated? Following the gdal_translate
@@ -438,9 +440,9 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
      **/
     if (poPostGISRasterDS->pszWhere != NULL)
     {
-        osCommand.Printf("select rid, %s from %s.%s where %s ~"
-                "st_setsrid(st_makebox2d(st_point(%f, %f), st_point(%f, %f)),%d)"
-                " and %s", pszColumn, pszSchema, pszTable, pszColumn, 
+        osCommand.Printf("select rid, %s from %s.%s where %s ~ "
+                "st_setsrid(st_makebox2d(st_point(%f, %f), st_point(%f,"
+                "%f)),%d) and %s", pszColumn, pszSchema, pszTable, pszColumn, 
                 dfProjLowerLeftX, dfProjLowerLeftY, dfProjUpperRightX,
                 dfProjUpperRightY, poPostGISRasterDS->nSrid, pszWhere);
     }
@@ -448,12 +450,15 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
     else
     {
         osCommand.Printf("select rid, %s from %s.%s where %s ~ "
-                "st_setsrid(st_makebox2d(st_point(%f, %f), st_point(%f, %f)),%d)",
-                pszColumn, pszSchema, pszTable, pszColumn, dfProjLowerLeftX, 
-                dfProjLowerLeftY, dfProjUpperRightX, dfProjUpperRightY, 
-                poPostGISRasterDS->nSrid);
+                "st_setsrid(st_makebox2d(st_point(%f, %f), st_point(%f,"
+                "%f)),%d)", pszColumn, pszSchema, pszTable, pszColumn, 
+                dfProjLowerLeftX, dfProjLowerLeftY, dfProjUpperRightX, 
+                dfProjUpperRightY, poPostGISRasterDS->nSrid);
     }
 
+    CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IReadBlock: "
+            "The query = %s", osCommand.c_str());
+
     poResult = PQexec(poPostGISRasterDS->poConn, osCommand.c_str());
     if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK ||
             PQntuples(poResult) <= 0)
@@ -462,6 +467,8 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
             PQclear(poResult);
 
         /* TODO: Raise an error and exit? */
+        CPLDebug("PostGIS_Raster", "PostGISRasterRasterBand::IReadBlock: "
+                "The block (%d, %d) is empty", nBlockXOff, nBlockYOff);
         NullBlock(pImage);
         return CE_None;
     }
@@ -482,6 +489,8 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
             return CE_Failure;
         }
 
+        int nRid = atoi(PQgetvalue(poResult, 0, 0));
+        
         /* Only data size, without payload */
         nExpectedDataSize = nNaturalBlockXSize * nNaturalBlockYSize *
             nPixelSize;
@@ -490,6 +499,10 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
                 nExpectedDataSize);
 
         memcpy(pImage, pbyDataToRead, nExpectedDataSize * sizeof(char));
+        
+        CPLDebug("PostGIS_Raster", "IReadBlock: Copied %d bytes from block "
+                "(%d, %d) (rid = %d) to %p", nExpectedDataSize, nBlockXOff, 
+                nBlockYOff, nRid, pImage);
 
         CPLFree(pbyData);
         PQclear(poResult);
@@ -504,8 +517,8 @@ CPLErr PostGISRasterRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void*
     else
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                "Overlapping raster data. Feature under development, not available"
-                "yet");
+                "Overlapping raster data. Feature under development, not "
+                "available yet");
         if (poResult)
             PQclear(poResult);
 
diff --git a/frmts/rasdaman/rasdamandataset.cpp b/frmts/rasdaman/rasdamandataset.cpp
index d8421da..e6c2011 100644
--- a/frmts/rasdaman/rasdamandataset.cpp
+++ b/frmts/rasdaman/rasdamandataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasdamandataset.cpp 20597 2010-09-12 22:03:49Z rouault $
+ * $Id: rasdamandataset.cpp 23362 2011-11-11 11:11:52Z rouault $
  * Project:  rasdaman Driver
  * Purpose:  Implement Rasdaman GDAL driver 
  * Author:   Constantin Jucovschi, jucovschi at yahoo.com
@@ -42,7 +42,7 @@
 
 #include "rasodmg/database.hh"
 
-CPL_CVSID("$Id: rasdamandataset.cpp 20597 2010-09-12 22:03:49Z rouault $");
+CPL_CVSID("$Id: rasdamandataset.cpp 23362 2011-11-11 11:11:52Z rouault $");
 
 
 CPL_C_START
@@ -69,8 +69,6 @@ class RasdamanDataset : public GDALPamDataset
     
     static GDALDataset *Open( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
-
 private:
   void getTypes(const r_Base_Type* baseType, int &counter, int pos);
   void createBands(const char* queryString);
@@ -219,22 +217,6 @@ RasdamanDataset::~RasdamanDataset()
 }
 
 /************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr RasdamanDataset::GetGeoTransform( double * padfTransform )
-
-{
-    padfTransform[0] = 0.0;
-    padfTransform[1] = 1.0;
-    padfTransform[2] = 0.0;
-    padfTransform[3] = 0.0;
-    padfTransform[4] = 0.0;
-    padfTransform[5] = 1.0;
-    return CE_None;
-}
-
-/************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
diff --git a/frmts/rasterlite/frmt_rasterlite.html b/frmts/rasterlite/frmt_rasterlite.html
index 4905d7f..9be9ceb 100644
--- a/frmts/rasterlite/frmt_rasterlite.html
+++ b/frmts/rasterlite/frmt_rasterlite.html
@@ -65,7 +65,7 @@ recent enough sqlite3 library is needed to read rasterlite databases. rasterlite
 <li><p><b>DRIVER</b>=[GTiff/GIF/PNG/JPEG/EPSILON/...] : name of the GDAL driver to use for storing tiles. Defaults to GTiff</p></li>
 <li><p><b>COMPRESS</b>=[LZW/JPEG/DEFLATE/...] : (GTiff driver) name of the compression method</p></li>
 <li><p><b>PHOTOMETRIC</b>=[RGB/YCbCr/...] : (GTiff driver) photometric interpretation</p></li>
-<li><p><b>QUALITY</b> : (GTiff / JPEG drivers) JPEG quality 1-100. Defaults to 75</p></li>
+<li><p><b>QUALITY</b> : (JPEG-compressed GTiff, JPEG and WEBP drivers) JPEG/WEBP quality 1-100. Defaults to 75</p></li>
 <li><p><b>TARGET</b> : (EPSILON driver) target size reduction as a percentage of the original (0-100). Defaults to 96.</p></li>
 <li><p><b>FILTER</b> : (EPSILON driver) Filter ID. Defaults to 'daub97lift'.</p></li>
 </ul>
diff --git a/frmts/rasterlite/rasterlitecreatecopy.cpp b/frmts/rasterlite/rasterlitecreatecopy.cpp
index 3f66cd0..e0c05fc 100644
--- a/frmts/rasterlite/rasterlitecreatecopy.cpp
+++ b/frmts/rasterlite/rasterlitecreatecopy.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterlitecreatecopy.cpp 20090 2010-07-17 22:18:37Z rouault $
+ * $Id: rasterlitecreatecopy.cpp 22035 2011-03-25 23:57:59Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
@@ -33,7 +33,7 @@
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterlitecreatecopy.cpp 20090 2010-07-17 22:18:37Z rouault $");
+CPL_CVSID("$Id: rasterlitecreatecopy.cpp 22035 2011-03-25 23:57:59Z rouault $");
 
 /************************************************************************/
 /*                  RasterliteGetTileDriverOptions ()                   */
@@ -85,7 +85,7 @@ static char** RasterliteGetTileDriverOptions(char** papszOptions)
             papszTileDriverOptions =
                 CSLSetNameValue(papszTileDriverOptions, "JPEG_QUALITY", pszQuality);
         }
-        else if (EQUAL(pszDriverName, "JPEG"))
+        else if (EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP"))
         {
             papszTileDriverOptions =
                 CSLSetNameValue(papszTileDriverOptions, "QUALITY", pszQuality);
@@ -332,6 +332,13 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
     
     const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
+    if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
+                 pszDriverName);
+        return NULL;
+    }
+
     GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
     if ( hTileDriver == NULL)
     {
@@ -646,7 +653,7 @@ RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Insert new entry into raster table                              */
 /* -------------------------------------------------------------------- */
 
-            vsi_l_offset nDataLength;
+            vsi_l_offset nDataLength = 0;
             GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
                                                    &nDataLength, FALSE);
 
diff --git a/frmts/rasterlite/rasterlitedataset.cpp b/frmts/rasterlite/rasterlitedataset.cpp
index 2039e22..0a076e9 100644
--- a/frmts/rasterlite/rasterlitedataset.cpp
+++ b/frmts/rasterlite/rasterlitedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterlitedataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: rasterlitedataset.cpp 23661 2011-12-29 22:54:32Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
@@ -34,7 +34,7 @@
 
 #include "rasterlitedataset.h"
 
-CPL_CVSID("$Id: rasterlitedataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: rasterlitedataset.cpp 23661 2011-12-29 22:54:32Z rouault $");
 
 /************************************************************************/
 /*                            RasterliteBand()                          */
@@ -119,6 +119,13 @@ CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
     while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL )
     {
         OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
+        if (hGeom == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "null geometry found");
+            OGR_F_Destroy(hFeat);
+            OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
+            return CE_Failure;
+        }
         
         OGREnvelope oEnvelope;
         OGR_G_GetEnvelope(hGeom, &oEnvelope);
@@ -570,34 +577,66 @@ RasterliteDataset::RasterliteDataset(RasterliteDataset* poMainDS, int nLevel)
 
 RasterliteDataset::~RasterliteDataset()
 {
-    if (poMainDS == NULL)
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                      CloseDependentDatasets()                        */
+/************************************************************************/
+
+int RasterliteDataset::CloseDependentDatasets()
+{
+    int bRet = GDALPamDataset::CloseDependentDatasets();
+
+    if (poMainDS == NULL && !bMustFree)
     {
         CSLDestroy(papszMetadata);
+        papszMetadata = NULL;
         CSLDestroy(papszSubDatasets);
+        papszSubDatasets = NULL;
         CSLDestroy(papszImageStructure);
+        papszImageStructure = NULL;
         CPLFree(pszSRS);
+        pszSRS = NULL;
 
         if (papoOverviews)
         {
             int i;
             for(i=1;i<nResolutions;i++)
+            {
+                if (papoOverviews[i-1] != NULL &&
+                    papoOverviews[i-1]->bMustFree)
+                {
+                    papoOverviews[i-1]->poMainDS = NULL;
+                }
                 delete papoOverviews[i-1];
+            }
             CPLFree(papoOverviews);
+            papoOverviews = NULL;
+            nResolutions = 0;
+            bRet = TRUE;
         }
 
         if (hDS != NULL)
             OGRReleaseDataSource(hDS);
-            
+        hDS = NULL;
+
         CPLFree(padfXResolutions);
         CPLFree(padfYResolutions);
-        
+        padfXResolutions = padfYResolutions = NULL;
+
         delete poCT;
+        poCT = NULL;
     }
-    else if (bMustFree)
+    else if (poMainDS != NULL && bMustFree)
     {
         poMainDS->papoOverviews[nLevel-1] = NULL;
         delete poMainDS;
+        poMainDS = NULL;
+        bRet = TRUE;
     }
+
+    return bRet;
 }
 
 /************************************************************************/
@@ -932,7 +971,7 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
     /* fetch non spatial tables */
     CPLString osOldVal = CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "FALSE");
     CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
-    OGRDataSourceH hDS = OGROpen(osFileName.c_str(), TRUE, NULL);
+    OGRDataSourceH hDS = OGROpen(osFileName.c_str(), (poOpenInfo->eAccess == GA_Update) ? TRUE : FALSE, NULL);
     CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
     CPLDebug("RASTERLITE", "SQLite DB Open");
     
@@ -1099,7 +1138,10 @@ GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
         }
         else
         {
+            CPLString osOldVal = CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO");
+            CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", "YES");
             OGR_L_GetExtent(hMetadataLyr, &oEnvelope, TRUE);
+            CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", osOldVal.c_str());
             //printf("minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
             //       oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
         }
@@ -1315,7 +1357,7 @@ void GDALRegister_Rasterlite()
 "   <Option name='BLOCKYSIZE' type='int' default='256' description='Tile Height'/>"
 "   <Option name='DRIVER' type='string' default='GTiff' description='GDAL driver to use for storing tiles' default='GTiff'/>"
 "   <Option name='COMPRESS' type='string' default='(GTiff driver) Compression method' default='NONE'/>"
-"   <Option name='QUALITY' type='int' description='(GTiff / JPEG drivers) JPEG quality 1-100' default='75'/>"
+"   <Option name='QUALITY' type='int' description='(JPEG-compressed GTiff, JPEG and WEBP drivers) JPEG/WEBP Quality 1-100' default='75'/>"
 "   <Option name='PHOTOMETRIC' type='string-select' description='(GTiff driver) Photometric interpretation'>"
 "       <Value>MINISBLACK</Value>"
 "       <Value>MINISWHITE</Value>"
diff --git a/frmts/rasterlite/rasterlitedataset.h b/frmts/rasterlite/rasterlitedataset.h
index 3514391..5a3d7a6 100644
--- a/frmts/rasterlite/rasterlitedataset.h
+++ b/frmts/rasterlite/rasterlitedataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterlitedataset.h 17720 2009-09-30 22:32:20Z rouault $
+ * $Id: rasterlitedataset.h 21723 2011-02-15 19:52:18Z rouault $
  *
  * Project:  GDAL Rasterlite driver
  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
@@ -65,7 +65,10 @@ class RasterliteDataset : public GDALPamDataset
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
-    
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
   private:
   
     int bMustFree;
diff --git a/frmts/raw/GNUmakefile b/frmts/raw/GNUmakefile
index 0e1d9bf..ba8fa77 100644
--- a/frmts/raw/GNUmakefile
+++ b/frmts/raw/GNUmakefile
@@ -8,7 +8,7 @@ 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
+		ntv2dataset.o ace2dataset.o snodasdataset.o
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS)
 
diff --git a/frmts/raw/ace2dataset.cpp b/frmts/raw/ace2dataset.cpp
new file mode 100644
index 0000000..84eb5c4
--- /dev/null
+++ b/frmts/raw/ace2dataset.cpp
@@ -0,0 +1,400 @@
+/******************************************************************************
+ * $Id: ace2dataset.cpp 22163 2011-04-14 21:26:21Z rouault $
+ *
+ * Project:  ACE2 Driver
+ * Purpose:  Implementation of ACE2 elevation format read support.
+ *           http://tethys.eaprs.cse.dmu.ac.uk/ACE2/shared/documentation
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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 "rawdataset.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: ace2dataset.cpp 22163 2011-04-14 21:26:21Z rouault $");
+
+CPL_C_START
+void    GDALRegister_ACE2(void);
+CPL_C_END
+
+static const char * const apszCategorySource[] =
+{
+    "Pure SRTM (above 60deg N pure GLOBE data, below 60S pure ACE [original] data)",
+    "SRTM voids filled by interpolation and/or altimeter data",
+    "SRTM data warped using the ERS-1 Geodetic Mission",
+    "SRTM data warped using EnviSat & ERS-2 data",
+    "Mean lake level data derived from Altimetry",
+    "GLOBE/ACE data warped using combined altimetry (only above 60deg N)",
+    "Pure altimetry data (derived from ERS-1 Geodetic Mission, ERS-2 and EnviSat data using Delaunay Triangulation",
+    NULL
+};
+
+static const char * const apszCategoryQuality[] =
+{
+    "Generic - use base datasets",
+    "Accuracy of greater than +/- 16m",
+    "Accuracy between +/- 16m - +/- 10m",
+    "Accuracy between +/-10m - +/-5m",
+    "Accuracy between +/-5m - +/-1m",
+    "Accuracy between +/-1m",
+    NULL
+};
+
+static const char * const apszCategoryConfidence[] =
+{
+    "No confidence could be derived due to lack of data",
+    "Heights generated by interpolation",
+    "Low confidence",
+    "Low confidence",
+    "Low confidence",
+    "Medium confidence",
+    "Medium confidence",
+    "Medium confidence",
+    "Medium confidence",
+    "Medium confidence",
+    "Medium confidence",
+    "Medium confidence",
+    "Medium confidence",
+    "High confidence",
+    "High confidence",
+    "High confidence",
+    "High confidence",
+    "Inland water confidence",
+    "Inland water confidence",
+    "Inland water confidence",
+    "Inland water confidence",
+    "Inland water confidence",
+    NULL
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             ACE2Dataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class ACE2Dataset : public GDALPamDataset
+{
+    friend class ACE2RasterBand;
+
+    double       adfGeoTransform[6];
+
+  public:
+
+                ACE2Dataset();
+
+    virtual const char *GetProjectionRef(void);
+    virtual CPLErr GetGeoTransform( double * );
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ACE2RasterBand                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class ACE2RasterBand : public RawRasterBand
+{
+    public:
+            ACE2RasterBand(VSILFILE* fpRaw,
+                           GDALDataType eDataType,
+                           int nXSize, int nYSize);
+
+        virtual const char *GetUnitType();
+        virtual char **GetCategoryNames();
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             ACE2Dataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                            ACE2Dataset()                             */
+/************************************************************************/
+
+ACE2Dataset::ACE2Dataset()
+{
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr ACE2Dataset::GetGeoTransform( double * padfTransform )
+
+{
+    memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *ACE2Dataset::GetProjectionRef()
+
+{
+    return SRS_WKT_WGS84;
+}
+
+/************************************************************************/
+/*                          ACE2RasterBand()                            */
+/************************************************************************/
+
+ACE2RasterBand::ACE2RasterBand(VSILFILE* fpRaw,
+                               GDALDataType eDataType,
+                               int nXSize, int nYSize) :
+    RawRasterBand( fpRaw, 0, GDALGetDataTypeSize(eDataType) / 8,
+                   nXSize * GDALGetDataTypeSize(eDataType) / 8, eDataType,
+                   CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE)
+{
+}
+
+/************************************************************************/
+/*                             GetUnitType()                            */
+/************************************************************************/
+
+const char *ACE2RasterBand::GetUnitType()
+{
+    if (eDataType == GDT_Float32)
+        return "m";
+    else
+        return "";
+}
+
+/************************************************************************/
+/*                         GetCategoryNames()                           */
+/************************************************************************/
+
+char **ACE2RasterBand::GetCategoryNames()
+{
+    if (eDataType == GDT_Int16)
+    {
+        const char* pszName = poDS->GetDescription();
+        if (strstr(pszName, "_SOURCE_"))
+            return (char**) apszCategorySource;
+        else if (strstr(pszName, "_QUALITY_"))
+            return (char**) apszCategoryQuality;
+        else if (strstr(pszName, "_CONF_"))
+            return (char**) apszCategoryConfidence;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int ACE2Dataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    if (! (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "ACE2") ||
+           strstr(poOpenInfo->pszFilename, ".ACE2.gz") ||
+           strstr(poOpenInfo->pszFilename, ".ace2.gz")) )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ACE2Dataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+    const char* pszBasename = CPLGetBasename(poOpenInfo->pszFilename);
+    int nXSize = 0, nYSize = 0;
+
+    if (strlen(pszBasename) < 7)
+        return NULL;
+
+    /* Determine southwest coordinates from filename */
+
+    /* e.g. 30S120W_5M.ACE2 */
+    char pszLatLonValueString[4];
+    memset(pszLatLonValueString, 0, 4);
+    strncpy(pszLatLonValueString, &pszBasename[0], 2);
+    int southWestLat = atoi(pszLatLonValueString);
+    memset(pszLatLonValueString, 0, 4);
+    strncpy(pszLatLonValueString, &pszBasename[3], 3);
+    int southWestLon = atoi(pszLatLonValueString);
+
+    if(pszBasename[2] == 'N' || pszBasename[2] == 'n')
+        /*southWestLat = southWestLat*/;
+    else if(pszBasename[2] == 'S' || pszBasename[2] == 's')
+        southWestLat = southWestLat * -1;
+    else
+        return NULL;
+
+    if(pszBasename[6] == 'E' || pszBasename[6] == 'e')
+        /*southWestLon = southWestLon*/;
+    else if(pszBasename[6] == 'W' || pszBasename[6] == 'w')
+        southWestLon = southWestLon * -1;
+    else
+        return NULL;
+
+
+    GDALDataType eDT;
+    if (strstr(pszBasename, "_CONF_") ||
+        strstr(pszBasename, "_QUALITY_") ||
+        strstr(pszBasename, "_SOURCE_"))
+        eDT = GDT_Int16;
+    else
+        eDT = GDT_Float32;
+    int nWordSize = GDALGetDataTypeSize(eDT) / 8;
+
+    VSIStatBufL sStat;
+    if (strstr(pszBasename, "_5M"))
+        sStat.st_size = 180 * 180 * nWordSize;
+    else if (strstr(pszBasename, "_30S"))
+        sStat.st_size = 1800 * 1800 * nWordSize;
+    else if (strstr(pszBasename, "_9S"))
+        sStat.st_size = 6000 * 6000 * nWordSize;
+    else if (strstr(pszBasename, "_3S"))
+        sStat.st_size = 18000 * 18000 * nWordSize;
+    /* Check file size otherwise */
+    else if(VSIStatL(poOpenInfo->pszFilename, &sStat) != 0)
+    {
+        return NULL;
+    }
+
+    double dfPixelSize = 0;
+    if (sStat.st_size == 180 * 180 * nWordSize)
+    {
+        /* 5 minute */
+        nXSize = nYSize = 180;
+        dfPixelSize = 5. / 60;
+    }
+    else if (sStat.st_size == 1800 * 1800 * nWordSize)
+    {
+        /* 30 s */
+        nXSize = nYSize = 1800;
+        dfPixelSize = 30. / 3600;
+    }
+    else if (sStat.st_size == 6000 * 6000 * nWordSize)
+    {
+        /* 9 s */
+        nXSize = nYSize = 6000;
+        dfPixelSize = 9. / 3600;
+    }
+    else if (sStat.st_size == 18000 * 18000 * nWordSize)
+    {
+        /* 3 s */
+        nXSize = nYSize = 18000;
+        dfPixelSize = 3. / 3600;
+    }
+    else
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Open file.                                                      */
+/* -------------------------------------------------------------------- */
+
+    CPLString osFilename = poOpenInfo->pszFilename;
+    if ((strstr(poOpenInfo->pszFilename, ".ACE2.gz") ||
+         strstr(poOpenInfo->pszFilename, ".ace2.gz")) &&
+        strncmp(poOpenInfo->pszFilename, "/vsigzip/", 10) != 0)
+        osFilename = "/vsigzip/" + osFilename;
+
+    VSILFILE* fpImage = VSIFOpenL( osFilename, "rb+" );
+    if (fpImage == NULL)
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create the dataset.                                             */
+/* -------------------------------------------------------------------- */
+    ACE2Dataset  *poDS;
+
+    poDS = new ACE2Dataset();
+    poDS->nRasterXSize = nXSize;
+    poDS->nRasterYSize = nYSize;
+
+    poDS->adfGeoTransform[0] = southWestLon;
+    poDS->adfGeoTransform[1] = dfPixelSize;
+    poDS->adfGeoTransform[2] = 0.0;
+    poDS->adfGeoTransform[3] = southWestLat + nYSize * dfPixelSize;
+    poDS->adfGeoTransform[4] = 0.0;
+    poDS->adfGeoTransform[5] = -dfPixelSize;
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetBand( 1, new ACE2RasterBand(fpImage, eDT, nXSize, nYSize ) );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
+    return( poDS );
+}
+
+/************************************************************************/
+/*                          GDALRegister_ACE2()                         */
+/************************************************************************/
+
+void GDALRegister_ACE2()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "ACE2" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "ACE2" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "ACE2" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                   "frmt_various.html#ACE2" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ACE2" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnOpen = ACE2Dataset::Open;
+        poDriver->pfnIdentify = ACE2Dataset::Identify;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/frmts/raw/atlsci_spheroid.cpp b/frmts/raw/atlsci_spheroid.cpp
index 38fad4c..a64de12 100644
--- a/frmts/raw/atlsci_spheroid.cpp
+++ b/frmts/raw/atlsci_spheroid.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: atlsci_spheroid.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: atlsci_spheroid.cpp 22381 2011-05-16 21:14:22Z rouault $
  *
  * Project:  Spheroid classes
  * Purpose:  Provide spheroid lookup table base classes.
@@ -30,7 +30,7 @@
 #include "atlsci_spheroid.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: atlsci_spheroid.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: atlsci_spheroid.cpp 22381 2011-05-16 21:14:22Z rouault $");
 
 /**********************************************************************/
 /* ================================================================== */
@@ -44,15 +44,15 @@ void SpheroidItem :: SetValuesByRadii(const char *spheroidname, double eq_radius
     spheroid_name = CPLStrdup(spheroidname);
     equitorial_radius=eq_radius;
     polar_radius=p_radius;
-    inverse_flattening=eq_radius/(eq_radius - polar_radius);
+    inverse_flattening=(eq_radius == polar_radius) ? 0 : eq_radius/(eq_radius - polar_radius);
 }
 
 void SpheroidItem :: SetValuesByEqRadiusAndInvFlattening(const char *spheroidname, double eq_radius, double inverseflattening)
 {
     spheroid_name = CPLStrdup(spheroidname);
     equitorial_radius=eq_radius;
-    polar_radius=eq_radius*(1.0 - (1.0/inverse_flattening));
     inverse_flattening=inverseflattening;
+    polar_radius=(inverse_flattening == 0) ? eq_radius : eq_radius*(1.0 - (1.0/inverse_flattening));
 }
 SpheroidItem :: SpheroidItem()
 {
diff --git a/frmts/raw/btdataset.cpp b/frmts/raw/btdataset.cpp
index 593e1de..5f31449 100644
--- a/frmts/raw/btdataset.cpp
+++ b/frmts/raw/btdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: btdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: btdataset.cpp 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  VTP .bt Driver
  * Purpose:  Implementation of VTP .bt elevation format read/write support.
@@ -31,7 +31,7 @@
 #include "rawdataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: btdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: btdataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
 
 CPL_C_START
 void    GDALRegister_BT(void);
@@ -87,7 +87,7 @@ class BTDataset : public GDALPamDataset
 /* ==================================================================== */
 /************************************************************************/
 
-class BTRasterBand : public GDALRasterBand
+class BTRasterBand : public GDALPamRasterBand
 {
     VSILFILE          *fpImage;
 
@@ -102,6 +102,7 @@ class BTRasterBand : public GDALRasterBand
     virtual const char* GetUnitType();
     virtual CPLErr SetUnitType(const char*);
 	virtual double GetNoDataValue( int* = NULL );
+    virtual CPLErr SetNoDataValue( double );
 };
 
 
@@ -258,6 +259,11 @@ double BTRasterBand::GetNoDataValue( int* pbSuccess /*= NULL */ )
 	return -32768;
 }
 
+CPLErr BTRasterBand::SetNoDataValue( double )
+
+{
+    return CE_None;
+}
 
 /************************************************************************/
 /*                            GetUnitType()                             */
@@ -490,7 +496,7 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 /* -------------------------------------------------------------------- */
     int bNorth;
 
-    nShortTemp = oSRS.GetUTMZone( &bNorth );
+    nShortTemp = (GInt16) oSRS.GetUTMZone( &bNorth );
     if( bNorth )
         nShortTemp = -nShortTemp;
 
@@ -502,7 +508,7 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 /* -------------------------------------------------------------------- */
     if( oSRS.GetAuthorityName( "GEOGCS|DATUM" ) != NULL
         && EQUAL(oSRS.GetAuthorityName( "GEOGCS|DATUM" ),"EPSG") )
-        nShortTemp = atoi(oSRS.GetAuthorityCode( "GEOGCS|DATUM" )) + 2000;
+        nShortTemp = (GInt16) (atoi(oSRS.GetAuthorityCode( "GEOGCS|DATUM" )) + 2000);
     else
         nShortTemp = -2;
     nShortTemp = CPL_LSBWORD16( nShortTemp ); /* datum unknown */
@@ -629,7 +635,7 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
         if( fp != NULL )
         {
             char *pszBuffer, *pszBufPtr;
-            int  nBufMax = 100000;
+            int  nBufMax = 10000;
             int nBytes;
 
             pszBuffer = (char *) CPLMalloc(nBufMax);
@@ -863,7 +869,7 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
     nTemp = CPL_LSBWORD32( nYSize );
     memcpy( abyHeader+14, &nTemp, 4 );
 
-    nShortTemp = CPL_LSBWORD16( GDALGetDataTypeSize( eType ) / 8 );
+    nShortTemp = (GInt16) (CPL_LSBWORD16( GDALGetDataTypeSize( eType ) / 8 ));
     memcpy( abyHeader + 18, &nShortTemp, 2 );
     
     if( eType == GDT_Float32 )
@@ -946,6 +952,8 @@ void GDALRegister_BT()
         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "bt" );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
                                    "Int16 Int32 Float32" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = BTDataset::Open;
         poDriver->pfnCreate = BTDataset::Create;
 
diff --git a/frmts/raw/dipxdataset.cpp b/frmts/raw/dipxdataset.cpp
index 7984375..1b5acb4 100644
--- a/frmts/raw/dipxdataset.cpp
+++ b/frmts/raw/dipxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dipxdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: dipxdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Implementation for ELAS DIPEx format variant.
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dipxdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: dipxdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 void	GDALRegister_DIPEx(void);
@@ -300,6 +300,11 @@ GDALDataset *DIPExDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
@@ -341,7 +346,8 @@ void GDALRegister_DIPEx()
         poDriver->SetDescription( "DIPEx" );
         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
                                    "DIPEx" );
-        
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = DIPExDataset::Open;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
diff --git a/frmts/raw/doq1dataset.cpp b/frmts/raw/doq1dataset.cpp
index 3a98c16..a701f3e 100644
--- a/frmts/raw/doq1dataset.cpp
+++ b/frmts/raw/doq1dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: doq1dataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: doq1dataset.cpp 21717 2011-02-13 20:16:30Z rouault $
  *
  * Project:  USGS DOQ Driver (First Generation Format)
  * Purpose:  Implementation of DOQ1Dataset
@@ -30,7 +30,7 @@
 #include "rawdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: doq1dataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
+CPL_CVSID("$Id: doq1dataset.cpp 21717 2011-02-13 20:16:30Z rouault $");
 
 static double DOQGetField( unsigned char *, int );
 static void DOQGetDescription( GDALDataset *, unsigned char * );
@@ -62,7 +62,7 @@ CPL_C_END
 
 class DOQ1Dataset : public RawDataset
 {
-    FILE	*fpImage;	// image data file.
+    VSILFILE	*fpImage;	// image data file.
     
     double	dfULX, dfULY;
     double	dfXPixelSize, dfYPixelSize;
@@ -100,7 +100,7 @@ DOQ1Dataset::~DOQ1Dataset()
 
     CPLFree( pszProjection );
     if( fpImage != NULL )
-        VSIFClose( fpImage );
+        VSIFCloseL( fpImage );
 }
 
 /************************************************************************/
@@ -142,7 +142,7 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*	We assume the user is pointing to the binary (ie. .bil) file.	*/
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 212 || poOpenInfo->fp == NULL )
+    if( poOpenInfo->nHeaderBytes < 212 )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -199,11 +199,12 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = nWidth;
     poDS->nRasterYSize = nHeight;
     
-/* -------------------------------------------------------------------- */
-/*      Assume ownership of the file handled from the GDALOpenInfo.     */
-/* -------------------------------------------------------------------- */
-    poDS->fpImage = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
+    poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (poDS->fpImage == NULL)
+    {
+        delete poDS;
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Compute layout of data.                                         */
@@ -227,7 +228,7 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->SetBand( i+1, 
             new RawRasterBand( poDS, i+1, poDS->fpImage,
                                nSkipBytes + i, nBytesPerPixel, nBytesPerLine,
-                               GDT_Byte, TRUE ) );
+                               GDT_Byte, TRUE, TRUE ) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -291,8 +292,8 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     unsigned char	abyRecordData[500];
     
-    if( VSIFSeek( poDS->fpImage, nBytesPerLine * 2, SEEK_SET ) != 0
-        || VSIFRead(abyRecordData,sizeof(abyRecordData),1,poDS->fpImage) != 1 )
+    if( VSIFSeekL( poDS->fpImage, nBytesPerLine * 2, SEEK_SET ) != 0
+        || VSIFReadL(abyRecordData,sizeof(abyRecordData),1,poDS->fpImage) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Header read error on %s.\n",
@@ -304,8 +305,8 @@ GDALDataset *DOQ1Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->dfULX = DOQGetField( abyRecordData + 288, 24 );
     poDS->dfULY = DOQGetField( abyRecordData + 312, 24 );
 
-    if( VSIFSeek( poDS->fpImage, nBytesPerLine * 3, SEEK_SET ) != 0
-        || VSIFRead(abyRecordData,sizeof(abyRecordData),1,poDS->fpImage) != 1 )
+    if( VSIFSeekL( poDS->fpImage, nBytesPerLine * 3, SEEK_SET ) != 0
+        || VSIFReadL(abyRecordData,sizeof(abyRecordData),1,poDS->fpImage) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Header read error on %s.\n",
@@ -349,6 +350,7 @@ void GDALRegister_DOQ1()
                                    "USGS DOQ (Old Style)" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_various.html#DOQ1" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
         
         poDriver->pfnOpen = DOQ1Dataset::Open;
 
diff --git a/frmts/raw/doq2dataset.cpp b/frmts/raw/doq2dataset.cpp
index ae2ddc0..4ad42d2 100644
--- a/frmts/raw/doq2dataset.cpp
+++ b/frmts/raw/doq2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: doq2dataset.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: doq2dataset.cpp 21717 2011-02-13 20:16:30Z rouault $
  *
  * Project:  USGS DOQ Driver (Second Generation Format)
  * Purpose:  Implementation of DOQ2Dataset
@@ -30,7 +30,7 @@
 #include "rawdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: doq2dataset.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: doq2dataset.cpp 21717 2011-02-13 20:16:30Z rouault $");
 
 CPL_C_START
 void	GDALRegister_DOQ2(void);
@@ -59,7 +59,7 @@ CPL_C_END
 
 class DOQ2Dataset : public RawDataset
 {
-    FILE	*fpImage;	// image data file.
+    VSILFILE	*fpImage;	// image data file.
     
     double	dfULX, dfULY;
     double	dfXPixelSize, dfYPixelSize;
@@ -97,7 +97,7 @@ DOQ2Dataset::~DOQ2Dataset()
 
     CPLFree( pszProjection );
     if( fpImage != NULL )
-        VSIFClose( fpImage );
+        VSIFCloseL( fpImage );
 }
 
 /************************************************************************/
@@ -139,7 +139,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*	We assume the user is pointing to the binary (ie. .bil) file.	*/
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 212 || poOpenInfo->fp == NULL )
+    if( poOpenInfo->nHeaderBytes < 212 )
         return NULL;
 
     int         nLineCount = 0;
@@ -160,10 +160,14 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
                 "BEGIN_USGS_DOQ_HEADER", 21) )
         return NULL;
 
+    VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (fp == NULL)
+        return NULL;
+
     /* read and discard the first line */
-    pszLine = CPLReadLine( poOpenInfo->fp );
+    pszLine = CPLReadLineL( fp );
 
-    while( (pszLine = CPLReadLine( poOpenInfo->fp )) != NULL )
+    while( (pszLine = CPLReadLineL( fp )) != NULL )
     {
 	char    **papszTokens;
 
@@ -300,7 +304,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
         CSLDestroy( papszTokens );
     }
 
-    CPLReadLine( NULL );
+    CPLReadLineL( NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Do these values look coherent for a DOQ file?  It would be      */
@@ -312,6 +316,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
         || nBandTypes < 1 || nBandTypes > 9 )
     {
         CSLDestroy( papszMetadata );
+        VSIFCloseL(fp);
         return NULL;
     }
 
@@ -325,6 +330,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
                   "DOQ Data Type (%d) is not a supported configuration.\n",
                   nBandTypes );
         CSLDestroy( papszMetadata );
+        VSIFCloseL(fp);
         return NULL;
     }
     
@@ -337,6 +343,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
         CPLError( CE_Failure, CPLE_NotSupported, 
                   "The DOQ2 driver does not support update access to existing"
                   " datasets.\n" );
+        VSIFCloseL(fp);
         return NULL;
     }
 /* -------------------------------------------------------------------- */
@@ -351,12 +358,8 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->SetMetadata( papszMetadata );
     CSLDestroy( papszMetadata );
-    
-/* -------------------------------------------------------------------- */
-/*      Assume ownership of the file handled from the GDALOpenInfo.     */
-/* -------------------------------------------------------------------- */
-    poDS->fpImage = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
+
+    poDS->fpImage = fp;
 
 /* -------------------------------------------------------------------- */
 /*      Compute layout of data.                                         */
@@ -376,7 +379,7 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->SetBand( i+1, 
             new RawRasterBand( poDS, i+1, poDS->fpImage,
                                nSkipBytes + i, nBytesPerPixel, nBytesPerLine,
-                               GDT_Byte, TRUE ) );
+                               GDT_Byte, TRUE, TRUE ) );
     }
 
     if (nProjType == 1)
@@ -432,6 +435,7 @@ void GDALRegister_DOQ2()
                                    "USGS DOQ (New Style)" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_various.html#DOQ2" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = DOQ2Dataset::Open;
 
diff --git a/frmts/raw/ehdrdataset.cpp b/frmts/raw/ehdrdataset.cpp
index ce2ea3a..8400d03 100644
--- a/frmts/raw/ehdrdataset.cpp
+++ b/frmts/raw/ehdrdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ehdrdataset.cpp 21623 2011-02-02 18:53:34Z warmerdam $
+ * $Id: ehdrdataset.cpp 21783 2011-02-21 22:32:11Z rouault $
  *
  * Project:  ESRI .hdr Driver
  * Purpose:  Implementation of EHdrDataset
@@ -31,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ehdrdataset.cpp 21623 2011-02-02 18:53:34Z warmerdam $");
+CPL_CVSID("$Id: ehdrdataset.cpp 21783 2011-02-21 22:32:11Z rouault $");
 
 CPL_C_START
 void	GDALRegister_EHdr(void);
@@ -57,6 +57,8 @@ class EHdrDataset : public RawDataset
 
     VSILFILE	*fpImage;	// image data file.
 
+    CPLString   osHeaderExt;
+
     int         bGotTransform;
     double      adfGeoTransform[6];
     char       *pszProjection;
@@ -250,7 +252,7 @@ CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
         iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
                 
-        ((GByte *) pImage)[iPixel++] = nOutWord;
+        ((GByte *) pImage)[iPixel++] = (GByte) nOutWord;
     }
 
     CPLFree( pabyBuffer );
@@ -428,6 +430,7 @@ EHdrDataset::EHdrDataset()
     papszHDR = NULL;
     bHDRDirty = FALSE;
     bCLRDirty = FALSE;
+    osHeaderExt = "hdr";
 }
 
 /************************************************************************/
@@ -710,7 +713,7 @@ CPLErr EHdrDataset::RewriteHDR()
 {
     CPLString osPath = CPLGetPath( GetDescription() );
     CPLString osName = CPLGetBasename( GetDescription() );
-    CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, "hdr" );
+    CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
 
 /* -------------------------------------------------------------------- */
 /*      Write .hdr file.                                                */
@@ -813,6 +816,20 @@ CPLErr EHdrDataset::ReadSTX()
               EHdrRasterBand* poBand = (EHdrRasterBand*)papoBands[i-1];
               poBand->dfMin = atof(papszTokens[1]);
               poBand->dfMax = atof(papszTokens[2]);
+
+              int bNoDataSet = FALSE;
+              double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
+              if (bNoDataSet && dfNoData == poBand->dfMin)
+              {
+                  /* Triggered by /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/HongKong/srtm/n22e113.zip/n22e113.bil */
+                  CPLDebug("EHDr", "Ignoring .stx file where min == nodata. "
+                           "The nodata value shouldn't be taken into account "
+                           "in minimum value computation.");
+                  CSLDestroy( papszTokens );
+                  papszTokens = NULL;
+                  break;
+              }
+
               poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
               // reads optional mean and stddev
               if ( !EQUAL(papszTokens[3], "#") )
@@ -917,7 +934,7 @@ char **EHdrDataset::GetFileList()
     papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
-    CPLString osFilename = CPLFormCIFilename( osPath, osName, "hdr" );
+    CPLString osFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
     papszFileList = CSLAddString( papszFileList, osFilename );
 
     // Statistics file
@@ -965,10 +982,21 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
     CPLString osHDRFilename;
 
+    const char* pszHeaderExt = "hdr";
+    if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "SRC" ) &&
+        osName.size() == 7 &&
+        (osName[0] == 'e' || osName[0] == 'E' || osName[0] == 'w' || osName[0] == 'W') &&
+        (osName[4] == 'n' || osName[4] == 'N' || osName[4] == 's' || osName[4] == 'S') )
+    {
+        /* It is a GTOPO30 or SRTM30 source file, whose header extension is .sch */
+        /* see http://dds.cr.usgs.gov/srtm/version1/SRTM30/GTOPO30_Documentation */
+        pszHeaderExt = "sch";
+    }
+
     if( poOpenInfo->papszSiblingFiles )
     {
         int iFile = CSLFindString(poOpenInfo->papszSiblingFiles, 
-                                  CPLFormFilename( NULL, osName, "hdr" ) );
+                                  CPLFormFilename( NULL, osName, pszHeaderExt ) );
         if( iFile < 0 ) // return if there is no corresponding .hdr file
             return NULL;
         
@@ -978,7 +1006,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        osHDRFilename = CPLFormCIFilename( osPath, osName, "hdr" );
+        osHDRFilename = CPLFormCIFilename( osPath, osName, pszHeaderExt );
     }
 
     bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
@@ -1099,11 +1127,11 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else if( EQUAL(papszTokens[0],"PIXELTYPE") )
         {
-            chPixelType = toupper(papszTokens[1][0]);
+            chPixelType = (char) toupper(papszTokens[1][0]);
         }
         else if( EQUAL(papszTokens[0],"byteorder") )
         {
-            chByteOrder = toupper(papszTokens[1][0]);
+            chByteOrder = (char) toupper(papszTokens[1][0]);
         }
 
         /* http://www.worldclim.org/futdown.htm have the projection extensions */
@@ -1111,12 +1139,14 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             bHasInternalProjection = TRUE;
         }
-        else if( EQUAL(papszTokens[0],"MinValue") )
+        else if( EQUAL(papszTokens[0],"MinValue") ||
+                 EQUAL(papszTokens[0],"MIN_VALUE") )
         {
             dfMin = atof(papszTokens[1]);
             bHasMin = TRUE;
         }
-        else if( EQUAL(papszTokens[0],"MaxValue") )
+        else if( EQUAL(papszTokens[0],"MaxValue") ||
+                 EQUAL(papszTokens[0],"MAX_VALUE") )
         {
             dfMax = atof(papszTokens[1]);
             bHasMax = TRUE;
@@ -1171,7 +1201,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         VSIStatBufL sStatBuf;
         if( VSIStatL( poOpenInfo->pszFilename, &sStatBuf ) == 0 )
         {
-            size_t nBytes = sStatBuf.st_size/nCols/nRows/nBands;
+            size_t nBytes = (size_t) (sStatBuf.st_size/nCols/nRows/nBands);
             if( nBytes > 0 && nBytes != 3 )
                 nBits = nBytes*8;
 
@@ -1206,6 +1236,8 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS = new EHdrDataset();
 
+    poDS->osHeaderExt = pszHeaderExt;
+
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
@@ -1599,9 +1631,9 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                 int nIndex = atoi( papszValues[0] ); // Index
                 if (nIndex >= 0 && nIndex < 65536)
                 {
-                    oEntry.c1 = atoi( papszValues[1] ); // Red
-                    oEntry.c2 = atoi( papszValues[2] ); // Green
-                    oEntry.c3 = atoi( papszValues[3] ); // Blue
+                    oEntry.c1 = (short) atoi( papszValues[1] ); // Red
+                    oEntry.c2 = (short) atoi( papszValues[2] ); // Green
+                    oEntry.c3 = (short) atoi( papszValues[3] ); // Blue
                     oEntry.c4 = 255;
 
                     oColorTable.SetColorEntry( nIndex, &oEntry );
diff --git a/frmts/raw/eirdataset.cpp b/frmts/raw/eirdataset.cpp
index 20675fc..8d5a4e5 100644
--- a/frmts/raw/eirdataset.cpp
+++ b/frmts/raw/eirdataset.cpp
@@ -352,7 +352,8 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
             strncpy( szLayout, papszTokens[1], sizeof(szLayout) );
             szLayout[sizeof(szLayout)-1] = '\0';
         }
-        else if( EQUAL(papszTokens[0],"DATATYPE") )
+        else if( EQUAL(papszTokens[0],"DATATYPE") 
+                 || EQUAL(papszTokens[0],"DATA_TYPE") )
         {
             if ( EQUAL(papszTokens[1], "U1")
                  || EQUAL(papszTokens[1], "U2") 
@@ -398,7 +399,7 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
         else if( EQUAL(papszTokens[0],"BYTE_ORDER") )
         {
             // M for MSB, L for LSB
-            chByteOrder = toupper(papszTokens[1][0]);
+            chByteOrder = (char) toupper(papszTokens[1][0]);
         }
         else if( EQUAL(papszTokens[0],"DATA_OFFSET") )
         {
diff --git a/frmts/raw/envidataset.cpp b/frmts/raw/envidataset.cpp
index f56c694..a3d65f3 100644
--- a/frmts/raw/envidataset.cpp
+++ b/frmts/raw/envidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envidataset.cpp 22304 2011-05-05 15:18:06Z warmerdam $
+ * $Id: envidataset.cpp 23170 2011-10-03 09:35:21Z rprinceley $
  *
  * Project:  ENVI .hdr Driver
  * Purpose:  Implementation of ENVI .hdr labelled raw raster support.
@@ -32,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: envidataset.cpp 22304 2011-05-05 15:18:06Z warmerdam $");
+CPL_CVSID("$Id: envidataset.cpp 23170 2011-10-03 09:35:21Z rprinceley $");
 
 CPL_C_START
 void GDALRegister_ENVI(void);
@@ -1784,7 +1784,19 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
     pszInterleave = CSLFetchNameValue(poDS->papszHeader,"interleave");
 
-    
+    /* In case, there is no interleave keyword, we try to derive it from the */
+    /* file extension, if it matches one of the expected interleaving mode */
+    if( pszInterleave == NULL )
+    {
+        const char* pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
+        if ( EQUAL(pszExtension, "BSQ") ||
+             EQUAL(pszExtension, "BIP") ||
+             EQUAL(pszExtension, "BIL") )
+        {
+            pszInterleave = pszExtension;
+        }
+    }
+
     if (!GDALCheckDatasetDimensions(nSamples, nLines) || !GDALCheckBandCount(nBands, FALSE) ||
         pszInterleave == NULL )
     {
@@ -1876,11 +1888,27 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue(poDS->papszHeader,"file_type" ) != NULL )
     {
+        // when the file type is one of these we return an invalid file type err
+            //'envi meta file'
+            //'envi virtual mosaic'
+            //'envi spectral library'
+            //'envi fft result'
+
+        // when the file type is one of these we open it 
+            //'envi standard'
+            //'envi classification' 
+
+        // when the file type is anything else we attempt to open it as a raster.
+
         const char * pszEnviFileType;
         pszEnviFileType = CSLFetchNameValue(poDS->papszHeader,"file_type");
-        if(!EQUAL(pszEnviFileType, "ENVI Standard") &&
-           !EQUAL(pszEnviFileType, "ENVI") &&
-           !EQUAL(pszEnviFileType, "ENVI Classification"))
+
+        // envi gdal does not support any of these
+        // all others we will attempt to open
+        if(EQUAL(pszEnviFileType, "envi meta file") ||
+           EQUAL(pszEnviFileType, "envi virtual mosaic") ||
+           EQUAL(pszEnviFileType, "envi spectral library") ||
+           EQUAL(pszEnviFileType, "envi fft result"))
         {
             CPLError( CE_Failure, CPLE_OpenFailed, 
                       "File %s contains an invalid file type in the ENVI .hdr\n"
@@ -2101,9 +2129,9 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             GDALColorEntry sEntry;
 
-            sEntry.c1 = atoi(papszClassColors[i*3+0]);
-            sEntry.c2 = atoi(papszClassColors[i*3+1]);
-            sEntry.c3 = atoi(papszClassColors[i*3+2]);
+            sEntry.c1 = (short) atoi(papszClassColors[i*3+0]);
+            sEntry.c2 = (short) atoi(papszClassColors[i*3+1]);
+            sEntry.c3 = (short) atoi(papszClassColors[i*3+2]);
             sEntry.c4 = 255;
             oCT.SetColorEntry( i, &sEntry );
         }
diff --git a/frmts/raw/fastdataset.cpp b/frmts/raw/fastdataset.cpp
index 1a1d945..c1506bd 100644
--- a/frmts/raw/fastdataset.cpp
+++ b/frmts/raw/fastdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fastdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: fastdataset.cpp 22610 2011-06-28 21:20:06Z rouault $
  *
  * Project:  EOSAT FAST Format reader
  * Purpose:  Reads Landsat FAST-L7A, IRS 1C/1D
@@ -32,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: fastdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: fastdataset.cpp 22610 2011-06-28 21:20:06Z rouault $");
 
 CPL_C_START
 void	GDALRegister_FAST(void);
@@ -110,7 +110,7 @@ class FASTDataset : public GDALPamDataset
     double      adfGeoTransform[6];
     char        *pszProjection;
 
-    FILE	*fpHeader;
+    VSILFILE	*fpHeader;
     CPLString apoChannelFilenames[7];
     VSILFILE	*fpChannels[7];
     const char	*pszFilename;
@@ -209,7 +209,7 @@ FASTDataset::~FASTDataset()
 	if ( fpChannels[i] )
 	    VSIFCloseL( fpChannels[i] );
     if( fpHeader != NULL )
-        VSIFClose( fpHeader );
+        VSIFCloseL( fpHeader );
 }
 
 /************************************************************************/
@@ -463,7 +463,8 @@ void FASTDataset::TryEuromap_IRS_1C_1D_ChannelNameConvention()
             for (int j = 0; j < 2; j ++)
             {
                 char* pszChannelFilename = CPLStrdup(pszFilename);
-                pszChannelFilename[strlen(pszChannelFilename)-1] = '1' + j;
+                pszChannelFilename[strlen(pszChannelFilename)-1] 
+                    = (char) ('1' + j);
                 if (OpenChannel( pszChannelFilename, nBands ))
                     nBands++;
                 else
@@ -591,8 +592,8 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
     int		i;
-	
-    if( poOpenInfo->fp == NULL )
+
+    if( poOpenInfo->nHeaderBytes < 1024)
         return NULL;
 
     if( !EQUALN((const char *) poOpenInfo->pabyHeader + 52,
@@ -608,8 +609,13 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS = new FASTDataset();
 
-    poDS->fpHeader = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
+    poDS->fpHeader = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (poDS->fpHeader == NULL)
+    {
+        delete poDS;
+        return NULL;
+    }
+
     poDS->pszFilename = poOpenInfo->pszFilename;
     poDS->pszDirname = CPLStrdup( CPLGetDirname( poOpenInfo->pszFilename ) );
     
@@ -620,8 +626,8 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     char	*pszHeader = (char *) CPLMalloc( ADM_HEADER_SIZE + 1 );
     size_t      nBytesRead;
  
-    VSIFSeek( poDS->fpHeader, 0, SEEK_SET );
-    nBytesRead = VSIFRead( pszHeader, 1, ADM_HEADER_SIZE, poDS->fpHeader );
+    VSIFSeekL( poDS->fpHeader, 0, SEEK_SET );
+    nBytesRead = VSIFReadL( pszHeader, 1, ADM_HEADER_SIZE, poDS->fpHeader );
     if ( nBytesRead < ADM_MIN_HEADER_SIZE )
     {
 	CPLDebug( "FAST", "Header file too short. Reading failed" );
@@ -669,7 +675,6 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLFree( pszTemp );
 
     // Read filenames
-    pszTemp = pszHeader;
     poDS->nBands = 0;
     
     if (strstr( pszHeader, FILENAME ) == NULL)
@@ -728,10 +733,10 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     /* the usual patterns like bandX.dat, etc... */
     if ( !poDS->nBands )
     {
+        pszTemp = pszHeader;
         for ( i = 0; i < 7; i++ )
         {
             char *pszFilename = NULL ;
-    
             if ( pszTemp )
                 pszTemp = strstr( pszTemp, FILENAME );
             if ( pszTemp )
@@ -1129,6 +1134,7 @@ void GDALRegister_FAST()
                                    "EOSAT FAST Format" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_fast.html" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = FASTDataset::Open;
 
diff --git a/frmts/raw/genbindataset.cpp b/frmts/raw/genbindataset.cpp
index 27f9959..0a12962 100644
--- a/frmts/raw/genbindataset.cpp
+++ b/frmts/raw/genbindataset.cpp
@@ -893,6 +893,8 @@ void GDALRegister_GenBin()
                                    "Generic Binary (.hdr Labelled)" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_various.html#GenBin" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = GenBinDataset::Open;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
diff --git a/frmts/raw/gscdataset.cpp b/frmts/raw/gscdataset.cpp
index 8f7a70b..163d6b0 100644
--- a/frmts/raw/gscdataset.cpp
+++ b/frmts/raw/gscdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gscdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
+ * $Id: gscdataset.cpp 21715 2011-02-13 19:18:59Z rouault $
  *
  * Project:  GSC Geogrid format driver.
  * Purpose:  Implements support for reading and writing GSC Geogrid format.
@@ -30,7 +30,7 @@
 #include "rawdataset.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gscdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
+CPL_CVSID("$Id: gscdataset.cpp 21715 2011-02-13 19:18:59Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -40,7 +40,7 @@ CPL_CVSID("$Id: gscdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
 
 class GSCDataset : public RawDataset
 {
-    FILE	*fpImage;	// image data file.
+    VSILFILE	*fpImage;	// image data file.
     
     double	adfGeoTransform[6];
 
@@ -77,7 +77,7 @@ GSCDataset::~GSCDataset()
 {
     FlushCache();
     if( fpImage != NULL )
-        VSIFClose( fpImage );
+        VSIFCloseL( fpImage );
 }
 
 /************************************************************************/
@@ -104,7 +104,7 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Does this plausible look like a GSC Geogrid file?               */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 20 || poOpenInfo->fp == NULL )
+    if( poOpenInfo->nHeaderBytes < 20 )
         return NULL;
 
     if( poOpenInfo->pabyHeader[12] != 0x02
@@ -149,16 +149,20 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Assume ownership of the file handled from the GDALOpenInfo.     */
 /* -------------------------------------------------------------------- */
-    poDS->fpImage = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
+    poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (poDS->fpImage == NULL)
+    {
+        delete poDS;
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read the header information in the second record. 		*/
 /* -------------------------------------------------------------------- */
     float	afHeaderInfo[8];
 
-    if( VSIFSeek( poDS->fpImage, nRecordLen + 12, SEEK_SET ) != 0
-        || VSIFRead( afHeaderInfo, sizeof(float), 8, poDS->fpImage ) != 8 )
+    if( VSIFSeekL( poDS->fpImage, nRecordLen + 12, SEEK_SET ) != 0
+        || VSIFReadL( afHeaderInfo, sizeof(float), 8, poDS->fpImage ) != 8 )
     {
         CPLError( CE_Failure, CPLE_FileIO, 
                   "Failure reading second record of GSC file with %d record length.",
@@ -192,7 +196,7 @@ GDALDataset *GSCDataset::Open( GDALOpenInfo * poOpenInfo )
     poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
                                 nRecordLen * 2 + 4,
                                 sizeof(float), nRecordLen,
-                                GDT_Float32, bNative, FALSE );
+                                GDT_Float32, bNative, TRUE );
     poDS->SetBand( 1, poBand );
 
     poBand->SetNoDataValue( -1.0000000150474662199e+30 );
@@ -229,6 +233,7 @@ void GDALRegister_GSC()
                                    "GSC Geogrid" );
 //        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
 //                                   "frmt_various.html#GSC" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = GSCDataset::Open;
 
diff --git a/frmts/raw/idadataset.cpp b/frmts/raw/idadataset.cpp
index aabbcf3..8ccf45d 100644
--- a/frmts/raw/idadataset.cpp
+++ b/frmts/raw/idadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: idadataset.cpp 16706 2009-04-02 03:44:07Z warmerdam $
+ * $Id: idadataset.cpp 22614 2011-06-29 19:08:07Z 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 16706 2009-04-02 03:44:07Z warmerdam $");
+CPL_CVSID("$Id: idadataset.cpp 22614 2011-06-29 19:08:07Z rouault $");
 
 CPL_C_START
 void	GDALRegister_IDA(void);
@@ -545,7 +545,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
 /* -------------------------------------------------------------------- */
     bHeaderDirty = TRUE;
 
-    abyHeader[23] = nProjection;
+    abyHeader[23] = (GByte) nProjection;
     c2tp( dfLatCenter, abyHeader + 120 );
     c2tp( dfLongCenter, abyHeader + 126 );
     c2tp( dfParallel1, abyHeader + 156 );
@@ -663,6 +663,8 @@ void IDADataset::ReadColorTable()
         pszLine = CPLReadLine( fp );
     }
 
+    VSIFClose( fp );
+
 /* -------------------------------------------------------------------- */
 /*      Attach RAT to band.                                             */
 /* -------------------------------------------------------------------- */
@@ -1006,7 +1008,7 @@ static void c2tp(double x, GByte *r)
     r[5] |= 0x80;
 
   // put exponent
-  r[0] = exp + 129;
+  r[0] = (GByte) (exp + 129);
 }
 
 /************************************************************************/
@@ -1055,9 +1057,9 @@ GDALDataset *IDADataset::Create( const char * pszFilename,
     abyHeader[22] = 200; /* image type - CALCULATED */
     abyHeader[23] = 0; /* projection - NONE */
     abyHeader[30] = nYSize % 256;
-    abyHeader[31] = nYSize / 256;
+    abyHeader[31] = (GByte) (nYSize / 256);
     abyHeader[32] = nXSize % 256;
-    abyHeader[33] = nXSize / 256;
+    abyHeader[33] = (GByte) (nXSize / 256);
 
     abyHeader[170] = 255; /* missing = 255 */
     c2tp( 1.0, abyHeader + 171 ); /* slope = 1.0 */
diff --git a/frmts/raw/landataset.cpp b/frmts/raw/landataset.cpp
index 238387c..29f3bcf 100644
--- a/frmts/raw/landataset.cpp
+++ b/frmts/raw/landataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: landataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: landataset.cpp 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  eCognition
  * Purpose:  Implementation of Erdas .LAN / .GIS format.
@@ -29,9 +29,9 @@
 
 #include "rawdataset.h"
 #include "cpl_string.h"
-#include "ogr_srs_api.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: landataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: landataset.cpp 23033 2011-09-03 18:46:11Z rouault $");
 
 CPL_C_START
 void	GDALRegister_LAN(void);
@@ -150,9 +150,14 @@ class LANDataset : public RawDataset
     	        ~LANDataset();
     
     virtual CPLErr GetGeoTransform( double * padfTransform );
+    virtual CPLErr SetGeoTransform( double * padfTransform );
     virtual const char *GetProjectionRef();
+    virtual CPLErr SetProjection( const char * );
 
     static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *Create( const char * pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char ** papszOptions );
 };
 
 /************************************************************************/
@@ -362,6 +367,7 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     else
         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
+
     if( poDS->fpImage == NULL )
         return NULL;
 
@@ -597,6 +603,49 @@ CPLErr LANDataset::GetGeoTransform( double * padfTransform )
 }
 
 /************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr LANDataset::SetGeoTransform( double * padfTransform )
+
+{
+    unsigned char abyHeader[128];
+
+    memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
+
+    VSIFSeekL( fpImage, 0, SEEK_SET );
+    VSIFReadL( abyHeader, 128, 1, fpImage );
+
+    // Upper Left X
+    float f32Val;
+
+    f32Val = (float) (adfGeoTransform[0] + 0.5 * adfGeoTransform[1]);
+    memcpy( abyHeader + 112, &f32Val, 4 );
+    
+    // Upper Left Y
+    f32Val = (float) (adfGeoTransform[3] + 0.5 * adfGeoTransform[5]);
+    memcpy( abyHeader + 116, &f32Val, 4 );
+    
+    // width of pixel
+    f32Val = (float) adfGeoTransform[1];
+    memcpy( abyHeader + 120, &f32Val, 4 );
+    
+    // height of pixel
+    f32Val = (float) fabs(adfGeoTransform[5]);
+    memcpy( abyHeader + 124, &f32Val, 4 );
+
+    if( VSIFSeekL( fpImage, 0, SEEK_SET ) != 0 
+        || VSIFWriteL( abyHeader, 128, 1, fpImage ) != 1 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "File IO Error writing header with new geotransform." );
+        return CE_Failure;
+    }
+    else
+        return CE_None;
+}
+
+/************************************************************************/
 /*                          GetProjectionRef()                          */
 /*                                                                      */
 /*      Use PAM coordinate system if available in preference to the     */
@@ -615,6 +664,98 @@ const char *LANDataset::GetProjectionRef()
 }
 
 /************************************************************************/
+/*                           SetProjection()                            */
+/************************************************************************/
+
+CPLErr LANDataset::SetProjection( const char * pszWKT )
+
+{
+    unsigned char abyHeader[128];
+
+    VSIFSeekL( fpImage, 0, SEEK_SET );
+    VSIFReadL( abyHeader, 128, 1, fpImage );
+
+    OGRSpatialReference oSRS( pszWKT );
+    
+    GUInt16 nProjCode = 0;
+
+    if( oSRS.IsGeographic() )
+        nProjCode = 0;
+
+    else if( oSRS.GetUTMZone() != 0 )
+        nProjCode = 1;
+
+    // Too bad we have no way of recognising state plane projections. 
+
+    else 
+    {
+        const char *pszProjection = oSRS.GetAttrValue("PROJECTION");
+
+        if( pszProjection == NULL )
+            ;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
+            nProjCode = 3;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
+            nProjCode = 4;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_MERCATOR_1SP) )
+            nProjCode = 5;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_POLAR_STEREOGRAPHIC) )
+            nProjCode = 6;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_POLYCONIC) )
+            nProjCode = 7;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_EQUIDISTANT_CONIC) )
+            nProjCode = 8;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_TRANSVERSE_MERCATOR) )
+            nProjCode = 9;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_STEREOGRAPHIC) )
+            nProjCode = 10;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
+            nProjCode = 11;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_AZIMUTHAL_EQUIDISTANT) )
+            nProjCode = 12;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_GNOMONIC) )
+            nProjCode = 13;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_ORTHOGRAPHIC) )
+            nProjCode = 14;
+        // we don't have GVNP.
+        else if( EQUAL(pszProjection,
+                       SRS_PT_SINUSOIDAL) )
+            nProjCode = 16;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_EQUIRECTANGULAR) )
+            nProjCode = 17;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_MILLER_CYLINDRICAL) )
+            nProjCode = 18;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_VANDERGRINTEN) )
+            nProjCode = 19;
+        else if( EQUAL(pszProjection,
+                       SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
+            nProjCode = 20;
+    }
+
+    memcpy( abyHeader + 88, &nProjCode, 2 );
+
+    VSIFSeekL( fpImage, 0, SEEK_SET );
+    VSIFWriteL( abyHeader, 128, 1, fpImage );
+
+    return GDALPamDataset::SetProjection( pszWKT );
+}
+
+/************************************************************************/
 /*                            GetFileList()                             */
 /************************************************************************/
 
@@ -702,6 +843,146 @@ void LANDataset::CheckForStatistics()
 }
 
 /************************************************************************/
+/*                               Create()                               */
+/************************************************************************/
+
+GDALDataset *LANDataset::Create( const char * pszFilename,
+                                 int nXSize, int nYSize, int nBands,
+                                 GDALDataType eType,
+                                 char ** papszOptions )
+
+{
+    if( eType != GDT_Byte && eType != GDT_Int16 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create .GIS file with unsupported data type '%s'.",
+                  GDALGetDataTypeName( eType ) );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to create the file.                                         */
+/* -------------------------------------------------------------------- */
+    VSILFILE	*fp;
+
+    fp = VSIFOpenL( pszFilename, "wb" );
+
+    if( fp == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Attempt to create file `%s' failed.\n",
+                  pszFilename );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write out the header.                                           */
+/* -------------------------------------------------------------------- */
+    unsigned char abyHeader[128];
+    GInt16  n16Val;
+    GInt32  n32Val;
+
+    memset( abyHeader, 0, sizeof(abyHeader) );
+    
+    memcpy( abyHeader + 0, "HEAD74", 6 );
+
+    // Pixel type
+    if( eType == GDT_Byte ) // do we want 4bit?
+        n16Val = 0;
+    else
+        n16Val = 2;
+    memcpy( abyHeader + 6, &n16Val, 2 );
+
+    // Number of Bands.
+    n16Val = (GInt16) nBands;
+    memcpy( abyHeader + 8, &n16Val, 2 );
+
+    // Unknown (6)
+
+    // Width
+    n32Val = nXSize;
+    memcpy( abyHeader + 16, &n32Val, 4 );
+    
+    // Height
+    n32Val = nYSize;
+    memcpy( abyHeader + 20, &n32Val, 4 );
+
+    // X Start (4)
+    // Y Start (4)
+
+    // Unknown (56)
+
+    // Coordinate System
+    n16Val = 0;
+    memcpy( abyHeader + 88, &n16Val, 2 );
+
+    // Classes in coverage 
+    n16Val = 0;
+    memcpy( abyHeader + 90, &n16Val, 2 );
+
+    // Unknown (14)
+
+    // Area Unit
+    n16Val = 0;
+    memcpy( abyHeader + 106, &n16Val, 2 );
+
+    // Pixel Area
+    float f32Val;
+
+    f32Val = 0.0f;
+    memcpy( abyHeader + 108, &f32Val, 4 );
+
+    // Upper Left X
+    f32Val = 0.5f;
+    memcpy( abyHeader + 112, &f32Val, 4 );
+    
+    // Upper Left Y
+    f32Val = (float) (nYSize - 0.5);
+    memcpy( abyHeader + 116, &f32Val, 4 );
+    
+    // width of pixel
+    f32Val = 1.0f;
+    memcpy( abyHeader + 120, &f32Val, 4 );
+    
+    // height of pixel
+    f32Val = 1.0f;
+    memcpy( abyHeader + 124, &f32Val, 4 );
+
+    VSIFWriteL( abyHeader, sizeof(abyHeader), 1, fp );
+
+/* -------------------------------------------------------------------- */
+/*      Extend the file to the target size.                             */
+/* -------------------------------------------------------------------- */
+    vsi_l_offset nImageBytes;
+
+    if( eType != GDT_Byte )
+        nImageBytes = nXSize * (vsi_l_offset) nYSize * 2;
+    else
+        nImageBytes = nXSize * (vsi_l_offset) nYSize;
+
+    memset( abyHeader, 0, sizeof(abyHeader) );
+    
+    while( nImageBytes > 0 )
+    {
+        vsi_l_offset nWriteThisTime = MIN(nImageBytes,sizeof(abyHeader));
+        
+        if( VSIFWriteL( abyHeader, 1, (size_t)nWriteThisTime, fp ) 
+            != nWriteThisTime )
+        {
+            VSIFCloseL( fp );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Failed to write whole Istar file." );
+            return NULL;
+        }
+        nImageBytes -= nWriteThisTime;
+    }
+
+    VSIFCloseL( fp );
+
+    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+}
+
+/************************************************************************/
 /*                          GDALRegister_LAN()                          */
 /************************************************************************/
 
@@ -720,8 +1001,11 @@ void GDALRegister_LAN()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_various.html#LAN" );
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
+                                   "Byte Int16" );
         
         poDriver->pfnOpen = LANDataset::Open;
+        poDriver->pfnCreate = LANDataset::Create;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/raw/lcpdataset.cpp b/frmts/raw/lcpdataset.cpp
index 319f7d1..e12ac2f 100644
--- a/frmts/raw/lcpdataset.cpp
+++ b/frmts/raw/lcpdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: lcpdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: lcpdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  LCP Driver
  * Purpose:  FARSITE v.4 Landscape file (.lcp) reader for GDAL
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: lcpdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: lcpdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 void    GDALRegister_LCP(void);
@@ -728,6 +728,11 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     CPLFree(pszList);
 
     return( poDS );
diff --git a/frmts/raw/makefile.vc b/frmts/raw/makefile.vc
index d9e486b..e86fbc2 100644
--- a/frmts/raw/makefile.vc
+++ b/frmts/raw/makefile.vc
@@ -6,7 +6,7 @@ OBJ	=	rawdataset.obj ehdrdataset.obj pauxdataset.obj doq1dataset.obj\
 		btdataset.obj landataset.obj cpgdataset.obj idadataset.obj \
 		ndfdataset.obj dipxdataset.obj genbindataset.obj \
 		lcpdataset.obj eirdataset.obj gtxdataset.obj loslasdataset.obj \
-		ntv2dataset.obj
+		ntv2dataset.obj ace2dataset.obj snodasdataset.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/raw/mffdataset.cpp b/frmts/raw/mffdataset.cpp
index d7673bf..a9013db 100644
--- a/frmts/raw/mffdataset.cpp
+++ b/frmts/raw/mffdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mffdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: mffdataset.cpp 23425 2011-11-26 19:14:25Z rouault $
  *
  * Project:  GView
  * Purpose:  Implementation of Atlantis MFF Support
@@ -33,7 +33,7 @@
 #include "ogr_spatialref.h"
 #include "atlsci_spheroid.h"
 
-CPL_CVSID("$Id: mffdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: mffdataset.cpp 23425 2011-11-26 19:14:25Z rouault $");
 
 CPL_C_START
 void	GDALRegister_MFF(void);
@@ -543,7 +543,7 @@ void MFFDataset::ScanForProjectionInfo()
     if (pszOriginLong != NULL)
         oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN,atof(pszOriginLong));
 
-    if ((pszSpheroidName == NULL))
+    if (pszSpheroidName == NULL)
     {
         CPLError(CE_Warning,CPLE_AppDefined,
             "Warning- unspecified ellipsoid.  Using wgs-84 parameters.\n");
diff --git a/frmts/raw/ndfdataset.cpp b/frmts/raw/ndfdataset.cpp
index b993016..f6b7abd 100644
--- a/frmts/raw/ndfdataset.cpp
+++ b/frmts/raw/ndfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ndfdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ndfdataset.cpp 21749 2011-02-19 12:25:29Z rouault $
  *
  * Project:  NDF Driver
  * Purpose:  Implementation of NLAPS Data Format read support.
@@ -31,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ndfdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ndfdataset.cpp 21749 2011-02-19 12:25:29Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -49,8 +49,6 @@ class NDFDataset : public RawDataset
     char        **papszHeader;
     const char  *Get( const char *pszKey, const char *pszDefault);
 
-    int         ReadHeader( VSILFILE * );
-
   public:
     		NDFDataset();
     	        ~NDFDataset();
@@ -166,9 +164,6 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      The user must select the header file (ie. .H1).                 */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->fp == NULL )
-        return NULL;
-
     if( poOpenInfo->nHeaderBytes < 50 )
         return NULL;
 
@@ -182,14 +177,18 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      keyword is already seperated from the value by an equal         */
 /*      sign.                                                           */
 /* -------------------------------------------------------------------- */
+
+    VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (fp == NULL)
+        return NULL;
+
     const char *pszLine;
     const int nHeaderMax = 1000;
     int nHeaderLines = 0;
     char **papszHeader = (char **) CPLMalloc(sizeof(char *) * (nHeaderMax+1));
 
-    VSIRewind( poOpenInfo->fp );
-    while( nHeaderLines < nHeaderMax 
-           && (pszLine = CPLReadLine( poOpenInfo->fp )) != NULL 
+    while( nHeaderLines < nHeaderMax
+           && (pszLine = CPLReadLineL( fp )) != NULL
            && !EQUAL(pszLine,"END_OF_HDR;") )
     {
         char *pszFixed;
@@ -204,6 +203,8 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
         papszHeader[nHeaderLines++] = pszFixed;
         papszHeader[nHeaderLines] = NULL;
     }
+    VSIFCloseL(fp);
+    fp = NULL;
     
     if( CSLFetchNameValue( papszHeader, "PIXELS_PER_LINE" ) == NULL 
         || CSLFetchNameValue( papszHeader, "LINES_PER_DATA_FILE" ) == NULL 
@@ -443,6 +444,7 @@ void GDALRegister_NDF()
                                    "NLAPS Data Format" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_various.html#NDF" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = NDFDataset::Open;
 
diff --git a/frmts/raw/ntv2dataset.cpp b/frmts/raw/ntv2dataset.cpp
index bc6c5e8..fe4b862 100644
--- a/frmts/raw/ntv2dataset.cpp
+++ b/frmts/raw/ntv2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntv2dataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ntv2dataset.cpp 21682 2011-02-11 21:25:05Z warmerdam $
  *
  * Project:  Horizontal Datum Formats
  * Purpose:  Implementation of NTv2 datum shift format used in Canada, France, 
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ntv2dataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ntv2dataset.cpp 21682 2011-02-11 21:25:05Z warmerdam $");
 
 /** 
  * The header for the file, and each grid consists of 11 16byte records.
@@ -86,7 +86,7 @@ class NTv2Dataset : public RawDataset
     VSILFILE	*fpImage;	// image data file.
 
     int         nRecordLength;
-    int         nGridOffset;
+    vsi_l_offset nGridOffset;
     
     double      adfGeoTransform[6];
 
@@ -824,10 +824,10 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
     memset( achHeader, 0, 16 );
 
     // Use -1 (0x000080bf) as the default error value.
-    achHeader[10] = 0x80;
-    achHeader[11] = 0xbf;
-    achHeader[14] = 0x80;
-    achHeader[15] = 0xbf;
+    memset( achHeader + 10, 0x80, 1 );
+    memset( achHeader + 11, 0xbf, 1 );
+    memset( achHeader + 14, 0x80, 1 );
+    memset( achHeader + 15, 0xbf, 1 );
 
     for( i = 0; i < nXSize * nYSize; i++ )
         VSIFWriteL( achHeader, 1, 16, fp );
diff --git a/frmts/raw/pnmdataset.cpp b/frmts/raw/pnmdataset.cpp
index c327eb0..0fb395b 100644
--- a/frmts/raw/pnmdataset.cpp
+++ b/frmts/raw/pnmdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pnmdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: pnmdataset.cpp 21696 2011-02-12 20:35:50Z rouault $
  *
  * Project:  PNM Driver
  * Purpose:  Portable anymap file format imlementation
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: pnmdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: pnmdataset.cpp 21696 2011-02-12 20:35:50Z rouault $");
 
 CPL_C_START
 void    GDALRegister_PNM(void);
@@ -119,7 +119,7 @@ int PNMDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      Verify that this is a _raw_ ppm or pgm file.  Note, we don't    */
 /*      support ascii files, or pbm (1bit) files.                       */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 10 || poOpenInfo->fp == NULL )
+    if( poOpenInfo->nHeaderBytes < 10 )
         return FALSE;
 
     if( poOpenInfo->pabyHeader[0] != 'P'  ||
@@ -217,10 +217,8 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterYSize = nHeight;
 
 /* -------------------------------------------------------------------- */
-/*      Assume ownership of the file handled from the GDALOpenInfo.     */
+/*      Open file                                                       */
 /* -------------------------------------------------------------------- */
-    VSIFClose( poOpenInfo->fp );
-    poOpenInfo->fp = NULL;
 
     if( poOpenInfo->eAccess == GA_Update )
         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
@@ -428,6 +426,7 @@ void GDALRegister_PNM()
 "<CreationOptionList>"
 "   <Option name='MAXVAL' type='unsigned int' description='Maximum color value'/>"
 "</CreationOptionList>" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnOpen = PNMDataset::Open;
         poDriver->pfnCreate = PNMDataset::Create;
diff --git a/frmts/raw/snodasdataset.cpp b/frmts/raw/snodasdataset.cpp
new file mode 100644
index 0000000..ec1f544
--- /dev/null
+++ b/frmts/raw/snodasdataset.cpp
@@ -0,0 +1,516 @@
+/******************************************************************************
+ * $Id: snodasdataset.cpp 21984 2011-03-19 17:22:58Z 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
+ *
+ * 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 "ogr_srs_api.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: snodasdataset.cpp 21984 2011-03-19 17:22:58Z rouault $");
+
+// g++ -g -Wall -fPIC frmts/raw/snodasdataset.cpp -shared -o gdal_SNODAS.so -Iport -Igcore -Ifrmts/raw -Iogr -L. -lgdal
+
+CPL_C_START
+void    GDALRegister_SNODAS(void);
+CPL_C_END
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            SNODASDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class SNODASRasterBand;
+
+class SNODASDataset : public RawDataset
+{
+    CPLString   osDataFilename;
+    int         bGotTransform;
+    double      adfGeoTransform[6];
+    int         bHasNoData;
+    double      dfNoData;
+    int         bHasMin;
+    double      dfMin;
+    int         bHasMax;
+    double      dfMax;
+
+    friend class SNODASRasterBand;
+
+  public:
+                    SNODASDataset();
+                    ~SNODASDataset();
+
+    virtual CPLErr GetGeoTransform( double * padfTransform );
+    virtual const char *GetProjectionRef(void);
+
+    virtual char **GetFileList();
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
+};
+
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            SNODASRasterBand                          */
+/* ==================================================================== */
+/************************************************************************/
+
+class SNODASRasterBand : public RawRasterBand
+{
+    public:
+            SNODASRasterBand(VSILFILE* fpRaw, int nXSize, int nYSize);
+
+        virtual double GetNoDataValue( int *pbSuccess = NULL );
+        virtual double GetMinimum( int *pbSuccess = NULL );
+        virtual double GetMaximum(int *pbSuccess = NULL );
+};
+
+
+/************************************************************************/
+/*                         SNODASRasterBand()                           */
+/************************************************************************/
+
+SNODASRasterBand::SNODASRasterBand(VSILFILE* fpRaw,
+                                   int nXSize, int nYSize) :
+    RawRasterBand( fpRaw, 0, 2,
+                   nXSize * 2, GDT_Int16,
+                   !CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE)
+{
+}
+
+/************************************************************************/
+/*                          GetNoDataValue()                            */
+/************************************************************************/
+
+double SNODASRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    SNODASDataset* poGDS = (SNODASDataset*) poDS;
+    if (pbSuccess)
+        *pbSuccess = poGDS->bHasNoData;
+    if (poGDS->bHasNoData)
+        return poGDS->dfNoData;
+    else
+        return RawRasterBand::GetNoDataValue(pbSuccess);
+}
+
+/************************************************************************/
+/*                            GetMinimum()                              */
+/************************************************************************/
+
+double SNODASRasterBand::GetMinimum( int *pbSuccess )
+{
+    SNODASDataset* poGDS = (SNODASDataset*) poDS;
+    if (pbSuccess)
+        *pbSuccess = poGDS->bHasMin;
+    if (poGDS->bHasMin)
+        return poGDS->dfMin;
+    else
+        return RawRasterBand::GetMinimum(pbSuccess);
+}
+
+/************************************************************************/
+/*                            GetMaximum()                             */
+/************************************************************************/
+
+double SNODASRasterBand::GetMaximum( int *pbSuccess )
+{
+    SNODASDataset* poGDS = (SNODASDataset*) poDS;
+    if (pbSuccess)
+        *pbSuccess = poGDS->bHasMax;
+    if (poGDS->bHasMax)
+        return poGDS->dfMax;
+    else
+        return RawRasterBand::GetMaximum(pbSuccess);
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            SNODASDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                           SNODASDataset()                            */
+/************************************************************************/
+
+SNODASDataset::SNODASDataset()
+{
+    bGotTransform = 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;
+    bHasNoData = FALSE;
+    dfNoData = 0.0;
+    bHasMin = FALSE;
+    dfMin = 0.0;
+    bHasMax = FALSE;
+    dfMax = 0.0;
+}
+
+/************************************************************************/
+/*                           ~SNODASDataset()                           */
+/************************************************************************/
+
+SNODASDataset::~SNODASDataset()
+
+{
+    FlushCache();
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *SNODASDataset::GetProjectionRef()
+
+{
+    return SRS_WKT_WGS84;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr SNODASDataset::GetGeoTransform( double * padfTransform )
+
+{
+    if( bGotTransform )
+    {
+        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
+        return CE_None;
+    }
+    else
+    {
+        return GDALPamDataset::GetGeoTransform( padfTransform );
+    }
+}
+
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **SNODASDataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+    papszFileList = CSLAddString(papszFileList, osDataFilename);
+
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                            Identify()                                */
+/************************************************************************/
+
+int SNODASDataset::Identify( GDALOpenInfo * poOpenInfo )
+{
+    if (poOpenInfo->nHeaderBytes == 0)
+        return FALSE;
+
+    return EQUALN((const char*)poOpenInfo->pabyHeader,
+                  "Format version: NOHRSC GIS/RS raster file v1.1",
+                  strlen("Format version: NOHRSC GIS/RS raster file v1.1"));
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if( !Identify(poOpenInfo) )
+        return NULL;
+
+    VSILFILE    *fp;
+
+    fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
+
+    if( fp == NULL )
+    {
+        return NULL;
+    }
+
+    const char *    pszLine;
+    int             nRows = -1, nCols = -1;
+    CPLString       osDataFilename;
+    int             bIsInteger = FALSE, bIs2Bytes = FALSE;
+    double          dfNoData = 0;
+    int             bHasNoData = FALSE;
+    double          dfMin = 0;
+    int             bHasMin = FALSE;
+    double          dfMax = 0;
+    int             bHasMax = FALSE;
+    double          dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
+    int             bHasMinX = FALSE, bHasMinY = FALSE, bHasMaxX = FALSE, bHasMaxY = FALSE;
+    int             bNotProjected = FALSE, bIsWGS84 = FALSE;
+    CPLString       osDescription, osDataUnits;
+    int             nStartYear = -1, nStartMonth = -1, nStartDay = -1,
+                    nStartHour = -1, nStartMinute = -1, nStartSecond = -1;
+    int             nStopYear = -1, nStopMonth = -1, nStopDay = -1,
+                    nStopHour = -1, nStopMinute = -1, nStopSecond = -1;
+
+    while( (pszLine = CPLReadLine2L( fp, 256, NULL )) != NULL )
+    {
+        char** papszTokens = CSLTokenizeStringComplex( pszLine, ":", TRUE, FALSE );
+        if( CSLCount( papszTokens ) != 2 )
+        {
+            CSLDestroy( papszTokens );
+            continue;
+        }
+        if( papszTokens[1][0] == ' ' )
+            memmove(papszTokens[1], papszTokens[1] + 1, strlen(papszTokens[1] + 1) + 1);
+
+        if( EQUAL(papszTokens[0],"Data file pathname") )
+        {
+            osDataFilename = papszTokens[1];
+        }
+        else if( EQUAL(papszTokens[0],"Description") )
+        {
+            osDescription = papszTokens[1];
+        }
+        else if( EQUAL(papszTokens[0],"Data units") )
+        {
+            osDataUnits= papszTokens[1];
+        }
+
+        else if( EQUAL(papszTokens[0],"Start year") )
+            nStartYear = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Start month") )
+            nStartMonth = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Start day") )
+            nStartDay = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Start hour") )
+            nStartHour = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Start minute") )
+            nStartMinute = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Start second") )
+            nStartSecond = atoi(papszTokens[1]);
+
+        else if( EQUAL(papszTokens[0],"Stop year") )
+            nStopYear = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Stop month") )
+            nStopMonth = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Stop day") )
+            nStopDay = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Stop hour") )
+            nStopHour = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Stop minute") )
+            nStopMinute = atoi(papszTokens[1]);
+        else if( EQUAL(papszTokens[0],"Stop second") )
+            nStopSecond = atoi(papszTokens[1]);
+
+        else if( EQUAL(papszTokens[0],"Number of columns") )
+        {
+            nCols = atoi(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Number of rows") )
+        {
+            nRows = atoi(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Data type"))
+        {
+            bIsInteger = EQUAL(papszTokens[1],"integer");
+        }
+        else if( EQUAL(papszTokens[0],"Data bytes per pixel"))
+        {
+            bIs2Bytes = EQUAL(papszTokens[1],"2");
+        }
+        else if( EQUAL(papszTokens[0],"Projected"))
+        {
+            bNotProjected = EQUAL(papszTokens[1],"no");
+        }
+        else if( EQUAL(papszTokens[0],"Horizontal datum"))
+        {
+            bIsWGS84 = EQUAL(papszTokens[1],"WGS84");
+        }
+        else if( EQUAL(papszTokens[0],"No data value"))
+        {
+            bHasNoData = TRUE;
+            dfNoData = CPLAtofM(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Minimum data value"))
+        {
+            bHasMin = TRUE;
+            dfMin = CPLAtofM(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Maximum data value"))
+        {
+            bHasMax = TRUE;
+            dfMax = CPLAtofM(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Minimum x-axis coordinate") )
+        {
+            bHasMinX = TRUE;
+            dfMinX = CPLAtofM(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Minimum y-axis coordinate") )
+        {
+            bHasMinY = TRUE;
+            dfMinY = CPLAtofM(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Maximum x-axis coordinate") )
+        {
+            bHasMaxX = TRUE;
+            dfMaxX = CPLAtofM(papszTokens[1]);
+        }
+        else if( EQUAL(papszTokens[0],"Maximum y-axis coordinate") )
+        {
+            bHasMaxY = TRUE;
+            dfMaxY = CPLAtofM(papszTokens[1]);
+        }
+
+        CSLDestroy( papszTokens );
+    }
+
+    VSIFCloseL( fp );
+
+/* -------------------------------------------------------------------- */
+/*      Did we get the required keywords?  If not we return with        */
+/*      this never having been considered to be a match. This isn't     */
+/*      an error!                                                       */
+/* -------------------------------------------------------------------- */
+    if( nRows == -1 || nCols == -1 || !bIsInteger || !bIs2Bytes )
+        return NULL;
+
+    if( !bNotProjected || !bIsWGS84 )
+        return NULL;
+
+    if( osDataFilename.size() == 0 )
+        return NULL;
+
+    if (!GDALCheckDatasetDimensions(nCols, nRows))
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Open target binary file.                                        */
+/* -------------------------------------------------------------------- */
+    const char* pszPath = CPLGetPath(poOpenInfo->pszFilename);
+    osDataFilename = CPLFormFilename(pszPath, osDataFilename, NULL);
+
+    VSILFILE* fpRaw = VSIFOpenL( osDataFilename, "rb" );
+
+    if( fpRaw == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    SNODASDataset     *poDS;
+
+    poDS = new SNODASDataset();
+
+    poDS->nRasterXSize = nCols;
+    poDS->nRasterYSize = nRows;
+    poDS->osDataFilename = osDataFilename;
+    poDS->bHasNoData = bHasNoData;
+    poDS->dfNoData = dfNoData;
+    poDS->bHasMin = bHasMin;
+    poDS->dfMin = dfMin;
+    poDS->bHasMax = bHasMax;
+    poDS->dfMax = dfMax;
+    if (bHasMinX && bHasMinY && bHasMaxX && bHasMaxY)
+    {
+        poDS->bGotTransform = TRUE;
+        poDS->adfGeoTransform[0] = dfMinX;
+        poDS->adfGeoTransform[1] = (dfMaxX - dfMinX) / nCols;
+        poDS->adfGeoTransform[2] = 0.0;
+        poDS->adfGeoTransform[3] = dfMaxY;
+        poDS->adfGeoTransform[4] = 0.0;
+        poDS->adfGeoTransform[5] = - (dfMaxY - dfMinY) / nRows;
+    }
+
+    if (osDescription.size())
+        poDS->SetMetadataItem("Description", osDescription);
+    if (osDataUnits.size())
+        poDS->SetMetadataItem("Data_Units", osDataUnits);
+    if (nStartYear != -1 && nStartMonth != -1 && nStartDay != -1 &&
+        nStartHour != -1 && nStartMinute != -1 && nStartSecond != -1)
+        poDS->SetMetadataItem("Start_Date",
+                              CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
+                                        nStartYear, nStartMonth, nStartDay,
+                                        nStartHour, nStartMinute, nStartSecond));
+    if (nStopYear != -1 && nStopMonth != -1 && nStopDay != -1 &&
+        nStopHour != -1 && nStopMinute != -1 && nStopSecond != -1)
+        poDS->SetMetadataItem("Stop_Date",
+                              CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
+                                        nStopYear, nStopMonth, nStopDay,
+                                        nStopHour, nStopMinute, nStopSecond));
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    poDS->SetBand( 1, new SNODASRasterBand( fpRaw, nCols, nRows) );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+   
+    return( poDS );
+}
+
+/************************************************************************/
+/*                       GDALRegister_SNODAS()                          */
+/************************************************************************/
+
+void GDALRegister_SNODAS()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "SNODAS" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "SNODAS" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "Snow Data Assimilation System" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                   "frmt_various.html#SNODAS" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "hdr" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+        poDriver->pfnOpen = SNODASDataset::Open;
+        poDriver->pfnIdentify = SNODASDataset::Identify;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/frmts/rik/rikdataset.cpp b/frmts/rik/rikdataset.cpp
index 670cc7b..7d160ae 100644
--- a/frmts/rik/rikdataset.cpp
+++ b/frmts/rik/rikdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rikdataset.cpp 20246 2010-08-10 17:24:28Z rouault $
+ * $Id: rikdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  RIK Reader
  * Purpose:  All code for RIK Reader
@@ -31,7 +31,7 @@
 #include <zlib.h>
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: rikdataset.cpp 20246 2010-08-10 17:24:28Z rouault $");
+CPL_CVSID("$Id: rikdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 CPL_C_START
 void	GDALRegister_RIK(void);
@@ -1130,7 +1130,12 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
-    
+
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/rmf/rmfdataset.cpp b/frmts/rmf/rmfdataset.cpp
index ba663f4..a39d096 100644
--- a/frmts/rmf/rmfdataset.cpp
+++ b/frmts/rmf/rmfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rmfdataset.cpp 19798 2010-06-04 10:44:58Z dron $
+ * $Id: rmfdataset.cpp 22766 2011-07-23 10:14:28Z rouault $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Read/write raster files used in GIS "Integratsia"
@@ -32,7 +32,7 @@
 
 #include "rmfdataset.h"
 
-CPL_CVSID("$Id: rmfdataset.cpp 19798 2010-06-04 10:44:58Z dron $");
+CPL_CVSID("$Id: rmfdataset.cpp 22766 2011-07-23 10:14:28Z rouault $");
 
 CPL_C_START
 void    GDALRegister_RMF(void);
@@ -78,7 +78,7 @@ RMFRasterBand::RMFRasterBand( RMFDataset *poDS, int nBand,
         (poDS->GetRasterXSize() % poDS->sHeader.nTileWidth) * nDataSize;
     nLastTileHeight = poDS->GetRasterYSize() % poDS->sHeader.nTileHeight;
 
-#if DEBUG
+#ifdef DEBUG
     CPLDebug( "RMF",
               "Band %d: tile width is %d, tile height is %d, "
               " last tile width %d, last tile height %d, "
@@ -1056,7 +1056,7 @@ void RMFDataset::FlushCache()
 int RMFDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if( poOpenInfo->fp == NULL )
+    if( poOpenInfo->pabyHeader == NULL)
         return FALSE;
 
     if( memcmp(poOpenInfo->pabyHeader, RMF_SigRSW, sizeof(RMF_SigRSW)) != 0
@@ -1312,7 +1312,7 @@ do {                                                                    \
     }
 #endif
 
-#if DEBUG
+#ifdef DEBUG
     CPLDebug( "RMF", "List of block offsets/sizes:" );
 
     for ( i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i += 2 )
@@ -1430,7 +1430,7 @@ do {                                                                    \
     poDS->nYTiles = ( poDS->nRasterYSize + poDS->sHeader.nTileHeight - 1 ) /
         poDS->sHeader.nTileHeight;
 
-#if DEBUG
+#ifdef DEBUG
     CPLDebug( "RMF", "Image is %d tiles wide, %d tiles long",
               poDS->nXTiles, poDS->nYTiles );
 #endif
@@ -1627,6 +1627,7 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     {
         CPLError( CE_Failure, CPLE_OpenFailed, "Unable to create file %s.\n",
                   pszFilename );
+        delete poDS;
         return NULL;
     }
 
@@ -1695,10 +1696,25 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     {
         GUInt32 i;
 
+        if ( poDS->sHeader.nBitDepth > 8 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Cannot create color table of RSW with nBitDepth = %d. Retry with MTW ?",
+                      poDS->sHeader.nBitDepth );
+            delete poDS;
+            return NULL;
+        }
+
         poDS->sHeader.nClrTblOffset = nCurPtr;
         poDS->nColorTableSize = 1 << poDS->sHeader.nBitDepth;
         poDS->sHeader.nClrTblSize = poDS->nColorTableSize * 4;
-        poDS->pabyColorTable = (GByte *) CPLMalloc( poDS->sHeader.nClrTblSize );
+        poDS->pabyColorTable = (GByte *) VSIMalloc( poDS->sHeader.nClrTblSize );
+        if (poDS->pabyColorTable == NULL)
+        {
+            CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
+            delete poDS;
+            return NULL;
+        }
         for ( i = 0; i < poDS->nColorTableSize; i++ )
         {
             poDS->pabyColorTable[i * 4] =
@@ -1804,6 +1820,7 @@ void GDALRegister_RMF()
 "   <Option name='BLOCKXSIZE' type='int' description='Tile Width'/>"
 "   <Option name='BLOCKYSIZE' type='int' description='Tile Height'/>"
 "</CreationOptionList>" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
         poDriver->pfnIdentify = RMFDataset::Identify;
         poDriver->pfnOpen = RMFDataset::Open;
diff --git a/frmts/rs2/rs2dataset.cpp b/frmts/rs2/rs2dataset.cpp
index 8ca2d24..4a248a2 100644
--- a/frmts/rs2/rs2dataset.cpp
+++ b/frmts/rs2/rs2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rs2dataset.cpp 22066 2011-03-29 17:09:16Z warmerdam $
+ * $Id: rs2dataset.cpp 23570 2011-12-13 22:23:32Z rouault $
  *
  * Project:  Polarimetric Workstation
  * Purpose:  Radarsat 2 - XML Products (product.xml) driver
@@ -31,7 +31,7 @@
 #include "cpl_minixml.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: rs2dataset.cpp 22066 2011-03-29 17:09:16Z warmerdam $");
+CPL_CVSID("$Id: rs2dataset.cpp 23570 2011-12-13 22:23:32Z rouault $");
 
 CPL_C_START
 void    GDALRegister_RS2(void);
@@ -89,6 +89,9 @@ class RS2Dataset : public GDALPamDataset
 
     char        **papszExtraFiles;
 
+  protected:
+    virtual int         CloseDependentDatasets();
+
   public:
             RS2Dataset();
            ~RS2Dataset();
@@ -564,12 +567,34 @@ RS2Dataset::~RS2Dataset()
         GDALDeinitGCPs( nGCPCount, pasGCPList );
         CPLFree( pasGCPList );
     }
+
+    CloseDependentDatasets();
     
     CSLDestroy( papszSubDatasets );
     CSLDestroy( papszExtraFiles );
 }
 
 /************************************************************************/
+/*                      CloseDependentDatasets()                        */
+/************************************************************************/
+
+int RS2Dataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
+    if (nBands != 0)
+        bHasDroppedRef = TRUE;
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       delete papoBands[iBand];
+    }
+    nBands = 0;
+
+    return bHasDroppedRef;
+}
+
+/************************************************************************/
 /*                            GetFileList()                             */
 /************************************************************************/
 
@@ -670,16 +695,20 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         if (*pszFilename == ':')
             pszFilename++;
 
-        osMDFilename = pszFilename;
+        //need to redo the directory check:
+        //the GDALOpenInfo check would have failed because of the calibration string on the filename
+        VSIStatBufL  sStat;
+        if( VSIStatL( pszFilename, &sStat ) == 0 )
+        	poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode );
     }
 
-    else if( poOpenInfo->bIsDirectory )
+    if( poOpenInfo->bIsDirectory )
     {
         osMDFilename = 
-            CPLFormCIFilename( poOpenInfo->pszFilename, "product.xml", NULL );
+            CPLFormCIFilename( pszFilename, "product.xml", NULL );
     }
     else
-        osMDFilename = poOpenInfo->pszFilename;
+        osMDFilename = pszFilename;
 
 /* -------------------------------------------------------------------- */
 /*      Ingest the Product.xml file.                                    */
diff --git a/frmts/saga/sagadataset.cpp b/frmts/saga/sagadataset.cpp
index 2d0a091..ab8e3d1 100644
--- a/frmts/saga/sagadataset.cpp
+++ b/frmts/saga/sagadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sagadataset.cpp 22479 2011-06-02 10:41:56Z rouault $
+ * $Id: sagadataset.cpp 22699 2011-07-11 18:12:32Z rouault $
  * Project:  SAGA GIS Binary Driver
  * Purpose:  Implements the SAGA GIS Binary Grid Format.
  * Author:   Volker Wichmann, wichmann at laserdata.at
@@ -35,7 +35,7 @@
 
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: sagadataset.cpp 22479 2011-06-02 10:41:56Z rouault $");
+CPL_CVSID("$Id: sagadataset.cpp 22699 2011-07-11 18:12:32Z rouault $");
 
 #ifndef INT_MAX
 # define INT_MAX 2147483647
@@ -137,7 +137,7 @@ SAGARasterBand::SAGARasterBand( SAGADataset *poDS, int nBand )
 
 {
     this->poDS = poDS;
-    nBand = nBand;
+    this->nBand = nBand;
     
     eDataType = GDT_Float32;
 
@@ -405,13 +405,13 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
         else if( EQUALN(papszTokens[0],"CELLCOUNT_Y",strlen("CELLCOUNT_Y")) )
             nRows = atoi(papszTokens[1]);
         else if( EQUALN(papszTokens[0],"POSITION_XMIN",strlen("POSITION_XMIN")) )
-            dXmin = atof(papszTokens[1]);
+            dXmin = CPLAtofM(papszTokens[1]);
         else if( EQUALN(papszTokens[0],"POSITION_YMIN",strlen("POSITION_YMIN")) )
-            dYmin = atof(papszTokens[1]);
+            dYmin = CPLAtofM(papszTokens[1]);
         else if( EQUALN(papszTokens[0],"CELLSIZE",strlen("CELLSIZE")) )
-            dCellsize = atof(papszTokens[1]);
+            dCellsize = CPLAtofM(papszTokens[1]);
         else if( EQUALN(papszTokens[0],"NODATA_VALUE",strlen("NODATA_VALUE")) )
-            dNoData = atof(papszTokens[1]);
+            dNoData = CPLAtofM(papszTokens[1]);
         else if( EQUALN(papszTokens[0],"DATAFORMAT",strlen("DATAFORMAT")) )
             strncpy( szDataFormat, papszTokens[1], sizeof(szDataFormat)-1 );
         else if( EQUALN(papszTokens[0],"BYTEORDER_BIG",strlen("BYTEORDER_BIG")) )
@@ -419,7 +419,7 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
         else if( EQUALN(papszTokens[0],"TOPTOBOTTOM",strlen("TOPTOBOTTOM")) )
             strncpy( szTopToBottom, papszTokens[1], sizeof(szTopToBottom)-1 );
         else if( EQUALN(papszTokens[0],"Z_FACTOR",strlen("Z_FACTOR")) )
-            dZFactor = atof(papszTokens[1]);
+            dZFactor = CPLAtofM(papszTokens[1]);
 
         CSLDestroy( papszTokens );
     }
@@ -563,7 +563,17 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     poBand->m_Cols		= nCols;
 	
     poDS->SetBand( 1, poBand );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
 
     return poDS;
 }
@@ -781,60 +791,57 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
     char abyNoData[8];
     double dfNoDataVal = 0.0;
 
-    switch (eType)	/* GDT_Byte, GDT_UInt16, GDT_Int16, GDT_UInt32  */
-    {				/* GDT_Int32, GDT_Float32, GDT_Float64 */
-      case (GDT_Byte):
-      {
-          GByte nodata = SG_NODATA_GDT_Byte;
-          dfNoDataVal = nodata;
-          memcpy(abyNoData, &nodata, 1);
-          break;
-      }
-      case (GDT_UInt16):
-      {
-          GUInt16 nodata = SG_NODATA_GDT_UInt16;
-          dfNoDataVal = nodata;
-          memcpy(abyNoData, &nodata, 2);
-          break;
-      }
-      case (GDT_Int16):
-      {
-          GInt16 nodata = SG_NODATA_GDT_Int16;
-          dfNoDataVal = nodata;
-          memcpy(abyNoData, &nodata, 2);
-          break;
-      }
-      case (GDT_UInt32):
-      {
-          GUInt32 nodata = SG_NODATA_GDT_UInt32;
-          dfNoDataVal = nodata;
-          memcpy(abyNoData, &nodata, 4);
-          break;
-      }
-      case (GDT_Int32):
-      {
-          GInt32 nodata = SG_NODATA_GDT_Int32;
-          dfNoDataVal = nodata;
-          memcpy(abyNoData, &nodata, 4);
-          break;
-      }
-      default:
-      case (GDT_Float32):
-      {
-          float nodata = SG_NODATA_GDT_Float32;
-          dfNoDataVal = nodata;
-          memcpy(abyNoData, &nodata, 4);
-          break;
-      }
-      case (GDT_Float64):
-      {
-          double nodata = SG_NODATA_GDT_Float64;
-          dfNoDataVal = nodata;
-          memcpy(abyNoData, &nodata, 8);
-          break;
+    const char* pszNoDataValue = CSLFetchNameValue(papszParmList, "NODATA_VALUE");
+    if (pszNoDataValue)
+    {
+        dfNoDataVal = CPLAtofM(pszNoDataValue);
+    }
+    else
+    {
+      switch (eType)	/* GDT_Byte, GDT_UInt16, GDT_Int16, GDT_UInt32  */
+      {				/* GDT_Int32, GDT_Float32, GDT_Float64 */
+        case (GDT_Byte):
+        {
+            dfNoDataVal = SG_NODATA_GDT_Byte;
+            break;
+        }
+        case (GDT_UInt16):
+        {
+            dfNoDataVal = SG_NODATA_GDT_UInt16;
+            break;
+        }
+        case (GDT_Int16):
+        {
+            dfNoDataVal = SG_NODATA_GDT_Int16;
+            break;
+        }
+        case (GDT_UInt32):
+        {
+            dfNoDataVal = SG_NODATA_GDT_UInt32;
+            break;
+        }
+        case (GDT_Int32):
+        {
+            dfNoDataVal = SG_NODATA_GDT_Int32;
+            break;
+        }
+        default:
+        case (GDT_Float32):
+        {
+            dfNoDataVal = SG_NODATA_GDT_Float32;
+            break;
+        }
+        case (GDT_Float64):
+        {
+            dfNoDataVal = SG_NODATA_GDT_Float64;
+            break;
+        }
       }
     }
-    
+
+    GDALCopyWords(&dfNoDataVal, GDT_Float64, 0,
+                  abyNoData, eType, 0, 1);
+
     CPLString osHdrFilename = CPLResetExtension( pszFilename, "sgrd" );
     CPLErr eErr = WriteHeader( osHdrFilename, eType,
                                nXSize, nYSize,
@@ -921,6 +928,13 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
     
     char** papszCreateOptions = NULL;
     papszCreateOptions = CSLSetNameValue(papszCreateOptions, "FILL_NODATA", "NO");
+
+    int bHasNoDataValue = FALSE;
+    double dfNoDataValue = poSrcBand->GetNoDataValue(&bHasNoDataValue);
+    if (bHasNoDataValue)
+        papszCreateOptions = CSLSetNameValue(papszCreateOptions, "NODATA_VALUE",
+                                             CPLSPrintf("%.16g", dfNoDataValue));
+    
     GDALDataset* poDstDS =
         Create(pszFilename, poSrcBand->GetXSize(), poSrcBand->GetYSize(),
                1, poSrcBand->GetRasterDataType(), papszCreateOptions);
diff --git a/frmts/sde/sdedataset.cpp b/frmts/sde/sdedataset.cpp
index d3590f4..09b1596 100644
--- a/frmts/sde/sdedataset.cpp
+++ b/frmts/sde/sdedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdedataset.cpp 17926 2009-10-30 12:59:56Z hobu $
+ * $Id: sdedataset.cpp 22255 2011-04-29 19:03:26Z warmerdam $
  *
  * Project:  ESRI ArcSDE Raster reader
  * Purpose:  Dataset implementaion for ESRI ArcSDE Rasters
@@ -78,7 +78,7 @@ CPLErr SDEDataset::ComputeRasterInfo() {
         return CE_Fatal;
     }
     
-    long nRasterColumnId = 0;
+    LONG nRasterColumnId = 0;
 
     nSDEErr = SE_rascolinfo_get_id( hRasterColumn, 
                                     &nRasterColumnId);
@@ -97,30 +97,35 @@ CPLErr SDEDataset::ComputeRasterInfo() {
         IssueSDEError( nSDEErr, "SE_rascolinfo_get_id" );
         return CE_Fatal;
     }
+    
+    LONG nBandsRet;
     nSDEErr = SE_raster_get_bands(  hConnection, 
                                     raster, 
                                     &paohSDERasterBands, 
-                                    (long*)&nBands);
+                                    &nBandsRet);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_raster_get_bands" );
         return CE_Fatal;
     }
+
+    nBands = nBandsRet;
     
     SE_RASBANDINFO band;
     
     // grab our other stuff from the first band and hope for the best
     band = paohSDERasterBands[0];
     
-    
-    nSDEErr = SE_rasbandinfo_get_band_size( band, 
-                                            (long*)&nRasterXSize, 
-                                            (long*)&nRasterYSize);
+    LONG nXSRet, nYSRet;
+    nSDEErr = SE_rasbandinfo_get_band_size( band, &nXSRet, &nYSRet );
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_band_size" );
         return CE_Fatal;
     }
+
+    nRasterXSize = nXSRet;
+    nRasterYSize = nYSRet;
     
     SE_ENVELOPE extent;
     nSDEErr = SE_rasbandinfo_get_extent(band, &extent);
diff --git a/frmts/sde/sdedataset.h b/frmts/sde/sdedataset.h
index 7968ec1..ac70e74 100644
--- a/frmts/sde/sdedataset.h
+++ b/frmts/sde/sdedataset.h
@@ -11,7 +11,7 @@ class SDEDataset : public GDALDataset
     private:
         
 
-        long                nSubDataCount;
+        LONG                nSubDataCount;
         char*               pszWKT;
         
         double              dfMinX, dfMaxX, dfMinY, dfMaxY;
diff --git a/frmts/sde/sderasterband.cpp b/frmts/sde/sderasterband.cpp
index 5e701a6..647f794 100644
--- a/frmts/sde/sderasterband.cpp
+++ b/frmts/sde/sderasterband.cpp
@@ -211,21 +211,21 @@ int SDERasterBand::GetOverviewCount( void )
     // otherwise request it from SDE and set our member data with it.
     long nSDEErr;
     BOOL bSkipLevel;
+    LONG nOvRet;
     
     // return nothing if we were an overview band
     if (nOverview != -1)
         return 0;
 
-    nSDEErr = SE_rasbandinfo_get_max_level(*poBand, 
-                                           (long*)&nOverviews, 
-                                           &bSkipLevel);
+    nSDEErr = SE_rasbandinfo_get_max_level(*poBand, &nOvRet, &bSkipLevel);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_band_size" );
     }
     
+    nOverviews = nOvRet;
+
     return nOverviews;
-    
 } 
 
 /************************************************************************/
@@ -234,8 +234,7 @@ int SDERasterBand::GetOverviewCount( void )
 GDALDataType SDERasterBand::GetRasterDataType(void) 
 {
     // Always ask SDE what it thinks our type is.
-    long nSDEErr;
-
+    LONG nSDEErr;
     
     nSDEErr = SE_rasbandinfo_get_pixel_type(*poBand, &nSDERasterType);
     if( nSDEErr != SE_SUCCESS )
@@ -379,7 +378,7 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     if (error != CE_None)
         return error;
 
-    long level;
+    LONG level;
     nSDEErr = SE_rastileinfo_get_level(hTile, &level);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -394,7 +393,7 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
         return CE_Fatal;
     }        
 
-    long row, column;
+    LONG row, column;
     nSDEErr = SE_rastileinfo_get_rowcol(hTile, &row, &column);
     if( nSDEErr != SE_SUCCESS )
     {
@@ -402,7 +401,7 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
         return CE_Fatal;
     }     
 
-    long length;
+    LONG length;
     unsigned char* pixels;
     nSDEErr = SE_rastileinfo_get_pixel_data(hTile, (void**) &pixels, &length);
     if( nSDEErr != SE_SUCCESS )
@@ -466,7 +465,7 @@ void SDERasterBand::ComputeColorTable(void)
     SE_COLORMAP_TYPE eCMap_Type;
     SE_COLORMAP_DATA_TYPE eCMap_DataType;
     
-    long nCMapEntries;
+    LONG nCMapEntries;
     void * phSDEColormapData;
     
     unsigned char* puszSDECMapData;
@@ -647,21 +646,22 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
     if (error != CE_None)
         return error;
 
-
+    LONG nBXRet, nBYRet;
     nSDEErr = SE_rasterattr_get_tile_size (poGDS->hAttributes, 
-                                           (long*)&nBlockXSize, 
-                                           (long*)&nBlockYSize);
+                                           &nBXRet, &nBYRet);
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rasterattr_get_tile_size" );
         return CE_Fatal;
     }
-    
-    long offset_x, offset_y, num_bands;
 
+    nBlockXSize = nBXRet;
+    nBlockYSize = nBYRet;
+    
+    LONG offset_x, offset_y, num_bands, nXSRet, nYSRet;
+    
     nSDEErr = SE_rasterattr_get_image_size_by_level (poGDS->hAttributes,
-                                                     (long*)&nRasterXSize,
-                                                     (long*)&nRasterYSize,
+                                                     &nXSRet, &nYSRet,
                                                      &offset_x,
                                                      &offset_y,
                                                      &num_bands,
@@ -673,6 +673,9 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
         return CE_Fatal;
     }
 
+    nRasterXSize = nXSRet;
+    nRasterYSize = nYSRet;
+
     nBlockSize = nBlockXSize * nBlockYSize;
 
     // We're the base level
@@ -707,7 +710,8 @@ SE_RASCONSTRAINT& SDERasterBand::InitializeConstraint( long* nBlockXOff,
             IssueSDEError( nSDEErr, "SE_rasconstraint_create" );
         }       
 
-        nSDEErr = SE_rasconstraint_set_bands(hConstraint, 1, (long*)&nBand);
+        LONG nBandIn = nBand;
+        nSDEErr = SE_rasconstraint_set_bands(hConstraint, 1, &nBandIn);
         if( nSDEErr != SE_SUCCESS )
         {
             IssueSDEError( nSDEErr, "SE_rasconstraint_set_bands" );
diff --git a/frmts/sde/sderasterband.h b/frmts/sde/sderasterband.h
index 0c47b50..4edc616 100644
--- a/frmts/sde/sderasterband.h
+++ b/frmts/sde/sderasterband.h
@@ -31,7 +31,7 @@ class SDERasterBand : public GDALRasterBand
         int                     nOverviews;
         long                    nBlockSize;
         double                  dfDepth;
-        long                    nSDERasterType;
+        LONG                    nSDERasterType;
         SE_QUERYINFO            hQuery;
         SE_RASCONSTRAINT        hConstraint;
         GDALRasterBand**        papoOverviews;
diff --git a/frmts/sdts/sdtsdataset.cpp b/frmts/sdts/sdtsdataset.cpp
index b789c84..93d4d77 100644
--- a/frmts/sdts/sdtsdataset.cpp
+++ b/frmts/sdts/sdtsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdtsdataset.cpp 20504 2010-09-02 02:40:49Z warmerdam $
+ * $Id: sdtsdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  GDALDataset driver for SDTS Raster translator.
@@ -31,7 +31,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: sdtsdataset.cpp 20504 2010-09-02 02:40:49Z warmerdam $");
+CPL_CVSID("$Id: sdtsdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
 
 /**
  \file sdtsdataset.cpp
@@ -285,6 +285,11 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
+/* -------------------------------------------------------------------- */
+/*      Check for external overviews.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
     return( poDS );
 }
 
diff --git a/frmts/sgi/sgidataset.cpp b/frmts/sgi/sgidataset.cpp
index 7a2719d..4e4e31b 100644
--- a/frmts/sgi/sgidataset.cpp
+++ b/frmts/sgi/sgidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sgidataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: sgidataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  SGI Image Driver
  * Purpose:  Implement SGI Image Support based on Paul Bourke's SGI Image code.
@@ -35,7 +35,7 @@
 #include "cpl_port.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: sgidataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: sgidataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 CPL_C_START
 void	GDALRegister_SGI(void);
@@ -334,7 +334,7 @@ CPLErr SGIRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                 && pabyRawBuf[iX + nRepeatCount + 1] 
                 == pabyRawBuf[iX + nRepeatCount + 3]) )
         { // encode a constant run.
-            pabyRLEBuf[nRLEBytes++] = nRepeatCount; 
+            pabyRLEBuf[nRLEBytes++] = (GByte) nRepeatCount; 
             pabyRLEBuf[nRLEBytes++] = pabyRawBuf[iX];
             iX += nRepeatCount;
         }
@@ -357,7 +357,7 @@ CPLErr SGIRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                     break;
             }
 
-            pabyRLEBuf[nRLEBytes++] = 0x80 | nRepeatCount; 
+            pabyRLEBuf[nRLEBytes++] = (GByte) (0x80 | nRepeatCount); 
             memcpy( pabyRLEBuf + nRLEBytes, 
                     pabyRawBuf + iX, 
                     nRepeatCount );
@@ -758,7 +758,7 @@ GDALDataset *SGIDataset::Create( const char * pszFilename,
     
     while( nPixelsRemaining > 0 )
     {
-        pabyRLELine[nRLEBytes] = MIN(127,nPixelsRemaining);
+        pabyRLELine[nRLEBytes] = (GByte) MIN(127,nPixelsRemaining);
         pabyRLELine[nRLEBytes+1] = 0;
         nPixelsRemaining -= pabyRLELine[nRLEBytes];
 
diff --git a/frmts/srtmhgt/srtmhgtdataset.cpp b/frmts/srtmhgt/srtmhgtdataset.cpp
index 61592ea..9858648 100644
--- a/frmts/srtmhgt/srtmhgtdataset.cpp
+++ b/frmts/srtmhgt/srtmhgtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: srtmhgtdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: srtmhgtdataset.cpp 22163 2011-04-14 21:26:21Z rouault $
  *
  * Project:  SRTM HGT Driver
  * Purpose:  SRTM HGT File Read Support.
@@ -37,7 +37,7 @@
 
 #define SRTMHG_NODATA_VALUE -32768
 
-CPL_CVSID("$Id: srtmhgtdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: srtmhgtdataset.cpp 22163 2011-04-14 21:26:21Z rouault $");
 
 CPL_C_START
 void	GDALRegister_SRTMHGT(void);
@@ -299,14 +299,14 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
   int southWestLon = atoi(latLonValueString);
 
   if(fileName[0] == 'N' || fileName[0] == 'n')
-    southWestLat = southWestLat;
+    /*southWestLat = southWestLat */;
   else if(fileName[0] == 'S' || fileName[0] == 's')
     southWestLat = southWestLat * -1;
   else
     return NULL;
 
   if(fileName[3] == 'E' || fileName[3] == 'e')
-    southWestLon = southWestLon;
+    /*southWestLon = southWestLon */;
   else if(fileName[3] == 'W' || fileName[3] == 'w')
     southWestLon = southWestLon * -1;
   else
@@ -486,6 +486,12 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename, GDALDataset
 /*      Write output file.                                              */
 /* -------------------------------------------------------------------- */
     VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
+    if (fp == NULL)
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Cannot create file %s", pszFilename );
+        return NULL;
+    }
 
     GInt16* panData = (GInt16*) CPLMalloc(sizeof(GInt16) * nXSize);
     GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(1);
diff --git a/frmts/terragen/terragendataset.cpp b/frmts/terragen/terragendataset.cpp
index 19dfcad..9887057 100644
--- a/frmts/terragen/terragendataset.cpp
+++ b/frmts/terragen/terragendataset.cpp
@@ -106,7 +106,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-// CPL_CVSID("$Id: terragendataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+// CPL_CVSID("$Id: terragendataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 CPL_C_START
 void	GDALRegister_Terragen(void);
@@ -621,7 +621,7 @@ bool TerragenDataset::write_header()
 	// Increase the heightscale until the physical span
 	// fits within a 16-bit range. The smaller the logical span,
 	// the more necessary this becomes.
-	int hs, bh;
+	int hs, bh=0;
 	for(hs = m_nHeightScale; hs <= 32767; hs++)
 	{
 		double prevdelta = 1.0e30;
@@ -659,8 +659,8 @@ bool TerragenDataset::write_header()
         return false;
 	}
 		
-	m_nHeightScale = hs;
-	m_nBaseHeight = bh;
+	m_nHeightScale = (GInt16) hs;
+	m_nBaseHeight = (GInt16) bh;
 
 
 	// m_nHeightScale is the one that gives us the 
diff --git a/frmts/til/tildataset.cpp b/frmts/til/tildataset.cpp
index 3d6aa04..338d403 100644
--- a/frmts/til/tildataset.cpp
+++ b/frmts/til/tildataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tildataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: tildataset.cpp 22713 2011-07-12 10:06:39Z rouault $
  *
  * Project:  EarthWatch .TIL Driver
  * Purpose:  Implementation of the TILDataset class.
@@ -35,7 +35,7 @@
 #include "cpl_multiproc.h"
 #include "cplkeywordparser.h"
 
-CPL_CVSID("$Id: tildataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: tildataset.cpp 22713 2011-07-12 10:06:39Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,10 +48,18 @@ class CPL_DLL TILDataset : public GDALPamDataset
     VRTDataset *poVRTDS;
     std::vector<GDALDataset *> apoTileDS;
 
+    CPLString                  osRPBFilename;
+    CPLString                  osIMDFilename;
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
   public:
     TILDataset();
     ~TILDataset();
 
+    virtual char **GetFileList(void);
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo *poOpenInfo );
 };
@@ -124,14 +132,31 @@ TILDataset::TILDataset()
 TILDataset::~TILDataset()
 
 {
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int TILDataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
     if( poVRTDS )
+    {
+        bHasDroppedRef = TRUE;
         delete poVRTDS;
+        poVRTDS = NULL;
+    }
 
     while( !apoTileDS.empty() )
     {
         GDALClose( (GDALDatasetH) apoTileDS.back() );
         apoTileDS.pop_back();
     }
+
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -177,8 +202,13 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try to find the corresponding .IMD file.                        */
 /* -------------------------------------------------------------------- */
-    char **papszIMD = GDALLoadIMDFile( poOpenInfo->pszFilename, 
-                                       poOpenInfo->papszSiblingFiles );
+    char **papszIMD = NULL;
+    CPLString osIMDFilename = 
+        GDALFindAssociatedFile( poOpenInfo->pszFilename, "IMD", 
+                                poOpenInfo->papszSiblingFiles, 0 );
+
+    if( osIMDFilename != "" )
+        papszIMD = GDALLoadIMDFile( osIMDFilename, NULL );
 
     if( papszIMD == NULL )
     {
@@ -228,6 +258,8 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS = new TILDataset();
 
+    poDS->osIMDFilename = osIMDFilename; 
+    poDS->SetMetadata( papszIMD, "IMD" );
     poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszIMD,"numColumns","0"));
     poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszIMD,"numRows","0"));
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
@@ -338,14 +370,9 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
         osKey.Printf( "TILE_%d.LRRowOffset", iTile );
         int nLRY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
 
-#ifdef notdef
-        GDALDataset *poTileDS = (GDALDataset *) 
-            GDALOpen(osFilename,GA_ReadOnly);
-#else
         GDALDataset *poTileDS = 
             new GDALProxyPoolDataset( osFilename, 
                                       nLRX - nULX + 1, nLRY - nULY + 1 );
-#endif
         if( poTileDS == NULL )
             continue;
 
@@ -353,10 +380,9 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 
         for( iBand = 1; iBand <= nBandCount; iBand++ )
         {
-#ifndef notdef
             ((GDALProxyPoolDataset *) poTileDS)->
                 AddSrcBandDescription( eDT, nLRX - nULX + 1, 1 );
-#endif            
+
             GDALRasterBand *poSrcBand = poTileDS->GetRasterBand(iBand);
 
             VRTSourcedRasterBand *poVRTBand = 
@@ -373,18 +399,21 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Set RPC and IMD metadata.                                       */
 /* -------------------------------------------------------------------- */
-    char **papszRPCMD = GDALLoadRPBFile( poOpenInfo->pszFilename,
-                                         poOpenInfo->papszSiblingFiles );
-        
-    if( papszRPCMD != NULL )
+    poDS->osRPBFilename = 
+        GDALFindAssociatedFile( poOpenInfo->pszFilename, "RPB", 
+                                poOpenInfo->papszSiblingFiles, 0 );
+    if( poDS->osRPBFilename != "" )
     {
-        poDS->SetMetadata( papszRPCMD, "RPC" );
-        CSLDestroy( papszRPCMD );
+        char **papszRPCMD = GDALLoadRPBFile( poOpenInfo->pszFilename,
+                                             poOpenInfo->papszSiblingFiles );
+        
+        if( papszRPCMD != NULL )
+        {
+            poDS->SetMetadata( papszRPCMD, "RPC" );
+            CSLDestroy( papszRPCMD );
+        }
     }
 
-    if( papszIMD != NULL )
-        poDS->SetMetadata( papszIMD, "IMD" );
-
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
@@ -405,6 +434,29 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **TILDataset::GetFileList()
+
+{
+    unsigned int  i;
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+    for( i = 0; i < apoTileDS.size(); i++ )
+        papszFileList = CSLAddString( papszFileList,
+                                      apoTileDS[i]->GetDescription() );
+    
+    papszFileList = CSLAddString( papszFileList, osIMDFilename );
+
+
+    if( osRPBFilename != "" )
+        papszFileList = CSLAddString( papszFileList, osRPBFilename );
+
+    return papszFileList;
+}
+
+/************************************************************************/
 /*                          GDALRegister_TIL()                          */
 /************************************************************************/
 
@@ -422,7 +474,9 @@ void GDALRegister_TIL()
                                    "EarthWatch .TIL" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_til.html" );
-        
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = TILDataset::Open;
         poDriver->pfnIdentify = TILDataset::Identify;
 
diff --git a/frmts/tsx/tsxdataset.cpp b/frmts/tsx/tsxdataset.cpp
index 322161c..6f01584 100644
--- a/frmts/tsx/tsxdataset.cpp
+++ b/frmts/tsx/tsxdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tsxdataset.cpp 19617 2010-05-04 23:21:04Z pvachon $
+ * $Id: tsxdataset.cpp 23569 2011-12-13 21:53:07Z rouault $
  *
  * Project:     TerraSAR-X XML Product Support
  * Purpose:     Support for TerraSAR-X XML Metadata files
@@ -35,7 +35,7 @@
 
 #define MAX_GCPS 5000    //this should be more than enough ground control points
 
-CPL_CVSID("$Id: tsxdataset.cpp 19617 2010-05-04 23:21:04Z pvachon $");
+CPL_CVSID("$Id: tsxdataset.cpp 23569 2011-12-13 21:53:07Z rouault $");
 
 CPL_C_START
 void GDALRegister_TSX(void);
@@ -64,18 +64,18 @@ enum eProductType {
 /* GetFilePath: return a relative path to a file within an XML node.
  * Returns Null on failure
  */
-const char *GetFilePath(CPLXMLNode *psXMLNode, char **pszNodeType) {
+const char *GetFilePath(CPLXMLNode *psXMLNode, const char **pszNodeType) {
     const char *pszDirectory, *pszFilename;
 
     pszDirectory = CPLGetXMLValue( psXMLNode, "file.location.path", "" );
     pszFilename = CPLGetXMLValue( psXMLNode, "file.location.filename", "" );
-    *pszNodeType = strdup(CPLGetXMLValue (psXMLNode, "type", " " ));
+    *pszNodeType = CPLGetXMLValue (psXMLNode, "type", " " );
 
     if (pszDirectory == NULL || pszFilename == NULL) {
         return NULL;
     }
 
-    return strdup( CPLFormFilename( pszDirectory, pszFilename, "" ) );
+    return CPLFormFilename( pszDirectory, pszFilename, "" );
 }
 
 /************************************************************************/
@@ -95,7 +95,6 @@ class TSXDataset : public GDALPamDataset {
     bool bHaveGeoTransform;
 
     char *pszGeorefFile;
-    FILE *fp;
 
     eProductType nProduct;
 public:
@@ -256,12 +255,31 @@ TSXDataset::~TSXDataset() {
 /*                              Identify()                              */
 /************************************************************************/
 
-int TSXDataset::Identify( GDALOpenInfo *poOpenInfo ) {
+int TSXDataset::Identify( GDALOpenInfo *poOpenInfo )
+{
     if (poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 260)
-        return 0;
+    {
+        if( poOpenInfo->bIsDirectory )
+        {
+            CPLString osFilename =
+                CPLFormCIFilename( poOpenInfo->pszFilename, CPLGetFilename( poOpenInfo->pszFilename ), "xml" );
+
+            /* Check if the filename contains TSX1_SAR (TerraSAR-X) or TDX1_SAR (TanDEM-X) */
+            if (!(EQUALN(CPLGetBasename( osFilename ), "TSX1_SAR", 8) ||
+                  EQUALN(CPLGetBasename( osFilename ), "TDX1_SAR", 8)))
+                return 0;
+
+            VSIStatBufL sStat;
+            if( VSIStatL( osFilename, &sStat ) == 0 )
+                return 1;
+
+            return 0;
+        }
+    }
 
-    /* Check if the filename contains TSX1_SAR */
-    if (!EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TSX1_SAR", 8))
+    /* Check if the filename contains TSX1_SAR (TerraSAR-X) or TDX1_SAR (TanDEM-X) */
+    if (!(EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TSX1_SAR", 8) ||
+          EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TDX1_SAR", 8)))
         return 0;
 
     /* finally look for the <level1Product tag */
@@ -317,7 +335,10 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
     CPLXMLNode *psNode;
     CPLXMLNode *psGeolocationGrid = CPLGetXMLNode( psGeorefData, "=geoReference.geolocationGrid" );
     if (psGeolocationGrid==NULL)
+    {
+        CPLDestroyXMLNode( psGeorefData );
         return false;
+    }
     nGCPCount = atoi(CPLGetXMLValue( psGeolocationGrid, "numberOfGridPoints.total", "0" ));
     //count the gcps if the given count value is invalid
     if (nGCPCount<=0)
@@ -328,7 +349,11 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
     }
     //if there are no gcps, fail
     if(nGCPCount<=0)
+    {
+        CPLDestroyXMLNode( psGeorefData );
         return false;
+    }
+
     //put some reasonable limits of the number of gcps
     if (nGCPCount>MAX_GCPS )
         nGCPCount=MAX_GCPS;
@@ -349,7 +374,10 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
                  !strcmp(CPLGetXMLValue(psNode,"row","error"), "error") ||
                  !strcmp(CPLGetXMLValue(psNode,"lon","error"), "error") ||
                  !strcmp(CPLGetXMLValue(psNode,"lat","error"), "error"))
-             return false;
+        {
+            CPLDestroyXMLNode( psGeorefData );
+            return false;
+        }
     }
     for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
     {
@@ -382,11 +410,13 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
          //looks like height is in meters - should it be converted so xyz are all on the same scale??
          psGCP->dfGCPZ = 0;
              //atof(CPLGetXMLValue(psNode,"height",""));
-
     }
 
+    CPLFree(pszGCPProjection);
     osr.exportToWkt( &(pszGCPProjection) );
 
+    CPLDestroyXMLNode( psGeorefData );
+
     return true;
 }
 
@@ -398,7 +428,8 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
 /* -------------------------------------------------------------------- */
 /*      Is this a TerraSAR-X product file?                              */
 /* -------------------------------------------------------------------- */
-    if (!TSXDataset::Identify( poOpenInfo )) {
+    if (!TSXDataset::Identify( poOpenInfo ))
+    {
         return NULL; /* nope */
     }
 
@@ -413,23 +444,37 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
         return NULL;
     }
 
+    CPLString osFilename;
+
+    if( poOpenInfo->bIsDirectory )
+    {
+        osFilename =
+                CPLFormCIFilename( poOpenInfo->pszFilename, CPLGetFilename( poOpenInfo->pszFilename ), "xml" );
+    }
+    else
+        osFilename = poOpenInfo->pszFilename;
+
     /* Ingest the XML */
     CPLXMLNode *psData, *psComponents, *psProductInfo;
-    psData = CPLParseXMLFile( poOpenInfo->pszFilename );
+    psData = CPLParseXMLFile( osFilename );
+    if (psData == NULL)
+        return NULL;
 
     /* find the product components */
     psComponents = CPLGetXMLNode( psData, "=level1Product.productComponents" );
     if (psComponents == NULL) {
         CPLError( CE_Failure, CPLE_OpenFailed,
             "Unable to find <productComponents> tag in file.\n" );
+        CPLDestroyXMLNode(psData);
         return NULL;
     }
 
     /* find the product info tag */
     psProductInfo = CPLGetXMLNode( psData, "=level1Product.productInfo" );
-    if (psComponents == NULL) {
+    if (psProductInfo == NULL) {
         CPLError( CE_Failure, CPLE_OpenFailed,
             "Unable to find <productInfo> tag in file.\n" );
+        CPLDestroyXMLNode(psData);
         return NULL;
     }
 
@@ -438,8 +483,6 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
 /* -------------------------------------------------------------------- */
 
     TSXDataset *poDS = new TSXDataset();
-    poDS->fp = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Read in product info.                                           */
@@ -459,7 +502,7 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
         "acquisitionInfo.imagingMode", "unknown" ) );
     poDS->SetMetadataItem( "PRODUCT_VARIANT", CPLGetXMLValue( psProductInfo,
         "productVariantInfo.productVariant", "unknown" ) );
-    char *pszDataType = strdup( CPLGetXMLValue( psProductInfo,
+    char *pszDataType = CPLStrdup( CPLGetXMLValue( psProductInfo,
         "imageDataInfo.imageDataType", "unknown" ) );
     poDS->SetMetadataItem( "IMAGE_TYPE", pszDataType );
 
@@ -511,9 +554,9 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
     for (psComponent = psComponents->psChild; psComponent != NULL;
          psComponent = psComponent->psNext)
     {
-        char *pszType;
+        const char *pszType = NULL;
         pszPath = CPLFormFilename(
-                CPLGetDirname( poOpenInfo->pszFilename ),
+                CPLGetDirname( osFilename ),
                 GetFilePath(psComponent, &pszType),
                 "" );
         const char *pszPolLayer = CPLGetXMLValue(psComponent, "polLayer", " ");
@@ -525,9 +568,8 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
             }
             else if (EQUALN(pszType, "GEOREF", 6)) {
                 /* save the path to the georef data for later use */
-                pszGeorefFile = strdup( pszPath );
+                pszGeorefFile = CPLStrdup( pszPath );
             }
-            CPLFree(pszType);
         }
         else if( !EQUALN(pszPolLayer, " ", 1) &&
             EQUALN(psComponent->pszValue, "imageData", 9) ) {
@@ -558,14 +600,14 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
                 poBand = new TSXRasterBand( poDS, eDataType, ePol,
                     poBandData );
                 poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
-            }
 
-            //copy georeferencing info from the band
-            //need error checking??
-            //it will just save the info from the last band
-            CPLFree( poDS->pszProjection );
-            poDS->pszProjection = CPLStrdup(poBandData->GetProjectionRef());
-            geoTransformErr = poBandData->GetGeoTransform(poDS->adfGeoTransform);
+                //copy georeferencing info from the band
+                //need error checking??
+                //it will just save the info from the last band
+                CPLFree( poDS->pszProjection );
+                poDS->pszProjection = CPLStrdup(poBandData->GetProjectionRef());
+                geoTransformErr = poBandData->GetGeoTransform(poDS->adfGeoTransform);
+            }
         }
     }
 
@@ -619,7 +661,6 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
             int nGCP = 0;
             double dfAvgHeight = atof(CPLGetXMLValue(psSceneInfo,
                 "sceneAverageHeight", "0.0"));
-            char szID[3];
 
             //count and allocate gcps - there should be five - 4 corners and a centre
             poDS->nGCPCount = 0;
@@ -644,15 +685,13 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
                         !EQUAL(psNode->pszValue, "sceneCornerCoord"))
                         continue;
 
-                    CPLSPrintf( szID, "%d", nGCP );
-
                     psGCP->dfGCPPixel = atof(CPLGetXMLValue(psNode, "refColumn",
                         "0.0"));
                     psGCP->dfGCPLine = atof(CPLGetXMLValue(psNode, "refRow", "0.0"));
                     psGCP->dfGCPX = atof(CPLGetXMLValue(psNode, "lon", "0.0"));
                     psGCP->dfGCPY = atof(CPLGetXMLValue(psNode, "lat", "0.0"));
                     psGCP->dfGCPZ = dfAvgHeight;
-                    psGCP->pszId = CPLStrdup( szID );
+                    psGCP->pszId = CPLStrdup( CPLSPrintf( "%d", nGCP ) );
                     psGCP->pszInfo = CPLStrdup("");
 
                     nGCP++;
@@ -661,6 +700,7 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
                 //set the projection string - the fields are lat/long - seems to be WGS84 datum
                 OGRSpatialReference osr;
                 osr.SetWellKnownGeogCS( "WGS84" );
+                CPLFree(poDS->pszGCPProjection);
                 osr.exportToWkt( &(poDS->pszGCPProjection) );
             }
         }
@@ -686,6 +726,8 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
             "Proceeding with caution.");
     }
 
+    CPLFree(pszGeorefFile);
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -763,6 +805,8 @@ void GDALRegister_TSX() {
                                    "TerraSAR-X Product" );
 /*        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_tsx.html" ); */
 
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = TSXDataset::Open;
         poDriver->pfnIdentify = TSXDataset::Identify;
 
diff --git a/frmts/usgsdem/usgsdem_create.cpp b/frmts/usgsdem/usgsdem_create.cpp
index bf3c884..526a8c4 100644
--- a/frmts/usgsdem/usgsdem_create.cpp
+++ b/frmts/usgsdem/usgsdem_create.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: usgsdem_create.cpp 17551 2009-08-21 11:49:27Z rouault $
+ * $Id: usgsdem_create.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  USGS DEM Driver
  * Purpose:  CreateCopy() implementation.
@@ -36,7 +36,7 @@
 #include "gdalwarper.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: usgsdem_create.cpp 17551 2009-08-21 11:49:27Z rouault $");
+CPL_CVSID("$Id: usgsdem_create.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 typedef struct 
 {
@@ -61,7 +61,7 @@ typedef struct
     char 	**papszOptions;
     int         bStrict;
 
-    FILE       *fp;
+    VSILFILE  *fp;
 
     GInt16     *panData;
     
@@ -80,7 +80,7 @@ static void USGSDEMWriteCleanup( USGSDEMWriteInfo *psWInfo )
     CPLFree( psWInfo->pszDstSRS );
     CPLFree( psWInfo->pszFilename );
     if( psWInfo->fp != NULL )
-        VSIFClose( psWInfo->fp );
+        VSIFCloseL( psWInfo->fp );
     if( psWInfo->panData != NULL )
         VSIFree( psWInfo->panData );
 }
@@ -282,9 +282,9 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
         CSLFetchNameValue( psWInfo->papszOptions, "TEMPLATE" );
     if( pszTemplate != NULL )
     {
-        FILE *fpTemplate;
+        VSILFILE *fpTemplate;
 
-        fpTemplate = VSIFOpen( pszTemplate, "rb" );
+        fpTemplate = VSIFOpenL( pszTemplate, "rb" );
         if( fpTemplate == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
@@ -293,14 +293,14 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
             return FALSE;
         }
 
-        if( VSIFRead( achARec, 1, 1024, fpTemplate ) != 1024 )
+        if( VSIFReadL( achARec, 1, 1024, fpTemplate ) != 1024 )
         {
             CPLError( CE_Failure, CPLE_FileIO, 
                       "Unable to read 1024 byte A Record from template file '%s'.\n%s",
                       pszTemplate, VSIStrerror( errno ) );
             return FALSE;
         }
-        VSIFClose( fpTemplate );
+        VSIFCloseL( fpTemplate );
     }
     
 /* -------------------------------------------------------------------- */
@@ -528,8 +528,8 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
     }
 
     /* take into account z resolutions that are not 1.0 */
-    nMin = (int) floor(nMin * psWInfo->dfElevStepSize);
-    nMax = (int) ceil(nMax * psWInfo->dfElevStepSize);
+    nMin = (GInt16) floor(nMin * psWInfo->dfElevStepSize);
+    nMax = (GInt16) ceil(nMax * psWInfo->dfElevStepSize);
     
     USGSDEMPrintDouble( achARec + 738, (double) nMin );
     USGSDEMPrintDouble( achARec + 762, (double) nMax );
@@ -690,7 +690,7 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
 /* -------------------------------------------------------------------- */
 /*      Write to file.                                                  */
 /* -------------------------------------------------------------------- */
-    if( VSIFWrite( achARec, 1, 1024, psWInfo->fp ) != 1024 )
+    if( VSIFWriteL( achARec, 1, 1024, psWInfo->fp ) != 1024 )
     {
         CPLError( CE_Failure, CPLE_FileIO, 
                   "Error writing DEM/CDED A record.\n%s", 
@@ -787,8 +787,8 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
     }
     
     /* take into account z resolutions that are not 1.0 */
-    nMin = (int) floor(nMin * psWInfo->dfElevStepSize);
-    nMax = (int) ceil(nMax * psWInfo->dfElevStepSize);
+    nMin = (GInt16) floor(nMin * psWInfo->dfElevStepSize);
+    nMax = (GInt16) ceil(nMax * psWInfo->dfElevStepSize);
 
     USGSDEMPrintDouble( achBuffer +  96, (double) nMin );
     USGSDEMPrintDouble( achBuffer +  120, (double) nMax );
@@ -806,7 +806,7 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
 
         if( iOffset + 6 > 1024 )
         {
-            if( VSIFWrite( achBuffer, 1, 1024, psWInfo->fp ) != 1024 )
+            if( VSIFWriteL( achBuffer, 1, 1024, psWInfo->fp ) != 1024 )
             {
                 CPLError( CE_Failure, CPLE_FileIO, 
                           "Failure writing profile to disk.\n%s", 
@@ -826,7 +826,7 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
 /* -------------------------------------------------------------------- */
 /*      Flush final partial block.                                      */
 /* -------------------------------------------------------------------- */
-    if( VSIFWrite( achBuffer, 1, 1024, psWInfo->fp ) != 1024 )
+    if( VSIFWriteL( achBuffer, 1, 1024, psWInfo->fp ) != 1024 )
     {
         CPLError( CE_Failure, CPLE_FileIO, 
                   "Failure writing profile to disk.\n%s", 
@@ -1523,7 +1523,7 @@ USGSDEMCreateCopy( const char *pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    sWInfo.fp = VSIFOpen( pszFilename, "wb" );
+    sWInfo.fp = VSIFOpenL( pszFilename, "wb" );
     if( sWInfo.fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
diff --git a/frmts/usgsdem/usgsdemdataset.cpp b/frmts/usgsdem/usgsdemdataset.cpp
index c5bc27a..07696f3 100644
--- a/frmts/usgsdem/usgsdemdataset.cpp
+++ b/frmts/usgsdem/usgsdemdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: usgsdemdataset.cpp 21831 2011-02-24 17:51:40Z warmerdam $
+ * $Id: usgsdemdataset.cpp 21830 2011-02-24 17:46:07Z warmerdam $
  *
  * Project:  USGS DEM Driver
  * Purpose:  All reader for USGS DEM Reader
@@ -33,7 +33,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: usgsdemdataset.cpp 21831 2011-02-24 17:51:40Z warmerdam $");
+CPL_CVSID("$Id: usgsdemdataset.cpp 21830 2011-02-24 17:46:07Z warmerdam $");
 
 CPL_C_START
 void	GDALRegister_USGSDEM(void);
@@ -50,17 +50,188 @@ GDALDataset *USGSDEMCreateCopy( const char *, GDALDataset *, int, char **,
                                 GDALProgressFunc pfnProgress, 
                                 void * pProgressData );
 
+
+/************************************************************************/
+/*                              ReadInt()                               */
+/************************************************************************/
+
+static int ReadInt( VSILFILE *fp )
+{
+    int nVal = 0;
+    char c;
+    int nRead = 0;
+    vsi_l_offset nOffset = VSIFTellL(fp);
+
+    while (TRUE)
+    {
+        if (VSIFReadL(&c, 1, 1, fp) != 1)
+        {
+            return 0;
+        }
+        else
+            nRead ++;
+        if (!isspace((int)c))
+            break;
+    }
+
+    int nSign = 1;
+    if (c == '-')
+        nSign = -1;
+    else if (c == '+')
+        nSign = 1;
+    else if (c >= '0' && c <= '9')
+        nVal = c - '0';
+    else
+    {
+        VSIFSeekL(fp, nOffset + nRead, SEEK_SET);
+        return 0;
+    }
+
+    while (TRUE)
+    {
+        if (VSIFReadL(&c, 1, 1, fp) != 1)
+            return nSign * nVal;
+        nRead ++;
+        if (c >= '0' && c <= '9')
+            nVal = nVal * 10 + (c - '0');
+        else
+        {
+            VSIFSeekL(fp, nOffset + (nRead - 1), SEEK_SET);
+            return nSign * nVal;
+        }
+    }
+}
+
+typedef struct
+{
+    VSILFILE *fp;
+    int max_size;
+    char* buffer;
+    int buffer_size;
+    int cur_index;
+} Buffer;
+
+/************************************************************************/
+/*                       USGSDEMRefillBuffer()                          */
+/************************************************************************/
+
+static void USGSDEMRefillBuffer( Buffer* psBuffer )
+{
+    memmove(psBuffer->buffer, psBuffer->buffer + psBuffer->cur_index,
+            psBuffer->buffer_size - psBuffer->cur_index);
+
+    psBuffer->buffer_size -= psBuffer->cur_index;
+    psBuffer->buffer_size += VSIFReadL(psBuffer->buffer + psBuffer->buffer_size,
+                                       1, psBuffer->max_size - psBuffer->buffer_size,
+                                       psBuffer->fp);
+    psBuffer->cur_index = 0;
+}
+
+/************************************************************************/
+/*               USGSDEMReadIntFromBuffer()                             */
+/************************************************************************/
+
+static int USGSDEMReadIntFromBuffer( Buffer* psBuffer )
+{
+    int nVal = 0;
+    char c;
+
+    while (TRUE)
+    {
+        if (psBuffer->cur_index >= psBuffer->buffer_size)
+        {
+            USGSDEMRefillBuffer(psBuffer);
+            if (psBuffer->cur_index >= psBuffer->buffer_size)
+            {
+                return 0;
+            }
+        }
+
+        c = psBuffer->buffer[psBuffer->cur_index];
+        psBuffer->cur_index ++;
+        if (!isspace((int)c))
+            break;
+    }
+
+    int nSign = 1;
+    if (c == '-')
+        nSign = -1;
+    else if (c == '+')
+        nSign = 1;
+    else if (c >= '0' && c <= '9')
+        nVal = c - '0';
+    else
+    {
+        return 0;
+    }
+
+    while (TRUE)
+    {
+        if (psBuffer->cur_index >= psBuffer->buffer_size)
+        {
+            USGSDEMRefillBuffer(psBuffer);
+            if (psBuffer->cur_index >= psBuffer->buffer_size)
+            {
+                return nSign * nVal;
+            }
+        }
+
+        c = psBuffer->buffer[psBuffer->cur_index];
+        if (c >= '0' && c <= '9')
+        {
+            psBuffer->cur_index ++;
+            nVal = nVal * 10 + (c - '0');
+        }
+        else
+            return nSign * nVal;
+    }
+}
+
+/************************************************************************/
+/*                USGSDEMReadDoubleFromBuffer()                         */
+/************************************************************************/
+
+static double USGSDEMReadDoubleFromBuffer( Buffer* psBuffer, int nCharCount )
+
+{
+    int     i;
+
+    if (psBuffer->cur_index + nCharCount > psBuffer->buffer_size)
+    {
+        USGSDEMRefillBuffer(psBuffer);
+        if (psBuffer->cur_index + nCharCount > psBuffer->buffer_size)
+        {
+            return 0;
+        }
+    }
+
+    char* szPtr = psBuffer->buffer + psBuffer->cur_index;
+    char backupC = szPtr[nCharCount];
+    szPtr[nCharCount] = 0;
+    for( i = 0; i < nCharCount; i++ )
+    {
+        if( szPtr[i] == 'D' )
+            szPtr[i] = 'E';
+    }
+
+    double dfVal = CPLAtof(szPtr);
+    szPtr[nCharCount] = backupC;
+    psBuffer->cur_index += nCharCount;
+
+    return dfVal;
+}
+
 /************************************************************************/
 /*                              DConvert()                              */
 /************************************************************************/
 
-static double DConvert( FILE *fp, int nCharCount )
+static double DConvert( VSILFILE *fp, int nCharCount )
 
 {
     char	szBuffer[100];
     int		i;
 
-    VSIFRead( szBuffer, nCharCount, 1, fp );
+    VSIFReadL( szBuffer, nCharCount, 1, fp );
     szBuffer[nCharCount] = '\0';
 
     for( i = 0; i < nCharCount; i++ )
@@ -94,9 +265,9 @@ class USGSDEMDataset : public GDALPamDataset
 
     const char  *pszUnits; 
 
-    int         LoadFromFile( FILE * );
+    int         LoadFromFile( VSILFILE * );
 
-    FILE	*fp;
+    VSILFILE	*fp;
 
   public:
                 USGSDEMDataset();
@@ -110,7 +281,7 @@ class USGSDEMDataset : public GDALPamDataset
 
 /************************************************************************/
 /* ==================================================================== */
-/*                            USGSDEMRasterBand                             */
+/*                            USGSDEMRasterBand                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -171,7 +342,7 @@ CPLErr USGSDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Seek to data.                                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeek(poGDS->fp, poGDS->nDataStartOffset, 0);
+    VSIFSeekL(poGDS->fp, poGDS->nDataStartOffset, 0);
 
     dfYMin = poGDS->adfGeoTransform[3] 
         + (GetYSize()-0.5) * poGDS->adfGeoTransform[5];
@@ -179,21 +350,29 @@ CPLErr USGSDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Read all the profiles into the image buffer.                    */
 /* -------------------------------------------------------------------- */
+
+    Buffer sBuffer;
+    sBuffer.max_size = 32768;
+    sBuffer.buffer = (char*) CPLMalloc(sBuffer.max_size + 1);
+    sBuffer.fp = poGDS->fp;
+    sBuffer.buffer_size = 0;
+    sBuffer.cur_index = 0;
+
     for( int i = 0; i < GetXSize(); i++)
     {
         int	njunk, nCPoints, lygap;
         double	djunk, dxStart, dyStart, dfElevOffset;
 
-        fscanf(poGDS->fp, "%d", &njunk);
-        fscanf(poGDS->fp, "%d", &njunk);
-        fscanf(poGDS->fp, "%d", &nCPoints);
-        fscanf(poGDS->fp, "%d", &njunk);
+        njunk = USGSDEMReadIntFromBuffer(&sBuffer);
+        njunk = USGSDEMReadIntFromBuffer(&sBuffer);
+        nCPoints = USGSDEMReadIntFromBuffer(&sBuffer);
+        njunk = USGSDEMReadIntFromBuffer(&sBuffer);
 
-        dxStart = DConvert(poGDS->fp, 24);
-        dyStart = DConvert(poGDS->fp, 24);
-        dfElevOffset = DConvert(poGDS->fp, 24);
-        djunk = DConvert(poGDS->fp, 24);
-        djunk = DConvert(poGDS->fp, 24);
+        dxStart = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
+        dyStart = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
+        dfElevOffset = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
+        djunk = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
+        djunk = USGSDEMReadDoubleFromBuffer(&sBuffer, 24);
 
         if( EQUALN(poGDS->pszProjection,"GEOGCS",6) )
             dyStart = dyStart / 3600.0;
@@ -205,7 +384,8 @@ CPLErr USGSDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             int		iY = GetYSize() - j - 1;
             int         nElev;
 
-            fscanf(poGDS->fp, "%d", &nElev);
+            nElev = USGSDEMReadIntFromBuffer(&sBuffer);
+            
             if (iY < 0 || iY >= GetYSize() )
                 bad = TRUE;
             else if( nElev == USGSDEM_NODATA )
@@ -227,6 +407,7 @@ CPLErr USGSDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             }
         }
     }
+    CPLFree(sBuffer.buffer);
 
     return CE_None;
 }
@@ -282,7 +463,7 @@ USGSDEMDataset::~USGSDEMDataset()
 
     CPLFree( pszProjection );
     if( fp != NULL )
-        VSIFClose( fp );
+        VSIFCloseL( fp );
 }
 
 /************************************************************************/
@@ -295,7 +476,7 @@ USGSDEMDataset::~USGSDEMDataset()
 /*      read.                                                           */
 /************************************************************************/
 
-int USGSDEMDataset::LoadFromFile(FILE *InDem)
+int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
 {
     int		i, j;
     int		nRow, nColumn;
@@ -311,22 +492,22 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
     int		iUTMZone;
 
     // check for version of DEM format
-    VSIFSeek(InDem, 864, 0);
+    VSIFSeekL(InDem, 864, 0);
 
     // Read DEM into matrix
-    fscanf(InDem, "%d", &nRow);
-    fscanf(InDem, "%d", &nColumn);
+    nRow = ReadInt(InDem);
+    nColumn = ReadInt(InDem);
     bNewFormat = ((nRow!=1)||(nColumn!=1));
     if (bNewFormat)
     {
-        VSIFSeek(InDem, 1024, 0); 	// New Format
-        fscanf(InDem, "%d", &i);
-        fscanf(InDem, "%d", &j);
+        VSIFSeekL(InDem, 1024, 0); 	// New Format
+        i = ReadInt(InDem);
+        j = ReadInt(InDem);
         if ((i!=1)||(j!=1 && j != 0))	// File OK?
         {
-            VSIFSeek(InDem, 893, 0); 	// Undocumented Format (39109h1.dem)
-            fscanf(InDem, "%d", &i);
-            fscanf(InDem, "%d", &j);
+            VSIFSeekL(InDem, 893, 0); 	// Undocumented Format (39109h1.dem)
+            i = ReadInt(InDem);
+            j = ReadInt(InDem);
             if ((i!=1)||(j!=1))			// File OK?
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -342,13 +523,13 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
     else
         nDataStartOffset = 864;
 
-    VSIFSeek(InDem, 156, 0);
-    fscanf(InDem, "%d", &nCoordSystem);
-    fscanf(InDem, "%d", &iUTMZone);
+    VSIFSeekL(InDem, 156, 0);
+    nCoordSystem = ReadInt(InDem);
+    iUTMZone = ReadInt(InDem);
 
-    VSIFSeek(InDem, 528, 0);
-    fscanf(InDem, "%d", &nGUnit);
-    fscanf(InDem, "%d", &nVUnit);
+    VSIFSeekL(InDem, 528, 0);
+    nGUnit = ReadInt(InDem);
+    nVUnit = ReadInt(InDem);
 
     // Vertical Units in meters
     if (nVUnit==1)
@@ -356,7 +537,7 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
     else
         pszUnits = "m";
 
-    VSIFSeek(InDem, 816, 0);
+    VSIFSeekL(InDem, 816, 0);
     dxdelta = DConvert(InDem, 12);
     dydelta = DConvert(InDem, 12);
     fVRes = DConvert(InDem, 12);
@@ -372,7 +553,7 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
 /* -------------------------------------------------------------------- */
 /*      Read four corner coordinates.                                   */
 /* -------------------------------------------------------------------- */
-    VSIFSeek(InDem, 546, 0);
+    VSIFSeekL(InDem, 546, 0);
     for (i = 0; i < 4; i++)
     {
         corners[i].x = DConvert(InDem, 24);
@@ -388,8 +569,8 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
     dElevMin = DConvert(InDem, 48);
     dElevMax = DConvert(InDem, 48);
 
-    VSIFSeek(InDem, 858, 0);
-    fscanf(InDem, "%d", &nProfiles);
+    VSIFSeekL(InDem, 858, 0);
+    nProfiles = ReadInt(InDem);
 
 /* -------------------------------------------------------------------- */
 /*      Collect the spatial reference system.                           */
@@ -403,8 +584,8 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
         char szHorzDatum[3];
 
         // year of data compilation
-        VSIFSeek(InDem, 876, 0);
-        fread(szDateBuffer, 4, 1, InDem);
+        VSIFSeekL(InDem, 876, 0);
+        VSIFReadL(szDateBuffer, 4, 1, InDem);
         szDateBuffer[4] = 0;
 
         // Horizontal datum
@@ -415,8 +596,8 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
         // 5=Old Hawaii Datum
         // 6=Puerto Rico Datum
         int datum;
-        VSIFSeek(InDem, 890, 0);
-        VSIFRead( szHorzDatum, 1, 2, InDem );
+        VSIFSeekL(InDem, 890, 0);
+        VSIFReadL( szHorzDatum, 1, 2, InDem );
         szHorzDatum[2] = '\0';
         datum = atoi(szHorzDatum);
         switch (datum)
@@ -484,11 +665,11 @@ int USGSDEMDataset::LoadFromFile(FILE *InDem)
         extent_max.y = ceil(extent_max.y/dydelta) * dydelta;
 
         // Forceably compute X extents based on first profile and pixelsize.
-        VSIFSeek(InDem, nDataStartOffset, 0);
-        fscanf(InDem, "%d", &njunk);
-        fscanf(InDem, "%d", &njunk);
-        fscanf(InDem, "%d", &njunk);
-        fscanf(InDem, "%d", &njunk);
+        VSIFSeekL(InDem, nDataStartOffset, 0);
+        njunk = ReadInt(InDem);
+        njunk = ReadInt(InDem);
+        njunk = ReadInt(InDem);
+        njunk = ReadInt(InDem);
         dxStart = DConvert(InDem, 24);
         
         nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
@@ -555,7 +736,7 @@ const char *USGSDEMDataset::GetProjectionRef()
 int USGSDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-    if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 200 )
+    if( poOpenInfo->nHeaderBytes < 200 )
         return FALSE;
 
     if( !EQUALN((const char *) poOpenInfo->pabyHeader+156, "     0",6)
@@ -582,6 +763,10 @@ GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !Identify( poOpenInfo ) )
         return NULL;
 
+    VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (fp == NULL)
+        return NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
@@ -589,8 +774,7 @@ GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS = new USGSDEMDataset();
 
-    poDS->fp = poOpenInfo->fp;
-    poOpenInfo->fp = NULL;
+    poDS->fp = fp;
     
 /* -------------------------------------------------------------------- */
 /*	Read the file.							*/
@@ -678,7 +862,9 @@ void GDALRegister_USGSDEM()
 "   <Option name='NTS' type='string' description='NTS Mapsheet name, used to derive TOPLEFT.'/>"
 "   <Option name='INTERNALNAME' type='string' description='Dataset name written into file header.'/>"
 "</CreationOptionList>" );
-        
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
         poDriver->pfnOpen = USGSDEMDataset::Open;
         poDriver->pfnCreateCopy = USGSDEMCreateCopy;
         poDriver->pfnIdentify = USGSDEMDataset::Identify;
diff --git a/frmts/vrt/vrt_tutorial.dox b/frmts/vrt/vrt_tutorial.dox
index f2ebb2c..36678f0 100755
--- a/frmts/vrt/vrt_tutorial.dox
+++ b/frmts/vrt/vrt_tutorial.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: vrt_tutorial.dox 20970 2010-10-26 16:03:14Z rouault $ */
+/* $Id: vrt_tutorial.dox 22897 2011-08-07 18:38:56Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -682,7 +682,7 @@ calling the pixel function, and the imaginary portion would be lost.
   <VRTRasterBand dataType="Float32" band="1" subClass="VRTDerivedRasterBand">
     <Description>Magnitude</Description>
     <PixelFunctionType>MyFirstFunction</PixelFunctionType>
-    <SourceTransferType>"CFloat64"</SourceTransferType>
+    <SourceTransferType>CFloat64</SourceTransferType>
     ...
 \endcode
 
diff --git a/frmts/vrt/vrtdataset.cpp b/frmts/vrt/vrtdataset.cpp
index 466a560..1f704da 100644
--- a/frmts/vrt/vrtdataset.cpp
+++ b/frmts/vrt/vrtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: vrtdataset.cpp 22809 2011-07-24 21:51:09Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDataset
@@ -32,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: vrtdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: vrtdataset.cpp 22809 2011-07-24 21:51:09Z rouault $");
 
 /************************************************************************/
 /*                            VRTDataset()                             */
@@ -66,6 +66,8 @@ VRTDataset::VRTDataset( int nXSize, int nYSize )
     
     GDALRegister_VRT();
     poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
+
+    bCompatibleForDatasetIO = -1;
 }
 
 /************************************************************************/
@@ -231,15 +233,26 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
         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( psGCPList, CXT_Element, "GCP" );
+            psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
+
+            if( psLastChild == NULL )
+                psGCPList->psChild = psXMLGCP;
+            else
+                psLastChild->psNext = psXMLGCP;
+            psLastChild = psXMLGCP;
 
             CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
 
@@ -919,10 +932,40 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
 
 	/* ---- Check for our sourced band 'derived' subclass ---- */
         if(pszSubClass != NULL && EQUAL(pszSubClass,"VRTDerivedRasterBand")) {
-	    poBand = new VRTDerivedRasterBand
-		(this, GetRasterCount() + 1, eType, 
-		 GetRasterXSize(), GetRasterYSize());
-	}
+
+            /* We'll need a pointer to the subclass in case we need */
+            /* to set the new band's pixel function below. */
+            VRTDerivedRasterBand* poDerivedBand;
+
+            poDerivedBand = new VRTDerivedRasterBand
+                (this, GetRasterCount() + 1, eType,
+                 GetRasterXSize(), GetRasterYSize());
+
+            /* Set the pixel function options it provided. */
+            const char* pszFuncName =
+                CSLFetchNameValue(papszOptions, "PixelFunctionType");
+            if (pszFuncName != NULL)
+                poDerivedBand->SetPixelFunctionName(pszFuncName);
+
+            const char* pszTransferTypeName =
+                CSLFetchNameValue(papszOptions, "SourceTransferType");
+            if (pszTransferTypeName != NULL) {
+                GDALDataType eTransferType =
+                    GDALGetDataTypeByName(pszTransferTypeName);
+                if (eTransferType == GDT_Unknown) {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "invalid SourceTransferType: \"%s\".",
+                              pszTransferTypeName);
+                    delete poDerivedBand;
+                    return CE_Failure;
+                }
+                poDerivedBand->SetSourceTransferType(eTransferType);
+            }
+
+            /* We're done with the derived band specific stuff, so */
+            /* we can assigned the base class pointer now. */
+            poBand = poDerivedBand;
+        }
 	else {
 
 	    /* ---- Standard sourced band ---- */
@@ -999,7 +1042,8 @@ VRTDataset::Create( const char * pszName,
     if( EQUALN(pszName,"<VRTDataset",11) )
     {
         GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update );
-        poDS->SetDescription( "<FromXML>" );
+        if (poDS)
+            poDS->SetDescription( "<FromXML>" );
         return poDS;
     }
     else
@@ -1075,7 +1119,8 @@ CPLErr VRTDataset::Delete( const char * pszFilename )
     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
     if (hDriver && EQUAL(GDALGetDriverShortName(hDriver), "VRT"))
     {
-        if( VSIUnlink( pszFilename ) != 0 )
+        if( strstr(pszFilename, "<VRTDataset") == NULL &&
+            VSIUnlink( pszFilename ) != 0 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Deleting %s failed:\n%s",
@@ -1118,3 +1163,150 @@ void VRTDataset::SetMaskBand(VRTRasterBand* poMaskBand)
     this->poMaskBand = poMaskBand;
     poMaskBand->SetIsMaskBand();
 }
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int VRTDataset::CloseDependentDatasets()
+{
+    /* We need to call it before removing the sources, otherwise */
+    /* we would remove them from the serizalized VRT */
+    FlushCache();
+
+    int bHasDroppedRef = GDALDataset::CloseDependentDatasets();
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       bHasDroppedRef |= ((VRTRasterBand *) papoBands[iBand])->
+                                                CloseDependentDatasets();
+    }
+    return bHasDroppedRef;
+}
+
+/************************************************************************/
+/*                      CheckCompatibleForDatasetIO()                   */
+/************************************************************************/
+
+/* We will return TRUE only if all the bands are VRTSourcedRasterBands */
+/* made of identical sources, that are strictly VRTSimpleSource, and that */
+/* the band number of each source is the band number of the VRTSouredRasterBand */
+
+int VRTDataset::CheckCompatibleForDatasetIO()
+{
+    int iBand;
+    int nSources = 0;
+    VRTSource    **papoSources = NULL;
+    for(iBand = 0; iBand < nBands; iBand++)
+    {
+        if (!((VRTRasterBand *) papoBands[iBand])->IsSourcedRasterBand())
+            return FALSE;
+
+        VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[iBand];
+
+        /* If there are overviews, let's VRTSourcedRasterBand::IRasterIO() */
+        /* do the job */
+        if (poBand->GetOverviewCount() != 0)
+            return FALSE;
+
+        if (iBand == 0)
+        {
+            nSources = poBand->nSources;
+            papoSources = poBand->papoSources;
+            for(int iSource = 0; iSource < nSources; iSource++)
+            {
+                if (!papoSources[iSource]->IsSimpleSource())
+                    return FALSE;
+
+                VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
+                if (!EQUAL(poSource->GetType(), "SimpleSource"))
+                    return FALSE;
+                if (poSource->GetBand() == NULL)
+                    return FALSE;
+                if (poSource->GetBand()->GetBand() != iBand + 1)
+                    return FALSE;
+            }
+        }
+        else if (nSources != poBand->nSources)
+        {
+            return FALSE;
+        }
+        else
+        {
+            for(int iSource = 0; iSource < nSources; iSource++)
+            {
+                VRTSimpleSource* poRefSource = (VRTSimpleSource* )papoSources[iSource];
+                VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
+                if (!EQUAL(poSource->GetType(), "SimpleSource"))
+                    return FALSE;
+                if (!poSource->IsSameExceptBandNumber(poRefSource))
+                    return FALSE;
+                if (poSource->GetBand() == NULL)
+                    return FALSE;
+                if (poSource->GetBand()->GetBand() != iBand + 1)
+                    return FALSE;
+            }
+        }
+    }
+
+    return nSources != 0;
+}
+
+/************************************************************************/
+/*                              IRasterIO()                             */
+/************************************************************************/
+
+CPLErr VRTDataset::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 (bCompatibleForDatasetIO < 0)
+    {
+        bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
+    }
+    if (bCompatibleForDatasetIO && eRWFlag == GF_Read && nBandCount > 1)
+    {
+        for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
+        {
+            VRTSourcedRasterBand* poBand =
+                    (VRTSourcedRasterBand*)GetRasterBand(panBandMap[iBandIndex]);
+
+            /* Dirty little trick to initialize the buffer without doing */
+            /* any real I/O */
+            int nSavedSources = poBand->nSources;
+            poBand->nSources = 0;
+
+            GByte *pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
+            poBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
+                                pabyBandData, nBufXSize, nBufYSize,
+                                eBufType,
+                                nPixelSpace, nLineSpace);
+
+            poBand->nSources = nSavedSources;
+        }
+
+        CPLErr eErr = CE_None;
+        /* Use the last band, because when sources reference a GDALProxyDataset, they */
+        /* don't necessary instanciate all underlying rasterbands */
+        VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[nBands - 1];
+        for(int iSource = 0; eErr == CE_None && iSource < poBand->nSources; iSource++)
+        {
+            VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
+            eErr = poSource->DatasetRasterIO( nXOff, nYOff, nXSize, nYSize,
+                                              pData, nBufXSize, nBufYSize,
+                                              eBufType,
+                                              nBandCount, panBandMap,
+                                              nPixelSpace, nLineSpace, nBandSpace);
+        }
+        return eErr;
+    }
+
+    return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                  pData, nBufXSize, nBufYSize,
+                                  eBufType,
+                                  nBandCount, panBandMap,
+                                  nPixelSpace, nLineSpace, nBandSpace);
+}
diff --git a/frmts/vrt/vrtdataset.h b/frmts/vrt/vrtdataset.h
index 66ed0e6..0ce5ce7 100644
--- a/frmts/vrt/vrtdataset.h
+++ b/frmts/vrt/vrtdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.h 21290 2010-12-19 10:41:00Z rouault $
+ * $Id: vrtdataset.h 23574 2011-12-14 19:29:48Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Declaration of virtual gdal dataset classes.
@@ -81,11 +81,16 @@ public:
                               GDALDataType eBufType, 
                               int nPixelSpace, int nLineSpace ) = 0;
 
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess ) = 0;
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess ) = 0;
+
     virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * ) = 0;
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) = 0;
     
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
+
+    virtual int    IsSimpleSource() { return FALSE; }
 };
 
 typedef VRTSource *(*VRTSourceParser)(CPLXMLNode *, const char *);
@@ -119,6 +124,12 @@ class CPL_DLL VRTDataset : public GDALDataset
 
     VRTRasterBand *poMaskBand;
 
+    int            bCompatibleForDatasetIO;
+    int            CheckCompatibleForDatasetIO();
+
+  protected:
+    virtual int         CloseDependentDatasets();
+
   public:
                  VRTDataset(int nXSize, int nYSize);
                 ~VRTDataset();
@@ -151,6 +162,13 @@ class CPL_DLL VRTDataset : public GDALDataset
                             
     virtual char      **GetFileList();
 
+    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 CPLXMLNode *SerializeToXML( const char *pszVRTPath);
     virtual CPLErr      XMLInit( CPLXMLNode *, const char * );
  
@@ -178,6 +196,9 @@ class CPL_DLL VRTWarpedDataset : public VRTDataset
 
     friend class VRTWarpedRasterBand;
 
+  protected:
+    virtual int         CloseDependentDatasets();
+
 public:
     int               nOverviewCount;
     VRTWarpedDataset  **papoOverviews;
@@ -303,6 +324,10 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
     void SetIsMaskBand();
 
     CPLErr UnsetNoDataValue();
+
+    virtual int         CloseDependentDatasets();
+
+    virtual int         IsSourcedRasterBand() { return FALSE; }
 };
 
 /************************************************************************/
@@ -312,7 +337,7 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
 class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
 {
   private:
-    int            bAlreadyInIRasterIO;
+    int            bAntiRecursionFlag;
     CPLString      osLastLocationInfo;
 
     void           Initialize( int nXSize, int nYSize );
@@ -346,6 +371,9 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
     virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
 
+    virtual double GetMinimum( int *pbSuccess = NULL );
+    virtual double GetMaximum(int *pbSuccess = NULL );
+
     CPLErr         AddSource( VRTSource * );
     CPLErr         AddSimpleSource( GDALRasterBand *poSrcBand, 
                                     int nSrcXOff=-1, int nSrcYOff=-1, 
@@ -378,6 +406,10 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
+
+    virtual int         CloseDependentDatasets();
+
+    virtual int         IsSourcedRasterBand() { return TRUE; }
 };
 
 /************************************************************************/
@@ -545,6 +577,9 @@ public:
                               GDALDataType eBufType, 
                               int nPixelSpace, int nLineSpace );
 
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
+
     void            DstToSrc( double dfX, double dfY,
                               double &dfXOut, double &dfYOut );
     void            SrcToDst( double dfX, double dfY,
@@ -552,6 +587,18 @@ public:
     
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
+
+    virtual int    IsSimpleSource() { return TRUE; }
+    virtual const char* GetType() { return "SimpleSource"; }
+
+    GDALRasterBand* GetBand();
+    int             IsSameExceptBandNumber(VRTSimpleSource* poOtherSource);
+    CPLErr          DatasetRasterIO(
+                               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);
 };
 
 /************************************************************************/
@@ -566,7 +613,12 @@ public:
                               void *pData, int nBufXSize, int nBufYSize, 
                               GDALDataType eBufType, 
                               int nPixelSpace, int nLineSpace );
+
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
+
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
+    virtual const char* GetType() { return "AveragedSource"; }
 };
 
 /************************************************************************/
@@ -583,8 +635,14 @@ public:
                              void *pData, int nBufXSize, int nBufYSize, 
                              GDALDataType eBufType, 
                              int nPixelSpace, int nLineSpace );
+
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
+
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
     virtual CPLErr XMLInit( CPLXMLNode *, const char * );
+    virtual const char* GetType() { return "ComplexSource"; }
+
     double  LookupValue( double dfInput );
 
     int            bDoScaling;
@@ -685,6 +743,9 @@ public:
                               GDALDataType eBufType, 
                               int nPixelSpace, int nLineSpace );
 
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
+
     VRTImageReadFunc    pfnReadFunc;
     void               *pCBData;
     GDALDataType        eType;
diff --git a/frmts/vrt/vrtderivedrasterband.cpp b/frmts/vrt/vrtderivedrasterband.cpp
index 500906c..73f6905 100644
--- a/frmts/vrt/vrtderivedrasterband.cpp
+++ b/frmts/vrt/vrtderivedrasterband.cpp
@@ -30,6 +30,9 @@
 #include "vrtdataset.h"
 #include "cpl_minixml.h"
 #include "cpl_string.h"
+#include <map>
+
+static std::map<CPLString, GDALDerivedPixelFunc> osMapPixelFunction;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -37,10 +40,6 @@
 /* ==================================================================== */
 /************************************************************************/
 
-static int nFunctions = 0;
-static GDALDerivedPixelFunc *papfnPixelFunctions = NULL;
-static char **papszNames = NULL;
-
 /************************************************************************/
 /*                        VRTDerivedRasterBand()                        */
 /************************************************************************/
@@ -103,31 +102,14 @@ VRTDerivedRasterBand::~VRTDerivedRasterBand()
 CPLErr CPL_STDCALL GDALAddDerivedBandPixelFunc
 (const char *pszFuncName, GDALDerivedPixelFunc pfnNewFunction)
 {
-    int ii;
-
     /* ---- Init ---- */
-    if ((pszFuncName == NULL) || (pfnNewFunction == NULL)) {
-	return CE_None;
-    }
-
-    /* ---- Check for match with fn already on list, and replace ---- */
-    for (ii = 0; ii < nFunctions; ii++) {
-	if (strcmp(pszFuncName, papszNames[ii]) == 0) {
-	    papfnPixelFunctions[ii] = pfnNewFunction;
-	    return CE_None;
-	}
+    if ((pszFuncName == NULL) || (pszFuncName[0] == '\0') ||
+        (pfnNewFunction == NULL))
+    {
+      return CE_None;
     }
 
-    /* ---- Increment pixel function counter and add name/fn to lists ---- */
-    nFunctions++;
-
-    papfnPixelFunctions = (GDALDerivedPixelFunc *) 
-        CPLRealloc(papfnPixelFunctions, sizeof(void*) * nFunctions);
-    papfnPixelFunctions[nFunctions - 1] = pfnNewFunction;
-
-    papszNames = (char **)
-	CPLRealloc(papszNames, sizeof(void*) * nFunctions);
-    papszNames[nFunctions - 1] = (char *)pszFuncName;
+    osMapPixelFunction[pszFuncName] = pfnNewFunction;
 
     return CE_None;
 }
@@ -166,19 +148,19 @@ CPLErr VRTDerivedRasterBand::AddPixelFunction
 GDALDerivedPixelFunc VRTDerivedRasterBand::GetPixelFunction
 (const char *pszFuncName)
 {
-    int ii;
-
     /* ---- Init ---- */
-    if ((pszFuncName == NULL) || (pszFuncName[0] == '\0')) return NULL;
-
-    /* ---- Check for match with fn added with AddPixelFunction ---- */
-    for (ii = 0; ii < nFunctions; ii++) {
-	if (strcmp(pszFuncName, papszNames[ii]) == 0) {
-	    return papfnPixelFunctions[ii];
-	}
+    if ((pszFuncName == NULL) || (pszFuncName[0] == '\0'))
+    {
+        return NULL;
     }
 
-    return NULL;
+    std::map<CPLString, GDALDerivedPixelFunc>::iterator oIter =
+        osMapPixelFunction.find(pszFuncName);
+
+    if( oIter == osMapPixelFunction.end())
+        return NULL;
+
+    return oIter->second;
 }
 
 /************************************************************************/
@@ -359,17 +341,19 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
     pBuffers = (void **) CPLMalloc(sizeof(void *) * nSources);
     for (iSource = 0; iSource < nSources; iSource++) {
         pBuffers[iSource] = (void *) 
-	    malloc(sourcesize * nBufXSize * nBufYSize);
-        if (pBuffers[iSource] == NULL) {
+            VSIMalloc(sourcesize * nBufXSize * nBufYSize);
+        if (pBuffers[iSource] == NULL)
+        {
             for (ii = 0; ii < iSource; ii++) {
-                free(pBuffers[iSource]);
-	    }
-	    CPLError( CE_Failure, CPLE_OutOfMemory, 
-		      "VRTDerivedRasterBand::IRasterIO:" \
-		      "Out of memory allocating %d bytes.\n",
-		      nPixelSpace * nBufXSize * nBufYSize);
-	    return CE_Failure;
-	}
+                VSIFree(pBuffers[iSource]);
+            }
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                "VRTDerivedRasterBand::IRasterIO:" \
+                "Out of memory allocating %d bytes.\n",
+                nPixelSpace * nBufXSize * nBufYSize);
+            return CE_Failure;
+        }
+
         /* ------------------------------------------------------------ */
         /* #4045: Initialize the newly allocated buffers before handing */
         /* them off to the sources. These buffers are packed, so we     */
@@ -406,7 +390,7 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
 
     /* ---- Release buffers ---- */
     for (iSource = 0; iSource < nSources; iSource++) {
-        free(pBuffers[iSource]);
+        VSIFree(pBuffers[iSource]);
     }
     CPLFree(pBuffers);
 
diff --git a/frmts/vrt/vrtdriver.cpp b/frmts/vrt/vrtdriver.cpp
index edb4997..51c3197 100644
--- a/frmts/vrt/vrtdriver.cpp
+++ b/frmts/vrt/vrtdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdriver.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: vrtdriver.cpp 21945 2011-03-12 21:11:37Z warmerdam $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDriver
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "gdal_alg_priv.h"
 
-CPL_CVSID("$Id: vrtdriver.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: vrtdriver.cpp 21945 2011-03-12 21:11:37Z warmerdam $");
 
 /************************************************************************/
 /*                             VRTDriver()                              */
@@ -159,7 +159,8 @@ VRTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      it to disk as a special case to avoid extra layers of           */
 /*      indirection.                                                    */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poSrcDS->GetDriver()->GetDescription(),"VRT") )
+    if( poSrcDS->GetDriver() != NULL &&
+        EQUAL(poSrcDS->GetDriver()->GetDescription(),"VRT") )
     {
 
     /* -------------------------------------------------------------------- */
@@ -217,6 +218,8 @@ VRTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                             poSrcDS->GetRasterXSize(),
                             poSrcDS->GetRasterYSize(),
                             0, GDT_Byte, NULL );
+    if (poVRTDS == NULL)
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a geotransform?                                      */
@@ -251,6 +254,10 @@ VRTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( papszMD )
         poVRTDS->SetMetadata( papszMD, "IMD" );
 
+    papszMD = poSrcDS->GetMetadata( "GEOLOCATION" );
+    if( papszMD )
+        poVRTDS->SetMetadata( papszMD, "GEOLOCATION" );
+
 /* -------------------------------------------------------------------- */
 /*      GCPs                                                            */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/vrt/vrtrasterband.cpp b/frmts/vrt/vrtrasterband.cpp
index af14fbf..1897e61 100644
--- a/frmts/vrt/vrtrasterband.cpp
+++ b/frmts/vrt/vrtrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtrasterband.cpp 21714 2011-02-13 18:37:57Z rouault $
+ * $Id: vrtrasterband.cpp 22761 2011-07-21 18:53:58Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRasterBand
@@ -31,7 +31,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtrasterband.cpp 21714 2011-02-13 18:37:57Z rouault $");
+CPL_CVSID("$Id: vrtrasterband.cpp 22761 2011-07-21 18:53:58Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -350,6 +350,8 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
         CSLDestroy( papszCategoryNames );
         papszCategoryNames = NULL;
 
+        CPLStringList oCategoryNames;
+
         for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
              psEntry != NULL; psEntry = psEntry->psNext )
         {
@@ -358,9 +360,11 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
                 || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
                 continue;
             
-            papszCategoryNames = CSLAddString( papszCategoryNames, 
+            oCategoryNames.AddString(
                                 (psEntry->psChild) ? psEntry->psChild->pszValue : "");
         }
+
+        papszCategoryNames = oCategoryNames.StealList();
     }
 
 /* -------------------------------------------------------------------- */
@@ -574,11 +578,17 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
     {
         CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
                                                  "CategoryNames" );
+        CPLXMLNode* psLastChild = NULL;
 
         for( int iEntry=0; papszCategoryNames[iEntry] != NULL; iEntry++ )
         {
-            CPLCreateXMLElementAndValue( psCT_XML, "Category", 
+            CPLXMLNode *psNode = CPLCreateXMLElementAndValue( NULL, "Category",
                                          papszCategoryNames[iEntry] );
+            if( psLastChild == NULL )
+                psCT_XML->psChild = psNode;
+            else
+                psLastChild->psNext = psNode;
+            psLastChild = psNode;
         }
     }
 
@@ -1117,3 +1127,12 @@ void VRTRasterBand::SetIsMaskBand()
     nBand = 0;
     bIsMaskBand = TRUE;
 }
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int VRTRasterBand::CloseDependentDatasets()
+{
+    return FALSE;
+}
diff --git a/frmts/vrt/vrtrawrasterband.cpp b/frmts/vrt/vrtrawrasterband.cpp
index 2ac91b4..f08e38e 100644
--- a/frmts/vrt/vrtrawrasterband.cpp
+++ b/frmts/vrt/vrtrawrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtrawrasterband.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: vrtrawrasterband.cpp 22776 2011-07-23 18:07:58Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRawRasterBand
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: vrtrawrasterband.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: vrtrawrasterband.cpp 22776 2011-07-23 18:07:58Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -200,6 +200,11 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
     if( fp == NULL )
         fp = CPLOpenShared( pszExpandedFilename, "rb", TRUE );
 
+    if( fp == NULL && ((VRTDataset *)poDS)->GetAccess() == GA_Update )
+    {
+        fp = CPLOpenShared( pszExpandedFilename, "wb+", TRUE );
+    }
+
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
diff --git a/frmts/vrt/vrtsourcedrasterband.cpp b/frmts/vrt/vrtsourcedrasterband.cpp
index b08709f..f1ea8e3 100644
--- a/frmts/vrt/vrtsourcedrasterband.cpp
+++ b/frmts/vrt/vrtsourcedrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsourcedrasterband.cpp 21179 2010-11-28 16:18:00Z rouault $
+ * $Id: vrtsourcedrasterband.cpp 23574 2011-12-14 19:29:48Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSourcedRasterBand
@@ -31,7 +31,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtsourcedrasterband.cpp 21179 2010-11-28 16:18:00Z rouault $");
+CPL_CVSID("$Id: vrtsourcedrasterband.cpp 23574 2011-12-14 19:29:48Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -94,7 +94,7 @@ void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
     nSources = 0;
     papoSources = NULL;
     bEqualAreas = FALSE;
-    bAlreadyInIRasterIO = FALSE;
+    bAntiRecursionFlag = FALSE;
 }
 
 /************************************************************************/
@@ -104,11 +104,7 @@ void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
 VRTSourcedRasterBand::~VRTSourcedRasterBand()
 
 {
-    for( int i = 0; i < nSources; i++ )
-        delete papoSources[i];
-
-    CPLFree( papoSources );
-    nSources = 0;
+    CloseDependentDatasets();
 }
 
 /************************************************************************/
@@ -135,7 +131,7 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     /* When using GDALProxyPoolDataset for sources, the recusion will not be */
     /* detected at VRT opening but when doing RasterIO. As the proxy pool will */
     /* return the already opened dataset, we can just test a member variable. */
-    if ( bAlreadyInIRasterIO )
+    if ( bAntiRecursionFlag )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "VRTSourcedRasterBand::IRasterIO() called recursively on the same band. "
@@ -161,7 +157,7 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*      nodata value if available.                                      */
 /* -------------------------------------------------------------------- */
     if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
-         (!bNoDataValueSet || dfNoDataValue == 0) )
+         (!bNoDataValueSet || (!CPLIsNan(dfNoDataValue) && dfNoDataValue == 0)) )
     {
         if (nLineSpace == nBufXSize * nPixelSpace)
         {
@@ -206,7 +202,7 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             return CE_None;
     }
     
-    bAlreadyInIRasterIO = TRUE;
+    bAntiRecursionFlag = TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      Overlay each source in turn over top this.                      */
@@ -219,7 +215,7 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                             eBufType, nPixelSpace, nLineSpace);
     }
     
-    bAlreadyInIRasterIO = FALSE;
+    bAntiRecursionFlag = FALSE;
     
     return eErr;
 }
@@ -253,6 +249,109 @@ CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 }
 
 /************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
+{
+    const char *pszValue = NULL;
+
+    if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
+    {
+        if( pbSuccess != NULL )
+            *pbSuccess = TRUE;
+
+        return CPLAtofM(pszValue);
+    }
+
+    if ( bAntiRecursionFlag )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "VRTSourcedRasterBand::GetMinimum() called recursively on the same band. "
+                  "It looks like the VRT is referencing itself." );
+        if( pbSuccess != NULL )
+            *pbSuccess = FALSE;
+        return 0.0;
+    }
+    bAntiRecursionFlag = TRUE;
+
+    double dfMin = 0;
+    for( int iSource = 0; iSource < nSources; iSource++ )
+    {
+        int bSuccess = FALSE;
+        double dfSourceMin = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(), &bSuccess);
+        if (!bSuccess)
+        {
+            dfMin = GDALRasterBand::GetMinimum(pbSuccess);
+            bAntiRecursionFlag = FALSE;
+            return dfMin;
+        }
+
+        if (iSource == 0 || dfSourceMin < dfMin)
+            dfMin = dfSourceMin;
+    }
+
+    bAntiRecursionFlag = FALSE;
+
+    if( pbSuccess != NULL )
+        *pbSuccess = TRUE;
+
+    return dfMin;
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
+{
+    const char *pszValue = NULL;
+
+    if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
+    {
+        if( pbSuccess != NULL )
+            *pbSuccess = TRUE;
+
+        return CPLAtofM(pszValue);
+    }
+
+    if ( bAntiRecursionFlag )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "VRTSourcedRasterBand::GetMaximum() called recursively on the same band. "
+                  "It looks like the VRT is referencing itself." );
+        if( pbSuccess != NULL )
+            *pbSuccess = FALSE;
+        return 0.0;
+    }
+    bAntiRecursionFlag = TRUE;
+
+    double dfMax = 0;
+    for( int iSource = 0; iSource < nSources; iSource++ )
+    {
+        int bSuccess = FALSE;
+        double dfSourceMax = papoSources[iSource]->GetMaximum(GetXSize(), GetYSize(), &bSuccess);
+        if (!bSuccess)
+        {
+            dfMax = GDALRasterBand::GetMaximum(pbSuccess);
+            bAntiRecursionFlag = FALSE;
+            return dfMax;
+        }
+
+        if (iSource == 0 || dfSourceMax > dfMax)
+            dfMax = dfSourceMax;
+    }
+
+    bAntiRecursionFlag = FALSE;
+
+    if( pbSuccess != NULL )
+        *pbSuccess = TRUE;
+
+    return dfMax;
+}
+
+
+/************************************************************************/
 /*                             AddSource()                              */
 /************************************************************************/
 
@@ -753,6 +852,10 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
         {
             int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
             int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+
+            if (!papoSources[iSource]->IsSimpleSource())
+                continue;
+
             VRTSimpleSource *poSrc = (VRTSimpleSource *) papoSources[iSource];
 
             if( !poSrc->GetSrcDstWindow( iPixel, iLine, 1, 1, 1, 1,
@@ -978,3 +1081,22 @@ void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
     VRTRasterBand::GetFileList( ppapszFileList, pnSize,
                                 pnMaxSize, hSetFiles);
 }
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int VRTSourcedRasterBand::CloseDependentDatasets()
+{
+    if (nSources == 0)
+        return FALSE;
+
+    for( int i = 0; i < nSources; i++ )
+        delete papoSources[i];
+
+    CPLFree( papoSources );
+    papoSources = NULL;
+    nSources = 0;
+
+    return TRUE;
+}
diff --git a/frmts/vrt/vrtsources.cpp b/frmts/vrt/vrtsources.cpp
index 052670e..ec26aa7 100644
--- a/frmts/vrt/vrtsources.cpp
+++ b/frmts/vrt/vrtsources.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsources.cpp 21809 2011-02-23 21:01:09Z rouault $
+ * $Id: vrtsources.cpp 23465 2011-12-04 15:54:52Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and 
@@ -35,7 +35,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: vrtsources.cpp 21809 2011-02-23 21:01:09Z rouault $");
+CPL_CVSID("$Id: vrtsources.cpp 23465 2011-12-04 15:54:52Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -72,6 +72,7 @@ VRTSimpleSource::VRTSimpleSource()
     poRasterBand = NULL;
     poMaskBandMainBand = NULL;
     bNoDataSet = FALSE;
+    dfNoDataValue = VRT_NODATA_UNSET;
 }
 
 /************************************************************************/
@@ -203,12 +204,20 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
 
     VSIStatBufL sStat;
+    if ( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
+         strstr(poDS->GetDescription(), "/vsicurl/ftp") != NULL )
+    {
+        /* Testing the existence of remote ressources can be excruciating */
+        /* slow, so let's just suppose they exist */
+        pszRelativePath = poDS->GetDescription();
+        bRelativeToVRT = FALSE;
+    }
     /* If this isn't actually a file, don't even try to know if it is */
     /* a relative path. It can't be !, and unfortunately */
     /* CPLIsFilenameRelative() can only work with strings that are filenames */
     /* To be clear NITF_TOC_ENTRY:CADRG_JOG-A_250K_1_0:some_path isn't a relative */
     /* file path */
-    if( VSIStatExL( poDS->GetDescription(), &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
+    else if( VSIStatExL( poDS->GetDescription(), &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
     {
         pszRelativePath = poDS->GetDescription();
         bRelativeToVRT = FALSE;
@@ -322,7 +331,7 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     }
     else
         nSrcBand = atoi(pszSourceBand);
-    if (nSrcBand <= 0)
+    if (!GDALCheckBandCount(nSrcBand, 0))
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Invalid <SourceBand> element in VRTRasterBand." );
@@ -457,9 +466,18 @@ void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
 /* -------------------------------------------------------------------- */
 /*      Is the filename even a real filesystem object?                  */
 /* -------------------------------------------------------------------- */
-        VSIStatBufL  sStat;
-        if( VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
-            return;
+        if ( strstr(pszFilename, "/vsicurl/http") != NULL ||
+             strstr(pszFilename, "/vsicurl/ftp") != NULL )
+        {
+            /* Testing the existence of remote ressources can be excruciating */
+            /* slow, so let's just suppose they exist */
+        }
+        else
+        {
+            VSIStatBufL  sStat;
+            if( VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
+                return;
+        }
             
 /* -------------------------------------------------------------------- */
 /*      Is it already in the list ?                                     */
@@ -489,6 +507,38 @@ void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
 }
 
 /************************************************************************/
+/*                             GetBand()                                */
+/************************************************************************/
+
+GDALRasterBand* VRTSimpleSource::GetBand()
+{
+    return poMaskBandMainBand ? NULL : poRasterBand;
+}
+
+/************************************************************************/
+/*                       IsSameExceptBandNumber()                       */
+/************************************************************************/
+
+int VRTSimpleSource::IsSameExceptBandNumber(VRTSimpleSource* poOtherSource)
+{
+    return nSrcXOff == poOtherSource->nSrcXOff &&
+           nSrcYOff == poOtherSource->nSrcYOff &&
+           nSrcXSize == poOtherSource->nSrcXSize &&
+           nSrcYSize == poOtherSource->nSrcYSize &&
+           nDstXOff == poOtherSource->nDstXOff &&
+           nDstYOff == poOtherSource->nDstYOff &&
+           nDstXSize == poOtherSource->nDstXSize &&
+           nDstYSize == poOtherSource->nDstYSize &&
+           bNoDataSet == poOtherSource->bNoDataSet &&
+           dfNoDataValue == poOtherSource->dfNoDataValue &&
+           GetBand() != NULL && poOtherSource->GetBand() != NULL &&
+           GetBand()->GetDataset() != NULL &&
+           poOtherSource->GetBand()->GetDataset() != NULL &&
+           EQUAL(GetBand()->GetDataset()->GetDescription(),
+                 poOtherSource->GetBand()->GetDataset()->GetDescription());
+}
+
+/************************************************************************/
 /*                              SrcToDst()                              */
 /*                                                                      */
 /*      Note: this is a no-op if the dst window is -1,-1,-1,-1.         */
@@ -757,6 +807,107 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 }
 
 /************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double VRTSimpleSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
+{
+    // The window we will actually request from the source raster band.
+    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+
+    // The window we will actual set _within_ the pData buffer.
+    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+
+    if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
+                          nXSize, nYSize,
+                          &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
+                          &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
+        nReqXOff != 0 || nReqYOff != 0 ||
+        nReqXSize != poRasterBand->GetXSize() ||
+        nReqYSize != poRasterBand->GetYSize())
+    {
+        *pbSuccess = FALSE;
+        return 0;
+    }
+
+    return poRasterBand->GetMinimum(pbSuccess);
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double VRTSimpleSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
+{
+    // The window we will actually request from the source raster band.
+    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+
+    // The window we will actual set _within_ the pData buffer.
+    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+
+    if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
+                          nXSize, nYSize,
+                          &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
+                          &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
+        nReqXOff != 0 || nReqYOff != 0 ||
+        nReqXSize != poRasterBand->GetXSize() ||
+        nReqYSize != poRasterBand->GetYSize())
+    {
+        *pbSuccess = FALSE;
+        return 0;
+    }
+
+    return poRasterBand->GetMaximum(pbSuccess);
+}
+
+
+/************************************************************************/
+/*                          DatasetRasterIO()                           */
+/************************************************************************/
+
+CPLErr VRTSimpleSource::DatasetRasterIO(
+                               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 (!EQUAL(GetType(), "SimpleSource"))
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "DatasetRasterIO() not implemented for %s", GetType());
+        return CE_Failure;
+    }
+
+    // The window we will actually request from the source raster band.
+    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+
+    // The window we will actual set _within_ the pData buffer.
+    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+
+    if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
+                          nBufXSize, nBufYSize,
+                          &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
+                          &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
+    {
+        return CE_None;
+    }
+
+    GDALDataset* poDS = poRasterBand->GetDataset();
+    if (poDS == NULL)
+        return CE_Failure;
+
+    return poDS->RasterIO( GF_Read,
+                           nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+                           ((unsigned char *) pData)
+                           + nOutXOff * nPixelSpace
+                           + nOutYOff * nLineSpace,
+                           nOutXSize, nOutYSize,
+                           eBufType, nBandCount, panBandMap,
+                           nPixelSpace, nLineSpace, nBandSpace );
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*                         VRTAveragedSource                            */
 /* ==================================================================== */
@@ -912,7 +1063,7 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                     if (CPLIsNan(fSampledValue))
                         continue;
 
-                    if( bNoDataSet && EQUAL_TO_NODATA(fSampledValue, dfNoDataValue))
+                    if( bNoDataSet && ARE_REAL_EQUAL(fSampledValue, dfNoDataValue))
                         continue;
 
                     nPixelCount++;
@@ -947,6 +1098,26 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 }
 
 /************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double VRTAveragedSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
+{
+    *pbSuccess = FALSE;
+    return 0;
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double VRTAveragedSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
+{
+    *pbSuccess = FALSE;
+    return 0;
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*                          VRTComplexSource                            */
 /* ==================================================================== */
@@ -1191,6 +1362,7 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     int bIsComplex = GDALDataTypeIsComplex(eBufType);
     GDALDataType eWrkDataType = (bIsComplex) ? GDT_CFloat32 : GDT_Float32;
     int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
+    int bNoDataSetAndNotNan = bNoDataSet && !CPLIsNan(dfNoDataValue);
 
     if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
     {
@@ -1252,7 +1424,7 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                 float fResult = pafData[iX + iY * nOutXSize];
                 if( CPLIsNan(dfNoDataValue) && CPLIsNan(fResult) )
                     continue;
-                if( bNoDataSet && EQUAL_TO_NODATA(fResult, dfNoDataValue) )
+                if( bNoDataSetAndNotNan && ARE_REAL_EQUAL(fResult, dfNoDataValue) )
                     continue;
 
                 if (nColorTableComponent)
@@ -1339,6 +1511,38 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 }
 
 /************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
+{
+    if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
+        nLUTItemCount == 0 && nColorTableComponent == 0)
+    {
+        return VRTSimpleSource::GetMinimum(nXSize, nYSize, pbSuccess);
+    }
+
+    *pbSuccess = FALSE;
+    return 0;
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
+{
+    if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
+        nLUTItemCount == 0 && nColorTableComponent == 0)
+    {
+        return VRTSimpleSource::GetMaximum(nXSize, nYSize, pbSuccess);
+    }
+
+    *pbSuccess = FALSE;
+    return 0;
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*                          VRTFuncSource                               */
 /* ==================================================================== */
@@ -1411,6 +1615,26 @@ VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 }
 
 /************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double VRTFuncSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
+{
+    *pbSuccess = FALSE;
+    return 0;
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double VRTFuncSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
+{
+    *pbSuccess = FALSE;
+    return 0;
+}
+
+/************************************************************************/
 /*                        VRTParseCoreSources()                         */
 /************************************************************************/
 
diff --git a/frmts/vrt/vrtwarped.cpp b/frmts/vrt/vrtwarped.cpp
index 1155f87..a81cc4f 100644
--- a/frmts/vrt/vrtwarped.cpp
+++ b/frmts/vrt/vrtwarped.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtwarped.cpp 22647 2011-07-05 17:18:18Z rouault $
+ * $Id: vrtwarped.cpp 23545 2011-12-12 00:50:37Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTWarpedRasterBand *and VRTWarpedDataset.
@@ -34,7 +34,7 @@
 #include "gdal_alg_priv.h"
 #include <cassert>
 
-CPL_CVSID("$Id: vrtwarped.cpp 22647 2011-07-05 17:18:18Z rouault $");
+CPL_CVSID("$Id: vrtwarped.cpp 23545 2011-12-12 00:50:37Z rouault $");
 
 /************************************************************************/
 /*                      GDALAutoCreateWarpedVRT()                       */
@@ -76,7 +76,7 @@ CPL_CVSID("$Id: vrtwarped.cpp 22647 2011-07-05 17:18:18Z rouault $");
  * @param dfMaxError Maximum error measured in input pixels that is allowed in 
  * approximating the transformation (0.0 for exact calculations).
  *
- * @param psOptions Additional warp options, normally NULL.
+ * @param psOptionsIn Additional warp options, normally NULL.
  *
  * @return NULL on failure, or a new virtual dataset handle on success.
  */
@@ -164,6 +164,7 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
                                          psWO->pTransformerArg, 
                                          dfMaxError );
         psWO->pfnTransformer = GDALApproxTransform;
+        GDALApproxTransformerOwnsSubtransformer(psWO->pTransformerArg, TRUE);
     }
 
 /* -------------------------------------------------------------------- */
@@ -285,8 +286,19 @@ VRTWarpedDataset::VRTWarpedDataset( int nXSize, int nYSize )
 VRTWarpedDataset::~VRTWarpedDataset()
 
 {
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int VRTWarpedDataset::CloseDependentDatasets()
+{
     FlushCache();
 
+    int bHasDroppedRef = VRTDataset::CloseDependentDatasets();
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup overviews.                                              */
 /* -------------------------------------------------------------------- */
@@ -300,10 +312,13 @@ VRTWarpedDataset::~VRTWarpedDataset()
         {
             GDALReferenceDataset( hDS );
             GDALClose( hDS );
+            bHasDroppedRef = TRUE;
         }
     }
 
     CPLFree( papoOverviews );
+    nOverviewCount = 0;
+    papoOverviews = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup warper if one is in effect.                             */
@@ -326,6 +341,7 @@ VRTWarpedDataset::~VRTWarpedDataset()
             {
                 GDALReferenceDataset( psWO->hSrcDS );
                 GDALClose( psWO->hSrcDS );
+                bHasDroppedRef = TRUE;
             }
         }
 
@@ -336,7 +352,19 @@ VRTWarpedDataset::~VRTWarpedDataset()
             GDALDestroyTransformer( psWO->pTransformerArg );
 
         delete poWarper;
+        poWarper = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Destroy the raster bands if they exist.                         */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       delete papoBands[iBand];
     }
+    nBands = 0;
+
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -1089,11 +1117,12 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
                 memset( pBandData, 
                         MAX(0,MIN(255,(int)adfInitRealImag[0])), 
                         nBandSize);
-            else if( adfInitRealImag[0] == 0.0 && adfInitRealImag[1] == 0 )
+            else if( !CPLIsNan(adfInitRealImag[0]) && adfInitRealImag[0] == 0.0 &&
+                     !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
             {
                 memset( pBandData, 0, nBandSize );
             }
-            else if( adfInitRealImag[1] == 0.0 )
+            else if( !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
             {
                 GDALCopyWords( &adfInitRealImag, GDT_Float64, 0, 
                                pBandData,psWO->eWorkingDataType,nWordSize,
@@ -1224,6 +1253,8 @@ CPLErr VRTWarpedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     GDALRasterBlock *poBlock;
 
     poBlock = GetLockedBlockRef( nBlockXOff, nBlockYOff, TRUE );
+    if( poBlock == NULL )
+        return CE_Failure;
 
     eErr = poWDS->ProcessBlock( nBlockXOff, nBlockYOff );
 
diff --git a/frmts/wcs/frmt_wcs.html b/frmts/wcs/frmt_wcs.html
index 8f260e8..600098c 100644
--- a/frmts/wcs/frmt_wcs.html
+++ b/frmts/wcs/frmt_wcs.html
@@ -33,7 +33,7 @@ supported by GDAL should work.  The driver will prefer a format with "tiff"
 in the name, otherwise
 it will fallback to the first offered format.   Coordinate systems are read
 from the DescribeCoverage result, and are expected to be in the form of 
-<tt>EPSG:n</tt> in the <tt>>supportedCRSs<</tt> element. <p>
+<tt>EPSG:n</tt> in the <tt><supportedCRSs></tt> element. <p>
 
 The service description file has the following additional elements as 
 immediate children of the <tt>WCS_GDAL</tt> element that may be optionally
@@ -55,8 +55,23 @@ userid and password to the remote server.
 <li> <b>DescribeCoverageExtra</b>: An additional set of keywords to add to DescribeCoverage requests in URL encoded form.  eg. "&CustNo=775"
 <li> <b>Version</b>:  Set a specific WCS version to use.  Currently defaults to 1.0.0 and 1.1.0 is also supported.
 <li> <b>FieldName</b>: Name of the field being accessed.  Used only with WCS 1.1.0+.  Defaults to the first field in the DescribeCoverage result.
+<li> <b>DefaultTime</b>: A timePosition to use by default when accessing 
+coverages with a time dimension.  Populated with the last offered time 
+position by default.
 </ul>
 
+
+<h3>Time</h3>
+
+Starting with GDAL 1.9.0, this driver includes experimental support for time based WCS 1.0.0 servers.
+On initial access the last offered time position will be identified as the
+DefaultTime.  Each time position available for the coverage will be treated
+as a subdataset. <p>
+
+Note that time based subdatasets are not supported when the service description
+is the filename.  Currently time support is not available for versions other
+than WCS 1.0.0.  <p>
+
 See Also:<p>
 
 <ul>
diff --git a/frmts/wcs/wcsdataset.cpp b/frmts/wcs/wcsdataset.cpp
index 437d283..e628088 100644
--- a/frmts/wcs/wcsdataset.cpp
+++ b/frmts/wcs/wcsdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wcsdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: wcsdataset.cpp 22618 2011-06-29 20:02:57Z rouault $
  *
  * Project:  WCS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WCS.
@@ -31,10 +31,9 @@
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 #include "cpl_http.h"
-#include "cpl_base64.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: wcsdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: wcsdataset.cpp 22618 2011-06-29 20:02:57Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -51,6 +50,10 @@ class CPL_DLL WCSDataset : public GDALPamDataset
     int         bServiceDirty;
     CPLXMLNode *psService;
 
+    char       *apszCoverageOfferingMD[2];
+
+    char      **papszSDSModifiers;
+
     int         nVersion;  // eg 100 for 1.0.0, 110 for 1.1.0
 
     CPLString   osCRS;
@@ -60,6 +63,9 @@ class CPL_DLL WCSDataset : public GDALPamDataset
 
     CPLString   osBandIdentifier;
 
+    CPLString   osDefaultTime;
+    std::vector<CPLString> aosTimePositions;
+
     int         TestUseBlockIO( int, int, int, int, int, int );
     CPLErr      DirectRasterIO( GDALRWFlag, int, int, int, int,
                                 void *, int, int, GDALDataType,
@@ -85,15 +91,22 @@ class CPL_DLL WCSDataset : public GDALPamDataset
     GByte      *pabySavedDataBuffer;
 
     char      **papszHttpOptions;
+
+    int         nMaxCols;
+    int         nMaxRows;
     
   public:
                 WCSDataset();
                 ~WCSDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
+    static int Identify( GDALOpenInfo * );
 
     virtual CPLErr GetGeoTransform( double * );
     virtual const char *GetProjectionRef(void);
+    virtual char **GetFileList(void);
+
+    virtual char **GetMetadata( const char *pszDomain );
 };
 
 /************************************************************************/
@@ -184,13 +197,19 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDS, int nBand, int iOverview )
 
         nOverviewCount = atoi(CPLGetXMLValue(poODS->psService,"OverviewCount",
                                              "-1"));
-        if( nOverviewCount == -1 )
+        if( nOverviewCount < 0 )
         {
             for( nOverviewCount = 0; 
                  (MAX(nRasterXSize,nRasterYSize) / (1 << nOverviewCount)) > 900;
                  nOverviewCount++ ) {}
         }
-        
+        else if( nOverviewCount > 30 )
+        {
+            /* There's no reason to have more than 30 overviews, because */
+            /* 2^(30+1) overflows a int32 */
+            nOverviewCount = 30;
+        }
+
         papoOverviews = (WCSRasterBand **) 
             CPLCalloc( nOverviewCount, sizeof(void*) );
         
@@ -311,15 +330,20 @@ CPLErr WCSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             GDALRasterBlock *poBlock = poTargBand->GetLockedBlockRef(
                 nBlockXOff, nBlockYOff, TRUE );
 
-            eErr = poTileBand->RasterIO( GF_Read, 
-                                         0, 0, nBlockXSize, nBlockYSize, 
-                                         poBlock->GetDataRef(), 
-                                         nBlockXSize, nBlockYSize, 
-                                         eDataType, 0, 0 );
-            poBlock->DropLock();
+            if( poBlock != NULL )
+            {
+                eErr = poTileBand->RasterIO( GF_Read,
+                                            0, 0, nBlockXSize, nBlockYSize,
+                                            poBlock->GetDataRef(),
+                                            nBlockXSize, nBlockYSize,
+                                            eDataType, 0, 0 );
+                poBlock->DropLock();
+            }
+            else
+                eErr = CE_Failure;
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
@@ -341,6 +365,10 @@ CPLErr WCSRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  int nPixelSpace, int nLineSpace )
     
 {
+    if( (poODS->nMaxCols > 0 && poODS->nMaxCols < nBufXSize)
+        ||  (poODS->nMaxRows > 0 && poODS->nMaxRows < nBufYSize) )
+        return CE_Failure;
+
     if( poODS->TestUseBlockIO( nXOff, nYOff, nXSize, nYSize,
                                nBufXSize,nBufYSize ) )
         return GDALPamRasterBand::IRasterIO( 
@@ -425,6 +453,14 @@ WCSDataset::WCSDataset()
 
     pabySavedDataBuffer = NULL;
     papszHttpOptions = NULL;
+
+    nMaxCols = -1;
+    nMaxRows = -1;
+
+    apszCoverageOfferingMD[0] = NULL;
+    apszCoverageOfferingMD[1] = NULL;
+
+    papszSDSModifiers = NULL;
 }
 
 /************************************************************************/
@@ -447,6 +483,9 @@ WCSDataset::~WCSDataset()
     pszProjection = NULL;
 
     CSLDestroy( papszHttpOptions );
+    CSLDestroy( papszSDSModifiers );
+
+    CPLFree( apszCoverageOfferingMD[0] );
 
     FlushMemoryResult();
 }
@@ -489,6 +528,10 @@ CPLErr WCSDataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nPixelSpace, int nLineSpace, int nBandSpace)
 
 {
+    if( (nMaxCols > 0 && nMaxCols < nBufXSize)
+        ||  (nMaxRows > 0 && nMaxRows < nBufYSize) )
+        return CE_Failure;
+
 /* -------------------------------------------------------------------- */
 /*      We need various criteria to skip out to block based methods.    */
 /* -------------------------------------------------------------------- */
@@ -556,7 +599,7 @@ WCSDataset::DirectRasterIO( GDALRWFlag eRWFlag,
                   "Returned tile does not match expected configuration.\n"
                   "Got %dx%d instead of %dx%d.", 
                   poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(),
-                  nBufXSize, nBufXSize );
+                  nBufXSize, nBufYSize );
         delete poTileDS;
         return CE_Failure;
     }
@@ -675,6 +718,13 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
     CPLFree( pszEncoded );
     
 /* -------------------------------------------------------------------- */
+/*      Do we have a time we want to use?                               */
+/* -------------------------------------------------------------------- */
+    CPLString osTime;
+
+    osTime = CSLFetchNameValueDef( papszSDSModifiers, "time", osDefaultTime );
+    
+/* -------------------------------------------------------------------- */
 /*      Construct a "simple" GetCoverage request (WCS 1.0).		*/
 /* -------------------------------------------------------------------- */
     CPLString osRequest;
@@ -692,6 +742,18 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
             osCRS.c_str(),
             CPLGetXMLValue( psService, "GetCoverageExtra", "" ) );
  
+        if( CPLGetXMLValue( psService, "Resample", NULL ) )
+        {
+            osRequest += "&INTERPOLATION=";
+            osRequest += CPLGetXMLValue( psService, "Resample", "" );
+        }
+
+        if( osTime != "" )
+        {
+            osRequest += "&time=";
+            osRequest += osTime;
+        }
+
         if( bSelectingBands )
         {
             osRequest += CPLString().Printf( "&%s=%s", 
@@ -741,13 +803,13 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
             dfXStep = (nXSize/(double)nBufXSize) * adfGeoTransform[1];
             dfYStep = (nYSize/(double)nBufYSize) * adfGeoTransform[5];
             
-            dfMinX = nXOff * adfGeoTransform[1] + adfGeoTransform[0] 
-                + dfXStep * 0.49;
-            dfMaxX = dfMinX + (nBufXSize - 1 + 0.02) * dfXStep;
+            dfMinX  = nXOff * adfGeoTransform[1] + adfGeoTransform[0] 
+                    + dfXStep * 0.5;
+            dfMaxX  = dfMinX + (nBufXSize - 1) * dfXStep;
 
-            dfMaxY = nYOff * adfGeoTransform[5] + adfGeoTransform[3] 
-                + dfYStep * 0.49;
-            dfMinY = dfMaxY + (nBufYSize - 1 + 0.02) * dfYStep;
+            dfMaxY  = nYOff * adfGeoTransform[5] + adfGeoTransform[3] 
+                    + dfYStep * 0.5;
+            dfMinY  = dfMaxY + (nBufYSize - 1) * dfYStep;
         }
 
         osRequest.Printf( 
@@ -949,6 +1011,22 @@ int WCSDataset::ExtractGridInfo100()
                       pszNativeCRSs );
     }
 
+    // We should try to use the services name for the CRS if possible.
+    if( pszNativeCRSs != NULL
+        && ( EQUALN(pszNativeCRSs,"EPSG:",5)
+             || EQUALN(pszNativeCRSs,"AUTO:",5)
+             || EQUALN(pszNativeCRSs,"Image ",6)
+             || EQUALN(pszNativeCRSs,"Engineering ",12)
+             || EQUALN(pszNativeCRSs,"OGC:",4) ) )
+    {
+        osCRS = pszNativeCRSs;
+        
+        size_t nDivider = osCRS.find( " " );
+
+        if( nDivider != std::string::npos )
+            osCRS.resize( nDivider-1 );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Do we have a coordinate system override?                        */
 /* -------------------------------------------------------------------- */
@@ -968,6 +1046,13 @@ int WCSDataset::ExtractGridInfo100()
 
         CPLFree( pszProjection );
         oSRS.exportToWkt( &pszProjection );
+
+        if( EQUALN(pszProjOverride,"EPSG:",5)
+            || EQUALN(pszProjOverride,"AUTO:",5)
+            || EQUALN(pszProjOverride,"OGC:",4)
+            || EQUALN(pszProjOverride,"Image ",6)
+            || EQUALN(pszProjOverride,"Engineering ",12) )
+            osCRS = pszProjOverride;
     }
 
 /* -------------------------------------------------------------------- */
@@ -976,7 +1061,7 @@ int WCSDataset::ExtractGridInfo100()
     OGRSpatialReference oSRS;
     const char *pszAuth;
 
-    if( pszProjection && strlen(pszProjection) > 0 )
+    if( pszProjection && strlen(pszProjection) > 0 && osCRS == "" )
     {
         oSRS.SetFromUserInput( pszProjection );
         pszAuth = oSRS.GetAuthorityName(NULL);
@@ -1137,6 +1222,46 @@ int WCSDataset::ExtractGridInfo100()
         }
     }
 
+/* -------------------------------------------------------------------- */
+/*      Do we have a temporal domain?  If so, try to identify a         */
+/*      default time value.                                             */
+/* -------------------------------------------------------------------- */
+    osDefaultTime = CPLGetXMLValue( psService, "DefaultTime", "" );
+    CPLXMLNode * psTD = 
+        CPLGetXMLNode( psService, "CoverageOffering.domainSet.temporalDomain" );
+    CPLString osServiceURL = CPLGetXMLValue( psService, "ServiceURL", "" );
+    CPLString osCoverageExtra = CPLGetXMLValue( psService, "GetCoverageExtra", "" );
+
+    if( psTD != NULL )
+    {
+        CPLXMLNode *psTime;
+
+        // collect all the allowed time positions.
+
+        for( psTime = psTD->psChild; psTime != NULL; psTime = psTime->psNext )
+        {
+            if( psTime->eType == CXT_Element
+                && EQUAL(psTime->pszValue,"timePosition")
+                && psTime->psChild != NULL
+                && psTime->psChild->eType == CXT_Text )
+                aosTimePositions.push_back( psTime->psChild->pszValue );
+        }
+
+        // we will default to the last - likely the most recent - entry.
+        
+        if( aosTimePositions.size() > 0 
+            && osDefaultTime == ""
+            && osServiceURL.ifind("time=") == std::string::npos
+            && osCoverageExtra.ifind("time=") == std::string::npos )
+        {
+            osDefaultTime = aosTimePositions[aosTimePositions.size()-1];
+
+            bServiceDirty = TRUE;
+            CPLCreateXMLElementAndValue( psService, "DefaultTime", 
+                                         osDefaultTime );
+        }
+    }
+
     return TRUE;
 }
 
@@ -1567,11 +1692,10 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
 
 {
 /* -------------------------------------------------------------------- */
-/*      In this case we can presume the error was already issued by     */
-/*      CPLHTTPFetch().                                                 */
+/*      There isn't much we can do in this case.  Hopefully an error    */
+/*      was already issued by CPLHTTPFetch()                            */
 /* -------------------------------------------------------------------- */
-    if( psResult == NULL || psResult->nDataLen == 0 ||
-        CPLGetLastErrorNo() != 0 )
+    if( psResult == NULL || psResult->nDataLen == 0 )
     {
         CPLHTTPDestroyResult( psResult );
         return TRUE;
@@ -1635,6 +1759,14 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
         return TRUE;
     }
 
+
+/* -------------------------------------------------------------------- */
+/*      Hopefully the error already issued by CPLHTTPFetch() is         */
+/*      sufficient.                                                     */
+/* -------------------------------------------------------------------- */
+    if( CPLGetLastErrorNo() != 0 )
+        return TRUE;
+
     return FALSE;
 }
 
@@ -1648,6 +1780,18 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
 int WCSDataset::EstablishRasterDetails()
 
 {
+    CPLXMLNode * psCO = CPLGetXMLNode( psService, "CoverageOffering" );
+
+    const char* pszCols = CPLGetXMLValue( psCO, "dimensionLimit.columns", NULL );
+    const char* pszRows = CPLGetXMLValue( psCO, "dimensionLimit.rows", NULL );
+    if( pszCols && pszRows )
+    {
+        nMaxCols = atoi(pszCols);
+        nMaxRows = atoi(pszRows);
+        SetMetadataItem("MAXNCOLS", pszCols, "IMAGE_STRUCTURE" );
+        SetMetadataItem("MAXNROWS", pszRows, "IMAGE_STRUCTURE" );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Do we already have bandcount and pixel type settings?           */
 /* -------------------------------------------------------------------- */
@@ -1672,7 +1816,16 @@ int WCSDataset::EstablishRasterDetails()
 
     if( poDS == NULL )
         return FALSE;
-    
+
+    const char* pszPrj = poDS->GetProjectionRef();
+    if( pszPrj && strlen(pszPrj) > 0 )
+    {
+        if( pszProjection )
+            CPLFree( pszProjection );
+
+        pszProjection = CPLStrdup( pszPrj );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Record details.                                                 */
 /* -------------------------------------------------------------------- */
@@ -1838,10 +1991,10 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
 /*      Steal the memory buffer from HTTP result.                       */
 /* -------------------------------------------------------------------- */
     pabySavedDataBuffer = psResult->pabyData;
-
+        
     psResult->pabyData = NULL;
     psResult->nDataLen = psResult->nDataAlloc = 0;
-
+    
     if( poDS == NULL )
         FlushMemoryResult();
 
@@ -1851,12 +2004,44 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
 }
 
 /************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int WCSDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Is this a WCS_GDAL service description file or "in url"         */
+/*      equivelent?                                                     */
+/* -------------------------------------------------------------------- */
+    if( poOpenInfo->nHeaderBytes == 0
+        && EQUALN((const char *) poOpenInfo->pszFilename,"<WCS_GDAL>",10) )
+        return TRUE;
+
+    else if( poOpenInfo->nHeaderBytes >= 10
+             && EQUALN((const char *) poOpenInfo->pabyHeader,"<WCS_GDAL>",10) )
+        return TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Is this apparently a WCS subdataset reference?                  */
+/* -------------------------------------------------------------------- */
+    else if( EQUALN((const char *) poOpenInfo->pszFilename,"WCS_SDS:",8) 
+             && poOpenInfo->nHeaderBytes == 0 )
+        return TRUE;
+
+    else
+        return FALSE;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
 GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
+    char **papszModifiers = NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Is this a WCS_GDAL service description file or "in url"         */
 /*      equivelent?                                                     */
@@ -1873,17 +2058,42 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         psService = CPLParseXMLFile( poOpenInfo->pszFilename );
     }
-    else
-        return NULL;
+/* -------------------------------------------------------------------- */
+/*      Is this apparently a subdataset?                                */
+/* -------------------------------------------------------------------- */
+    else if( EQUALN((const char *) poOpenInfo->pszFilename,"WCS_SDS:",8) 
+             && poOpenInfo->nHeaderBytes == 0 )
+    {
+        int iLast;
+
+        papszModifiers = CSLTokenizeString2( poOpenInfo->pszFilename+8, ",",
+                                             CSLT_HONOURSTRINGS );
+
+        iLast = CSLCount(papszModifiers)-1;
+        if( iLast >= 0 )
+        {
+            psService = CPLParseXMLFile( papszModifiers[iLast] );
+            CPLFree( papszModifiers[iLast] );
+            papszModifiers[iLast] = NULL;
+        }
 
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Success so far?                                                 */
+/* -------------------------------------------------------------------- */
     if( psService == NULL )
+    {
+        CSLDestroy( papszModifiers );
         return NULL;
+    }
         
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
+        CSLDestroy( papszModifiers );
         CPLDestroyXMLNode( psService );
         CPLError( CE_Failure, CPLE_NotSupported, 
                   "The WCS driver does not support update access to existing"
@@ -1897,6 +2107,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !CPLGetXMLValue( psService, "ServiceURL", NULL )
         || !CPLGetXMLValue( psService, "CoverageName", NULL ) )
     {
+        CSLDestroy( papszModifiers );
         CPLError( CE_Failure, CPLE_OpenFailed, 
                   "Missing one or both of ServiceURL and CoverageName elements.\n"
                   "See WCS driver documentation for details on service description file format." );
@@ -1919,6 +2130,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
         nVersion = 100;
     else
     {
+        CSLDestroy( papszModifiers );
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "WCS Version '%s' not supported.", pszVersion );
         CPLDestroyXMLNode( psService );
@@ -1935,6 +2147,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->psService = psService;
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->nVersion = nVersion;
+    poDS->papszSDSModifiers = papszModifiers;
 
 /* -------------------------------------------------------------------- */
 /*      Capture HTTP parameters.                                        */
@@ -1994,20 +2207,77 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     int nBandCount = atoi(CPLGetXMLValue(psService,"BandCount","1"));
     int iBand;
+
+    if (!GDALCheckBandCount(nBandCount, 0))
+    {
+        delete poDS;
+        return NULL;
+    }
      
     for( iBand = 0; iBand < nBandCount; iBand++ )
         poDS->SetBand( iBand+1, new WCSRasterBand( poDS, iBand+1, -1 ) );
 
 /* -------------------------------------------------------------------- */
+/*      Set time metadata on the dataset if we are selecting a          */
+/*      temporal slice.                                                 */
+/* -------------------------------------------------------------------- */
+    CPLString osTime = CSLFetchNameValueDef( poDS->papszSDSModifiers, "time", 
+                                             poDS->osDefaultTime );
+    
+    if( osTime != "" )
+        poDS->GDALMajorObject::SetMetadataItem( "TIME_POSITION", 
+                                                osTime.c_str() );
+
+/* -------------------------------------------------------------------- */
 /*      Do we have a band identifier to select only a subset of bands?  */
 /* -------------------------------------------------------------------- */
     poDS->osBandIdentifier = CPLGetXMLValue(psService,"BandIdentifier","");
 
 /* -------------------------------------------------------------------- */
+/*      Do we have time based subdatasets?  If so, record them in       */
+/*      metadata.  Note we don't do subdatasets if this is a            */
+/*      subdataset or if this is an all-in-memory service.              */
+/* -------------------------------------------------------------------- */
+    if( !EQUALN(poOpenInfo->pszFilename,"WCS_SDS:",8) 
+        && !EQUALN(poOpenInfo->pszFilename,"<WCS_GDAL>",10) 
+        && poDS->aosTimePositions.size() > 0 )
+    {
+        char **papszSubdatasets = NULL;
+        int iTime;
+
+        for( iTime = 0; iTime < (int)poDS->aosTimePositions.size(); iTime++ )
+        {
+            CPLString osName;
+            CPLString osValue;
+            
+            osName.Printf( "SUBDATASET_%d_NAME", iTime+1 );
+            osValue.Printf( "WCS_SDS:time=\"%s\",%s", 
+                           poDS->aosTimePositions[iTime].c_str(), 
+                           poOpenInfo->pszFilename );
+            papszSubdatasets = CSLSetNameValue( papszSubdatasets, 
+                                                osName, osValue );
+
+            CPLString osCoverage = 
+                CPLGetXMLValue( poDS->psService, "CoverageName", "" );
+
+            osName.Printf( "SUBDATASET_%d_DESC", iTime+1 );
+            osValue.Printf( "Coverage %s at time %s", 
+                            osCoverage.c_str(), 
+                            poDS->aosTimePositions[iTime].c_str() );
+            papszSubdatasets = CSLSetNameValue( papszSubdatasets, 
+                                                osName, osValue );
+        }
+        
+        poDS->GDALMajorObject::SetMetadata( papszSubdatasets, 
+                                            "SUBDATASETS" );
+        
+        CSLDestroy( papszSubdatasets );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->TryLoadXML();
-
     return( poDS );
 }
 
@@ -2029,13 +2299,76 @@ CPLErr WCSDataset::GetGeoTransform( double * padfTransform )
 const char *WCSDataset::GetProjectionRef()
 
 {
-    if( pszProjection )
+    const char* pszPrj = GDALPamDataset::GetProjectionRef();
+    if( pszPrj && strlen(pszPrj) > 0 )
+        return pszPrj;
+
+    if ( pszProjection && strlen(pszProjection) > 0 )
         return pszProjection;
-    else
-        return GDALPamDataset::GetProjectionRef();
+
+    return( "" );
 }
 
 /************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **WCSDataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+/* -------------------------------------------------------------------- */
+/*      ESRI also wishes to include service urls in the file list       */
+/*      though this is not currently part of the general definition     */
+/*      of GetFileList() for GDAL.                                      */
+/* -------------------------------------------------------------------- */
+#ifdef ESRI_BUILD
+    CPLString file;
+    file.Printf( "%s%s",
+                 CPLGetXMLValue( psService, "ServiceURL", "" ),
+                 CPLGetXMLValue( psService, "CoverageName", "" ) );
+    papszFileList = CSLAddString( papszFileList, file.c_str() );
+#endif /* def ESRI_BUILD */
+    
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **WCSDataset::GetMetadata( const char *pszDomain )
+
+{
+    if( pszDomain == NULL
+        || !EQUAL(pszDomain,"xml:CoverageOffering") )
+        return GDALPamDataset::GetMetadata( pszDomain );
+
+    
+    CPLXMLNode *psNode = CPLGetXMLNode( psService, "CoverageOffering" );
+
+    if( psNode == NULL )
+        psNode = CPLGetXMLNode( psService, "CoverageDescription" );
+
+    if( psNode == NULL )
+        return NULL;
+
+    if( apszCoverageOfferingMD[0] == NULL )
+    {
+        CPLXMLNode *psNext = psNode->psNext;
+        psNode->psNext = NULL;
+
+        apszCoverageOfferingMD[0] = CPLSerializeXMLTree( psNode );
+
+        psNode->psNext = psNext;
+    }
+
+    return apszCoverageOfferingMD;
+}
+
+
+/************************************************************************/
 /*                          GDALRegister_WCS()                        */
 /************************************************************************/
 
@@ -2053,8 +2386,10 @@ void GDALRegister_WCS()
                                    "OGC Web Coverage Service" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_wcs.html" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
         
         poDriver->pfnOpen = WCSDataset::Open;
+        poDriver->pfnIdentify = WCSDataset::Identify;
 
         GetGDALDriverManager()->RegisterDriver( poDriver );
     }
diff --git a/frmts/webp/GNUmakefile b/frmts/webp/GNUmakefile
new file mode 100644
index 0000000..ce06549
--- /dev/null
+++ b/frmts/webp/GNUmakefile
@@ -0,0 +1,13 @@
+
+include ../../GDALmake.opt
+
+OBJ	=	webpdataset.o
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/webp/frmt_webp.html b/frmts/webp/frmt_webp.html
new file mode 100644
index 0000000..345d19e
--- /dev/null
+++ b/frmts/webp/frmt_webp.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>WEBP - WEBP</title>
+</head>
+
+<body>
+
+<h1>WEBP - WEBP</h1>
+
+<p>Starting with GDAL 1.9.0, GDAL can read and write WebP images through the WebP library.</p>
+
+<p>WebP is a new image format that provides lossy compression for photographic images.
+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>
+
+<p>The WEBP driver only supports 3 bands (RGB) images</p>
+
+<p>The WEBP driver can be used as the internal format used by the <a href="frmt_rasterlite.html">Rasterlite</a> driver.</p>
+
+<h2>Creation options</h2>
+
+<ul>
+<li><p><b>QUALITY=n</b> By default the quality flag is set to 75, but this
+option can be used to select other values.  Values must be in the
+range 1-100.  Low values result in higher compression ratios, but poorer
+image quality. <p></li>
+</ul>
+
+<p>See Also:</p>
+
+<ul>
+<li><a href="http://code.google.com/intl/fr/speed/webp/">WebP home page</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/webp/makefile.vc b/frmts/webp/makefile.vc
new file mode 100644
index 0000000..5e5220b
--- /dev/null
+++ b/frmts/webp/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	webpdataset.obj
+
+EXTRAFLAGS 	= 	$(WEBP_CFLAGS) 
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/webp/webpdataset.cpp b/frmts/webp/webpdataset.cpp
new file mode 100644
index 0000000..038269c
--- /dev/null
+++ b/frmts/webp/webpdataset.cpp
@@ -0,0 +1,670 @@
+/******************************************************************************
+ * $Id: webpdataset.cpp 23692 2012-01-03 19:10:14Z 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
+ *
+ * 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_pam.h"
+#include "cpl_string.h"
+
+#include "webp/decode.h"
+#include "webp/encode.h"
+
+CPL_CVSID("$Id: webpdataset.cpp 23692 2012-01-03 19:10:14Z rouault $");
+
+CPL_C_START
+void    GDALRegister_WEBP(void);
+CPL_C_END
+
+/************************************************************************/
+/* ==================================================================== */
+/*                               WEBPDataset                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class WEBPRasterBand;
+
+class WEBPDataset : public GDALPamDataset
+{
+    friend class WEBPRasterBand;
+
+    VSILFILE*   fpImage;
+    GByte* pabyUncompressed;
+    int    bHasBeenUncompressed;
+    CPLErr Uncompress();
+
+  public:
+                 WEBPDataset();
+                 ~WEBPDataset();
+
+    virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
+                                   void *, int, int, GDALDataType,
+                                   int, int *, int, int, int );
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+    static GDALDataset* CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            WEBPRasterBand                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class WEBPRasterBand : public GDALPamRasterBand
+{
+    friend class WEBPDataset;
+
+  public:
+
+                   WEBPRasterBand( WEBPDataset *, int );
+
+    virtual CPLErr IReadBlock( int, int, void * );
+    virtual GDALColorInterp GetColorInterpretation();
+};
+
+/************************************************************************/
+/*                          WEBPRasterBand()                            */
+/************************************************************************/
+
+WEBPRasterBand::WEBPRasterBand( WEBPDataset *poDS, int nBand )
+
+{
+    this->poDS = poDS;
+
+    eDataType = GDT_Byte;
+
+    nBlockXSize = poDS->nRasterXSize;
+    nBlockYSize = 1;
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr WEBPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                  void * pImage )
+
+{
+    WEBPDataset* poGDS = (WEBPDataset*) poDS;
+
+    poGDS->Uncompress();
+
+    int i;
+    GByte* pabyUncompressed =
+        &poGDS->pabyUncompressed[nBlockYOff * nRasterXSize  * 3 + nBand - 1];
+    for(i=0;i<nRasterXSize;i++)
+        ((GByte*)pImage)[i] = pabyUncompressed[3 * i];
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                       GetColorInterpretation()                       */
+/************************************************************************/
+
+GDALColorInterp WEBPRasterBand::GetColorInterpretation()
+
+{
+    if ( nBand == 1 )
+        return GCI_RedBand;
+
+    else if( nBand == 2 )
+        return GCI_GreenBand;
+
+    else if ( nBand == 3 )
+        return GCI_BlueBand;
+
+    else
+        return GCI_AlphaBand;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             WEBPDataset                               */
+/* ==================================================================== */
+/************************************************************************/
+
+
+/************************************************************************/
+/*                            WEBPDataset()                              */
+/************************************************************************/
+
+WEBPDataset::WEBPDataset()
+
+{
+    fpImage = NULL;
+    pabyUncompressed = NULL;
+    bHasBeenUncompressed = FALSE;
+}
+
+/************************************************************************/
+/*                           ~WEBPDataset()                             */
+/************************************************************************/
+
+WEBPDataset::~WEBPDataset()
+
+{
+    FlushCache();
+    if (fpImage)
+        VSIFCloseL(fpImage);
+    VSIFree(pabyUncompressed);
+}
+
+/************************************************************************/
+/*                            Uncompress()                              */
+/************************************************************************/
+
+CPLErr WEBPDataset::Uncompress()
+{
+    if (bHasBeenUncompressed)
+        return CE_None;
+    bHasBeenUncompressed = TRUE;
+
+    VSIFSeekL(fpImage, 0, SEEK_END);
+    vsi_l_offset nSize = VSIFTellL(fpImage);
+    if (nSize != (vsi_l_offset)(uint32_t)nSize)
+        return CE_Failure;
+    VSIFSeekL(fpImage, 0, SEEK_SET);
+    uint8_t* pabyCompressed = (uint8_t*)VSIMalloc(nSize);
+    if (pabyCompressed == NULL)
+        return CE_Failure;
+    VSIFReadL(pabyCompressed, 1, nSize, fpImage);
+    uint8_t* pRet = WebPDecodeRGBInto(pabyCompressed, (uint32_t)nSize,
+                        (uint8_t*)pabyUncompressed, nRasterXSize * nRasterYSize * 3,
+                        nRasterXSize * 3);
+    VSIFree(pabyCompressed);
+    if (pRet == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "WebPDecodeRGBInto() failed");
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr WEBPDataset::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) &&
+       (nBandCount == 3) &&
+       (nBands == 3) &&
+       (nXOff == 0) && (nXOff == 0) &&
+       (nXSize == nBufXSize) && (nXSize == nRasterXSize) &&
+       (nYSize == nBufYSize) && (nYSize == nRasterYSize) &&
+       (eBufType == GDT_Byte) && 
+       (nPixelSpace == 3) &&
+       (nLineSpace == (nPixelSpace*nXSize)) &&
+       (nBandSpace == 1) &&
+       (pData != NULL) &&
+       (panBandMap != NULL) &&
+       (panBandMap[0] == 1) && (panBandMap[1] == 2) && (panBandMap[2] == 3))
+    {
+        Uncompress();
+        memcpy(pData, pabyUncompressed, 3 * nXSize * nYSize);
+        return CE_None;
+    }
+
+    return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                     pData, nBufXSize, nBufYSize, eBufType,
+                                     nBandCount, panBandMap,
+                                     nPixelSpace, nLineSpace, nBandSpace);
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+
+int WEBPDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    GByte  *pabyHeader = NULL;
+    int    nHeaderBytes = poOpenInfo->nHeaderBytes;
+
+    pabyHeader = poOpenInfo->pabyHeader;
+
+    if( nHeaderBytes < 20 )
+        return FALSE;
+
+    return memcmp(pabyHeader, "RIFF", 4) == 0 &&
+           memcmp(pabyHeader + 8, "WEBP", 4) == 0 &&
+           memcmp(pabyHeader + 12, "VP8 ", 4) == 0;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if( !Identify( poOpenInfo ) )
+        return NULL;
+
+    int nWidth, nHeight;
+    if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes,
+                     &nWidth, &nHeight))
+        return NULL;
+
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "The WEBP driver does not support update access to existing"
+                  " datasets.\n" );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Open the file using the large file api.                         */
+/* -------------------------------------------------------------------- */
+    VSILFILE* fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+
+    if( fpImage == NULL )
+        return NULL;
+
+    GByte* pabyUncompressed = (GByte*)VSIMalloc3(nWidth, nHeight, 3);
+    if (pabyUncompressed == NULL)
+    {
+        VSIFCloseL(fpImage);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    WEBPDataset  *poDS;
+
+    poDS = new WEBPDataset();
+    poDS->nRasterXSize = nWidth;
+    poDS->nRasterYSize = nHeight;
+    poDS->fpImage = fpImage;
+    poDS->pabyUncompressed = pabyUncompressed;
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 0; iBand < 3; iBand++ )
+        poDS->SetBand( iBand+1, new WEBPRasterBand( poDS, iBand+1 ) );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+
+    poDS->TryLoadXML( poOpenInfo->papszSiblingFiles );
+
+/* -------------------------------------------------------------------- */
+/*      Open overviews.                                                 */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         WEBPDatasetWriter()                          */
+/************************************************************************/
+
+int WEBPDatasetWriter(const uint8_t* data, size_t data_size,
+                      const WebPPicture* const picture)
+{
+    return VSIFWriteL(data, 1, data_size, (VSILFILE*)picture->custom_ptr)
+            == data_size;
+}
+
+/************************************************************************/
+/*                              CreateCopy()                            */
+/************************************************************************/
+
+GDALDataset *
+WEBPDataset::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();
+
+/* -------------------------------------------------------------------- */
+/*      WEBP library initialization                                     */
+/* -------------------------------------------------------------------- */
+
+    WebPPicture sPicture;
+    if (!WebPPictureInit(&sPicture))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureInit() failed");
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Some some rudimentary checks                                    */
+/* -------------------------------------------------------------------- */
+
+    if( nXSize > 16383 || nYSize > 16383 )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "WEBP maximum image dimensions are 16383 x 16383.");
+
+        return NULL;
+    }
+
+    if( nBands != 3 )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "WEBP driver doesn't support %d bands. Must be 3 (RGB) bands.",
+                  nBands );
+
+        return NULL;
+    }
+
+    GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+
+    if( eDT != GDT_Byte )
+    {
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
+                  "WEBP driver doesn't support data type %s. "
+                  "Only eight bit byte bands supported.",
+                  GDALGetDataTypeName(
+                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
+
+        if (bStrict)
+            return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      What options has the user selected?                             */
+/* -------------------------------------------------------------------- */
+    float fQuality = 75.0f;
+    const char* pszQUALITY = CSLFetchNameValue(papszOptions, "QUALITY"); 
+    if( pszQUALITY != NULL )
+    {
+        fQuality = (float) atof(pszQUALITY);
+        if( fQuality < 0.0f || fQuality > 100.0f )
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "%s=%s is not a legal value.", "QUALITY", pszQUALITY);
+            return NULL;
+        }
+    }
+
+    WebPPreset nPreset = WEBP_PRESET_DEFAULT;
+    const char* pszPRESET = CSLFetchNameValueDef(papszOptions, "PRESET", "DEFAULT");
+    if (EQUAL(pszPRESET, "DEFAULT"))
+        nPreset = WEBP_PRESET_DEFAULT;
+    else if (EQUAL(pszPRESET, "PICTURE"))
+        nPreset = WEBP_PRESET_PICTURE;
+    else if (EQUAL(pszPRESET, "PHOTO"))
+        nPreset = WEBP_PRESET_PHOTO;
+    else if (EQUAL(pszPRESET, "PICTURE"))
+        nPreset = WEBP_PRESET_PICTURE;
+    else if (EQUAL(pszPRESET, "DRAWING"))
+        nPreset = WEBP_PRESET_DRAWING;
+    else if (EQUAL(pszPRESET, "ICON"))
+        nPreset = WEBP_PRESET_ICON;
+    else if (EQUAL(pszPRESET, "TEXT"))
+        nPreset = WEBP_PRESET_TEXT;
+    else
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "%s=%s is not a legal value.", "PRESET", pszPRESET );
+        return NULL;
+    }
+
+    WebPConfig sConfig;
+    if (!WebPConfigInitInternal(&sConfig, nPreset, fQuality, WEBP_ENCODER_ABI_VERSION))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "WebPConfigInit() failed");
+        return NULL;
+    }
+
+
+#define FETCH_AND_SET_OPTION_INT(name, fieldname, minval, maxval) \
+{ \
+    const char* pszVal = CSLFetchNameValue(papszOptions, name); \
+    if (pszVal != NULL) \
+    { \
+        sConfig.fieldname = atoi(pszVal); \
+        if (sConfig.fieldname < minval || sConfig.fieldname > maxval) \
+        { \
+            CPLError( CE_Failure, CPLE_IllegalArg, \
+                      "%s=%s is not a legal value.", name, pszVal ); \
+            return NULL; \
+        } \
+    } \
+}
+
+    FETCH_AND_SET_OPTION_INT("TARGETSIZE", target_size, 0, INT_MAX);
+
+    const char* pszPSNR = CSLFetchNameValue(papszOptions, "PSNR");
+    if (pszPSNR)
+    {
+        sConfig.target_PSNR = atof(pszPSNR);
+        if (sConfig.target_PSNR < 0)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "PSNR=%s is not a legal value.", pszPSNR );
+            return NULL;
+        }
+    }
+
+    FETCH_AND_SET_OPTION_INT("METHOD", method, 0, 6);
+    FETCH_AND_SET_OPTION_INT("SEGMENTS", segments, 1, 4);
+    FETCH_AND_SET_OPTION_INT("SNS_STRENGTH", sns_strength, 0, 100);
+    FETCH_AND_SET_OPTION_INT("FILTER_STRENGTH", filter_strength, 0, 100);
+    FETCH_AND_SET_OPTION_INT("FILTER_SHARPNESS", filter_sharpness, 0, 7);
+    FETCH_AND_SET_OPTION_INT("FILTER_TYPE", filter_type, 0, 1);
+    FETCH_AND_SET_OPTION_INT("AUTOFILTER", autofilter, 0, 1);
+    FETCH_AND_SET_OPTION_INT("PASS", pass, 1, 10);
+    FETCH_AND_SET_OPTION_INT("PREPROCESSING", preprocessing, 0, 1);
+    FETCH_AND_SET_OPTION_INT("PARTITIONS", partitions, 0, 3);
+
+    if (!WebPValidateConfig(&sConfig))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "WebPValidateConfig() failed");
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Allocate memory                                                 */
+/* -------------------------------------------------------------------- */
+    GByte   *pabyBuffer;
+
+    pabyBuffer = (GByte *) VSIMalloc( 3 * nXSize * nYSize );
+    if (pabyBuffer == NULL)
+    {
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the dataset.                                             */
+/* -------------------------------------------------------------------- */
+    VSILFILE    *fpImage;
+
+    fpImage = VSIFOpenL( pszFilename, "wb" );
+    if( fpImage == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Unable to create WEBP file %s.\n",
+                  pszFilename );
+        VSIFree(pabyBuffer);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      WEBP library settings                                           */
+/* -------------------------------------------------------------------- */
+
+#if WEBP_ENCODER_ABI_VERSION >= 0x0002
+    sPicture.colorspace = WEBP_YUV420;
+#else
+    sPicture.colorspace = 0;
+#endif
+    sPicture.width = nXSize;
+    sPicture.height = nYSize;
+    sPicture.writer = WEBPDatasetWriter;
+    sPicture.custom_ptr = fpImage;
+    if (!WebPPictureAlloc(&sPicture))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureAlloc() failed");
+        VSIFree(pabyBuffer);
+        VSIFCloseL( fpImage );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Acquire source imagery.                                         */
+/* -------------------------------------------------------------------- */
+    CPLErr      eErr = CE_None;
+
+    eErr = poSrcDS->RasterIO( GF_Read, 0, 0, nXSize, nYSize,
+                              pabyBuffer, nXSize, nYSize, GDT_Byte,
+                              3, NULL,
+                              3, 3 * nXSize, 1 );
+
+/* -------------------------------------------------------------------- */
+/*      Import and write to file                                        */
+/* -------------------------------------------------------------------- */
+    if (eErr == CE_None &&
+        !WebPPictureImportRGB(&sPicture, pabyBuffer, 3 * nXSize))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureImportRGB() failed");
+        eErr = CE_Failure;
+    }
+
+    if (eErr == CE_None && !WebPEncode(&sConfig, &sPicture))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed");
+        eErr = CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup and close.                                              */
+/* -------------------------------------------------------------------- */
+    CPLFree( pabyBuffer );
+
+    WebPPictureFree(&sPicture);
+
+    VSIFCloseL( fpImage );
+
+    if( eErr != CE_None )
+    {
+        VSIUnlink( pszFilename );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      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);
+    WEBPDataset *poDS = (WEBPDataset*) WEBPDataset::Open( &oOpenInfo );
+    CPLPopErrorHandler();
+    if( poDS )
+    {
+        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+        return poDS;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                         GDALRegister_WEBP()                          */
+/************************************************************************/
+
+void GDALRegister_WEBP()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "WEBP" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "WEBP" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "WEBP" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                   "frmt_webp.html" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "webp" );
+        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/webp" );
+
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                                   "Byte" );
+
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>\n"
+"   <Option name='QUALITY' type='float' description='good=100, bad=0' default='75'/>\n"
+"   <Option name='PRESET' type='string-select' description='kind of image' default='DEFAULT'>\n"
+"       <Value>DEFAULT</Value>\n"
+"       <Value>PICTURE</Value>\n"
+"       <Value>PHOTO</Value>\n"
+"       <Value>DRAWING</Value>\n"
+"       <Value>ICON</Value>\n"
+"       <Value>TEXT</Value>\n"
+"   </Option>\n"
+"   <Option name='TARGETSIZE' type='int' description='if non-zero, desired target size in bytes. Has precedence over QUALITY'/>\n"
+"   <Option name='PSNR' type='float' description='if non-zero, minimal distortion to to achieve. Has precedence over TARGETSIZE'/>\n"
+"   <Option name='METHOD' type='int' description='quality/speed trade-off. fast=0, slower-better=6' default='4'/>\n"
+"   <Option name='SEGMENTS' type='int' description='maximum number of segments [1-4]' default='4'/>\n"
+"   <Option name='SNS_STRENGTH' type='int' description='Spatial Noise Shaping. off=0, maximum=100' default='50'/>\n"
+"   <Option name='FILTER_STRENGTH' type='int' description='Filter strength. off=0, strongest=100' default='20'/>\n"
+"   <Option name='FILTER_SHARPNESS' type='int' description='Filter sharpness. off=0, least sharp=7' default='0'/>\n"
+"   <Option name='FILTER_TYPE' type='int' description='Filtering type. simple=0, strong=1' default='0'/>\n"
+"   <Option name='AUTOFILTER' type='int' description=\"Auto adjust filter's strength. off=0, on=1\" default='0'/>\n"
+"   <Option name='PASS' type='int' description='Number of entropy analysis passes [1-10]' default='1'/>\n"
+"   <Option name='PREPROCESSING' type='int' description='Preprocessing filter. none=0, segment-smooth=1' default='0'/>\n"
+"   <Option name='PARTITIONS' type='int' description='log2(number of token partitions) in [0..3]' default='0'/>\n"
+"</CreationOptionList>\n" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnIdentify = WEBPDataset::Identify;
+        poDriver->pfnOpen = WEBPDataset::Open;
+        poDriver->pfnCreateCopy = WEBPDataset::CreateCopy;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
diff --git a/frmts/wms/GNUmakefile b/frmts/wms/GNUmakefile
index c740679..66fa3db 100644
--- a/frmts/wms/GNUmakefile
+++ b/frmts/wms/GNUmakefile
@@ -1,9 +1,11 @@
 
 include ../../GDALmake.opt
 
-OBJ	=	cache.o dataset.o gdalhttp.o md5.o minidriver.o rasterband.o stuff.o wmsdriver.o \
-		minidriver_wms.o minidriver_tileservice.o minidriver_worldwind.o minidriver_tms.o
-
+OBJ =	cache.o dataset.o gdalhttp.o md5.o minidriver.o \
+	rasterband.o stuff.o wmsdriver.o minidriver_wms.o \
+	minidriver_tileservice.o minidriver_worldwind.o \
+	minidriver_tms.o minidriver_tiled_wms.o wmsmetadataset.o \
+	minidriver_virtualearth.o
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS) $(CURL_INC)
 
@@ -14,4 +16,7 @@ clean:
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 
-$(OBJ) $(O_OBJ):	gdalhttp.h md5.h minidriver_tileservice.h minidriver_wms.h minidriver_worldwind.h minidriver_tms.h wmsdriver.h 
+$(OBJ) $(O_OBJ):	gdalhttp.h md5.h minidriver_tileservice.h \
+	minidriver_wms.h minidriver_worldwind.h minidriver_tms.h \
+	minidriver_tiled_wms.h wmsdriver.h wmsmetadataset.h \
+	minidriver_virtualearth.h
diff --git a/frmts/wms/WMSServerList.txt b/frmts/wms/WMSServerList.txt
new file mode 100644
index 0000000..4e067d2
--- /dev/null
+++ b/frmts/wms/WMSServerList.txt
@@ -0,0 +1,49 @@
+TMS:
+http://maps.opengeo.org/geowebcache/service/tms/1.0.0
+http://demo.opengeo.org/geoserver/gwc/service/tms/1.0.0
+http://osm.omniscale.net/proxy/tms/1.0.0
+http://apps.esdi-humboldt.cz/mapproxy/tms/1.0.0
+http://apps.esdi-humboldt.cz/cgi-bin/tilecache/tilecache.cgi/1.0.0
+http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0
+http://www2.terriscope.fr/geocache/tms
+
+WMS-C:
+http://maps.opengeo.org/geowebcache/service/wms?SERVICE=WMS&TILED=true
+http://demo.opengeo.org/geoserver/gwc/service/wms?SERVICE=WMS&TILED=true
+http://osm.omniscale.net/proxy/service?SERVICE=WMS&TILED=true
+http://apps.esdi-humboldt.cz/mapproxy/service?SERVICE=WMS&tiled=true
+http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0?SERVICE=WMS
+http://wmsc1.terrapages.net/getpngmap?SERVICE=WMS
+http://wxs.ign.fr/geoportail/wmsc?SERVICE=WMS                                                               # requires a key
+http://www2.terriscope.fr/geocache/wms?SERVICE=WMS
+
+Regular WMS:
+http://maps.opengeo.org/geowebcache/service/wms?SERVICE=WMS
+http://demo.opengeo.org/geoserver/gwc/service/wms?SERVICE=WMS
+http://osm.omniscale.net/proxy/service?SERVICE=WMS
+http://apps.esdi-humboldt.cz/mapproxy/service?SERVICE=WMS
+http://wms.geobase.ca/wms-bin/cubeserv.cgi?SERVICE=WMS
+http://mapserver-slp.mendelu.cz/cgi-bin/mapserv?map=/var/local/slp/krtinyWMS.map&SERVICE=WMS
+http://vmap0.tiles.osgeo.org/wms/vmap0?SERVICE=WMS
+http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi?SERVICE=WMS
+http://www.ga.gov.au/bin/getmap.pl?dataset=national&Service=WMS
+http://wms.geosignal.fr/metropole?SERVICE=WMS&FORMAT=image/png
+http://wms.lizardtech.com/lizardtech/iserv/ows?SERVICE=WMS
+http://wms.ess-ws.nrcan.gc.ca/wms/mapserv?map=/export/wms/mapfiles/indexcouverture/canvec.map&SERVICE=WMS
+http://210.69.84.29:80/liteview6.5/servlet/MapGuideLiteView?SERVICE=WMS                                     # EPSG:NONE
+http://geodata.epa.gov:80/wmsconnector/com.esri.wms.Esrimap/WasteWaterImage?SERVICE=WMS                     # EPSG:NONE
+http://map.ngdc.noaa.gov:80/wmsconnector/com.esri.wms.Esrimap/basicworld?SERVICE=WMS                        # EPSG:NONE
+http://neowms.sci.gsfc.nasa.gov/wms/wms?SERVICE=WMS                                                         # SRS only defined in top layer
+http://www.cubewerx.com/demo/cubeserv/cubeserv.cgi?SERVICE=WMS
+http://www2.demis.nl/wms/wms.asp?wms=WorldMap&SERVICE=WMS
+http://iws.erdas.com/ecwp/ecw_wms.dll?service=WMS
+http://v2.suite.opengeo.org/geoserver/gwc/service/wms?SERVICE=WMS
+http://demo.mapserver.org/cgi-bin/wms?SERVICE=WMS
+http://geonames.nga.mil/names/request.asp?SERVICE=WMS
+
+WMTS:
+http://maps.opengeo.org/geowebcache/service/wmts?REQUEST=getcapabilities
+http://v2.suite.opengeo.org/geoserver/gwc/service/wmts?REQUEST=getcapabilities
+http://www.cubewerx.com/demo/cubeserv/cubeserv.cgi?SERVICE=WMTS&REQUEST=getcapabilities
+http://iws.erdas.com/ecwp/ecw_wmts.dll?service=WMTS&request=getcapabilities
+http://www2.terriscope.fr/geocache/wmts?service=WMTS&request=getcapabilities
\ No newline at end of file
diff --git a/frmts/wms/cache.cpp b/frmts/wms/cache.cpp
index 6f361ea..7009f06 100644
--- a/frmts/wms/cache.cpp
+++ b/frmts/wms/cache.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cache.cpp 18020 2009-11-14 14:33:20Z rouault $
+ * $Id: cache.cpp 21880 2011-02-27 14:28:26Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -66,9 +66,10 @@ CPLErr GDALWMSCache::Write(const char *key, const CPLString &file_name) {
 CPLErr GDALWMSCache::Read(const char *key, CPLString *file_name) {
     CPLErr ret = CE_Failure;
     CPLString cache_file(KeyToCacheFile(key));
-    FILE *f = VSIFOpen(cache_file.c_str(), "rb");
-    if (f != NULL) {
-        VSIFClose(f);
+    VSILFILE* fp = VSIFOpenL(cache_file.c_str(), "rb");
+    if (fp != NULL)
+    {
+        VSIFCloseL(fp);
         *file_name = cache_file;
         ret = CE_None;
     }
diff --git a/frmts/wms/dataset.cpp b/frmts/wms/dataset.cpp
index 7d64756..cb8ad3a 100644
--- a/frmts/wms/dataset.cpp
+++ b/frmts/wms/dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dataset.cpp 21304 2010-12-21 09:44:03Z nowakpl $
+ * $Id: dataset.cpp 23192 2011-10-06 20:31:54Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -26,7 +26,14 @@
  * 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"
 
@@ -37,18 +44,295 @@ GDALWMSDataset::GDALWMSDataset() {
     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;
 }
 
 GDALWMSDataset::~GDALWMSDataset() {
     if (m_mini_driver) delete m_mini_driver;
     if (m_cache) delete m_cache;
 }
+
 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) {
+
+	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') {
+			m_overview_count = atoi(overview_count);
+		    } else if (tlevel[0] != '\0') {
+			m_overview_count = 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);
+			m_overview_count = 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 < m_overview_count; ++j) {
+                    band->AddOverview(scale);
+                    band->m_color_interp = color_interp;
+                    scale *= 0.5;
+                }
+            }
+	}
+    }
+
     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", "");
@@ -80,6 +364,7 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             m_offline_mode = 0;
         }
     }
+
     if (ret == CE_None) {
         const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
         if (advise_read[0] != '\0') {
@@ -94,6 +379,7 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             m_use_advise_read = 0;
         }
     }
+
     if (ret == CE_None) {
         const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
         if (m_use_advise_read) {
@@ -110,127 +396,9 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             }
         }
     }
-    if (ret == CE_None) {
-        const char *block_size_x = CPLGetXMLValue(config, "BlockSizeX", "1024");
-        const char *block_size_y = CPLGetXMLValue(config, "BlockSizeY", "1024");
-        m_block_size_x = atoi(block_size_x);
-        m_block_size_y = atoi(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)
-    {
-        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;
-        }
-    }
-    if (ret == CE_None) {
-    	const int clamp_requests_bool = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
-    	if (clamp_requests_bool == -1) {
-	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true / false expected.");
-	    ret = CE_Failure;
-	} else {
-	    m_clamp_requests = clamp_requests_bool;
-	}
-    }
-    if (ret == CE_None) {
-        CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
-        if (data_window_node == NULL) {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
-            ret = CE_Failure;
-        } else {
-            const char *overview_count = CPLGetXMLValue(config, "OverviewCount", "");
-            const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", "-180.0");
-            const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", "90.0");
-            const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", "180.0");
-            const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", "-90.0");
-            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", "");
-            const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", "1");
-            const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", "1");
-            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;
-                }
-            }
-            if (ret == CE_None) {
-                if (tlevel[0] != '\0') {
-                    m_data_window.m_tlevel = atoi(tlevel);
-                } else {
-                    m_data_window.m_tlevel = 0;
-                }
-            }
-            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') {
-                    m_overview_count = atoi(overview_count);
-                } else if (tlevel[0] != '\0') {
-                    m_overview_count = 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);
-                    m_overview_count = 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;
-                }
-            }
-        }
-    }
+
+    // Let the local configuration override the minidriver supplied projection
+
     if (ret == CE_None) {
         const char *proj = CPLGetXMLValue(config, "Projection", "");
         if (proj[0] != '\0') {
@@ -241,10 +409,7 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             }
         }
     }
-    
-    const char *bands_count = CPLGetXMLValue(config, "BandsCount", "3");
-    int nBandCount = atoi(bands_count);
-    
+
     if (ret == CE_None) {
         CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
         if (cache_node != NULL) {
@@ -257,72 +422,7 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             }
         }
     }
-    if (ret == CE_None) {
-        CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
-        if (service_node != NULL) {
-            const char *service_name = CPLGetXMLValue(service_node, "name", "");
-            if (service_name[0] != '\0') {
-                GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
-                GDALWMSMiniDriverFactory *const mdf = mdm->Find(CPLString(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);
-                    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;
-        }
-    }
-    if (ret == CE_None) {
-        nRasterXSize = m_data_window.m_sx;
-        nRasterYSize = m_data_window.m_sy;
-
-        if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
-            !GDALCheckBandCount(nBandCount, 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 < nBandCount; ++i) {
-            GDALColorInterp color_interp = (nBandCount <= 4 && i <= 3 ? default_color_interp[nBandCount - 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 < m_overview_count; ++j) {
-                band->AddOverview(scale);
-                band->m_color_interp = color_interp;
-                scale *= 0.5;
-            }
-        }
-    }
+    
     if (ret == CE_None) {
     	const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
     	if (v == -1) {
@@ -392,12 +492,68 @@ const GDALWMSDataWindow *GDALWMSDataset::WMSGetDataWindow() const {
     return &m_data_window;
 }
 
-int GDALWMSDataset::WMSGetBlockSizeX() const {
-    return m_block_size_x;
+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::WMSSetOverviewCount(int count) {
+    m_overview_count=count;
+}
+
+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;
 }
 
-int GDALWMSDataset::WMSGetBlockSizeY() const {
-    return m_block_size_y;
+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;
 }
 
 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) {
@@ -409,3 +565,15 @@ CPLErr GDALWMSDataset::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int b
     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_twms_Clementine.xml b/frmts/wms/frmt_twms_Clementine.xml
new file mode 100644
index 0000000..ccf3914
--- /dev/null
+++ b/frmts/wms/frmt_twms_Clementine.xml
@@ -0,0 +1,6 @@
+<GDAL_WMS>
+    <Service name="TiledWMS">
+	<ServerUrl>http://onmoon.jpl.nasa.gov/wms.cgi?</ServerUrl>
+	<TiledGroupName>Clementine</TiledGroupName>
+    </Service>
+</GDAL_WMS>
diff --git a/frmts/wms/frmt_twms_daily.xml b/frmts/wms/frmt_twms_daily.xml
new file mode 100644
index 0000000..933fe8b
--- /dev/null
+++ b/frmts/wms/frmt_twms_daily.xml
@@ -0,0 +1,7 @@
+<GDAL_WMS>
+    <Service name="TiledWMS">
+	<ServerUrl>http://onearth.jpl.nasa.gov/wms.cgi?</ServerUrl>
+	<TiledGroupName>Daily Planet</TiledGroupName>
+	<Change key="${time}">2009-10-12</Change>
+    </Service>
+</GDAL_WMS>
diff --git a/frmts/wms/frmt_twms_srtm.xml b/frmts/wms/frmt_twms_srtm.xml
new file mode 100644
index 0000000..f4b3572
--- /dev/null
+++ b/frmts/wms/frmt_twms_srtm.xml
@@ -0,0 +1,6 @@
+<GDAL_WMS>
+    <Service name="TiledWMS">
+	<ServerUrl>http://onearth.jpl.nasa.gov/wms.cgi?</ServerUrl>
+	<TiledGroupName>Global SRTM Elevation</TiledGroupName>
+    </Service>
+</GDAL_WMS>
diff --git a/frmts/wms/frmt_wms.html b/frmts/wms/frmt_wms.html
index 974863d..f2924d6 100644
--- a/frmts/wms/frmt_wms.html
+++ b/frmts/wms/frmt_wms.html
@@ -30,14 +30,14 @@
 		</tr>
 		<tr>
 			<td class="xml">    <Service name="<span class="value">WMS</span>"></td>
-			<td class="desc">Define what mini-driver to use, currently supported are: WMS, WorldWind, TileService, TMS. (required)</td>
+			<td class="desc">Define what mini-driver to use, currently supported are: WMS, WorldWind, TileService, TMS, TiledWMS or VirtualEarth. (required)</td>
 		</tr>
 		<tr>
 			<td class="xml">        <Version><span class="value">1.1.1</span></Version></td>
 			<td class="desc">WMS version. (optional, defaults to 1.1.1)</td>
 		</tr>
 		<tr>
-			<td class="xml">        <ServerURL><span class="value">http://onearth.jpl.nasa.gov/wms.cgi?</span></ServerUrl></td>
+			<td class="xml">        <ServerUrl><span class="value">http://onearth.jpl.nasa.gov/wms.cgi?</span></ServerUrl></td>
 			<td class="desc">WMS server URL. (required)</td>
 		</tr>
 		<tr>
@@ -58,8 +58,12 @@
         </tr>
 		<tr>
 			<td class="xml">        <Layers><span class="value">modis,global_mosaic</span></Layers></td>
-			<td class="desc">Comma separated list of layers. (required)</td>
+			<td class="desc">Comma separated list of layers. (required, except for TiledWMS)</td>
 		</tr>
+        <tr>
+            <td class="xml">        <TiledGroupName><span class="value">Clementine</span></TiledGroupName></td>
+            <td class="desc">Comma separated list of layers. (required for TiledWMS)</td>
+        </tr>
 		<tr>
 			<td class="xml">        <Styles></Styles></td>
 			<td class="desc">Comma separated list of styles. (optional)</td>
@@ -76,23 +80,23 @@
 		</tr>
 		<tr>
 			<td class="xml">    <DataWindow></td>
-			<td class="desc">Define size and extents of the data. (required)</td>
+			<td class="desc">Define size and extents of the data. (required, except for TiledWMS and VirtualEarth)</td>
 		</tr>
 		<tr>
 			<td class="xml">        <UpperLeftX><span class="value">-180.0</span></UpperLeftX></td>
-			<td class="desc">X (longitude) coordinate of upper-left corner. (optional, defaults to -180.0)</td>
+			<td class="desc">X (longitude) coordinate of upper-left corner. (optional, defaults to -180.0, except for VirtualEarth)</td>
 		</tr>
 		<tr>
 			<td class="xml">        <UpperLeftY><span class="value">90.0</span></UpperLeftY></td>
-			<td class="desc">Y (latitude) coordinate of upper-left corner. (optional, defaults to 90.0)</td>
+			<td class="desc">Y (latitude) coordinate of upper-left corner. (optional, defaults to 90.0, except for VirtualEarth)</td>
 		</tr>
 		<tr>
 			<td class="xml">        <LowerRightX><span class="value">180.0</span></LowerRightX></td>
-			<td class="desc">X (longitude) coordinate of lower-right corner. (optional, defaults to 180.0)</td>
+			<td class="desc">X (longitude) coordinate of lower-right corner. (optional, defaults to 180.0, except for VirtualEarth)</td>
 		</tr>
 		<tr>
 			<td class="xml">        <LowerRightY><span class="value">-90.0</span></LowerRightY></td>
-			<td class="desc">Y (latitude) coordinate of lower-right corner. (optional, defaults to -90.0)</td>
+			<td class="desc">Y (latitude) coordinate of lower-right corner. (optional, defaults to -90.0, except for VirtualEarth)</td>
 		</tr>
 		<tr>
 			<td class="xml">        <SizeX><span class="value">2666666</span></SizeX></td>
@@ -140,11 +144,11 @@
 		</tr>
 		<tr>
 			<td class="xml">    <BlockSizeX><span class="value">1024</span></BlockSizeX></td>
-			<td class="desc">Block size in pixels. (optional, defaults to 1024)</td>
+			<td class="desc">Block size in pixels. (optional, defaults to 1024, except for VirtualEarth)</td>
 		</tr>
 		<tr>
 			<td class="xml">    <BlockSizeY><span class="value">1024</span></BlockSizeY></td>
-			<td class="desc">Block size in pixels. (optional, defaults to 1024)</td>
+			<td class="desc">Block size in pixels. (optional, defaults to 1024, except for VirtualEarth)</td>
 		</tr>
 		<tr>
 			<td class="xml">    <OverviewCount><span class="value">10</span></OverviewCount></td>
@@ -198,6 +202,18 @@
 			<td class="xml">    <UserAgent><span class="value">GDAL WMS driver (http://www.gdal.org/frmt_wms.html)</span></UserAgent></td>
 			<td class="desc">HTTP User-agent string. Some servers might require a well-known user-agent such as "Mozilla/5.0" (optional, defaults to "GDAL WMS driver (http://www.gdal.org/frmt_wms.html)"). Added in GDAL 1.8.0</td>
 		</tr>
+        <tr>
+            <td class="xml">    <Referer><span class="value">http://example.foo/</span></Referer></td>
+            <td class="desc">HTTP Referer string. Some servers might require it (optional). Added in GDAL 1.9.0</td>
+        </tr>
+		<tr>
+			<td class="xml">    <ZeroBlockHttpCodes><span class="value">204,404</span></ZeroBlockHttpCodes></td>
+			<td class="desc">Comma separated list of HTTP response codes that will be interpreted as a 0 filled image (i.e. black for 3 bands, and transparent for 4 bands) instead of aborting the request. Added in GDAL 1.9.0. (optional, defaults to 204)</td>
+		</tr>
+		<tr>
+			<td class="xml">    <ZeroBlockOnServerException><span class="value">true</span></ZeroBlockOnServerException></td>
+			<td class="desc">Wether to treat a Service Exception returned by the server as a 0 filled image instead of aborting the request. Added in 1.9.0. (optional, defaults to false)</td>
+		</tr>
 		<tr>
 			<td class="xml"></GDAL_WMS></td>
 			<td class="desc"></td>
@@ -271,17 +287,56 @@
   Two examples of usage of the TMS service are included in the examples below.
 </p>  
 
+<h3>OnEarth Tiled WMS (GDAL 1.9.0 and later)</h3>
+<p>
+The OnEarth Tiled WMS minidriver supports the Tiled WMS specification
+implemented for the JPL OnEarth driver per the specification at
+<a href="http://onearth.jpl.nasa.gov/tiled.html">http://onearth.jpl.nasa.gov/tiled.html</a>.<p>
+
+A typical OnEarth Tiled WMS configuration file might look like:
+
+<pre>
+<GDAL_WMS>
+    <Service name="TiledWMS">
+	<ServerUrl>http://onmoon.jpl.nasa.gov/wms.cgi?</ServerUrl>
+	<TiledGroupName>Clementine</TiledGroupName>
+    </Service>
+</GDAL_WMS>
+</pre>
+
+Most of the other information is automatically fetched from the remote
+server using the GetTileService method at open time. <p>
+
+<h3>VirtualEarth (GDAL 1.9.0 and later)</h3>
+<p>
+Access to web-based Virtual Earth tile services. Access is always tile based.<p>
+<p>The ${quadkey} variable must be found in the ServerUrl element.<p>
+<p>The DataWindow element might be omitted. The default values are :
+<ul>
+<li>UpperLeftX = -20037508.34</li>
+<li>UpperLeftY = 20037508.34</li>
+<li>LowerRightX = 20037508.34</li>
+<li>LowerRightY = -20037508.34</li>
+<li>TileLevel = 19</li>
+<li>OverviewCount = 18</li>
+<li>SRS = EPSG:900913</li>
+<li>BlockSizeX = 256</li>
+<li>BlockSizeY = 256</li>
+</ul>
+</p> 
+
 <h2>Examples</h2>
 
 <ul>
-    <li>
+    <li><p>
 	<a href="frmt_wms_onearth_global_mosaic.xml">onearth_global_mosaic.xml</a> - Landsat mosaic from a <a href="http://onearth.jpl.nasa.gov/">OnEarth</a> WMS server<br>
 	<pre>gdal_translate -of JPEG -outsize 500 250 onearth_global_mosaic.xml onearth_global_mosaic.jpg</pre>
 	<img src="http://sydney.freeearthfoundation.com/gdalwms/onearth_global_mosaic.jpg" alt="example output">
 	<pre>gdal_translate -of JPEG -projwin -10 55 30 35 -outsize 500 250 onearth_global_mosaic.xml onearth_global_mosaic2.jpg</pre>
 	<img src="http://sydney.freeearthfoundation.com/gdalwms/onearth_global_mosaic2.jpg" alt="example output">
-    </li>
-    <li>
+    </p></li>
+
+    <li><p>
 	<a href="frmt_wms_metacarta_wmsc.xml">metacarta_wmsc.xml</a> - 
 	It is possible to configure a WMS Service conforming to a WMS-C cache by
 	specifying a number of overviews and specifying the 'block size' as the 
@@ -289,34 +344,101 @@
 	a 19-level "Global Profile" WMS-C cache.
 	<pre>gdal_translate -of PNG -outsize 500 250 metacarta_wmsc.xml metacarta_wmsc.png</pre>
 	<img src="http://sydney.freeearthfoundation.com/gdalwms/metacarta_wmsc.png" alt="example output">
-    </li>
-    <li>
+    </p></li>
+
+    <li><p>
 	<a href="frmt_wms_tileservice_bmng.xml">tileservice_bmng.xml</a> - TileService, Blue Marble NG (January)<br>
 	<pre>gdal_translate -of JPEG -outsize 500 250 tileservice_bmng.xml tileservice_bmng.jpg</pre>
 	<img src="http://sydney.freeearthfoundation.com/gdalwms/tileservice_bmng.jpg" alt="example output">
-    </li>
-    <li>
+    </p></li>
+
+    <li><p>
 	<a href="frmt_wms_tileservice_nysdop2004.xml">tileservice_nysdop2004.xml</a> - TileService, NYSDOP 2004<br>
 	<pre>gdal_translate -of JPEG -projwin -73.687030 41.262680 -73.686359 41.262345 -outsize 500 250 tileservice_nysdop2004.xml tileservice_nysdop2004.jpg</pre>
 	<img src="http://sydney.freeearthfoundation.com/gdalwms/tileservice_nysdop2004.jpg" alt="example output">
-    </li>
-    <li>
+    </p></li>
+
+    <li><p>
      <a href="frmt_wms_openstreetmap_tms.xml">OpenStreetMap TMS Service Example</a>: Connect to OpenStreetMap tile service. Note that this file takes advantage of the tile cache; more information about configuring the tile cache settings is available above.<br />
      <tt>gdal_translate -of PNG -outsize 512 512 frmt_wms_openstreetmap_tms.xml openstreetmap.png</tt>
-    </li>
+    </p></li>
 
-    <li>
+    <li><p>
      <a href="frmt_wms_metacarta_tms.xml">MetaCarta TMS Layer Example</a>, accessing the default MetaCarta TMS layer.<br />
           <tt>gdal_translate -of PNG -outsize 512 256 frmt_wms_metacarta_tms.xml metacarta.png</tt>
-    </li>
+    </p></li>
+
+    <li><p>
+     <a href="frmt_wms_bluemarble_s3_tms.xml">BlueMarble Amazon S3 Example</a> accessed with the TMS minidriver.
+    </p></li>
+
+    <li><p>
+     <a href="frmt_wms_googlemaps_tms.xml">Google Maps</a> accessed with the TMS minidriver.
+    </p></li>
+
+    <li><p>
+     <a href="frmt_wms_arcgis_mapserver_tms.xml">ArcGIS MapServer Tiles</a> accessed with the TMS minidriver.
+    </p></li>
+
+    <li><p>
+     <a href="frmt_wms_swissgeo_tms.xml">Swiss Geoportal maps</a> accessed with the TMS minidriver (needs GDAL >= 1.9.0)
+    </p></li>
+
+    <li><p>
+     OnEarth Tiled WMS <a href="frmt_twms_Clementine.xml">Clementine</a>,
+     <a href="frmt_twms_daily.xml">daily</a>, and
+     <a href="frmt_twms_srtm.xml">srtm</a> examples.<p>
+    </p></li>
+
+    <li><p>
+     <a href="frmt_wms_virtualearth.xml">VirtualEarth Aerial Layer</a> accessed with the VirtualEarth minidriver.
+    </p></li>
+</ul>
+
+<h2>Open syntax</h2>
+
+The WMS driver can open :
+<ul>
+<li><p>
+a local service description XML file : <pre>gdalinfo description_file.xml</pre>
+</p></li>
+
+<li><p>
+the content of a description XML file provided as filename :
+<pre>gdalinfo "<GDAL_WMS><Service name=\"TiledWMS\"><ServerUrl>http://onearth.jpl.nasa.gov/wms.cgi?</ServerUrl><TiledGroupName>Global SRTM Elevation</TiledGroupName></Service></GDAL_WMS>"</pre>
+</p></li>
+
+<li><p>
+(GDAL >= 1.9.0) the base URL of a WMS service, prefixed with <i>WMS:</i> :
+<pre>gdalinfo "WMS:http://wms.geobase.ca/wms-bin/cubeserv.cgi"</pre><p>
+A list of subdatasets will be returned, resulting from the parsing of the GetCapabilities request on that server.
+</p></li>
+
+<li><p>
+(GDAL >= 1.9.0) a pseudo GetMap request, such as the subdataset name returned by the previous syntax :
+<pre>gdalinfo "WMS:http://wms.geobase.ca/wms-bin/cubeserv.cgi?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=DNEC_250K:ELEVATION/ELEVATION&SRS=EPSG:42304&BBOX=-3000000,-1500000,6000000,4500000"</pre>
+</p></li>
+
+<li><p>
+(GDAL >= 1.9.0) the base URL of a Tiled WMS service, prefixed with <i>WMS:</i> and with request=GetTileService as GET argument:
+<pre>gdalinfo "WMS:http://onearth.jpl.nasa.gov/wms.cgi?request=GetTileService"</pre><p>
+A list of subdatasets will be returned, resulting from the parsing of the GetTileService request on that server.
+</p></li>
+
+<li><p>
+(GDAL >= 1.9.0) the URL of a REST definition for a ArcGIS MapServer:
+<pre>gdalinfo "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer?f=json&pretty=true"</pre><p>
+</p></li>
 </ul>
 
-<p>See Also:</p>
+<h2>See Also:</h2>
 
 <ul>
 <li><a href="http://www.opengeospatial.org/standards/wms">OGC WMS Standards</a></li>
-<li><a href="http://wiki.osgeo.org/index.php/WMS_Tiling_Client_Recommendation">WMS Tiling Client Recommendation</a></li>
-<li><a href="http://www.worldwindcentral.com/wiki/TileService">TileService</a></li>
+<li><a href="http://wiki.osgeo.org/index.php/WMS_Tiling_Client_Recommendation">WMS Tiling Client Recommendation (WMS-C)</a></li>
+<li><a href="http://www.worldwindcentral.com/wiki/TileService">WorldWind TileService</a></li>
+<li><a href="http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification">TMS Specification</a></li>
+<li><a href="http://onearth.jpl.nasa.gov/tiled.html">OnEarth Tiled WMS specification</a></li>
 </ul>
 
 </body>
diff --git a/frmts/wms/frmt_wms_arcgis_mapserver_tms.xml b/frmts/wms/frmt_wms_arcgis_mapserver_tms.xml
new file mode 100644
index 0000000..dd4d9d3
--- /dev/null
+++ b/frmts/wms/frmt_wms_arcgis_mapserver_tms.xml
@@ -0,0 +1,21 @@
+<GDAL_WMS>
+    <Service name="TMS">
+        <ServerUrl>http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/${z}/${y}/${x}</ServerUrl>>
+    </Service>
+    <DataWindow>
+        <UpperLeftX>-20037508.34</UpperLeftX>
+        <UpperLeftY>20037508.34</UpperLeftY>
+        <LowerRightX>20037508.34</LowerRightX>
+        <LowerRightY>-20037508.34</LowerRightY>
+        <TileLevel>17</TileLevel>
+        <TileCountX>1</TileCountX>
+        <TileCountY>1</TileCountY>
+        <YOrigin>top</YOrigin>
+    </DataWindow>
+    <Projection>EPSG:900913</Projection>
+    <BlockSizeX>256</BlockSizeX>
+    <BlockSizeY>256</BlockSizeY>
+    <BandsCount>3</BandsCount>
+    <MaxConnections>10</MaxConnections>
+    <Cache />
+</GDAL_WMS>
diff --git a/frmts/wms/frmt_wms_bluemarble_s3_tms.xml b/frmts/wms/frmt_wms_bluemarble_s3_tms.xml
new file mode 100644
index 0000000..eea12a4
--- /dev/null
+++ b/frmts/wms/frmt_wms_bluemarble_s3_tms.xml
@@ -0,0 +1,20 @@
+<GDAL_WMS>
+  <Service name="TMS">
+    <ServerUrl>http://s3.amazonaws.com/com.modestmaps.bluemarble/${z}-r${y}-c${x}.jpg</ServerUrl>
+  </Service>
+  <DataWindow>
+    <UpperLeftX>-20037508.34</UpperLeftX>
+    <UpperLeftY>20037508.34</UpperLeftY>
+    <LowerRightX>20037508.34</LowerRightX>
+    <LowerRightY>-20037508.34</LowerRightY>
+    <TileLevel>9</TileLevel>
+    <TileCountX>1</TileCountX>
+    <TileCountY>1</TileCountY>
+    <YOrigin>top</YOrigin>
+  </DataWindow>
+  <Projection>EPSG:900913</Projection>
+  <BlockSizeX>256</BlockSizeX>
+  <BlockSizeY>256</BlockSizeY>
+  <BandsCount>3</BandsCount>
+  <Cache/>
+</GDAL_WMS>
diff --git a/frmts/wms/frmt_wms_googlemaps_tms.xml b/frmts/wms/frmt_wms_googlemaps_tms.xml
new file mode 100644
index 0000000..64b2fd2
--- /dev/null
+++ b/frmts/wms/frmt_wms_googlemaps_tms.xml
@@ -0,0 +1,29 @@
+<GDAL_WMS>
+
+<!-- Data is subject to term of use detailed at http://code.google.com/intl/nl/apis/maps/terms.html and
+     http://www.google.com/intl/en_ALL/help/terms_maps.html -->
+
+    <Service name="TMS">
+        <ServerUrl>http://mt.google.com/vt/lyrs=m&x=${x}&y=${y}&z=${z}</ServerUrl> <!-- Map -->
+        <!-- <ServerUrl>http://mt.google.com/vt/lyrs=s&x=${x}&y=${y}&z=${z}</ServerUrl> --> <!-- Satellite -->
+        <!-- <ServerUrl>http://mt.google.com/vt/lyrs=y&x=${x}&y=${y}&z=${z}</ServerUrl> --> <!-- Hybrid -->
+        <!-- <ServerUrl>http://mt.google.com/vt/lyrs=t&x=${x}&y=${y}&z=${z}</ServerUrl> --> <!-- Terrain -->
+        <!-- <ServerUrl>http://mt.google.com/vt/lyrs=p&x=${x}&y=${y}&z=${z}</ServerUrl> --> <!-- Terrain, Streets and Water  -->
+    </Service>
+    <DataWindow>
+        <UpperLeftX>-20037508.34</UpperLeftX>
+        <UpperLeftY>20037508.34</UpperLeftY>
+        <LowerRightX>20037508.34</LowerRightX>
+        <LowerRightY>-20037508.34</LowerRightY>
+        <TileLevel>20</TileLevel>
+        <TileCountX>1</TileCountX>
+        <TileCountY>1</TileCountY>
+        <YOrigin>top</YOrigin>
+    </DataWindow>
+    <Projection>EPSG:900913</Projection>
+    <BlockSizeX>256</BlockSizeX>
+    <BlockSizeY>256</BlockSizeY>
+    <BandsCount>3</BandsCount>
+    <MaxConnections>5</MaxConnections>
+    <Cache />
+</GDAL_WMS>
diff --git a/frmts/wms/frmt_wms_openstreetmap_tms.xml b/frmts/wms/frmt_wms_openstreetmap_tms.xml
index 82b2144..3c197a0 100644
--- a/frmts/wms/frmt_wms_openstreetmap_tms.xml
+++ b/frmts/wms/frmt_wms_openstreetmap_tms.xml
@@ -7,9 +7,9 @@
         <UpperLeftY>20037508.34</UpperLeftY>
         <LowerRightX>20037508.34</LowerRightX>
         <LowerRightY>-20037508.34</LowerRightY>
-        <TileLevel>19</TileLevel>
-	<TileCountX>1</TileCountX>
-	<TileCountY>1</TileCountY>
+        <TileLevel>18</TileLevel>
+        <TileCountX>1</TileCountX>
+        <TileCountY>1</TileCountY>
         <YOrigin>top</YOrigin>
     </DataWindow>
     <Projection>EPSG:900913</Projection>
diff --git a/frmts/wms/frmt_wms_swissgeo_tms.xml b/frmts/wms/frmt_wms_swissgeo_tms.xml
new file mode 100644
index 0000000..afb750a
--- /dev/null
+++ b/frmts/wms/frmt_wms_swissgeo_tms.xml
@@ -0,0 +1,34 @@
+<GDAL_WMS>
+
+<!-- Caution : currently the georeferencing only works properly for the lowest-resolution level (base band).
+     Some overviews levels are not exactly at half resolution of the neighbouring overview level, and
+     the extent might also be slightly different... -->
+
+<!-- Do not open this file as such in a GUI like QGIS since the smallest overview for now is 48000x32000 !,
+     which means that it would need to fetch thousands and thousands of tiles...
+     or alter the <OverviewCount> to be 8. But in which case the above warning will apply. -->
+
+<!-- Data is subject to term of use detailed at http://www.geo.admin.ch/internet/geoportal/en/home/geoadmin/contact.html#copyright -->
+
+    <Service name="TMS">
+        <ServerUrl>http://tile8.geo.admin.ch/geoadmin/ch.swisstopo.pixelkarte-farbe/${z}/${xxx}/${yyy}.jpeg</ServerUrl>
+    </Service>
+    <DataWindow>
+        <UpperLeftX>420000</UpperLeftX>
+        <UpperLeftY>350000</UpperLeftY>
+        <LowerRightX>900000</LowerRightX>
+        <LowerRightY>30000</LowerRightY>
+        <SizeX>192000</SizeX>
+        <SizeY>128000</SizeY>
+        <TileLevel>22</TileLevel>
+        <YOrigin>bottom</YOrigin>
+    </DataWindow>
+    <Projection>EPSG:21781</Projection>
+    <OverviewCount>2</OverviewCount>
+    <BlockSizeX>256</BlockSizeX>
+    <BlockSizeY>256</BlockSizeY>
+    <BandsCount>3</BandsCount>
+    <Cache />
+    <UserAgent>Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110312 Gentoo Firefox/3.6.15</UserAgent>
+    <Referer>http://map.geo.admin.ch/?lang=en</Referer>
+</GDAL_WMS>
diff --git a/frmts/wms/frmt_wms_virtualearth.xml b/frmts/wms/frmt_wms_virtualearth.xml
new file mode 100644
index 0000000..0e566bb
--- /dev/null
+++ b/frmts/wms/frmt_wms_virtualearth.xml
@@ -0,0 +1,7 @@
+<GDAL_WMS>
+  <Service name="VirtualEarth">
+    <ServerUrl>http://a${server_num}.ortho.tiles.virtualearth.net/tiles/a${quadkey}.jpeg?g=90</ServerUrl>
+  </Service>
+  <MaxConnections>4</MaxConnections>
+  <Cache/>
+</GDAL_WMS>
diff --git a/frmts/wms/gdalhttp.cpp b/frmts/wms/gdalhttp.cpp
index 481cc2e..22d64f5 100644
--- a/frmts/wms/gdalhttp.cpp
+++ b/frmts/wms/gdalhttp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalhttp.cpp 21304 2010-12-21 09:44:03Z nowakpl $
+ * $Id: gdalhttp.cpp 22007 2011-03-21 20:44:14Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -87,6 +87,11 @@ void CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL, con
         pszUserAgent = "GDAL WMS driver (http://www.gdal.org/frmt_wms.html)";
     curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_USERAGENT, pszUserAgent);
 
+    /* Set Referer */
+    const char *pszReferer = CSLFetchNameValue(const_cast<char **>(psRequest->papszOptions), "REFERER");
+    if (pszReferer != NULL)
+        curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_REFERER, pszReferer);
+
     /* Set URL */
     curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_URL, psRequest->pszURL);
 
@@ -252,9 +257,17 @@ CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const ch
         if ((psRequest->pszError == NULL) && (psRequest->m_curl_error != NULL) && (psRequest->m_curl_error[0] != '\0')) {
             psRequest->pszError = CPLStrdup(psRequest->m_curl_error);
         }
-        
+
+        /* In the case of a file:// URL, curl will return a status == 0, so if there's no */
+        /* error returned, patch the status code to be 200, as it would be for http:// */
+        if (strncmp(psRequest->pszURL, "file://", 7) == 0 && psRequest->nStatus == 0 &&
+            psRequest->pszError == NULL)
+        {
+            psRequest->nStatus = 200;
+        }
+
         CPLDebug("HTTP", "Request [%d] %s : status = %d, content type = %s, error = %s",
-                 conn_i, psRequest->pszURL, psRequest->nStatus,
+                 i, psRequest->pszURL, psRequest->nStatus,
                  (psRequest->pszContentType) ? psRequest->pszContentType : "(null)",
                  (psRequest->pszError) ? psRequest->pszError : "(null)");
 
diff --git a/frmts/wms/makefile.vc b/frmts/wms/makefile.vc
index afbec75..620f2eb 100644
--- a/frmts/wms/makefile.vc
+++ b/frmts/wms/makefile.vc
@@ -1,6 +1,7 @@
 
 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_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/md5.cpp b/frmts/wms/md5.cpp
index 427527e..63dc7e1 100644
--- a/frmts/wms/md5.cpp
+++ b/frmts/wms/md5.cpp
@@ -28,6 +28,11 @@ with libraries such as some versions of Kerberos.  No particular
 need to worry about whether the system supplies an MD5 library, as
 this file is only about 3k of object code.  */
 
+/* Modified by E. Rouault, to fix :
+   warning: argument to 'sizeof' in 'memset' call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess]
+        memset(ctx, 0, sizeof(ctx)); */   /* In case it's sensitive */
+/* at the end of cvs_MD5Final */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -172,7 +177,7 @@ struct cvs_MD5Context *ctx)
     putu32(ctx->buf[1], digest + 4);
     putu32(ctx->buf[2], digest + 8);
     putu32(ctx->buf[3], digest + 12);
-    memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
+    memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
 }
 
 #ifndef ASM_MD5
diff --git a/frmts/wms/minidriver.cpp b/frmts/wms/minidriver.cpp
index f7d2926..fdb6515 100644
--- a/frmts/wms/minidriver.cpp
+++ b/frmts/wms/minidriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver.cpp 18020 2009-11-14 14:33:20Z rouault $
+ * $Id: minidriver.cpp 21702 2011-02-13 01:30:30Z warmerdam $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -64,9 +64,9 @@ GDALWMSMiniDriverFactory::~GDALWMSMiniDriverFactory() {
 }
 
 GDALWMSMiniDriverManager *GetGDALWMSMiniDriverManager() {
-    if (g_mini_driver_manager == 0) {
+    if (g_mini_driver_manager == NULL) {
         CPLMutexHolderD(&g_mini_driver_manager_mutex);
-        if (g_mini_driver_manager == 0) {
+        if (g_mini_driver_manager == NULL) {
             g_mini_driver_manager = new GDALWMSMiniDriverManager();
         }
         CPLAssert(g_mini_driver_manager != NULL);
diff --git a/frmts/wms/minidriver_tiled_wms.cpp b/frmts/wms/minidriver_tiled_wms.cpp
new file mode 100644
index 0000000..18e9c35
--- /dev/null
+++ b/frmts/wms/minidriver_tiled_wms.cpp
@@ -0,0 +1,539 @@
+/******************************************************************************
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Implementation of the OnEarth Tiled WMS minidriver.
+ *           http://onearth.jpl.nasa.gov/tiled.html
+ * Author:   Lucian Plesea (Lucian dot Pleasea at jpl.nasa.gov)
+ *           Adam Nowacki
+ *
+ ******************************************************************************
+ * 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"
+
+CPP_GDALWMSMiniDriverFactory(TiledWMS)
+
+/************************************************************************/
+/*                           SearchXMLSiblings()                        */
+/************************************************************************/
+
+/*
+ * \brief Search for a sibling of the root node with a given name.
+ *
+ * Searches only the next siblings of the node passed in for the named element or attribute.
+ * If the first character of the pszElement is '=', the search includes the psRoot node
+ * 
+ * @param psRoot the root node to search.  This should be a node of type
+ * CXT_Element.  NULL is safe.
+ *
+ * @param pszElement the name of the element or attribute to search for.
+ *
+ *
+ * @return The first matching node or NULL on failure. 
+ */
+
+static CPLXMLNode *SearchXMLSiblings( CPLXMLNode *psRoot, const char *pszElement )
+
+{
+    if( psRoot == NULL || pszElement == NULL )
+        return NULL;
+
+    // If the strings starts with '=', include the current node
+    if (pszElement[0]=='=') {
+	if (EQUAL(psRoot->pszValue,pszElement+1))
+	    return psRoot;
+	else return SearchXMLSiblings(psRoot,pszElement+1);
+    }
+
+    // Only search the siblings, starting with psRoot->psNext
+    for (psRoot=psRoot->psNext;psRoot!=NULL;psRoot=psRoot->psNext) {
+	if ( (psRoot->eType == CXT_Element ||
+              psRoot->eType == CXT_Attribute)
+	     && EQUAL(pszElement,psRoot->pszValue) )
+            return psRoot;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                        SearchLeafGroupName()                         */
+/************************************************************************/
+
+/*
+ * \brief Search for a leaf TileGroup node by name.
+ *
+ * @param psRoot the root node to search.  This should be a node of type
+ * CXT_Element.  NULL is safe.
+ *
+ * @param pszElement the name of the TileGroup to search for.
+ *
+ * @return The XML node of the matching TileGroup or NULL on failure.
+ */
+
+static CPLXMLNode *SearchLeafGroupName( CPLXMLNode *psRoot, const char *name )
+
+{
+    CPLXMLNode *ret=NULL;
+
+    if( psRoot == NULL || name == NULL ) return NULL;
+
+    // Has to be a leaf TileGroup with the right name
+    if (NULL==CPLSearchXMLNode(psRoot->psChild,"=TiledGroup"))
+    {
+        if (EQUAL(name,CPLGetXMLValue(psRoot,"Name","")))
+        {
+            return psRoot;
+        }
+        else
+        { // Try a sibling
+            return SearchLeafGroupName(psRoot->psNext,name);
+        }
+    }
+    else
+    { // Is metagroup, try children then siblings
+        ret=SearchLeafGroupName(psRoot->psChild,name);
+        if (NULL!=ret) return ret;
+        return SearchLeafGroupName(psRoot->psNext,name);
+    }
+}
+
+/************************************************************************/
+/*                             BandInterp()                             */
+/************************************************************************/
+
+/*
+ * \brief Utility function to calculate color band interpretation.
+ * Only handles Gray, GrayAlpha, RGB and RGBA, based on total band count
+ *
+ * @param nbands is the total number of bands in the image
+ *
+ * @param band is the band number, starting with 1
+ *
+ * @return GDALColorInterp of the band
+ */
+
+static GDALColorInterp BandInterp(int nbands, int band) {
+    switch (nbands) {
+      case 1: return GCI_GrayIndex;
+      case 2: return ((band==1)?GCI_GrayIndex:GCI_AlphaBand);
+      case 3: // RGB
+      case 4: // RBGA
+        if (band<3)
+            return ((band==1)?GCI_RedBand:GCI_GreenBand);
+        return ((band==3)?GCI_BlueBand:GCI_AlphaBand);
+      default:
+        return GCI_Undefined;
+    }
+}
+
+/************************************************************************/
+/*                              FindBbox()                              */
+/************************************************************************/
+
+/*
+ * \brief Utility function to find the position of the bbox parameter value 
+ * within a request string.  The search for the bbox is case insensitive
+ *
+ * @param in, the string to search into
+ *
+ * @return The position from the begining of the string or -1 if not found
+ */
+
+static int FindBbox(CPLString in) {
+
+    size_t pos = in.ifind("&bbox=");
+    if (pos == std::string::npos)
+        return -1;
+    else
+        return (int)pos + 6;
+}
+
+/************************************************************************/
+/*                         FindChangePattern()                          */
+/************************************************************************/
+
+/*
+ * \brief Utility function to pick the right request pattern based on
+ * the change request list
+ *
+ * @param cdata, the list of possible requests, white space separated
+ * @param substs, the list of substitutions
+ * @param ret The best match request
+ */
+
+void FindChangePattern( char *cdata,char **substs, CPLString &ret) {
+    char **papszTokens=CSLTokenizeString2(cdata," \t\n\r",
+                                          CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
+
+    int matchcount=CSLCount(substs);
+    for (int j=0;j<CSLCount(papszTokens);j++)
+    {
+        int thiscount=0;
+        CPLString this_string=papszTokens[j];
+        for (int i=0;i<matchcount;i++) {
+            char *key = NULL;
+            CPLParseNameValue(substs[i],&key);
+            if (key)
+            {
+                if (std::string::npos!=this_string.find(key,0))
+                    thiscount++;
+                CPLFree(key);
+            }
+        }
+        if (thiscount==matchcount) {
+            ret=papszTokens[j];
+            break;
+        }
+    }
+
+    // if no match is found, return first string
+    if (ret.empty()) ret=papszTokens[0];
+    CSLDestroy(papszTokens);
+}
+
+GDALWMSMiniDriver_TiledWMS::GDALWMSMiniDriver_TiledWMS() {
+    m_requests = NULL;
+    m_substs = NULL;
+}
+
+GDALWMSMiniDriver_TiledWMS::~GDALWMSMiniDriver_TiledWMS() {
+    CSLDestroy(m_requests);
+    CSLDestroy(m_substs);
+}
+
+
+// Returns the scale of a WMS request as compared to the base resolution
+double GDALWMSMiniDriver_TiledWMS::Scale(const char *request) {
+    int bbox=FindBbox(request);
+    if (bbox<0) return 0;
+    double x,y,X,Y;
+    sscanf(request+bbox,"%lf,%lf,%lf,%lf",&x,&y,&X,&Y);
+    return (m_data_window.m_x1-m_data_window.m_x0)/(X-x)*m_bsx/m_data_window.m_sx;
+}
+
+
+// Finds, extracts, and returns the highest resolution request string from a list, starting at item i
+void GDALWMSMiniDriver_TiledWMS::GetLowestScale(char **& list,int i, CPLString &req) {
+    req="";
+    double scale=-1;
+    int position=-1;
+    while (NULL!=list[i]) {
+	double tscale=Scale(list[i]);
+	if (tscale>=scale) {
+	    scale=tscale;
+	    position=i;
+	}
+	i++;
+    }
+    if (position>-1) {
+        req=list[position];
+        list = CSLRemoveStrings(list,position,1,NULL);
+    }
+}
+
+
+CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config) {
+    CPLErr ret = CE_None;
+    CPLXMLNode *tileServiceConfig=NULL;
+    CPLHTTPResult *psResult=NULL;
+    CPLXMLNode *TG=NULL;
+
+    char **requests=NULL;
+    char **substs=NULL;
+
+    for (int once=1;once;once--) { // Something to break out of
+        // Parse info from the service
+
+        m_end_url = CPLGetXMLValue(config,"AdditionalArgs","");
+        m_base_url = CPLGetXMLValue(config, "ServerURL", "");
+        if (m_base_url.empty()) {
+            CPLError(ret=CE_Failure, CPLE_AppDefined, "GDALWMS, WMS mini-driver: ServerURL missing.");
+            break;
+        }
+
+        m_tiledGroupName = CPLGetXMLValue(config, "TiledGroupName", "");
+        if (m_tiledGroupName.empty()) {
+            CPLError(ret=CE_Failure, CPLE_AppDefined, "GDALWMS, Tiled WMS: TiledGroupName missing.");
+            break;
+        }
+
+        // Change strings, key is an attribute, value is the value of the Change node
+        // Multiple substitutions are possible
+        TG=CPLSearchXMLNode(config, "Change");
+        while(TG!=NULL) {
+            CPLString name=CPLGetXMLValue(TG,"key","");
+            if (!name.empty()) {
+                CPLString value=CPLGetXMLValue(TG,"","");
+                substs=CSLSetNameValue(substs,name,value);
+            } else {
+                CPLError(ret=CE_Failure, CPLE_AppDefined, "GDALWMS, Tiled WMS: Syntax error in configuration file.\n"
+                         "Change element needs a non-empty \"key\" attribute");
+                break;
+            }
+            TG=SearchXMLSiblings(TG,"Change");
+        }
+        if (ret!=CE_None) break;
+
+        CPLString getTileServiceUrl = m_base_url + "request=GetTileService";
+        psResult = CPLHTTPFetch(getTileServiceUrl, NULL);
+
+        if (NULL==psResult) {
+            CPLError(ret=CE_Failure, CPLE_AppDefined, 
+                     "GDALWMS, Tiled WMS: Can't use GDAL HTTP, no curl support.");
+            break;
+        }
+
+        if ((psResult->nStatus!=0)||(NULL==psResult->pabyData)||('\0'==psResult->pabyData[0])) {
+            CPLError(ret=CE_Failure, CPLE_AppDefined,
+                     "GDALWMS, Tiled WMS: Can't get server response to GetTileService.");
+            break;
+        }
+
+        if (NULL==(tileServiceConfig=CPLParseXMLString((const char*)psResult->pabyData))) {
+            CPLError(ret=CE_Failure,CPLE_AppDefined, "GDALWMS, Tiled WMS: Error parsing the GetTileService response.");
+            break;
+        }
+    
+        m_base_url=CPLGetXMLValue(tileServiceConfig,"TiledPatterns.OnlineResource.xlink:href","");
+        if (m_base_url.empty()) {
+            CPLError(ret=CE_Failure,CPLE_AppDefined, "GDALWMS, Tiled WMS: Can't locate OnlineResource in the server response.");
+            break;
+        }
+    
+        if (NULL==(TG=CPLSearchXMLNode(tileServiceConfig, "TiledPatterns"))) {
+            CPLError(ret=CE_Failure,CPLE_AppDefined, 
+                     "GDALWMS, Tiled WMS: Can't locate TiledPatterns in server response.");
+            break;
+        }
+    
+        if (NULL==(TG=SearchLeafGroupName(TG->psChild,m_tiledGroupName))) {
+            CPLError(ret=CE_Failure,CPLE_AppDefined,
+                     "GDALWMS, Tiled WMS: Can't locate TiledGroup in server response.");
+            break;
+        }
+
+        if (0>(m_bands_count=atoi(CPLGetXMLValue(TG, "Bands", "3")))) {
+            CPLError(ret=CE_Failure,CPLE_AppDefined,
+                     "GDALWMS, Tiled WMS: Invalid number of bands in server response");
+            break;
+        }
+        if (!GDALCheckBandCount(m_bands_count, FALSE))
+        {
+            ret = CE_Failure;
+            break;
+        }
+
+        m_parent_dataset->WMSSetBandsCount(m_bands_count);
+        m_parent_dataset->WMSSetDataType(GDALGetDataTypeByName(CPLGetXMLValue(TG, "DataType", "Byte")));
+        m_projection_wkt=CPLGetXMLValue(TG, "Projection","");
+
+        // Bounding box for the group itself
+        CPLXMLNode *latlonbbox = CPLSearchXMLNode(TG, "LatLonBoundingBox");
+        if (NULL==latlonbbox) {
+            CPLError(ret=CE_Failure,CPLE_AppDefined,
+                     "GDALWMS, Tiled WMS: Can't locate the LatLonBoundingBox in server response.");
+            break;
+        }
+
+        m_data_window.m_x0=atof(CPLGetXMLValue(latlonbbox,"minx","0"));
+        m_data_window.m_x1=atof(CPLGetXMLValue(latlonbbox,"maxx","-1"));
+        m_data_window.m_y0=atof(CPLGetXMLValue(latlonbbox,"maxy","0"));
+        m_data_window.m_y1=atof(CPLGetXMLValue(latlonbbox,"miny","-1"));
+
+        if ((m_data_window.m_x1-m_data_window.m_x0)<0) {
+            CPLError(ret=CE_Failure,CPLE_AppDefined,
+                     "GDALWMS, Tiled WMS: Coordinate order in boundingbox problem in server response.");
+            break;
+        }
+
+        m_overview_count=0;
+        CPLXMLNode *Pattern=TG->psChild;
+
+        m_bsx=m_bsy=-1;
+        m_data_window.m_sx=m_data_window.m_sy=0;
+
+        for (int once=1;once;once--) { // Something to break out of
+            while ((NULL!=Pattern)&&(NULL!=(Pattern=SearchXMLSiblings(Pattern,"=TilePattern")))) {
+                int mbsx,mbsy;
+
+                CPLString request;
+                FindChangePattern(Pattern->psChild->pszValue,substs,request);
+
+                char **papszTokens=CSLTokenizeString2(request,"&",0);
+
+                mbsx=atoi(CSLFetchNameValue(papszTokens,"WIDTH"));
+                mbsy=atoi(CSLFetchNameValue(papszTokens,"HEIGHT"));
+                if (m_projection_wkt.empty()) {
+                    const char* pszSRS = CSLFetchNameValue(papszTokens,"SRS");
+                    m_projection_wkt = (pszSRS) ? pszSRS : "";
+                    if (!m_projection_wkt.empty())
+                        m_projection_wkt=ProjToWKT(m_projection_wkt);
+                }
+
+                if (-1==m_bsx) m_bsx=mbsx;
+                if (-1==m_bsy) m_bsy=mbsy;
+                if ((m_bsy!=mbsy)||(m_bsy!=mbsy)) {
+                    CPLError(ret=CE_Failure,CPLE_AppDefined,
+                             "GDALWMS, Tiled WMS: Tileset uses different block sizes.");
+                    m_overview_count=0;
+                    CSLDestroy(papszTokens);
+                    break;
+                }
+
+                const char* pszBBOX = CSLFetchNameValue(papszTokens,"BBOX");
+                if (pszBBOX == NULL)
+                {
+                    CPLError(ret=CE_Failure,CPLE_AppDefined,
+                        "GDALWMS, Tiled WMS: BBOX parameter not found in server response.");
+                    CSLDestroy(papszTokens);
+                    break;
+                }
+
+                double x,y,X,Y;
+                if (sscanf(pszBBOX,"%lf,%lf,%lf,%lf",&x,&y,&X,&Y) != 4)
+                {
+                    CPLError(ret=CE_Failure,CPLE_AppDefined,
+                        "GDALWMS, Tiled WMS: Invalid value for BBOX parameter in server response.");
+                    CSLDestroy(papszTokens);
+                    break;
+                }
+                int sx=static_cast<int>((m_data_window.m_x1-m_data_window.m_x0)/(X-x)*m_bsx);
+                int sy=static_cast<int>(fabs((m_data_window.m_y1-m_data_window.m_y0)/(Y-y)*m_bsy));
+                if (sx>m_data_window.m_sx) m_data_window.m_sx=sx;
+                if (sy>m_data_window.m_sy) m_data_window.m_sy=sy;
+                CSLDestroy(papszTokens);
+
+                // Only use overlays where the top coordinate is within a pixel from the top of coverage
+                double pix_off,temp;
+                pix_off=m_bsy*modf(fabs((Y-m_data_window.m_y0)/(Y-y)),&temp);
+                if ((pix_off<1)||((m_bsy-pix_off)<1)) {
+                    requests=CSLAddString(requests,request);
+                    m_overview_count++;
+                } else
+                    CPLError(CE_Warning,CPLE_AppDefined,
+                             "GDALWMS, Tiled WMS: Overlay size %dX%d can't be used due to alignment",sx,sy);
+
+                Pattern=Pattern->psNext;
+
+            }
+
+            // The tlevel is needed, the tx and ty are not used by this minidriver
+            m_data_window.m_tlevel = 0;
+            m_data_window.m_tx = 0;
+            m_data_window.m_ty = 0;
+
+            // Make sure the parent_dataset values are set before creating the bands
+            m_parent_dataset->WMSSetBlockSize(m_bsx,m_bsy);
+            m_parent_dataset->WMSSetRasterSize(m_data_window.m_sx,m_data_window.m_sy);
+
+            m_parent_dataset->WMSSetDataWindow(m_data_window);
+            m_parent_dataset->WMSSetOverviewCount(m_overview_count);
+            m_parent_dataset->WMSSetClamp(false);
+
+            // Ready for the Rasterband creation
+            int i;
+            for (i=0;i<m_overview_count;i++) {
+                CPLString request="";
+                GetLowestScale(requests,i,request);
+                double scale=Scale(request);
+
+                if (i == 0)
+                {
+                    if (fabs(scale-1.0) >1e-6)
+                    {
+                        CPLError(ret=CE_Failure,CPLE_AppDefined,
+                         "GDALWMS, Tiled WMS: Did not get expected scale : %.15f", scale);
+                        break;
+                    }
+                }
+
+                // Prepare the request and insert it back into the list
+                int startBbox=FindBbox(request);
+                int BboxSize=request.find_first_of("&",startBbox);
+                request.replace(startBbox,BboxSize,"${GDAL_BBOX}");
+                requests = CSLInsertString(requests,i,request);
+
+                // Create the Rasterband or overview
+                for (int j = 1; j <= m_bands_count; j++) {
+                    if (i == 0) {
+                        GDALWMSRasterBand *band=new GDALWMSRasterBand(m_parent_dataset, j, scale);
+                        band->SetColorInterpretation(BandInterp(m_bands_count,j));
+                        m_parent_dataset->mSetBand(j, band);
+                    } else
+                        m_parent_dataset->mGetBand(j)->AddOverview(scale);
+                }
+            }
+
+            if (i != m_overview_count)
+                break;
+
+            if ((m_overview_count==0)||(m_bsx<1)||(m_bsy<1)) {
+                CPLError(ret=CE_Failure,CPLE_AppDefined,
+                         "GDALWMS, Tiled WMS: No usable TilePattern elements found");
+                break;
+            }
+        }
+    }
+
+    m_requests=requests;
+    m_substs=substs;
+
+    if (tileServiceConfig) CPLDestroyXMLNode(tileServiceConfig);
+    if (psResult) CPLHTTPDestroyResult(psResult);
+
+    return ret;
+}
+
+void GDALWMSMiniDriver_TiledWMS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
+    caps->m_capabilities_version = 1;
+    caps->m_has_arb_overviews = 0;
+    caps->m_has_image_request = 1;
+    caps->m_has_tiled_image_requeset = 1;
+    caps->m_max_overview_count = 32;
+}
+
+
+// not called
+void GDALWMSMiniDriver_TiledWMS::ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri) {
+}
+
+void GDALWMSMiniDriver_TiledWMS::TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri) {
+    *url = m_base_url;
+    URLAppend(url,CSLGetField(m_requests,-tiri.m_level));
+    URLSearchAndReplace(url,"${GDAL_BBOX}","%013.8f,%013.8f,%013.8f,%013.8f",
+                        iri.m_x0,iri.m_y1,iri.m_x1,iri.m_y0);
+    if (m_substs!=NULL) {
+	for (int i=0;i<CSLCount(m_substs);i++) {
+	    char *k;
+	    const char *v=CPLParseNameValue(m_substs[i],&k);
+	    URLSearchAndReplace(url,k,"%s",v);
+	    VSIFree(k);
+	}
+    }
+    URLAppend(url,m_end_url);
+}
+
+const char *GDALWMSMiniDriver_TiledWMS::GetProjectionInWKT() {
+    return m_projection_wkt.c_str();
+}
+
diff --git a/frmts/wms/minidriver_tiled_wms.h b/frmts/wms/minidriver_tiled_wms.h
new file mode 100644
index 0000000..ae6569e
--- /dev/null
+++ b/frmts/wms/minidriver_tiled_wms.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Declarations for the OnEarth Tiled WMS minidriver.
+ *           http://onearth.jpl.nasa.gov/tiled.html
+ * Author:   Lucian Plesea (Lucian dot Pleasea at jpl.nasa.gov)
+ *           Adam Nowacki
+ *
+ ******************************************************************************
+ * 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.
+ ****************************************************************************/
+
+H_GDALWMSMiniDriverFactory(TiledWMS)
+
+class GDALWMSMiniDriver_TiledWMS : public GDALWMSMiniDriver {
+public:
+    GDALWMSMiniDriver_TiledWMS();
+    virtual ~GDALWMSMiniDriver_TiledWMS();
+
+public:
+    virtual CPLErr Initialize(CPLXMLNode *config);
+    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
+    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
+    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
+    virtual const char *GetProjectionInWKT();
+
+protected:
+    double Scale(const char *request);
+    void GetLowestScale(char **& list,int i, CPLString &req);
+    GDALWMSDataWindow m_data_window;
+    int m_overview_count;
+    int m_bands_count;
+    char **m_requests;
+    char **m_substs;
+    CPLString m_base_url;
+    CPLString m_end_url;
+    CPLString m_tiledGroupName;
+    int m_iversion;
+    int m_bsx,m_bsy;
+    CPLString m_projection_wkt;
+};
+
diff --git a/frmts/wms/minidriver_tms.cpp b/frmts/wms/minidriver_tms.cpp
index d131533..22264ab 100644
--- a/frmts/wms/minidriver_tms.cpp
+++ b/frmts/wms/minidriver_tms.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_tms.cpp 18589 2010-01-19 18:54:53Z warmerdam $
+ * $Id: minidriver_tms.cpp 22021 2011-03-23 21:51:19Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -94,4 +94,10 @@ void GDALWMSMiniDriver_TMS::TiledImageRequest(CPLString *url, const GDALWMSImage
     URLSearchAndReplace(url, "${x}", "%d", tiri.m_x);
     URLSearchAndReplace(url, "${y}", "%d", tms_y);
     URLSearchAndReplace(url, "${z}", "%d", tiri.m_level);
+
+    /* Hack for some TMS like servers that require tile numbers split into 3 groups of */
+    /* 3 digits, like http://tile8.geo.admin.ch/geoadmin/ch.swisstopo.pixelkarte-farbe */
+    URLSearchAndReplace(url, "${xxx}", "%03d/%03d/%03d", tiri.m_x / 1000000, (tiri.m_x / 1000) % 1000, tiri.m_x % 1000);
+    URLSearchAndReplace(url, "${yyy}", "%03d/%03d/%03d", tms_y / 1000000, (tms_y / 1000) % 1000, tms_y % 1000);
+
 }
diff --git a/frmts/wms/minidriver_virtualearth.cpp b/frmts/wms/minidriver_virtualearth.cpp
new file mode 100644
index 0000000..55775fb
--- /dev/null
+++ b/frmts/wms/minidriver_virtualearth.cpp
@@ -0,0 +1,114 @@
+/******************************************************************************
+ * $Id: minidriver_virtualearth.cpp 23033 2011-09-03 18:46:11Z rouault $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Implementation of Dataset and RasterBand classes for WMS
+ *           and other similar services.
+ * Author:   Even Rouault
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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 "stdinc.h"
+
+CPP_GDALWMSMiniDriverFactory(VirtualEarth)
+
+GDALWMSMiniDriver_VirtualEarth::GDALWMSMiniDriver_VirtualEarth()
+{
+}
+
+GDALWMSMiniDriver_VirtualEarth::~GDALWMSMiniDriver_VirtualEarth()
+{
+}
+
+CPLErr GDALWMSMiniDriver_VirtualEarth::Initialize(CPLXMLNode *config)
+{
+    CPLErr ret = CE_None;
+
+    if (ret == CE_None) {
+        const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
+        if (base_url[0] != '\0') {
+            m_base_url = base_url;
+            if (m_base_url.find("${quadkey}") == std::string::npos) {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "GDALWMS, VirtualEarth mini-driver: ${quadkey} missing in ServerURL.");
+                ret = CE_Failure;
+            }
+        } else {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "GDALWMS, VirtualEarth mini-driver: ServerURL missing.");
+            ret = CE_Failure;
+        }
+    }
+
+    m_parent_dataset->WMSSetDefaultBlockSize(256, 256);
+    m_parent_dataset->WMSSetDefaultDataWindowCoordinates(-20037508.34,20037508.34,20037508.34,-20037508.34);
+    m_parent_dataset->WMSSetDefaultTileLevel(19);
+    m_parent_dataset->WMSSetDefaultOverviewCount(18);
+    m_parent_dataset->WMSSetNeedsDataWindow(FALSE);
+
+    m_projection_wkt=ProjToWKT("EPSG:900913");
+
+    return ret;
+}
+
+void GDALWMSMiniDriver_VirtualEarth::GetCapabilities(GDALWMSMiniDriverCapabilities *caps)
+{
+    caps->m_capabilities_version = 1;
+    caps->m_has_arb_overviews = 0;
+    caps->m_has_image_request = 0;
+    caps->m_has_tiled_image_requeset = 1;
+    caps->m_max_overview_count = 32;
+}
+
+void GDALWMSMiniDriver_VirtualEarth::TiledImageRequest(CPLString *url,
+                                                       const GDALWMSImageRequestInfo &iri,
+                                                       const GDALWMSTiledImageRequestInfo &tiri)
+{
+
+    *url = m_base_url;
+
+    char szTileNumber[64];
+    int x = tiri.m_x;
+    int y = tiri.m_y;
+    int z = MIN(32,tiri.m_level);
+
+    for(int i = 0; i < z; i ++)
+    {
+        int row = (y & 1);
+        int col = (x & 1);
+
+        szTileNumber[z-1-i] = (char) ('0' + (col | (row << 1)));
+
+        x = x >> 1;
+        y = y >> 1;
+    }
+    szTileNumber[z] = 0;
+
+    URLSearchAndReplace(url, "${quadkey}", "%s", szTileNumber);
+    URLSearchAndReplace(url, "${server_num}", "%d",
+                        (tiri.m_x + tiri.m_y + z) % 4);
+}
+
+const char *GDALWMSMiniDriver_VirtualEarth::GetProjectionInWKT() {
+    return m_projection_wkt.c_str();
+}
diff --git a/frmts/wms/minidriver_virtualearth.h b/frmts/wms/minidriver_virtualearth.h
new file mode 100644
index 0000000..cedd5a7
--- /dev/null
+++ b/frmts/wms/minidriver_virtualearth.h
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * $Id: minidriver_virtualearth.h 21948 2011-03-12 21:31:21Z rouault $
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  Implementation of Dataset and RasterBand classes for WMS
+ *           and other similar services.
+ * Author:   Even Rouault
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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.
+ ****************************************************************************/
+
+H_GDALWMSMiniDriverFactory(VirtualEarth)
+
+class GDALWMSMiniDriver_VirtualEarth : public GDALWMSMiniDriver {
+public:
+    GDALWMSMiniDriver_VirtualEarth();
+    virtual ~GDALWMSMiniDriver_VirtualEarth();
+
+public:
+    virtual CPLErr Initialize(CPLXMLNode *config);
+    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
+    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
+    virtual const char* GetProjectionInWKT();
+
+protected:
+    CPLString m_base_url;
+    CPLString m_projection_wkt;
+};
diff --git a/frmts/wms/minidriver_wms.cpp b/frmts/wms/minidriver_wms.cpp
index fd7226a..ead3a4c 100644
--- a/frmts/wms/minidriver_wms.cpp
+++ b/frmts/wms/minidriver_wms.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_wms.cpp 18345 2009-12-19 11:02:39Z rouault $
+ * $Id: minidriver_wms.cpp 23033 2011-09-03 18:46:11Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -112,11 +112,9 @@ CPLErr GDALWMSMiniDriver_WMS::Initialize(CPLXMLNode *config) {
         m_styles = CPLGetXMLValue(config, "Styles", "");
         m_transparent = CPLGetXMLValue(config, "Transparent","");
         // the transparent flag needs to be "TRUE" or "FALSE" in upper case according to the WMS spec so force upper case
-        int i=0; 
-        while (m_transparent[i] != '\0')
+        for(int i=0; i<(int)m_transparent.size();i++)
         {
-            m_transparent[i] = toupper(m_transparent[i]);
-            i ++;
+            m_transparent[i] = (char) toupper(m_transparent[i]);
         }
     }
 
@@ -153,6 +151,8 @@ void GDALWMSMiniDriver_WMS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps)
 void GDALWMSMiniDriver_WMS::ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri) {
     // http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&width=1000&height=500&layers=modis,global_mosaic&styles=&srs=EPSG:4326&format=image/jpeg&bbox=-180.000000,-90.000000,180.000000,090.000000    
     *url = m_base_url;
+    if (m_base_url.ifind( "service=") == std::string::npos)
+        URLAppend(url, "&service=WMS");
     URLAppend(url, "&request=GetMap");
     URLAppendF(url, "&version=%s", m_version.c_str());
     URLAppendF(url, "&layers=%s", m_layers.c_str());
diff --git a/frmts/wms/rasterband.cpp b/frmts/wms/rasterband.cpp
index 4665283..1519202 100644
--- a/frmts/wms/rasterband.cpp
+++ b/frmts/wms/rasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterband.cpp 21304 2010-12-21 09:44:03Z nowakpl $
+ * $Id: rasterband.cpp 23192 2011-10-06 20:31:54Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -40,7 +40,7 @@ GDALWMSRasterBand::GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, d
     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 + 1;
+    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;
@@ -82,6 +82,12 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
         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");
     }
@@ -160,6 +166,7 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
             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);
@@ -169,6 +176,7 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                             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;
                         }
                     }
@@ -190,23 +198,38 @@ CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by
                                 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 if (download_requests[i].nStatus == 204) {
-                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, 
+               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;
+                    ret = CE_Failure;
+                }
             }
         }
         CPLHTTPCleanupRequest(&download_requests[i]);
@@ -238,7 +261,14 @@ CPLErr GDALWMSRasterBand::IReadBlock(int x, int y, void *buffer) {
         }
     }
 
-    return ReadBlocks(x, y, buffer, bx0, by0, bx1, by1, 0);
+    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) {
@@ -275,8 +305,7 @@ GDALRasterBand *GDALWMSRasterBand::GetOverview(int n) {
 }
 
 void GDALWMSRasterBand::AddOverview(double scale) {
-    int i;
-    GDALWMSRasterBand *overview = new GDALWMSRasterBand(m_parent_dataset, nBand - 1, 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;
@@ -284,7 +313,7 @@ void GDALWMSRasterBand::AddOverview(double scale) {
     }
     m_overviews.insert(it, overview);
     it = m_overviews.begin();
-    for (i = 0; it != m_overviews.end(); ++it, ++i) {
+    for (int i = 0; it != m_overviews.end(); ++it, ++i) {
         GDALWMSRasterBand *p = *it;
         p->m_overview = i;
     }
@@ -300,6 +329,8 @@ bool GDALWMSRasterBand::IsBlockInCache(int x, int y) {
     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;
@@ -436,10 +467,15 @@ CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name,
                         int line_space = pixel_space * nBlockXSize;
                         if (color_table == NULL) {
                             if( ib <= ds->GetRasterCount()) {
-                               if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, &ib, pixel_space, line_space, 0) != CE_None) {
-                                   CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
-                                   ret = CE_Failure;
-                               }
+				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
@@ -600,3 +636,10 @@ CPLErr GDALWMSRasterBand::AdviseRead(int x0, int y0, int sx, int sy, int bsx, in
 GDALColorInterp GDALWMSRasterBand::GetColorInterpretation() {
     return m_color_interp;
 }
+
+CPLErr GDALWMSRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
+{
+    m_color_interp = eNewInterp;
+    return CE_None;
+}
+
diff --git a/frmts/wms/stdinc.h b/frmts/wms/stdinc.h
index f5ebc7c..5ad33c2 100644
--- a/frmts/wms/stdinc.h
+++ b/frmts/wms/stdinc.h
@@ -1,6 +1,7 @@
 #include <math.h>
 #include <vector>
 #include <list>
+#include <algorithm>
 #include <curl/curl.h>
 #include <gdal.h>
 #include <gdalwarper.h>
@@ -11,6 +12,7 @@
 #include <gdal_priv.h>
 #include <gdal_pam.h>
 #include <cpl_multiproc.h>
+#include <cpl_http.h>
 
 #include "md5.h"
 #include "gdalhttp.h"
@@ -19,3 +21,5 @@
 #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
index cb6cfa9..ddd34a8 100644
--- a/frmts/wms/stuff.cpp
+++ b/frmts/wms/stuff.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: stuff.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: stuff.cpp 22177 2011-04-16 19:45:11Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -51,7 +51,20 @@ CPLString ProjToWKT(const CPLString &proj) {
     OGRSpatialReference sr;
     CPLString srs;
 
-    if (sr.SetFromUserInput(proj.c_str()) != OGRERR_NONE) return 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);
diff --git a/frmts/wms/wmsdriver.cpp b/frmts/wms/wmsdriver.cpp
index 9a86a4d..6a9b9f1 100644
--- a/frmts/wms/wmsdriver.cpp
+++ b/frmts/wms/wmsdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsdriver.cpp 18020 2009-11-14 14:33:20Z rouault $
+ * $Id: wmsdriver.cpp 22576 2011-06-24 13:14:21Z warmerdam $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -29,18 +29,750 @@
  ****************************************************************************/
 
 #include "stdinc.h"
+#include "wmsmetadataset.h"
 
-GDALDataset *GDALWMSDatasetOpen(GDALOpenInfo *poOpenInfo) {
+/************************************************************************/
+/*              GDALWMSDatasetGetConfigFromURL()                        */
+/************************************************************************/
+
+static
+CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
+{
+    const char* pszBaseURL = poOpenInfo->pszFilename;
+    if (EQUALN(pszBaseURL, "WMS:", 4))
+        pszBaseURL += 4;
+
+    CPLString osLayer = CPLURLGetValue(pszBaseURL, "LAYERS");
+    CPLString osVersion = CPLURLGetValue(pszBaseURL, "VERSION");
+    CPLString osSRS = CPLURLGetValue(pszBaseURL, "SRS");
+    CPLString osCRS = CPLURLGetValue(pszBaseURL, "CRS");
+    CPLString osBBOX = CPLURLGetValue(pszBaseURL, "BBOX");
+    CPLString osFormat = CPLURLGetValue(pszBaseURL, "FORMAT");
+    CPLString osTransparent = CPLURLGetValue(pszBaseURL, "TRANSPARENT");
+
+    /* GDAL specific extensions to alter the default settings */
+    CPLString osOverviewCount = CPLURLGetValue(pszBaseURL, "OVERVIEWCOUNT");
+    CPLString osTileSize = CPLURLGetValue(pszBaseURL, "TILESIZE");
+    CPLString osMinResolution = CPLURLGetValue(pszBaseURL, "MINRESOLUTION");
+    CPLString osBBOXOrder = CPLURLGetValue(pszBaseURL, "BBOXORDER");
+
+    CPLString osBaseURL = pszBaseURL;
+    /* Remove all keywords to get base URL */
+
+    osBaseURL = CPLURLAddKVP(osBaseURL, "VERSION", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "REQUEST", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "LAYERS", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "SRS", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "CRS", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "BBOX", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "FORMAT", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "TRANSPARENT", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "STYLES", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "WIDTH", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "HEIGHT", NULL);
+
+    osBaseURL = CPLURLAddKVP(osBaseURL, "OVERVIEWCOUNT", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "TILESIZE", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "MINRESOLUTION", NULL);
+    osBaseURL = CPLURLAddKVP(osBaseURL, "BBOXORDER", NULL);
+
+    if (osBaseURL.size() > 0 && osBaseURL[osBaseURL.size() - 1] == '&')
+        osBaseURL.resize(osBaseURL.size() - 1);
+
+    if (osVersion.size() == 0)
+        osVersion = "1.1.1";
+
+    CPLString osSRSTag;
+    CPLString osSRSValue;
+    if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0"))
+    {
+        if (osSRS.size())
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "WMS version 1.3 and above expects CRS however SRS was set instead.");
+        }
+        osSRSValue = osCRS;
+        osSRSTag = "CRS";
+    }
+    else
+    {
+        if (osCRS.size())
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "WMS version 1.1.1 and below expects SRS however CRS was set instead.");
+        }
+        osSRSValue = osSRS;
+        osSRSTag = "SRS";
+    }
+
+    if (osSRSValue.size() == 0)
+        osSRSValue = "EPSG:4326";
+    
+    if (osBBOX.size() == 0)
+    {
+        if (osBBOXOrder.compare("yxYX") == 0)
+            osBBOX = "-90,-180,90,180";
+        else
+            osBBOX = "-180,-90,180,90";
+    }
+
+    char** papszTokens = CSLTokenizeStringComplex(osBBOX, ",", 0, 0);
+    if (CSLCount(papszTokens) != 4)
+    {
+        CSLDestroy(papszTokens);
+        return NULL;
+    }
+    const char* pszMinX = papszTokens[0];
+    const char* pszMinY = papszTokens[1];
+    const char* pszMaxX = papszTokens[2];
+    const char* pszMaxY = papszTokens[3];
+
+    if (osBBOXOrder.compare("yxYX") == 0)
+    {
+        std::swap(pszMinX, pszMinY);
+        std::swap(pszMaxX, pszMaxY);
+    }
+
+    double dfMinX = CPLAtofM(pszMinX);
+    double dfMinY = CPLAtofM(pszMinY);
+    double dfMaxX = CPLAtofM(pszMaxX);
+    double dfMaxY = CPLAtofM(pszMaxY);
+
+    if (dfMaxY <= dfMinY || dfMaxX <= dfMinX)
+    {
+        CSLDestroy(papszTokens);
+        return NULL;
+    }
+
+    int nTileSize = atoi(osTileSize);
+    if (nTileSize <= 128 || nTileSize > 2048)
+        nTileSize = 1024;
+
+    int nXSize, nYSize;
+
+    int nOverviewCount = (osOverviewCount.size()) ? atoi(osOverviewCount) : 20;
+
+    if (osMinResolution.size() != 0)
+    {
+        double dfMinResolution = CPLAtofM(osMinResolution);
+
+        while (nOverviewCount > 20)
+        {
+            nOverviewCount --;
+            dfMinResolution *= 2;
+        }
+
+        nXSize = (int) ((dfMaxX - dfMinX) / dfMinResolution + 0.5);
+        nYSize = (int) ((dfMaxY - dfMinY) / dfMinResolution + 0.5);
+    }
+    else
+    {
+        double dfRatio = (dfMaxX - dfMinX) / (dfMaxY - dfMinY);
+        if (dfRatio > 1)
+        {
+            nXSize = nTileSize;
+            nYSize = (int) (nXSize / dfRatio);
+        }
+        else
+        {
+            nYSize = nTileSize;
+            nXSize = (int) (nYSize * dfRatio);
+        }
+
+        if (nOverviewCount < 0 || nOverviewCount > 20)
+            nOverviewCount = 20;
+
+        nXSize = nXSize * (1 << nOverviewCount);
+        nYSize = nYSize * (1 << nOverviewCount);
+    }
+
+    int bTransparent = osTransparent.size() ? CSLTestBoolean(osTransparent) : FALSE;
+
+    if (osFormat.size() == 0)
+    {
+        if (!bTransparent)
+        {
+            osFormat = "image/jpeg";
+        }
+        else
+        {
+            osFormat = "image/png";
+        }
+    }
+
+    char* pszEscapedURL = CPLEscapeString(osBaseURL.c_str(), -1, CPLES_XML);
+    char* pszEscapedLayerURL = CPLEscapeString(osLayer.c_str(), -1, CPLES_URL);
+    char* pszEscapedLayerXML = CPLEscapeString(pszEscapedLayerURL, -1, CPLES_XML);
+
+    CPLString osXML = CPLSPrintf(
+            "<GDAL_WMS>\n"
+            "  <Service name=\"WMS\">\n"
+            "    <Version>%s</Version>\n"
+            "    <ServerUrl>%s</ServerUrl>\n"
+            "    <Layers>%s</Layers>\n"
+            "    <%s>%s</%s>\n"
+            "    <ImageFormat>%s</ImageFormat>\n"
+            "    <Transparent>%s</Transparent>\n"
+            "    <BBoxOrder>%s</BBoxOrder>\n"
+            "  </Service>\n"
+            "  <DataWindow>\n"
+            "    <UpperLeftX>%s</UpperLeftX>\n"
+            "    <UpperLeftY>%s</UpperLeftY>\n"
+            "    <LowerRightX>%s</LowerRightX>\n"
+            "    <LowerRightY>%s</LowerRightY>\n"
+            "    <SizeX>%d</SizeX>\n"
+            "    <SizeY>%d</SizeY>\n"
+            "  </DataWindow>\n"
+            "  <BandsCount>%d</BandsCount>\n"
+            "  <BlockSizeX>%d</BlockSizeX>\n"
+            "  <BlockSizeY>%d</BlockSizeY>\n"
+            "  <OverviewCount>%d</OverviewCount>\n"
+            "</GDAL_WMS>\n",
+            osVersion.c_str(),
+            pszEscapedURL,
+            pszEscapedLayerXML,
+            osSRSTag.c_str(),
+            osSRSValue.c_str(),
+            osSRSTag.c_str(),
+            osFormat.c_str(),
+            (bTransparent) ? "TRUE" : "FALSE",
+            (osBBOXOrder.size()) ? osBBOXOrder.c_str() : "xyXY",
+            pszMinX, pszMaxY, pszMaxX, pszMinY,
+            nXSize, nYSize,
+            (bTransparent) ? 4 : 3,
+            nTileSize, nTileSize,
+            nOverviewCount);
+
+    CPLFree(pszEscapedURL);
+    CPLFree(pszEscapedLayerURL);
+    CPLFree(pszEscapedLayerXML);
+
+    CSLDestroy(papszTokens);
+
+    CPLDebug("WMS", "Opening WMS :\n%s", osXML.c_str());
+
+    return CPLParseXMLString(osXML);
+}
+
+/************************************************************************/
+/*              GDALWMSDatasetGetConfigFromTileMap()                    */
+/************************************************************************/
+
+static
+CPLXMLNode * GDALWMSDatasetGetConfigFromTileMap(CPLXMLNode* psXML)
+{
+    CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TileMap" );
+    if (psRoot == NULL)
+        return NULL;
+
+    CPLXMLNode* psTileSets = CPLGetXMLNode(psRoot, "TileSets");
+    if (psTileSets == NULL)
+        return NULL;
+
+    const char* pszURL = CPLGetXMLValue(psRoot, "tilemapservice", NULL);
+
+    int bCanChangeURL = TRUE;
+
+    CPLString osURL;
+    if (pszURL)
+    {
+        osURL = pszURL;
+        /* Special hack for http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/basic/ */
+        if (strlen(pszURL) > 10 &&
+            strncmp(pszURL, "http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/",
+                            strlen("http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/")) == 0 &&
+            strcmp(pszURL + strlen(pszURL) - strlen("1.0.0/"), "1.0.0/") == 0)
+        {
+            osURL.resize(strlen(pszURL) - strlen("1.0.0/"));
+            bCanChangeURL = FALSE;
+        }
+        osURL += "${z}/${x}/${y}.${format}";
+    }
+
+    const char* pszSRS = CPLGetXMLValue(psRoot, "SRS", NULL);
+    if (pszSRS == NULL)
+        return NULL;
+
+    CPLXMLNode* psBoundingBox = CPLGetXMLNode( psRoot, "BoundingBox" );
+    if (psBoundingBox == NULL)
+        return NULL;
+
+    const char* pszMinX = CPLGetXMLValue(psBoundingBox, "minx", NULL);
+    const char* pszMinY = CPLGetXMLValue(psBoundingBox, "miny", NULL);
+    const char* pszMaxX = CPLGetXMLValue(psBoundingBox, "maxx", NULL);
+    const char* pszMaxY = CPLGetXMLValue(psBoundingBox, "maxy", NULL);
+    if (pszMinX == NULL || pszMinY == NULL || pszMaxX == NULL || pszMaxY == NULL)
+        return NULL;
+
+    double dfMinX = CPLAtofM(pszMinX);
+    double dfMinY = CPLAtofM(pszMinY);
+    double dfMaxX = CPLAtofM(pszMaxX);
+    double dfMaxY = CPLAtofM(pszMaxY);
+    if (dfMaxY <= dfMinY || dfMaxX <= dfMinX)
+        return NULL;
+
+    CPLXMLNode* psTileFormat = CPLGetXMLNode( psRoot, "TileFormat" );
+    if (psTileFormat == NULL)
+        return NULL;
+
+    const char* pszTileWidth = CPLGetXMLValue(psTileFormat, "width", NULL);
+    const char* pszTileHeight = CPLGetXMLValue(psTileFormat, "height", NULL);
+    const char* pszTileFormat = CPLGetXMLValue(psTileFormat, "extension", NULL);
+    if (pszTileWidth == NULL || pszTileHeight == NULL || pszTileFormat == NULL)
+        return NULL;
+
+    int nTileWidth = atoi(pszTileWidth);
+    int nTileHeight = atoi(pszTileHeight);
+    if (nTileWidth < 128 || nTileHeight < 128)
+        return NULL;
+
+    CPLXMLNode* psIter = psTileSets->psChild;
+    int nLevelCount = 0;
+    double dfPixelSize = 0;
+    for(; psIter != NULL; psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element &&
+            EQUAL(psIter->pszValue, "TileSet"))
+        {
+            const char* pszOrder =
+                CPLGetXMLValue(psIter, "order", NULL);
+            if (pszOrder == NULL)
+            {
+                CPLDebug("WMS", "Cannot find order attribute");
+                return NULL;
+            }
+            if (atoi(pszOrder) != nLevelCount)
+            {
+                CPLDebug("WMS", "Expected order=%d, got %s", nLevelCount, pszOrder);
+                return NULL;
+            }
+
+            const char* pszHref =
+                CPLGetXMLValue(psIter, "href", NULL);
+            if (nLevelCount == 0 && pszHref != NULL)
+            {
+                if (bCanChangeURL && strlen(pszHref) > 10 &&
+                    strcmp(pszHref + strlen(pszHref) - strlen("/0"), "/0") == 0)
+                {
+                    osURL = pszHref;
+                    osURL.resize(strlen(pszHref) - strlen("/0"));
+                    osURL += "/${z}/${x}/${y}.${format}";
+                }
+            }
+            const char* pszUnitsPerPixel =
+                CPLGetXMLValue(psIter, "units-per-pixel", NULL);
+            if (pszUnitsPerPixel == NULL)
+                return NULL;
+            dfPixelSize = CPLAtofM(pszUnitsPerPixel);
+
+            nLevelCount++;
+        }
+    }
+
+    if (nLevelCount == 0 || osURL.size() == 0)
+        return NULL;
+
+    int nXSize = 0;
+    int nYSize = 0;
+
+    while(nLevelCount > 0)
+    {
+        GIntBig nXSizeBig = (GIntBig)((dfMaxX - dfMinX) / dfPixelSize + 0.5);
+        GIntBig nYSizeBig = (GIntBig)((dfMaxY - dfMinY) / dfPixelSize + 0.5);
+        if (nXSizeBig < INT_MAX && nYSizeBig < INT_MAX)
+        {
+            nXSize = (int)nXSizeBig;
+            nYSize = (int)nYSizeBig;
+            break;
+        }
+        CPLDebug("WMS", "Dropping one overview level so raster size fits into 32bit...");
+        dfPixelSize *= 2;
+        nLevelCount --;
+    }
+
+    char* pszEscapedURL = CPLEscapeString(osURL.c_str(), -1, CPLES_XML);
+    
+    CPLString osXML = CPLSPrintf(
+            "<GDAL_WMS>\n"
+            "  <Service name=\"TMS\">\n"
+            "    <ServerUrl>%s</ServerUrl>\n"
+            "    <Format>%s</Format>\n"
+            "  </Service>\n"
+            "  <DataWindow>\n"
+            "    <UpperLeftX>%s</UpperLeftX>\n"
+            "    <UpperLeftY>%s</UpperLeftY>\n"
+            "    <LowerRightX>%s</LowerRightX>\n"
+            "    <LowerRightY>%s</LowerRightY>\n"
+            "    <TileLevel>%d</TileLevel>\n"
+            "    <SizeX>%d</SizeX>\n"
+            "    <SizeY>%d</SizeY>\n"
+            "  </DataWindow>\n"
+            "  <Projection>%s</Projection>\n"
+            "  <BlockSizeX>%d</BlockSizeX>\n"
+            "  <BlockSizeY>%d</BlockSizeY>\n"
+            "  <BandsCount>%d</BandsCount>\n"
+            "</GDAL_WMS>\n",
+            pszEscapedURL,
+            pszTileFormat,
+            pszMinX, pszMaxY, pszMaxX, pszMinY,
+            nLevelCount - 1,
+            nXSize, nYSize,
+            pszSRS,
+            nTileWidth, nTileHeight, 3);
+    CPLDebug("WMS", "Opening TMS :\n%s", osXML.c_str());
+
+    CPLFree(pszEscapedURL);
+
+    return CPLParseXMLString(osXML);
+}
+
+/************************************************************************/
+/*             GDALWMSDatasetGetConfigFromArcGISJSON()                  */
+/************************************************************************/
+
+static CPLXMLNode* GDALWMSDatasetGetConfigFromArcGISJSON(const char* pszURL,
+                                                         const char* pszContent)
+{
+    /* TODO : use JSONC library to parse. But we don't really need it */
+    CPLString osTmpFilename(CPLSPrintf("/vsimem/WMSArcGISJSON%p", pszURL));
+    VSILFILE* fp = VSIFileFromMemBuffer( osTmpFilename,
+                                         (GByte*)pszContent,
+                                         strlen(pszContent),
+                                         FALSE);
+    const char* pszLine;
+    int nTileWidth = -1, nTileHeight = -1;
+    int nWKID = -1;
+    double dfMinX = 0, dfMaxY = 0;
+    int bHasMinX = FALSE, bHasMaxY = FALSE;
+    int nExpectedLevel = 0;
+    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)
+        {
+            int nVal = atoi(pszPtr + strlen("\"wkid\" : "));
+            if (nWKID < 0)
+                nWKID = nVal;
+            else if (nWKID != nVal)
+            {
+                CPLDebug("WMS", "Inconsisant WKID values : %d, %d", nVal, nWKID);
+                VSIFCloseL(fp);
+                return NULL;
+            }
+        }
+        else if ((pszPtr = strstr(pszLine, "\"x\" : ")) != NULL)
+        {
+            bHasMinX = TRUE;
+            dfMinX = CPLAtofM(pszPtr + strlen("\"x\" : "));
+        }
+        else if ((pszPtr = strstr(pszLine, "\"y\" : ")) != NULL)
+        {
+            bHasMaxY = TRUE;
+            dfMaxY = CPLAtofM(pszPtr + strlen("\"y\" : "));
+        }
+        else if ((pszPtr = strstr(pszLine, "\"level\" : ")) != NULL)
+        {
+            int nLevel = atoi(pszPtr + strlen("\"level\" : "));
+            if (nLevel != nExpectedLevel)
+            {
+                CPLDebug("WMS", "Expected level : %d, got : %d", nExpectedLevel, nLevel);
+                VSIFCloseL(fp);
+                return NULL;
+            }
+
+            if ((pszPtr = strstr(pszLine, "\"resolution\" : ")) != NULL)
+            {
+                double dfResolution = CPLAtofM(pszPtr + strlen("\"resolution\" : "));
+                if (nLevel == 0)
+                    dfBaseResolution = dfResolution;
+            }
+            else
+            {
+                CPLDebug("WMS", "Did not get resolution");
+                VSIFCloseL(fp);
+                return NULL;
+            }
+            nExpectedLevel ++;
+        }
+    }
+    VSIFCloseL(fp);
+
+    int nLevelCount = nExpectedLevel - 1;
+    if (nLevelCount < 1)
+    {
+        CPLDebug("WMS", "Did not get levels");
+        return NULL;
+    }
+
+    if (nTileWidth <= 0)
+    {
+        CPLDebug("WMS", "Did not get tile width");
+        return NULL;
+    }
+    if (nTileHeight <= 0)
+    {
+        CPLDebug("WMS", "Did not get tile height");
+        return NULL;
+    }
+    if (nWKID <= 0)
+    {
+        CPLDebug("WMS", "Did not get WKID");
+        return NULL;
+    }
+    if (!bHasMinX)
+    {
+        CPLDebug("WMS", "Did not get min x");
+        return NULL;
+    }
+    if (!bHasMaxY)
+    {
+        CPLDebug("WMS", "Did not get max y");
+        return NULL;
+    }
+    
+    if (nWKID == 102100)
+        nWKID = 3857;
+
+    const char* pszEndURL = strstr(pszURL, "/MapServer?f=json");
+    CPLAssert(pszEndURL);
+    CPLString osURL(pszURL);
+    osURL.resize(pszEndURL - pszURL);
+
+    double dfMaxX = dfMinX + dfBaseResolution * nTileWidth;
+    double dfMinY = dfMaxY - dfBaseResolution * nTileHeight;
+
+    int nTileCountX = 1;
+    if (fabs(dfMinX - -180) < 1e-4 && fabs(dfMaxY - 90) < 1e-4 &&
+        fabs(dfMinY - -90) < 1e-4)
+    {
+        nTileCountX = 2;
+        dfMaxX = 180;
+    }
+
+    CPLString osXML = CPLSPrintf(
+            "<GDAL_WMS>\n"
+            "  <Service name=\"TMS\">\n"
+            "    <ServerUrl>%s/MapServer/tile/${z}/${y}/${x}</ServerUrl>\n"
+            "  </Service>\n"
+            "  <DataWindow>\n"
+            "    <UpperLeftX>%.8f</UpperLeftX>\n"
+            "    <UpperLeftY>%.8f</UpperLeftY>\n"
+            "    <LowerRightX>%.8f</LowerRightX>\n"
+            "    <LowerRightY>%.8f</LowerRightY>\n"
+            "    <TileLevel>%d</TileLevel>\n"
+            "    <TileCountX>%d</TileCountX>\n"
+            "    <YOrigin>top</YOrigin>\n"
+            "  </DataWindow>\n"
+            "  <Projection>EPSG:%d</Projection>\n"
+            "  <BlockSizeX>%d</BlockSizeX>\n"
+            "  <BlockSizeY>%d</BlockSizeY>\n"
+            "  <Cache/>\n"
+            "</GDAL_WMS>\n",
+            osURL.c_str(),
+            dfMinX, dfMaxY, dfMaxX, dfMinY,
+            nLevelCount,
+            nTileCountX,
+            nWKID,
+            nTileWidth, nTileHeight);
+    CPLDebug("WMS", "Opening TMS :\n%s", osXML.c_str());
+
+    return CPLParseXMLString(osXML);
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int GDALWMSDataset::Identify(GDALOpenInfo *poOpenInfo)
+{
+    const char* pszFilename = poOpenInfo->pszFilename;
+    const char* pabyHeader = (const char *) poOpenInfo->pabyHeader;
+    if (poOpenInfo->nHeaderBytes == 0 &&
+         EQUALN(pszFilename, "<GDAL_WMS>", 10))
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes >= 10 &&
+             EQUALN(pabyHeader, "<GDAL_WMS>", 10))
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes == 0 &&
+             (EQUALN(pszFilename, "WMS:", 4) ||
+             CPLString(pszFilename).ifind("SERVICE=WMS") != std::string::npos) )
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             (strstr(pabyHeader, "<WMT_MS_Capabilities") != NULL ||
+              strstr(pabyHeader, "<WMS_Capabilities") != NULL ||
+              strstr(pabyHeader, "<!DOCTYPE WMT_MS_Capabilities") != NULL))
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<WMS_Tile_Service") != NULL)
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<TileMap version=\"1.0.0\"") != NULL)
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<Services") != NULL &&
+             strstr(pabyHeader, "<TileMapService version=\"1.0") != NULL)
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<TileMapService version=\"1.0.0\"") != NULL)
+    {
+        return TRUE;
+    }
+    else if (poOpenInfo->nHeaderBytes == 0 &&
+             EQUALN(pszFilename, "http", 4) &&
+             strstr(pszFilename, "/MapServer?f=json") != NULL)
+    {
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                                 Open()                               */
+/************************************************************************/
+
+GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
+{
     CPLXMLNode *config = NULL;
     CPLErr ret = CE_None;
 
-    if ((poOpenInfo->nHeaderBytes == 0) && EQUALN((const char *) poOpenInfo->pszFilename, "<GDAL_WMS>", 10)) {
-        config = CPLParseXMLString(poOpenInfo->pszFilename);
-    } else if ((poOpenInfo->nHeaderBytes >= 10) && EQUALN((const char *) poOpenInfo->pabyHeader, "<GDAL_WMS>", 10)) {
-        config = CPLParseXMLFile(poOpenInfo->pszFilename);
-    } else return NULL;
+    const char* pszFilename = poOpenInfo->pszFilename;
+    const char* pabyHeader = (const char *) poOpenInfo->pabyHeader;
+
+    if (poOpenInfo->nHeaderBytes == 0 &&
+        EQUALN(pszFilename, "<GDAL_WMS>", 10))
+    {
+        config = CPLParseXMLString(pszFilename);
+    }
+    else if (poOpenInfo->nHeaderBytes >= 10 &&
+             EQUALN(pabyHeader, "<GDAL_WMS>", 10))
+    {
+        config = CPLParseXMLFile(pszFilename);
+    }
+    else if (poOpenInfo->nHeaderBytes == 0 &&
+             (EQUALN(pszFilename, "WMS:http", 8) ||
+              EQUALN(pszFilename, "http", 4)) &&
+             strstr(pszFilename, "/MapServer?f=json") != NULL)
+    {
+        if (EQUALN(pszFilename, "WMS:http", 8))
+            pszFilename += 4;
+        CPLString osURL(pszFilename);
+        if (strstr(pszFilename, "&pretty=true") == NULL)
+            osURL += "&pretty=true";
+        CPLHTTPResult *psResult = CPLHTTPFetch(osURL.c_str(), NULL);
+        if (psResult == NULL)
+            return NULL;
+        if (psResult->pabyData == NULL)
+        {
+            CPLHTTPDestroyResult(psResult);
+            return NULL;
+        }
+        config = GDALWMSDatasetGetConfigFromArcGISJSON(osURL,
+                                                       (const char*)psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+    }
+
+    else if (poOpenInfo->nHeaderBytes == 0 &&
+             (EQUALN(pszFilename, "WMS:", 4) ||
+              CPLString(pszFilename).ifind("SERVICE=WMS") != std::string::npos))
+    {
+        CPLString osLayers = CPLURLGetValue(pszFilename, "LAYERS");
+        CPLString osRequest = CPLURLGetValue(pszFilename, "REQUEST");
+        if (osLayers.size() != 0)
+            config = GDALWMSDatasetGetConfigFromURL(poOpenInfo);
+        else if (EQUAL(osRequest, "GetTileService"))
+            return GDALWMSMetaDataset::DownloadGetTileService(poOpenInfo);
+        else
+            return GDALWMSMetaDataset::DownloadGetCapabilities(poOpenInfo);
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             (strstr(pabyHeader, "<WMT_MS_Capabilities") != NULL ||
+              strstr(pabyHeader, "<WMS_Capabilities") != NULL ||
+              strstr(pabyHeader, "<!DOCTYPE WMT_MS_Capabilities") != NULL))
+    {
+        CPLXMLNode* psXML = CPLParseXMLFile(pszFilename);
+        if (psXML == NULL)
+            return NULL;
+        GDALDataset* poRet = GDALWMSMetaDataset::AnalyzeGetCapabilities(psXML);
+        CPLDestroyXMLNode( psXML );
+        return poRet;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<WMS_Tile_Service") != NULL)
+    {
+        CPLXMLNode* psXML = CPLParseXMLFile(pszFilename);
+        if (psXML == NULL)
+            return NULL;
+        GDALDataset* poRet = GDALWMSMetaDataset::AnalyzeGetTileService(psXML);
+        CPLDestroyXMLNode( psXML );
+        return poRet;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<TileMap version=\"1.0.0\"") != NULL)
+    {
+        CPLXMLNode* psXML = CPLParseXMLFile(pszFilename);
+        if (psXML == NULL)
+            return NULL;
+        config = GDALWMSDatasetGetConfigFromTileMap(psXML);
+        CPLDestroyXMLNode( psXML );
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<Services") != NULL &&
+             strstr(pabyHeader, "<TileMapService version=\"1.0") != NULL)
+    {
+        CPLXMLNode* psXML = CPLParseXMLFile(pszFilename);
+        if (psXML == NULL)
+            return NULL;
+        CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=Services" );
+        GDALDataset* poRet = NULL;
+        if (psRoot)
+        {
+            CPLXMLNode* psTileMapService = CPLGetXMLNode(psRoot, "TileMapService");
+            if (psTileMapService)
+            {
+                const char* pszHref = CPLGetXMLValue(psTileMapService, "href", NULL);
+                if (pszHref)
+                {
+                    poRet = (GDALDataset*) GDALOpen(pszHref, GA_ReadOnly);
+                }
+            }
+        }
+        CPLDestroyXMLNode( psXML );
+        return poRet;
+    }
+    else if (poOpenInfo->nHeaderBytes != 0 &&
+             strstr(pabyHeader, "<TileMapService version=\"1.0.0\"") != NULL)
+    {
+        CPLXMLNode* psXML = CPLParseXMLFile(pszFilename);
+        if (psXML == NULL)
+            return NULL;
+        GDALDataset* poRet = GDALWMSMetaDataset::AnalyzeTileMapService(psXML);
+        CPLDestroyXMLNode( psXML );
+        return poRet;
+    }
+    else
+        return NULL;
     if (config == NULL) return NULL;
-    
+
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
 /* -------------------------------------------------------------------- */
@@ -57,12 +789,58 @@ GDALDataset *GDALWMSDatasetOpen(GDALOpenInfo *poOpenInfo) {
     ret = ds->Initialize(config);
     if (ret != CE_None) {
         delete ds;
-        ds = 0;
+        ds = NULL;
     }
     CPLDestroyXMLNode(config);
 
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    if (ds != NULL)
+    {
+        ds->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
+        ds->SetDescription( poOpenInfo->pszFilename );
+        ds->TryLoadXML();
+    }
+
     return ds;
 }
+/************************************************************************/
+/*                             CreateCopy()                             */
+/************************************************************************/
+
+GDALDataset *GDALWMSDataset::CreateCopy( const char * pszFilename,
+                                         GDALDataset *poSrcDS,
+                                         int bStrict, char ** papszOptions,
+                                         GDALProgressFunc pfnProgress,
+                                         void * pProgressData )
+{
+    if (poSrcDS->GetDriver() == NULL ||
+        !EQUAL(poSrcDS->GetDriver()->GetDescription(), "WMS"))
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Source dataset must be a WMS dataset");
+        return NULL;
+    }
+
+    const char* pszXML = poSrcDS->GetMetadataItem("XML", "WMS");
+    if (pszXML == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot get XML definition of source WMS dataset");
+        return NULL;
+    }
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
+    if (fp == NULL)
+        return NULL;
+
+    VSIFWriteL(pszXML, 1, strlen(pszXML), fp);
+    VSIFCloseL(fp);
+
+    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
+    return Open(&oOpenInfo);
+}
 
 /************************************************************************/
 /*                         GDALDeregister_WMS()                         */
@@ -85,8 +863,11 @@ void GDALRegister_WMS() {
         driver->SetDescription("WMS");
         driver->SetMetadataItem(GDAL_DMD_LONGNAME, "OGC Web Map Service");
         driver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_wms.html");
-        driver->pfnOpen = GDALWMSDatasetOpen;
+        driver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+        driver->pfnOpen = GDALWMSDataset::Open;
+        driver->pfnIdentify = GDALWMSDataset::Identify;
         driver->pfnUnloadDriver = GDALDeregister_WMS;
+        driver->pfnCreateCopy = GDALWMSDataset::CreateCopy;
         GetGDALDriverManager()->RegisterDriver(driver);
 
         GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
@@ -94,5 +875,7 @@ void GDALRegister_WMS() {
         mdm->Register(new GDALWMSMiniDriverFactory_TileService());
         mdm->Register(new GDALWMSMiniDriverFactory_WorldWind());
         mdm->Register(new GDALWMSMiniDriverFactory_TMS());
+        mdm->Register(new GDALWMSMiniDriverFactory_TiledWMS());
+        mdm->Register(new GDALWMSMiniDriverFactory_VirtualEarth());
     }
 }
diff --git a/frmts/wms/wmsdriver.h b/frmts/wms/wmsdriver.h
index 9f173d9..7e079d5 100644
--- a/frmts/wms/wmsdriver.h
+++ b/frmts/wms/wmsdriver.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsdriver.h 21304 2010-12-21 09:44:03Z nowakpl $
+ * $Id: wmsdriver.h 23192 2011-10-06 20:31:54Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -38,9 +38,10 @@ void URLAppendF(CPLString *url, const char *s, ...);
 void URLAppend(CPLString *url, const CPLString &s);
 CPLString BufferToVSIFile(GByte *buffer, size_t size);
 CPLErr MakeDirs(const char *path);
+
+
 int StrToBool(const char *p);
 int URLSearchAndReplace (CPLString *base, const char *search, const char *fmt, ...);
-
 /* Convert a.b.c.d to a * 0x1000000 + b * 0x10000 + c * 0x100 + d */
 int VersionStringToInt(const char *version);
 
@@ -59,6 +60,10 @@ public:
     int m_sx, m_sy;
     int m_tx, m_ty, m_tlevel;
     enum { BOTTOM = -1, DEFAULT = 0, TOP = 1 } m_y_origin;
+
+    GDALWMSDataWindow() : m_x0(-180), m_y0(90), m_x1(180), m_y1(-90),
+                          m_sx(-1), m_sy(-1), m_tx(0), m_ty(0),
+                          m_tlevel(-1), m_y_origin(DEFAULT) {}
 };
 
 class GDALWMSTiledImageRequestInfo {
@@ -190,31 +195,50 @@ protected:
 
 class GDALWMSDataset : public GDALPamDataset {
     friend class GDALWMSRasterBand;
-    friend GDALDataset *GDALWMSDatasetOpen(GDALOpenInfo *poOpenInfo);
 
 public:
     GDALWMSDataset();
     virtual ~GDALWMSDataset();
 
-public:
     virtual const char *GetProjectionRef();
     virtual CPLErr SetProjection(const char *proj);
     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 const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain = "" );
 
-protected:
-    virtual CPLErr 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);
+    const GDALWMSDataWindow *WMSGetDataWindow() const;
+    void WMSSetClamp(bool flag);
+    void WMSSetOverviewCount(int count);
+    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 mSetBand(int i, GDALRasterBand *band) { SetBand(i,band); };
+    GDALWMSRasterBand *mGetBand(int i) { return reinterpret_cast<GDALWMSRasterBand *>(GetRasterBand(i)); };
+
+
+    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);
+
+    static GDALDataset* Open(GDALOpenInfo *poOpenInfo);
+    static int Identify(GDALOpenInfo *poOpenInfo);
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
 
 protected:
+    virtual CPLErr 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 Initialize(CPLXMLNode *config);
 
-public:
-    const GDALWMSDataWindow *WMSGetDataWindow() const;
-    int WMSGetBlockSizeX() const;
-    int WMSGetBlockSizeY() const;
-
-protected:
     GDALWMSDataWindow m_data_window;
     GDALWMSMiniDriver *m_mini_driver;
     GDALWMSMiniDriverCapabilities m_mini_driver_caps;
@@ -231,7 +255,19 @@ protected:
     int m_http_timeout;
     int m_clamp_requests;
     int m_unsafeSsl;
+    std::vector<int> m_http_zeroblock_codes;
+    int m_zeroblock_on_serverexceptions;
     CPLString m_osUserAgent;
+    CPLString m_osReferer;
+
+    GDALWMSDataWindow m_default_data_window;
+    int m_default_block_size_x, m_default_block_size_y;
+    int m_default_tile_count_x, m_default_tile_count_y;
+    int m_default_overview_count;
+
+    int m_bNeedsDataWindow;
+
+    CPLString m_osXML;
 };
 
 class GDALWMSRasterBand : public GDALPamRasterBand {
@@ -240,24 +276,24 @@ class GDALWMSRasterBand : public GDALPamRasterBand {
 public:
     GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, double scale);
     virtual ~GDALWMSRasterBand();
-
-public:
+    void AddOverview(double scale);
     virtual CPLErr AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, char **options);
 
-protected:
-    CPLErr ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read);
+    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr SetColorInterpretation( GDALColorInterp );
     virtual CPLErr IReadBlock(int x, int y, void *buffer);
     virtual CPLErr 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);
     virtual int HasArbitraryOverviews();
     virtual int GetOverviewCount();
     virtual GDALRasterBand *GetOverview(int n);
-    void AddOverview(double scale);
+
+protected:
+    CPLErr ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read);
     bool IsBlockInCache(int x, int y);
     void AskMiniDriverForBlock(CPLString *url, int x, int y);
     CPLErr ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read);
     CPLErr ZeroBlock(int x, int y, int to_buffer_band, void *buffer);
     CPLErr ReportWMSException(const char *file_name);
-    virtual GDALColorInterp GetColorInterpretation();
 
 protected:
     GDALWMSDataset *m_parent_dataset;
@@ -267,6 +303,5 @@ protected:
     GDALColorInterp m_color_interp;
 };
 
-GDALDataset *GDALWMSDatasetOpen(GDALOpenInfo *poOpenInfo);
 GDALWMSMiniDriverManager *GetGDALWMSMiniDriverManager();
 void DestroyWMSMiniDriverManager(void);
diff --git a/frmts/wms/wmsmetadataset.cpp b/frmts/wms/wmsmetadataset.cpp
new file mode 100644
index 0000000..dc35664
--- /dev/null
+++ b/frmts/wms/wmsmetadataset.cpp
@@ -0,0 +1,729 @@
+/******************************************************************************
+ * $Id: wmsmetadataset.cpp 22576 2011-06-24 13:14:21Z warmerdam $
+ *
+ * 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>
+ *
+ * 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 "wmsmetadataset.h"
+
+int VersionStringToInt(const char *version);
+
+/************************************************************************/
+/*                          GDALWMSMetaDataset()                        */
+/************************************************************************/
+
+GDALWMSMetaDataset::GDALWMSMetaDataset() : papszSubDatasets(NULL)
+{
+}
+
+/************************************************************************/
+/*                         ~GDALWMSMetaDataset()                        */
+/************************************************************************/
+
+GDALWMSMetaDataset::~GDALWMSMetaDataset()
+{
+    CSLDestroy(papszSubDatasets);
+}
+
+/************************************************************************/
+/*                            AddSubDataset()                           */
+/************************************************************************/
+
+void GDALWMSMetaDataset::AddSubDataset(const char* pszName,
+                                       const char* pszDesc)
+{
+    char    szName[80];
+    int     nCount = CSLCount(papszSubDatasets ) / 2;
+
+    sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName, pszName );
+
+    sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName, pszDesc);
+}
+
+/************************************************************************/
+/*                        DownloadGetCapabilities()                     */
+/************************************************************************/
+
+GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInfo)
+{
+    const char* pszURL = poOpenInfo->pszFilename;
+    if (EQUALN(pszURL, "WMS:", 4))
+        pszURL += 4;
+
+    CPLString osFormat = CPLURLGetValue(pszURL, "FORMAT");
+    CPLString osTransparent = CPLURLGetValue(pszURL, "TRANSPARENT");
+    CPLString osVersion = CPLURLGetValue(pszURL, "VERSION");
+
+    if (osVersion.size() == 0)
+        osVersion = "1.1.1";
+
+    CPLString osURL(pszURL);
+    osURL = CPLURLAddKVP(osURL, "SERVICE", "WMS");
+    osURL = CPLURLAddKVP(osURL, "VERSION", osVersion);
+    osURL = CPLURLAddKVP(osURL, "REQUEST", "GetCapabilities");
+    /* Remove all other keywords */
+    osURL = CPLURLAddKVP(osURL, "LAYERS", NULL);
+    osURL = CPLURLAddKVP(osURL, "SRS", NULL);
+    osURL = CPLURLAddKVP(osURL, "CRS", NULL);
+    osURL = CPLURLAddKVP(osURL, "BBOX", NULL);
+    osURL = CPLURLAddKVP(osURL, "FORMAT", NULL);
+    osURL = CPLURLAddKVP(osURL, "TRANSPARENT", NULL);
+    osURL = CPLURLAddKVP(osURL, "STYLES", NULL);
+    osURL = CPLURLAddKVP(osURL, "WIDTH", NULL);
+    osURL = CPLURLAddKVP(osURL, "HEIGHT", NULL);
+
+    CPLHTTPResult* psResult = CPLHTTPFetch( osURL, NULL );
+    if (psResult == NULL)
+    {
+        return NULL;
+    }
+    if (psResult->nStatus != 0 || psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Error returned by server : %s (%d)",
+                 (psResult->pszErrBuf) ? psResult->pszErrBuf : "unknown",
+                 psResult->nStatus);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    if (psResult->pabyData == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Empty content returned by server");
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
+    if (psXML == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid XML content : %s",
+                psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    GDALDataset* poRet = AnalyzeGetCapabilities(psXML, osFormat, osTransparent);
+
+    CPLHTTPDestroyResult(psResult);
+    CPLDestroyXMLNode( psXML );
+
+    return poRet;
+}
+
+
+/************************************************************************/
+/*                         DownloadGetTileService()                     */
+/************************************************************************/
+
+GDALDataset *GDALWMSMetaDataset::DownloadGetTileService(GDALOpenInfo *poOpenInfo)
+{
+    const char* pszURL = poOpenInfo->pszFilename;
+    if (EQUALN(pszURL, "WMS:", 4))
+        pszURL += 4;
+
+    CPLString osURL(pszURL);
+    osURL = CPLURLAddKVP(osURL, "SERVICE", "WMS");
+    osURL = CPLURLAddKVP(osURL, "REQUEST", "GetTileService");
+    /* Remove all other keywords */
+    osURL = CPLURLAddKVP(osURL, "VERSION", NULL);
+    osURL = CPLURLAddKVP(osURL, "LAYERS", NULL);
+    osURL = CPLURLAddKVP(osURL, "SRS", NULL);
+    osURL = CPLURLAddKVP(osURL, "CRS", NULL);
+    osURL = CPLURLAddKVP(osURL, "BBOX", NULL);
+    osURL = CPLURLAddKVP(osURL, "FORMAT", NULL);
+    osURL = CPLURLAddKVP(osURL, "TRANSPARENT", NULL);
+    osURL = CPLURLAddKVP(osURL, "STYLES", NULL);
+    osURL = CPLURLAddKVP(osURL, "WIDTH", NULL);
+    osURL = CPLURLAddKVP(osURL, "HEIGHT", NULL);
+
+    CPLHTTPResult* psResult = CPLHTTPFetch( osURL, NULL );
+    if (psResult == NULL)
+    {
+        return NULL;
+    }
+    if (psResult->nStatus != 0 || psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Error returned by server : %s (%d)",
+                 (psResult->pszErrBuf) ? psResult->pszErrBuf : "unknown",
+                 psResult->nStatus);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    if (psResult->pabyData == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Empty content returned by server");
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
+    if (psXML == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid XML content : %s",
+                psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    GDALDataset* poRet = AnalyzeGetTileService(psXML);
+
+    CPLHTTPDestroyResult(psResult);
+    CPLDestroyXMLNode( psXML );
+
+    return poRet;
+}
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **GDALWMSMetaDataset::GetMetadata( const char *pszDomain )
+
+{
+    if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+        return papszSubDatasets;
+
+    return GDALPamDataset::GetMetadata( pszDomain );
+}
+
+/************************************************************************/
+/*                           AddSubDataset()                            */
+/************************************************************************/
+
+void GDALWMSMetaDataset::AddSubDataset( const char* pszLayerName,
+                                          const char* pszTitle,
+                                          const char* pszAbstract,
+                                          const char* pszSRS,
+                                          const char* pszMinX,
+                                          const char* pszMinY,
+                                          const char* pszMaxX,
+                                          const char* pszMaxY,
+                                          CPLString osFormat,
+                                          CPLString osTransparent)
+
+{
+    CPLString osSubdatasetName = "WMS:";
+    osSubdatasetName += osGetURL;
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SERVICE", "WMS");
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "VERSION", osVersion);
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "REQUEST", "GetMap");
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "LAYERS", pszLayerName);
+    if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0"))
+    {
+        osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "CRS", pszSRS);
+        /* FIXME: this should apply to all SRS that need axis inversion */
+        if (strcmp(pszSRS, "EPSG:4326") == 0)
+            osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "BBOXORDER", "yxYX");
+    }
+    else
+        osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SRS", pszSRS);
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "BBOX",
+             CPLSPrintf("%s,%s,%s,%s", pszMinX, pszMinY, pszMaxX, pszMaxY));
+    if (osFormat.size() != 0)
+        osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "FORMAT",
+                                        osFormat);
+    if (osTransparent.size() != 0)
+        osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TRANSPARENT",
+                                        osTransparent);
+
+    if (pszTitle)
+    {
+        if (osXMLEncoding.size() != 0 &&
+            osXMLEncoding != "utf-8" &&
+            osXMLEncoding != "UTF-8")
+        {
+            char* pszRecodedTitle = CPLRecode(pszTitle, osXMLEncoding.c_str(),
+                                              CPL_ENC_UTF8);
+            if (pszRecodedTitle)
+                AddSubDataset(osSubdatasetName, pszRecodedTitle);
+            else
+                AddSubDataset(osSubdatasetName, pszTitle);
+            CPLFree(pszRecodedTitle);
+        }
+        else
+        {
+            AddSubDataset(osSubdatasetName, pszTitle);
+        }
+    }
+    else
+    {
+        AddSubDataset(osSubdatasetName, pszLayerName);
+    }
+}
+
+
+/************************************************************************/
+/*                         AddWMSCSubDataset()                          */
+/************************************************************************/
+
+void GDALWMSMetaDataset::AddWMSCSubDataset(WMSCTileSetDesc& oWMSCTileSetDesc,
+                                          const char* pszTitle,
+                                          CPLString osTransparent)
+{
+    CPLString osSubdatasetName = "WMS:";
+    osSubdatasetName += osGetURL;
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SERVICE", "WMS");
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "VERSION", osVersion);
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "REQUEST", "GetMap");
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "LAYERS", oWMSCTileSetDesc.osLayers);
+    if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0"))
+        osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "CRS", oWMSCTileSetDesc.osSRS);
+    else
+        osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SRS", oWMSCTileSetDesc.osSRS);
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "BBOX",
+             CPLSPrintf("%s,%s,%s,%s", oWMSCTileSetDesc.osMinX.c_str(),
+                                       oWMSCTileSetDesc.osMinY.c_str(),
+                                       oWMSCTileSetDesc.osMaxX.c_str(),
+                                       oWMSCTileSetDesc.osMaxY.c_str()));
+
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "FORMAT", oWMSCTileSetDesc.osFormat);
+    if (osTransparent.size() != 0)
+        osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TRANSPARENT",
+                                        osTransparent);
+    if (oWMSCTileSetDesc.nTileWidth != oWMSCTileSetDesc.nTileHeight)
+        CPLDebug("WMS", "Weird: nTileWidth != nTileHeight for %s",
+                 oWMSCTileSetDesc.osLayers.c_str());
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TILESIZE",
+                                    CPLSPrintf("%d", oWMSCTileSetDesc.nTileWidth));
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "OVERVIEWCOUNT",
+                                    CPLSPrintf("%d", oWMSCTileSetDesc.nResolutions - 1));
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "MINRESOLUTION",
+                                    CPLSPrintf("%.16f", oWMSCTileSetDesc.dfMinResolution));
+    osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TILED", "true");
+
+    if (pszTitle)
+    {
+        if (osXMLEncoding.size() != 0 &&
+            osXMLEncoding != "utf-8" &&
+            osXMLEncoding != "UTF-8")
+        {
+            char* pszRecodedTitle = CPLRecode(pszTitle, osXMLEncoding.c_str(),
+                                              CPL_ENC_UTF8);
+            if (pszRecodedTitle)
+                AddSubDataset(osSubdatasetName, pszRecodedTitle);
+            else
+                AddSubDataset(osSubdatasetName, pszTitle);
+            CPLFree(pszRecodedTitle);
+        }
+        else
+        {
+            AddSubDataset(osSubdatasetName, pszTitle);
+        }
+    }
+    else
+    {
+        AddSubDataset(osSubdatasetName, oWMSCTileSetDesc.osLayers);
+    }
+}
+
+/************************************************************************/
+/*                             ExploreLayer()                           */
+/************************************************************************/
+
+void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
+                                      CPLString osFormat,
+                                      CPLString osTransparent,
+                                      const char* pszSRS,
+                                      const char* pszMinX,
+                                      const char* pszMinY,
+                                      const char* pszMaxX,
+                                      const char* pszMaxY)
+{
+    const char* pszName = CPLGetXMLValue(psXML, "Name", NULL);
+    const char* pszTitle = CPLGetXMLValue(psXML, "Title", NULL);
+    const char* pszAbstract = CPLGetXMLValue(psXML, "Abstract", NULL);
+
+    const char* pszSRSLocal = NULL;
+    const char* pszMinXLocal = NULL;
+    const char* pszMinYLocal = NULL;
+    const char* pszMaxXLocal = NULL;
+    const char* pszMaxYLocal = NULL;
+
+    const char* pszSRSTagName =
+        VersionStringToInt(osVersion.c_str()) >= VersionStringToInt("1.3.0") ? "CRS" : "SRS";
+
+    /* 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" );
+    if (psSRS == NULL)
+    {
+        psSRS = CPLGetXMLNode( psXML, "LatLonBoundingBox" );
+        pszSRSLocal = CPLGetXMLValue(psXML, pszSRSTagName, NULL);
+        if (pszSRSLocal == NULL)
+            pszSRSLocal = "EPSG:4326";
+    }
+    else
+        pszSRSLocal = CPLGetXMLValue(psSRS, pszSRSTagName, NULL);
+
+    if (pszSRSLocal != NULL && psSRS != NULL)
+    {
+        pszMinXLocal = CPLGetXMLValue(psSRS, "minx", NULL);
+        pszMinYLocal = CPLGetXMLValue(psSRS, "miny", NULL);
+        pszMaxXLocal = CPLGetXMLValue(psSRS, "maxx", NULL);
+        pszMaxYLocal = CPLGetXMLValue(psSRS, "maxy", NULL);
+
+        if (pszMinXLocal && pszMinYLocal && pszMaxXLocal && pszMaxYLocal)
+        {
+            pszSRS = pszSRSLocal;
+            pszMinX = pszMinXLocal;
+            pszMinY = pszMinYLocal;
+            pszMaxX = pszMaxXLocal;
+            pszMaxY = pszMaxYLocal;
+        }
+    }
+
+    if (pszName != NULL && pszSRS && pszMinX && pszMinY && pszMaxX && pszMaxY)
+    {
+        CPLString osLocalTransparent(osTransparent);
+        if (osLocalTransparent.size() == 0)
+        {
+            const char* pszOpaque = CPLGetXMLValue(psXML, "opaque", "0");
+            if (EQUAL(pszOpaque, "1"))
+                osLocalTransparent = "FALSE";
+        }
+
+        WMSCKeyType oWMSCKey(pszName, pszSRS);
+        std::map<WMSCKeyType, WMSCTileSetDesc>::iterator oIter = osMapWMSCTileSet.find(oWMSCKey);
+        if (oIter != osMapWMSCTileSet.end())
+        {
+            AddWMSCSubDataset(oIter->second, pszTitle, osLocalTransparent);
+        }
+        else
+        {
+            AddSubDataset(pszName, pszTitle, pszAbstract,
+                          pszSRS, pszMinX, pszMinY,
+                          pszMaxX, pszMaxY, osFormat, osLocalTransparent);
+        }
+    }
+
+    CPLXMLNode* psIter = psXML->psChild;
+    for(; psIter != NULL; psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element)
+        {
+            if (EQUAL(psIter->pszValue, "Layer"))
+                ExploreLayer(psIter, osFormat, osTransparent,
+                             pszSRS, pszMinX, pszMinY, pszMaxX, pszMaxY);
+        }
+    }
+}
+
+/************************************************************************/
+/*                         ParseWMSCTileSets()                          */
+/************************************************************************/
+
+void GDALWMSMetaDataset::ParseWMSCTileSets(CPLXMLNode* psXML)
+{
+    CPLXMLNode* psIter = psXML->psChild;
+    for(;psIter;psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element && EQUAL(psIter->pszValue, "TileSet"))
+        {
+            const char* pszSRS = CPLGetXMLValue(psIter, "SRS", NULL);
+            if (pszSRS == NULL)
+                continue;
+
+            CPLXMLNode* psBoundingBox = CPLGetXMLNode( psIter, "BoundingBox" );
+            if (psBoundingBox == NULL)
+                continue;
+
+            const char* pszMinX = CPLGetXMLValue(psBoundingBox, "minx", NULL);
+            const char* pszMinY = CPLGetXMLValue(psBoundingBox, "miny", NULL);
+            const char* pszMaxX = CPLGetXMLValue(psBoundingBox, "maxx", NULL);
+            const char* pszMaxY = CPLGetXMLValue(psBoundingBox, "maxy", NULL);
+            if (pszMinX == NULL || pszMinY == NULL || pszMaxX == NULL || pszMaxY == NULL)
+                continue;
+
+            double dfMinX = CPLAtofM(pszMinX);
+            double dfMinY = CPLAtofM(pszMinY);
+            double dfMaxX = CPLAtofM(pszMaxX);
+            double dfMaxY = CPLAtofM(pszMaxY);
+            if (dfMaxY <= dfMinY || dfMaxX <= dfMinX)
+                continue;
+
+            const char* pszFormat = CPLGetXMLValue( psIter, "Format", NULL );
+            if (pszFormat == NULL)
+                continue;
+            if (strstr(pszFormat, "kml"))
+                continue;
+
+            const char* pszTileWidth = CPLGetXMLValue(psIter, "Width", NULL);
+            const char* pszTileHeight = CPLGetXMLValue(psIter, "Height", NULL);
+            if (pszTileWidth == NULL || pszTileHeight == NULL)
+                continue;
+
+            int nTileWidth = atoi(pszTileWidth);
+            int nTileHeight = atoi(pszTileHeight);
+            if (nTileWidth < 128 || nTileHeight < 128)
+                continue;
+
+            const char* pszLayers = CPLGetXMLValue(psIter, "Layers", NULL);
+            if (pszLayers == NULL)
+                continue;
+
+            const char* pszResolutions = CPLGetXMLValue(psIter, "Resolutions", NULL);
+            if (pszResolutions == NULL)
+                continue;
+            char** papszTokens = CSLTokenizeStringComplex(pszResolutions, " ", 0, 0);
+            double dfMinResolution = 0;
+            int i;
+            for(i=0; papszTokens && papszTokens[i]; i++)
+            {
+                double dfResolution = CPLAtofM(papszTokens[i]);
+                if (i==0 || dfResolution < dfMinResolution)
+                    dfMinResolution = dfResolution;
+            }
+            CSLDestroy(papszTokens);
+            int nResolutions = i;
+            if (nResolutions == 0)
+                continue;
+
+            const char* pszStyles = CPLGetXMLValue(psIter, "Styles", "");
+
+            /* http://demo.opengeo.org/geoserver/gwc/service/wms?tiled=TRUE&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities */
+            /* has different variations of formats for the same (formats, SRS) tuple, so just */
+            /* keep the first one which is a png format */
+            WMSCKeyType oWMSCKey(pszLayers, pszSRS);
+            std::map<WMSCKeyType, WMSCTileSetDesc>::iterator oIter = osMapWMSCTileSet.find(oWMSCKey);
+            if (oIter != osMapWMSCTileSet.end())
+                continue;
+
+            WMSCTileSetDesc oWMSCTileSet;
+            oWMSCTileSet.osLayers = pszLayers;
+            oWMSCTileSet.osSRS = pszSRS;
+            oWMSCTileSet.osMinX = pszMinX;
+            oWMSCTileSet.osMinY = pszMinY;
+            oWMSCTileSet.osMaxX = pszMaxX;
+            oWMSCTileSet.osMaxY = pszMaxY;
+            oWMSCTileSet.dfMinX = dfMinX;
+            oWMSCTileSet.dfMinY = dfMinY;
+            oWMSCTileSet.dfMaxX = dfMaxX;
+            oWMSCTileSet.dfMaxY = dfMaxY;
+            oWMSCTileSet.nResolutions = nResolutions;
+            oWMSCTileSet.dfMinResolution = dfMinResolution;
+            oWMSCTileSet.osFormat = pszFormat;
+            oWMSCTileSet.osStyle = pszStyles;
+            oWMSCTileSet.nTileWidth = nTileWidth;
+            oWMSCTileSet.nTileHeight = nTileHeight;
+
+            osMapWMSCTileSet[oWMSCKey] = oWMSCTileSet;
+        }
+    }
+}
+
+/************************************************************************/
+/*                        AnalyzeGetCapabilities()                      */
+/************************************************************************/
+
+GDALDataset* GDALWMSMetaDataset::AnalyzeGetCapabilities(CPLXMLNode* psXML,
+                                                          CPLString osFormat,
+                                                          CPLString osTransparent)
+{
+    const char* pszEncoding = NULL;
+    if (psXML->eType == CXT_Element && strcmp(psXML->pszValue, "?xml") == 0)
+        pszEncoding = CPLGetXMLValue(psXML, "encoding", NULL);
+
+    CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=WMT_MS_Capabilities" );
+    if (psRoot == NULL)
+        psRoot = CPLGetXMLNode( psXML, "=WMS_Capabilities" );
+    if (psRoot == NULL)
+        return NULL;
+    CPLXMLNode* psCapability = CPLGetXMLNode(psRoot, "Capability");
+    if (psCapability == NULL)
+        return NULL;
+
+    CPLXMLNode* psOnlineResource = CPLGetXMLNode(psCapability,
+                             "Request.GetMap.DCPType.HTTP.Get.OnlineResource");
+    if (psOnlineResource == NULL)
+        return NULL;
+    const char* pszGetURL =
+        CPLGetXMLValue(psOnlineResource, "xlink:href", NULL);
+    if (pszGetURL == NULL)
+        return NULL;
+
+    CPLXMLNode* psLayer = CPLGetXMLNode(psCapability, "Layer");
+    if (psLayer == NULL)
+        return NULL;
+
+    CPLXMLNode* psVendorSpecificCapabilities =
+        CPLGetXMLNode(psCapability, "VendorSpecificCapabilities");
+
+    GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
+    const char* pszVersion = CPLGetXMLValue(psRoot, "version", NULL);
+    if (pszVersion)
+        poDS->osVersion = pszVersion;
+    else
+        poDS->osVersion = "1.1.1";
+    poDS->osGetURL = pszGetURL;
+    poDS->osXMLEncoding = pszEncoding ? pszEncoding : "";
+    if (psVendorSpecificCapabilities)
+        poDS->ParseWMSCTileSets(psVendorSpecificCapabilities);
+    poDS->ExploreLayer(psLayer, osFormat, osTransparent);
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                          AddTiledSubDataset()                        */
+/************************************************************************/
+
+void GDALWMSMetaDataset::AddTiledSubDataset(const char* pszTiledGroupName,
+                                            const char* pszTitle)
+{
+    CPLString osSubdatasetName = "<GDAL_WMS><Service name=\"TiledWMS\"><ServerUrl>";
+    osSubdatasetName += osGetURL;
+    osSubdatasetName += "</ServerUrl><TiledGroupName>";
+    osSubdatasetName += pszTiledGroupName;
+    osSubdatasetName += "</TiledGroupName></Service></GDAL_WMS>";
+
+    if (pszTitle)
+    {
+        if (osXMLEncoding.size() != 0 &&
+            osXMLEncoding != "utf-8" &&
+            osXMLEncoding != "UTF-8")
+        {
+            char* pszRecodedTitle = CPLRecode(pszTitle, osXMLEncoding.c_str(),
+                                              CPL_ENC_UTF8);
+            if (pszRecodedTitle)
+                AddSubDataset(osSubdatasetName, pszRecodedTitle);
+            else
+                AddSubDataset(osSubdatasetName, pszTitle);
+            CPLFree(pszRecodedTitle);
+        }
+        else
+        {
+            AddSubDataset(osSubdatasetName, pszTitle);
+        }
+    }
+    else
+    {
+        AddSubDataset(osSubdatasetName, pszTiledGroupName);
+    }
+}
+
+/************************************************************************/
+/*                     AnalyzeGetTileServiceRecurse()                   */
+/************************************************************************/
+
+void GDALWMSMetaDataset::AnalyzeGetTileServiceRecurse(CPLXMLNode* psXML)
+{
+    CPLXMLNode* psIter = psXML->psChild;
+    for(; psIter != NULL; psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element &&
+            EQUAL(psIter->pszValue, "TiledGroup"))
+        {
+            const char* pszName = CPLGetXMLValue(psIter, "Name", NULL);
+            const char* pszTitle = CPLGetXMLValue(psIter, "Title", NULL);
+            if (pszName)
+                AddTiledSubDataset(pszName, pszTitle);
+        }
+        else if (psIter->eType == CXT_Element &&
+            EQUAL(psIter->pszValue, "TiledGroups"))
+        {
+            AnalyzeGetTileServiceRecurse(psIter);
+        }
+    }
+}
+
+/************************************************************************/
+/*                        AnalyzeGetTileService()                       */
+/************************************************************************/
+
+GDALDataset* GDALWMSMetaDataset::AnalyzeGetTileService(CPLXMLNode* psXML)
+{
+    const char* pszEncoding = NULL;
+    if (psXML->eType == CXT_Element && strcmp(psXML->pszValue, "?xml") == 0)
+        pszEncoding = CPLGetXMLValue(psXML, "encoding", NULL);
+
+    CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=WMS_Tile_Service" );
+    if (psRoot == NULL)
+        return NULL;
+    CPLXMLNode* psTiledPatterns = CPLGetXMLNode(psRoot, "TiledPatterns");
+    if (psTiledPatterns == NULL)
+        return NULL;
+
+    const char* pszURL = CPLGetXMLValue(psTiledPatterns,
+                                        "OnlineResource.xlink:href", NULL);
+    if (pszURL == NULL)
+        return NULL;
+
+    GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
+    poDS->osGetURL = pszURL;
+    poDS->osXMLEncoding = pszEncoding ? pszEncoding : "";
+
+    poDS->AnalyzeGetTileServiceRecurse(psTiledPatterns);
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                        AnalyzeTileMapService()                       */
+/************************************************************************/
+
+GDALDataset* GDALWMSMetaDataset::AnalyzeTileMapService(CPLXMLNode* psXML)
+{
+    CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TileMapService" );
+    if (psRoot == NULL)
+        return NULL;
+    CPLXMLNode* psTileMaps = CPLGetXMLNode(psRoot, "TileMaps");
+    if (psTileMaps == NULL)
+        return NULL;
+
+    GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
+
+    CPLXMLNode* psIter = psTileMaps->psChild;
+    for(; psIter != NULL; psIter = psIter->psNext)
+    {
+        if (psIter->eType == CXT_Element &&
+            EQUAL(psIter->pszValue, "TileMap"))
+        {
+            const char* pszHref = CPLGetXMLValue(psIter, "href", NULL);
+            const char* pszTitle = CPLGetXMLValue(psIter, "title", NULL);
+            if (pszHref && pszTitle)
+            {
+                CPLString osHref(pszHref);
+                const char* pszDup100 = strstr(pszHref, "1.0.0/1.0.0/");
+                if (pszDup100)
+                {
+                    osHref.resize(pszDup100 - pszHref);
+                    osHref += pszDup100 + strlen("1.0.0/");
+                }
+                poDS->AddSubDataset(osHref, pszTitle);
+            }
+        }
+    }
+
+    return poDS;
+}
+
diff --git a/frmts/wms/wmsmetadataset.h b/frmts/wms/wmsmetadataset.h
new file mode 100644
index 0000000..c6de71e
--- /dev/null
+++ b/frmts/wms/wmsmetadataset.h
@@ -0,0 +1,119 @@
+/******************************************************************************
+ * $Id: wmsmetadataset.h 22557 2011-06-22 15:56:00Z 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>
+ *
+ * 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 _WMS_METADATASET_H_INCLUDED
+#define _WMS_METADATASET_H_INCLUDED
+
+#include "gdal_pam.h"
+#include "cpl_string.h"
+#include "cpl_http.h"
+#include <map>
+
+class WMSCTileSetDesc
+{
+    public:
+        CPLString osLayers;
+        CPLString osSRS;
+        CPLString osMinX, osMinY, osMaxX, osMaxY;
+        double    dfMinX, dfMinY, dfMaxX, dfMaxY;
+        int       nResolutions;
+        double    dfMinResolution;
+        CPLString osFormat;
+        CPLString osStyle;
+        int       nTileWidth, nTileHeight;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          GDALWMSMetaDataset                          */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALWMSMetaDataset : public GDALPamDataset
+{
+  private:
+    CPLString osGetURL;
+    CPLString osVersion;
+    CPLString osXMLEncoding;
+    char** papszSubDatasets;
+
+    typedef std::pair<CPLString, CPLString> WMSCKeyType;
+    std::map<WMSCKeyType, WMSCTileSetDesc> osMapWMSCTileSet;
+
+    void                AddSubDataset(const char* pszName,
+                                      const char* pszDesc);
+
+    void                AddSubDataset(const char* pszLayerName,
+                                      const char* pszTitle,
+                                      const char* pszAbstract,
+                                      const char* pszSRS,
+                                      const char* pszMinX,
+                                      const char* pszMinY,
+                                      const char* pszMaxX,
+                                      const char* pszMaxY,
+                                      CPLString osFormat,
+                                      CPLString osTransparent);
+
+    void                ExploreLayer(CPLXMLNode* psXML,
+                                     CPLString osFormat,
+                                     CPLString osTransparent,
+                                     const char* pszSRS = NULL,
+                                     const char* pszMinX = NULL,
+                                     const char* pszMinY = NULL,
+                                     const char* pszMaxX = NULL,
+                                     const char* pszMaxY = NULL);
+
+    void                AddTiledSubDataset(const char* pszTiledGroupName,
+                                           const char* pszTitle);
+
+    void                AnalyzeGetTileServiceRecurse(CPLXMLNode* psXML);
+
+    void                AddWMSCSubDataset(WMSCTileSetDesc& oWMSCTileSetDesc,
+                                          const char* pszTitle,
+                                          CPLString osTransparent);
+
+    void                ParseWMSCTileSets(CPLXMLNode* psXML);
+
+  public:
+        GDALWMSMetaDataset();
+       ~GDALWMSMetaDataset();
+
+    virtual char      **GetMetadata( const char * pszDomain = "" );
+
+    static GDALDataset* AnalyzeGetCapabilities(CPLXMLNode* psXML,
+                                               CPLString osFormat = "",
+                                               CPLString osTransparent = "");
+    static GDALDataset* AnalyzeGetTileService(CPLXMLNode* psXML);
+    static GDALDataset* AnalyzeTileMapService(CPLXMLNode* psXML);
+
+    static GDALDataset* DownloadGetCapabilities(GDALOpenInfo *poOpenInfo);
+    static GDALDataset* DownloadGetTileService(GDALOpenInfo *poOpenInfo);
+};
+
+#endif // _WMS_METADATASET_H_INCLUDED
diff --git a/frmts/xpm/xpmdataset.cpp b/frmts/xpm/xpmdataset.cpp
index 0f58403..f1611ca 100644
--- a/frmts/xpm/xpmdataset.cpp
+++ b/frmts/xpm/xpmdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: xpmdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: xpmdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $
  *
  * Project:  XPM Driver
  * Purpose:  Implement GDAL XPM Support
@@ -33,7 +33,7 @@
 #include "gdal_frmts.h"						      
 
 
-CPL_CVSID("$Id: xpmdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: xpmdataset.cpp 21680 2011-02-11 21:12:07Z warmerdam $");
 
 static unsigned char *ParseXPM( const char *pszInput,
                                 int *pnXSize, int *pnYSize, 
@@ -110,7 +110,7 @@ GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     VSIFSeekL( fp, 0, SEEK_END );
-    nFileSize = VSIFTellL( fp );
+    nFileSize = (unsigned int) VSIFTellL( fp );
     
     pszFileContents = (char *) VSIMalloc(nFileSize+1);
     if( pszFileContents == NULL )
diff --git a/frmts/xyz/xyzdataset.cpp b/frmts/xyz/xyzdataset.cpp
index 88a9e2a..4039c71 100644
--- a/frmts/xyz/xyzdataset.cpp
+++ b/frmts/xyz/xyzdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: xyzdataset.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: xyzdataset.cpp 22596 2011-06-27 18:53:18Z rouault $
  *
  * Project:  XYZ driver
  * Purpose:  GDALDataset driver for XYZ dataset.
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: xyzdataset.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: xyzdataset.cpp 22596 2011-06-27 18:53:18Z rouault $");
 
 CPL_C_START
 void    GDALRegister_XYZ(void);
@@ -51,6 +51,7 @@ class XYZDataset : public GDALPamDataset
     
     VSILFILE   *fp;
     int         bHasHeaderLine;
+    int         nCommentLineCount;
     int         nXIndex;
     int         nYIndex;
     int         nZIndex;
@@ -59,7 +60,7 @@ class XYZDataset : public GDALPamDataset
     int         nDataLineNum; /* line with values (header line and empty lines ignored) */
     double      adfGeoTransform[6];
     
-    static int          IdentifyEx( GDALOpenInfo *, int& );
+    static int          IdentifyEx( GDALOpenInfo *, int&, int& nCommentLineCount );
 
   public:
                  XYZDataset();
@@ -126,6 +127,10 @@ CPLErr XYZRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     {
         poGDS->nDataLineNum = 0;
         VSIFSeekL(poGDS->fp, 0, SEEK_SET);
+
+        for(int i=0;i<poGDS->nCommentLineCount;i++)
+            CPLReadLine2L(poGDS->fp, 100, NULL);
+
         if (poGDS->bHasHeaderLine)
         {
             const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
@@ -285,8 +290,8 @@ XYZDataset::~XYZDataset()
 
 int XYZDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
-    int bHasHeaderLine;
-    return IdentifyEx(poOpenInfo, bHasHeaderLine);
+    int bHasHeaderLine, nCommentLineCount;
+    return IdentifyEx(poOpenInfo, bHasHeaderLine, nCommentLineCount);
 }
 
 /************************************************************************/
@@ -294,12 +299,15 @@ int XYZDataset::Identify( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 
 
-int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo, int& bHasHeaderLine )
+int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
+                            int& bHasHeaderLine,
+                            int& nCommentLineCount)
 
 {
     int         i;
 
     bHasHeaderLine = FALSE;
+    nCommentLineCount = 0;
 
     CPLString osFilename(poOpenInfo->pszFilename);
 
@@ -327,7 +335,34 @@ int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo, int& bHasHeaderLine )
 /*      Chech that it looks roughly as a XYZ dataset                    */
 /* -------------------------------------------------------------------- */
     const char* pszData = (const char*)poOpenInfo->pabyHeader;
-    for(i=0;i<poOpenInfo->nHeaderBytes;i++)
+
+    /* Skip comments line at the beginning such as in */
+    /* http://pubs.usgs.gov/of/2003/ofr-03-230/DATA/NSLCU.XYZ */
+    i=0;
+    if (pszData[i] == '/')
+    {
+        nCommentLineCount ++;
+
+        i++;
+        for(;i<poOpenInfo->nHeaderBytes;i++)
+        {
+            char ch = pszData[i];
+            if (ch == 13 || ch == 10)
+            {
+                if (ch == 13 && pszData[i+1] == 10)
+                    i++;
+                if (pszData[i+1] == '/')
+                {
+                    nCommentLineCount ++;
+                    i++;
+                }
+                else
+                    break;
+            }
+        }
+    }
+
+    for(;i<poOpenInfo->nHeaderBytes;i++)
     {
         char ch = pszData[i];
         if (ch == 13 || ch == 10)
@@ -402,8 +437,9 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 {
     int         i;
     int         bHasHeaderLine;
+    int         nCommentLineCount = 0;
 
-    if (!IdentifyEx(poOpenInfo, bHasHeaderLine))
+    if (!IdentifyEx(poOpenInfo, bHasHeaderLine, nCommentLineCount))
         return NULL;
 
     CPLString osFilename(poOpenInfo->pszFilename);
@@ -433,7 +469,11 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     const char* pszLine;
     int nXIndex = -1, nYIndex = -1, nZIndex = -1;
     int nMinTokens = 0;
-    
+
+
+    for(i=0;i<nCommentLineCount;i++)
+        CPLReadLine2L(fp, 100, NULL);
+
 /* -------------------------------------------------------------------- */
 /*      Parse header line                                               */
 /* -------------------------------------------------------------------- */
@@ -700,6 +740,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS = new XYZDataset();
     poDS->fp = fp;
     poDS->bHasHeaderLine = bHasHeaderLine;
+    poDS->nCommentLineCount = nCommentLineCount;
     poDS->nXIndex = nXIndex;
     poDS->nYIndex = nYIndex;
     poDS->nZIndex = nZIndex;
diff --git a/frmts/zlib/makefile.vc b/frmts/zlib/makefile.vc
index 54d1025..9dd2a02 100644
--- a/frmts/zlib/makefile.vc
+++ b/frmts/zlib/makefile.vc
@@ -1,4 +1,4 @@
-# $Id: makefile.vc 10656 2007-01-19 01:31:01Z mloskot $
+# $Id: makefile.vc 21680 2011-02-11 21:12:07Z warmerdam $
 #
 # Makefile to build zlib using NMAKE and Visual C++ compiler.
 #
@@ -20,6 +20,8 @@ GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
+EXTRAFLAGS = $(SOFTWARNFLAGS) /wd4131
+
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
 
diff --git a/frmts/zmap/GNUmakefile b/frmts/zmap/GNUmakefile
new file mode 100644
index 0000000..b45a92f
--- /dev/null
+++ b/frmts/zmap/GNUmakefile
@@ -0,0 +1,13 @@
+
+OBJ	=	zmapdataset.o
+
+include ../../GDALmake.opt
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/zmap/makefile.vc b/frmts/zmap/makefile.vc
new file mode 100644
index 0000000..d26204a
--- /dev/null
+++ b/frmts/zmap/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ	=	zmapdataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/zmap/zmapdataset.cpp b/frmts/zmap/zmapdataset.cpp
new file mode 100644
index 0000000..d7720a7
--- /dev/null
+++ b/frmts/zmap/zmapdataset.cpp
@@ -0,0 +1,722 @@
+/******************************************************************************
+ * $Id: zmapdataset.cpp 22671 2011-07-08 18:08:12Z 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
+ *
+ * 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_vsi_virtual.h"
+#include "cpl_string.h"
+#include "gdal_pam.h"
+
+CPL_CVSID("$Id: zmapdataset.cpp 22671 2011-07-08 18:08:12Z rouault $");
+
+CPL_C_START
+void    GDALRegister_ZMap(void);
+CPL_C_END
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              ZMapDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class ZMapRasterBand;
+
+class ZMapDataset : public GDALPamDataset
+{
+    friend class ZMapRasterBand;
+
+    VSILFILE   *fp;
+    int         nValuesPerLine;
+    int         nFieldSize;
+    int         nDecimalCount;
+    int         nColNum;
+    double      dfNoDataValue;
+    vsi_l_offset nDataStartOff;
+    double      adfGeoTransform[6];
+
+  public:
+                 ZMapDataset();
+    virtual     ~ZMapDataset();
+
+    virtual CPLErr GetGeoTransform( double * );
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+    static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress, void * pProgressData );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ZMapRasterBand                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class ZMapRasterBand : public GDALPamRasterBand
+{
+    friend class ZMapDataset;
+
+  public:
+
+                ZMapRasterBand( ZMapDataset * );
+
+    virtual CPLErr IReadBlock( int, int, void * );
+
+    virtual double GetNoDataValue( int *pbSuccess = NULL );
+};
+
+
+/************************************************************************/
+/*                           ZMapRasterBand()                           */
+/************************************************************************/
+
+ZMapRasterBand::ZMapRasterBand( ZMapDataset *poDS )
+
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+
+    eDataType = GDT_Float64;
+
+    nBlockXSize = 1;
+    nBlockYSize = poDS->GetRasterYSize();
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr ZMapRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                  void * pImage )
+
+{
+    int i;
+    ZMapDataset *poGDS = (ZMapDataset *) poDS;
+
+    if (poGDS->fp == NULL)
+        return CE_Failure;
+
+    if (nBlockXOff < poGDS->nColNum + 1)
+    {
+        VSIFSeekL(poGDS->fp, poGDS->nDataStartOff, SEEK_SET);
+        poGDS->nColNum = -1;
+    }
+
+    if (nBlockXOff > poGDS->nColNum + 1)
+    {
+        for(i=poGDS->nColNum + 1;i<nBlockXOff;i++)
+        {
+            if (IReadBlock(i,0,pImage) != CE_None)
+                return CE_Failure;
+        }
+    }
+
+    char* pszLine;
+    i = 0;
+    double dfExp = pow(10.0, poGDS->nDecimalCount);
+    while(i<nRasterYSize)
+    {
+        pszLine = (char*)CPLReadLineL(poGDS->fp);
+        if (pszLine == NULL)
+            return CE_Failure;
+        int nExpected = nRasterYSize - i;
+        if (nExpected > poGDS->nValuesPerLine)
+            nExpected = poGDS->nValuesPerLine;
+        if ((int)strlen(pszLine) != nExpected * poGDS->nFieldSize)
+            return CE_Failure;
+
+        for(int j=0;j<nExpected;j++)
+        {
+            char* pszValue = pszLine + j * poGDS->nFieldSize;
+            char chSaved = pszValue[poGDS->nFieldSize];
+            pszValue[poGDS->nFieldSize] = 0;
+            if (strchr(pszValue, '.') != NULL)
+                ((double*)pImage)[i+j] = CPLAtofM(pszValue);
+            else
+                ((double*)pImage)[i+j] = atoi(pszValue) * dfExp;
+            pszValue[poGDS->nFieldSize] = chSaved;
+        }
+
+        i += nExpected;
+    }
+
+    poGDS->nColNum ++;
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetNoDataValue()                            */
+/************************************************************************/
+
+double ZMapRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    ZMapDataset *poGDS = (ZMapDataset *) poDS;
+
+    if (pbSuccess)
+        *pbSuccess = TRUE;
+
+    return poGDS->dfNoDataValue;
+}
+
+/************************************************************************/
+/*                            ~ZMapDataset()                            */
+/************************************************************************/
+
+ZMapDataset::ZMapDataset()
+{
+    fp = NULL;
+    nDataStartOff = 0;
+    nColNum = -1;
+    nValuesPerLine = 0;
+    nFieldSize = 0;
+    nDecimalCount = 0;
+    dfNoDataValue = 0.0;
+    adfGeoTransform[0] = 0;
+    adfGeoTransform[1] = 1;
+    adfGeoTransform[2] = 0;
+    adfGeoTransform[3] = 0;
+    adfGeoTransform[4] = 0;
+    adfGeoTransform[5] = 1;
+}
+
+/************************************************************************/
+/*                            ~ZMapDataset()                            */
+/************************************************************************/
+
+ZMapDataset::~ZMapDataset()
+
+{
+    FlushCache();
+    if (fp)
+        VSIFCloseL(fp);
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int ZMapDataset::Identify( GDALOpenInfo * poOpenInfo )
+{
+    int         i;
+
+    if (poOpenInfo->nHeaderBytes == 0)
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Chech that it looks roughly as a ZMap dataset                   */
+/* -------------------------------------------------------------------- */
+    const char* pszData = (const char*)poOpenInfo->pabyHeader;
+
+    /* Skip comments line at the beginning */
+    i=0;
+    if (pszData[i] == '!')
+    {
+        i++;
+        for(;i<poOpenInfo->nHeaderBytes;i++)
+        {
+            char ch = pszData[i];
+            if (ch == 13 || ch == 10)
+            {
+                i++;
+                if (ch == 13 && pszData[i] == 10)
+                    i++;
+                if (pszData[i] != '!')
+                    break;
+            }
+        }
+    }
+
+    if (pszData[i] != '@')
+        return FALSE;
+    i++;
+
+    char** papszTokens = CSLTokenizeString2( pszData+i, ",", 0 );
+    if (CSLCount(papszTokens) < 3)
+    {
+        CSLDestroy(papszTokens);
+        return FALSE;
+    }
+
+    const char* pszToken = papszTokens[1];
+    while (*pszToken == ' ')
+        pszToken ++;
+
+    if (strncmp(pszToken, "GRID", 4) != 0)
+    {
+        CSLDestroy(papszTokens);
+        return FALSE;
+    }
+
+    CSLDestroy(papszTokens);
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
+
+{
+    if (!Identify(poOpenInfo))
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Find dataset characteristics                                    */
+/* -------------------------------------------------------------------- */
+    VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+    if (fp == NULL)
+        return NULL;
+
+    const char* pszLine;
+
+    while((pszLine = CPLReadLine2L(fp, 100, NULL)) != NULL)
+    {
+        if (*pszLine == '!')
+        {
+            continue;
+        }
+        else
+            break;
+    }
+    if (pszLine == NULL)
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    /* Parse first header line */
+    char** papszTokens = CSLTokenizeString2( pszLine, ",", 0 );
+    if (CSLCount(papszTokens) != 3)
+    {
+        CSLDestroy(papszTokens);
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    int nValuesPerLine = atoi(papszTokens[2]);
+    if (nValuesPerLine <= 0)
+    {
+        CSLDestroy(papszTokens);
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    CSLDestroy(papszTokens);
+    papszTokens = NULL;
+
+    /* Parse second header line */
+    pszLine = CPLReadLine2L(fp, 100, NULL);
+    if (pszLine == NULL)
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
+    papszTokens = CSLTokenizeString2( pszLine, ",", 0 );
+    if (CSLCount(papszTokens) != 5)
+    {
+        CSLDestroy(papszTokens);
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    int nFieldSize = atoi(papszTokens[0]);
+    double dfNoDataValue = CPLAtofM(papszTokens[1]);
+    int nDecimalCount = atoi(papszTokens[3]);
+    int nColumnNumber = atoi(papszTokens[4]);
+
+    CSLDestroy(papszTokens);
+    papszTokens = NULL;
+
+    if (nFieldSize <= 0 || nFieldSize >= 40 ||
+        nDecimalCount <= 0 || nDecimalCount >= nFieldSize ||
+        nColumnNumber != 1)
+    {
+        CPLDebug("ZMap", "nFieldSize=%d, nDecimalCount=%d, nColumnNumber=%d",
+                 nFieldSize, nDecimalCount, nColumnNumber);
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    /* Parse third header line */
+    pszLine = CPLReadLine2L(fp, 100, NULL);
+    if (pszLine == NULL)
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
+    papszTokens = CSLTokenizeString2( pszLine, ",", 0 );
+    if (CSLCount(papszTokens) != 6)
+    {
+        CSLDestroy(papszTokens);
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    int nRows = atoi(papszTokens[0]);
+    int nCols = atoi(papszTokens[1]);
+    double dfMinX = CPLAtofM(papszTokens[2]);
+    double dfMaxX = CPLAtofM(papszTokens[3]);
+    double dfMinY = CPLAtofM(papszTokens[4]);
+    double dfMaxY = CPLAtofM(papszTokens[5]);
+
+    CSLDestroy(papszTokens);
+    papszTokens = NULL;
+
+    if (!GDALCheckDatasetDimensions(nCols, nRows) ||
+        nCols == 1 || nRows == 1)
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
+    
+    /* Ignore fourth header line */
+    pszLine = CPLReadLine2L(fp, 100, NULL);
+    if (pszLine == NULL)
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+    /* Check fifth header line */
+    pszLine = CPLReadLine2L(fp, 100, NULL);
+    if (pszLine == NULL || pszLine[0] != '@')
+    {
+        VSIFCloseL(fp);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a corresponding GDALDataset.                             */
+/* -------------------------------------------------------------------- */
+    ZMapDataset         *poDS;
+
+    poDS = new ZMapDataset();
+    poDS->fp = fp;
+    poDS->nDataStartOff = VSIFTellL(fp);
+    poDS->nValuesPerLine = nValuesPerLine;
+    poDS->nFieldSize = nFieldSize;
+    poDS->nDecimalCount = nDecimalCount;
+    poDS->nRasterXSize = nCols;
+    poDS->nRasterYSize = nRows;
+    poDS->dfNoDataValue = dfNoDataValue;
+
+    if (CSLTestBoolean(CPLGetConfigOption("ZMAP_PIXEL_IS_POINT", "FALSE")))
+    {
+        double dfStepX = (dfMaxX - dfMinX) / (nCols - 1);
+        double dfStepY = (dfMaxY - dfMinY) / (nRows - 1);
+
+        poDS->adfGeoTransform[0] = dfMinX - dfStepX / 2;
+        poDS->adfGeoTransform[1] = dfStepX;
+        poDS->adfGeoTransform[3] = dfMaxY + dfStepY / 2;
+        poDS->adfGeoTransform[5] = -dfStepY;
+    }
+    else
+    {
+        double dfStepX = (dfMaxX - dfMinX) / nCols ;
+        double dfStepY = (dfMaxY - dfMinY) / nRows;
+
+        poDS->adfGeoTransform[0] = dfMinX;
+        poDS->adfGeoTransform[1] = dfStepX;
+        poDS->adfGeoTransform[3] = dfMaxY;
+        poDS->adfGeoTransform[5] = -dfStepY;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    poDS->nBands = 1;
+    poDS->SetBand( 1, new ZMapRasterBand( poDS ) );
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Support overviews.                                              */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    return( poDS );
+}
+
+
+/************************************************************************/
+/*                       WriteRightJustified()                          */
+/************************************************************************/
+
+static void WriteRightJustified(VSILFILE* fp, const char *pszValue, int nWidth)
+{
+    int nLen = strlen(pszValue);
+    CPLAssert(nLen <= nWidth);
+    int i;
+    for(i=0;i<nWidth -nLen;i++)
+        VSIFWriteL(" ", 1, 1, fp);
+    VSIFWriteL(pszValue, 1, nLen, fp);
+}
+
+static void WriteRightJustified(VSILFILE* fp, int nValue, int nWidth)
+{
+    CPLString osValue(CPLSPrintf("%d", nValue));
+    WriteRightJustified(fp, osValue.c_str(), nWidth);
+}
+
+static void WriteRightJustified(VSILFILE* fp, double dfValue, int nWidth,
+                                int nDecimals = -1)
+{
+    char szFormat[32];
+    if (nDecimals >= 0)
+        sprintf(szFormat, "%%.%df", nDecimals);
+    else
+        sprintf(szFormat, "%%g");
+    char* pszValue = (char*)CPLSPrintf(szFormat, dfValue);
+    char* pszE = strchr(pszValue, 'e');
+    if (pszE)
+        *pszE = 'E';
+
+    if ((int)strlen(pszValue) > nWidth)
+    {
+        sprintf(szFormat, "%%.%dg", nDecimals);
+        pszValue = (char*)CPLSPrintf(szFormat, dfValue);
+        pszE = strchr(pszValue, 'e');
+        if (pszE)
+            *pszE = 'E';
+    }
+    
+    CPLString osValue(pszValue);
+    WriteRightJustified(fp, osValue.c_str(), nWidth);
+}
+
+/************************************************************************/
+/*                             CreateCopy()                             */
+/************************************************************************/
+
+GDALDataset* ZMapDataset::CreateCopy( const char * pszFilename,
+                                     GDALDataset *poSrcDS,
+                                     int bStrict, char ** papszOptions,
+                                     GDALProgressFunc pfnProgress,
+                                     void * pProgressData )
+{
+/* -------------------------------------------------------------------- */
+/*      Some some rudimentary checks                                    */
+/* -------------------------------------------------------------------- */
+    int nBands = poSrcDS->GetRasterCount();
+    if (nBands == 0)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "ZMap driver does not support source dataset with zero band.\n");
+        return NULL;
+    }
+
+    if (nBands != 1)
+    {
+        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
+                  "ZMap driver only uses the first band of the dataset.\n");
+        if (bStrict)
+            return NULL;
+    }
+
+    if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Get source dataset info                                         */
+/* -------------------------------------------------------------------- */
+
+    int nXSize = poSrcDS->GetRasterXSize();
+    int nYSize = poSrcDS->GetRasterYSize();
+    if (nXSize == 1 || nYSize == 1)
+    {
+        return NULL;
+    }
+    
+    double adfGeoTransform[6];
+    poSrcDS->GetGeoTransform(adfGeoTransform);
+    if (adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "ZMap driver does not support CreateCopy() from skewed or rotated dataset.\n");
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create target file                                              */
+/* -------------------------------------------------------------------- */
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
+    if (fp == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Cannot create %s", pszFilename );
+        return NULL;
+    }
+
+    int nFieldSize = 20;
+    int nValuesPerLine = 4;
+    int nDecimalCount = 7;
+
+    int bHasNoDataValue = FALSE;
+    double dfNoDataValue =
+        poSrcDS->GetRasterBand(1)->GetNoDataValue(&bHasNoDataValue);
+    if (!bHasNoDataValue)
+        dfNoDataValue = 1.e30;
+
+    VSIFPrintfL(fp, "!\n");
+    VSIFPrintfL(fp, "! Created by GDAL.\n");
+    VSIFPrintfL(fp, "!\n");
+    VSIFPrintfL(fp, "@GRID FILE, GRID, %d\n", nValuesPerLine);
+
+    WriteRightJustified(fp, nFieldSize, 10);
+    VSIFPrintfL(fp, ",");
+    WriteRightJustified(fp, dfNoDataValue, 10);
+    VSIFPrintfL(fp, ",");
+    WriteRightJustified(fp, "", 10);
+    VSIFPrintfL(fp, ",");
+    WriteRightJustified(fp, nDecimalCount, 10);
+    VSIFPrintfL(fp, ",");
+    WriteRightJustified(fp, 1, 10);
+    VSIFPrintfL(fp, "\n");
+
+    WriteRightJustified(fp, nYSize, 10);
+    VSIFPrintfL(fp, ",");
+    WriteRightJustified(fp, nXSize, 10);
+    VSIFPrintfL(fp, ",");
+
+    if (CSLTestBoolean(CPLGetConfigOption("ZMAP_PIXEL_IS_POINT", "FALSE")))
+    {
+        WriteRightJustified(fp, adfGeoTransform[0] + adfGeoTransform[1] / 2, 14, 7);
+        VSIFPrintfL(fp, ",");
+        WriteRightJustified(fp, adfGeoTransform[0] + adfGeoTransform[1] * nXSize -
+                                adfGeoTransform[1] / 2, 14, 7);
+        VSIFPrintfL(fp, ",");
+        WriteRightJustified(fp, adfGeoTransform[3] + adfGeoTransform[5] * nYSize -
+                                adfGeoTransform[5] / 2, 14, 7);
+        VSIFPrintfL(fp, ",");
+        WriteRightJustified(fp, adfGeoTransform[3] + adfGeoTransform[5] / 2, 14, 7);
+    }
+    else
+    {
+        WriteRightJustified(fp, adfGeoTransform[0], 14, 7);
+        VSIFPrintfL(fp, ",");
+        WriteRightJustified(fp, adfGeoTransform[0] + adfGeoTransform[1] * nXSize, 14, 7);
+        VSIFPrintfL(fp, ",");
+        WriteRightJustified(fp, adfGeoTransform[3] + adfGeoTransform[5] * nYSize, 14, 7);
+        VSIFPrintfL(fp, ",");
+        WriteRightJustified(fp, adfGeoTransform[3], 14, 7);
+    }
+
+    VSIFPrintfL(fp, "\n");
+
+    VSIFPrintfL(fp, "0.0, 0.0, 0.0\n");
+    VSIFPrintfL(fp, "@\n");
+
+/* -------------------------------------------------------------------- */
+/*      Copy imagery                                                    */
+/* -------------------------------------------------------------------- */
+    double* padfLineBuffer = (double*) CPLMalloc(nYSize * sizeof(double));
+    int i, j;
+    CPLErr eErr = CE_None;
+    for(i=0;i<nXSize && eErr == CE_None;i++)
+    {
+        eErr = poSrcDS->GetRasterBand(1)->RasterIO(
+                                            GF_Read, i, 0, 1, nYSize,
+                                            padfLineBuffer, 1, nYSize,
+                                            GDT_Float64, 0, 0);
+        if (eErr != CE_None)
+            break;
+        int bEOLPrinted = FALSE;
+        for(j=0;j<nYSize;j++)
+        {
+            WriteRightJustified(fp, padfLineBuffer[j], nFieldSize, nDecimalCount);
+            if (((j + 1) % nValuesPerLine) == 0)
+            {
+                bEOLPrinted = TRUE;
+                VSIFPrintfL(fp, "\n");
+            }
+            else
+                bEOLPrinted = FALSE;
+        }
+        if (!bEOLPrinted)
+            VSIFPrintfL(fp, "\n");
+
+        if (!pfnProgress( (j+1) * 1.0 / nYSize, NULL, pProgressData))
+            break;
+    }
+    CPLFree(padfLineBuffer);
+    VSIFCloseL(fp);
+
+    if (eErr != CE_None)
+        return NULL;
+
+    return (GDALDataset*) GDALOpen(pszFilename, GA_ReadOnly);
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr ZMapDataset::GetGeoTransform( double * padfTransform )
+
+{
+    memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
+
+    return( CE_None );
+}
+
+/************************************************************************/
+/*                         GDALRegister_ZMap()                          */
+/************************************************************************/
+
+void GDALRegister_ZMap()
+
+{
+    GDALDriver  *poDriver;
+
+    if( GDALGetDriverByName( "ZMap" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "ZMap" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                   "ZMap Plus Grid" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                                   "frmt_various.html#ZMap" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dat" );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnOpen = ZMapDataset::Open;
+        poDriver->pfnIdentify = ZMapDataset::Identify;
+        poDriver->pfnCreateCopy = ZMapDataset::CreateCopy;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
+
diff --git a/gcore/gdal.h b/gcore/gdal.h
index bce8ddf..07c286d 100644
--- a/gcore/gdal.h
+++ b/gcore/gdal.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.h 20854 2010-10-17 10:01:22Z rouault $
+ * $Id: gdal.h 23431 2011-11-27 15:02:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C/Public declarations.
@@ -221,16 +221,16 @@ void CPL_DLL CPL_STDCALL GDALAllRegister( void );
 
 GDALDatasetH CPL_DLL CPL_STDCALL GDALCreate( GDALDriverH hDriver,
                                  const char *, int, int, int, GDALDataType,
-                                 char ** );
+                                 char ** ) CPL_WARN_UNUSED_RESULT;
 GDALDatasetH CPL_DLL CPL_STDCALL
 GDALCreateCopy( GDALDriverH, const char *, GDALDatasetH,
-                int, char **, GDALProgressFunc, void * );
+                int, char **, GDALProgressFunc, void * ) CPL_WARN_UNUSED_RESULT;
 
 GDALDriverH CPL_DLL CPL_STDCALL GDALIdentifyDriver( const char * pszFilename,
                                             char ** papszFileList );
 GDALDatasetH CPL_DLL CPL_STDCALL
-GDALOpen( const char *pszFilename, GDALAccess eAccess );
-GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared( const char *, GDALAccess );
+GDALOpen( const char *pszFilename, GDALAccess eAccess ) CPL_WARN_UNUSED_RESULT;
+GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared( const char *, GDALAccess ) CPL_WARN_UNUSED_RESULT;
 int          CPL_DLL CPL_STDCALL GDALDumpOpenDatasets( FILE * );
 
 GDALDriverH CPL_DLL CPL_STDCALL GDALGetDriverByName( const char * );
diff --git a/gcore/gdal_frmts.h b/gcore/gdal_frmts.h
index 7f8f7c1..f574d5f 100644
--- a/gcore/gdal_frmts.h
+++ b/gcore/gdal_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_frmts.h 21249 2010-12-13 23:43:02Z rouault $
+ * $Id: gdal_frmts.h 23473 2011-12-05 22:17:02Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Prototypes for all format specific driver initializations.
@@ -39,6 +39,7 @@ void CPL_DLL GDALRegister_GXF(void);
 void CPL_DLL GDALRegister_OGDI(void);
 void CPL_DLL GDALRegister_HFA(void);
 void CPL_DLL GDALRegister_AAIGrid(void);
+void CPL_DLL GDALRegister_GRASSASCIIGrid(void);
 void CPL_DLL GDALRegister_AIGrid(void);
 void CPL_DLL GDALRegister_AIGrid2(void);
 void CPL_DLL GDALRegister_CEOS(void);
@@ -55,6 +56,7 @@ void CPL_DLL GDALRegister_DTED(void);
 void CPL_DLL GDALRegister_MFF(void);
 void CPL_DLL GDALRegister_HKV(void);
 void CPL_DLL GDALRegister_PNG(void);
+void CPL_DLL GDALRegister_GTA(void);
 void CPL_DLL GDALRegister_JPEG(void);
 void CPL_DLL GDALRegister_JPEG2000(void);
 void CPL_DLL GDALRegister_JP2KAK(void);
@@ -86,6 +88,7 @@ void CPL_DLL GDALRegister_BMP(void);
 void CPL_DLL GDALRegister_GSC(void);
 void CPL_DLL GDALRegister_NITF(void);
 void CPL_DLL GDALRegister_RPFTOC(void);
+void CPL_DLL GDALRegister_ECRGTOC(void);
 void CPL_DLL GDALRegister_MrSID(void);
 void CPL_DLL GDALRegister_MG4Lidar(void);
 void CPL_DLL GDALRegister_PCIDSK(void);
@@ -160,6 +163,13 @@ void CPL_DLL GDALRegister_HF2(void);
 void CPL_DLL GDALRegister_PDF(void);
 void CPL_DLL GDALRegister_JPEGLS(void);
 void CPL_DLL GDALRegister_OZI(void);
+void CPL_DLL GDALRegister_ACE2(void);
+void CPL_DLL GDALRegister_CTG(void);
+void CPL_DLL GDALRegister_E00GRID(void);
+void CPL_DLL GDALRegister_SNODAS(void);
+void CPL_DLL GDALRegister_WEBP(void);
+void CPL_DLL GDALRegister_ZMap(void);
+void CPL_DLL GDALRegister_NGSGEOID(void);
 CPL_C_END
 
 #endif /* ndef GDAL_FRMTS_H_INCLUDED */
diff --git a/gcore/gdal_misc.cpp b/gcore/gdal_misc.cpp
index bc22294..40e6616 100644
--- a/gcore/gdal_misc.cpp
+++ b/gcore/gdal_misc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_misc.cpp 21408 2011-01-05 19:26:04Z rouault $
+ * $Id: gdal_misc.cpp 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Free standing functions for GDAL.
@@ -34,7 +34,7 @@
 #include <ctype.h>
 #include <string>
 
-CPL_CVSID("$Id: gdal_misc.cpp 21408 2011-01-05 19:26:04Z rouault $");
+CPL_CVSID("$Id: gdal_misc.cpp 23156 2011-10-01 15:34:16Z rouault $");
 
 #include "ogr_spatialref.h"
 
@@ -208,7 +208,7 @@ GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
  *
  * Returns the size of a a GDT_* type in bits, <b>not bytes</b>!
  *
- * @param data type, such as GDT_Byte. 
+ * @param eDataType type, such as GDT_Byte.
  * @return the number of bits or zero if it is not recognised.
  */
 
@@ -1029,6 +1029,79 @@ GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
 
     return pasReturn;
 }
+
+/************************************************************************/
+/*                       GDALFindAssociatedFile()                       */
+/************************************************************************/
+
+/**
+ * Find file with alternate extension.
+ *
+ * Finds the file with the indicated extension, substituting it in place
+ * of the extension of the base filename.  Generally used to search for 
+ * associated files like world files .RPB files, etc.  If necessary, the
+ * extension will be tried in both upper and lower case.  If a sibling file
+ * list is available it will be used instead of doing VSIStatExL() calls to 
+ * probe the file system.  
+ *
+ * Note that the result is a dynamic CPLString so this method should not 
+ * be used in a situation where there could be cross heap issues.  It is
+ * generally imprudent for application built on GDAL to use this function
+ * unless they are sure they will always use the same runtime heap as GDAL.
+ *
+ * @param pszBaseFilename the filename relative to which to search.
+ * @param pszExt the target extension in either upper or lower case.
+ * @param papszSiblingFiles the list of files in the same directory as 
+ * pszBaseFilename or NULL if they are not known. 
+ * @param nFlags special options controlling search.  None defined yet, just 
+ * pass 0.
+ * 
+ * @return an empty string if the target is not found, otherwise the target
+ * file with similar path style as the pszBaseFilename. 
+ */
+
+CPLString GDALFindAssociatedFile( const char *pszBaseFilename, 
+                                  const char *pszExt,
+                                  char **papszSiblingFiles, 
+                                  int nFlags )
+
+{
+    (void) nFlags;
+
+    CPLString osTarget = CPLResetExtension( pszBaseFilename, pszExt );
+
+    if( papszSiblingFiles == NULL )
+    {
+        VSIStatBufL sStatBuf;
+
+        if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
+        {
+            CPLString osAltExt = pszExt;
+
+            if( islower( pszExt[0] ) )
+                osAltExt.toupper();
+            else
+                osAltExt.tolower();
+
+            osTarget = CPLResetExtension( pszBaseFilename, osAltExt );
+
+            if( VSIStatExL( osTarget, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
+                return "";
+        }
+    }
+    else
+    {
+        int iSibling = CSLFindString( papszSiblingFiles, 
+                                      CPLGetFilename(osTarget) );
+        if( iSibling < 0 )
+            return "";
+
+        osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
+        osTarget += papszSiblingFiles[iSibling];
+    }
+
+    return osTarget;
+}
                              
 /************************************************************************/
 /*                         GDALLoadOziMapFile()                         */
@@ -1441,13 +1514,48 @@ int CPL_STDCALL GDALReadTabFile( const char * pszBaseFilename,
 
 
 {
+    return GDALReadTabFile2(pszBaseFilename, padfGeoTransform,
+                            ppszWKT, pnGCPCount, ppasGCPs,
+                            NULL, NULL);
+}
+
+
+int GDALReadTabFile2( const char * pszBaseFilename,
+                      double *padfGeoTransform, char **ppszWKT,
+                      int *pnGCPCount, GDAL_GCP **ppasGCPs,
+                      char** papszSiblingFiles, char** ppszTabFileNameOut )
+{
     const char	*pszTAB;
     VSILFILE	*fpTAB;
 
+    if (ppszTabFileNameOut)
+        *ppszTabFileNameOut = NULL;
+
+    pszTAB = CPLResetExtension( pszBaseFilename, "tab" );
+
+    if (papszSiblingFiles)
+    {
+        int iSibling = CSLFindString(papszSiblingFiles, CPLGetFilename(pszTAB));
+        if (iSibling >= 0)
+        {
+            CPLString osTabFilename = pszBaseFilename;
+            osTabFilename.resize(strlen(pszBaseFilename) -
+                                 strlen(CPLGetFilename(pszBaseFilename)));
+            osTabFilename += papszSiblingFiles[iSibling];
+            if ( GDALLoadTabFile(osTabFilename, padfGeoTransform, ppszWKT,
+                                 pnGCPCount, ppasGCPs ) )
+            {
+                if (ppszTabFileNameOut)
+                    *ppszTabFileNameOut = CPLStrdup(osTabFilename);
+                return TRUE;
+            }
+        }
+        return FALSE;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Try lower case, then upper case.                                */
 /* -------------------------------------------------------------------- */
-    pszTAB = CPLResetExtension( pszBaseFilename, "tab" );
 
     fpTAB = VSIFOpenL( pszTAB, "rt" );
 
@@ -1465,8 +1573,14 @@ int CPL_STDCALL GDALReadTabFile( const char * pszBaseFilename,
 /* -------------------------------------------------------------------- */
 /*      We found the file, now load and parse it.                       */
 /* -------------------------------------------------------------------- */
-    return GDALLoadTabFile( pszTAB, padfGeoTransform, ppszWKT,
-                            pnGCPCount, ppasGCPs );
+    if (GDALLoadTabFile( pszTAB, padfGeoTransform, ppszWKT,
+                         pnGCPCount, ppasGCPs ) )
+    {
+        if (ppszTabFileNameOut)
+            *ppszTabFileNameOut = CPLStrdup(pszTAB);
+        return TRUE;
+    }
+    return FALSE;
 }
 
 /************************************************************************/
@@ -1597,6 +1711,14 @@ GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
                    double *padfGeoTransform )
 
 {
+    return GDALReadWorldFile2(pszBaseFilename, pszExtension,
+                              padfGeoTransform, NULL, NULL);
+}
+
+int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
+                        double *padfGeoTransform, char** papszSiblingFiles,
+                        char** ppszWorldFileNameOut )
+{
     const char  *pszTFW;
     char        szExtUpper[32], szExtLower[32];
     int         i;
@@ -1604,6 +1726,9 @@ GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
     VALIDATE_POINTER1( pszBaseFilename, "GDALReadWorldFile", FALSE );
     VALIDATE_POINTER1( padfGeoTransform, "GDALReadWorldFile", FALSE );
 
+    if (ppszWorldFileNameOut)
+        *ppszWorldFileNameOut = NULL;
+
 /* -------------------------------------------------------------------- */
 /*      If we aren't given an extension, try both the unix and          */
 /*      windows style extensions.                                       */
@@ -1622,8 +1747,9 @@ GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
         szDerivedExtension[2] = 'w';
         szDerivedExtension[3] = '\0';
         
-        if( GDALReadWorldFile( pszBaseFilename, szDerivedExtension, 
-                               padfGeoTransform ) )
+        if( GDALReadWorldFile2( pszBaseFilename, szDerivedExtension,
+                                padfGeoTransform, papszSiblingFiles,
+                                ppszWorldFileNameOut ) )
             return TRUE;
 
         // unix version - extension + 'w'
@@ -1632,8 +1758,9 @@ GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
 
         strcpy( szDerivedExtension, oBaseExt.c_str() );
         strcat( szDerivedExtension, "w" );
-        return GDALReadWorldFile( pszBaseFilename, szDerivedExtension, 
-                                  padfGeoTransform );
+        return GDALReadWorldFile2( pszBaseFilename, szDerivedExtension,
+                                  padfGeoTransform, papszSiblingFiles,
+                                  ppszWorldFileNameOut );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1654,14 +1781,34 @@ GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
         szExtLower[i] = (char) tolower(szExtLower[i]);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try lower case, then upper case.                                */
-/* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
     int bGotTFW;
 
     pszTFW = CPLResetExtension( pszBaseFilename, szExtLower );
 
+    if (papszSiblingFiles)
+    {
+        int iSibling = CSLFindString(papszSiblingFiles, CPLGetFilename(pszTFW));
+        if (iSibling >= 0)
+        {
+            CPLString osTFWFilename = pszBaseFilename;
+            osTFWFilename.resize(strlen(pszBaseFilename) -
+                                 strlen(CPLGetFilename(pszBaseFilename)));
+            osTFWFilename += papszSiblingFiles[iSibling];
+            if (GDALLoadWorldFile( osTFWFilename, padfGeoTransform ))
+            {
+                if (ppszWorldFileNameOut)
+                    *ppszWorldFileNameOut = CPLStrdup(osTFWFilename);
+                return TRUE;
+            }
+        }
+        return FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try lower case, then upper case.                                */
+/* -------------------------------------------------------------------- */
+
     bGotTFW = VSIStatExL( pszTFW, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0;
 
     if( !bGotTFW  && VSIIsCaseSensitiveFS(pszTFW) )
@@ -1676,7 +1823,13 @@ GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
 /* -------------------------------------------------------------------- */
 /*      We found the file, now load and parse it.                       */
 /* -------------------------------------------------------------------- */
-    return GDALLoadWorldFile( pszTFW, padfGeoTransform );
+    if (GDALLoadWorldFile( pszTFW, padfGeoTransform ))
+    {
+        if (ppszWorldFileNameOut)
+            *ppszWorldFileNameOut = CPLStrdup(pszTFW);
+        return TRUE;
+    }
+    return FALSE;
 }
 
 /************************************************************************/
@@ -2155,6 +2308,8 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
  *  --config key value: set system configuration option. 
  *  --debug [on/off/value]: set debug level.
  *  --mempreload dir: preload directory contents into /vsimem
+ *  --pause: Pause for user input (allows time to attach debugger)
+ *  --locale [locale]: Install a locale using setlocale() (debugging)
  *  --help-general: report detailed help on general options. 
  *
  * The argument array is replaced "in place" and should be freed with 
@@ -2171,7 +2326,8 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
  *        exit( -argc );
  *
  * @param nArgc number of values in the argument list.
- * @param Pointer to the argument list array (will be updated in place). 
+ * @param ppapszArgv pointer to the argument list array (will be updated in place).
+ * @param nOptions unused for now.
  *
  * @return updated nArgc argument count.  Return of 0 requests terminate 
  * without error, return of -1 requests exit with error code.
@@ -2480,6 +2636,8 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
             printf( "  --optfile filename: expand an option file into the argument list.\n" );
             printf( "  --config key value: set system configuration option.\n" );
             printf( "  --debug [on/off/value]: set debug level.\n" );
+            printf( "  --pause: wait for user input, time to attach debugger\n" );
+            printf( "  --locale [locale]: install locale for debugging (ie. en_US.UTF-8)\n" );
             printf( "  --help-general: report detailed help on general options.\n" );
             CSLDestroy( papszReturn );
             return 0;
@@ -2494,6 +2652,15 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
         }
 
 /* -------------------------------------------------------------------- */
+/*      --pause                                                         */
+/* -------------------------------------------------------------------- */
+        else if( EQUAL(papszArgv[iArg],"--pause") )
+        {
+            printf( "Hit <ENTER> to Continue.\n" );
+            CPLReadLine( stdin );
+        }
+
+/* -------------------------------------------------------------------- */
 /*      carry through unrecognised options.                             */
 /* -------------------------------------------------------------------- */
         else
diff --git a/gcore/gdal_pam.h b/gcore/gdal_pam.h
index c2a5f3c..4c07008 100644
--- a/gcore/gdal_pam.h
+++ b/gcore/gdal_pam.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_pam.h 21291 2010-12-19 20:42:06Z rouault $
+ * $Id: gdal_pam.h 22920 2011-08-10 21:08:07Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Declaration for Peristable Auxilary Metadata classes.
@@ -67,6 +67,7 @@ class GDALPamRasterBand;
                                  GCIF_BAND_DESCRIPTION) 
 
 /* GDAL PAM Flags */
+/* ERO 2011/04/13 : GPF_AUXMODE seems to be unimplemented */
 #define GPF_DIRTY		0x01  // .pam file needs to be written on close
 #define GPF_TRIED_READ_FAILED   0x02  // no need to keep trying to read .pam.
 #define GPF_DISABLED            0x04  // do not try any PAM stuff. 
@@ -108,6 +109,9 @@ class CPL_DLL GDALPamDataset : public GDALDataset
 {
     friend class GDALPamRasterBand;
 
+  private:
+    int IsPamFilenameAPotentialSiblingFile();
+
   protected:
                 GDALPamDataset(void);
 
@@ -117,10 +121,10 @@ class CPL_DLL GDALPamDataset : public GDALDataset
     virtual CPLXMLNode *SerializeToXML( const char *);
     virtual CPLErr      XMLInit( CPLXMLNode *, const char * );
     
-    virtual CPLErr TryLoadXML();
+    virtual CPLErr TryLoadXML(char **papszSiblingFiles = NULL);
     virtual CPLErr TrySaveXML();
 
-    CPLErr  TryLoadAux();
+    CPLErr  TryLoadAux(char **papszSiblingFiles = NULL);
     CPLErr  TrySaveAux();
 
     virtual const char *BuildPamFilename();
diff --git a/gcore/gdal_priv.h b/gcore/gdal_priv.h
index 0b5da1a..91f14d9 100644
--- a/gcore/gdal_priv.h
+++ b/gcore/gdal_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_priv.h 21431 2011-01-07 22:24:09Z warmerdam $
+ * $Id: gdal_priv.h 23431 2011-11-27 15:02:24Z rouault $
  *
  * Name:     gdal_priv.h
  * Project:  GDAL Core
@@ -73,7 +73,7 @@ class CPL_DLL GDALMultiDomainMetadata
 {
 private:
     char **papszDomainList;
-    char ***papapszMetadataLists;
+    CPLStringList **papoMetadataLists;
 
 public:
     GDALMultiDomainMetadata();
@@ -171,6 +171,8 @@ class CPL_DLL GDALDefaultOverviews
 
     int        IsInitialized();
 
+    int        CloseDependentDatasets();
+
     // Overview Related
 
     int        GetOverviewCount(int);
@@ -201,6 +203,35 @@ class CPL_DLL GDALDefaultOverviews
     int        HaveMaskFile( char **papszSiblings = NULL, 
                              const char *pszBasename = NULL );
 
+    char**     GetSiblingFiles() { return papszInitSiblingFiles; }
+};
+
+/* ******************************************************************** */
+/*                             GDALOpenInfo                             */
+/*                                                                      */
+/*      Structure of data about dataset for open functions.             */
+/* ******************************************************************** */
+
+class CPL_DLL GDALOpenInfo
+{
+  public:
+                GDALOpenInfo( const char * pszFile, GDALAccess eAccessIn,
+                              char **papszSiblingFiles = NULL );
+                ~GDALOpenInfo( void );
+
+    char        *pszFilename;
+    char        **papszSiblingFiles;
+
+    GDALAccess  eAccess;
+
+    int         bStatOK;
+    int         bIsDirectory;
+
+    FILE        *fp;
+
+    int         nHeaderBytes;
+    GByte       *pabyHeader;
+
 };
 
 /* ******************************************************************** */
@@ -210,6 +241,8 @@ class CPL_DLL GDALDefaultOverviews
 /* Internal method for now. Might be subject to later revisions */
 GDALDatasetH GDALOpenInternal( const char * pszFilename, GDALAccess eAccess,
                                const char* const * papszAllowedDrivers);
+GDALDatasetH GDALOpenInternal( GDALOpenInfo& oOpenInfo,
+                               const char* const * papszAllowedDrivers);
 
 //! A set of associated raster bands, usually from one file.
 
@@ -220,10 +253,13 @@ class CPL_DLL GDALDataset : public GDALMajorObject
 
     /* Internal method for now. Might be subject to later revisions */
     friend GDALDatasetH GDALOpenInternal( const char *, GDALAccess, const char* const * papszAllowedDrivers);
+    friend GDALDatasetH GDALOpenInternal( GDALOpenInfo& oOpenInfo,
+                                          const char* const * papszAllowedDrivers);
 
     friend class GDALDriver;
     friend class GDALDefaultOverviews;
     friend class GDALProxyDataset;
+    friend class GDALDriverManager;
 
   protected:
     GDALDriver  *poDriver;
@@ -258,6 +294,8 @@ class CPL_DLL GDALDataset : public GDALMajorObject
                                int, int *, int, int, int );
     void   BlockBasedFlushCache();
 
+    virtual int         CloseDependentDatasets();
+
     friend class GDALRasterBand;
     
   public:
@@ -321,6 +359,8 @@ class CPL_DLL GDALDataset : public GDALMajorObject
 
     CPLErr BuildOverviews( const char *, int, int *,
                            int, int *, GDALProgressFunc, void * );
+
+    void ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
 };
 
 /* ******************************************************************** */
@@ -563,6 +603,8 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     virtual GDALRasterBand *GetMaskBand();
     virtual int             GetMaskFlags();
     virtual CPLErr          CreateMaskBand( int nFlags );
+
+    void ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
 };
 
 /* ******************************************************************** */
@@ -616,34 +658,6 @@ class CPL_DLL GDALNoDataValuesMaskBand : public GDALRasterBand
 };
 
 /* ******************************************************************** */
-/*                             GDALOpenInfo                             */
-/*                                                                      */
-/*      Structure of data about dataset for open functions.             */
-/* ******************************************************************** */
-
-class CPL_DLL GDALOpenInfo
-{
-  public:
-                GDALOpenInfo( const char * pszFile, GDALAccess eAccessIn,
-                              char **papszSiblingFiles = NULL );
-                ~GDALOpenInfo( void );
-    
-    char        *pszFilename;
-    char        **papszSiblingFiles;
-
-    GDALAccess  eAccess;
-
-    int         bStatOK;
-    int         bIsDirectory;
-
-    FILE        *fp;
-
-    int         nHeaderBytes;
-    GByte       *pabyHeader;
-
-};
-
-/* ******************************************************************** */
 /*                              GDALDriver                              */
 /* ******************************************************************** */
 
@@ -670,7 +684,7 @@ class CPL_DLL GDALDriver : public GDALMajorObject
 /* -------------------------------------------------------------------- */
     GDALDataset         *Create( const char * pszName,
                                  int nXSize, int nYSize, int nBands,
-                                 GDALDataType eType, char ** papszOptions );
+                                 GDALDataType eType, char ** papszOptions ) CPL_WARN_UNUSED_RESULT;
 
     CPLErr              Delete( const char * pszName );
     CPLErr              Rename( const char * pszNewName,
@@ -681,7 +695,7 @@ class CPL_DLL GDALDriver : public GDALMajorObject
     GDALDataset         *CreateCopy( const char *, GDALDataset *, 
                                      int, char **,
                                      GDALProgressFunc pfnProgress, 
-                                     void * pProgressData );
+                                     void * pProgressData ) CPL_WARN_UNUSED_RESULT;
     
 /* -------------------------------------------------------------------- */
 /*      The following are semiprivate, not intended to be accessed      */
@@ -719,7 +733,7 @@ class CPL_DLL GDALDriver : public GDALMajorObject
     GDALDataset         *DefaultCreateCopy( const char *, GDALDataset *, 
                                             int, char **,
                                             GDALProgressFunc pfnProgress, 
-                                            void * pProgressData );
+                                            void * pProgressData ) CPL_WARN_UNUSED_RESULT;
     static CPLErr        DefaultCopyMasks( GDALDataset *poSrcDS, 
                                            GDALDataset *poDstDS, 
                                            int bStrict );
@@ -895,13 +909,23 @@ int CPL_DLL GDALCheckDatasetDimensions( int nXSize, int nYSize );
 int CPL_DLL GDALCheckBandCount( int nBands, int bIsZeroAllowed );
 
 
-// Test if pixel value matches nodata value. Avoid using strict comparison as
-// the stored nodata value in GeoTIFF files is stored as a string, so there might
-// be numerical imprecision when reading it back. See #3573
-#define EQUAL_TO_NODATA(dfValue, dfNoDataValue) \
- (dfValue == dfNoDataValue || (dfNoDataValue != 0 && fabs(1 - dfValue / dfNoDataValue) < 1e-10 ))
+// Test if 2 floating point values match. Usefull when comparing values
+// stored as a string at some point. See #3573, #4183
+#define ARE_REAL_EQUAL(dfVal1, dfVal2) \
+ (fabs(dfVal1 - dfVal2) < 1e-10 || (dfVal2 != 0 && fabs(1 - dfVal1 / dfVal2) < 1e-10 ))
 
+/* Internal use only */
+int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
+                        double *padfGeoTransform, char** papszSiblingFiles,
+                        char** ppszWorldFileNameOut);
+int GDALReadTabFile2( const char * pszBaseFilename,
+                      double *padfGeoTransform, char **ppszWKT,
+                      int *pnGCPCount, GDAL_GCP **ppasGCPs,
+                      char** papszSiblingFiles, char** ppszTabFileNameOut );
 
 CPL_C_END
 
+CPLString GDALFindAssociatedFile( const char *pszBasename, const char *pszExt,
+                                  char **papszSiblingFiles, int nFlags );
+
 #endif /* ndef GDAL_PRIV_H_INCLUDED */
diff --git a/gcore/gdal_rat.cpp b/gcore/gdal_rat.cpp
index 3ef6df5..149de81 100644
--- a/gcore/gdal_rat.cpp
+++ b/gcore/gdal_rat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: gdal_rat.cpp 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterAttributeTable and related classes.
@@ -30,7 +30,7 @@
 #include "gdal_priv.h"
 #include "gdal_rat.h"
 
-CPL_CVSID("$Id: gdal_rat.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: gdal_rat.cpp 23156 2011-10-01 15:34:16Z rouault $");
 
 /**
  * \class GDALRasterAttributeTable
@@ -1262,7 +1262,7 @@ CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT,
  *
  * @param poTable the color table to copy from.
  *
- * @param CE_None on success or CE_Failure if something goes wrong.
+ * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr GDALRasterAttributeTable::InitializeFromColorTable( 
diff --git a/gcore/gdal_rpcimdio.cpp b/gcore/gdal_rpcimdio.cpp
index 24192c2..d3204d6 100644
--- a/gcore/gdal_rpcimdio.cpp
+++ b/gcore/gdal_rpcimdio.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rpcimdio.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gdal_rpcimdio.cpp 22057 2011-03-28 15:20:21Z warmerdam $
  *
  * Project:  GDAL Core
  * Purpose:  Functions for reading RPC and IMD formats, and normalizing.
@@ -29,10 +29,11 @@
  ****************************************************************************/
 
 #include "gdal.h"
+#include "gdal_priv.h"
 #include "cpl_string.h"
 #include "cplkeywordparser.h"
 
-CPL_CVSID("$Id: gdal_rpcimdio.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: gdal_rpcimdio.cpp 22057 2011-03-28 15:20:21Z warmerdam $");
 
 /************************************************************************/
 /*                          GDALLoadRPBFile()                           */
@@ -62,33 +63,11 @@ char **CPL_STDCALL GDALLoadRPBFile( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to identify the RPB file in upper or lower case.            */
 /* -------------------------------------------------------------------- */
-    CPLString osTarget = CPLResetExtension( pszFilename, "RPB" );
+    CPLString osTarget = GDALFindAssociatedFile( pszFilename, "RPB", 
+                                                 papszSiblingFiles, 0 );
 
-    /* Is this already a RPB file ? */
-    if (EQUAL(CPLGetExtension(pszFilename), "RPB"))
-        osTarget = pszFilename;
-    else if( papszSiblingFiles == NULL )
-    {
-        VSIStatBufL sStatBuf;
-        
-        if( VSIStatL( osTarget, &sStatBuf ) != 0 )
-        {
-            osTarget = CPLResetExtension( pszFilename, "rpb" );
-
-            if( VSIStatL( osTarget, &sStatBuf ) != 0 )
-                return NULL;
-        }
-    }
-    else
-    {
-        int iSibling = CSLFindString( papszSiblingFiles, 
-                                      CPLGetFilename(osTarget) );
-        if( iSibling < 0 )
-            return NULL;
-
-        osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
-        osTarget += papszSiblingFiles[iSibling];
-    }
+    if( osTarget == "" )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Read file and parse.                                            */
@@ -506,33 +485,11 @@ char ** CPL_STDCALL GDALLoadIMDFile( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Try to identify the IMD file in upper or lower case.            */
 /* -------------------------------------------------------------------- */
-    CPLString osTarget = CPLResetExtension( pszFilename, "IMD" );
+    CPLString osTarget = GDALFindAssociatedFile( pszFilename, "IMD", 
+                                                 papszSiblingFiles, 0 );
 
-    /* Is this already a IMD file ? */
-    if (EQUAL(CPLGetExtension(pszFilename), "IMD"))
-        osTarget = pszFilename;
-    else if( papszSiblingFiles == NULL )
-    {
-        VSIStatBufL sStatBuf;
-        
-        if( VSIStatL( osTarget, &sStatBuf ) != 0 )
-        {
-            osTarget = CPLResetExtension( pszFilename, "imd" );
-
-            if( VSIStatL( osTarget, &sStatBuf ) != 0 )
-                return NULL;
-        }
-    }
-    else
-    {
-        int iSibling = CSLFindString( papszSiblingFiles, 
-                                      CPLGetFilename(osTarget) );
-        if( iSibling < 0 )
-            return NULL;
-
-        osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
-        osTarget += papszSiblingFiles[iSibling];
-    }
+    if( osTarget == "" )
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Read file and parse.                                            */
@@ -604,7 +561,6 @@ CPLErr CPL_STDCALL GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 
 {
     CPLString osRPBFilename = CPLResetExtension( pszFilename, "IMD" );
-    
 
 /* -------------------------------------------------------------------- */
 /*      Read file and parse.                                            */
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index 0ef1a5d..56392d7 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    8
-#  define GDAL_VERSION_REV      1
+#  define GDAL_VERSION_MINOR    9
+#  define GDAL_VERSION_REV      0
 #  define GDAL_VERSION_BUILD    0
 #endif
 
@@ -15,9 +15,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20110709
+#  define GDAL_RELEASE_DATE     20111229
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "1.8.1"
+#  define GDAL_RELEASE_NAME     "1.9.0"
 #endif
-
diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp
index 7b25541..e250dc1 100644
--- a/gcore/gdaldataset.cpp
+++ b/gcore/gdaldataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldataset.cpp 21440 2011-01-08 17:06:36Z rouault $
+ * $Id: gdaldataset.cpp 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for raster file formats.  
@@ -32,7 +32,7 @@
 #include "cpl_hash_set.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdaldataset.cpp 21440 2011-01-08 17:06:36Z rouault $");
+CPL_CVSID("$Id: gdaldataset.cpp 23156 2011-10-01 15:34:16Z rouault $");
 
 CPL_C_START
 GDALAsyncReader *
@@ -475,7 +475,7 @@ CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions )
     (void) eType;
     (void) papszOptions;
 
-    CPLError( CE_Failure, CPLE_NotSupported, 
+    ReportError( CE_Failure, CPLE_NotSupported,
               "Dataset does not support the AddBand() method." );
 
     return CE_Failure;
@@ -526,7 +526,7 @@ void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
                            MAX(nNewBand,nBands));
         if (papoNewBands == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
+            ReportError(CE_Failure, CPLE_OutOfMemory,
                      "Cannot allocate band array");
             return;
         }
@@ -543,7 +543,7 @@ void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
 /* -------------------------------------------------------------------- */
     if( papoBands[nNewBand-1] != NULL )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
+        ReportError(CE_Failure, CPLE_NotSupported,
                  "Cannot set band %d as it is already set", nNewBand);
         return;
     }
@@ -663,7 +663,7 @@ GDALRasterBand * GDALDataset::GetRasterBand( int nBandId )
     {
         if( nBandId < 1 || nBandId > nBands )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg,
+            ReportError( CE_Failure, CPLE_IllegalArg,
                       "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
                       nBandId );
             return NULL;
@@ -792,11 +792,11 @@ const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
  * @return CE_Failure if an error occurs, otherwise CE_None.
  */
 
-CPLErr GDALDataset::SetProjection( const char * )
+CPLErr GDALDataset::SetProjection( const char * pszProjection )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "Dataset does not support the SetProjection() method." );
     return CE_Failure;
 }
@@ -908,11 +908,11 @@ CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS, double * padfTransform
  * written.
  */
 
-CPLErr GDALDataset::SetGeoTransform( double * )
+CPLErr GDALDataset::SetGeoTransform( double * padfTransform )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetGeoTransform() not supported for this dataset." );
     
     return( CE_Failure );
@@ -1138,7 +1138,7 @@ void GDALDataset::MarkAsShared()
     if(CPLHashSetLookup(phSharedDatasetSet, psStruct) != NULL)
     {
         CPLFree(psStruct);
-        CPLError(CE_Failure, CPLE_AppDefined,
+        ReportError(CE_Failure, CPLE_AppDefined,
                  "An existing shared dataset has already this description. This should not happen");
     }
     else
@@ -1304,7 +1304,7 @@ CPLErr GDALDataset::SetGCPs( int nGCPCount,
     (void) pszGCPProjection;
 
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "Dataset does not support the SetGCPs() method." );
 
     return CE_Failure;
@@ -1348,7 +1348,7 @@ CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
  * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
  * @param nOverviews number of overviews to build. 
  * @param panOverviewList the list of overview decimation factors to build. 
- * @param nBand number of bands to build overviews for in panBandList.  Build
+ * @param nListBands number of bands to build overviews for in panBandList.  Build
  * for all bands if this is 0. 
  * @param panBandList list of band numbers. 
  * @param pfnProgress a function to call to report progress, or NULL.
@@ -1445,7 +1445,7 @@ CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
                                           pfnProgress, pProgressData );
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "BuildOverviews() not supported for this dataset." );
         
         return( CE_Failure );
@@ -1491,6 +1491,12 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
         GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
         GByte *pabyBandData;
 
+        if (poBand == NULL)
+        {
+            eErr = CE_Failure;
+            break;
+        }
+
         pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
         
         eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
@@ -1592,7 +1598,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 
     if( NULL == pData )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        ReportError( CE_Failure, CPLE_AppDefined,
                   "The buffer into which the data should be read is null" );
             return CE_Failure;
     }
@@ -1624,7 +1630,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     {
         if (nPixelSpace > INT_MAX / nBufXSize)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            ReportError( CE_Failure, CPLE_AppDefined,
                       "Int overflow : %d x %d", nPixelSpace, nBufXSize );
             return CE_Failure;
         }
@@ -1638,7 +1644,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     {
         if (nLineSpace > INT_MAX / nBufYSize)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            ReportError( CE_Failure, CPLE_AppDefined,
                       "Int overflow : %d x %d", nLineSpace, nBufYSize );
             return CE_Failure;
         }
@@ -1649,7 +1655,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     {
         if (nBandCount > GetRasterCount())
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            ReportError( CE_Failure, CPLE_IllegalArg,
                       "nBandCount cannot be greater than %d",
                       GetRasterCount() );
             return CE_Failure;
@@ -1657,7 +1663,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
         panBandMap = (int *) VSIMalloc2(sizeof(int), nBandCount);
         if (panBandMap == NULL)
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, 
+            ReportError( CE_Failure, CPLE_OutOfMemory,
                       "Out of memory while allocating band map array" );
             return CE_Failure;
         }
@@ -1673,7 +1679,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
         || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        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 );
@@ -1682,7 +1688,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 
     if( eRWFlag != GF_Read && eRWFlag != GF_Write )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
                   eRWFlag );
         eErr = CE_Failure;
@@ -1692,7 +1698,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     {
         if( panBandMap[i] < 1 || panBandMap[i] > GetRasterCount() )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            ReportError( CE_Failure, CPLE_IllegalArg,
                       "panBandMap[%d] = %d, this band does not exist on dataset.",
                       i, panBandMap[i] );
             eErr = CE_Failure;
@@ -1700,7 +1706,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 
         if( eErr == CE_None && GetRasterBand( panBandMap[i] ) == NULL )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg, 
+            ReportError( CE_Failure, CPLE_IllegalArg,
                       "panBandMap[%d]=%d, this band should exist but is NULL!",
                       i, panBandMap[i] );
             eErr = CE_Failure;
@@ -1906,7 +1912,7 @@ int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
 
 CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                 int nBufXSize, int nBufYSize, 
-                                GDALDataType eDT, 
+                                GDALDataType eBufType, 
                                 int nBandCount, int *panBandMap,
                                 char **papszOptions )
 
@@ -1924,7 +1930,7 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
             poBand = GetRasterBand(panBandMap[iBand]);
 
         eErr = poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize,
-                                   nBufXSize, nBufYSize, eDT, papszOptions );
+                                   nBufXSize, nBufYSize, eBufType, papszOptions );
 
         if( eErr != CE_None )
             return eErr;
@@ -1972,7 +1978,7 @@ GDALDatasetAdviseRead( GDALDatasetH hDS,
  * 
  * The returned filenames will normally be relative or absolute paths 
  * depending on the path used to originally open the dataset.  The strings
- * will be UTF8 encoded.
+ * will be UTF-8 encoded.
  *
  * This method is the same as the C GDALGetFileList() function.
  *
@@ -2034,8 +2040,20 @@ char **GDALDataset::GetFileList()
             szDerivedExtension[2] = 'w';
             szDerivedExtension[3] = '\0';
             CPLString osWorldFilename = CPLResetExtension( osMainFilename, szDerivedExtension );
-            
-            if( VSIStatExL( osWorldFilename, &sStat, VSI_STAT_EXISTS_FLAG ) == 0 )
+
+            if (oOvManager.papszInitSiblingFiles)
+            {
+                int iSibling = CSLFindString(oOvManager.papszInitSiblingFiles,
+                                             CPLGetFilename(osWorldFilename));
+                if (iSibling >= 0)
+                {
+                    osWorldFilename.resize(strlen(osWorldFilename) -
+                                           strlen(oOvManager.papszInitSiblingFiles[iSibling]));
+                    osWorldFilename += oOvManager.papszInitSiblingFiles[iSibling];
+                    papszList = CSLAddString( papszList, osWorldFilename );
+                }
+            }
+            else if( VSIStatExL( osWorldFilename, &sStat, VSI_STAT_EXISTS_FLAG ) == 0 )
                 papszList = CSLAddString( papszList, osWorldFilename );
         }
     }
@@ -2111,7 +2129,7 @@ CPLErr GDALDataset::CreateMaskBand( int nFlags )
         return CE_None;
     }
 
-    CPLError( CE_Failure, CPLE_NotSupported,
+    ReportError( CE_Failure, CPLE_NotSupported,
               "CreateMaskBand() not supported for this dataset." );
     
     return( CE_Failure );
@@ -2156,11 +2174,15 @@ CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
  * use.) </li>
  * </ul>
  *
+ * For drivers supporting the VSI virtual file API, it is possible to open
+ * a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
+ * (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+ *
  * \sa GDALOpenShared()
  *
  * @param pszFilename the name of the file to access.  In the case of
  * exotic drivers this may not refer to a physical file, but instead contain
- * information for the driver on how to access a dataset.  It should be in UTF8
+ * information for the driver on how to access a dataset.  It should be in UTF-8
  * encoding.
  *
  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
@@ -2182,11 +2204,18 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
 GDALDatasetH GDALOpenInternal( const char * pszFilename, GDALAccess eAccess,
                                const char* const * papszAllowedDrivers)
 {
-    VALIDATE_POINTER1( pszFilename, "GDALOpen", NULL );
+    GDALOpenInfo oOpenInfo( pszFilename, eAccess );
+    return GDALOpenInternal(oOpenInfo, papszAllowedDrivers);
+}
+
+GDALDatasetH GDALOpenInternal( GDALOpenInfo& oOpenInfo,
+                               const char* const * papszAllowedDrivers)
+{
+
+    VALIDATE_POINTER1( oOpenInfo.pszFilename, "GDALOpen", NULL );
 
     int         iDriver;
     GDALDriverManager *poDM = GetGDALDriverManager();
-    GDALOpenInfo oOpenInfo( pszFilename, eAccess );
     CPLLocaleC  oLocaleForcer;
 
     CPLErrorReset();
@@ -2216,11 +2245,11 @@ GDALDatasetH GDALOpenInternal( const char * pszFilename, GDALAccess eAccess,
 
             if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
                 CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s (pid=%d, responsiblePID=%d).",
-                          pszFilename, poDS, poDriver->GetDescription(),
+                          oOpenInfo.pszFilename, poDS, poDriver->GetDescription(),
                           (int)CPLGetPID(), (int)GDALGetResponsiblePIDForCurrentThread() );
             else
                 CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
-                          pszFilename, poDS, poDriver->GetDescription() );
+                          oOpenInfo.pszFilename, poDS, poDriver->GetDescription() );
 
             return (GDALDatasetH) poDS;
         }
@@ -2232,12 +2261,12 @@ GDALDatasetH GDALOpenInternal( const char * pszFilename, GDALAccess eAccess,
     if( oOpenInfo.bStatOK )
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "`%s' not recognised as a supported file format.\n",
-                  pszFilename );
+                  oOpenInfo.pszFilename );
     else
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "`%s' does not exist in the file system,\n"
                   "and is not recognised as a supported dataset name.\n",
-                  pszFilename );
+                  oOpenInfo.pszFilename );
 
     return NULL;
 }
@@ -2262,12 +2291,16 @@ GDALDatasetH GDALOpenInternal( const char * pszFilename, GDALAccess eAccess,
  * it is not safe to use the same dataset from different threads, unless the user
  * does explicitely use mutexes in its code.
  *
+ * For drivers supporting the VSI virtual file API, it is possible to open
+ * a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
+ * (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+ *
  * \sa GDALOpen()
  *
  * @param pszFilename the name of the file to access.  In the case of
  * exotic drivers this may not refer to a physical file, but instead contain
  * information for the driver on how to access a dataset.  It should be in 
- * UTF8 encoding.
+ * UTF-8 encoding.
  *
  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
  * drivers support only read only access.
@@ -2630,3 +2663,79 @@ void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsyncRea
     ((GDALDataset *) hDS) -> EndAsyncReader((GDALAsyncReader *)hAsyncReaderH);	
 }
 
+/************************************************************************/
+/*                       CloseDependentDatasets()                       */
+/************************************************************************/
+
+/**
+ * Drop references to any other datasets referenced by this dataset.
+ *
+ * This method should release any reference to other datasets (e.g. a VRT
+ * dataset to its sources), but not close the current dataset itself.
+ *
+ * If at least, one reference to a dependant dataset has been dropped,
+ * this method should return TRUE. Otherwise it *should* return FALSE.
+ * (Failure to return the proper value might result in infinite loop)
+ *
+ * This method can be called several times on a given dataset. After
+ * the first time, it should not do anything and return FALSE.
+ *
+ * The driver implementation may choose to destroy its raster bands,
+ * so be careful not to call any method on the raster bands afterwards.
+ *
+ * Basically the only safe action you can do after calling CloseDependantDatasets()
+ * is to call the destructor.
+ *
+ * Note: the only legitimate caller of CloseDependantDatasets() is
+ * GDALDriverManager::~GDALDriverManager()
+ *
+ * @return TRUE if at least one reference to another dataset has been dropped.
+ */
+int GDALDataset::CloseDependentDatasets()
+{
+    return oOvManager.CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                            ReportError()                             */
+/************************************************************************/
+
+/**
+ * \brief Emits an error related to a dataset.
+ *
+ * This function is a wrapper for regular CPLError(). The only difference
+ * with CPLError() is that it prepends the error message with the dataset
+ * name.
+ *
+ * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
+ * @param err_no the error number (CPLE_*) from cpl_error.h.
+ * @param fmt a printf() style format string.  Any additional arguments
+ * will be treated as arguments to fill in this format in a manner
+ * similar to printf().
+ *
+ * @since GDAL 1.9.0
+ */
+
+void GDALDataset::ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+
+    char szNewFmt[256];
+    const char* pszDSName = GetDescription();
+    if (strlen(fmt) + strlen(pszDSName) + 3 >= sizeof(szNewFmt) - 1)
+        pszDSName = CPLGetFilename(pszDSName);
+    if (pszDSName[0] != '\0' &&
+        strlen(fmt) + strlen(pszDSName) + 3 < sizeof(szNewFmt) - 1)
+    {
+        snprintf(szNewFmt, sizeof(szNewFmt), "%s: %s",
+                 pszDSName, fmt);
+        CPLErrorV( eErrClass, err_no, szNewFmt, args );
+    }
+    else
+    {
+        CPLErrorV( eErrClass, err_no, fmt, args );
+    }
+    va_end(args);
+}
diff --git a/gcore/gdaldefaultoverviews.cpp b/gcore/gdaldefaultoverviews.cpp
index d0a8e08..df2a1cf 100644
--- a/gcore/gdaldefaultoverviews.cpp
+++ b/gcore/gdaldefaultoverviews.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldefaultoverviews.cpp 20750 2010-10-04 18:36:48Z rouault $
+ * $Id: gdaldefaultoverviews.cpp 22381 2011-05-16 21:14:22Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Helper code to implement overview and mask support for many 
@@ -31,7 +31,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaldefaultoverviews.cpp 20750 2010-10-04 18:36:48Z rouault $");
+CPL_CVSID("$Id: gdaldefaultoverviews.cpp 22381 2011-05-16 21:14:22Z rouault $");
 
 /************************************************************************/
 /*                        GDALDefaultOverviews()                        */
@@ -66,8 +66,19 @@ GDALDefaultOverviews::~GDALDefaultOverviews()
     CPLFree( pszInitName );
     CSLDestroy( papszInitSiblingFiles );
 
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                       CloseDependentDatasets()                       */
+/************************************************************************/
+
+int GDALDefaultOverviews::CloseDependentDatasets()
+{
+    int bHasDroppedRef = FALSE;
     if( poODS != NULL )
     {
+        bHasDroppedRef = TRUE;
         poODS->FlushCache();
         GDALClose( poODS );
         poODS = NULL;
@@ -77,11 +88,14 @@ GDALDefaultOverviews::~GDALDefaultOverviews()
     {
         if( bOwnMaskDS )
         {
+            bHasDroppedRef = TRUE;
             poMaskDS->FlushCache();
             GDALClose( poMaskDS );
         }
         poMaskDS = NULL;
     }
+
+    return bHasDroppedRef;
 }
 
 /************************************************************************/
@@ -189,7 +203,9 @@ void GDALDefaultOverviews::OverviewScan()
 
         if( bExists )
         {
-            poODS = (GDALDataset*) GDALOpen( osOvrFilename, poDS->GetAccess() );
+            GDALOpenInfo oOpenInfo(osOvrFilename, poDS->GetAccess(),
+                                   papszInitSiblingFiles);
+            poODS = (GDALDataset*) GDALOpenInternal( oOpenInfo, NULL );
         }
     }
 
@@ -203,8 +219,28 @@ void GDALDefaultOverviews::OverviewScan()
 /* -------------------------------------------------------------------- */
     if( !poODS && !EQUAL(pszInitName,":::VIRTUAL:::") )
     {
-        poODS = GDALFindAssociatedAuxFile( pszInitName, poDS->GetAccess(),
-                                           poDS );
+        int bTryFindAssociatedAuxFile = TRUE;
+        if( papszInitSiblingFiles )
+        {
+            CPLString osAuxFilename = CPLResetExtension( pszInitName, "aux");
+            int iSibling = CSLFindString( papszInitSiblingFiles,
+                                        CPLGetFilename(osAuxFilename) );
+            if( iSibling < 0 )
+            {
+                osAuxFilename = pszInitName;
+                osAuxFilename += ".aux";
+                iSibling = CSLFindString( papszInitSiblingFiles,
+                                        CPLGetFilename(osAuxFilename) );
+                if( iSibling < 0 )
+                    bTryFindAssociatedAuxFile = FALSE;
+            }
+        }
+
+        if (bTryFindAssociatedAuxFile)
+        {
+            poODS = GDALFindAssociatedAuxFile( pszInitName, poDS->GetAccess(),
+                                            poDS );
+        }
 
         if( poODS )
         {
@@ -668,8 +704,9 @@ GDALDefaultOverviews::BuildOverviews(
                     (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
 
                 if( nOvFactor == - panOverviewList[i] 
-                    || nOvFactor == GDALOvLevelAdjust( -panOverviewList[i], 
-                                                       poBand->GetXSize() ) )
+                    || (panOverviewList[i] < 0 &&
+                        nOvFactor == GDALOvLevelAdjust( -panOverviewList[i],
+                                                       poBand->GetXSize() )) )
                 {
                     papoOverviewBands[nNewOverviews++] = poOverview;
                     break;
@@ -955,7 +992,7 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
         pszBasename = poDS->GetDescription();
 
     // Don't bother checking for masks of masks. 
-    if( EQUAL(CPLGetExtension(pszBasename),".msk") )
+    if( EQUAL(CPLGetExtension(pszBasename),"msk") )
         return FALSE;
 
     osMskFilename.Printf( "%s.msk", pszBasename );
@@ -978,7 +1015,9 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    poMaskDS = (GDALDataset *) GDALOpen( osMskFilename, poDS->GetAccess() );
+    GDALOpenInfo oOpenInfo(osMskFilename, poDS->GetAccess(),
+                           papszInitSiblingFiles);
+    poMaskDS = (GDALDataset *) GDALOpenInternal( oOpenInfo, NULL );
     CPLAssert( poMaskDS != poDS );
 
     if( poMaskDS == NULL )
diff --git a/gcore/gdaldriver.cpp b/gcore/gdaldriver.cpp
index 793398b..27bcbf6 100644
--- a/gcore/gdaldriver.cpp
+++ b/gcore/gdaldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldriver.cpp 21431 2011-01-07 22:24:09Z warmerdam $
+ * $Id: gdaldriver.cpp 22294 2011-05-03 18:38:45Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriver class (and C wrappers)
@@ -29,7 +29,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdaldriver.cpp 21431 2011-01-07 22:24:09Z warmerdam $");
+CPL_CVSID("$Id: gdaldriver.cpp 22294 2011-05-03 18:38:45Z rouault $");
 
 /************************************************************************/
 /*                             GDALDriver()                             */
@@ -240,23 +240,26 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
          iBand++ )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
-        GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
 
         int nMaskFlags = poSrcBand->GetMaskFlags();
         if( eErr == CE_None
             && !(nMaskFlags & (GMF_ALL_VALID|GMF_PER_DATASET|GMF_ALPHA|GMF_NODATA) ) )
         {
-            eErr = poDstBand->CreateMaskBand( nMaskFlags );
-            if( eErr == CE_None )
+            GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
+            if (poDstBand != NULL)
             {
-                eErr = GDALRasterBandCopyWholeRaster(
-                    poSrcBand->GetMaskBand(),
-                    poDstBand->GetMaskBand(),
-                    (char**)papszOptions,
-                    GDALDummyProgress, NULL);
+                eErr = poDstBand->CreateMaskBand( nMaskFlags );
+                if( eErr == CE_None )
+                {
+                    eErr = GDALRasterBandCopyWholeRaster(
+                        poSrcBand->GetMaskBand(),
+                        poDstBand->GetMaskBand(),
+                        (char**)papszOptions,
+                        GDALDummyProgress, NULL);
+                }
+                else if( !bStrict )
+                    eErr = CE_None;
             }
-            else if( !bStrict )
-                eErr = CE_None;
         }
     }
 
diff --git a/gcore/gdaldrivermanager.cpp b/gcore/gdaldrivermanager.cpp
index c53a890..003c305 100644
--- a/gcore/gdaldrivermanager.cpp
+++ b/gcore/gdaldrivermanager.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldrivermanager.cpp 18770 2010-02-09 01:29:11Z hobu $
+ * $Id: gdaldrivermanager.cpp 23175 2011-10-04 21:28:28Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriverManager class.
@@ -34,7 +34,7 @@
 #include "cpl_multiproc.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: gdaldrivermanager.cpp 18770 2010-02-09 01:29:11Z hobu $");
+CPL_CVSID("$Id: gdaldrivermanager.cpp 23175 2011-10-04 21:28:28Z rouault $");
 
 static const char *pszUpdatableINST_DATA = 
 "__INST_DATA_TARGET:                                                                                                                                      ";
@@ -124,16 +124,69 @@ GDALDriverManager::GDALDriverManager()
 
 /************************************************************************/
 /*                         ~GDALDriverManager()                         */
-/*                                                                      */
-/*      Eventually this should also likely clean up all open            */
-/*      datasets.  Or perhaps the drivers that own them should do       */
-/*      that in their destructor?                                       */
 /************************************************************************/
 
+void GDALDatasetPoolPreventDestroy(); /* keep that in sync with gdalproxypool.cpp */
+void GDALDatasetPoolForceDestroy(); /* keep that in sync with gdalproxypool.cpp */
+
 GDALDriverManager::~GDALDriverManager()
 
 {
 /* -------------------------------------------------------------------- */
+/*      Cleanup any open datasets.                                      */
+/* -------------------------------------------------------------------- */
+    int i, nDSCount;
+    GDALDataset **papoDSList;
+
+    /* First begin by requesting each reamining dataset to drop any reference */
+    /* to other datasets */
+    int bHasDroppedRef;
+
+    /* We have to prevent the destroying of the dataset pool during this first */
+    /* phase, otherwise it cause crashes with a VRT B referencing a VRT A, and if */
+    /* CloseDependentDatasets() is called first on VRT A. */
+    /* If we didn't do this nasty trick, due to the refCountOfDisableRefCount */
+    /* mechanism that cheats the real refcount of the dataset pool, we might */
+    /* destroy the dataset pool too early, leading the VRT A to */
+    /* destroy itself indirectly ... Ok, I am aware this explanation does */
+    /* not make any sense unless you try it under a debugger ... */
+    /* When people just manipulate "top-level" dataset handles, we luckily */
+    /* don't need this horrible hack, but GetOpenDatasets() expose "low-level" */
+    /* datasets, which defeat some "design" of the proxy pool */
+    GDALDatasetPoolPreventDestroy();
+
+    do
+    {
+        papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
+        /* If a dataset has dropped a reference, the list might have become */
+        /* invalid, so go out of the loop and try again with the new valid */
+        /* list */
+        bHasDroppedRef = FALSE;
+        for(i=0;i<nDSCount && !bHasDroppedRef;i++)
+        {
+            //CPLDebug("GDAL", "Call CloseDependentDatasets() on %s",
+            //      papoDSList[i]->GetDescription() );
+            bHasDroppedRef = papoDSList[i]->CloseDependentDatasets();
+        }
+    } while(bHasDroppedRef);
+
+    /* Now let's destroy the dataset pool. Nobody shoud use it afterwards */
+    /* if people have well released their dependent datasets above */
+    GDALDatasetPoolForceDestroy();
+
+    /* Now close the stand-alone datasets */
+    papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
+    for(i=0;i<nDSCount;i++)
+    {
+        CPLDebug( "GDAL", "force close of %s in GDALDriverManager cleanup.",
+                  papoDSList[i]->GetDescription() );
+        /* 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 */
+        delete papoDSList[i];
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Destroy the existing drivers.                                   */
 /* -------------------------------------------------------------------- */
     while( GetDriverCount() > 0 )
@@ -181,6 +234,15 @@ GDALDriverManager::~GDALDriverManager()
     CPLCleanupTLS();
 
 /* -------------------------------------------------------------------- */
+/*      Cleanup our mutex.                                              */
+/* -------------------------------------------------------------------- */
+    if( hDMMutex )
+    {
+        CPLDestroyMutex( hDMMutex );
+        hDMMutex = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Ensure the global driver manager pointer is NULLed out.         */
 /* -------------------------------------------------------------------- */
     if( poDM == this )
@@ -483,7 +545,7 @@ void GDALDriverManager::SetHome( const char * pszNewHome )
  * \brief This method unload undesirable drivers.
  *
  * All drivers specified in the space delimited list in the GDAL_SKIP 
- * environmentvariable) will be deregistered and destroyed.  This method 
+ * environment variable) will be deregistered and destroyed.  This method 
  * should normally be called after registration of standard drivers to allow 
  * the user a way of unloading undesired drivers.  The GDALAllRegister()
  * function already invokes AutoSkipDrivers() at the end, so if that functions
@@ -611,11 +673,26 @@ void GDALDriverManager::AutoLoadDrivers()
     }
 
 /* -------------------------------------------------------------------- */
+/*      Format the ABI version specific subdirectory to look in.        */
+/* -------------------------------------------------------------------- */
+    CPLString osABIVersion;
+
+    osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
+
+/* -------------------------------------------------------------------- */
 /*      Scan each directory looking for files starting with gdal_       */
 /* -------------------------------------------------------------------- */
     for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
     {
-        char  **papszFiles = CPLReadDir( papszSearchPath[iDir] );
+        char **papszFiles = NULL;
+        VSIStatBufL sStatBuf;
+        CPLString osABISpecificDir =
+            CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
+        
+        if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
+            osABISpecificDir = papszSearchPath[iDir];
+
+        papszFiles = CPLReadDir( osABISpecificDir );
 
         for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
         {
@@ -637,14 +714,23 @@ void GDALDriverManager::AutoLoadDrivers()
                      CPLGetBasename(papszFiles[iFile]) + 5 );
             
             pszFilename = 
-                CPLFormFilename( papszSearchPath[iDir], 
+                CPLFormFilename( osABISpecificDir, 
                                  papszFiles[iFile], NULL );
 
+            CPLErrorReset();
+            CPLPushErrorHandler(CPLQuietErrorHandler);
             pRegister = CPLGetSymbol( pszFilename, pszFuncName );
+            CPLPopErrorHandler();
             if( pRegister == NULL )
             {
+                CPLString osLastErrorMsg(CPLGetLastErrorMsg());
                 strcpy( pszFuncName, "GDALRegisterMe" );
                 pRegister = CPLGetSymbol( pszFilename, pszFuncName );
+                if( pRegister == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "%s", osLastErrorMsg.c_str() );
+                }
             }
             
             if( pRegister != NULL )
diff --git a/gcore/gdaljp2box.cpp b/gcore/gdaljp2box.cpp
index bd13260..fd82a15 100644
--- a/gcore/gdaljp2box.cpp
+++ b/gcore/gdaljp2box.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2box.cpp 22592 2011-06-27 12:27:36Z warmerdam $
+ * $Id: gdaljp2box.cpp 23076 2011-09-07 18:28:51Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  GDALJP2Box Implementation - Low level JP2 box reader.
@@ -30,7 +30,7 @@
 #include "gdaljp2metadata.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaljp2box.cpp 22592 2011-06-27 12:27:36Z warmerdam $");
+CPL_CVSID("$Id: gdaljp2box.cpp 23076 2011-09-07 18:28:51Z rouault $");
 
 /************************************************************************/
 /*                             GDALJP2Box()                             */
@@ -291,10 +291,7 @@ void GDALJP2Box::SetType( const char *pszType )
 {
     CPLAssert( strlen(pszType) == 4 );
 
-    szBoxType[0] = pszType[3];
-    szBoxType[1] = pszType[2];
-    szBoxType[2] = pszType[1];
-    szBoxType[3] = pszType[0];
+    memcpy(szBoxType, pszType, 4);
     szBoxType[4] = '\0';
 }
 
@@ -365,15 +362,13 @@ GDALJP2Box *GDALJP2Box::CreateAsocBox( int nCount, GDALJP2Box **papoBoxes )
 /* -------------------------------------------------------------------- */
     for( iBox = 0; iBox < nCount; iBox++ )
     {
-        GUInt32   nLBox, nTBox;
+        GUInt32   nLBox;
 
         nLBox = CPL_MSBWORD32(papoBoxes[iBox]->nBoxLength);
         memcpy( pabyNext, &nLBox, 4 );
         pabyNext += 4;
 
-        memcpy( &nTBox, papoBoxes[iBox]->szBoxType, 4 );
-        nTBox = CPL_MSBWORD32( nTBox );
-        memcpy( pabyNext, &nTBox, 4 );
+        memcpy( pabyNext, papoBoxes[iBox]->szBoxType, 4 );
         pabyNext += 4;
 
         memcpy( pabyNext, papoBoxes[iBox]->pabyData, 
diff --git a/gcore/gdaljp2metadata.cpp b/gcore/gdaljp2metadata.cpp
index 32472fb..cde9230 100644
--- a/gcore/gdaljp2metadata.cpp
+++ b/gcore/gdaljp2metadata.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.cpp 22650 2011-07-06 00:59:22Z warmerdam $
+ * $Id: gdaljp2metadata.cpp 22678 2011-07-09 19:47:12Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  GDALJP2Metadata - Read GeoTIFF and/or GML georef info.
@@ -35,7 +35,7 @@
 #include "ogr_api.h"
 #include "gt_wkt_srs_for_gdal.h"
 
-CPL_CVSID("$Id: gdaljp2metadata.cpp 22650 2011-07-06 00:59:22Z warmerdam $");
+CPL_CVSID("$Id: gdaljp2metadata.cpp 22678 2011-07-09 19:47:12Z rouault $");
 
 static const unsigned char msi_uuid2[16] =
 {0xb1,0x4b,0xf8,0xbd,0x08,0x3d,0x4b,0x43,
@@ -45,6 +45,10 @@ static const unsigned char msig_uuid[16] =
 { 0x96,0xA9,0xF1,0xF1,0xDC,0x98,0x40,0x2D,
   0xA7,0xAE,0xD6,0x8E,0x34,0x45,0x18,0x09 };
 
+static const unsigned char xmp_uuid[16] =
+{ 0xBE,0x7A,0xCF,0xCB,0x97,0xA9,0x42,0xE8,
+  0x9C,0x71,0x99,0x94,0x91,0xE3,0xAF,0xAC};
+
 /************************************************************************/
 /*                          GDALJP2Metadata()                           */
 /************************************************************************/
@@ -58,6 +62,7 @@ GDALJP2Metadata::GDALJP2Metadata()
     pasGCPList = NULL;
 
     papszGMLMetadata = NULL;
+    papszMetadata = NULL;
 
     nGeoTIFFSize = 0;
     pabyGeoTIFFData = NULL;
@@ -65,6 +70,8 @@ GDALJP2Metadata::GDALJP2Metadata()
     nMSIGSize = 0;
     pabyMSIGData = NULL;
 
+    pszXMPMetadata = NULL;
+
     bHaveGeoTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -91,6 +98,8 @@ GDALJP2Metadata::~GDALJP2Metadata()
     CPLFree( pabyGeoTIFFData );
     CPLFree( pabyMSIGData );
     CSLDestroy( papszGMLMetadata );
+    CSLDestroy( papszMetadata );
+    CPLFree( pszXMPMetadata );
 }
 
 /************************************************************************/
@@ -211,7 +220,7 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         if( EQUAL(oBox.GetType(),"uuid") 
             && memcmp( oBox.GetUUID(), msi_uuid2, 16 ) == 0 )
         {
-	    nGeoTIFFSize = (int) oBox.GetDataLength();
+            nGeoTIFFSize = (int) oBox.GetDataLength();
             pabyGeoTIFFData = oBox.ReadBoxData();
         }
 
@@ -221,7 +230,7 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         if( EQUAL(oBox.GetType(),"uuid") 
             && memcmp( oBox.GetUUID(), msig_uuid, 16 ) == 0 )
         {
-	    nMSIGSize = (int) oBox.GetDataLength();
+            nMSIGSize = (int) oBox.GetDataLength();
             pabyMSIGData = oBox.ReadBoxData();
 
             if( nMSIGSize < 70 
@@ -234,6 +243,16 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         }
 
 /* -------------------------------------------------------------------- */
+/*      Collect XMP box.                                                */
+/* -------------------------------------------------------------------- */
+        if( EQUAL(oBox.GetType(),"uuid")
+            && memcmp( oBox.GetUUID(), xmp_uuid, 16 ) == 0 &&
+            pszXMPMetadata == NULL )
+        {
+            pszXMPMetadata = (char*) oBox.ReadBoxData();
+        }
+
+/* -------------------------------------------------------------------- */
 /*      Process asoc box looking for Labelled GML data.                 */
 /* -------------------------------------------------------------------- */
         if( EQUAL(oBox.GetType(),"asoc") )
@@ -306,17 +325,17 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
                             (nHorzNum/(double)nHorzDen) * pow(10.0,nHorzExp)/100;
                         CPLString osFormatter;
 
-                        papszGMLMetadata = CSLSetNameValue( 
-                            papszGMLMetadata, 
+                        papszMetadata = CSLSetNameValue( 
+                            papszMetadata, 
                             "TIFFTAG_XRESOLUTION",
                             osFormatter.Printf("%g",dfHorzRes) );
                         
-                        papszGMLMetadata = CSLSetNameValue( 
-                            papszGMLMetadata, 
+                        papszMetadata = CSLSetNameValue( 
+                            papszMetadata, 
                             "TIFFTAG_YRESOLUTION",
                             osFormatter.Printf("%g",dfVertRes) );
-                        papszGMLMetadata = CSLSetNameValue( 
-                            papszGMLMetadata, 
+                        papszMetadata = CSLSetNameValue( 
+                            papszMetadata, 
                             "TIFFTAG_RESOLUTIONUNIT", 
                             "3 (pixels/cm)" );
                         
@@ -986,7 +1005,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 "<gml:FeatureCollection\n"
 "   xmlns:gml=\"http://www.opengis.net/gml\"\n"
 "   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
-"   xsi:schemaLocation=\"http://www.opengeospatial.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlJP2Profile/1.0.0/gmlJP2Profile.xsd\">\n"
+"   xsi:schemaLocation=\"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlJP2Profile/1.0.0/gmlJP2Profile.xsd\">\n"
 "  <gml:boundedBy>\n"
 "    <gml:Null>withheld</gml:Null>\n"
 "  </gml:boundedBy>\n"
diff --git a/gcore/gdaljp2metadata.h b/gcore/gdaljp2metadata.h
index 9275430..35b7f31 100644
--- a/gcore/gdaljp2metadata.h
+++ b/gcore/gdaljp2metadata.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.h 22650 2011-07-06 00:59:22Z warmerdam $
+ * $Id: gdaljp2metadata.h 22678 2011-07-09 19:47:12Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  JP2 Box Reader (and GMLJP2 Interpreter)
@@ -122,6 +122,9 @@ public:
     int         nGCPCount;
     GDAL_GCP    *pasGCPList;
 
+    char  **papszMetadata;
+    char   *pszXMPMetadata;
+
 public:
             GDALJP2Metadata();
             ~GDALJP2Metadata();
diff --git a/gcore/gdalmajorobject.cpp b/gcore/gdalmajorobject.cpp
index 2e1404c..f6f27a1 100644
--- a/gcore/gdalmajorobject.cpp
+++ b/gcore/gdalmajorobject.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalmajorobject.cpp 18719 2010-02-04 16:42:38Z mloskot $
+ * $Id: gdalmajorobject.cpp 23156 2011-10-01 15:34:16Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for objects with metadata, etc.
@@ -30,7 +30,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalmajorobject.cpp 18719 2010-02-04 16:42:38Z mloskot $");
+CPL_CVSID("$Id: gdalmajorobject.cpp 23156 2011-10-01 15:34:16Z rouault $");
 
 /************************************************************************/
 /*                          GDALMajorObject()                           */
@@ -192,7 +192,7 @@ GDALGetMetadata( GDALMajorObjectH hObject, const char * pszDomain )
  *
  * The C function GDALSetMetadata() does the same thing as this method.
  *
- * @param papszMetadata the metadata in name=value string list format to 
+ * @param papszMetadataIn the metadata in name=value string list format to
  * apply.  
  * @param pszDomain the domain of interest.  Use "" or NULL for the default
  * domain. 
diff --git a/gcore/gdalmultidomainmetadata.cpp b/gcore/gdalmultidomainmetadata.cpp
index 68861e8..ce4f558 100644
--- a/gcore/gdalmultidomainmetadata.cpp
+++ b/gcore/gdalmultidomainmetadata.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalmultidomainmetadata.cpp 21812 2011-02-23 21:47:23Z rouault $
+ * $Id: gdalmultidomainmetadata.cpp 22798 2011-07-24 12:19:53Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALMultiDomainMetadata class.  This class
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include <map>
 
-CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 21812 2011-02-23 21:47:23Z rouault $");
+CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 22798 2011-07-24 12:19:53Z rouault $");
 
 /************************************************************************/
 /*                      GDALMultiDomainMetadata()                       */
@@ -42,7 +42,7 @@ GDALMultiDomainMetadata::GDALMultiDomainMetadata()
 
 {
     papszDomainList = NULL;
-    papapszMetadataLists = NULL;
+    papoMetadataLists = NULL;
 }
 
 /************************************************************************/
@@ -70,10 +70,10 @@ void GDALMultiDomainMetadata::Clear()
 
     for( i = 0; i < nDomainCount; i++ )
     {
-        CSLDestroy( papapszMetadataLists[i] );
+        delete papoMetadataLists[i];
     }
-    CPLFree( papapszMetadataLists );
-    papapszMetadataLists = NULL;
+    CPLFree( papoMetadataLists );
+    papoMetadataLists = NULL;
 }
 
 
@@ -92,7 +92,7 @@ char **GDALMultiDomainMetadata::GetMetadata( const char *pszDomain )
     if( iDomain == -1 )
         return NULL;
     else
-        return papapszMetadataLists[iDomain];
+        return papoMetadataLists[iDomain]->List();
 }
 
 /************************************************************************/
@@ -115,17 +115,20 @@ CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata,
         papszDomainList = CSLAddString( papszDomainList, pszDomain );
         nDomainCount = CSLCount( papszDomainList );
 
-        papapszMetadataLists = (char ***) 
-            CPLRealloc( papapszMetadataLists, sizeof(char*)*(nDomainCount+1) );
-        papapszMetadataLists[nDomainCount] = NULL;
-        papapszMetadataLists[nDomainCount-1] = CSLDuplicate( papszMetadata );
-    }
-    else
-    {
-        CSLDestroy( papapszMetadataLists[iDomain] );
-        papapszMetadataLists[iDomain] = CSLDuplicate( papszMetadata );
+        papoMetadataLists = (CPLStringList **) 
+            CPLRealloc( papoMetadataLists, sizeof(void*)*(nDomainCount+1) );
+        papoMetadataLists[nDomainCount] = NULL;
+        papoMetadataLists[nDomainCount-1] = new CPLStringList();
+        iDomain = nDomainCount-1;
     }
 
+    papoMetadataLists[iDomain]->Assign( CSLDuplicate( papszMetadata ) );
+
+    // we want to mark name/value pair domains as being sorted for fast
+    // access.
+    if( !EQUALN(pszDomain,"xml:",4) && !EQUAL(pszDomain, "SUBDATASETS") )
+        papoMetadataLists[iDomain]->Sort();
+
     return CE_None;
 }
 
@@ -137,11 +140,15 @@ const char *GDALMultiDomainMetadata::GetMetadataItem( const char *pszName,
                                                       const char *pszDomain )
 
 {
-    char **papszMD = GetMetadata( pszDomain );
-    if( papszMD != NULL )
-        return CSLFetchNameValue( papszMD, pszName );
-    else
+    if( pszDomain == NULL )
+        pszDomain = "";
+
+    int iDomain = CSLFindString( papszDomainList, pszDomain );
+
+    if( iDomain == -1 )
         return NULL;
+    else
+        return papoMetadataLists[iDomain]->FetchNameValue( pszName );
 }
 
 /************************************************************************/
@@ -156,46 +163,21 @@ CPLErr GDALMultiDomainMetadata::SetMetadataItem( const char *pszName,
     if( pszDomain == NULL )
         pszDomain = "";
 
-    int iDomain = CSLFindString( papszDomainList, pszDomain );
-
 /* -------------------------------------------------------------------- */
 /*      Create the domain if it does not already exist.                 */
 /* -------------------------------------------------------------------- */
+    int iDomain = CSLFindString( papszDomainList, pszDomain );
+
     if( iDomain == -1 )
     {
-        int nDomainCount;
-
-        papszDomainList = CSLAddString( papszDomainList, pszDomain );
-        nDomainCount = CSLCount( papszDomainList );
-
-        papapszMetadataLists = (char ***) 
-            CPLRealloc( papapszMetadataLists, sizeof(char*)*(nDomainCount+1) );
-        papapszMetadataLists[nDomainCount] = NULL;
-        iDomain = nDomainCount-1;
-        papapszMetadataLists[iDomain] = NULL;
+        SetMetadata( NULL, pszDomain );
+        iDomain = CSLFindString( papszDomainList, pszDomain );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set the value in the domain list.                               */
 /* -------------------------------------------------------------------- */
-    if( pszValue != NULL )
-    {
-        papapszMetadataLists[iDomain] = 
-            CSLSetNameValue( papapszMetadataLists[iDomain], 
-                             pszName, pszValue );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Remove the target key from the domain list.                     */
-/* -------------------------------------------------------------------- */
-    else
-    {
-        int iKey = CSLFindName( papapszMetadataLists[iDomain], pszName );
-
-        if( iKey != -1 )
-            papapszMetadataLists[iDomain] = 
-                CSLRemoveStrings(papapszMetadataLists[iDomain],iKey,1,NULL);
-    }
+    papoMetadataLists[iDomain]->SetNameValue( pszName, pszValue );
 
     return CE_None;
 }
@@ -218,7 +200,6 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, int bMerge )
     for( psMetadata = psTree->psChild; 
          psMetadata != NULL; psMetadata = psMetadata->psNext )
     {
-        char **papszMD = NULL;
         CPLXMLNode *psMDI;
         const char *pszDomain, *pszFormat;
 
@@ -229,6 +210,16 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, int bMerge )
         pszDomain = CPLGetXMLValue( psMetadata, "domain", "" );
         pszFormat = CPLGetXMLValue( psMetadata, "format", "" );
 
+        // Make sure we have a CPLStringList for this domain, 
+        // without wiping out an existing one.
+        if( GetMetadata( pszDomain ) == NULL )  
+            SetMetadata( NULL, pszDomain );
+
+        int iDomain = CSLFindString( papszDomainList, pszDomain );
+        CPLAssert( iDomain != -1 );
+        
+        CPLStringList *poMDList = papoMetadataLists[iDomain];
+
 /* -------------------------------------------------------------------- */
 /*      XML format subdocuments.                                        */
 /* -------------------------------------------------------------------- */
@@ -243,8 +234,7 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, int bMerge )
             
             char *pszDoc = CPLSerializeXMLTree( psSubDoc );
 
-            papszMD = (char **) CPLCalloc(sizeof(char*),2);
-            papszMD[0] = pszDoc;
+            poMDList->AddStringDirectly( pszDoc );
         }
 
 /* -------------------------------------------------------------------- */
@@ -253,87 +243,23 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, int bMerge )
 /* -------------------------------------------------------------------- */
         else
         {
-            /* Keep a map of keys to ensure that if duplicate keys are found */
-            /* in the metadata, the newer values will replace the older */
-            /* ones, as done with CSLSetNameValue() before r21714 */
-            std::map<CPLString, int> oMap;
-            if( bMerge )
-            {
-                papszMD = GetMetadata( pszDomain );
-                if( papszMD != NULL )
-                {
-                    papszMD = CSLDuplicate( papszMD );
-                    for(int i=0;papszMD[i] != NULL;i++)
-                    {
-                        char* pszKey = NULL;
-                        CPLParseNameValue(papszMD[i], &pszKey);
-                        if (pszKey)
-                        {
-                            oMap[pszKey] = i;
-                            CPLFree(pszKey);
-                        }
-                    }
-                }
-            }
-
-            int nCount = 0;
-            for( psMDI = psMetadata->psChild; psMDI != NULL; 
+            for( psMDI = psMetadata->psChild; psMDI != NULL;
                  psMDI = psMDI->psNext )
             {
-                if( !EQUAL(psMDI->pszValue,"MDI") 
-                    || psMDI->eType != CXT_Element 
-                    || psMDI->psChild == NULL 
-                    || psMDI->psChild->psNext == NULL 
+                if( !EQUAL(psMDI->pszValue,"MDI")
+                    || psMDI->eType != CXT_Element
+                    || psMDI->psChild == NULL
+                    || psMDI->psChild->psNext == NULL
                     || psMDI->psChild->eType != CXT_Attribute
                     || psMDI->psChild->psChild == NULL )
                     continue;
-                nCount ++;
-            }
 
-            if( nCount > 0 )
-            {
-                int nPrevSize = CSLCount(papszMD);
-                papszMD = (char**)CPLRealloc(papszMD,
-                            (nPrevSize + nCount + 1) * sizeof(char*));
-                int i = nPrevSize;
-                for( psMDI = psMetadata->psChild; psMDI != NULL;
-                     psMDI = psMDI->psNext )
-                {
-                    if( !EQUAL(psMDI->pszValue,"MDI")
-                        || psMDI->eType != CXT_Element
-                        || psMDI->psChild == NULL
-                        || psMDI->psChild->psNext == NULL
-                        || psMDI->psChild->eType != CXT_Attribute
-                        || psMDI->psChild->psChild == NULL )
-                        continue;
-
-                    char* pszName = psMDI->psChild->psChild->pszValue;
-                    char* pszValue = psMDI->psChild->psNext->pszValue;
-                    if( pszName != NULL && pszValue != NULL )
-                    {
-                        char* pszLine = (char *) CPLMalloc(strlen(pszName)+
-                                                        strlen(pszValue)+2);
-                        sprintf( pszLine, "%s=%s", pszName, pszValue );
-                        std::map<CPLString, int>::iterator iter = oMap.find(pszName);
-                        if (iter == oMap.end())
-                        {
-                            oMap[pszName] = i;
-                            papszMD[i++] = pszLine;
-                        }
-                        else
-                        {
-                            int iToReplace = iter->second;
-                            CPLFree(papszMD[iToReplace]);
-                            papszMD[iToReplace] = pszLine;
-                        }
-                    }
-                }
-                papszMD[i] = NULL;
+                char* pszName = psMDI->psChild->psChild->pszValue;
+                char* pszValue = psMDI->psChild->psNext->pszValue;
+                if( pszName != NULL && pszValue != NULL )
+                    poMDList->SetNameValue( pszName, pszValue );
             }
         }
-
-        SetMetadata( papszMD, pszDomain );
-        CSLDestroy( papszMD );
     }
 
     return CSLCount(papszDomainList) != 0;
@@ -352,7 +278,7 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
          papszDomainList != NULL && papszDomainList[iDomain] != NULL; 
          iDomain++)
     {
-        char **papszMD = papapszMetadataLists[iDomain];
+        char **papszMD = papoMetadataLists[iDomain]->List();
         CPLXMLNode *psMD;
         int bFormatXML = FALSE;
         
diff --git a/gcore/gdalnodatamaskband.cpp b/gcore/gdalnodatamaskband.cpp
index 9fdf9c1..612eb1b 100644
--- a/gcore/gdalnodatamaskband.cpp
+++ b/gcore/gdalnodatamaskband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalnodatamaskband.cpp 19692 2010-05-13 17:16:55Z rouault $
+ * $Id: gdalnodatamaskband.cpp 22857 2011-08-02 18:17:45Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALNoDataMaskBand, a class implementing all
@@ -30,7 +30,7 @@
 
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalnodatamaskband.cpp 19692 2010-05-13 17:16:55Z rouault $");
+CPL_CVSID("$Id: gdalnodatamaskband.cpp 22857 2011-08-02 18:17:45Z rouault $");
 
 /************************************************************************/
 /*                        GDALNoDataMaskBand()                          */
@@ -143,7 +143,10 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
                                pabySrc, nXSizeRequest, nYSizeRequest,
                                eWrkDT, 0, nBlockXSize * (GDALGetDataTypeSize(eWrkDT)/8) );
     if( eErr != CE_None )
+    {
+        CPLFree(pabySrc);
         return eErr;
+    }
 
     int bIsNoDataNan = CPLIsNan(dfNoDataValue);
 
@@ -204,7 +207,7 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
               float fVal =((float *)pabySrc)[i];
               if( bIsNoDataNan && CPLIsNan(fVal))
                   ((GByte *) pImage)[i] = 0;
-              else if( EQUAL_TO_NODATA(fVal, fNoData) )
+              else if( ARE_REAL_EQUAL(fVal, fNoData) )
                   ((GByte *) pImage)[i] = 0;
               else
                   ((GByte *) pImage)[i] = 255;
@@ -219,7 +222,7 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
               double dfVal =((double *)pabySrc)[i];
               if( bIsNoDataNan && CPLIsNan(dfVal))
                   ((GByte *) pImage)[i] = 0;
-              else if( EQUAL_TO_NODATA(dfVal, dfNoDataValue) )
+              else if( ARE_REAL_EQUAL(dfVal, dfNoDataValue) )
                   ((GByte *) pImage)[i] = 0;
               else
                   ((GByte *) pImage)[i] = 255;
diff --git a/gcore/gdalopeninfo.cpp b/gcore/gdalopeninfo.cpp
index 5fcf197..049d9ea 100644
--- a/gcore/gdalopeninfo.cpp
+++ b/gcore/gdalopeninfo.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalopeninfo.cpp 21447 2011-01-09 16:02:28Z rouault $
+ * $Id: gdalopeninfo.cpp 21991 2011-03-20 16:45:19Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALOpenInfo class.
@@ -34,7 +34,7 @@
 #include <unistd.h>
 #endif
 
-CPL_CVSID("$Id: gdalopeninfo.cpp 21447 2011-01-09 16:02:28Z rouault $");
+CPL_CVSID("$Id: gdalopeninfo.cpp 21991 2011-03-20 16:45:19Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -163,8 +163,13 @@ retry:
     }
     else if( bStatOK && !bIsDirectory )
     {
-        if( CSLTestBoolean( 
-                CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" )) )
+        const char* pszOptionVal =
+            CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
+        if (EQUAL(pszOptionVal, "EMPTY_DIR"))
+        {
+            papszSiblingFiles = CSLAddString( NULL, CPLGetFilename(pszFilename) );
+        }
+        else if( CSLTestBoolean(pszOptionVal) )
         {
             /* skip reading the directory */
             papszSiblingFiles = NULL;
diff --git a/gcore/gdalpamdataset.cpp b/gcore/gdalpamdataset.cpp
index 4620ad7..17cfd4a 100644
--- a/gcore/gdalpamdataset.cpp
+++ b/gcore/gdalpamdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalpamdataset.cpp 21295 2010-12-19 22:00:31Z rouault $
+ * $Id: gdalpamdataset.cpp 22922 2011-08-10 21:50:46Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamDataset, a dataset base class that 
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalpamdataset.cpp 21295 2010-12-19 22:00:31Z rouault $");
+CPL_CVSID("$Id: gdalpamdataset.cpp 22922 2011-08-10 21:50:46Z rouault $");
 
 /************************************************************************/
 /*                           GDALPamDataset()                           */
@@ -48,9 +48,10 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 21295 2010-12-19 22:00:31Z rouault $");
  * 
  * <h3>Enabling PAM</h3>
  * 
- * PAM support can be enabled in GDAL by setting the GDAL_PAM_ENABLED
+ * PAM support can be enabled (resp. disabled) in GDAL by setting the GDAL_PAM_ENABLED
  * configuration option (via CPLSetConfigOption(), or the environment) to 
- * the value of YES.  
+ * the value of YES (resp. NO). Note: The default value is build dependant and defaults
+ * to YES in Windows and Unix builds.
  *
  * <h3>PAM Proxy Files</h3>
  * 
@@ -58,10 +59,12 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 21295 2010-12-19 22:00:31Z rouault $");
  * read-only media such as CDROMs or in directories where the user does not
  * have write permissions, it is possible to enable the "PAM Proxy Database".
  * When enabled the .aux.xml files are kept in a different directory, writable
- * by the user. 
+ * by the user. Overviews will also be stored in the PAM proxy directory.
  *
- * To enable this, set the GDAL_PAM_PROXY_DIR configuration open to be
- * the name of the directory where the proxies should be kept.  
+ * To enable this, set the GDAL_PAM_PROXY_DIR configuration option to be
+ * the name of the directory where the proxies should be kept. The configuration
+ * option must be set *before* the first access to PAM, because its value is cached
+ * for later access.
  *
  * <h3>Adding PAM to Drivers</h3>
  *
@@ -219,17 +222,28 @@ CPLXMLNode *GDALPamDataset::SerializeToXML( const char *pszUnused )
         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( psPamGCPList, CXT_Element, "GCP" );
+            psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
+
+            if( psLastChild == NULL )
+                psPamGCPList->psChild = psXMLGCP;
+            else
+                psLastChild->psNext = psXMLGCP;
+            psLastChild = psXMLGCP;
 
             CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
 
@@ -311,6 +325,7 @@ void GDALPamDataset::PamInitialize()
         return;
     }
 
+    /* ERO 2011/04/13 : GPF_AUXMODE seems to be unimplemented */
     if( EQUAL( CPLGetConfigOption( "GDAL_PAM_MODE", "PAM" ), "AUX") )
         nPamFlags |= GPF_AUXMODE;
 
@@ -430,7 +445,17 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
         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 )
+        {
+            GDALDeinitGCPs( psPam->nGCPCount, psPam->pasGCPList );
+            CPLFree( psPam->pasGCPList );
+            psPam->nGCPCount = 0;
+            psPam->pasGCPList = 0;
+        }
+
         psPam->pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
          
         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
@@ -632,10 +657,37 @@ const char *GDALPamDataset::BuildPamFilename()
 }
 
 /************************************************************************/
+/*                   IsPamFilenameAPotentialSiblingFile()               */
+/************************************************************************/
+
+int GDALPamDataset::IsPamFilenameAPotentialSiblingFile()
+{
+    if (psPam == NULL)
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Determine if the PAM filename is a .aux.xml file next to the    */
+/*      physical file, or if it comes from the ProxyDB                  */
+/* -------------------------------------------------------------------- */
+    const char *pszPhysicalFile = psPam->osPhysicalFilename;
+
+    if( strlen(pszPhysicalFile) == 0 && GetDescription() != NULL )
+        pszPhysicalFile = GetDescription();
+
+    int nLenPhysicalFile = strlen(pszPhysicalFile);
+    int bIsSiblingPamFile = strncmp(psPam->pszPamFilename, pszPhysicalFile,
+                                    nLenPhysicalFile) == 0 &&
+                            strcmp(psPam->pszPamFilename + nLenPhysicalFile,
+                                   ".aux.xml") == 0;
+
+    return bIsSiblingPamFile;
+}
+
+/************************************************************************/
 /*                             TryLoadXML()                             */
 /************************************************************************/
 
-CPLErr GDALPamDataset::TryLoadXML()
+CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
 
 {
     CPLXMLNode *psTree = NULL;
@@ -660,6 +712,24 @@ CPLErr GDALPamDataset::TryLoadXML()
 
     VSIStatBufL sStatBuf;
 
+/* -------------------------------------------------------------------- */
+/*      In case the PAM filename is a .aux.xml file next to the         */
+/*      physical file and we have a siblings list, then we can skip     */
+/*      stat'ing the filesystem.                                        */
+/* -------------------------------------------------------------------- */
+    if (papszSiblingFiles != NULL && IsPamFilenameAPotentialSiblingFile())
+    {
+        int iSibling = CSLFindString( papszSiblingFiles,
+                                      CPLGetFilename(psPam->pszPamFilename) );
+        if( iSibling >= 0 )
+        {
+            CPLErrorReset();
+            CPLPushErrorHandler( CPLQuietErrorHandler );
+            psTree = CPLParseXMLFile( psPam->pszPamFilename );
+            CPLPopErrorHandler();
+        }
+    }
+    else
     if( VSIStatExL( psPam->pszPamFilename, &sStatBuf,
                     VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0
         && VSI_ISREG( sStatBuf.st_mode ) )
@@ -705,7 +775,7 @@ CPLErr GDALPamDataset::TryLoadXML()
 /*      If we fail, try .aux.                                           */
 /* -------------------------------------------------------------------- */
     if( psTree == NULL )
-        return TryLoadAux();
+        return TryLoadAux(papszSiblingFiles);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize ourselves from this XML tree.                        */
@@ -1002,18 +1072,29 @@ char **GDALPamDataset::GetFileList()
     VSIStatBufL sStatBuf;
     char **papszFileList = GDALDataset::GetFileList();
 
-    if( psPam && psPam->osPhysicalFilename.size() > 0 
+    if( psPam && psPam->osPhysicalFilename.size() > 0
         && CSLFindString( papszFileList, psPam->osPhysicalFilename ) == -1 )
     {
         papszFileList = CSLInsertString( papszFileList, 0, 
                                          psPam->osPhysicalFilename );
     }
 
-    if( psPam && psPam->pszPamFilename 
-        && (nPamFlags & GPF_DIRTY 
-            || VSIStatExL( psPam->pszPamFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0) )
+    if( psPam && psPam->pszPamFilename )
     {
-        papszFileList = CSLAddString( papszFileList, psPam->pszPamFilename );
+        int bAddPamFile = (nPamFlags & GPF_DIRTY);
+        if (!bAddPamFile)
+        {
+            if (oOvManager.GetSiblingFiles() != NULL && IsPamFilenameAPotentialSiblingFile())
+                bAddPamFile = CSLFindString(oOvManager.GetSiblingFiles(),
+                                  CPLGetFilename(psPam->pszPamFilename)) >= 0;
+            else
+                bAddPamFile = VSIStatExL( psPam->pszPamFilename, &sStatBuf,
+                                          VSI_STAT_EXISTS_FLAG ) == 0;
+        }
+        if (bAddPamFile)
+        {
+            papszFileList = CSLAddString( papszFileList, psPam->pszPamFilename );
+        }
     }
 
     if( psPam && psPam->osAuxFilename.size() > 0 &&
@@ -1321,7 +1402,7 @@ char **GDALPamDataset::GetMetadata( const char *pszDomain )
 /*                             TryLoadAux()                             */
 /************************************************************************/
 
-CPLErr GDALPamDataset::TryLoadAux()
+CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
 
 {
 /* -------------------------------------------------------------------- */
@@ -1343,10 +1424,26 @@ CPLErr GDALPamDataset::TryLoadAux()
     if( strlen(pszPhysicalFile) == 0 )
         return CE_None;
 
+    if( papszSiblingFiles )
+    {
+        CPLString osAuxFilename = CPLResetExtension( pszPhysicalFile, "aux");
+        int iSibling = CSLFindString( papszSiblingFiles,
+                                      CPLGetFilename(osAuxFilename) );
+        if( iSibling < 0 )
+        {
+            osAuxFilename = pszPhysicalFile;
+            osAuxFilename += ".aux";
+            iSibling = CSLFindString( papszSiblingFiles,
+                                      CPLGetFilename(osAuxFilename) );
+            if( iSibling < 0 )
+                return CE_None;
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Try to open .aux file.                                          */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poAuxDS = GDALFindAssociatedAuxFile( pszPhysicalFile, 
+    GDALDataset *poAuxDS = GDALFindAssociatedAuxFile( pszPhysicalFile,
                                                       GA_ReadOnly, this );
 
     if( poAuxDS == NULL )
@@ -1420,6 +1517,9 @@ CPLErr GDALPamDataset::TryLoadAux()
             CSLDestroy( papszMerged );
         }
 
+        if( strlen(poAuxBand->GetDescription()) > 0 )
+            poBand->SetDescription( poAuxBand->GetDescription() );
+
         if( poAuxBand->GetCategoryNames() != NULL )
             poBand->SetCategoryNames( poAuxBand->GetCategoryNames() );
 
diff --git a/gcore/gdalpamproxydb.cpp b/gcore/gdalpamproxydb.cpp
index af134cb..b771f74 100644
--- a/gcore/gdalpamproxydb.cpp
+++ b/gcore/gdalpamproxydb.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalpamproxydb.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gdalpamproxydb.cpp 22812 2011-07-25 04:50:23Z warmerdam $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of the GDAL PAM Proxy database interface.
@@ -35,7 +35,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalpamproxydb.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: gdalpamproxydb.cpp 22812 2011-07-25 04:50:23Z warmerdam $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -281,12 +281,17 @@ static void InitProxyDB()
 void PamCleanProxyDB()
 
 {
-    CPLMutexHolderD( &hProxyDBLock );
-    
-    bProxyDBInitialized = FALSE;
+    {
+        CPLMutexHolderD( &hProxyDBLock );
+        
+        bProxyDBInitialized = FALSE;
+        
+        delete poProxyDB;
+        poProxyDB = NULL;
+    }
 
-    delete poProxyDB;
-    poProxyDB = NULL;
+    CPLDestroyMutex( hProxyDBLock );
+    hProxyDBLock = NULL;
 }
 
 /************************************************************************/
diff --git a/gcore/gdalpamrasterband.cpp b/gcore/gdalpamrasterband.cpp
index 29805de..b9f1913 100644
--- a/gcore/gdalpamrasterband.cpp
+++ b/gcore/gdalpamrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalpamrasterband.cpp 21714 2011-02-13 18:37:57Z rouault $
+ * $Id: gdalpamrasterband.cpp 22858 2011-08-02 18:18:19Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamRasterBand, a raster band base class
@@ -33,7 +33,7 @@
 #include "gdal_rat.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalpamrasterband.cpp 21714 2011-02-13 18:37:57Z rouault $");
+CPL_CVSID("$Id: gdalpamrasterband.cpp 22858 2011-08-02 18:18:19Z rouault $");
 
 /************************************************************************/
 /*                         GDALPamRasterBand()                          */
@@ -130,11 +130,17 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( const char *pszUnused )
     {
         CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
                                                  "CategoryNames" );
+        CPLXMLNode* psLastChild = NULL;
 
         for( int iEntry=0; psPam->papszCategoryNames[iEntry] != NULL; iEntry++)
         {
-            CPLCreateXMLElementAndValue( psCT_XML, "Category", 
+            CPLXMLNode *psNode = CPLCreateXMLElementAndValue( NULL, "Category",
                                          psPam->papszCategoryNames[iEntry] );
+            if( psLastChild == NULL )
+                psCT_XML->psChild = psNode;
+            else
+                psLastChild->psNext = psNode;
+            psLastChild = psNode;
         }
     }
 
@@ -361,7 +367,7 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
     if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL )
     {
         CPLXMLNode *psEntry;
-        char **papszCategoryNames = NULL;
+        CPLStringList oCategoryNames;
 
         for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
              psEntry != NULL; psEntry = psEntry->psNext )
@@ -372,11 +378,11 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
                 || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
                 continue;
             
-            papszCategoryNames = CSLAddString( papszCategoryNames, 
+            oCategoryNames.AddString( 
                                  (psEntry->psChild) ? psEntry->psChild->pszValue : "" );
         }
         
-        GDALPamRasterBand::SetCategoryNames( papszCategoryNames );
+        GDALPamRasterBand::SetCategoryNames( oCategoryNames.List() );
     }
 
 /* -------------------------------------------------------------------- */
@@ -513,6 +519,18 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Category names                                                  */
+/* -------------------------------------------------------------------- */
+    if( nCloneFlags & GCIF_CATEGORYNAMES )
+    {
+        if( poSrcBand->GetCategoryNames() != NULL )
+        {
+            if( !bOnlyIfMissing || GetCategoryNames() == NULL )
+                GDALPamRasterBand::SetCategoryNames( poSrcBand->GetCategoryNames() );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Offset/scale                                                    */
 /* -------------------------------------------------------------------- */
     if( nCloneFlags & GCIF_SCALEOFFSET )
@@ -1008,10 +1026,11 @@ PamFindMatchingHistogram( CPLXMLNode *psSavedHistograms,
             || !EQUAL(psXMLHist->pszValue,"HistItem") )
             continue;
 
-        // should try and make min/max test a bit fuzzy.
+        double dfHistMin = atof(CPLGetXMLValue( psXMLHist, "HistMin", "0"));
+        double dfHistMax = atof(CPLGetXMLValue( psXMLHist, "HistMax", "0"));
 
-        if( atof(CPLGetXMLValue( psXMLHist, "HistMin", "0")) != dfMin 
-            || atof(CPLGetXMLValue( psXMLHist, "HistMax", "0")) != dfMax
+        if( !(ARE_REAL_EQUAL(dfHistMin, dfMin))
+            || !(ARE_REAL_EQUAL(dfHistMax, dfMax))
             || atoi(CPLGetXMLValue( psXMLHist, 
                                     "BucketCount","0")) != nBuckets
             || !atoi(CPLGetXMLValue( psXMLHist, 
diff --git a/gcore/gdalproxydataset.cpp b/gcore/gdalproxydataset.cpp
index 6e565b6..610810a 100644
--- a/gcore/gdalproxydataset.cpp
+++ b/gcore/gdalproxydataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproxydataset.cpp 21867 2011-02-26 21:05:35Z rouault $
+ * $Id: gdalproxydataset.cpp 21866 2011-02-26 21:04:58Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that act as proxy for underlying
@@ -30,7 +30,7 @@
 
 #include "gdal_proxy.h"
 
-CPL_CVSID("$Id: gdalproxydataset.cpp 21867 2011-02-26 21:05:35Z rouault $");
+CPL_CVSID("$Id: gdalproxydataset.cpp 21866 2011-02-26 21:04:58Z rouault $");
 
 /* ******************************************************************** */
 /*                        GDALProxyDataset                              */
diff --git a/gcore/gdalproxypool.cpp b/gcore/gdalproxypool.cpp
index b813d0a..4c2228e 100644
--- a/gcore/gdalproxypool.cpp
+++ b/gcore/gdalproxypool.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalproxypool.cpp 21211 2010-12-08 13:38:25Z rouault $
+ * $Id: gdalproxypool.cpp 21669 2011-02-10 00:49:16Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that differ the opening of the
@@ -31,7 +31,7 @@
 #include "gdal_proxy.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalproxypool.cpp 21211 2010-12-08 13:38:25Z rouault $");
+CPL_CVSID("$Id: gdalproxypool.cpp 21669 2011-02-10 00:49:16Z rouault $");
 
 /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
 void** GDALGetphDLMutex();
@@ -102,6 +102,9 @@ class GDALDatasetPool
         static void Unref();
         static GDALProxyPoolCacheEntry* RefDataset(const char* pszFileName, GDALAccess eAccess);
         static void UnrefDataset(GDALProxyPoolCacheEntry* cacheEntry);
+
+        static void PreventDestroy();
+        static void ForceDestroy();
 };
 
 
@@ -319,6 +322,22 @@ void GDALDatasetPool::Ref()
       singleton->refCount++;
 }
 
+/* keep that in sync with gdaldrivermanager.cpp */
+void GDALDatasetPool::PreventDestroy()
+{
+    CPLMutexHolderD( GDALGetphDLMutex() );
+    if (! singleton)
+        return;
+    singleton->refCountOfDisableRefCount ++;
+}
+
+/* keep that in sync with gdaldrivermanager.cpp */
+void GDALDatasetPoolPreventDestroy()
+{
+    GDALDatasetPool::PreventDestroy();
+}
+
+
 /************************************************************************/
 /*                               Unref()                                */
 /************************************************************************/
@@ -342,6 +361,25 @@ void GDALDatasetPool::Unref()
     }
 }
 
+/* keep that in sync with gdaldrivermanager.cpp */
+void GDALDatasetPool::ForceDestroy()
+{
+    CPLMutexHolderD( GDALGetphDLMutex() );
+    if (! singleton)
+        return;
+    singleton->refCountOfDisableRefCount --;
+    CPLAssert(singleton->refCountOfDisableRefCount == 0);
+    singleton->refCount = 0;
+    delete singleton;
+    singleton = NULL;
+}
+
+/* keep that in sync with gdaldrivermanager.cpp */
+void GDALDatasetPoolForceDestroy()
+{
+    GDALDatasetPool::ForceDestroy();
+}
+
 /************************************************************************/
 /*                           RefDataset()                               */
 /************************************************************************/
diff --git a/gcore/gdalrasterband.cpp b/gcore/gdalrasterband.cpp
index 26025ae..a463947 100644
--- a/gcore/gdalrasterband.cpp
+++ b/gcore/gdalrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterband.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: gdalrasterband.cpp 23425 2011-11-26 19:14:25Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for format specific band class implementation.  This
@@ -40,7 +40,7 @@
 // (minimum value, maximum value, etc.)
 #define GDALSTAT_APPROX_NUMSAMPLES 2500
 
-CPL_CVSID("$Id: gdalrasterband.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: gdalrasterband.cpp 23425 2011-11-26 19:14:25Z rouault $");
 
 /************************************************************************/
 /*                           GDALRasterBand()                           */
@@ -187,7 +187,7 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 
     if( NULL == pData )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        ReportError( CE_Failure, CPLE_AppDefined,
                   "The buffer into which the data should be read is null" );
             return CE_Failure;
     }
@@ -210,7 +210,7 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 
     if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
     {
-        CPLError(eFlushBlockErr, CPLE_AppDefined,
+        ReportError(eFlushBlockErr, CPLE_AppDefined,
                  "An error occured while writing a dirty block");
         CPLErr eErr = eFlushBlockErr;
         eFlushBlockErr = CE_None;
@@ -228,7 +228,7 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
     {
         if (nPixelSpace > INT_MAX / nBufXSize)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            ReportError( CE_Failure, CPLE_AppDefined,
                       "Int overflow : %d x %d", nPixelSpace, nBufXSize );
             return CE_Failure;
         }
@@ -241,7 +241,7 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
     if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
         || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        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 );
@@ -250,7 +250,7 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 
     if( eRWFlag != GF_Read && eRWFlag != GF_Write )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
                   eRWFlag );
         return CE_Failure;
@@ -397,7 +397,7 @@ CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
         
     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nXBlockOff value (%d) in "
                         "GDALRasterBand::ReadBlock()\n",
                   nXBlockOff );
@@ -407,7 +407,7 @@ CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
 
     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nYBlockOff value (%d) in "
                         "GDALRasterBand::ReadBlock()\n",
                   nYBlockOff );
@@ -452,7 +452,7 @@ CPLErr GDALRasterBand::IWriteBlock( int, int, void * )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "WriteBlock() not supported for this dataset." );
     
     return( CE_Failure );
@@ -500,7 +500,7 @@ CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
 
     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nXBlockOff value (%d) in "
                         "GDALRasterBand::WriteBlock()\n",
                   nXBlockOff );
@@ -510,7 +510,7 @@ CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
 
     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nYBlockOff value (%d) in "
                         "GDALRasterBand::WriteBlock()\n",
                   nYBlockOff );
@@ -520,7 +520,7 @@ CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
 
     if( eAccess == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
+        ReportError( CE_Failure, CPLE_NoWriteAccess,
                   "Attempt to write to read only dataset in"
                   "GDALRasterBand::WriteBlock().\n" );
 
@@ -529,7 +529,7 @@ CPLErr GDALRasterBand::WriteBlock( int nXBlockOff, int nYBlockOff,
 
     if( eFlushBlockErr != CE_None )
     {
-        CPLError(eFlushBlockErr, CPLE_AppDefined,
+        ReportError(eFlushBlockErr, CPLE_AppDefined,
                  "An error occured while writing a dirty block");
         CPLErr eErr = eFlushBlockErr;
         eFlushBlockErr = CE_None;
@@ -628,7 +628,7 @@ void GDALRasterBand::GetBlockSize( int * pnXSize, int *pnYSize )
 {
     if( nBlockXSize <= 0 || nBlockYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
+        ReportError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
                  nBlockXSize, nBlockYSize );
         if( pnXSize != NULL )
             *pnXSize = 0;
@@ -678,14 +678,14 @@ int GDALRasterBand::InitBlockInfo()
     /* would have neglected to do it itself */
     if( nBlockXSize <= 0 || nBlockYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
+        ReportError( CE_Failure, CPLE_AppDefined, "Invalid block dimension : %d * %d",
                   nBlockXSize, nBlockYSize );
         return FALSE;
     }
 
     if( nRasterXSize <= 0 || nRasterYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "Invalid raster dimension : %d * %d",
+        ReportError( CE_Failure, CPLE_AppDefined, "Invalid raster dimension : %d * %d",
                   nRasterXSize, nRasterYSize );
         return FALSE;
     }
@@ -702,7 +702,7 @@ int GDALRasterBand::InitBlockInfo()
         GIntBig nBigSizeInBytes = (GIntBig)nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
         if ((GIntBig)nSizeInBytes != nBigSizeInBytes)
         {
-            CPLError( CE_Failure, CPLE_NotSupported, "Too big block : %d * %d",
+            ReportError( CE_Failure, CPLE_NotSupported, "Too big block : %d * %d",
                         nBlockXSize, nBlockYSize );
             return FALSE;
         }
@@ -711,14 +711,14 @@ int GDALRasterBand::InitBlockInfo()
     /* Check for overflows in computation of nBlocksPerRow and nBlocksPerColumn */
     if (nRasterXSize > INT_MAX - (nBlockXSize-1))
     {
-        CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
+        ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
                     nRasterXSize, nBlockXSize );
         return FALSE;
     }
 
     if (nRasterYSize > INT_MAX - (nBlockYSize-1))
     {
-        CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
+        ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
                     nRasterYSize, nBlockYSize );
         return FALSE;
     }
@@ -737,7 +737,7 @@ int GDALRasterBand::InitBlockInfo()
         }
         else
         {
-            CPLError( CE_Failure, CPLE_NotSupported, "Too many blocks : %d x %d",
+            ReportError( CE_Failure, CPLE_NotSupported, "Too many blocks : %d x %d",
                      nBlocksPerRow, nBlocksPerColumn );
             return FALSE;
         }
@@ -747,14 +747,14 @@ int GDALRasterBand::InitBlockInfo()
         /* Check for overflows in computation of nSubBlocksPerRow and nSubBlocksPerColumn */
         if (nBlocksPerRow > INT_MAX - (SUBBLOCK_SIZE+1))
         {
-            CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
+            ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster width (%d) for block width (%d)",
                         nRasterXSize, nBlockXSize );
             return FALSE;
         }
 
         if (nBlocksPerColumn > INT_MAX - (SUBBLOCK_SIZE+1))
         {
-            CPLError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
+            ReportError( CE_Failure, CPLE_NotSupported, "Inappropriate raster height (%d) for block height (%d)",
                         nRasterYSize, nBlockYSize );
             return FALSE;
         }
@@ -771,7 +771,7 @@ int GDALRasterBand::InitBlockInfo()
         }
         else
         {
-            CPLError( CE_Failure, CPLE_NotSupported, "Too many subblocks : %d x %d",
+            ReportError( CE_Failure, CPLE_NotSupported, "Too many subblocks : %d x %d",
                       nSubBlocksPerRow, nSubBlocksPerColumn );
             return FALSE;
         }
@@ -779,7 +779,7 @@ int GDALRasterBand::InitBlockInfo()
 
     if( papoBlocks == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
+        ReportError( CE_Failure, CPLE_OutOfMemory,
                   "Out of memory in InitBlockInfo()." );
         return FALSE;
     }
@@ -834,18 +834,16 @@ CPLErr GDALRasterBand::AdoptBlock( int nXBlockOff, int nYBlockOff,
 
     if( papoBlocks[nSubBlock] == NULL )
     {
-        int nSubGridSize = 
+        const int nSubGridSize = 
             sizeof(GDALRasterBlock*) * SUBBLOCK_SIZE * SUBBLOCK_SIZE;
 
-        papoBlocks[nSubBlock] = (GDALRasterBlock *) VSIMalloc(nSubGridSize);
+        papoBlocks[nSubBlock] = (GDALRasterBlock *) VSICalloc(1, nSubGridSize);
         if( papoBlocks[nSubBlock] == NULL )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory,
+            ReportError( CE_Failure, CPLE_OutOfMemory,
                       "Out of memory in AdoptBlock()." );
             return CE_Failure;
         }
-
-        memset( papoBlocks[nSubBlock], 0, nSubGridSize );
     }
 
 /* -------------------------------------------------------------------- */
@@ -891,7 +889,7 @@ CPLErr GDALRasterBand::FlushCache()
 
     if (eFlushBlockErr != CE_None)
     {
-        CPLError(eFlushBlockErr, CPLE_AppDefined,
+        ReportError(eFlushBlockErr, CPLE_AppDefined,
                  "An error occured while writing a dirty block");
         eFlushBlockErr = CE_None;
     }
@@ -1008,7 +1006,7 @@ CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff, int bWriteDir
 /* -------------------------------------------------------------------- */
     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nBlockXOff value (%d) in "
                         "GDALRasterBand::FlushBlock()\n",
                   nXBlockOff );
@@ -1018,7 +1016,7 @@ CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff, int bWriteDir
 
     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nBlockYOff value (%d) in "
                         "GDALRasterBand::FlushBlock()\n",
                   nYBlockOff );
@@ -1102,7 +1100,7 @@ CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff, int bWriteDir
  * caller release this lock (with GDALRasterBlock::DropLock()) or else
  * severe problems may result.
  *
- * @param nBlockXOff the horizontal block offset, with zero indicating
+ * @param nXBlockOff the horizontal block offset, with zero indicating
  * the left most block, 1 the next block and so forth. 
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
@@ -1125,7 +1123,7 @@ GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
 /* -------------------------------------------------------------------- */
     if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nBlockXOff value (%d) in "
                         "GDALRasterBand::TryGetLockedBlockRef()\n",
                   nXBlockOff );
@@ -1135,7 +1133,7 @@ GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
 
     if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
+        ReportError( CE_Failure, CPLE_IllegalArg,
                   "Illegal nBlockYOff value (%d) in "
                         "GDALRasterBand::TryGetLockedBlockRef()\n",
                   nYBlockOff );
@@ -1199,7 +1197,7 @@ GDALRasterBlock *GDALRasterBand::TryGetLockedBlockRef( int nXBlockOff,
  * Note that calling GetLockedBlockRef() on a previously uncached band will
  * enable caching.
  * 
- * @param nBlockXOff the horizontal block offset, with zero indicating
+ * @param nXBlockOff the horizontal block offset, with zero indicating
  * the left most block, 1 the next block and so forth. 
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
@@ -1239,7 +1237,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
     /* -------------------------------------------------------------------- */
         if( nXBlockOff < 0 || nXBlockOff >= nBlocksPerRow )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg,
+            ReportError( CE_Failure, CPLE_IllegalArg,
                       "Illegal nBlockXOff value (%d) in "
                       "GDALRasterBand::GetLockedBlockRef()\n",
                       nXBlockOff );
@@ -1249,7 +1247,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
 
         if( nYBlockOff < 0 || nYBlockOff >= nBlocksPerColumn )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg,
+            ReportError( CE_Failure, CPLE_IllegalArg,
                       "Illegal nBlockYOff value (%d) in "
                       "GDALRasterBand::GetLockedBlockRef()\n",
                       nYBlockOff );
@@ -1281,10 +1279,10 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
         {
             poBlock->DropLock();
             FlushBlock( nXBlockOff, nYBlockOff );
-            CPLError( CE_Failure, CPLE_AppDefined,
-		      "IReadBlock failed at X offset %d, Y offset %d",
-		      nXBlockOff, nYBlockOff );
-	    return( NULL );
+            ReportError( CE_Failure, CPLE_AppDefined,
+                "IReadBlock failed at X offset %d, Y offset %d",
+                nXBlockOff, nYBlockOff );
+            return( NULL );
         }
 
         if( !bJustInitialize )
@@ -1317,7 +1315,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
  * second argument allows the imaginary component of a complex
  * constant value to be specified.
  * 
- * @param dfRealvalue Real component of fill value
+ * @param dfRealValue Real component of fill value
  * @param dfImaginaryValue Imaginary component of fill value, defaults to zero
  * 
  * @return CE_Failure if the write fails, otherwise CE_None
@@ -1335,7 +1333,7 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
 
     // Check we can write to the file
     if( eAccess == GA_ReadOnly ) {
-        CPLError(CE_Failure, CPLE_NoWriteAccess,
+        ReportError(CE_Failure, CPLE_NoWriteAccess,
                  "Attempt to write to read only dataset in"
                  "GDALRasterBand::Fill().\n" );
         return CE_Failure;
@@ -1351,7 +1349,7 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
     int blockByteSize = blockSize * elementSize;
     unsigned char* srcBlock = (unsigned char*) VSIMalloc(blockByteSize);
     if (srcBlock == NULL) {
-	CPLError(CE_Failure, CPLE_OutOfMemory,
+        ReportError(CE_Failure, CPLE_OutOfMemory,
                  "GDALRasterBand::Fill(): Out of memory "
 		 "allocating %d bytes.\n", blockByteSize);
         return CE_Failure;
@@ -1372,7 +1370,7 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
 	for (int i = 0; i < nBlocksPerRow; ++i) {
 	    GDALRasterBlock* destBlock = GetLockedBlockRef(i, j, TRUE);
 	    if (destBlock == NULL) {
-		CPLError(CE_Failure, CPLE_OutOfMemory,
+            ReportError(CE_Failure, CPLE_OutOfMemory,
 			 "GDALRasterBand::Fill(): Error "
 			 "while retrieving cache block.\n");
                 VSIFree(srcBlock);
@@ -1515,11 +1513,11 @@ char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
  * by the driver CE_Failure is returned, but no error message is reported.
  */
 
-CPLErr GDALRasterBand::SetCategoryNames( char ** )
+CPLErr GDALRasterBand::SetCategoryNames( char ** papszNames )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetCategoryNames() not supported for this dataset." );
     
     return CE_Failure;
@@ -1613,11 +1611,11 @@ GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
  * been emitted.
  */
 
-CPLErr GDALRasterBand::SetNoDataValue( double )
+CPLErr GDALRasterBand::SetNoDataValue( double dfNoData )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetNoDataValue() not supported for this dataset." );
 
     return CE_Failure;
@@ -1882,7 +1880,7 @@ CPLErr GDALRasterBand::SetColorInterpretation( GDALColorInterp eColorInterp)
 {
     (void) eColorInterp;
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetColorInterpretation() not supported for this dataset." );
     return CE_Failure;
 }
@@ -1974,7 +1972,7 @@ CPLErr GDALRasterBand::SetColorTable( GDALColorTable * poCT )
 {
     (void) poCT;
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetColorTable() not supported for this dataset." );
     return CE_Failure;
 }
@@ -2237,7 +2235,7 @@ CPLErr GDALRasterBand::BuildOverviews( const char * pszResampling,
     (void) pfnProgress;
     (void) pProgressData;
 
-    CPLError( CE_Failure, CPLE_NotSupported,
+    ReportError( CE_Failure, CPLE_NotSupported,
               "BuildOverviews() not supported for this dataset." );
     
     return( CE_Failure );
@@ -2315,7 +2313,7 @@ CPLErr GDALRasterBand::SetOffset( double dfNewOffset )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetOffset() not supported on this raster band." );
     
     return CE_Failure;
@@ -2413,7 +2411,7 @@ CPLErr GDALRasterBand::SetScale( double dfNewScale )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetScale() not supported on this raster band." );
     
     return CE_Failure;
@@ -2504,7 +2502,7 @@ CPLErr GDALRasterBand::SetUnitType( const char *pszNewValue )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetUnitType() not supported on this raster band." );
     return CE_Failure;
 }
@@ -2765,7 +2763,7 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
 
     if( !pfnProgress( 0.0, "Compute Histogram", pProgressData ) )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
         return CE_Failure;
     }
 
@@ -2859,6 +2857,8 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                     {
                         double dfReal = ((GInt16 *)pData)[iOffset*2];
                         double dfImag = ((GInt16 *)pData)[iOffset*2+1];
+                        if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
+                            continue;
                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
                     }
                     break;
@@ -2866,6 +2866,8 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                     {
                         double dfReal = ((GInt32 *)pData)[iOffset*2];
                         double dfImag = ((GInt32 *)pData)[iOffset*2+1];
+                        if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
+                            continue;
                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
                     }
                     break;
@@ -3201,7 +3203,7 @@ CPLErr
     *ppanHistogram = (int *) VSICalloc(sizeof(int), nBuckets);
     if( *ppanHistogram == NULL )
     {
-        CPLError( CE_Failure, CPLE_OutOfMemory,
+        ReportError( CE_Failure, CPLE_OutOfMemory,
                   "Out of memory in InitBlockInfo()." );
         return CE_Failure;
     }
@@ -3284,7 +3286,7 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand,
 
 CPLErr GDALRasterBand::AdviseRead( 
     int nXOff, int nYOff, int nXSize, int nYSize,
-    int nBufXSize, int nBufYSize, GDALDataType eDT, char **papszOptions )
+    int nBufXSize, int nBufYSize, GDALDataType eBufType, char **papszOptions )
 
 {
     return CE_None;
@@ -3374,13 +3376,13 @@ CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
      && (pdfStdDev == NULL || GetMetadataItem("STATISTICS_STDDEV") != NULL) )
     {
         if( pdfMin != NULL )
-            *pdfMin = atof(GetMetadataItem("STATISTICS_MINIMUM"));
+            *pdfMin = CPLAtofM(GetMetadataItem("STATISTICS_MINIMUM"));
         if( pdfMax != NULL )
-            *pdfMax = atof(GetMetadataItem("STATISTICS_MAXIMUM"));
+            *pdfMax = CPLAtofM(GetMetadataItem("STATISTICS_MAXIMUM"));
         if( pdfMean != NULL )
-            *pdfMean = atof(GetMetadataItem("STATISTICS_MEAN"));
+            *pdfMean = CPLAtofM(GetMetadataItem("STATISTICS_MEAN"));
         if( pdfStdDev != NULL )
-            *pdfStdDev = atof(GetMetadataItem("STATISTICS_STDDEV"));
+            *pdfStdDev = CPLAtofM(GetMetadataItem("STATISTICS_STDDEV"));
 
         return CE_None;
     }
@@ -3512,11 +3514,12 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 
     if( !pfnProgress( 0.0, "Compute Statistics", pProgressData ) )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
         return CE_Failure;
     }
 
     dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
+    bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
 
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
@@ -3620,7 +3623,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
                     CPLAssert( FALSE );
                 }
                 
-                if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
+                if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                     continue;
 
                 if( bFirstValue )
@@ -3754,8 +3757,8 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
                       default:
                         CPLAssert( FALSE );
                     }
-                    
-                    if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
+
+                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                         continue;
 
                     if( bFirstValue )
@@ -3782,7 +3785,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
                               / ((double)(nBlocksPerRow*nBlocksPerColumn)),
                               "Compute Statistics", pProgressData) )
             {
-                CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+                ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                 return CE_Failure;
             }
         }
@@ -3790,7 +3793,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 
     if( !pfnProgress( 1.0, "Compute Statistics", pProgressData ) )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
         return CE_Failure;
     }
 
@@ -3821,7 +3824,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
         return CE_None;
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
+        ReportError( CE_Failure, CPLE_AppDefined,
         "Failed to compute statistics, no valid pixels found in sampling." );
         return CE_Failure;
     }
@@ -3992,6 +3995,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
     double  dfNoDataValue;
 
     dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
+    bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
 
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
     int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
@@ -4095,7 +4099,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
                     CPLAssert( FALSE );
                 }
                 
-                if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
+                if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                     continue;
 
                 if( bFirstValue )
@@ -4225,7 +4229,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
                         CPLAssert( FALSE );
                     }
                     
-                    if( bGotNoDataValue && EQUAL_TO_NODATA(dfValue, dfNoDataValue) )
+                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                         continue;
 
                     if( bFirstValue )
@@ -4250,7 +4254,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 
     if (bFirstValue)
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
+        ReportError( CE_Failure, CPLE_AppDefined,
             "Failed to compute min/max, no valid pixels found in sampling." );
         return CE_Failure;
     }
@@ -4294,7 +4298,7 @@ CPLErr GDALRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetDefaultHistogram() not implemented for this format." );
 
     return CE_Failure;
@@ -4381,7 +4385,7 @@ CPLErr GDALRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        CPLError( CE_Failure, CPLE_NotSupported,
+        ReportError( CE_Failure, CPLE_NotSupported,
                   "SetDefaultRAT() not implemented for this format." );
 
     return CE_Failure;
@@ -4480,8 +4484,6 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
             /* Make sure we have as many values as bands */
             if (CSLCount(papszNoDataValues) == poDS->GetRasterCount() && poDS->GetRasterCount() != 0)
             {
-                CSLDestroy(papszNoDataValues);
-
                 /* Make sure that all bands have the same data type */
                 /* This is cleraly not a fundamental condition, just a condition to make implementation */
                 /* easier. */
@@ -4501,17 +4503,18 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
                     nMaskFlags = GMF_NODATA | GMF_PER_DATASET;
                     poMask = new GDALNoDataValuesMaskBand ( poDS );
                     bOwnMask = true;
+                    CSLDestroy(papszNoDataValues);
                     return poMask;
                 }
                 else
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined,
+                    ReportError(CE_Warning, CPLE_AppDefined,
                             "All bands should have the same type in order the NODATA_VALUES metadata item to be used as a mask.");
                 }
             }
             else
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
+                ReportError(CE_Warning, CPLE_AppDefined,
                         "NODATA_VALUES metadata item doesn't have the same number of values as the number of bands.\n"
                         "Ignoring it for mask.");
             }
@@ -4712,7 +4715,7 @@ CPLErr GDALRasterBand::CreateMaskBand( int nFlags )
         return CE_None;
     }
 
-    CPLError( CE_Failure, CPLE_NotSupported,
+    ReportError( CE_Failure, CPLE_NotSupported,
               "CreateMaskBand() not supported for this band." );
     
     return CE_Failure;
@@ -4760,7 +4763,7 @@ CPLErr CPL_STDCALL GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags )
  * @param poReferenceBand the raster band
  * @param pTranslationTable an already allocated translation table (at least 256 bytes),
  *                          or NULL to let the method allocate it
- * @param poApproximateMatching a pointer to a flag that is set if the matching
+ * @param pApproximateMatching a pointer to a flag that is set if the matching
  *                              is approximate. May be NULL.
  *
  * @return a translation table if the two bands are palette index and that they do
@@ -4894,3 +4897,47 @@ void GDALRasterBand::SetFlushBlockErr( CPLErr eErr )
 {
     eFlushBlockErr = eErr;
 }
+
+/************************************************************************/
+/*                            ReportError()                             */
+/************************************************************************/
+
+/**
+ * \brief Emits an error related to a raster band.
+ *
+ * This function is a wrapper for regular CPLError(). The only difference
+ * with CPLError() is that it prepends the error message with the dataset
+ * name and the band number.
+ *
+ * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
+ * @param err_no the error number (CPLE_*) from cpl_error.h.
+ * @param fmt a printf() style format string.  Any additional arguments
+ * will be treated as arguments to fill in this format in a manner
+ * similar to printf().
+ *
+ * @since GDAL 1.9.0
+ */
+
+void GDALRasterBand::ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+
+    char szNewFmt[256];
+    const char* pszDSName = poDS ? poDS->GetDescription() : "";
+    if (strlen(fmt) + strlen(pszDSName) + 20 >= sizeof(szNewFmt) - 1)
+        pszDSName = CPLGetFilename(pszDSName);
+    if (pszDSName[0] != '\0' &&
+        strlen(fmt) + strlen(pszDSName) + 20 < sizeof(szNewFmt) - 1)
+    {
+        snprintf(szNewFmt, sizeof(szNewFmt), "%s, band %d: %s",
+                 pszDSName, GetBand(), fmt);
+        CPLErrorV( eErrClass, err_no, szNewFmt, args );
+    }
+    else
+    {
+        CPLErrorV( eErrClass, err_no, fmt, args );
+    }
+    va_end(args);
+}
diff --git a/gcore/gdalrasterblock.cpp b/gcore/gdalrasterblock.cpp
index 2a2b2e7..53e721d 100644
--- a/gcore/gdalrasterblock.cpp
+++ b/gcore/gdalrasterblock.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterblock.cpp 20189 2010-08-06 15:15:34Z rouault $
+ * $Id: gdalrasterblock.cpp 22669 2011-07-07 22:37:44Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterBlock class and related global 
@@ -31,7 +31,7 @@
 #include "gdal_priv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalrasterblock.cpp 20189 2010-08-06 15:15:34Z rouault $");
+CPL_CVSID("$Id: gdalrasterblock.cpp 22669 2011-07-07 22:37:44Z rouault $");
 
 static int bCacheMaxInitialized = FALSE;
 static GIntBig nCacheMax = 40 * 1024*1024;
@@ -51,18 +51,18 @@ static void *hRBMutex = NULL;
  * \brief Set maximum cache memory.
  *
  * This function sets the maximum amount of memory that GDAL is permitted
- * to use for GDALRasterBlock caching.
+ * to use for GDALRasterBlock caching. The unit of the value is bytes.
  *
  * The maximum value is 2GB, due to the use of a signed 32 bit integer.
  * Use GDALSetCacheMax64() to be able to set a higher value.
  *
- * @param nNewSize the maximum number of bytes for caching.
+ * @param nNewSizeInBytes the maximum number of bytes for caching.
  */
 
-void CPL_STDCALL GDALSetCacheMax( int nNewSize )
+void CPL_STDCALL GDALSetCacheMax( int nNewSizeInBytes )
 
 {
-    GDALSetCacheMax64(nNewSize);
+    GDALSetCacheMax64(nNewSizeInBytes);
 }
 
 
@@ -74,22 +74,22 @@ void CPL_STDCALL GDALSetCacheMax( int nNewSize )
  * \brief Set maximum cache memory.
  *
  * This function sets the maximum amount of memory that GDAL is permitted
- * to use for GDALRasterBlock caching.
+ * to use for GDALRasterBlock caching. The unit of the value is bytes.
  *
  * Note: On 32 bit platforms, the maximum amount of memory that can be addressed
  * by a process might be 2 GB or 3 GB, depending on the operating system
  * capabilities. This function will not make any attempt to check the
  * consistency of the passed value with the effective capabilities of the OS.
  *
- * @param nNewSize the maximum number of bytes for caching.
+ * @param nNewSizeInBytes the maximum number of bytes for caching.
  *
  * @since GDAL 1.8.0
  */
 
-void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSize )
+void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSizeInBytes )
 
 {
-    nCacheMax = nNewSize;
+    nCacheMax = nNewSizeInBytes;
 
 /* -------------------------------------------------------------------- */
 /*      Flush blocks till we are under the new limit or till we         */
@@ -514,7 +514,10 @@ CPLErr GDALRasterBlock::Write()
 
     MarkClean();
 
-    return poBand->IWriteBlock( nXOff, nYOff, pData );
+    if (poBand->eFlushBlockErr == CE_None)
+        return poBand->IWriteBlock( nXOff, nYOff, pData );
+    else
+        return poBand->eFlushBlockErr;
 }
 
 /************************************************************************/
diff --git a/gcore/rasterio.cpp b/gcore/rasterio.cpp
index 28c33e1..bc3fd44 100644
--- a/gcore/rasterio.cpp
+++ b/gcore/rasterio.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterio.cpp 22421 2011-05-23 21:24:30Z rouault $
+ * $Id: rasterio.cpp 22420 2011-05-23 21:23:29Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
@@ -47,7 +47,7 @@
 #endif
 
 
-CPL_CVSID("$Id: rasterio.cpp 22421 2011-05-23 21:24:30Z rouault $");
+CPL_CVSID("$Id: rasterio.cpp 22420 2011-05-23 21:23:29Z rouault $");
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -70,6 +70,15 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     GDALRasterBlock *poBlock = NULL;
     int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY;
 
+    if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
+    {
+        CPLError(eFlushBlockErr, CPLE_AppDefined,
+                 "An error occured while writing a dirty block");
+        CPLErr eErr = eFlushBlockErr;
+        eFlushBlockErr = CE_None;
+        return eErr;
+    }
+
 /* ==================================================================== */
 /*      A common case is the data requested with the destination        */
 /*      is packed, and the block width is the raster width.             */
@@ -167,10 +176,21 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 && eRWFlag == GF_Read )
     {
-        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
-                              pData, nBufXSize, nBufYSize, 
-                              eBufType, nPixelSpace, nLineSpace ) == CE_None )
-            return CE_None;
+        int         nOverview;
+
+        nOverview =
+            GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
+                                        nBufXSize, nBufYSize);
+        if (nOverview >= 0)
+        {
+            GDALRasterBand* poOverviewBand = GetOverview(nOverview);
+            if (poOverviewBand == NULL)
+                return CE_Failure;
+
+            return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                            pData, nBufXSize, nBufYSize, eBufType,
+                                            nPixelSpace, nLineSpace );
+        }
     }
 
 /* ==================================================================== */
diff --git a/gdalnightlysvn.sh b/gdalnightlysvn.sh
index e99ed24..991bee7 100644
--- a/gdalnightlysvn.sh
+++ b/gdalnightlysvn.sh
@@ -4,7 +4,12 @@
 #
 # Script generates GDAL nightly snapshot packages.
 #
-VERBOSE=0
+###### CONFIGURATION BEGIN ######
+VERBOSE=1
+VERSION_STABLE="1.8"
+# Make sure we get the right swig. 
+PATH=/usr/local/swig-1.3.39/bin:$PATH
+###### CONFIGURATION END ######
 
 if [ $# != 1 ] ; then
     echo "Missing SVN branch!"
@@ -14,7 +19,7 @@ fi
 
 if [ $# -eq 1 ] ; then
   BRANCH=$1
-  if test ! "$BRANCH" = "trunk" -a ! "$BRANCH" = "stable"; then
+  if test ! "${BRANCH}" = "trunk" -a ! "${BRANCH}" = "stable"; then
     echo "Unknown branch passed!"
     echo "Available branches: trunk, stable"
     exit 1
@@ -27,18 +32,18 @@ fi
 
 GDAL="gdal"
 SVNBRANCH="trunk"
-if test "$BRANCH" = "stable"; then
-  GDAL="gdal-1.4"
-  SVNBRANCH="branches/1.4"
+if test "${BRANCH}" = "stable"; then
+  GDAL="gdal-${VERSION_STABLE}"
+  SVNBRANCH="branches/${VERSION_STABLE}"
 fi
 
 CWD=/osgeo/gdal
 DATE=`date +%Y%m%d`
 DATEVER=`date +%Y.%m.%d`
 NIGHTLYVER="svn-${BRANCH}-${DATEVER}"
-BUILDER="./mkgdaldist.sh"
+BUILDER="/osgeo/gdal/mkgdaldist.sh"
 GDALDIR="${CWD}/${GDAL}"
-DAILYDIR="${CWD}/gdal-web/dl/daily"
+DAILYDIR="/osgeo/gdal/gdal-web/daily"
 LOG="/dev/null"
 
 if test ${VERBOSE} = 1; then
@@ -52,6 +57,13 @@ fi
 
 cd ${GDALDIR}
 ${BUILDER} ${NIGHTLYVER} -date ${DATE} -branch ${SVNBRANCH} >& ${LOG}
+if test  $? -gt 0; then
+	echo
+	echo "Command ${BUILDER} failed. Check ${LOG} file for details."
+	cd ${CWD}
+	exit 1
+fi
+
 cd ${CWD}
 
 if test ${VERBOSE} = 1; then
@@ -62,9 +74,9 @@ if test ${VERBOSE} = 1; then
 	echo -n "Uploading ${NIGHTLYVER} to daily download..."
 fi
 
-find ${DAILYDIR} -name '*${BRANCH}*'
+find ${DAILYDIR} -name '*'${BRANCH}'*'
 if test $? -eq 0 ; then
-	find ${DAILYDIR} -name '*${BRANCH}*' | xargs rm -f
+	find ${DAILYDIR} -name '*'${BRANCH}'*' | xargs rm -f
 fi
 mv ${GDALDIR}/*${NIGHTLYVER}* ${DAILYDIR}
 mv ${GDALDIR}/gdalsvn*.zip ${DAILYDIR}
diff --git a/ltmain.sh b/ltmain.sh
index 3506ead..3061e3c 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -1,9 +1,9 @@
-# Generated from ltmain.m4sh.
 
-# ltmain.sh (GNU libtool) 2.2.6
+# libtool (GNU libtool) 2.4
 # Written by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 1996
 
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # This is free software; see the source for copying conditions.  There is NO
 # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
@@ -32,50 +32,56 @@
 #
 # Provide generalized library-building support services.
 #
-#     --config             show all configuration variables
-#     --debug              enable verbose shell tracing
-# -n, --dry-run            display commands without modifying any files
-#     --features           display basic configuration information and exit
-#     --mode=MODE          use operation mode MODE
-#     --preserve-dup-deps  don't remove duplicate dependency libraries
-#     --quiet, --silent    don't print informational messages
-#     --tag=TAG            use configuration variables from tag TAG
-# -v, --verbose            print informational messages (default)
-#     --version            print version information
-# -h, --help               print short or long help message
+#       --config             show all configuration variables
+#       --debug              enable verbose shell tracing
+#   -n, --dry-run            display commands without modifying any files
+#       --features           display basic configuration information and exit
+#       --mode=MODE          use operation mode MODE
+#       --preserve-dup-deps  don't remove duplicate dependency libraries
+#       --quiet, --silent    don't print informational messages
+#       --no-quiet, --no-silent
+#                            print informational messages (default)
+#       --tag=TAG            use configuration variables from tag TAG
+#   -v, --verbose            print more informational messages than default
+#       --no-verbose         don't print the extra informational messages
+#       --version            print version information
+#   -h, --help, --help-all   print short, long, or detailed help message
 #
 # MODE must be one of the following:
 #
-#       clean              remove files from the build directory
-#       compile            compile a source file into a libtool object
-#       execute            automatically set library path, then run a program
-#       finish             complete the installation of libtool libraries
-#       install            install libraries or executables
-#       link               create a library or an executable
-#       uninstall          remove libraries from an installed directory
+#         clean              remove files from the build directory
+#         compile            compile a source file into a libtool object
+#         execute            automatically set library path, then run a program
+#         finish             complete the installation of libtool libraries
+#         install            install libraries or executables
+#         link               create a library or an executable
+#         uninstall          remove libraries from an installed directory
 #
-# MODE-ARGS vary depending on the MODE.
+# MODE-ARGS vary depending on the MODE.  When passed as first option,
+# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
 # Try `$progname --help --mode=MODE' for a more detailed description of MODE.
 #
 # When reporting a bug, please describe a test case to reproduce it and
 # include the following information:
 #
-#       host-triplet:	$host
-#       shell:		$SHELL
-#       compiler:		$LTCC
-#       compiler flags:		$LTCFLAGS
-#       linker:		$LD (gnu? $with_gnu_ld)
-#       $progname:		(GNU libtool) 2.2.6 Debian-2.2.6a-4
-#       automake:		$automake_version
-#       autoconf:		$autoconf_version
+#         host-triplet:	$host
+#         shell:		$SHELL
+#         compiler:		$LTCC
+#         compiler flags:		$LTCFLAGS
+#         linker:		$LD (gnu? $with_gnu_ld)
+#         $progname:	(GNU libtool) 2.4
+#         automake:	$automake_version
+#         autoconf:	$autoconf_version
 #
 # Report bugs to <bug-libtool at gnu.org>.
+# GNU libtool home page: <http://www.gnu.org/software/libtool/>.
+# General help using GNU software: <http://www.gnu.org/gethelp/>.
 
-PROGRAM=ltmain.sh
+PROGRAM=libtool
 PACKAGE=libtool
-VERSION="2.2.6 Debian-2.2.6a-4"
+VERSION=2.4
 TIMESTAMP=""
-package_revision=1.3012
+package_revision=1.3293
 
 # Be Bourne compatible
 if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
@@ -91,10 +97,15 @@ fi
 BIN_SH=xpg4; export BIN_SH # for Tru64
 DUALCASE=1; export DUALCASE # for MKS sh
 
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
 # NLS nuisances: We save the old values to restore during execute mode.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
 lt_user_locale=
 lt_safe_locale=
 for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
@@ -107,24 +118,33 @@ do
 	  lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
 	fi"
 done
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
 
 $lt_unset CDPATH
 
 
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
 
 
 
 : ${CP="cp -f"}
-: ${ECHO="echo"}
-: ${EGREP="/bin/grep -E"}
-: ${FGREP="/bin/grep -F"}
-: ${GREP="/bin/grep"}
+test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
+: ${EGREP="grep -E"}
+: ${FGREP="grep -F"}
+: ${GREP="grep"}
 : ${LN_S="ln -s"}
 : ${MAKE="make"}
 : ${MKDIR="mkdir"}
 : ${MV="mv -f"}
 : ${RM="rm -f"}
-: ${SED="/bin/sed"}
+: ${SED="sed"}
 : ${SHELL="${CONFIG_SHELL-/bin/sh}"}
 : ${Xsed="$SED -e 1s/^X//"}
 
@@ -144,6 +164,27 @@ IFS=" 	$lt_nl"
 dirname="s,/[^/]*$,,"
 basename="s,^.*/,,"
 
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+    func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+    if test "X$func_dirname_result" = "X${1}"; then
+      func_dirname_result="${3}"
+    else
+      func_dirname_result="$func_dirname_result${2}"
+    fi
+} # func_dirname may be replaced by extended shell implementation
+
+
+# func_basename file
+func_basename ()
+{
+    func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+} # func_basename may be replaced by extended shell implementation
+
+
 # func_dirname_and_basename file append nondir_replacement
 # perform func_basename and func_dirname in a single function
 # call:
@@ -158,33 +199,183 @@ basename="s,^.*/,,"
 # those functions but instead duplicate the functionality here.
 func_dirname_and_basename ()
 {
-  # Extract subdirectory from the argument.
-  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
-  if test "X$func_dirname_result" = "X${1}"; then
-    func_dirname_result="${3}"
-  else
-    func_dirname_result="$func_dirname_result${2}"
-  fi
-  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+    # Extract subdirectory from the argument.
+    func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"`
+    if test "X$func_dirname_result" = "X${1}"; then
+      func_dirname_result="${3}"
+    else
+      func_dirname_result="$func_dirname_result${2}"
+    fi
+    func_basename_result=`$ECHO "${1}" | $SED -e "$basename"`
+} # func_dirname_and_basename may be replaced by extended shell implementation
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+    case ${2} in
+      .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+      *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+    esac
+} # func_stripname may be replaced by extended shell implementation
+
+
+# These SED scripts presuppose an absolute path with a trailing slash.
+pathcar='s,^/\([^/]*\).*$,\1,'
+pathcdr='s,^/[^/]*,,'
+removedotparts=':dotsl
+		s@/\./@/@g
+		t dotsl
+		s,/\.$,/,'
+collapseslashes='s@/\{1,\}@/@g'
+finalslash='s,/*$,/,'
+
+# func_normal_abspath PATH
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+#             value returned in "$func_normal_abspath_result"
+func_normal_abspath ()
+{
+  # Start from root dir and reassemble the path.
+  func_normal_abspath_result=
+  func_normal_abspath_tpath=$1
+  func_normal_abspath_altnamespace=
+  case $func_normal_abspath_tpath in
+    "")
+      # Empty path, that just means $cwd.
+      func_stripname '' '/' "`pwd`"
+      func_normal_abspath_result=$func_stripname_result
+      return
+    ;;
+    # The next three entries are used to spot a run of precisely
+    # two leading slashes without using negated character classes;
+    # we take advantage of case's first-match behaviour.
+    ///*)
+      # Unusual form of absolute path, do nothing.
+    ;;
+    //*)
+      # Not necessarily an ordinary path; POSIX reserves leading '//'
+      # and for example Cygwin uses it to access remote file shares
+      # over CIFS/SMB, so we conserve a leading double slash if found.
+      func_normal_abspath_altnamespace=/
+    ;;
+    /*)
+      # Absolute path, do nothing.
+    ;;
+    *)
+      # Relative path, prepend $cwd.
+      func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+    ;;
+  esac
+  # Cancel out all the simple stuff to save iterations.  We also want
+  # the path to end with a slash for ease of parsing, so make sure
+  # there is one (and only one) here.
+  func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
+  while :; do
+    # Processed it all yet?
+    if test "$func_normal_abspath_tpath" = / ; then
+      # If we ascended to the root using ".." the result may be empty now.
+      if test -z "$func_normal_abspath_result" ; then
+        func_normal_abspath_result=/
+      fi
+      break
+    fi
+    func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcar"`
+    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcdr"`
+    # Figure out what to do with it
+    case $func_normal_abspath_tcomponent in
+      "")
+        # Trailing empty path component, ignore it.
+      ;;
+      ..)
+        # Parent dir; strip last assembled component from result.
+        func_dirname "$func_normal_abspath_result"
+        func_normal_abspath_result=$func_dirname_result
+      ;;
+      *)
+        # Actual path component, append it.
+        func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
+      ;;
+    esac
+  done
+  # Restore leading double-slash if one was found on entry.
+  func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
 }
 
-# Generated shell functions inserted here.
+# func_relative_path SRCDIR DSTDIR
+# generates a relative path from SRCDIR to DSTDIR, with a trailing
+# slash if non-empty, suitable for immediately appending a filename
+# without needing to append a separator.
+#             value returned in "$func_relative_path_result"
+func_relative_path ()
+{
+  func_relative_path_result=
+  func_normal_abspath "$1"
+  func_relative_path_tlibdir=$func_normal_abspath_result
+  func_normal_abspath "$2"
+  func_relative_path_tbindir=$func_normal_abspath_result
+
+  # Ascend the tree starting from libdir
+  while :; do
+    # check if we have found a prefix of bindir
+    case $func_relative_path_tbindir in
+      $func_relative_path_tlibdir)
+        # found an exact match
+        func_relative_path_tcancelled=
+        break
+        ;;
+      $func_relative_path_tlibdir*)
+        # found a matching prefix
+        func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+        func_relative_path_tcancelled=$func_stripname_result
+        if test -z "$func_relative_path_result"; then
+          func_relative_path_result=.
+        fi
+        break
+        ;;
+      *)
+        func_dirname $func_relative_path_tlibdir
+        func_relative_path_tlibdir=${func_dirname_result}
+        if test "x$func_relative_path_tlibdir" = x ; then
+          # Have to descend all the way to the root!
+          func_relative_path_result=../$func_relative_path_result
+          func_relative_path_tcancelled=$func_relative_path_tbindir
+          break
+        fi
+        func_relative_path_result=../$func_relative_path_result
+        ;;
+    esac
+  done
 
-# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
-# is ksh but when the shell is invoked as "sh" and the current value of
-# the _XPG environment variable is not equal to 1 (one), the special
-# positional parameter $0, within a function call, is the name of the
-# function.
-progpath="$0"
+  # Now calculate path; take care to avoid doubling-up slashes.
+  func_stripname '' '/' "$func_relative_path_result"
+  func_relative_path_result=$func_stripname_result
+  func_stripname '/' '/' "$func_relative_path_tcancelled"
+  if test "x$func_stripname_result" != x ; then
+    func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
+  fi
+
+  # Normalisation. If bindir is libdir, return empty string,
+  # else relative path ending with a slash; either way, target
+  # file name can be directly appended.
+  if test ! -z "$func_relative_path_result"; then
+    func_stripname './' '' "$func_relative_path_result/"
+    func_relative_path_result=$func_stripname_result
+  fi
+}
 
 # The name of this program:
-# In the unlikely event $progname began with a '-', it would play havoc with
-# func_echo (imagine progname=-n), so we prepend ./ in that case:
 func_dirname_and_basename "$progpath"
 progname=$func_basename_result
-case $progname in
-  -*) progname=./$progname ;;
-esac
 
 # Make sure we have an absolute path for reexecution:
 case $progpath in
@@ -215,6 +406,15 @@ sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
 # Same as above, but do not quote variable references.
 double_quote_subst='s/\(["`\\]\)/\\\1/g'
 
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s,[].[^$\\*\/],\\&,g'
+
+# Sed substitution that converts a w32 file name or path
+# which contains forward slashes, into one that contains
+# (escaped) backslashes.  A very naive implementation.
+lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
 # Re-`\' parameter expansions in output of double_quote_subst that were
 # `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
 # in input to double_quote_subst, that '$' was protected from expansion.
@@ -243,7 +443,7 @@ opt_warning=:
 # name if it has been set yet.
 func_echo ()
 {
-    $ECHO "$progname${mode+: }$mode: $*"
+    $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
 }
 
 # func_verbose arg...
@@ -258,18 +458,25 @@ func_verbose ()
     :
 }
 
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
 # func_error arg...
 # Echo program name prefixed message to standard error.
 func_error ()
 {
-    $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+    $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
 }
 
 # func_warning arg...
 # Echo program name prefixed warning message to standard error.
 func_warning ()
 {
-    $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+    $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
 
     # bash bug again:
     :
@@ -326,9 +533,9 @@ func_mkdir_p ()
         case $my_directory_path in */*) ;; *) break ;; esac
 
         # ...otherwise throw away the child directory and loop
-        my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"`
+        my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
       done
-      my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'`
+      my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
 
       save_mkdir_p_IFS="$IFS"; IFS=':'
       for my_dir in $my_dir_list; do
@@ -378,7 +585,7 @@ func_mktempdir ()
         func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
     fi
 
-    $ECHO "X$my_tmpdir" | $Xsed
+    $ECHO "$my_tmpdir"
 }
 
 
@@ -392,7 +599,7 @@ func_quote_for_eval ()
 {
     case $1 in
       *[\\\`\"\$]*)
-	func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;;
+	func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
       *)
         func_quote_for_eval_unquoted_result="$1" ;;
     esac
@@ -419,7 +626,7 @@ func_quote_for_expand ()
 {
     case $1 in
       *[\\\`\"]*)
-	my_arg=`$ECHO "X$1" | $Xsed \
+	my_arg=`$ECHO "$1" | $SED \
 	    -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
       *)
         my_arg="$1" ;;
@@ -488,15 +695,39 @@ func_show_eval_locale ()
     fi
 }
 
-
-
+# func_tr_sh
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result.  All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+  case $1 in
+  [0-9]* | *[!a-zA-Z0-9_]*)
+    func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'`
+    ;;
+  * )
+    func_tr_sh_result=$1
+    ;;
+  esac
+}
 
 
 # func_version
 # Echo version message to standard output and exit.
 func_version ()
 {
-    $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / {
+    $opt_debug
+
+    $SED -n '/(C)/!b go
+	:more
+	/\./!{
+	  N
+	  s/\n# / /
+	  b more
+	}
+	:go
+	/^# '$PROGRAM' (GNU /,/# warranty; / {
         s/^# //
 	s/^# *$//
         s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
@@ -509,22 +740,28 @@ func_version ()
 # Echo short help message to standard output and exit.
 func_usage ()
 {
-    $SED -n '/^# Usage:/,/# -h/ {
+    $opt_debug
+
+    $SED -n '/^# Usage:/,/^#  *.*--help/ {
         s/^# //
 	s/^# *$//
 	s/\$progname/'$progname'/
 	p
     }' < "$progpath"
-    $ECHO
+    echo
     $ECHO "run \`$progname --help | more' for full usage"
     exit $?
 }
 
-# func_help
-# Echo long help message to standard output and exit.
+# func_help [NOEXIT]
+# Echo long help message to standard output and exit,
+# unless 'noexit' is passed as argument.
 func_help ()
 {
+    $opt_debug
+
     $SED -n '/^# Usage:/,/# Report bugs to/ {
+	:print
         s/^# //
 	s/^# *$//
 	s*\$progname*'$progname'*
@@ -537,8 +774,15 @@ func_help ()
 	s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
 	s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
 	p
-     }' < "$progpath"
-    exit $?
+	d
+     }
+     /^# .* home page:/b print
+     /^# General help using/b print
+     ' < "$progpath"
+    ret=$?
+    if test -z "$1"; then
+      exit $ret
+    fi
 }
 
 # func_missing_arg argname
@@ -546,63 +790,106 @@ func_help ()
 # exit_cmd.
 func_missing_arg ()
 {
-    func_error "missing argument for $1"
+    $opt_debug
+
+    func_error "missing argument for $1."
     exit_cmd=exit
 }
 
-exit_cmd=:
 
+# func_split_short_opt shortopt
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+func_split_short_opt ()
+{
+    my_sed_short_opt='1s/^\(..\).*$/\1/;q'
+    my_sed_short_rest='1s/^..\(.*\)$/\1/;q'
+
+    func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"`
+    func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"`
+} # func_split_short_opt may be replaced by extended shell implementation
 
 
+# func_split_long_opt longopt
+# Set func_split_long_opt_name and func_split_long_opt_arg shell
+# variables after splitting LONGOPT at the `=' sign.
+func_split_long_opt ()
+{
+    my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
+    my_sed_long_arg='1s/^--[^=]*=//'
+
+    func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"`
+    func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"`
+} # func_split_long_opt may be replaced by extended shell implementation
+
+exit_cmd=:
+
 
 
-# Check that we have a working $ECHO.
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
-  # Yippee, $ECHO works!
-  :
-else
-  # Restart under the correct shell, and then maybe $ECHO will work.
-  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
-fi
 
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit $EXIT_SUCCESS
-fi
 
 magic="%%%MAGIC variable%%%"
 magic_exe="%%%MAGIC EXE variable%%%"
 
 # Global variables.
-# $mode is unset
 nonopt=
-execute_dlfiles=
 preserve_args=
 lo2o="s/\\.lo\$/.${objext}/"
 o2lo="s/\\.${objext}\$/.lo/"
 extracted_archives=
 extracted_serial=0
 
-opt_dry_run=false
-opt_duplicate_deps=false
-opt_silent=false
-opt_debug=:
-
 # If this variable is set in any of the actions, the command in it
 # will be execed at the end.  This prevents here-documents from being
 # left over by shells.
 exec_cmd=
 
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+    eval "${1}=\$${1}\${2}"
+} # func_append may be replaced by extended shell implementation
+
+# func_append_quoted var value
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+func_append_quoted ()
+{
+    func_quote_for_eval "${2}"
+    eval "${1}=\$${1}\\ \$func_quote_for_eval_result"
+} # func_append_quoted may be replaced by extended shell implementation
+
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+    func_arith_result=`expr "${@}"`
+} # func_arith may be replaced by extended shell implementation
+
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+    func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len`
+} # func_len may be replaced by extended shell implementation
+
+
+# func_lo2o object
+func_lo2o ()
+{
+    func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+} # func_lo2o may be replaced by extended shell implementation
+
+
+# func_xform libobj-or-source
+func_xform ()
+{
+    func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
+} # func_xform may be replaced by extended shell implementation
+
+
 # func_fatal_configuration arg...
 # Echo program name prefixed message to standard error, followed by
 # a configuration failure hint, and exit.
@@ -636,16 +923,16 @@ func_config ()
 # Display the features supported by this script.
 func_features ()
 {
-    $ECHO "host: $host"
+    echo "host: $host"
     if test "$build_libtool_libs" = yes; then
-      $ECHO "enable shared libraries"
+      echo "enable shared libraries"
     else
-      $ECHO "disable shared libraries"
+      echo "disable shared libraries"
     fi
     if test "$build_old_libs" = yes; then
-      $ECHO "enable static libraries"
+      echo "enable static libraries"
     else
-      $ECHO "disable static libraries"
+      echo "disable static libraries"
     fi
 
     exit $?
@@ -692,117 +979,204 @@ func_enable_tag ()
   esac
 }
 
-# Parse options once, thoroughly.  This comes as soon as possible in
-# the script to make things like `libtool --version' happen quickly.
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
 {
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+# Shorthand for --mode=foo, only valid as the first argument
+case $1 in
+clean|clea|cle|cl)
+  shift; set dummy --mode clean ${1+"$@"}; shift
+  ;;
+compile|compil|compi|comp|com|co|c)
+  shift; set dummy --mode compile ${1+"$@"}; shift
+  ;;
+execute|execut|execu|exec|exe|ex|e)
+  shift; set dummy --mode execute ${1+"$@"}; shift
+  ;;
+finish|finis|fini|fin|fi|f)
+  shift; set dummy --mode finish ${1+"$@"}; shift
+  ;;
+install|instal|insta|inst|ins|in|i)
+  shift; set dummy --mode install ${1+"$@"}; shift
+  ;;
+link|lin|li|l)
+  shift; set dummy --mode link ${1+"$@"}; shift
+  ;;
+uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+  shift; set dummy --mode uninstall ${1+"$@"}; shift
+  ;;
+esac
 
-  # Shorthand for --mode=foo, only valid as the first argument
-  case $1 in
-  clean|clea|cle|cl)
-    shift; set dummy --mode clean ${1+"$@"}; shift
-    ;;
-  compile|compil|compi|comp|com|co|c)
-    shift; set dummy --mode compile ${1+"$@"}; shift
-    ;;
-  execute|execut|execu|exec|exe|ex|e)
-    shift; set dummy --mode execute ${1+"$@"}; shift
-    ;;
-  finish|finis|fini|fin|fi|f)
-    shift; set dummy --mode finish ${1+"$@"}; shift
-    ;;
-  install|instal|insta|inst|ins|in|i)
-    shift; set dummy --mode install ${1+"$@"}; shift
-    ;;
-  link|lin|li|l)
-    shift; set dummy --mode link ${1+"$@"}; shift
-    ;;
-  uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
-    shift; set dummy --mode uninstall ${1+"$@"}; shift
-    ;;
-  esac
 
-  # Parse non-mode specific arguments:
-  while test "$#" -gt 0; do
+
+# Option defaults:
+opt_debug=:
+opt_dry_run=false
+opt_config=false
+opt_preserve_dup_deps=false
+opt_features=false
+opt_finish=false
+opt_help=false
+opt_help_all=false
+opt_silent=:
+opt_verbose=:
+opt_silent=false
+opt_verbose=false
+
+
+# Parse options once, thoroughly.  This comes as soon as possible in the
+# script to make things like `--version' happen as quickly as we can.
+{
+  # this just eases exit handling
+  while test $# -gt 0; do
     opt="$1"
     shift
-
     case $opt in
-      --config)		func_config					;;
-
-      --debug)		preserve_args="$preserve_args $opt"
+      --debug|-x)	opt_debug='set -x'
 			func_echo "enabling shell trace mode"
-			opt_debug='set -x'
 			$opt_debug
 			;;
-
-      -dlopen)		test "$#" -eq 0 && func_missing_arg "$opt" && break
-			execute_dlfiles="$execute_dlfiles $1"
-			shift
+      --dry-run|--dryrun|-n)
+			opt_dry_run=:
 			;;
-
-      --dry-run | -n)	opt_dry_run=:					;;
-      --features)       func_features					;;
-      --finish)		mode="finish"					;;
-
-      --mode)		test "$#" -eq 0 && func_missing_arg "$opt" && break
-			case $1 in
-			  # Valid mode arguments:
-			  clean)	;;
-			  compile)	;;
-			  execute)	;;
-			  finish)	;;
-			  install)	;;
-			  link)		;;
-			  relink)	;;
-			  uninstall)	;;
-
-			  # Catch anything else as an error
-			  *) func_error "invalid argument for $opt"
-			     exit_cmd=exit
-			     break
-			     ;;
-		        esac
-
-			mode="$1"
+      --config)
+			opt_config=:
+func_config
+			;;
+      --dlopen|-dlopen)
+			optarg="$1"
+			opt_dlopen="${opt_dlopen+$opt_dlopen
+}$optarg"
 			shift
 			;;
-
       --preserve-dup-deps)
-			opt_duplicate_deps=:				;;
-
-      --quiet|--silent)	preserve_args="$preserve_args $opt"
-			opt_silent=:
+			opt_preserve_dup_deps=:
 			;;
-
-      --verbose| -v)	preserve_args="$preserve_args $opt"
+      --features)
+			opt_features=:
+func_features
+			;;
+      --finish)
+			opt_finish=:
+set dummy --mode finish ${1+"$@"}; shift
+			;;
+      --help)
+			opt_help=:
+			;;
+      --help-all)
+			opt_help_all=:
+opt_help=': help-all'
+			;;
+      --mode)
+			test $# = 0 && func_missing_arg $opt && break
+			optarg="$1"
+			opt_mode="$optarg"
+case $optarg in
+  # Valid mode arguments:
+  clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+  # Catch anything else as an error
+  *) func_error "invalid argument for $opt"
+     exit_cmd=exit
+     break
+     ;;
+esac
+			shift
+			;;
+      --no-silent|--no-quiet)
 			opt_silent=false
+func_append preserve_args " $opt"
 			;;
-
-      --tag)		test "$#" -eq 0 && func_missing_arg "$opt" && break
-			preserve_args="$preserve_args $opt $1"
-			func_enable_tag "$1"	# tagname is set here
+      --no-verbose)
+			opt_verbose=false
+func_append preserve_args " $opt"
+			;;
+      --silent|--quiet)
+			opt_silent=:
+func_append preserve_args " $opt"
+        opt_verbose=false
+			;;
+      --verbose|-v)
+			opt_verbose=:
+func_append preserve_args " $opt"
+opt_silent=false
+			;;
+      --tag)
+			test $# = 0 && func_missing_arg $opt && break
+			optarg="$1"
+			opt_tag="$optarg"
+func_append preserve_args " $opt $optarg"
+func_enable_tag "$optarg"
 			shift
 			;;
 
+      -\?|-h)		func_usage				;;
+      --help)		func_help				;;
+      --version)	func_version				;;
+
       # Separate optargs to long options:
-      -dlopen=*|--mode=*|--tag=*)
-			func_opt_split "$opt"
-			set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+      --*=*)
+			func_split_long_opt "$opt"
+			set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"}
 			shift
 			;;
 
-      -\?|-h)		func_usage					;;
-      --help)		opt_help=:					;;
-      --version)	func_version					;;
-
-      -*)		func_fatal_help "unrecognized option \`$opt'"	;;
-
-      *)		nonopt="$opt"
-			break
+      # Separate non-argument short options:
+      -\?*|-h*|-n*|-v*)
+			func_split_short_opt "$opt"
+			set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"}
+			shift
 			;;
+
+      --)		break					;;
+      -*)		func_fatal_help "unrecognized option \`$opt'" ;;
+      *)		set dummy "$opt" ${1+"$@"};	shift; break  ;;
     esac
   done
 
+  # Validate options:
+
+  # save first non-option argument
+  if test "$#" -gt 0; then
+    nonopt="$opt"
+    shift
+  fi
+
+  # preserve --debug
+  test "$opt_debug" = : || func_append preserve_args " --debug"
 
   case $host in
     *cygwin* | *mingw* | *pw32* | *cegcc*)
@@ -810,82 +1184,44 @@ func_enable_tag ()
       opt_duplicate_compiler_generated_deps=:
       ;;
     *)
-      opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+      opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
       ;;
   esac
 
-  # Having warned about all mis-specified options, bail out if
-  # anything was wrong.
-  $exit_cmd $EXIT_FAILURE
-}
+  $opt_help || {
+    # Sanity checks first:
+    func_check_version_match
 
-# func_check_version_match
-# Ensure that we are using m4 macros, and libtool script from the same
-# release of libtool.
-func_check_version_match ()
-{
-  if test "$package_revision" != "$macro_revision"; then
-    if test "$VERSION" != "$macro_version"; then
-      if test -z "$macro_version"; then
-        cat >&2 <<_LT_EOF
-$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
-$progname: definition of this LT_INIT comes from an older release.
-$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
-$progname: and run autoconf again.
-_LT_EOF
-      else
-        cat >&2 <<_LT_EOF
-$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
-$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
-$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
-$progname: and run autoconf again.
-_LT_EOF
-      fi
-    else
-      cat >&2 <<_LT_EOF
-$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
-$progname: but the definition of this LT_INIT comes from revision $macro_revision.
-$progname: You should recreate aclocal.m4 with macros from revision $package_revision
-$progname: of $PACKAGE $VERSION and run autoconf again.
-_LT_EOF
+    if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+      func_fatal_configuration "not configured to build any kind of library"
     fi
 
-    exit $EXIT_MISMATCH
-  fi
-}
-
-
-## ----------- ##
-##    Main.    ##
-## ----------- ##
+    # Darwin sucks
+    eval std_shrext=\"$shrext_cmds\"
 
-$opt_help || {
-  # Sanity checks first:
-  func_check_version_match
-
-  if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
-    func_fatal_configuration "not configured to build any kind of library"
-  fi
+    # Only execute mode is allowed to have -dlopen flags.
+    if test -n "$opt_dlopen" && test "$opt_mode" != execute; then
+      func_error "unrecognized option \`-dlopen'"
+      $ECHO "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
 
-  test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+    # Change the help message to a mode-specific one.
+    generic_help="$help"
+    help="Try \`$progname --help --mode=$opt_mode' for more information."
+  }
 
 
-  # Darwin sucks
-  eval std_shrext=\"$shrext_cmds\"
+  # Bail if the options were screwed
+  $exit_cmd $EXIT_FAILURE
+}
 
 
-  # Only execute mode is allowed to have -dlopen flags.
-  if test -n "$execute_dlfiles" && test "$mode" != execute; then
-    func_error "unrecognized option \`-dlopen'"
-    $ECHO "$help" 1>&2
-    exit $EXIT_FAILURE
-  fi
 
-  # Change the help message to a mode-specific one.
-  generic_help="$help"
-  help="Try \`$progname --help --mode=$mode' for more information."
-}
 
+## ----------- ##
+##    Main.    ##
+## ----------- ##
 
 # func_lalib_p file
 # True iff FILE is a libtool `.la' library or `.lo' object file.
@@ -950,12 +1286,9 @@ func_ltwrapper_executable_p ()
 # temporary ltwrapper_script.
 func_ltwrapper_scriptname ()
 {
-    func_ltwrapper_scriptname_result=""
-    if func_ltwrapper_executable_p "$1"; then
-	func_dirname_and_basename "$1" "" "."
-	func_stripname '' '.exe' "$func_basename_result"
-	func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
-    fi
+    func_dirname_and_basename "$1" "" "."
+    func_stripname '' '.exe' "$func_basename_result"
+    func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
 }
 
 # func_ltwrapper_p file
@@ -1001,6 +1334,37 @@ func_source ()
 }
 
 
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot.  Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+  func_resolve_sysroot_result=$1
+  case $func_resolve_sysroot_result in
+  =*)
+    func_stripname '=' '' "$func_resolve_sysroot_result"
+    func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+    ;;
+  esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+  case "$lt_sysroot:$1" in
+  ?*:"$lt_sysroot"*)
+    func_stripname "$lt_sysroot" '' "$1"
+    func_replace_sysroot_result="=$func_stripname_result"
+    ;;
+  *)
+    # Including no sysroot.
+    func_replace_sysroot_result=$1
+    ;;
+  esac
+}
+
 # func_infer_tag arg
 # Infer tagged configuration to use if any are available and
 # if one wasn't chosen via the "--tag" command line option.
@@ -1013,13 +1377,15 @@ func_infer_tag ()
     if test -n "$available_tags" && test -z "$tagname"; then
       CC_quoted=
       for arg in $CC; do
-        func_quote_for_eval "$arg"
-	CC_quoted="$CC_quoted $func_quote_for_eval_result"
+	func_append_quoted CC_quoted "$arg"
       done
+      CC_expanded=`func_echo_all $CC`
+      CC_quoted_expanded=`func_echo_all $CC_quoted`
       case $@ in
       # Blanks in the command may have been stripped by the calling shell,
       # but not from the CC environment variable when configure was run.
-      " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;;
+      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
       # Blanks at the start of $base_compile will cause this to fail
       # if we don't check for them as well.
       *)
@@ -1030,11 +1396,13 @@ func_infer_tag ()
 	    CC_quoted=
 	    for arg in $CC; do
 	      # Double-quote args containing other shell metacharacters.
-	      func_quote_for_eval "$arg"
-	      CC_quoted="$CC_quoted $func_quote_for_eval_result"
+	      func_append_quoted CC_quoted "$arg"
 	    done
+	    CC_expanded=`func_echo_all $CC`
+	    CC_quoted_expanded=`func_echo_all $CC_quoted`
 	    case "$@ " in
-	      " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*)
+	    " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+	    " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
 	      # The compiler in the base compile command matches
 	      # the one in the tagged configuration.
 	      # Assume this is the tagged configuration we want.
@@ -1097,6 +1465,486 @@ EOF
     }
 }
 
+
+##################################################
+# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
+##################################################
+
+# func_convert_core_file_wine_to_w32 ARG
+# Helper function used by file name conversion functions when $build is *nix,
+# and $host is mingw, cygwin, or some other w32 environment. Relies on a
+# correctly configured wine environment available, with the winepath program
+# in $build's $PATH.
+#
+# ARG is the $build file name to be converted to w32 format.
+# Result is available in $func_convert_core_file_wine_to_w32_result, and will
+# be empty on error (or when ARG is empty)
+func_convert_core_file_wine_to_w32 ()
+{
+  $opt_debug
+  func_convert_core_file_wine_to_w32_result="$1"
+  if test -n "$1"; then
+    # Unfortunately, winepath does not exit with a non-zero error code, so we
+    # are forced to check the contents of stdout. On the other hand, if the
+    # command is not found, the shell will set an exit code of 127 and print
+    # *an error message* to stdout. So we must check for both error code of
+    # zero AND non-empty stdout, which explains the odd construction:
+    func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
+    if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then
+      func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+        $SED -e "$lt_sed_naive_backslashify"`
+    else
+      func_convert_core_file_wine_to_w32_result=
+    fi
+  fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+  $opt_debug
+  # unfortunately, winepath doesn't convert paths, only file names
+  func_convert_core_path_wine_to_w32_result=""
+  if test -n "$1"; then
+    oldIFS=$IFS
+    IFS=:
+    for func_convert_core_path_wine_to_w32_f in $1; do
+      IFS=$oldIFS
+      func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+      if test -n "$func_convert_core_file_wine_to_w32_result" ; then
+        if test -z "$func_convert_core_path_wine_to_w32_result"; then
+          func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result"
+        else
+          func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+        fi
+      fi
+    done
+    IFS=$oldIFS
+  fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+  $opt_debug
+  if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+    func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+    if test "$?" -ne 0; then
+      # on failure, ensure result is empty
+      func_cygpath_result=
+    fi
+  else
+    func_cygpath_result=
+    func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'"
+  fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format.  Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+  $opt_debug
+  # awkward: cmd appends spaces to result
+  func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+    $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+  $opt_debug
+  if test -z "$2" && test -n "$1" ; then
+    func_error "Could not determine host file name corresponding to"
+    func_error "  \`$1'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback:
+    func_to_host_file_result="$1"
+  fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+  $opt_debug
+  if test -z "$4" && test -n "$3"; then
+    func_error "Could not determine the host path corresponding to"
+    func_error "  \`$3'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback.  This is a deliberately simplistic "conversion" and
+    # should not be "improved".  See libtool.info.
+    if test "x$1" != "x$2"; then
+      lt_replace_pathsep_chars="s|$1|$2|g"
+      func_to_host_path_result=`echo "$3" |
+        $SED -e "$lt_replace_pathsep_chars"`
+    else
+      func_to_host_path_result="$3"
+    fi
+  fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+  $opt_debug
+  case $4 in
+  $1 ) func_to_host_path_result="$3$func_to_host_path_result"
+    ;;
+  esac
+  case $4 in
+  $2 ) func_append func_to_host_path_result "$3"
+    ;;
+  esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via `$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+  $opt_debug
+  $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result.  If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+  $opt_debug
+  case ,$2, in
+    *,"$to_tool_file_cmd",*)
+      func_to_tool_file_result=$1
+      ;;
+    *)
+      $to_tool_file_cmd "$1"
+      func_to_tool_file_result=$func_to_host_file_result
+      ;;
+  esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+  func_to_host_file_result="$1"
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_msys_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+    # LT_CYGPATH in this case.
+    func_to_host_file_result=`cygpath -m "$1"`
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format.  Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_file_wine_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_file_wine_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_msys_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format.  Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set.  Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+    func_convert_core_file_wine_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via `$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format.  If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+#   file name conversion function    : func_convert_file_X_to_Y ()
+#   path conversion function         : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same.  If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+  $opt_debug
+  if test -z "$to_host_path_cmd"; then
+    func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+    to_host_path_cmd="func_convert_path_${func_stripname_result}"
+  fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+  $opt_debug
+  func_init_to_host_path_cmd
+  $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+  func_to_host_path_result="$1"
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from ARG.  MSYS
+    # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+    # and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_msys_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format.  Requires a wine environment and
+# a working winepath.  Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_path_wine_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format.  Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set.  Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from
+    # ARG. msys behavior is inconsistent here, cygpath turns them
+    # into '.;' and ';.', and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
 # func_mode_compile arg...
 func_mode_compile ()
 {
@@ -1137,12 +1985,12 @@ func_mode_compile ()
 	  ;;
 
 	-pie | -fpie | -fPIE)
-          pie_flag="$pie_flag $arg"
+          func_append pie_flag " $arg"
 	  continue
 	  ;;
 
 	-shared | -static | -prefer-pic | -prefer-non-pic)
-	  later="$later $arg"
+	  func_append later " $arg"
 	  continue
 	  ;;
 
@@ -1163,15 +2011,14 @@ func_mode_compile ()
 	  save_ifs="$IFS"; IFS=','
 	  for arg in $args; do
 	    IFS="$save_ifs"
-	    func_quote_for_eval "$arg"
-	    lastarg="$lastarg $func_quote_for_eval_result"
+	    func_append_quoted lastarg "$arg"
 	  done
 	  IFS="$save_ifs"
 	  func_stripname ' ' '' "$lastarg"
 	  lastarg=$func_stripname_result
 
 	  # Add the arguments to base_compile.
-	  base_compile="$base_compile $lastarg"
+	  func_append base_compile " $lastarg"
 	  continue
 	  ;;
 
@@ -1187,8 +2034,7 @@ func_mode_compile ()
       esac    #  case $arg_mode
 
       # Aesthetically quote the previous argument.
-      func_quote_for_eval "$lastarg"
-      base_compile="$base_compile $func_quote_for_eval_result"
+      func_append_quoted base_compile "$lastarg"
     done # for arg
 
     case $arg_mode in
@@ -1213,7 +2059,7 @@ func_mode_compile ()
     *.[cCFSifmso] | \
     *.ada | *.adb | *.ads | *.asm | \
     *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
-    *.[fF][09]? | *.for | *.java | *.obj | *.sx)
+    *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup)
       func_xform "$libobj"
       libobj=$func_xform_result
       ;;
@@ -1288,7 +2134,7 @@ func_mode_compile ()
     # Calculate the filename of the output object if compiler does
     # not support -o with -c
     if test "$compiler_c_o" = no; then
-      output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
       lockfile="$output_obj.lock"
     else
       output_obj=
@@ -1319,17 +2165,16 @@ compiler."
 	$opt_dry_run || $RM $removelist
 	exit $EXIT_FAILURE
       fi
-      removelist="$removelist $output_obj"
+      func_append removelist " $output_obj"
       $ECHO "$srcfile" > "$lockfile"
     fi
 
     $opt_dry_run || $RM $removelist
-    removelist="$removelist $lockfile"
+    func_append removelist " $lockfile"
     trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
 
-    if test -n "$fix_srcfile_path"; then
-      eval srcfile=\"$fix_srcfile_path\"
-    fi
+    func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+    srcfile=$func_to_tool_file_result
     func_quote_for_eval "$srcfile"
     qsrcfile=$func_quote_for_eval_result
 
@@ -1349,7 +2194,7 @@ compiler."
 
       if test -z "$output_obj"; then
 	# Place PIC objects in $objdir
-	command="$command -o $lobj"
+	func_append command " -o $lobj"
       fi
 
       func_show_eval_locale "$command"	\
@@ -1396,11 +2241,11 @@ compiler."
 	command="$base_compile $qsrcfile $pic_flag"
       fi
       if test "$compiler_c_o" = yes; then
-	command="$command -o $obj"
+	func_append command " -o $obj"
       fi
 
       # Suppress compiler output if we already did a PIC compilation.
-      command="$command$suppress_output"
+      func_append command "$suppress_output"
       func_show_eval_locale "$command" \
         '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
 
@@ -1445,13 +2290,13 @@ compiler."
 }
 
 $opt_help || {
-test "$mode" = compile && func_mode_compile ${1+"$@"}
+  test "$opt_mode" = compile && func_mode_compile ${1+"$@"}
 }
 
 func_mode_help ()
 {
     # We need to display help for each of the modes.
-    case $mode in
+    case $opt_mode in
       "")
         # Generic help is extracted from the usage comments
         # at the start of this file.
@@ -1482,10 +2327,11 @@ This mode accepts the following additional options:
 
   -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
   -no-suppress      do not suppress compiler output for multiple passes
-  -prefer-pic       try to building PIC objects only
-  -prefer-non-pic   try to building non-PIC objects only
+  -prefer-pic       try to build PIC objects only
+  -prefer-non-pic   try to build non-PIC objects only
   -shared           do not build a \`.o' file suitable for static linking
   -static           only build a \`.o' file suitable for static linking
+  -Wc,FLAG          pass FLAG directly to the compiler
 
 COMPILE-COMMAND is a command to be used in creating a \`standard' object file
 from the given SOURCEFILE.
@@ -1538,7 +2384,7 @@ either the \`install' or \`cp' program.
 
 The following components of INSTALL-COMMAND are treated specially:
 
-  -inst-prefix PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
 
 The rest of the components are interpreted as arguments to that command (only
 BSD-compatible install options are recognized)."
@@ -1558,6 +2404,8 @@ The following components of LINK-COMMAND are treated specially:
 
   -all-static       do not do any dynamic linking at all
   -avoid-version    do not add a version suffix if possible
+  -bindir BINDIR    specify path to binaries directory (for systems where
+                    libraries must be found in the PATH setting at runtime)
   -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
   -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
   -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
@@ -1586,6 +2434,11 @@ The following components of LINK-COMMAND are treated specially:
   -version-info CURRENT[:REVISION[:AGE]]
                     specify library version info [each variable defaults to 0]
   -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -Wc,FLAG
+  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wl,FLAG
+  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
+  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
 
 All other options (arguments beginning with \`-') are ignored.
 
@@ -1619,18 +2472,44 @@ Otherwise, only FILE itself is deleted using RM."
         ;;
 
       *)
-        func_fatal_help "invalid operation mode \`$mode'"
+        func_fatal_help "invalid operation mode \`$opt_mode'"
         ;;
     esac
 
-    $ECHO
+    echo
     $ECHO "Try \`$progname --help' for more information about other modes."
-
-    exit $?
 }
 
-  # Now that we've collected a possible --mode arg, show help if necessary
-  $opt_help && func_mode_help
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+  if test "$opt_help" = :; then
+    func_mode_help
+  else
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	func_mode_help
+      done
+    } | sed -n '1p; 2,$s/^Usage:/  or: /p'
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	echo
+	func_mode_help
+      done
+    } |
+    sed '1d
+      /^When reporting/,/^Report/{
+	H
+	d
+      }
+      $x
+      /information about other modes/d
+      /more detailed .*MODE/d
+      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+  fi
+  exit $?
+fi
 
 
 # func_mode_execute arg...
@@ -1643,13 +2522,16 @@ func_mode_execute ()
       func_fatal_help "you must specify a COMMAND"
 
     # Handle -dlopen flags immediately.
-    for file in $execute_dlfiles; do
+    for file in $opt_dlopen; do
       test -f "$file" \
 	|| func_fatal_help "\`$file' is not a file"
 
       dir=
       case $file in
       *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
 	# Check to see that this really is a libtool archive.
 	func_lalib_unsafe_p "$file" \
 	  || func_fatal_help "\`$lib' is not a valid libtool archive"
@@ -1671,7 +2553,7 @@ func_mode_execute ()
 	dir="$func_dirname_result"
 
 	if test -f "$dir/$objdir/$dlname"; then
-	  dir="$dir/$objdir"
+	  func_append dir "/$objdir"
 	else
 	  if test ! -f "$dir/$dlname"; then
 	    func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
@@ -1712,7 +2594,7 @@ func_mode_execute ()
     for file
     do
       case $file in
-      -*) ;;
+      -* | *.la | *.lo ) ;;
       *)
 	# Do a test to see if this is really a libtool program.
 	if func_ltwrapper_script_p "$file"; then
@@ -1728,8 +2610,7 @@ func_mode_execute ()
 	;;
       esac
       # Quote arguments (to preserve shell metacharacters).
-      func_quote_for_eval "$file"
-      args="$args $func_quote_for_eval_result"
+      func_append_quoted args "$file"
     done
 
     if test "X$opt_dry_run" = Xfalse; then
@@ -1754,29 +2635,66 @@ func_mode_execute ()
       # Display what would be done.
       if test -n "$shlibpath_var"; then
 	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
-	$ECHO "export $shlibpath_var"
+	echo "export $shlibpath_var"
       fi
       $ECHO "$cmd$args"
       exit $EXIT_SUCCESS
     fi
 }
 
-test "$mode" = execute && func_mode_execute ${1+"$@"}
+test "$opt_mode" = execute && func_mode_execute ${1+"$@"}
 
 
 # func_mode_finish arg...
 func_mode_finish ()
 {
     $opt_debug
-    libdirs="$nonopt"
+    libs=
+    libdirs=
     admincmds=
 
-    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
-      for dir
-      do
-	libdirs="$libdirs $dir"
-      done
+    for opt in "$nonopt" ${1+"$@"}
+    do
+      if test -d "$opt"; then
+	func_append libdirs " $opt"
+
+      elif test -f "$opt"; then
+	if func_lalib_unsafe_p "$opt"; then
+	  func_append libs " $opt"
+	else
+	  func_warning "\`$opt' is not a valid libtool archive"
+	fi
+
+      else
+	func_fatal_error "invalid argument \`$opt'"
+      fi
+    done
+
+    if test -n "$libs"; then
+      if test -n "$lt_sysroot"; then
+        sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+        sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+      else
+        sysroot_cmd=
+      fi
 
+      # Remove sysroot references
+      if $opt_dry_run; then
+        for lib in $libs; do
+          echo "removing references to $lt_sysroot and \`=' prefixes from $lib"
+        done
+      else
+        tmpdir=`func_mktempdir`
+        for lib in $libs; do
+	  sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+	    > $tmpdir/tmp-la
+	  mv -f $tmpdir/tmp-la $lib
+	done
+        ${RM}r "$tmpdir"
+      fi
+    fi
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
       for libdir in $libdirs; do
 	if test -n "$finish_cmds"; then
 	  # Do each command in the finish commands.
@@ -1786,7 +2704,7 @@ func_mode_finish ()
 	if test -n "$finish_eval"; then
 	  # Do the single finish_eval.
 	  eval cmds=\"$finish_eval\"
-	  $opt_dry_run || eval "$cmds" || admincmds="$admincmds
+	  $opt_dry_run || eval "$cmds" || func_append admincmds "
        $cmds"
 	fi
       done
@@ -1795,53 +2713,55 @@ func_mode_finish ()
     # Exit here if they wanted silent mode.
     $opt_silent && exit $EXIT_SUCCESS
 
-    $ECHO "X----------------------------------------------------------------------" | $Xsed
-    $ECHO "Libraries have been installed in:"
-    for libdir in $libdirs; do
-      $ECHO "   $libdir"
-    done
-    $ECHO
-    $ECHO "If you ever happen to want to link against installed libraries"
-    $ECHO "in a given directory, LIBDIR, you must either use libtool, and"
-    $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'"
-    $ECHO "flag during linking and do at least one of the following:"
-    if test -n "$shlibpath_var"; then
-      $ECHO "   - add LIBDIR to the \`$shlibpath_var' environment variable"
-      $ECHO "     during execution"
-    fi
-    if test -n "$runpath_var"; then
-      $ECHO "   - add LIBDIR to the \`$runpath_var' environment variable"
-      $ECHO "     during linking"
-    fi
-    if test -n "$hardcode_libdir_flag_spec"; then
-      libdir=LIBDIR
-      eval flag=\"$hardcode_libdir_flag_spec\"
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      echo "----------------------------------------------------------------------"
+      echo "Libraries have been installed in:"
+      for libdir in $libdirs; do
+	$ECHO "   $libdir"
+      done
+      echo
+      echo "If you ever happen to want to link against installed libraries"
+      echo "in a given directory, LIBDIR, you must either use libtool, and"
+      echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+      echo "flag during linking and do at least one of the following:"
+      if test -n "$shlibpath_var"; then
+	echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+	echo "     during execution"
+      fi
+      if test -n "$runpath_var"; then
+	echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+	echo "     during linking"
+      fi
+      if test -n "$hardcode_libdir_flag_spec"; then
+	libdir=LIBDIR
+	eval flag=\"$hardcode_libdir_flag_spec\"
 
-      $ECHO "   - use the \`$flag' linker flag"
-    fi
-    if test -n "$admincmds"; then
-      $ECHO "   - have your system administrator run these commands:$admincmds"
-    fi
-    if test -f /etc/ld.so.conf; then
-      $ECHO "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
-    fi
-    $ECHO
+	$ECHO "   - use the \`$flag' linker flag"
+      fi
+      if test -n "$admincmds"; then
+	$ECHO "   - have your system administrator run these commands:$admincmds"
+      fi
+      if test -f /etc/ld.so.conf; then
+	echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+      fi
+      echo
 
-    $ECHO "See any operating system documentation about shared libraries for"
-    case $host in
-      solaris2.[6789]|solaris2.1[0-9])
-        $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual"
-	$ECHO "pages."
-	;;
-      *)
-        $ECHO "more information, such as the ld(1) and ld.so(8) manual pages."
-        ;;
-    esac
-    $ECHO "X----------------------------------------------------------------------" | $Xsed
+      echo "See any operating system documentation about shared libraries for"
+      case $host in
+	solaris2.[6789]|solaris2.1[0-9])
+	  echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	  echo "pages."
+	  ;;
+	*)
+	  echo "more information, such as the ld(1) and ld.so(8) manual pages."
+	  ;;
+      esac
+      echo "----------------------------------------------------------------------"
+    fi
     exit $EXIT_SUCCESS
 }
 
-test "$mode" = finish && func_mode_finish ${1+"$@"}
+test "$opt_mode" = finish && func_mode_finish ${1+"$@"}
 
 
 # func_mode_install arg...
@@ -1852,7 +2772,7 @@ func_mode_install ()
     # install_prog (especially on Windows NT).
     if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
        # Allow the use of GNU shtool's install command.
-       $ECHO "X$nonopt" | $GREP shtool >/dev/null; then
+       case $nonopt in *shtool*) :;; *) false;; esac; then
       # Aesthetically quote it.
       func_quote_for_eval "$nonopt"
       install_prog="$func_quote_for_eval_result "
@@ -1866,7 +2786,12 @@ func_mode_install ()
     # The real first argument should be the name of the installation program.
     # Aesthetically quote it.
     func_quote_for_eval "$arg"
-    install_prog="$install_prog$func_quote_for_eval_result"
+    func_append install_prog "$func_quote_for_eval_result"
+    install_shared_prog=$install_prog
+    case " $install_prog " in
+      *[\\\ /]cp\ *) install_cp=: ;;
+      *) install_cp=false ;;
+    esac
 
     # We need to accept at least all the BSD install flags.
     dest=
@@ -1876,10 +2801,12 @@ func_mode_install ()
     install_type=
     isdir=no
     stripme=
+    no_mode=:
     for arg
     do
+      arg2=
       if test -n "$dest"; then
-	files="$files $dest"
+	func_append files " $dest"
 	dest=$arg
 	continue
       fi
@@ -1887,10 +2814,9 @@ func_mode_install ()
       case $arg in
       -d) isdir=yes ;;
       -f)
-	case " $install_prog " in
-	*[\\\ /]cp\ *) ;;
-	*) prev=$arg ;;
-	esac
+	if $install_cp; then :; else
+	  prev=$arg
+	fi
 	;;
       -g | -m | -o)
 	prev=$arg
@@ -1904,6 +2830,10 @@ func_mode_install ()
       *)
 	# If the previous option needed an argument, then skip it.
 	if test -n "$prev"; then
+	  if test "x$prev" = x-m && test -n "$install_override_mode"; then
+	    arg2=$install_override_mode
+	    no_mode=false
+	  fi
 	  prev=
 	else
 	  dest=$arg
@@ -1914,7 +2844,11 @@ func_mode_install ()
 
       # Aesthetically quote the argument.
       func_quote_for_eval "$arg"
-      install_prog="$install_prog $func_quote_for_eval_result"
+      func_append install_prog " $func_quote_for_eval_result"
+      if test -n "$arg2"; then
+	func_quote_for_eval "$arg2"
+      fi
+      func_append install_shared_prog " $func_quote_for_eval_result"
     done
 
     test -z "$install_prog" && \
@@ -1923,6 +2857,13 @@ func_mode_install ()
     test -n "$prev" && \
       func_fatal_help "the \`$prev' option requires an argument"
 
+    if test -n "$install_override_mode" && $no_mode; then
+      if $install_cp; then :; else
+	func_quote_for_eval "$install_override_mode"
+	func_append install_shared_prog " -m $func_quote_for_eval_result"
+      fi
+    fi
+
     if test -z "$files"; then
       if test -z "$dest"; then
 	func_fatal_help "no file or destination specified"
@@ -1977,10 +2918,13 @@ func_mode_install ()
       case $file in
       *.$libext)
 	# Do the static libraries later.
-	staticlibs="$staticlibs $file"
+	func_append staticlibs " $file"
 	;;
 
       *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
 	# Check to see that this really is a libtool archive.
 	func_lalib_unsafe_p "$file" \
 	  || func_fatal_help "\`$file' is not a valid libtool archive"
@@ -1994,23 +2938,23 @@ func_mode_install ()
 	if test "X$destdir" = "X$libdir"; then
 	  case "$current_libdirs " in
 	  *" $libdir "*) ;;
-	  *) current_libdirs="$current_libdirs $libdir" ;;
+	  *) func_append current_libdirs " $libdir" ;;
 	  esac
 	else
 	  # Note the libdir as a future libdir.
 	  case "$future_libdirs " in
 	  *" $libdir "*) ;;
-	  *) future_libdirs="$future_libdirs $libdir" ;;
+	  *) func_append future_libdirs " $libdir" ;;
 	  esac
 	fi
 
 	func_dirname "$file" "/" ""
 	dir="$func_dirname_result"
-	dir="$dir$objdir"
+	func_append dir "$objdir"
 
 	if test -n "$relink_command"; then
 	  # Determine the prefix the user has applied to our future dir.
-	  inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"`
+	  inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
 
 	  # Don't allow the user to place us outside of our expected
 	  # location b/c this prevents finding dependent libraries that
@@ -2023,9 +2967,9 @@ func_mode_install ()
 
 	  if test -n "$inst_prefix_dir"; then
 	    # Stick the inst_prefix_dir data into the link command.
-	    relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
 	  else
-	    relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"`
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
 	  fi
 
 	  func_warning "relinking \`$file'"
@@ -2043,7 +2987,7 @@ func_mode_install ()
 	  test -n "$relink_command" && srcname="$realname"T
 
 	  # Install the shared library and build the symlinks.
-	  func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \
+	  func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
 	      'exit $?'
 	  tstripme="$stripme"
 	  case $host_os in
@@ -2083,7 +3027,7 @@ func_mode_install ()
 	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
 
 	# Maybe install the static library, too.
-	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+	test -n "$old_library" && func_append staticlibs " $dir/$old_library"
 	;;
 
       *.lo)
@@ -2183,7 +3127,7 @@ func_mode_install ()
 	    if test -f "$lib"; then
 	      func_source "$lib"
 	    fi
-	    libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
 	    if test -n "$libdir" && test ! -f "$libfile"; then
 	      func_warning "\`$lib' has not been installed in \`$libdir'"
 	      finalize=no
@@ -2202,7 +3146,7 @@ func_mode_install ()
 		file="$func_basename_result"
 	        outputname="$tmpdir/$file"
 	        # Replace the output file specification.
-	        relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
 
 	        $opt_silent || {
 	          func_quote_for_expand "$relink_command"
@@ -2221,7 +3165,7 @@ func_mode_install ()
 	    }
 	  else
 	    # Install the binary that we compiled earlier.
-	    file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+	    file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
 	  fi
 	fi
 
@@ -2280,7 +3224,7 @@ func_mode_install ()
     fi
 }
 
-test "$mode" = install && func_mode_install ${1+"$@"}
+test "$opt_mode" = install && func_mode_install ${1+"$@"}
 
 
 # func_generate_dlsyms outputname originator pic_p
@@ -2323,6 +3267,22 @@ func_generate_dlsyms ()
 extern \"C\" {
 #endif
 
+#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
 /* External symbol declarations for the compiler. */\
 "
 
@@ -2332,10 +3292,11 @@ extern \"C\" {
 	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
 
 	  # Add our own program objects to the symbol list.
-	  progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	  progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
 	  for progfile in $progfiles; do
-	    func_verbose "extracting global C symbols from \`$progfile'"
-	    $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
+	    func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+	    func_verbose "extracting global C symbols from \`$func_to_tool_file_result'"
+	    $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
 	  done
 
 	  if test -n "$exclude_expsyms"; then
@@ -2371,7 +3332,7 @@ extern \"C\" {
 	      eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
 	      eval '$MV "$nlist"T "$nlist"'
 	      case $host in
-	        *cygwin | *mingw* | *cegcc* )
+	        *cygwin* | *mingw* | *cegcc* )
 	          eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
 	          eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
 	          ;;
@@ -2384,10 +3345,52 @@ extern \"C\" {
 	  func_verbose "extracting global C symbols from \`$dlprefile'"
 	  func_basename "$dlprefile"
 	  name="$func_basename_result"
-	  $opt_dry_run || {
-	    eval '$ECHO ": $name " >> "$nlist"'
-	    eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
-	  }
+          case $host in
+	    *cygwin* | *mingw* | *cegcc* )
+	      # if an import library, we need to obtain dlname
+	      if func_win32_import_lib_p "$dlprefile"; then
+	        func_tr_sh "$dlprefile"
+	        eval "curr_lafile=\$libfile_$func_tr_sh_result"
+	        dlprefile_dlbasename=""
+	        if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+	          # Use subshell, to avoid clobbering current variable values
+	          dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+	          if test -n "$dlprefile_dlname" ; then
+	            func_basename "$dlprefile_dlname"
+	            dlprefile_dlbasename="$func_basename_result"
+	          else
+	            # no lafile. user explicitly requested -dlpreopen <import library>.
+	            $sharedlib_from_linklib_cmd "$dlprefile"
+	            dlprefile_dlbasename=$sharedlib_from_linklib_result
+	          fi
+	        fi
+	        $opt_dry_run || {
+	          if test -n "$dlprefile_dlbasename" ; then
+	            eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+	          else
+	            func_warning "Could not compute DLL name from $name"
+	            eval '$ECHO ": $name " >> "$nlist"'
+	          fi
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+	            $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+	        }
+	      else # not an import lib
+	        $opt_dry_run || {
+	          eval '$ECHO ": $name " >> "$nlist"'
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	        }
+	      fi
+	    ;;
+	    *)
+	      $opt_dry_run || {
+	        eval '$ECHO ": $name " >> "$nlist"'
+	        func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	        eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	      }
+	    ;;
+          esac
 	done
 
 	$opt_dry_run || {
@@ -2415,36 +3418,19 @@ extern \"C\" {
 	  if test -f "$nlist"S; then
 	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
 	  else
-	    $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	    echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
 	  fi
 
-	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+	  echo >> "$output_objdir/$my_dlsyms" "\
 
 /* The mapping between symbol names and symbols.  */
 typedef struct {
   const char *name;
   void *address;
 } lt_dlsymlist;
-"
-	  case $host in
-	  *cygwin* | *mingw* | *cegcc* )
-	    $ECHO >> "$output_objdir/$my_dlsyms" "\
-/* DATA imports from DLLs on WIN32 con't be const, because
-   runtime relocations are performed -- see ld's documentation
-   on pseudo-relocs.  */"
-	    lt_dlsym_const= ;;
-	  *osf5*)
-	    echo >> "$output_objdir/$my_dlsyms" "\
-/* This system does not cope well with relocations in const data */"
-	    lt_dlsym_const= ;;
-	  *)
-	    lt_dlsym_const=const ;;
-	  esac
-
-	  $ECHO >> "$output_objdir/$my_dlsyms" "\
-extern $lt_dlsym_const lt_dlsymlist
+extern LT_DLSYM_CONST lt_dlsymlist
 lt_${my_prefix}_LTX_preloaded_symbols[];
-$lt_dlsym_const lt_dlsymlist
+LT_DLSYM_CONST lt_dlsymlist
 lt_${my_prefix}_LTX_preloaded_symbols[] =
 {\
   { \"$my_originator\", (void *) 0 },"
@@ -2457,7 +3443,7 @@ lt_${my_prefix}_LTX_preloaded_symbols[] =
 	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
 	    ;;
 	  esac
-	  $ECHO >> "$output_objdir/$my_dlsyms" "\
+	  echo >> "$output_objdir/$my_dlsyms" "\
   {0, (void *) 0}
 };
 
@@ -2500,7 +3486,7 @@ static const void *lt_preloaded_setup() {
 	for arg in $LTCFLAGS; do
 	  case $arg in
 	  -pie | -fpie | -fPIE) ;;
-	  *) symtab_cflags="$symtab_cflags $arg" ;;
+	  *) func_append symtab_cflags " $arg" ;;
 	  esac
 	done
 
@@ -2515,16 +3501,16 @@ static const void *lt_preloaded_setup() {
 	case $host in
 	*cygwin* | *mingw* | *cegcc* )
 	  if test -f "$output_objdir/$my_outputname.def"; then
-	    compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
-	    finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
 	  else
-	    compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
-	    finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
 	  fi
 	  ;;
 	*)
-	  compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
-	  finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+	  compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
 	  ;;
 	esac
 	;;
@@ -2538,8 +3524,8 @@ static const void *lt_preloaded_setup() {
       # really was required.
 
       # Nullify the symbol file.
-      compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
-      finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
     fi
 }
 
@@ -2549,6 +3535,7 @@ static const void *lt_preloaded_setup() {
 # Need a lot of goo to handle *both* DLLs and import libs
 # Has to be a shell function in order to 'eat' the argument
 # that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
 func_win32_libid ()
 {
   $opt_debug
@@ -2559,9 +3546,11 @@ func_win32_libid ()
     win32_libid_type="x86 archive import"
     ;;
   *ar\ archive*) # could be an import, or static
+    # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
     if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
-       $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
-      win32_nmres=`eval $NM -f posix -A $1 |
+       $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+      func_to_tool_file "$1" func_convert_file_msys_to_w32
+      win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
 	$SED -n -e '
 	    1,100{
 		/ I /{
@@ -2590,6 +3579,131 @@ func_win32_libid ()
   $ECHO "$win32_libid_type"
 }
 
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+  $opt_debug
+  sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+  $opt_debug
+  match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+  $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+    $SED '/^Contents of section '"$match_literal"':/{
+      # Place marker at beginning of archive member dllname section
+      s/.*/====MARK====/
+      p
+      d
+    }
+    # These lines can sometimes be longer than 43 characters, but
+    # are always uninteresting
+    /:[	 ]*file format pe[i]\{,1\}-/d
+    /^In archive [^:]*:/d
+    # Ensure marker is printed
+    /^====MARK====/p
+    # Remove all lines with less than 43 characters
+    /^.\{43\}/!d
+    # From remaining lines, remove first 43 characters
+    s/^.\{43\}//' |
+    $SED -n '
+      # Join marker and all lines until next marker into a single line
+      /^====MARK====/ b para
+      H
+      $ b para
+      b
+      :para
+      x
+      s/\n//g
+      # Remove the marker
+      s/^====MARK====//
+      # Remove trailing dots and whitespace
+      s/[\. \t]*$//
+      # Print
+      /./p' |
+    # we now have a list, one entry per line, of the stringified
+    # contents of the appropriate section of all members of the
+    # archive which possess that section. Heuristic: eliminate
+    # all those which have a first or second character that is
+    # a '.' (that is, objdump's representation of an unprintable
+    # character.) This should work for all archives with less than
+    # 0x302f exports -- but will fail for DLLs whose name actually
+    # begins with a literal '.' or a single character followed by
+    # a '.'.
+    #
+    # Of those that remain, print the first one.
+    $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+  test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+  test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+  $opt_debug
+  if func_cygming_gnu_implib_p "$1" ; then
+    # binutils import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+  elif func_cygming_ms_implib_p "$1" ; then
+    # ms-generated import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+  else
+    # unknown
+    sharedlib_from_linklib_result=""
+  fi
+}
 
 
 # func_extract_an_archive dir oldlib
@@ -2598,7 +3712,18 @@ func_extract_an_archive ()
     $opt_debug
     f_ex_an_ar_dir="$1"; shift
     f_ex_an_ar_oldlib="$1"
-    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?'
+    if test "$lock_old_archive_extraction" = yes; then
+      lockfile=$f_ex_an_ar_oldlib.lock
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    fi
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+		   'stat=$?; rm -f "$lockfile"; exit $stat'
+    if test "$lock_old_archive_extraction" = yes; then
+      $opt_dry_run || rm -f "$lockfile"
+    fi
     if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
      :
     else
@@ -2669,7 +3794,7 @@ func_extract_archives ()
 	    darwin_file=
 	    darwin_files=
 	    for darwin_file in $darwin_filelist; do
-	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
 	      $LIPO -create -output "$darwin_file" $darwin_files
 	    done # $darwin_filelist
 	    $RM -rf unfat-$$
@@ -2684,25 +3809,30 @@ func_extract_archives ()
         func_extract_an_archive "$my_xdir" "$my_xabs"
 	;;
       esac
-      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
     done
 
     func_extract_archives_result="$my_oldobjs"
 }
 
 
-
-# func_emit_wrapper_part1 [arg=no]
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
 #
-# Emit the first part of a libtool wrapper script on stdout.
-# For more information, see the description associated with
-# func_emit_wrapper(), below.
-func_emit_wrapper_part1 ()
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
 {
-	func_emit_wrapper_part1_arg1=no
-	if test -n "$1" ; then
-	  func_emit_wrapper_part1_arg1=$1
-	fi
+	func_emit_wrapper_arg1=${1-no}
 
 	$ECHO "\
 #! $SHELL
@@ -2718,7 +3848,6 @@ func_emit_wrapper_part1 ()
 
 # Sed substitution that helps us do robust quoting.  It backslashifies
 # metacharacters that are still active within double-quoted strings.
-Xsed='${SED} -e 1s/^X//'
 sed_quote_subst='$sed_quote_subst'
 
 # Be Bourne compatible
@@ -2749,31 +3878,132 @@ if test \"\$libtool_install_magic\" = \"$magic\"; then
 else
   # When we are sourced in execute mode, \$file and \$ECHO are already set.
   if test \"\$libtool_execute_magic\" != \"$magic\"; then
-    ECHO=\"$qecho\"
-    file=\"\$0\"
-    # Make sure echo works.
-    if test \"X\$1\" = X--no-reexec; then
-      # Discard the --no-reexec flag, and continue.
-      shift
-    elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then
-      # Yippee, \$ECHO works!
-      :
-    else
-      # Restart under the correct shell, and then maybe \$ECHO will work.
-      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
-    fi
-  fi\
+    file=\"\$0\""
+
+    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+    $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+    ECHO=\"$qECHO\"
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=\$0
+  shift
+  for lt_opt
+  do
+    case \"\$lt_opt\" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+        test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+        lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+        cat \"\$lt_dump_D/\$lt_dump_F\"
+        exit 0
+      ;;
+    --lt-*)
+        \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n \"\$lt_option_debug\"; then
+    echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\"
+    lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
 "
-	$ECHO "\
+  case $host in
+  # Backslashes separate directories on plain windows
+  *-*-mingw | *-*-os2* | *-cegcc*)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+    ;;
+
+  *)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+    ;;
+  esac
+  $ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  for lt_wr_arg
+  do
+    case \$lt_wr_arg in
+    --lt-*) ;;
+    *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+    esac
+    shift
+  done
+  func_exec_program_core \${1+\"\$@\"}
+}
+
+  # Parse options
+  func_parse_lt_options \"\$0\" \${1+\"\$@\"}
 
   # Find the directory that this script lives in.
-  thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
   test \"x\$thisdir\" = \"x\$file\" && thisdir=.
 
   # Follow symbolic links until we get to the real thisdir.
-  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
   while test -n \"\$file\"; do
-    destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
 
     # If there was a directory component, then change thisdir.
     if test \"x\$destdir\" != \"x\$file\"; then
@@ -2783,30 +4013,13 @@ else
       esac
     fi
 
-    file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
-    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
   done
-"
-}
-# end: func_emit_wrapper_part1
-
-# func_emit_wrapper_part2 [arg=no]
-#
-# Emit the second part of a libtool wrapper script on stdout.
-# For more information, see the description associated with
-# func_emit_wrapper(), below.
-func_emit_wrapper_part2 ()
-{
-	func_emit_wrapper_part2_arg1=no
-	if test -n "$1" ; then
-	  func_emit_wrapper_part2_arg1=$1
-	fi
-
-	$ECHO "\
 
   # Usually 'no', except on cygwin/mingw when embedded into
   # the cwrapper.
-  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
   if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
     # special case for '.'
     if test \"\$thisdir\" = \".\"; then
@@ -2814,7 +4027,7 @@ func_emit_wrapper_part2 ()
     fi
     # remove .libs from thisdir
     case \"\$thisdir\" in
-    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
     $objdir )   thisdir=. ;;
     esac
   fi
@@ -2869,6 +4082,18 @@ func_emit_wrapper_part2 ()
 
   if test -f \"\$progdir/\$program\"; then"
 
+	# fixup the dll searchpath if we need to.
+	#
+	# Fix the DLL searchpath if we need to.  Do this before prepending
+	# to shlibpath, because on Windows, both are PATH and uninstalled
+	# libraries must come first.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
 	# Export our shlibpath_var if we have one.
 	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
 	  $ECHO "\
@@ -2877,254 +4102,29 @@ func_emit_wrapper_part2 ()
 
     # Some systems cannot cope with colon-terminated $shlibpath_var
     # The second colon is a workaround for a bug in BeOS R4 sed
-    $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
 
     export $shlibpath_var
 "
 	fi
 
-	# fixup the dll searchpath if we need to.
-	if test -n "$dllsearchpath"; then
-	  $ECHO "\
-    # Add the dll search path components to the executable PATH
-    PATH=$dllsearchpath:\$PATH
-"
-	fi
-
 	$ECHO "\
     if test \"\$libtool_execute_magic\" != \"$magic\"; then
       # Run the actual program with our arguments.
-"
-	case $host in
-	# Backslashes separate directories on plain windows
-	*-*-mingw | *-*-os2* | *-cegcc*)
-	  $ECHO "\
-      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
-"
-	  ;;
-
-	*)
-	  $ECHO "\
-      exec \"\$progdir/\$program\" \${1+\"\$@\"}
-"
-	  ;;
-	esac
-	$ECHO "\
-      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
-      exit 1
+      func_exec_program \${1+\"\$@\"}
     fi
   else
     # The program doesn't exist.
     \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
     \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
-    $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
     exit 1
   fi
 fi\
 "
 }
-# end: func_emit_wrapper_part2
-
-
-# func_emit_wrapper [arg=no]
-#
-# Emit a libtool wrapper script on stdout.
-# Don't directly open a file because we may want to
-# incorporate the script contents within a cygwin/mingw
-# wrapper executable.  Must ONLY be called from within
-# func_mode_link because it depends on a number of variables
-# set therein.
-#
-# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
-# variable will take.  If 'yes', then the emitted script
-# will assume that the directory in which it is stored is
-# the $objdir directory.  This is a cygwin/mingw-specific
-# behavior.
-func_emit_wrapper ()
-{
-	func_emit_wrapper_arg1=no
-	if test -n "$1" ; then
-	  func_emit_wrapper_arg1=$1
-	fi
-
-	# split this up so that func_emit_cwrapperexe_src
-	# can call each part independently.
-	func_emit_wrapper_part1 "${func_emit_wrapper_arg1}"
-	func_emit_wrapper_part2 "${func_emit_wrapper_arg1}"
-}
 
 
-# func_to_host_path arg
-#
-# Convert paths to host format when used with build tools.
-# Intended for use with "native" mingw (where libtool itself
-# is running under the msys shell), or in the following cross-
-# build environments:
-#    $build          $host
-#    mingw (msys)    mingw  [e.g. native]
-#    cygwin          mingw
-#    *nix + wine     mingw
-# where wine is equipped with the `winepath' executable.
-# In the native mingw case, the (msys) shell automatically
-# converts paths for any non-msys applications it launches,
-# but that facility isn't available from inside the cwrapper.
-# Similar accommodations are necessary for $host mingw and
-# $build cygwin.  Calling this function does no harm for other
-# $host/$build combinations not listed above.
-#
-# ARG is the path (on $build) that should be converted to
-# the proper representation for $host. The result is stored
-# in $func_to_host_path_result.
-func_to_host_path ()
-{
-  func_to_host_path_result="$1"
-  if test -n "$1" ; then
-    case $host in
-      *mingw* )
-        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
-        case $build in
-          *mingw* ) # actually, msys
-            # awkward: cmd appends spaces to result
-            lt_sed_strip_trailing_spaces="s/[ ]*\$//"
-            func_to_host_path_tmp1=`( cmd //c echo "$1" |\
-              $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
-            func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
-              $SED -e "$lt_sed_naive_backslashify"`
-            ;;
-          *cygwin* )
-            func_to_host_path_tmp1=`cygpath -w "$1"`
-            func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
-              $SED -e "$lt_sed_naive_backslashify"`
-            ;;
-          * )
-            # Unfortunately, winepath does not exit with a non-zero
-            # error code, so we are forced to check the contents of
-            # stdout. On the other hand, if the command is not
-            # found, the shell will set an exit code of 127 and print
-            # *an error message* to stdout. So we must check for both
-            # error code of zero AND non-empty stdout, which explains
-            # the odd construction:
-            func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
-            if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
-              func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
-                $SED -e "$lt_sed_naive_backslashify"`
-            else
-              # Allow warning below.
-              func_to_host_path_result=""
-            fi
-            ;;
-        esac
-        if test -z "$func_to_host_path_result" ; then
-          func_error "Could not determine host path corresponding to"
-          func_error "  '$1'"
-          func_error "Continuing, but uninstalled executables may not work."
-          # Fallback:
-          func_to_host_path_result="$1"
-        fi
-        ;;
-    esac
-  fi
-}
-# end: func_to_host_path
-
-# func_to_host_pathlist arg
-#
-# Convert pathlists to host format when used with build tools.
-# See func_to_host_path(), above. This function supports the
-# following $build/$host combinations (but does no harm for
-# combinations not listed here):
-#    $build          $host
-#    mingw (msys)    mingw  [e.g. native]
-#    cygwin          mingw
-#    *nix + wine     mingw
-#
-# Path separators are also converted from $build format to
-# $host format. If ARG begins or ends with a path separator
-# character, it is preserved (but converted to $host format)
-# on output.
-#
-# ARG is a pathlist (on $build) that should be converted to
-# the proper representation on $host. The result is stored
-# in $func_to_host_pathlist_result.
-func_to_host_pathlist ()
-{
-  func_to_host_pathlist_result="$1"
-  if test -n "$1" ; then
-    case $host in
-      *mingw* )
-        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
-        # Remove leading and trailing path separator characters from
-        # ARG. msys behavior is inconsistent here, cygpath turns them
-        # into '.;' and ';.', and winepath ignores them completely.
-        func_to_host_pathlist_tmp2="$1"
-        # Once set for this call, this variable should not be
-        # reassigned. It is used in tha fallback case.
-        func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\
-          $SED -e 's|^:*||' -e 's|:*$||'`
-        case $build in
-          *mingw* ) # Actually, msys.
-            # Awkward: cmd appends spaces to result.
-            lt_sed_strip_trailing_spaces="s/[ ]*\$//"
-            func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\
-              $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
-            func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
-              $SED -e "$lt_sed_naive_backslashify"`
-            ;;
-          *cygwin* )
-            func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"`
-            func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
-              $SED -e "$lt_sed_naive_backslashify"`
-            ;;
-          * )
-            # unfortunately, winepath doesn't convert pathlists
-            func_to_host_pathlist_result=""
-            func_to_host_pathlist_oldIFS=$IFS
-            IFS=:
-            for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
-              IFS=$func_to_host_pathlist_oldIFS
-              if test -n "$func_to_host_pathlist_f" ; then
-                func_to_host_path "$func_to_host_pathlist_f"
-                if test -n "$func_to_host_path_result" ; then
-                  if test -z "$func_to_host_pathlist_result" ; then
-                    func_to_host_pathlist_result="$func_to_host_path_result"
-                  else
-                    func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result"
-                  fi
-                fi
-              fi
-              IFS=:
-            done
-            IFS=$func_to_host_pathlist_oldIFS
-            ;;
-        esac
-        if test -z "$func_to_host_pathlist_result" ; then
-          func_error "Could not determine the host path(s) corresponding to"
-          func_error "  '$1'"
-          func_error "Continuing, but uninstalled executables may not work."
-          # Fallback. This may break if $1 contains DOS-style drive
-          # specifications. The fix is not to complicate the expression
-          # below, but for the user to provide a working wine installation
-          # with winepath so that path translation in the cross-to-mingw
-          # case works properly.
-          lt_replace_pathsep_nix_to_dos="s|:|;|g"
-          func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
-            $SED -e "$lt_replace_pathsep_nix_to_dos"`
-        fi
-        # Now, add the leading and trailing path separators back
-        case "$1" in
-          :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
-            ;;
-        esac
-        case "$1" in
-          *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;"
-            ;;
-        esac
-        ;;
-    esac
-  fi
-}
-# end: func_to_host_pathlist
-
 # func_emit_cwrapperexe_src
 # emit the source code for a wrapper executable on stdout
 # Must ONLY be called from within func_mode_link because
@@ -3141,41 +4141,71 @@ func_emit_cwrapperexe_src ()
 
    This wrapper executable should never be moved out of the build directory.
    If it is, it will not operate correctly.
-
-   Currently, it simply execs the wrapper *script* "$SHELL $output",
-   but could eventually absorb all of the scripts functionality and
-   exec $objdir/$outputname directly.
 */
 EOF
 	    cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #ifdef _MSC_VER
 # include <direct.h>
 # include <process.h>
 # include <io.h>
-# define setmode _setmode
 #else
 # include <unistd.h>
 # include <stdint.h>
 # ifdef __CYGWIN__
 #  include <io.h>
-#  define HAVE_SETENV
-#  ifdef __STRICT_ANSI__
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* declarations of non-ANSI functions */
+#if defined(__MINGW32__)
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined(__CYGWIN__)
+# ifdef __STRICT_ANSI__
 char *realpath (const char *, char *);
 int putenv (char *);
 int setenv (const char *, const char *, int);
-#  endif
 # endif
+/* #elif defined (other platforms) ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined(_MSC_VER)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+# define S_IXUSR _S_IEXEC
+# ifndef _INTPTR_T_DEFINED
+#  define _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#elif defined(__MINGW32__)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+#elif defined(__CYGWIN__)
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined (other platforms) ... */
 #endif
-#include <malloc.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
 
 #if defined(PATH_MAX)
 # define LT_PATHMAX PATH_MAX
@@ -3192,14 +4222,7 @@ int setenv (const char *, const char *, int);
 # define S_IXGRP 0
 #endif
 
-#ifdef _MSC_VER
-# define S_IXUSR _S_IEXEC
-# define stat _stat
-# ifndef _INTPTR_T_DEFINED
-#  define intptr_t int
-# endif
-#endif
-
+/* path handling portability macros */
 #ifndef DIR_SEPARATOR
 # define DIR_SEPARATOR '/'
 # define PATH_SEPARATOR ':'
@@ -3230,10 +4253,6 @@ int setenv (const char *, const char *, int);
 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
 #endif /* PATH_SEPARATOR_2 */
 
-#ifdef __CYGWIN__
-# define FOPEN_WB "wb"
-#endif
-
 #ifndef FOPEN_WB
 # define FOPEN_WB "w"
 #endif
@@ -3246,22 +4265,13 @@ int setenv (const char *, const char *, int);
   if (stale) { free ((void *) stale); stale = 0; } \
 } while (0)
 
-#undef LTWRAPPER_DEBUGPRINTF
-#if defined DEBUGWRAPPER
-# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
-static void
-ltwrapper_debugprintf (const char *fmt, ...)
-{
-    va_list args;
-    va_start (args, fmt);
-    (void) vfprintf (stderr, fmt, args);
-    va_end (args);
-}
+#if defined(LT_DEBUGWRAPPER)
+static int lt_debug = 1;
 #else
-# define LTWRAPPER_DEBUGPRINTF(args)
+static int lt_debug = 0;
 #endif
 
-const char *program_name = NULL;
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
 
 void *xmalloc (size_t num);
 char *xstrdup (const char *string);
@@ -3271,41 +4281,27 @@ char *chase_symlinks (const char *pathspec);
 int make_executable (const char *path);
 int check_executable (const char *path);
 char *strendzap (char *str, const char *pat);
-void lt_fatal (const char *message, ...);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
 void lt_setenv (const char *name, const char *value);
 char *lt_extend_str (const char *orig_value, const char *add, int to_end);
-void lt_opt_process_env_set (const char *arg);
-void lt_opt_process_env_prepend (const char *arg);
-void lt_opt_process_env_append (const char *arg);
-int lt_split_name_value (const char *arg, char** name, char** value);
 void lt_update_exe_path (const char *name, const char *value);
 void lt_update_lib_path (const char *name, const char *value);
-
-static const char *script_text_part1 =
-EOF
-
-	    func_emit_wrapper_part1 yes |
-	        $SED -e 's/\([\\"]\)/\\\1/g' \
-	             -e 's/^/  "/' -e 's/$/\\n"/'
-	    echo ";"
-	    cat <<EOF
-
-static const char *script_text_part2 =
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
 EOF
-	    func_emit_wrapper_part2 yes |
-	        $SED -e 's/\([\\"]\)/\\\1/g' \
-	             -e 's/^/  "/' -e 's/$/\\n"/'
-	    echo ";"
 
 	    cat <<EOF
-const char * MAGIC_EXE = "$magic_exe";
+volatile const char * MAGIC_EXE = "$magic_exe";
 const char * LIB_PATH_VARNAME = "$shlibpath_var";
 EOF
 
 	    if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
-              func_to_host_pathlist "$temp_rpath"
+              func_to_host_path "$temp_rpath"
 	      cat <<EOF
-const char * LIB_PATH_VALUE   = "$func_to_host_pathlist_result";
+const char * LIB_PATH_VALUE   = "$func_to_host_path_result";
 EOF
 	    else
 	      cat <<"EOF"
@@ -3314,10 +4310,10 @@ EOF
 	    fi
 
 	    if test -n "$dllsearchpath"; then
-              func_to_host_pathlist "$dllsearchpath:"
+              func_to_host_path "$dllsearchpath:"
 	      cat <<EOF
 const char * EXE_PATH_VARNAME = "PATH";
-const char * EXE_PATH_VALUE   = "$func_to_host_pathlist_result";
+const char * EXE_PATH_VALUE   = "$func_to_host_path_result";
 EOF
 	    else
 	      cat <<"EOF"
@@ -3340,24 +4336,10 @@ EOF
 	    cat <<"EOF"
 
 #define LTWRAPPER_OPTION_PREFIX         "--lt-"
-#define LTWRAPPER_OPTION_PREFIX_LENGTH  5
 
-static const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;
 static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
-
 static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
-
-static const size_t env_set_opt_len     = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
-static const char *env_set_opt          = LTWRAPPER_OPTION_PREFIX "env-set";
-  /* argument is putenv-style "foo=bar", value of foo is set to bar */
-
-static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
-static const char *env_prepend_opt      = LTWRAPPER_OPTION_PREFIX "env-prepend";
-  /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
-
-static const size_t env_append_opt_len  = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
-static const char *env_append_opt       = LTWRAPPER_OPTION_PREFIX "env-append";
-  /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
+static const char *debug_opt            = LTWRAPPER_OPTION_PREFIX "debug";
 
 int
 main (int argc, char *argv[])
@@ -3374,10 +4356,13 @@ main (int argc, char *argv[])
   int i;
 
   program_name = (char *) xstrdup (base_name (argv[0]));
-  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
-  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+  newargz = XMALLOC (char *, argc + 1);
 
-  /* very simple arg parsing; don't want to rely on getopt */
+  /* very simple arg parsing; don't want to rely on getopt
+   * also, copy all non cwrapper options to newargz, except
+   * argz[0], which is handled differently
+   */
+  newargc=0;
   for (i = 1; i < argc; i++)
     {
       if (strcmp (argv[i], dumpscript_opt) == 0)
@@ -3391,25 +4376,57 @@ EOF
 	      esac
 
 	    cat <<"EOF"
-	  printf ("%s", script_text_part1);
-	  printf ("%s", script_text_part2);
+	  lt_dump_script (stdout);
 	  return 0;
 	}
+      if (strcmp (argv[i], debug_opt) == 0)
+	{
+          lt_debug = 1;
+          continue;
+	}
+      if (strcmp (argv[i], ltwrapper_option_prefix) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal (__FILE__, __LINE__,
+		    "unrecognized %s option: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
     }
+  newargz[++newargc] = NULL;
+
+EOF
+	    cat <<EOF
+  /* The GNU banner must be the first non-error debug message */
+  lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n");
+EOF
+	    cat <<"EOF"
+  lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
 
-  newargz = XMALLOC (char *, argc + 1);
   tmp_pathspec = find_executable (argv[0]);
   if (tmp_pathspec == NULL)
-    lt_fatal ("Couldn't find %s", argv[0]);
-  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
-			  tmp_pathspec));
+    lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (before symlink chase) at: %s\n",
+		  tmp_pathspec);
 
   actual_cwrapper_path = chase_symlinks (tmp_pathspec);
-  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
-			  actual_cwrapper_path));
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (after symlink chase) at: %s\n",
+		  actual_cwrapper_path);
   XFREE (tmp_pathspec);
 
-  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+  actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
   strendzap (actual_cwrapper_path, actual_cwrapper_name);
 
   /* wrapper name transforms */
@@ -3427,8 +4444,9 @@ EOF
   target_name = tmp_pathspec;
   tmp_pathspec = 0;
 
-  LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
-			  target_name));
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(main) libtool target name: %s\n",
+		  target_name);
 EOF
 
 	    cat <<EOF
@@ -3478,80 +4496,19 @@ EOF
 
   lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
   lt_setenv ("DUALCASE", "1");  /* for MSK sh */
-  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+  /* Update the DLL searchpath.  EXE_PATH_VALUE ($dllsearchpath) must
+     be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
+     because on Windows, both *_VARNAMEs are PATH but uninstalled
+     libraries must come first. */
   lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
 
-  newargc=0;
-  for (i = 1; i < argc; i++)
-    {
-      if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
-        {
-          if (argv[i][env_set_opt_len] == '=')
-            {
-              const char *p = argv[i] + env_set_opt_len + 1;
-              lt_opt_process_env_set (p);
-            }
-          else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
-            {
-              lt_opt_process_env_set (argv[++i]); /* don't copy */
-            }
-          else
-            lt_fatal ("%s missing required argument", env_set_opt);
-          continue;
-        }
-      if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
-        {
-          if (argv[i][env_prepend_opt_len] == '=')
-            {
-              const char *p = argv[i] + env_prepend_opt_len + 1;
-              lt_opt_process_env_prepend (p);
-            }
-          else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
-            {
-              lt_opt_process_env_prepend (argv[++i]); /* don't copy */
-            }
-          else
-            lt_fatal ("%s missing required argument", env_prepend_opt);
-          continue;
-        }
-      if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
-        {
-          if (argv[i][env_append_opt_len] == '=')
-            {
-              const char *p = argv[i] + env_append_opt_len + 1;
-              lt_opt_process_env_append (p);
-            }
-          else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
-            {
-              lt_opt_process_env_append (argv[++i]); /* don't copy */
-            }
-          else
-            lt_fatal ("%s missing required argument", env_append_opt);
-          continue;
-        }
-      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
-        {
-          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
-             namespace, but it is not one of the ones we know about and
-             have already dealt with, above (inluding dump-script), then
-             report an error. Otherwise, targets might begin to believe
-             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
-             namespace. The first time any user complains about this, we'll
-             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
-             or a configure.ac-settable value.
-           */
-          lt_fatal ("Unrecognized option in %s namespace: '%s'",
-                    ltwrapper_option_prefix, argv[i]);
-        }
-      /* otherwise ... */
-      newargz[++newargc] = xstrdup (argv[i]);
-    }
-  newargz[++newargc] = NULL;
-
-  LTWRAPPER_DEBUGPRINTF     (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+  lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
+		  nonnull (lt_argv_zero));
   for (i = 0; i < newargc; i++)
     {
-      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+      lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
+		      i, nonnull (newargz[i]));
     }
 
 EOF
@@ -3560,11 +4517,14 @@ EOF
 	      mingw*)
 		cat <<"EOF"
   /* execv doesn't actually work on mingw as expected on unix */
+  newargz = prepare_spawn (newargz);
   rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
   if (rval == -1)
     {
       /* failed to start process */
-      LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
+      lt_debugprintf (__FILE__, __LINE__,
+		      "(main) failed to launch target \"%s\": %s\n",
+		      lt_argv_zero, nonnull (strerror (errno)));
       return 127;
     }
   return rval;
@@ -3586,7 +4546,7 @@ xmalloc (size_t num)
 {
   void *p = (void *) malloc (num);
   if (!p)
-    lt_fatal ("Memory exhausted");
+    lt_fatal (__FILE__, __LINE__, "memory exhausted");
 
   return p;
 }
@@ -3620,8 +4580,8 @@ check_executable (const char *path)
 {
   struct stat st;
 
-  LTWRAPPER_DEBUGPRINTF (("(check_executable)  : %s\n",
-			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
+                  nonempty (path));
   if ((!path) || (!*path))
     return 0;
 
@@ -3638,8 +4598,8 @@ make_executable (const char *path)
   int rval = 0;
   struct stat st;
 
-  LTWRAPPER_DEBUGPRINTF (("(make_executable)   : %s\n",
-			  path ? (*path ? path : "EMPTY!") : "NULL!"));
+  lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+                  nonempty (path));
   if ((!path) || (!*path))
     return 0;
 
@@ -3665,8 +4625,8 @@ find_executable (const char *wrapper)
   int tmp_len;
   char *concat_name;
 
-  LTWRAPPER_DEBUGPRINTF (("(find_executable)   : %s\n",
-			  wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+  lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+                  nonempty (wrapper));
 
   if ((wrapper == NULL) || (*wrapper == '\0'))
     return NULL;
@@ -3719,7 +4679,8 @@ find_executable (const char *wrapper)
 		{
 		  /* empty path: current directory */
 		  if (getcwd (tmp, LT_PATHMAX) == NULL)
-		    lt_fatal ("getcwd failed");
+		    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+                              nonnull (strerror (errno)));
 		  tmp_len = strlen (tmp);
 		  concat_name =
 		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
@@ -3744,7 +4705,8 @@ find_executable (const char *wrapper)
     }
   /* Relative path | not found in path: prepend cwd */
   if (getcwd (tmp, LT_PATHMAX) == NULL)
-    lt_fatal ("getcwd failed");
+    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+              nonnull (strerror (errno)));
   tmp_len = strlen (tmp);
   concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
   memcpy (concat_name, tmp, tmp_len);
@@ -3770,8 +4732,9 @@ chase_symlinks (const char *pathspec)
   int has_symlinks = 0;
   while (strlen (tmp_pathspec) && !has_symlinks)
     {
-      LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
-			      tmp_pathspec));
+      lt_debugprintf (__FILE__, __LINE__,
+		      "checking path component for symlinks: %s\n",
+		      tmp_pathspec);
       if (lstat (tmp_pathspec, &s) == 0)
 	{
 	  if (S_ISLNK (s.st_mode) != 0)
@@ -3793,8 +4756,9 @@ chase_symlinks (const char *pathspec)
 	}
       else
 	{
-	  char *errstr = strerror (errno);
-	  lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+	  lt_fatal (__FILE__, __LINE__,
+		    "error accessing file \"%s\": %s",
+		    tmp_pathspec, nonnull (strerror (errno)));
 	}
     }
   XFREE (tmp_pathspec);
@@ -3807,7 +4771,8 @@ chase_symlinks (const char *pathspec)
   tmp_pathspec = realpath (pathspec, buf);
   if (tmp_pathspec == 0)
     {
-      lt_fatal ("Could not follow symlinks for %s", pathspec);
+      lt_fatal (__FILE__, __LINE__,
+		"could not follow symlinks for %s", pathspec);
     }
   return xstrdup (tmp_pathspec);
 #endif
@@ -3833,11 +4798,25 @@ strendzap (char *str, const char *pat)
   return str;
 }
 
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+  va_list args;
+  if (lt_debug)
+    {
+      (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+      va_start (args, fmt);
+      (void) vfprintf (stderr, fmt, args);
+      va_end (args);
+    }
+}
+
 static void
-lt_error_core (int exit_status, const char *mode,
+lt_error_core (int exit_status, const char *file,
+	       int line, const char *mode,
 	       const char *message, va_list ap)
 {
-  fprintf (stderr, "%s: %s: ", program_name, mode);
+  fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
   vfprintf (stderr, message, ap);
   fprintf (stderr, ".\n");
 
@@ -3846,20 +4825,32 @@ lt_error_core (int exit_status, const char *mode,
 }
 
 void
-lt_fatal (const char *message, ...)
+lt_fatal (const char *file, int line, const char *message, ...)
 {
   va_list ap;
   va_start (ap, message);
-  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
   va_end (ap);
 }
 
+static const char *
+nonnull (const char *s)
+{
+  return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+  return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
 void
 lt_setenv (const char *name, const char *value)
 {
-  LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
-                          (name ? name : "<NULL>"),
-                          (value ? value : "<NULL>")));
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_setenv) setting '%s' to '%s'\n",
+                  nonnull (name), nonnull (value));
   {
 #ifdef HAVE_SETENV
     /* always make a copy, for consistency with !HAVE_SETENV */
@@ -3904,95 +4895,12 @@ lt_extend_str (const char *orig_value, const char *add, int to_end)
   return new_value;
 }
 
-int
-lt_split_name_value (const char *arg, char** name, char** value)
-{
-  const char *p;
-  int len;
-  if (!arg || !*arg)
-    return 1;
-
-  p = strchr (arg, (int)'=');
-
-  if (!p)
-    return 1;
-
-  *value = xstrdup (++p);
-
-  len = strlen (arg) - strlen (*value);
-  *name = XMALLOC (char, len);
-  strncpy (*name, arg, len-1);
-  (*name)[len - 1] = '\0';
-
-  return 0;
-}
-
-void
-lt_opt_process_env_set (const char *arg)
-{
-  char *name = NULL;
-  char *value = NULL;
-
-  if (lt_split_name_value (arg, &name, &value) != 0)
-    {
-      XFREE (name);
-      XFREE (value);
-      lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg);
-    }
-
-  lt_setenv (name, value);
-  XFREE (name);
-  XFREE (value);
-}
-
-void
-lt_opt_process_env_prepend (const char *arg)
-{
-  char *name = NULL;
-  char *value = NULL;
-  char *new_value = NULL;
-
-  if (lt_split_name_value (arg, &name, &value) != 0)
-    {
-      XFREE (name);
-      XFREE (value);
-      lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg);
-    }
-
-  new_value = lt_extend_str (getenv (name), value, 0);
-  lt_setenv (name, new_value);
-  XFREE (new_value);
-  XFREE (name);
-  XFREE (value);
-}
-
-void
-lt_opt_process_env_append (const char *arg)
-{
-  char *name = NULL;
-  char *value = NULL;
-  char *new_value = NULL;
-
-  if (lt_split_name_value (arg, &name, &value) != 0)
-    {
-      XFREE (name);
-      XFREE (value);
-      lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg);
-    }
-
-  new_value = lt_extend_str (getenv (name), value, 1);
-  lt_setenv (name, new_value);
-  XFREE (new_value);
-  XFREE (name);
-  XFREE (value);
-}
-
 void
 lt_update_exe_path (const char *name, const char *value)
 {
-  LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
-                          (name ? name : "<NULL>"),
-                          (value ? value : "<NULL>")));
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
 
   if (name && *name && value && *value)
     {
@@ -4011,9 +4919,9 @@ lt_update_exe_path (const char *name, const char *value)
 void
 lt_update_lib_path (const char *name, const char *value)
 {
-  LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
-                          (name ? name : "<NULL>"),
-                          (value ? value : "<NULL>")));
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
 
   if (name && *name && value && *value)
     {
@@ -4023,11 +4931,152 @@ lt_update_lib_path (const char *name, const char *value)
     }
 }
 
+EOF
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XMALLOC (char *, argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+	new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+	{
+	  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+	  size_t length;
+	  unsigned int backslashes;
+	  const char *s;
+	  char *quoted_string;
+	  char *p;
+
+	  length = 0;
+	  backslashes = 0;
+	  if (quote_around)
+	    length++;
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		length += backslashes + 1;
+	      length++;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    length += backslashes + 1;
+
+	  quoted_string = XMALLOC (char, length + 1);
+
+	  p = quoted_string;
+	  backslashes = 0;
+	  if (quote_around)
+	    *p++ = '"';
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		{
+		  unsigned int j;
+		  for (j = backslashes + 1; j > 0; j--)
+		    *p++ = '\\';
+		}
+	      *p++ = c;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    {
+	      unsigned int j;
+	      for (j = backslashes; j > 0; j--)
+		*p++ = '\\';
+	      *p++ = '"';
+	    }
+	  *p = '\0';
+
+	  new_argv[i] = quoted_string;
+	}
+      else
+	new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+EOF
+		;;
+	    esac
+
+            cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+	    func_emit_wrapper yes |
+              $SED -e 's/\([\\"]\)/\\\1/g' \
+	           -e 's/^/  fputs ("/' -e 's/$/\\n", f);/'
 
+            cat <<"EOF"
+}
 EOF
 }
 # end: func_emit_cwrapperexe_src
 
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+    $opt_debug
+    case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+    *import*) : ;;
+    *) false ;;
+    esac
+}
+
 # func_mode_link arg...
 func_mode_link ()
 {
@@ -4072,6 +5121,7 @@ func_mode_link ()
     new_inherited_linker_flags=
 
     avoid_version=no
+    bindir=
     dlfiles=
     dlprefiles=
     dlself=no
@@ -4164,6 +5214,11 @@ func_mode_link ()
 	esac
 
 	case $prev in
+	bindir)
+	  bindir="$arg"
+	  prev=
+	  continue
+	  ;;
 	dlfiles|dlprefiles)
 	  if test "$preload" = no; then
 	    # Add the symbol object into the linking commands.
@@ -4195,9 +5250,9 @@ func_mode_link ()
 	    ;;
 	  *)
 	    if test "$prev" = dlfiles; then
-	      dlfiles="$dlfiles $arg"
+	      func_append dlfiles " $arg"
 	    else
-	      dlprefiles="$dlprefiles $arg"
+	      func_append dlprefiles " $arg"
 	    fi
 	    prev=
 	    continue
@@ -4221,7 +5276,7 @@ func_mode_link ()
 	    *-*-darwin*)
 	      case "$deplibs " in
 		*" $qarg.ltframework "*) ;;
-		*) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+		*) func_append deplibs " $qarg.ltframework" # this is fixed later
 		   ;;
 	      esac
 	      ;;
@@ -4240,7 +5295,7 @@ func_mode_link ()
 	    moreargs=
 	    for fil in `cat "$save_arg"`
 	    do
-#	      moreargs="$moreargs $fil"
+#	      func_append moreargs " $fil"
 	      arg=$fil
 	      # A libtool-controlled object.
 
@@ -4269,7 +5324,7 @@ func_mode_link ()
 
 		  if test "$prev" = dlfiles; then
 		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-		      dlfiles="$dlfiles $pic_object"
+		      func_append dlfiles " $pic_object"
 		      prev=
 		      continue
 		    else
@@ -4281,7 +5336,7 @@ func_mode_link ()
 		  # CHECK ME:  I think I busted this.  -Ossama
 		  if test "$prev" = dlprefiles; then
 		    # Preload the old-style object.
-		    dlprefiles="$dlprefiles $pic_object"
+		    func_append dlprefiles " $pic_object"
 		    prev=
 		  fi
 
@@ -4351,12 +5406,12 @@ func_mode_link ()
 	  if test "$prev" = rpath; then
 	    case "$rpath " in
 	    *" $arg "*) ;;
-	    *) rpath="$rpath $arg" ;;
+	    *) func_append rpath " $arg" ;;
 	    esac
 	  else
 	    case "$xrpath " in
 	    *" $arg "*) ;;
-	    *) xrpath="$xrpath $arg" ;;
+	    *) func_append xrpath " $arg" ;;
 	    esac
 	  fi
 	  prev=
@@ -4368,28 +5423,28 @@ func_mode_link ()
 	  continue
 	  ;;
 	weak)
-	  weak_libs="$weak_libs $arg"
+	  func_append weak_libs " $arg"
 	  prev=
 	  continue
 	  ;;
 	xcclinker)
-	  linker_flags="$linker_flags $qarg"
-	  compiler_flags="$compiler_flags $qarg"
+	  func_append linker_flags " $qarg"
+	  func_append compiler_flags " $qarg"
 	  prev=
 	  func_append compile_command " $qarg"
 	  func_append finalize_command " $qarg"
 	  continue
 	  ;;
 	xcompiler)
-	  compiler_flags="$compiler_flags $qarg"
+	  func_append compiler_flags " $qarg"
 	  prev=
 	  func_append compile_command " $qarg"
 	  func_append finalize_command " $qarg"
 	  continue
 	  ;;
 	xlinker)
-	  linker_flags="$linker_flags $qarg"
-	  compiler_flags="$compiler_flags $wl$qarg"
+	  func_append linker_flags " $qarg"
+	  func_append compiler_flags " $wl$qarg"
 	  prev=
 	  func_append compile_command " $wl$qarg"
 	  func_append finalize_command " $wl$qarg"
@@ -4425,6 +5480,11 @@ func_mode_link ()
 	continue
 	;;
 
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
       -dlopen)
 	prev=dlfiles
 	continue
@@ -4475,15 +5535,16 @@ func_mode_link ()
 	;;
 
       -L*)
-	func_stripname '-L' '' "$arg"
-	dir=$func_stripname_result
-	if test -z "$dir"; then
+	func_stripname "-L" '' "$arg"
+	if test -z "$func_stripname_result"; then
 	  if test "$#" -gt 0; then
 	    func_fatal_error "require no space between \`-L' and \`$1'"
 	  else
 	    func_fatal_error "need path for \`-L' option"
 	  fi
 	fi
+	func_resolve_sysroot "$func_stripname_result"
+	dir=$func_resolve_sysroot_result
 	# We need an absolute path.
 	case $dir in
 	[\\/]* | [A-Za-z]:[\\/]*) ;;
@@ -4495,24 +5556,30 @@ func_mode_link ()
 	  ;;
 	esac
 	case "$deplibs " in
-	*" -L$dir "*) ;;
+	*" -L$dir "* | *" $arg "*)
+	  # Will only happen for absolute or sysroot arguments
+	  ;;
 	*)
-	  deplibs="$deplibs -L$dir"
-	  lib_search_path="$lib_search_path $dir"
+	  # Preserve sysroot, but never include relative directories
+	  case $dir in
+	    [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
+	    *) func_append deplibs " -L$dir" ;;
+	  esac
+	  func_append lib_search_path " $dir"
 	  ;;
 	esac
 	case $host in
 	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
-	  testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+	  testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
 	  case :$dllsearchpath: in
 	  *":$dir:"*) ;;
 	  ::) dllsearchpath=$dir;;
-	  *) dllsearchpath="$dllsearchpath:$dir";;
+	  *) func_append dllsearchpath ":$dir";;
 	  esac
 	  case :$dllsearchpath: in
 	  *":$testbindir:"*) ;;
 	  ::) dllsearchpath=$testbindir;;
-	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  *) func_append dllsearchpath ":$testbindir";;
 	  esac
 	  ;;
 	esac
@@ -4522,7 +5589,7 @@ func_mode_link ()
       -l*)
 	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
 	  case $host in
-	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*)
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
 	    # These systems don't actually have a C or math library (as such)
 	    continue
 	    ;;
@@ -4536,7 +5603,7 @@ func_mode_link ()
 	    ;;
 	  *-*-rhapsody* | *-*-darwin1.[012])
 	    # Rhapsody C and math libraries are in the System framework
-	    deplibs="$deplibs System.ltframework"
+	    func_append deplibs " System.ltframework"
 	    continue
 	    ;;
 	  *-*-sco3.2v5* | *-*-sco5v6*)
@@ -4556,7 +5623,7 @@ func_mode_link ()
 	   ;;
 	 esac
 	fi
-	deplibs="$deplibs $arg"
+	func_append deplibs " $arg"
 	continue
 	;;
 
@@ -4568,8 +5635,8 @@ func_mode_link ()
       # Tru64 UNIX uses -model [arg] to determine the layout of C++
       # classes, name mangling, and exception handling.
       # Darwin uses the -arch flag to determine output architecture.
-      -model|-arch|-isysroot)
-	compiler_flags="$compiler_flags $arg"
+      -model|-arch|-isysroot|--sysroot)
+	func_append compiler_flags " $arg"
 	func_append compile_command " $arg"
 	func_append finalize_command " $arg"
 	prev=xcompiler
@@ -4577,12 +5644,12 @@ func_mode_link ()
 	;;
 
       -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
-	compiler_flags="$compiler_flags $arg"
+	func_append compiler_flags " $arg"
 	func_append compile_command " $arg"
 	func_append finalize_command " $arg"
 	case "$new_inherited_linker_flags " in
 	    *" $arg "*) ;;
-	    * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
+	    * ) func_append new_inherited_linker_flags " $arg" ;;
 	esac
 	continue
 	;;
@@ -4649,13 +5716,17 @@ func_mode_link ()
 	# We need an absolute path.
 	case $dir in
 	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	=*)
+	  func_stripname '=' '' "$dir"
+	  dir=$lt_sysroot$func_stripname_result
+	  ;;
 	*)
 	  func_fatal_error "only absolute run-paths are allowed"
 	  ;;
 	esac
 	case "$xrpath " in
 	*" $dir "*) ;;
-	*) xrpath="$xrpath $dir" ;;
+	*) func_append xrpath " $dir" ;;
 	esac
 	continue
 	;;
@@ -4708,8 +5779,8 @@ func_mode_link ()
 	for flag in $args; do
 	  IFS="$save_ifs"
           func_quote_for_eval "$flag"
-	  arg="$arg $wl$func_quote_for_eval_result"
-	  compiler_flags="$compiler_flags $func_quote_for_eval_result"
+	  func_append arg " $func_quote_for_eval_result"
+	  func_append compiler_flags " $func_quote_for_eval_result"
 	done
 	IFS="$save_ifs"
 	func_stripname ' ' '' "$arg"
@@ -4724,9 +5795,9 @@ func_mode_link ()
 	for flag in $args; do
 	  IFS="$save_ifs"
           func_quote_for_eval "$flag"
-	  arg="$arg $wl$func_quote_for_eval_result"
-	  compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
-	  linker_flags="$linker_flags $func_quote_for_eval_result"
+	  func_append arg " $wl$func_quote_for_eval_result"
+	  func_append compiler_flags " $wl$func_quote_for_eval_result"
+	  func_append linker_flags " $func_quote_for_eval_result"
 	done
 	IFS="$save_ifs"
 	func_stripname ' ' '' "$arg"
@@ -4754,23 +5825,27 @@ func_mode_link ()
 	arg="$func_quote_for_eval_result"
 	;;
 
-      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
-      # -r[0-9][0-9]* specifies the processor on the SGI compiler
-      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
-      # +DA*, +DD* enable 64-bit mode on the HP compiler
-      # -q* pass through compiler args for the IBM compiler
-      # -m*, -t[45]*, -txscale* pass through architecture-specific
-      # compiler args for GCC
-      # -F/path gives path to uninstalled frameworks, gcc on darwin
-      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
-      # @file GCC response files
+      # Flags to be passed through unchanged, with rationale:
+      # -64, -mips[0-9]      enable 64-bit mode for the SGI compiler
+      # -r[0-9][0-9]*        specify processor for the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+      # +DA*, +DD*           enable 64-bit mode for the HP compiler
+      # -q*                  compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+      # -F/path              path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-*  profiling flags for GCC
+      # @file                GCC response files
+      # -tp=*                Portland pgcc target processor selection
+      # --sysroot=*          for sysroot support
+      # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
       -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
-      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+      -O*|-flto*|-fwhopr*|-fuse-linker-plugin)
         func_quote_for_eval "$arg"
 	arg="$func_quote_for_eval_result"
         func_append compile_command " $arg"
         func_append finalize_command " $arg"
-        compiler_flags="$compiler_flags $arg"
+        func_append compiler_flags " $arg"
         continue
         ;;
 
@@ -4782,7 +5857,7 @@ func_mode_link ()
 
       *.$objext)
 	# A standard object.
-	objs="$objs $arg"
+	func_append objs " $arg"
 	;;
 
       *.lo)
@@ -4813,7 +5888,7 @@ func_mode_link ()
 
 	    if test "$prev" = dlfiles; then
 	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-		dlfiles="$dlfiles $pic_object"
+		func_append dlfiles " $pic_object"
 		prev=
 		continue
 	      else
@@ -4825,7 +5900,7 @@ func_mode_link ()
 	    # CHECK ME:  I think I busted this.  -Ossama
 	    if test "$prev" = dlprefiles; then
 	      # Preload the old-style object.
-	      dlprefiles="$dlprefiles $pic_object"
+	      func_append dlprefiles " $pic_object"
 	      prev=
 	    fi
 
@@ -4870,24 +5945,25 @@ func_mode_link ()
 
       *.$libext)
 	# An archive.
-	deplibs="$deplibs $arg"
-	old_deplibs="$old_deplibs $arg"
+	func_append deplibs " $arg"
+	func_append old_deplibs " $arg"
 	continue
 	;;
 
       *.la)
 	# A libtool-controlled library.
 
+	func_resolve_sysroot "$arg"
 	if test "$prev" = dlfiles; then
 	  # This library was specified with -dlopen.
-	  dlfiles="$dlfiles $arg"
+	  func_append dlfiles " $func_resolve_sysroot_result"
 	  prev=
 	elif test "$prev" = dlprefiles; then
 	  # The library was specified with -dlpreopen.
-	  dlprefiles="$dlprefiles $arg"
+	  func_append dlprefiles " $func_resolve_sysroot_result"
 	  prev=
 	else
-	  deplibs="$deplibs $arg"
+	  func_append deplibs " $func_resolve_sysroot_result"
 	fi
 	continue
 	;;
@@ -4925,7 +6001,7 @@ func_mode_link ()
 
     if test -n "$shlibpath_var"; then
       # get the directories listed in $shlibpath_var
-      eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+      eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
     else
       shlib_search_path=
     fi
@@ -4934,6 +6010,8 @@ func_mode_link ()
 
     func_dirname "$output" "/" ""
     output_objdir="$func_dirname_result$objdir"
+    func_to_tool_file "$output_objdir/"
+    tool_output_objdir=$func_to_tool_file_result
     # Create the object directory.
     func_mkdir_p "$output_objdir"
 
@@ -4954,12 +6032,12 @@ func_mode_link ()
     # Find all interdependent deplibs by searching for libraries
     # that are linked more than once (e.g. -la -lb -la)
     for deplib in $deplibs; do
-      if $opt_duplicate_deps ; then
+      if $opt_preserve_dup_deps ; then
 	case "$libs " in
-	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	*" $deplib "*) func_append specialdeplibs " $deplib" ;;
 	esac
       fi
-      libs="$libs $deplib"
+      func_append libs " $deplib"
     done
 
     if test "$linkmode" = lib; then
@@ -4972,9 +6050,9 @@ func_mode_link ()
       if $opt_duplicate_compiler_generated_deps; then
 	for pre_post_dep in $predeps $postdeps; do
 	  case "$pre_post_deps " in
-	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
 	  esac
-	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	  func_append pre_post_deps " $pre_post_dep"
 	done
       fi
       pre_post_deps=
@@ -5033,10 +6111,7 @@ func_mode_link ()
 	case $pass in
 	dlopen) libs="$dlfiles" ;;
 	dlpreopen) libs="$dlprefiles" ;;
-	link)
-	  libs="$deplibs %DEPLIBS%"
-	  test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
-	  ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
 	esac
       fi
       if test "$linkmode,$pass" = "lib,dlpreopen"; then
@@ -5044,17 +6119,19 @@ func_mode_link ()
 	for lib in $dlprefiles; do
 	  # Ignore non-libtool-libs
 	  dependency_libs=
+	  func_resolve_sysroot "$lib"
 	  case $lib in
-	  *.la)	func_source "$lib" ;;
+	  *.la)	func_source "$func_resolve_sysroot_result" ;;
 	  esac
 
 	  # Collect preopened libtool deplibs, except any this library
 	  # has declared as weak libs
 	  for deplib in $dependency_libs; do
-            deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"`
+	    func_basename "$deplib"
+            deplib_base=$func_basename_result
 	    case " $weak_libs " in
 	    *" $deplib_base "*) ;;
-	    *) deplibs="$deplibs $deplib" ;;
+	    *) func_append deplibs " $deplib" ;;
 	    esac
 	  done
 	done
@@ -5075,11 +6152,11 @@ func_mode_link ()
 	    compile_deplibs="$deplib $compile_deplibs"
 	    finalize_deplibs="$deplib $finalize_deplibs"
 	  else
-	    compiler_flags="$compiler_flags $deplib"
+	    func_append compiler_flags " $deplib"
 	    if test "$linkmode" = lib ; then
 		case "$new_inherited_linker_flags " in
 		    *" $deplib "*) ;;
-		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		    * ) func_append new_inherited_linker_flags " $deplib" ;;
 		esac
 	    fi
 	  fi
@@ -5164,7 +6241,7 @@ func_mode_link ()
 	    if test "$linkmode" = lib ; then
 		case "$new_inherited_linker_flags " in
 		    *" $deplib "*) ;;
-		    * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+		    * ) func_append new_inherited_linker_flags " $deplib" ;;
 		esac
 	    fi
 	  fi
@@ -5177,7 +6254,8 @@ func_mode_link ()
 	    test "$pass" = conv && continue
 	    newdependency_libs="$deplib $newdependency_libs"
 	    func_stripname '-L' '' "$deplib"
-	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    func_resolve_sysroot "$func_stripname_result"
+	    func_append newlib_search_path " $func_resolve_sysroot_result"
 	    ;;
 	  prog)
 	    if test "$pass" = conv; then
@@ -5191,7 +6269,8 @@ func_mode_link ()
 	      finalize_deplibs="$deplib $finalize_deplibs"
 	    fi
 	    func_stripname '-L' '' "$deplib"
-	    newlib_search_path="$newlib_search_path $func_stripname_result"
+	    func_resolve_sysroot "$func_stripname_result"
+	    func_append newlib_search_path " $func_resolve_sysroot_result"
 	    ;;
 	  *)
 	    func_warning "\`-L' is ignored for archives/objects"
@@ -5202,17 +6281,21 @@ func_mode_link ()
 	-R*)
 	  if test "$pass" = link; then
 	    func_stripname '-R' '' "$deplib"
-	    dir=$func_stripname_result
+	    func_resolve_sysroot "$func_stripname_result"
+	    dir=$func_resolve_sysroot_result
 	    # Make sure the xrpath contains only unique directories.
 	    case "$xrpath " in
 	    *" $dir "*) ;;
-	    *) xrpath="$xrpath $dir" ;;
+	    *) func_append xrpath " $dir" ;;
 	    esac
 	  fi
 	  deplibs="$deplib $deplibs"
 	  continue
 	  ;;
-	*.la) lib="$deplib" ;;
+	*.la)
+	  func_resolve_sysroot "$deplib"
+	  lib=$func_resolve_sysroot_result
+	  ;;
 	*.$libext)
 	  if test "$pass" = conv; then
 	    deplibs="$deplib $deplibs"
@@ -5230,7 +6313,7 @@ func_mode_link ()
 		match_pattern*)
 		  set dummy $deplibs_check_method; shift
 		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
-		  if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \
+		  if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
 		    | $EGREP "$match_pattern_regex" > /dev/null; then
 		    valid_a_lib=yes
 		  fi
@@ -5240,15 +6323,15 @@ func_mode_link ()
 		;;
 	      esac
 	      if test "$valid_a_lib" != yes; then
-		$ECHO
+		echo
 		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
-		$ECHO "*** I have the capability to make that library automatically link in when"
-		$ECHO "*** you link to this library.  But I can only do this if you have a"
-		$ECHO "*** shared version of the library, which you do not appear to have"
-		$ECHO "*** because the file extensions .$libext of this argument makes me believe"
-		$ECHO "*** that it is just a static archive that I should not use here."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because the file extensions .$libext of this argument makes me believe"
+		echo "*** that it is just a static archive that I should not use here."
 	      else
-		$ECHO
+		echo
 		$ECHO "*** Warning: Linking the shared library $output against the"
 		$ECHO "*** static library $deplib is not portable!"
 		deplibs="$deplib $deplibs"
@@ -5275,11 +6358,11 @@ func_mode_link ()
 	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
 	      # If there is no dlopen support or we're linking statically,
 	      # we need to preload.
-	      newdlprefiles="$newdlprefiles $deplib"
+	      func_append newdlprefiles " $deplib"
 	      compile_deplibs="$deplib $compile_deplibs"
 	      finalize_deplibs="$deplib $finalize_deplibs"
 	    else
-	      newdlfiles="$newdlfiles $deplib"
+	      func_append newdlfiles " $deplib"
 	    fi
 	  fi
 	  continue
@@ -5321,20 +6404,20 @@ func_mode_link ()
 
 	# Convert "-framework foo" to "foo.ltframework"
 	if test -n "$inherited_linker_flags"; then
-	  tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
 	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
 	    case " $new_inherited_linker_flags " in
 	      *" $tmp_inherited_linker_flag "*) ;;
-	      *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+	      *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
 	    esac
 	  done
 	fi
-	dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
 	if test "$linkmode,$pass" = "lib,link" ||
 	   test "$linkmode,$pass" = "prog,scan" ||
 	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
-	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
-	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+	  test -n "$dlopen" && func_append dlfiles " $dlopen"
+	  test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
 	fi
 
 	if test "$pass" = conv; then
@@ -5345,30 +6428,36 @@ func_mode_link ()
 	      func_fatal_error "cannot find name of link library for \`$lib'"
 	    fi
 	    # It is a libtool convenience library, so add in its objects.
-	    convenience="$convenience $ladir/$objdir/$old_library"
-	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
-	    tmp_libs=
-	    for deplib in $dependency_libs; do
-	      deplibs="$deplib $deplibs"
-	      if $opt_duplicate_deps ; then
-		case "$tmp_libs " in
-		*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-		esac
-	      fi
-	      tmp_libs="$tmp_libs $deplib"
-	    done
+	    func_append convenience " $ladir/$objdir/$old_library"
+	    func_append old_convenience " $ladir/$objdir/$old_library"
 	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
 	    func_fatal_error "\`$lib' is not a convenience library"
 	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_preserve_dup_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+	      esac
+	    fi
+	    func_append tmp_libs " $deplib"
+	  done
 	  continue
 	fi # $pass = conv
 
 
 	# Get the name of the library we link against.
 	linklib=
-	for l in $old_library $library_names; do
-	  linklib="$l"
-	done
+	if test -n "$old_library" &&
+	   { test "$prefer_static_libs" = yes ||
+	     test "$prefer_static_libs,$installed" = "built,no"; }; then
+	  linklib=$old_library
+	else
+	  for l in $old_library $library_names; do
+	    linklib="$l"
+	  done
+	fi
 	if test -z "$linklib"; then
 	  func_fatal_error "cannot find name of link library for \`$lib'"
 	fi
@@ -5385,9 +6474,9 @@ func_mode_link ()
 	    # statically, we need to preload.  We also need to preload any
 	    # dependent libraries so libltdl's deplib preloader doesn't
 	    # bomb out in the load deplibs phase.
-	    dlprefiles="$dlprefiles $lib $dependency_libs"
+	    func_append dlprefiles " $lib $dependency_libs"
 	  else
-	    newdlfiles="$newdlfiles $lib"
+	    func_append newdlfiles " $lib"
 	  fi
 	  continue
 	fi # $pass = dlopen
@@ -5409,14 +6498,14 @@ func_mode_link ()
 
 	# Find the relevant object directory and library name.
 	if test "X$installed" = Xyes; then
-	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	  if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
 	    func_warning "library \`$lib' was moved."
 	    dir="$ladir"
 	    absdir="$abs_ladir"
 	    libdir="$abs_ladir"
 	  else
-	    dir="$libdir"
-	    absdir="$libdir"
+	    dir="$lt_sysroot$libdir"
+	    absdir="$lt_sysroot$libdir"
 	  fi
 	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
 	else
@@ -5424,12 +6513,12 @@ func_mode_link ()
 	    dir="$ladir"
 	    absdir="$abs_ladir"
 	    # Remove this search path later
-	    notinst_path="$notinst_path $abs_ladir"
+	    func_append notinst_path " $abs_ladir"
 	  else
 	    dir="$ladir/$objdir"
 	    absdir="$abs_ladir/$objdir"
 	    # Remove this search path later
-	    notinst_path="$notinst_path $abs_ladir"
+	    func_append notinst_path " $abs_ladir"
 	  fi
 	fi # $installed = yes
 	func_stripname 'lib' '.la' "$laname"
@@ -5440,20 +6529,46 @@ func_mode_link ()
 	  if test -z "$libdir" && test "$linkmode" = prog; then
 	    func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
 	  fi
-	  # Prefer using a static library (so that no silly _DYNAMIC symbols
-	  # are required to link).
-	  if test -n "$old_library"; then
-	    newdlprefiles="$newdlprefiles $dir/$old_library"
-	    # Keep a list of preopened convenience libraries to check
-	    # that they are being used correctly in the link pass.
-	    test -z "$libdir" && \
-		dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
-	  # Otherwise, use the dlname, so that lt_dlopen finds it.
-	  elif test -n "$dlname"; then
-	    newdlprefiles="$newdlprefiles $dir/$dlname"
-	  else
-	    newdlprefiles="$newdlprefiles $dir/$linklib"
-	  fi
+	  case "$host" in
+	    # special handling for platforms with PE-DLLs.
+	    *cygwin* | *mingw* | *cegcc* )
+	      # Linker will automatically link against shared library if both
+	      # static and shared are present.  Therefore, ensure we extract
+	      # symbols from the import library if a shared library is present
+	      # (otherwise, the dlopen module name will be incorrect).  We do
+	      # this by putting the import library name into $newdlprefiles.
+	      # We recover the dlopen module name by 'saving' the la file
+	      # name in a special purpose variable, and (later) extracting the
+	      # dlname from the la file.
+	      if test -n "$dlname"; then
+	        func_tr_sh "$dir/$linklib"
+	        eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+	        func_append newdlprefiles " $dir/$linklib"
+	      else
+	        func_append newdlprefiles " $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          func_append dlpreconveniencelibs " $dir/$old_library"
+	      fi
+	    ;;
+	    * )
+	      # Prefer using a static library (so that no silly _DYNAMIC symbols
+	      # are required to link).
+	      if test -n "$old_library"; then
+	        func_append newdlprefiles " $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          func_append dlpreconveniencelibs " $dir/$old_library"
+	      # Otherwise, use the dlname, so that lt_dlopen finds it.
+	      elif test -n "$dlname"; then
+	        func_append newdlprefiles " $dir/$dlname"
+	      else
+	        func_append newdlprefiles " $dir/$linklib"
+	      fi
+	    ;;
+	  esac
 	fi # $pass = dlpreopen
 
 	if test -z "$libdir"; then
@@ -5471,7 +6586,7 @@ func_mode_link ()
 
 
 	if test "$linkmode" = prog && test "$pass" != link; then
-	  newlib_search_path="$newlib_search_path $ladir"
+	  func_append newlib_search_path " $ladir"
 	  deplibs="$lib $deplibs"
 
 	  linkalldeplibs=no
@@ -5484,7 +6599,8 @@ func_mode_link ()
 	  for deplib in $dependency_libs; do
 	    case $deplib in
 	    -L*) func_stripname '-L' '' "$deplib"
-	         newlib_search_path="$newlib_search_path $func_stripname_result"
+	         func_resolve_sysroot "$func_stripname_result"
+	         func_append newlib_search_path " $func_resolve_sysroot_result"
 		 ;;
 	    esac
 	    # Need to link against all dependency_libs?
@@ -5495,12 +6611,12 @@ func_mode_link ()
 	      # or/and link against static libraries
 	      newdependency_libs="$deplib $newdependency_libs"
 	    fi
-	    if $opt_duplicate_deps ; then
+	    if $opt_preserve_dup_deps ; then
 	      case "$tmp_libs " in
-	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      *" $deplib "*) func_append specialdeplibs " $deplib" ;;
 	      esac
 	    fi
-	    tmp_libs="$tmp_libs $deplib"
+	    func_append tmp_libs " $deplib"
 	  done # for deplib
 	  continue
 	fi # $linkmode = prog...
@@ -5515,7 +6631,7 @@ func_mode_link ()
 	      # Make sure the rpath contains only unique directories.
 	      case "$temp_rpath:" in
 	      *"$absdir:"*) ;;
-	      *) temp_rpath="$temp_rpath$absdir:" ;;
+	      *) func_append temp_rpath "$absdir:" ;;
 	      esac
 	    fi
 
@@ -5527,7 +6643,7 @@ func_mode_link ()
 	    *)
 	      case "$compile_rpath " in
 	      *" $absdir "*) ;;
-	      *) compile_rpath="$compile_rpath $absdir"
+	      *) func_append compile_rpath " $absdir" ;;
 	      esac
 	      ;;
 	    esac
@@ -5536,7 +6652,7 @@ func_mode_link ()
 	    *)
 	      case "$finalize_rpath " in
 	      *" $libdir "*) ;;
-	      *) finalize_rpath="$finalize_rpath $libdir"
+	      *) func_append finalize_rpath " $libdir" ;;
 	      esac
 	      ;;
 	    esac
@@ -5561,12 +6677,12 @@ func_mode_link ()
 	  case $host in
 	  *cygwin* | *mingw* | *cegcc*)
 	      # No point in relinking DLLs because paths are not encoded
-	      notinst_deplibs="$notinst_deplibs $lib"
+	      func_append notinst_deplibs " $lib"
 	      need_relink=no
 	    ;;
 	  *)
 	    if test "$installed" = no; then
-	      notinst_deplibs="$notinst_deplibs $lib"
+	      func_append notinst_deplibs " $lib"
 	      need_relink=yes
 	    fi
 	    ;;
@@ -5583,7 +6699,7 @@ func_mode_link ()
 	    fi
 	  done
 	  if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
-	    $ECHO
+	    echo
 	    if test "$linkmode" = prog; then
 	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
 	    else
@@ -5601,7 +6717,7 @@ func_mode_link ()
 	    *)
 	      case "$compile_rpath " in
 	      *" $absdir "*) ;;
-	      *) compile_rpath="$compile_rpath $absdir"
+	      *) func_append compile_rpath " $absdir" ;;
 	      esac
 	      ;;
 	    esac
@@ -5610,7 +6726,7 @@ func_mode_link ()
 	    *)
 	      case "$finalize_rpath " in
 	      *" $libdir "*) ;;
-	      *) finalize_rpath="$finalize_rpath $libdir"
+	      *) func_append finalize_rpath " $libdir" ;;
 	      esac
 	      ;;
 	    esac
@@ -5664,7 +6780,7 @@ func_mode_link ()
 	    linklib=$newlib
 	  fi # test -n "$old_archive_from_expsyms_cmds"
 
-	  if test "$linkmode" = prog || test "$mode" != relink; then
+	  if test "$linkmode" = prog || test "$opt_mode" != relink; then
 	    add_shlibpath=
 	    add_dir=
 	    add=
@@ -5686,9 +6802,9 @@ func_mode_link ()
 		      if test "X$dlopenmodule" != "X$lib"; then
 			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
 			if test -z "$old_library" ; then
-			  $ECHO
-			  $ECHO "*** And there doesn't seem to be a static archive available"
-			  $ECHO "*** The link will probably fail, sorry"
+			  echo
+			  echo "*** And there doesn't seem to be a static archive available"
+			  echo "*** The link will probably fail, sorry"
 			else
 			  add="$dir/$old_library"
 			fi
@@ -5720,7 +6836,7 @@ func_mode_link ()
 		if test -n "$inst_prefix_dir"; then
 		  case $libdir in
 		    [\\/]*)
-		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		      func_append add_dir " -L$inst_prefix_dir$libdir"
 		      ;;
 		  esac
 		fi
@@ -5742,7 +6858,7 @@ func_mode_link ()
 	    if test -n "$add_shlibpath"; then
 	      case :$compile_shlibpath: in
 	      *":$add_shlibpath:"*) ;;
-	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+	      *) func_append compile_shlibpath "$add_shlibpath:" ;;
 	      esac
 	    fi
 	    if test "$linkmode" = prog; then
@@ -5756,13 +6872,13 @@ func_mode_link ()
 		 test "$hardcode_shlibpath_var" = yes; then
 		case :$finalize_shlibpath: in
 		*":$libdir:"*) ;;
-		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+		*) func_append finalize_shlibpath "$libdir:" ;;
 		esac
 	      fi
 	    fi
 	  fi
 
-	  if test "$linkmode" = prog || test "$mode" = relink; then
+	  if test "$linkmode" = prog || test "$opt_mode" = relink; then
 	    add_shlibpath=
 	    add_dir=
 	    add=
@@ -5776,7 +6892,7 @@ func_mode_link ()
 	    elif test "$hardcode_shlibpath_var" = yes; then
 	      case :$finalize_shlibpath: in
 	      *":$libdir:"*) ;;
-	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+	      *) func_append finalize_shlibpath "$libdir:" ;;
 	      esac
 	      add="-l$name"
 	    elif test "$hardcode_automatic" = yes; then
@@ -5793,7 +6909,7 @@ func_mode_link ()
 	      if test -n "$inst_prefix_dir"; then
 		case $libdir in
 		  [\\/]*)
-		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		    func_append add_dir " -L$inst_prefix_dir$libdir"
 		    ;;
 		esac
 	      fi
@@ -5828,21 +6944,21 @@ func_mode_link ()
 
 	    # Just print a warning and add the library to dependency_libs so
 	    # that the program can be linked against the static library.
-	    $ECHO
+	    echo
 	    $ECHO "*** Warning: This system can not link to static lib archive $lib."
-	    $ECHO "*** I have the capability to make that library automatically link in when"
-	    $ECHO "*** you link to this library.  But I can only do this if you have a"
-	    $ECHO "*** shared version of the library, which you do not appear to have."
+	    echo "*** I have the capability to make that library automatically link in when"
+	    echo "*** you link to this library.  But I can only do this if you have a"
+	    echo "*** shared version of the library, which you do not appear to have."
 	    if test "$module" = yes; then
-	      $ECHO "*** But as you try to build a module library, libtool will still create "
-	      $ECHO "*** a static module, that should work as long as the dlopening application"
-	      $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      echo "*** But as you try to build a module library, libtool will still create "
+	      echo "*** a static module, that should work as long as the dlopening application"
+	      echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
 	      if test -z "$global_symbol_pipe"; then
-		$ECHO
-		$ECHO "*** However, this would only work if libtool was able to extract symbol"
-		$ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
-		$ECHO "*** not find such a program.  So, this module is probably useless."
-		$ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+		echo
+		echo "*** However, this would only work if libtool was able to extract symbol"
+		echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		echo "*** not find such a program.  So, this module is probably useless."
+		echo "*** \`nm' from GNU binutils and a full rebuild may help."
 	      fi
 	      if test "$build_old_libs" = no; then
 		build_libtool_libs=module
@@ -5870,27 +6986,33 @@ func_mode_link ()
 	           temp_xrpath=$func_stripname_result
 		   case " $xrpath " in
 		   *" $temp_xrpath "*) ;;
-		   *) xrpath="$xrpath $temp_xrpath";;
+		   *) func_append xrpath " $temp_xrpath";;
 		   esac;;
-	      *) temp_deplibs="$temp_deplibs $libdir";;
+	      *) func_append temp_deplibs " $libdir";;
 	      esac
 	    done
 	    dependency_libs="$temp_deplibs"
 	  fi
 
-	  newlib_search_path="$newlib_search_path $absdir"
+	  func_append newlib_search_path " $absdir"
 	  # Link against this library
 	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
 	  # ... and its dependency_libs
 	  tmp_libs=
 	  for deplib in $dependency_libs; do
 	    newdependency_libs="$deplib $newdependency_libs"
-	    if $opt_duplicate_deps ; then
+	    case $deplib in
+              -L*) func_stripname '-L' '' "$deplib"
+                   func_resolve_sysroot "$func_stripname_result";;
+              *) func_resolve_sysroot "$deplib" ;;
+            esac
+	    if $opt_preserve_dup_deps ; then
 	      case "$tmp_libs " in
-	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      *" $func_resolve_sysroot_result "*)
+                func_append specialdeplibs " $func_resolve_sysroot_result" ;;
 	      esac
 	    fi
-	    tmp_libs="$tmp_libs $deplib"
+	    func_append tmp_libs " $func_resolve_sysroot_result"
 	  done
 
 	  if test "$link_all_deplibs" != no; then
@@ -5900,8 +7022,10 @@ func_mode_link ()
 	      case $deplib in
 	      -L*) path="$deplib" ;;
 	      *.la)
+	        func_resolve_sysroot "$deplib"
+	        deplib=$func_resolve_sysroot_result
 	        func_dirname "$deplib" "" "."
-		dir="$func_dirname_result"
+		dir=$func_dirname_result
 		# We need an absolute path.
 		case $dir in
 		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
@@ -5928,8 +7052,8 @@ func_mode_link ()
                       if test -z "$darwin_install_name"; then
                           darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
                       fi
-		      compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
-		      linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
+		      func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+		      func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}"
 		      path=
 		    fi
 		  fi
@@ -5962,7 +7086,7 @@ func_mode_link ()
 	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
 	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
 	else
-	  compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
 	fi
       fi
       dependency_libs="$newdependency_libs"
@@ -5979,7 +7103,7 @@ func_mode_link ()
 	  for dir in $newlib_search_path; do
 	    case "$lib_search_path " in
 	    *" $dir "*) ;;
-	    *) lib_search_path="$lib_search_path $dir" ;;
+	    *) func_append lib_search_path " $dir" ;;
 	    esac
 	  done
 	  newlib_search_path=
@@ -6037,10 +7161,10 @@ func_mode_link ()
 	    -L*)
 	      case " $tmp_libs " in
 	      *" $deplib "*) ;;
-	      *) tmp_libs="$tmp_libs $deplib" ;;
+	      *) func_append tmp_libs " $deplib" ;;
 	      esac
 	      ;;
-	    *) tmp_libs="$tmp_libs $deplib" ;;
+	    *) func_append tmp_libs " $deplib" ;;
 	    esac
 	  done
 	  eval $var=\"$tmp_libs\"
@@ -6056,7 +7180,7 @@ func_mode_link ()
 	  ;;
 	esac
 	if test -n "$i" ; then
-	  tmp_libs="$tmp_libs $i"
+	  func_append tmp_libs " $i"
 	fi
       done
       dependency_libs=$tmp_libs
@@ -6097,7 +7221,7 @@ func_mode_link ()
       # Now set the variables for building old libraries.
       build_libtool_libs=no
       oldlibs="$output"
-      objs="$objs$old_deplibs"
+      func_append objs "$old_deplibs"
       ;;
 
     lib)
@@ -6130,10 +7254,10 @@ func_mode_link ()
 	if test "$deplibs_check_method" != pass_all; then
 	  func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
 	else
-	  $ECHO
+	  echo
 	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
 	  $ECHO "*** objects $objs is not portable!"
-	  libobjs="$libobjs $objs"
+	  func_append libobjs " $objs"
 	fi
       fi
 
@@ -6198,7 +7322,7 @@ func_mode_link ()
 	    age="$number_minor"
 	    revision="$number_revision"
 	    ;;
-	  freebsd-aout|freebsd-elf|sunos)
+	  freebsd-aout|freebsd-elf|qnx|sunos)
 	    current="$number_major"
 	    revision="$number_minor"
 	    age="0"
@@ -6210,9 +7334,6 @@ func_mode_link ()
 	    revision="$number_minor"
 	    lt_irix_increment=no
 	    ;;
-	  *)
-	    func_fatal_configuration "$modename: unknown library version type \`$version_type'"
-	    ;;
 	  esac
 	  ;;
 	no)
@@ -6334,7 +7455,7 @@ func_mode_link ()
 	  done
 
 	  # Make executables depend on our current version.
-	  verstring="$verstring:${current}.0"
+	  func_append verstring ":${current}.0"
 	  ;;
 
 	qnx)
@@ -6402,10 +7523,10 @@ func_mode_link ()
       fi
 
       func_generate_dlsyms "$libname" "$libname" "yes"
-      libobjs="$libobjs $symfileobj"
+      func_append libobjs " $symfileobj"
       test "X$libobjs" = "X " && libobjs=
 
-      if test "$mode" != relink; then
+      if test "$opt_mode" != relink; then
 	# Remove our outputs, but don't remove object files since they
 	# may have been created when compiling PIC objects.
 	removelist=
@@ -6421,7 +7542,7 @@ func_mode_link ()
 		   continue
 		 fi
 	       fi
-	       removelist="$removelist $p"
+	       func_append removelist " $p"
 	       ;;
 	    *) ;;
 	  esac
@@ -6432,27 +7553,28 @@ func_mode_link ()
 
       # Now set the variables for building old libraries.
       if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
-	oldlibs="$oldlibs $output_objdir/$libname.$libext"
+	func_append oldlibs " $output_objdir/$libname.$libext"
 
 	# Transform .lo files to .o files.
-	oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+	oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
       fi
 
       # Eliminate all temporary directories.
       #for path in $notinst_path; do
-      #	lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"`
-      #	deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"`
-      #	dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"`
+      #	lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+      #	deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
       #done
 
       if test -n "$xrpath"; then
 	# If the user specified any rpath flags, then add them.
 	temp_xrpath=
 	for libdir in $xrpath; do
-	  temp_xrpath="$temp_xrpath -R$libdir"
+	  func_replace_sysroot "$libdir"
+	  func_append temp_xrpath " -R$func_replace_sysroot_result"
 	  case "$finalize_rpath " in
 	  *" $libdir "*) ;;
-	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  *) func_append finalize_rpath " $libdir" ;;
 	  esac
 	done
 	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
@@ -6466,7 +7588,7 @@ func_mode_link ()
       for lib in $old_dlfiles; do
 	case " $dlprefiles $dlfiles " in
 	*" $lib "*) ;;
-	*) dlfiles="$dlfiles $lib" ;;
+	*) func_append dlfiles " $lib" ;;
 	esac
       done
 
@@ -6476,19 +7598,19 @@ func_mode_link ()
       for lib in $old_dlprefiles; do
 	case "$dlprefiles " in
 	*" $lib "*) ;;
-	*) dlprefiles="$dlprefiles $lib" ;;
+	*) func_append dlprefiles " $lib" ;;
 	esac
       done
 
       if test "$build_libtool_libs" = yes; then
 	if test -n "$rpath"; then
 	  case $host in
-	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*)
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
 	    # these systems don't actually have a c library (as such)!
 	    ;;
 	  *-*-rhapsody* | *-*-darwin1.[012])
 	    # Rhapsody C library is in the System framework
-	    deplibs="$deplibs System.ltframework"
+	    func_append deplibs " System.ltframework"
 	    ;;
 	  *-*-netbsd*)
 	    # Don't link with libc until the a.out ld.so is fixed.
@@ -6505,7 +7627,7 @@ func_mode_link ()
 	  *)
 	    # Add libc to deplibs on all other systems if necessary.
 	    if test "$build_libtool_need_lc" = "yes"; then
-	      deplibs="$deplibs -lc"
+	      func_append deplibs " -lc"
 	    fi
 	    ;;
 	  esac
@@ -6554,7 +7676,7 @@ EOF
 		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
 		  case " $predeps $postdeps " in
 		  *" $i "*)
-		    newdeplibs="$newdeplibs $i"
+		    func_append newdeplibs " $i"
 		    i=""
 		    ;;
 		  esac
@@ -6565,21 +7687,21 @@ EOF
 		  set dummy $deplib_matches; shift
 		  deplib_match=$1
 		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		    newdeplibs="$newdeplibs $i"
+		    func_append newdeplibs " $i"
 		  else
 		    droppeddeps=yes
-		    $ECHO
+		    echo
 		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
-		    $ECHO "*** I have the capability to make that library automatically link in when"
-		    $ECHO "*** you link to this library.  But I can only do this if you have a"
-		    $ECHO "*** shared version of the library, which I believe you do not have"
-		    $ECHO "*** because a test_compile did reveal that the linker did not use it for"
-		    $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+		    echo "*** I have the capability to make that library automatically link in when"
+		    echo "*** you link to this library.  But I can only do this if you have a"
+		    echo "*** shared version of the library, which I believe you do not have"
+		    echo "*** because a test_compile did reveal that the linker did not use it for"
+		    echo "*** its dynamic dependency list that programs get resolved with at runtime."
 		  fi
 		fi
 		;;
 	      *)
-		newdeplibs="$newdeplibs $i"
+		func_append newdeplibs " $i"
 		;;
 	      esac
 	    done
@@ -6597,7 +7719,7 @@ EOF
 		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
 		    case " $predeps $postdeps " in
 		    *" $i "*)
-		      newdeplibs="$newdeplibs $i"
+		      func_append newdeplibs " $i"
 		      i=""
 		      ;;
 		    esac
@@ -6608,29 +7730,29 @@ EOF
 		    set dummy $deplib_matches; shift
 		    deplib_match=$1
 		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		      newdeplibs="$newdeplibs $i"
+		      func_append newdeplibs " $i"
 		    else
 		      droppeddeps=yes
-		      $ECHO
+		      echo
 		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
-		      $ECHO "*** I have the capability to make that library automatically link in when"
-		      $ECHO "*** you link to this library.  But I can only do this if you have a"
-		      $ECHO "*** shared version of the library, which you do not appear to have"
-		      $ECHO "*** because a test_compile did reveal that the linker did not use this one"
-		      $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+		      echo "*** I have the capability to make that library automatically link in when"
+		      echo "*** you link to this library.  But I can only do this if you have a"
+		      echo "*** shared version of the library, which you do not appear to have"
+		      echo "*** because a test_compile did reveal that the linker did not use this one"
+		      echo "*** as a dynamic dependency that programs can get resolved with at runtime."
 		    fi
 		  fi
 		else
 		  droppeddeps=yes
-		  $ECHO
+		  echo
 		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
-		  $ECHO "*** make it link in!  You will probably need to install it or some"
-		  $ECHO "*** library that it depends on before this library will be fully"
-		  $ECHO "*** functional.  Installing it before continuing would be even better."
+		  echo "*** make it link in!  You will probably need to install it or some"
+		  echo "*** library that it depends on before this library will be fully"
+		  echo "*** functional.  Installing it before continuing would be even better."
 		fi
 		;;
 	      *)
-		newdeplibs="$newdeplibs $i"
+		func_append newdeplibs " $i"
 		;;
 	      esac
 	    done
@@ -6647,15 +7769,27 @@ EOF
 	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
 		case " $predeps $postdeps " in
 		*" $a_deplib "*)
-		  newdeplibs="$newdeplibs $a_deplib"
+		  func_append newdeplibs " $a_deplib"
 		  a_deplib=""
 		  ;;
 		esac
 	      fi
 	      if test -n "$a_deplib" ; then
 		libname=`eval "\\$ECHO \"$libname_spec\""`
+		if test -n "$file_magic_glob"; then
+		  libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
+		else
+		  libnameglob=$libname
+		fi
+		test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob`
 		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  if test "$want_nocaseglob" = yes; then
+		    shopt -s nocaseglob
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		    $nocaseglob
+		  else
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		  fi
 		  for potent_lib in $potential_libs; do
 		      # Follow soft links.
 		      if ls -lLd "$potent_lib" 2>/dev/null |
@@ -6672,13 +7806,13 @@ EOF
 			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
 			case $potliblink in
 			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
-			*) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+			*) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
 			esac
 		      done
 		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
 			 $SED -e 10q |
 			 $EGREP "$file_magic_regex" > /dev/null; then
-			newdeplibs="$newdeplibs $a_deplib"
+			func_append newdeplibs " $a_deplib"
 			a_deplib=""
 			break 2
 		      fi
@@ -6687,12 +7821,12 @@ EOF
 	      fi
 	      if test -n "$a_deplib" ; then
 		droppeddeps=yes
-		$ECHO
+		echo
 		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
-		$ECHO "*** I have the capability to make that library automatically link in when"
-		$ECHO "*** you link to this library.  But I can only do this if you have a"
-		$ECHO "*** shared version of the library, which you do not appear to have"
-		$ECHO "*** because I did check the linker path looking for a file starting"
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
 		if test -z "$potlib" ; then
 		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
 		else
@@ -6703,7 +7837,7 @@ EOF
 	      ;;
 	    *)
 	      # Add a -L argument.
-	      newdeplibs="$newdeplibs $a_deplib"
+	      func_append newdeplibs " $a_deplib"
 	      ;;
 	    esac
 	  done # Gone through all deplibs.
@@ -6719,7 +7853,7 @@ EOF
 	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
 		case " $predeps $postdeps " in
 		*" $a_deplib "*)
-		  newdeplibs="$newdeplibs $a_deplib"
+		  func_append newdeplibs " $a_deplib"
 		  a_deplib=""
 		  ;;
 		esac
@@ -6730,9 +7864,9 @@ EOF
 		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
 		  for potent_lib in $potential_libs; do
 		    potlib="$potent_lib" # see symlink-check above in file_magic test
-		    if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \
+		    if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
 		       $EGREP "$match_pattern_regex" > /dev/null; then
-		      newdeplibs="$newdeplibs $a_deplib"
+		      func_append newdeplibs " $a_deplib"
 		      a_deplib=""
 		      break 2
 		    fi
@@ -6741,12 +7875,12 @@ EOF
 	      fi
 	      if test -n "$a_deplib" ; then
 		droppeddeps=yes
-		$ECHO
+		echo
 		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
-		$ECHO "*** I have the capability to make that library automatically link in when"
-		$ECHO "*** you link to this library.  But I can only do this if you have a"
-		$ECHO "*** shared version of the library, which you do not appear to have"
-		$ECHO "*** because I did check the linker path looking for a file starting"
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
 		if test -z "$potlib" ; then
 		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
 		else
@@ -6757,32 +7891,32 @@ EOF
 	      ;;
 	    *)
 	      # Add a -L argument.
-	      newdeplibs="$newdeplibs $a_deplib"
+	      func_append newdeplibs " $a_deplib"
 	      ;;
 	    esac
 	  done # Gone through all deplibs.
 	  ;;
 	none | unknown | *)
 	  newdeplibs=""
-	  tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \
-	      -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'`
+	  tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
 	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
 	    for i in $predeps $postdeps ; do
 	      # can't use Xsed below, because $i might contain '/'
-	      tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"`
+	      tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
 	    done
 	  fi
-	  if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[	 ]//g' |
-	     $GREP . >/dev/null; then
-	    $ECHO
+	  case $tmp_deplibs in
+	  *[!\	\ ]*)
+	    echo
 	    if test "X$deplibs_check_method" = "Xnone"; then
-	      $ECHO "*** Warning: inter-library dependencies are not supported in this platform."
+	      echo "*** Warning: inter-library dependencies are not supported in this platform."
 	    else
-	      $ECHO "*** Warning: inter-library dependencies are not known to be supported."
+	      echo "*** Warning: inter-library dependencies are not known to be supported."
 	    fi
-	    $ECHO "*** All declared inter-library dependencies are being dropped."
+	    echo "*** All declared inter-library dependencies are being dropped."
 	    droppeddeps=yes
-	  fi
+	    ;;
+	  esac
 	  ;;
 	esac
 	versuffix=$versuffix_save
@@ -6794,23 +7928,23 @@ EOF
 	case $host in
 	*-*-rhapsody* | *-*-darwin1.[012])
 	  # On Rhapsody replace the C library with the System framework
-	  newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
 	  ;;
 	esac
 
 	if test "$droppeddeps" = yes; then
 	  if test "$module" = yes; then
-	    $ECHO
-	    $ECHO "*** Warning: libtool could not satisfy all declared inter-library"
+	    echo
+	    echo "*** Warning: libtool could not satisfy all declared inter-library"
 	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
-	    $ECHO "*** a static module, that should work as long as the dlopening"
-	    $ECHO "*** application is linked with the -dlopen flag."
+	    echo "*** a static module, that should work as long as the dlopening"
+	    echo "*** application is linked with the -dlopen flag."
 	    if test -z "$global_symbol_pipe"; then
-	      $ECHO
-	      $ECHO "*** However, this would only work if libtool was able to extract symbol"
-	      $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
-	      $ECHO "*** not find such a program.  So, this module is probably useless."
-	      $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+	      echo
+	      echo "*** However, this would only work if libtool was able to extract symbol"
+	      echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      echo "*** not find such a program.  So, this module is probably useless."
+	      echo "*** \`nm' from GNU binutils and a full rebuild may help."
 	    fi
 	    if test "$build_old_libs" = no; then
 	      oldlibs="$output_objdir/$libname.$libext"
@@ -6820,16 +7954,16 @@ EOF
 	      build_libtool_libs=no
 	    fi
 	  else
-	    $ECHO "*** The inter-library dependencies that have been dropped here will be"
-	    $ECHO "*** automatically added whenever a program is linked with this library"
-	    $ECHO "*** or is declared to -dlopen it."
+	    echo "*** The inter-library dependencies that have been dropped here will be"
+	    echo "*** automatically added whenever a program is linked with this library"
+	    echo "*** or is declared to -dlopen it."
 
 	    if test "$allow_undefined" = no; then
-	      $ECHO
-	      $ECHO "*** Since this library must not contain undefined symbols,"
-	      $ECHO "*** because either the platform does not support them or"
-	      $ECHO "*** it was explicitly requested with -no-undefined,"
-	      $ECHO "*** libtool will only create a static version of it."
+	      echo
+	      echo "*** Since this library must not contain undefined symbols,"
+	      echo "*** because either the platform does not support them or"
+	      echo "*** it was explicitly requested with -no-undefined,"
+	      echo "*** libtool will only create a static version of it."
 	      if test "$build_old_libs" = no; then
 		oldlibs="$output_objdir/$libname.$libext"
 		build_libtool_libs=module
@@ -6846,9 +7980,9 @@ EOF
       # Time to change all our "foo.ltframework" stuff back to "-framework foo"
       case $host in
 	*-*-darwin*)
-	  newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
-	  new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
-	  deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
 	  ;;
       esac
 
@@ -6861,7 +7995,7 @@ EOF
 	*)
 	  case " $deplibs " in
 	  *" -L$path/$objdir "*)
-	    new_libs="$new_libs -L$path/$objdir" ;;
+	    func_append new_libs " -L$path/$objdir" ;;
 	  esac
 	  ;;
 	esac
@@ -6871,10 +8005,10 @@ EOF
 	-L*)
 	  case " $new_libs " in
 	  *" $deplib "*) ;;
-	  *) new_libs="$new_libs $deplib" ;;
+	  *) func_append new_libs " $deplib" ;;
 	  esac
 	  ;;
-	*) new_libs="$new_libs $deplib" ;;
+	*) func_append new_libs " $deplib" ;;
 	esac
       done
       deplibs="$new_libs"
@@ -6891,10 +8025,12 @@ EOF
 	  hardcode_libdirs=
 	  dep_rpath=
 	  rpath="$finalize_rpath"
-	  test "$mode" != relink && rpath="$compile_rpath$rpath"
+	  test "$opt_mode" != relink && rpath="$compile_rpath$rpath"
 	  for libdir in $rpath; do
 	    if test -n "$hardcode_libdir_flag_spec"; then
 	      if test -n "$hardcode_libdir_separator"; then
+		func_replace_sysroot "$libdir"
+		libdir=$func_replace_sysroot_result
 		if test -z "$hardcode_libdirs"; then
 		  hardcode_libdirs="$libdir"
 		else
@@ -6903,18 +8039,18 @@ EOF
 		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
 		    ;;
 		  *)
-		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		    func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
 		    ;;
 		  esac
 		fi
 	      else
 		eval flag=\"$hardcode_libdir_flag_spec\"
-		dep_rpath="$dep_rpath $flag"
+		func_append dep_rpath " $flag"
 	      fi
 	    elif test -n "$runpath_var"; then
 	      case "$perm_rpath " in
 	      *" $libdir "*) ;;
-	      *) perm_rpath="$perm_rpath $libdir" ;;
+	      *) func_apped perm_rpath " $libdir" ;;
 	      esac
 	    fi
 	  done
@@ -6932,7 +8068,7 @@ EOF
 	    # We should set the runpath_var.
 	    rpath=
 	    for dir in $perm_rpath; do
-	      rpath="$rpath$dir:"
+	      func_append rpath "$dir:"
 	    done
 	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
 	  fi
@@ -6940,7 +8076,7 @@ EOF
 	fi
 
 	shlibpath="$finalize_shlibpath"
-	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
 	if test -n "$shlibpath"; then
 	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
 	fi
@@ -6966,18 +8102,18 @@ EOF
 	linknames=
 	for link
 	do
-	  linknames="$linknames $link"
+	  func_append linknames " $link"
 	done
 
 	# Use standard objects if they are pic
-	test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
 	test "X$libobjs" = "X " && libobjs=
 
 	delfiles=
 	if test -n "$export_symbols" && test -n "$include_expsyms"; then
 	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
 	  export_symbols="$output_objdir/$libname.uexp"
-	  delfiles="$delfiles $export_symbols"
+	  func_append delfiles " $export_symbols"
 	fi
 
 	orig_export_symbols=
@@ -7008,13 +8144,45 @@ EOF
 	    $opt_dry_run || $RM $export_symbols
 	    cmds=$export_symbols_cmds
 	    save_ifs="$IFS"; IFS='~'
-	    for cmd in $cmds; do
+	    for cmd1 in $cmds; do
 	      IFS="$save_ifs"
-	      eval cmd=\"$cmd\"
-	      func_len " $cmd"
-	      len=$func_len_result
-	      if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	      # Take the normal branch if the nm_file_list_spec branch
+	      # doesn't work or if tool conversion is not needed.
+	      case $nm_file_list_spec~$to_tool_file_cmd in
+		*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+		  try_normal_branch=yes
+		  eval cmd=\"$cmd1\"
+		  func_len " $cmd"
+		  len=$func_len_result
+		  ;;
+		*)
+		  try_normal_branch=no
+		  ;;
+	      esac
+	      if test "$try_normal_branch" = yes \
+		 && { test "$len" -lt "$max_cmd_len" \
+		      || test "$max_cmd_len" -le -1; }
+	      then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      elif test -n "$nm_file_list_spec"; then
+		func_basename "$output"
+		output_la=$func_basename_result
+		save_libobjs=$libobjs
+		save_output=$output
+		output=${output_objdir}/${output_la}.nm
+		func_to_tool_file "$output"
+		libobjs=$nm_file_list_spec$func_to_tool_file_result
+		func_append delfiles " $output"
+		func_verbose "creating $NM input file list: $output"
+		for obj in $save_libobjs; do
+		  func_to_tool_file "$obj"
+		  $ECHO "$func_to_tool_file_result"
+		done > "$output"
+		eval cmd=\"$cmd1\"
 		func_show_eval "$cmd" 'exit $?'
+		output=$save_output
+		libobjs=$save_libobjs
 		skipped_export=false
 	      else
 		# The command line is too long to execute in one step.
@@ -7036,7 +8204,7 @@ EOF
 	if test -n "$export_symbols" && test -n "$include_expsyms"; then
 	  tmp_export_symbols="$export_symbols"
 	  test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
-	  $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+	  $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
 	fi
 
 	if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
@@ -7048,7 +8216,7 @@ EOF
 	  # global variables. join(1) would be nice here, but unfortunately
 	  # isn't a blessed tool.
 	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
-	  delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	  func_append delfiles " $export_symbols $output_objdir/$libname.filter"
 	  export_symbols=$output_objdir/$libname.def
 	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
 	fi
@@ -7058,7 +8226,7 @@ EOF
 	  case " $convenience " in
 	  *" $test_deplib "*) ;;
 	  *)
-	    tmp_deplibs="$tmp_deplibs $test_deplib"
+	    func_append tmp_deplibs " $test_deplib"
 	    ;;
 	  esac
 	done
@@ -7078,21 +8246,21 @@ EOF
 	    test "X$libobjs" = "X " && libobjs=
 	  else
 	    gentop="$output_objdir/${outputname}x"
-	    generated="$generated $gentop"
+	    func_append generated " $gentop"
 
 	    func_extract_archives $gentop $convenience
-	    libobjs="$libobjs $func_extract_archives_result"
+	    func_append libobjs " $func_extract_archives_result"
 	    test "X$libobjs" = "X " && libobjs=
 	  fi
 	fi
 
 	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
 	  eval flag=\"$thread_safe_flag_spec\"
-	  linker_flags="$linker_flags $flag"
+	  func_append linker_flags " $flag"
 	fi
 
 	# Make a backup of the uninstalled library when relinking
-	if test "$mode" = relink; then
+	if test "$opt_mode" = relink; then
 	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
 	fi
 
@@ -7137,7 +8305,8 @@ EOF
 	    save_libobjs=$libobjs
 	  fi
 	  save_output=$output
-	  output_la=`$ECHO "X$output" | $Xsed -e "$basename"`
+	  func_basename "$output"
+	  output_la=$func_basename_result
 
 	  # Clear the reloadable object creation command queue and
 	  # initialize k to one.
@@ -7150,13 +8319,16 @@ EOF
 	  if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
 	    output=${output_objdir}/${output_la}.lnkscript
 	    func_verbose "creating GNU ld script: $output"
-	    $ECHO 'INPUT (' > $output
+	    echo 'INPUT (' > $output
 	    for obj in $save_libobjs
 	    do
-	      $ECHO "$obj" >> $output
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
 	    done
-	    $ECHO ')' >> $output
-	    delfiles="$delfiles $output"
+	    echo ')' >> $output
+	    func_append delfiles " $output"
+	    func_to_tool_file "$output"
+	    output=$func_to_tool_file_result
 	  elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
 	    output=${output_objdir}/${output_la}.lnk
 	    func_verbose "creating linker input file list: $output"
@@ -7170,10 +8342,12 @@ EOF
 	    fi
 	    for obj
 	    do
-	      $ECHO "$obj" >> $output
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
 	    done
-	    delfiles="$delfiles $output"
-	    output=$firstobj\"$file_list_spec$output\"
+	    func_append delfiles " $output"
+	    func_to_tool_file "$output"
+	    output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
 	  else
 	    if test -n "$save_libobjs"; then
 	      func_verbose "creating reloadable object files..."
@@ -7197,17 +8371,19 @@ EOF
 		  # command to the queue.
 		  if test "$k" -eq 1 ; then
 		    # The first file doesn't have a previous command to add.
-		    eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+		    reload_objs=$objlist
+		    eval concat_cmds=\"$reload_cmds\"
 		  else
 		    # All subsequent reloadable object files will link in
 		    # the last one created.
-		    eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\"
+		    reload_objs="$objlist $last_robj"
+		    eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
 		  fi
 		  last_robj=$output_objdir/$output_la-${k}.$objext
 		  func_arith $k + 1
 		  k=$func_arith_result
 		  output=$output_objdir/$output_la-${k}.$objext
-		  objlist=$obj
+		  objlist=" $obj"
 		  func_len " $last_robj"
 		  func_arith $len0 + $func_len_result
 		  len=$func_arith_result
@@ -7217,11 +8393,12 @@ EOF
 	      # reloadable object file.  All subsequent reloadable object
 	      # files will link in the last one created.
 	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
-	      eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+	      reload_objs="$objlist $last_robj"
+	      eval concat_cmds=\"\${concat_cmds}$reload_cmds\"
 	      if test -n "$last_robj"; then
 	        eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
 	      fi
-	      delfiles="$delfiles $output"
+	      func_append delfiles " $output"
 
 	    else
 	      output=
@@ -7255,7 +8432,7 @@ EOF
 		lt_exit=$?
 
 		# Restore the uninstalled library and exit
-		if test "$mode" = relink; then
+		if test "$opt_mode" = relink; then
 		  ( cd "$output_objdir" && \
 		    $RM "${realname}T" && \
 		    $MV "${realname}U" "$realname" )
@@ -7276,7 +8453,7 @@ EOF
 	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
 	      tmp_export_symbols="$export_symbols"
 	      test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
-	      $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+	      $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
 	    fi
 
 	    if test -n "$orig_export_symbols"; then
@@ -7288,7 +8465,7 @@ EOF
 	      # global variables. join(1) would be nice here, but unfortunately
 	      # isn't a blessed tool.
 	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
-	      delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+	      func_append delfiles " $export_symbols $output_objdir/$libname.filter"
 	      export_symbols=$output_objdir/$libname.def
 	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
 	    fi
@@ -7329,10 +8506,10 @@ EOF
 	# Add any objects from preloaded convenience libraries
 	if test -n "$dlprefiles"; then
 	  gentop="$output_objdir/${outputname}x"
-	  generated="$generated $gentop"
+	  func_append generated " $gentop"
 
 	  func_extract_archives $gentop $dlprefiles
-	  libobjs="$libobjs $func_extract_archives_result"
+	  func_append libobjs " $func_extract_archives_result"
 	  test "X$libobjs" = "X " && libobjs=
 	fi
 
@@ -7348,7 +8525,7 @@ EOF
 	    lt_exit=$?
 
 	    # Restore the uninstalled library and exit
-	    if test "$mode" = relink; then
+	    if test "$opt_mode" = relink; then
 	      ( cd "$output_objdir" && \
 	        $RM "${realname}T" && \
 		$MV "${realname}U" "$realname" )
@@ -7360,7 +8537,7 @@ EOF
 	IFS="$save_ifs"
 
 	# Restore the uninstalled library and exit
-	if test "$mode" = relink; then
+	if test "$opt_mode" = relink; then
 	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
 
 	  if test -n "$convenience"; then
@@ -7441,18 +8618,21 @@ EOF
       if test -n "$convenience"; then
 	if test -n "$whole_archive_flag_spec"; then
 	  eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
-	  reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+	  reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
 	else
 	  gentop="$output_objdir/${obj}x"
-	  generated="$generated $gentop"
+	  func_append generated " $gentop"
 
 	  func_extract_archives $gentop $convenience
 	  reload_conv_objs="$reload_objs $func_extract_archives_result"
 	fi
       fi
 
+      # If we're not building shared, we need to use non_pic_objs
+      test "$build_libtool_libs" != yes && libobjs="$non_pic_objects"
+
       # Create the old-style object.
-      reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+      reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
 
       output="$obj"
       func_execute_cmds "$reload_cmds" 'exit $?'
@@ -7512,8 +8692,8 @@ EOF
       case $host in
       *-*-rhapsody* | *-*-darwin1.[012])
 	# On Rhapsody replace the C library is the System framework
-	compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
-	finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
 	;;
       esac
 
@@ -7524,14 +8704,14 @@ EOF
 	if test "$tagname" = CXX ; then
 	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
 	    10.[0123])
-	      compile_command="$compile_command ${wl}-bind_at_load"
-	      finalize_command="$finalize_command ${wl}-bind_at_load"
+	      func_append compile_command " ${wl}-bind_at_load"
+	      func_append finalize_command " ${wl}-bind_at_load"
 	    ;;
 	  esac
 	fi
 	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
-	compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
-	finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
 	;;
       esac
 
@@ -7545,7 +8725,7 @@ EOF
 	*)
 	  case " $compile_deplibs " in
 	  *" -L$path/$objdir "*)
-	    new_libs="$new_libs -L$path/$objdir" ;;
+	    func_append new_libs " -L$path/$objdir" ;;
 	  esac
 	  ;;
 	esac
@@ -7555,17 +8735,17 @@ EOF
 	-L*)
 	  case " $new_libs " in
 	  *" $deplib "*) ;;
-	  *) new_libs="$new_libs $deplib" ;;
+	  *) func_append new_libs " $deplib" ;;
 	  esac
 	  ;;
-	*) new_libs="$new_libs $deplib" ;;
+	*) func_append new_libs " $deplib" ;;
 	esac
       done
       compile_deplibs="$new_libs"
 
 
-      compile_command="$compile_command $compile_deplibs"
-      finalize_command="$finalize_command $finalize_deplibs"
+      func_append compile_command " $compile_deplibs"
+      func_append finalize_command " $finalize_deplibs"
 
       if test -n "$rpath$xrpath"; then
 	# If the user specified any rpath flags, then add them.
@@ -7573,7 +8753,7 @@ EOF
 	  # This is the magic to use -rpath.
 	  case "$finalize_rpath " in
 	  *" $libdir "*) ;;
-	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  *) func_append finalize_rpath " $libdir" ;;
 	  esac
 	done
       fi
@@ -7592,18 +8772,18 @@ EOF
 	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
 		;;
 	      *)
-		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
 		;;
 	      esac
 	    fi
 	  else
 	    eval flag=\"$hardcode_libdir_flag_spec\"
-	    rpath="$rpath $flag"
+	    func_append rpath " $flag"
 	  fi
 	elif test -n "$runpath_var"; then
 	  case "$perm_rpath " in
 	  *" $libdir "*) ;;
-	  *) perm_rpath="$perm_rpath $libdir" ;;
+	  *) func_append perm_rpath " $libdir" ;;
 	  esac
 	fi
 	case $host in
@@ -7612,12 +8792,12 @@ EOF
 	  case :$dllsearchpath: in
 	  *":$libdir:"*) ;;
 	  ::) dllsearchpath=$libdir;;
-	  *) dllsearchpath="$dllsearchpath:$libdir";;
+	  *) func_append dllsearchpath ":$libdir";;
 	  esac
 	  case :$dllsearchpath: in
 	  *":$testbindir:"*) ;;
 	  ::) dllsearchpath=$testbindir;;
-	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  *) func_append dllsearchpath ":$testbindir";;
 	  esac
 	  ;;
 	esac
@@ -7643,18 +8823,18 @@ EOF
 	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
 		;;
 	      *)
-		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
 		;;
 	      esac
 	    fi
 	  else
 	    eval flag=\"$hardcode_libdir_flag_spec\"
-	    rpath="$rpath $flag"
+	    func_append rpath " $flag"
 	  fi
 	elif test -n "$runpath_var"; then
 	  case "$finalize_perm_rpath " in
 	  *" $libdir "*) ;;
-	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+	  *) func_append finalize_perm_rpath " $libdir" ;;
 	  esac
 	fi
       done
@@ -7668,8 +8848,8 @@ EOF
 
       if test -n "$libobjs" && test "$build_old_libs" = yes; then
 	# Transform all the library objects into standard objects.
-	compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-	finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
       fi
 
       func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
@@ -7681,15 +8861,15 @@ EOF
 
       wrappers_required=yes
       case $host in
+      *cegcc* | *mingw32ce*)
+        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
       *cygwin* | *mingw* )
         if test "$build_libtool_libs" != yes; then
           wrappers_required=no
         fi
         ;;
-      *cegcc)
-        # Disable wrappers for cegcc, we are cross compiling anyway.
-        wrappers_required=no
-        ;;
       *)
         if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
           wrappers_required=no
@@ -7698,13 +8878,19 @@ EOF
       esac
       if test "$wrappers_required" = no; then
 	# Replace the output file specification.
-	compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
 	link_command="$compile_command$compile_rpath"
 
 	# We have no uninstalled library dependencies, so finalize right now.
 	exit_status=0
 	func_show_eval "$link_command" 'exit_status=$?'
 
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
 	# Delete the generated files.
 	if test -f "$output_objdir/${outputname}S.${objext}"; then
 	  func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
@@ -7727,7 +8913,7 @@ EOF
 	  # We should set the runpath_var.
 	  rpath=
 	  for dir in $perm_rpath; do
-	    rpath="$rpath$dir:"
+	    func_append rpath "$dir:"
 	  done
 	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
 	fi
@@ -7735,7 +8921,7 @@ EOF
 	  # We should set the runpath_var.
 	  rpath=
 	  for dir in $finalize_perm_rpath; do
-	    rpath="$rpath$dir:"
+	    func_append rpath "$dir:"
 	  done
 	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
 	fi
@@ -7745,11 +8931,18 @@ EOF
 	# We don't need to create a wrapper script.
 	link_command="$compile_var$compile_command$compile_rpath"
 	# Replace the output file specification.
-	link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
 	# Delete the old output file.
 	$opt_dry_run || $RM $output
 	# Link the executable and exit
 	func_show_eval "$link_command" 'exit $?'
+
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
 	exit $EXIT_SUCCESS
       fi
 
@@ -7764,7 +8957,7 @@ EOF
 	if test "$fast_install" != no; then
 	  link_command="$finalize_var$compile_command$finalize_rpath"
 	  if test "$fast_install" = yes; then
-	    relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+	    relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
 	  else
 	    # fast_install is set to needless
 	    relink_command=
@@ -7776,13 +8969,19 @@ EOF
       fi
 
       # Replace the output file specification.
-      link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
 
       # Delete the old output files.
       $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
 
       func_show_eval "$link_command" 'exit $?'
 
+      if test -n "$postlink_cmds"; then
+	func_to_tool_file "$output_objdir/$outputname"
+	postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	func_execute_cmds "$postlink_cmds" 'exit $?'
+      fi
+
       # Now create the wrapper script.
       func_verbose "creating $output"
 
@@ -7800,18 +8999,7 @@ EOF
 	  fi
 	done
 	relink_command="(cd `pwd`; $relink_command)"
-	relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
-      fi
-
-      # Quote $ECHO for shipping.
-      if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then
-	case $progpath in
-	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
-	*) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
-	esac
-	qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"`
-      else
-	qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"`
+	relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
       fi
 
       # Only actually do things if not in dry run mode.
@@ -7891,7 +9079,7 @@ EOF
 	else
 	  oldobjs="$old_deplibs $non_pic_objects"
 	  if test "$preload" = yes && test -f "$symfileobj"; then
-	    oldobjs="$oldobjs $symfileobj"
+	    func_append oldobjs " $symfileobj"
 	  fi
 	fi
 	addlibs="$old_convenience"
@@ -7899,10 +9087,10 @@ EOF
 
       if test -n "$addlibs"; then
 	gentop="$output_objdir/${outputname}x"
-	generated="$generated $gentop"
+	func_append generated " $gentop"
 
 	func_extract_archives $gentop $addlibs
-	oldobjs="$oldobjs $func_extract_archives_result"
+	func_append oldobjs " $func_extract_archives_result"
       fi
 
       # Do each command in the archive commands.
@@ -7913,10 +9101,10 @@ EOF
 	# Add any objects from preloaded convenience libraries
 	if test -n "$dlprefiles"; then
 	  gentop="$output_objdir/${outputname}x"
-	  generated="$generated $gentop"
+	  func_append generated " $gentop"
 
 	  func_extract_archives $gentop $dlprefiles
-	  oldobjs="$oldobjs $func_extract_archives_result"
+	  func_append oldobjs " $func_extract_archives_result"
 	fi
 
 	# POSIX demands no paths to be encoded in archives.  We have
@@ -7932,9 +9120,9 @@ EOF
 	    done | sort | sort -uc >/dev/null 2>&1); then
 	  :
 	else
-	  $ECHO "copying selected object files to avoid basename conflicts..."
+	  echo "copying selected object files to avoid basename conflicts..."
 	  gentop="$output_objdir/${outputname}x"
-	  generated="$generated $gentop"
+	  func_append generated " $gentop"
 	  func_mkdir_p "$gentop"
 	  save_oldobjs=$oldobjs
 	  oldobjs=
@@ -7958,9 +9146,9 @@ EOF
 		esac
 	      done
 	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
-	      oldobjs="$oldobjs $gentop/$newobj"
+	      func_append oldobjs " $gentop/$newobj"
 	      ;;
-	    *) oldobjs="$oldobjs $obj" ;;
+	    *) func_append oldobjs " $obj" ;;
 	    esac
 	  done
 	fi
@@ -7970,6 +9158,16 @@ EOF
 	len=$func_len_result
 	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
 	  cmds=$old_archive_cmds
+	elif test -n "$archiver_list_spec"; then
+	  func_verbose "using command file archive linking..."
+	  for obj in $oldobjs
+	  do
+	    func_to_tool_file "$obj"
+	    $ECHO "$func_to_tool_file_result"
+	  done > $output_objdir/$libname.libcmd
+	  func_to_tool_file "$output_objdir/$libname.libcmd"
+	  oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+	  cmds=$old_archive_cmds
 	else
 	  # the command line is too long to link in one step, link in parts
 	  func_verbose "using piecewise archive linking..."
@@ -8043,7 +9241,7 @@ EOF
       done
       # Quote the link command for shipping.
       relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
-      relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
       if test "$hardcode_automatic" = yes ; then
 	relink_command=
       fi
@@ -8066,9 +9264,19 @@ EOF
 		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
 		test -z "$libdir" && \
 		  func_fatal_error "\`$deplib' is not a valid libtool archive"
-		newdependency_libs="$newdependency_libs $libdir/$name"
+		func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      -L*)
+		func_stripname -L '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		func_append newdependency_libs " -L$func_replace_sysroot_result"
 		;;
-	      *) newdependency_libs="$newdependency_libs $deplib" ;;
+	      -R*)
+		func_stripname -R '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		func_append newdependency_libs " -R$func_replace_sysroot_result"
+		;;
+	      *) func_append newdependency_libs " $deplib" ;;
 	      esac
 	    done
 	    dependency_libs="$newdependency_libs"
@@ -8082,9 +9290,9 @@ EOF
 		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
 		test -z "$libdir" && \
 		  func_fatal_error "\`$lib' is not a valid libtool archive"
-		newdlfiles="$newdlfiles $libdir/$name"
+		func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
 		;;
-	      *) newdlfiles="$newdlfiles $lib" ;;
+	      *) func_append newdlfiles " $lib" ;;
 	      esac
 	    done
 	    dlfiles="$newdlfiles"
@@ -8101,7 +9309,7 @@ EOF
 		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
 		test -z "$libdir" && \
 		  func_fatal_error "\`$lib' is not a valid libtool archive"
-		newdlprefiles="$newdlprefiles $libdir/$name"
+		func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
 		;;
 	      esac
 	    done
@@ -8113,7 +9321,7 @@ EOF
 		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
 		*) abs=`pwd`"/$lib" ;;
 	      esac
-	      newdlfiles="$newdlfiles $abs"
+	      func_append newdlfiles " $abs"
 	    done
 	    dlfiles="$newdlfiles"
 	    newdlprefiles=
@@ -8122,15 +9330,33 @@ EOF
 		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
 		*) abs=`pwd`"/$lib" ;;
 	      esac
-	      newdlprefiles="$newdlprefiles $abs"
+	      func_append newdlprefiles " $abs"
 	    done
 	    dlprefiles="$newdlprefiles"
 	  fi
 	  $RM $output
 	  # place dlname in correct position for cygwin
+	  # In fact, it would be nice if we could use this code for all target
+	  # systems that can't hard-code library paths into their executables
+	  # and that have no shared library path variable independent of PATH,
+	  # but it turns out we can't easily determine that from inspecting
+	  # libtool variables, so we have to hard-code the OSs to which it
+	  # applies here; at the moment, that means platforms that use the PE
+	  # object format with DLL files.  See the long comment at the top of
+	  # tests/bindir.at for full details.
 	  tdlname=$dlname
 	  case $host,$output,$installed,$module,$dlname in
-	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+	      # If a -bindir argument was supplied, place the dll there.
+	      if test "x$bindir" != x ;
+	      then
+		func_relative_path "$install_libdir" "$bindir"
+		tdlname=$func_relative_path_result$dlname
+	      else
+		# Otherwise fall back on heuristic.
+		tdlname=../bin/$dlname
+	      fi
+	      ;;
 	  esac
 	  $ECHO > $output "\
 # $outputname - a libtool library file
@@ -8189,7 +9415,7 @@ relink_command=\"$relink_command\""
     exit $EXIT_SUCCESS
 }
 
-{ test "$mode" = link || test "$mode" = relink; } &&
+{ test "$opt_mode" = link || test "$opt_mode" = relink; } &&
     func_mode_link ${1+"$@"}
 
 
@@ -8209,9 +9435,9 @@ func_mode_uninstall ()
     for arg
     do
       case $arg in
-      -f) RM="$RM $arg"; rmforce=yes ;;
-      -*) RM="$RM $arg" ;;
-      *) files="$files $arg" ;;
+      -f) func_append RM " $arg"; rmforce=yes ;;
+      -*) func_append RM " $arg" ;;
+      *) func_append files " $arg" ;;
       esac
     done
 
@@ -8220,24 +9446,23 @@ func_mode_uninstall ()
 
     rmdirs=
 
-    origobjdir="$objdir"
     for file in $files; do
       func_dirname "$file" "" "."
       dir="$func_dirname_result"
       if test "X$dir" = X.; then
-	objdir="$origobjdir"
+	odir="$objdir"
       else
-	objdir="$dir/$origobjdir"
+	odir="$dir/$objdir"
       fi
       func_basename "$file"
       name="$func_basename_result"
-      test "$mode" = uninstall && objdir="$dir"
+      test "$opt_mode" = uninstall && odir="$dir"
 
-      # Remember objdir for removal later, being careful to avoid duplicates
-      if test "$mode" = clean; then
+      # Remember odir for removal later, being careful to avoid duplicates
+      if test "$opt_mode" = clean; then
 	case " $rmdirs " in
-	  *" $objdir "*) ;;
-	  *) rmdirs="$rmdirs $objdir" ;;
+	  *" $odir "*) ;;
+	  *) func_append rmdirs " $odir" ;;
 	esac
       fi
 
@@ -8263,18 +9488,17 @@ func_mode_uninstall ()
 
 	  # Delete the libtool libraries and symlinks.
 	  for n in $library_names; do
-	    rmfiles="$rmfiles $objdir/$n"
+	    func_append rmfiles " $odir/$n"
 	  done
-	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+	  test -n "$old_library" && func_append rmfiles " $odir/$old_library"
 
-	  case "$mode" in
+	  case "$opt_mode" in
 	  clean)
-	    case "  $library_names " in
-	    # "  " in the beginning catches empty $dlname
+	    case " $library_names " in
 	    *" $dlname "*) ;;
-	    *) rmfiles="$rmfiles $objdir/$dlname" ;;
+	    *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
 	    esac
-	    test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+	    test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
 	    ;;
 	  uninstall)
 	    if test -n "$library_names"; then
@@ -8302,19 +9526,19 @@ func_mode_uninstall ()
 	  # Add PIC object to the list of files to remove.
 	  if test -n "$pic_object" &&
 	     test "$pic_object" != none; then
-	    rmfiles="$rmfiles $dir/$pic_object"
+	    func_append rmfiles " $dir/$pic_object"
 	  fi
 
 	  # Add non-PIC object to the list of files to remove.
 	  if test -n "$non_pic_object" &&
 	     test "$non_pic_object" != none; then
-	    rmfiles="$rmfiles $dir/$non_pic_object"
+	    func_append rmfiles " $dir/$non_pic_object"
 	  fi
 	fi
 	;;
 
       *)
-	if test "$mode" = clean ; then
+	if test "$opt_mode" = clean ; then
 	  noexename=$name
 	  case $file in
 	  *.exe)
@@ -8324,7 +9548,7 @@ func_mode_uninstall ()
 	    noexename=$func_stripname_result
 	    # $file with .exe has already been added to rmfiles,
 	    # add $file without .exe
-	    rmfiles="$rmfiles $file"
+	    func_append rmfiles " $file"
 	    ;;
 	  esac
 	  # Do a test to see if this is a libtool program.
@@ -8333,7 +9557,7 @@ func_mode_uninstall ()
 	      func_ltwrapper_scriptname "$file"
 	      relink_command=
 	      func_source $func_ltwrapper_scriptname_result
-	      rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
+	      func_append rmfiles " $func_ltwrapper_scriptname_result"
 	    else
 	      relink_command=
 	      func_source $dir/$noexename
@@ -8341,12 +9565,12 @@ func_mode_uninstall ()
 
 	    # note $name still contains .exe if it was in $file originally
 	    # as does the version of $file that was added into $rmfiles
-	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    func_append rmfiles " $odir/$name $odir/${name}S.${objext}"
 	    if test "$fast_install" = yes && test -n "$relink_command"; then
-	      rmfiles="$rmfiles $objdir/lt-$name"
+	      func_append rmfiles " $odir/lt-$name"
 	    fi
 	    if test "X$noexename" != "X$name" ; then
-	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	      func_append rmfiles " $odir/lt-${noexename}.c"
 	    fi
 	  fi
 	fi
@@ -8354,7 +9578,6 @@ func_mode_uninstall ()
       esac
       func_show_eval "$RM $rmfiles" 'exit_status=1'
     done
-    objdir="$origobjdir"
 
     # Try to remove the ${objdir}s in the directories where we deleted files
     for dir in $rmdirs; do
@@ -8366,16 +9589,16 @@ func_mode_uninstall ()
     exit $exit_status
 }
 
-{ test "$mode" = uninstall || test "$mode" = clean; } &&
+{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } &&
     func_mode_uninstall ${1+"$@"}
 
-test -z "$mode" && {
+test -z "$opt_mode" && {
   help="$generic_help"
   func_fatal_help "you must specify a MODE"
 }
 
 test -z "$exec_cmd" && \
-  func_fatal_help "invalid operation mode \`$mode'"
+  func_fatal_help "invalid operation mode \`$opt_mode'"
 
 if test -n "$exec_cmd"; then
   eval exec "$exec_cmd"
diff --git a/m4/acinclude.m4 b/m4/acinclude.m4
index fb741fc..454e4da 100644
--- a/m4/acinclude.m4
+++ b/m4/acinclude.m4
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: acinclude.m4 19157 2010-03-22 15:11:19Z hobu $
+dnl $Id: acinclude.m4 23370 2011-11-13 13:21:30Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure extra local definitions.
@@ -95,6 +95,15 @@ AC_DEFUN([AC_UNIX_STDIO_64],
 
   AC_MSG_CHECKING([for 64bit file io])
 
+  dnl Special case when using mingw cross compiler.
+  case "${host_os}" in
+    *mingw*)
+        with_unix_stdio_64=no
+        AC_DEFINE_UNQUOTED(VSI_STAT64,_stat64, [Define to name of 64bit stat function])
+        AC_DEFINE_UNQUOTED(VSI_STAT64_T,__stat64, [Define to name of 64bit stat structure])
+        ;;
+  esac
+
   if test x"$with_unix_stdio_64" = x"yes" ; then
     VSI_FTELL64=ftell64
     VSI_FSEEK64=fseek64
@@ -173,16 +182,18 @@ AC_DEFUN([AC_UNIX_STDIO_64],
 
     AC_CHECK_FUNC(stat64, VSI_STAT64=stat64 VSI_STAT64_T=stat64, VSI_STAT64=stat VSI_STAT64_T=stat)
     AC_CHECK_FUNC(fopen64, VSI_FOPEN64=fopen64, VSI_FOPEN64=fopen)
+    AC_CHECK_FUNC(ftruncate64, VSI_FTRUNCATE64=ftruncate64, VSI_FTRUNCATE64=ftruncate)
 
     AC_DEFINE(UNIX_STDIO_64, 1, [Define to 1 if you have fseek64, ftell64])
     AC_DEFINE(VSI_LARGE_API_SUPPORTED, 1, [Define to 1, if you have 64 bit STDIO API])
 
-    export VSI_FTELL64 VSI_FSEEK64 VSI_STAT64 VSI_STAT64_T VSI_OPEN64
+    export VSI_FTELL64 VSI_FSEEK64 VSI_STAT64 VSI_STAT64_T VSI_OPEN64 VSI_FTRUNCATE64
     AC_DEFINE_UNQUOTED(VSI_FTELL64,$VSI_FTELL64, [Define to name of 64bit ftell func])
     AC_DEFINE_UNQUOTED(VSI_FSEEK64,$VSI_FSEEK64, [Define to name of 64bit fseek func])
     AC_DEFINE_UNQUOTED(VSI_STAT64,$VSI_STAT64, [Define to name of 64bit stat function])
     AC_DEFINE_UNQUOTED(VSI_STAT64_T,$VSI_STAT64_T, [Define to name of 64bit stat structure])
     AC_DEFINE_UNQUOTED(VSI_FOPEN64,$VSI_FOPEN64, [Define to name of 64bit fopen function])
+    AC_DEFINE_UNQUOTED(VSI_FTRUNCATE64,$VSI_FTRUNCATE64, [Define to name of 64bit ftruncate function])
   else
     AC_MSG_RESULT([no])
   fi
diff --git a/m4/ax_lib_libkml.m4 b/m4/ax_lib_libkml.m4
index 7683d1a..f5d2b51 100644
--- a/m4/ax_lib_libkml.m4
+++ b/m4/ax_lib_libkml.m4
@@ -1,4 +1,4 @@
-dnl $Id: ax_lib_libkml.m4 21506 2011-01-15 19:35:36Z rouault $
+dnl $Id: ax_lib_libkml.m4 21505 2011-01-15 19:34:14Z rouault $
 dnl
 dnl @synopsis AX_LIB_LIBKML([MINIMUM-VERSION])
 dnl
@@ -31,7 +31,7 @@ dnl
 dnl @category InstalledPackages
 dnl @category Cxx
 dnl @author Mateusz Loskot <mateusz at loskot.net>
-dnl @version $Date: 2011-01-15 11:35:36 -0800 (Sat, 15 Jan 2011) $
+dnl @version $Date: 2011-01-15 11:34:14 -0800 (Sat, 15 Jan 2011) $
 dnl @license AllPermissive
 dnl          Copying and distribution of this file, with or without modification,
 dnl          are permitted in any medium without royalty provided the copyright notice and
diff --git a/m4/ax_lib_xerces.m4 b/m4/ax_lib_xerces.m4
index 8bfc044..0bd4c70 100644
--- a/m4/ax_lib_xerces.m4
+++ b/m4/ax_lib_xerces.m4
@@ -1,4 +1,4 @@
-dnl $Id: ax_lib_xerces.m4 20303 2010-08-15 10:35:05Z rouault $
+dnl $Id: ax_lib_xerces.m4 23370 2011-11-13 13:21:30Z rouault $
 dnl
 dnl @synopsis AX_LIB_XERCES([MINIMUM-VERSION])
 dnl
@@ -28,7 +28,7 @@ dnl
 dnl @category InstalledPackages
 dnl @category Cxx
 dnl @author Mateusz Loskot <mateusz at loskot.net>
-dnl @version $Date: 2010-08-15 03:35:05 -0700 (Sun, 15 Aug 2010) $
+dnl @version $Date: 2011-11-13 05:21:30 -0800 (Sun, 13 Nov 2011) $
 dnl @license AllPermissive
 dnl          Copying and distribution of this file, with or without modification,
 dnl          are permitted in any medium without royalty provided the copyright notice and
@@ -120,8 +120,8 @@ AC_DEFUN([AX_LIB_XERCES],
         saved_CPPFLAGS="$CPPFLAGS"
         CPPFLAGS="$CPPFLAGS -I$xerces_include_dir -I$xerces_include_dir2"
 
-        saved_LDFLAGS="$LDFLAGS"
-        LDFLAGS="$LDFLAGS $xerces_lib_flags"
+        saved_LIBS="$LIBS"
+        LIBS="$LIBS $xerces_lib_flags"
 
         dnl
         dnl Check Xerces headers
@@ -184,7 +184,7 @@ XMLPlatformUtils::Initialize();
         fi
 
         CPPFLAGS="$saved_CPPFLAGS"
-        LDFLAGS="$saved_LDFLAGS"
+        LIBS="$saved_LIBS"
     fi
 
     AC_MSG_CHECKING([for Xerces C++ Parser])
@@ -196,7 +196,8 @@ XMLPlatformUtils::Initialize();
             AC_SUBST([XERCES_LDFLAGS])
 
             HAVE_XERCES="yes"
-        else 
+        else
+            XERCES_CFLAGS=""
             HAVE_XERCES="no"
         fi
 
diff --git a/m4/geos.m4 b/m4/geos.m4
index bbc9dbc..386a2c8 100644
--- a/m4/geos.m4
+++ b/m4/geos.m4
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: geos.m4 13275 2007-12-06 19:00:50Z mloskot $
+dnl $Id: geos.m4 23370 2011-11-13 13:21:30Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Test for GEOS library presence
@@ -137,6 +137,10 @@ AC_DEFUN([GEOS_INIT],[
         []
       )
 
+      if test x"$HAVE_GEOS" = "xno"; then
+          GEOS_CFLAGS=""
+      fi
+
       CFLAGS="${ax_save_CFLAGS}"
       LIBS="${ax_save_LIBS}"
 
diff --git a/m4/iconv.m4 b/m4/iconv.m4
new file mode 100644
index 0000000..c8e48c7
--- /dev/null
+++ b/m4/iconv.m4
@@ -0,0 +1,273 @@
+dnl ***************************************************************************
+dnl $Id: iconv.m4 21730 2011-02-17 16:23:36Z dron $
+dnl
+dnl ***************************************************************************
+
+# iconv.m4 serial 17 (gettext-0.18.2)
+dnl Copyright (C) 2000-2002, 2007-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+  dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+  dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+  dnl those with the standalone portable GNU libiconv installed).
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+  dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed libiconv and not disabled its use
+  dnl via --without-libiconv-prefix, he wants to use it. The first
+  dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed.
+  am_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+  AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM(
+         [[
+#include <stdlib.h>
+#include <iconv.h>
+         ]],
+         [[iconv_t cd = iconv_open("","");
+           iconv(cd,NULL,NULL,NULL,NULL);
+           iconv_close(cd);]])],
+      [am_cv_func_iconv=yes])
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[
+#include <stdlib.h>
+#include <iconv.h>
+           ]],
+           [[iconv_t cd = iconv_open("","");
+             iconv(cd,NULL,NULL,NULL,NULL);
+             iconv_close(cd);]])],
+        [am_cv_lib_iconv=yes]
+        [am_cv_func_iconv=yes])
+      LIBS="$am_save_LIBS"
+    fi
+  ])
+  if test "$am_cv_func_iconv" = yes; then
+    AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
+      dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11,
+      dnl Solaris 10.
+      am_save_LIBS="$LIBS"
+      if test $am_cv_lib_iconv = yes; then
+        LIBS="$LIBS $LIBICONV"
+      fi
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#include <iconv.h>
+#include <string.h>
+int main ()
+{
+  int result = 0;
+  /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+     returns.  */
+  {
+    iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+    if (cd_utf8_to_88591 != (iconv_t)(-1))
+      {
+        static const char input[] = "\342\202\254"; /* EURO SIGN */
+        char buf[10];
+        const char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_utf8_to_88591,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 1;
+        iconv_close (cd_utf8_to_88591);
+      }
+  }
+  /* Test against Solaris 10 bug: Failures are not distinguishable from
+     successful returns.  */
+  {
+    iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
+    if (cd_ascii_to_88591 != (iconv_t)(-1))
+      {
+        static const char input[] = "\263";
+        char buf[10];
+        const char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_ascii_to_88591,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 2;
+        iconv_close (cd_ascii_to_88591);
+      }
+  }
+  /* Test against AIX 6.1..7.1 bug: Buffer overrun.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static const char input[] = "\304";
+        static char buf[2] = { (char)0xDE, (char)0xAD };
+        const char *inptr = input;
+        size_t inbytesleft = 1;
+        char *outptr = buf;
+        size_t outbytesleft = 1;
+        size_t res = iconv (cd_88591_to_utf8,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
+          result |= 4;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#if 0 /* This bug could be worked around by the caller.  */
+  /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+        char buf[50];
+        const char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_88591_to_utf8,
+                            (char **) &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if ((int)res > 0)
+          result |= 8;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#endif
+  /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+     provided.  */
+  if (/* Try standardized names.  */
+      iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+      /* Try IRIX, OSF/1 names.  */
+      && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+      /* Try AIX names.  */
+      && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+      /* Try HP-UX names.  */
+      && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+    result |= 16;
+  return result;
+}]])],
+        [am_cv_func_iconv_works=yes],
+        [am_cv_func_iconv_works=no],
+        [
+changequote(,)dnl
+         case "$host_os" in
+           aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+           *)            am_cv_func_iconv_works="guessing yes" ;;
+         esac
+changequote([,])dnl
+        ])
+      LIBS="$am_save_LIBS"
+    ])
+    case "$am_cv_func_iconv_works" in
+      *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+      *)   am_func_iconv=yes ;;
+    esac
+  else
+    am_func_iconv=no am_cv_lib_iconv=no
+  fi
+  if test "$am_func_iconv" = yes; then
+    AC_DEFINE([HAVE_ICONV], [1],
+      [Define if you have the iconv() function and it works.])
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    AC_MSG_CHECKING([how to link with libiconv])
+    AC_MSG_RESULT([$LIBICONV])
+  else
+    dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+    dnl either.
+    CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+  AC_SUBST([LIBICONV])
+  AC_SUBST([LTLIBICONV])
+])
+
+dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
+dnl avoid warnings like
+dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
+dnl This is tricky because of the way 'aclocal' is implemented:
+dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
+dnl   Otherwise aclocal's initial scan pass would miss the macro definition.
+dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
+dnl   Otherwise aclocal would emit many "Use of uninitialized value $1"
+dnl   warnings.
+m4_define([gl_iconv_AC_DEFUN],
+  m4_version_prereq([2.64],
+    [[AC_DEFUN_ONCE(
+        [$1], [$2])]],
+    [m4_ifdef([gl_00GNULIB],
+       [[AC_DEFUN_ONCE(
+           [$1], [$2])]],
+       [[AC_DEFUN(
+           [$1], [$2])]])]))
+gl_iconv_AC_DEFUN([AM_ICONV],
+[
+  AM_ICONV_LINK
+  if test "$am_cv_func_iconv" = yes; then
+    AC_MSG_CHECKING([for iconv declaration])
+    AC_CACHE_VAL([am_cv_proto_iconv], [
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+           ]],
+           [[]])],
+        [am_cv_proto_iconv_arg1=""],
+        [am_cv_proto_iconv_arg1="const"])
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+    am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    AC_MSG_RESULT([
+         $am_cv_proto_iconv])
+    AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
+      [Define as const if the declaration of iconv() needs const.])
+    dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
+    m4_ifdef([gl_ICONV_H_DEFAULTS],
+      [AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+       if test -n "$am_cv_proto_iconv_arg1"; then
+         ICONV_CONST="const"
+       fi
+      ])
+  fi
+])
diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4
new file mode 100644
index 0000000..96c4e2c
--- /dev/null
+++ b/m4/lib-ld.m4
@@ -0,0 +1,110 @@
+# lib-ld.m4 serial 3 (gettext-0.13)
+dnl Copyright (C) 1996-2003 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
+dnl with libtool.m4.
+
+dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  acl_cv_prog_gnu_ld=yes ;;
+*)
+  acl_cv_prog_gnu_ld=no ;;
+esac])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-1.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]* | [A-Za-z]:[\\/]*)]
+      [re_direlt='/[^/][^/]*/\.\./']
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(acl_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      acl_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break ;;
+      *)
+	test "$with_gnu_ld" != yes && break ;;
+      esac
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
diff --git a/m4/lib-link.m4 b/m4/lib-link.m4
new file mode 100644
index 0000000..e3d26fc
--- /dev/null
+++ b/m4/lib-link.m4
@@ -0,0 +1,709 @@
+# lib-link.m4 serial 13 (gettext-0.17)
+dnl Copyright (C) 2001-2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ(2.54)
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  define([Name],[translit([$1],[./-], [___])])
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+  AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+    AC_LIB_LINKFLAGS_BODY([$1], [$2])
+    ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+    ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+    ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+    ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
+  ])
+  LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+  LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+  INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+  LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  AC_SUBST([LIB]NAME[_PREFIX])
+  dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+  dnl results of this search when this library appears as a dependency.
+  HAVE_LIB[]NAME=yes
+  undefine([Name])
+  undefine([NAME])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. If found, it
+dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
+dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  define([Name],[translit([$1],[./-], [___])])
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+
+  dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+  dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed lib[]Name and not disabled its use
+  dnl via --without-lib[]Name-prefix, he wants to use it.
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+  AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+    ac_save_LIBS="$LIBS"
+    LIBS="$LIBS $LIB[]NAME"
+    AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
+    LIBS="$ac_save_LIBS"
+  ])
+  if test "$ac_cv_lib[]Name" = yes; then
+    HAVE_LIB[]NAME=yes
+    AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
+    AC_MSG_CHECKING([how to link with lib[]$1])
+    AC_MSG_RESULT([$LIB[]NAME])
+  else
+    HAVE_LIB[]NAME=no
+    dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+    dnl $INC[]NAME either.
+    CPPFLAGS="$ac_save_CPPFLAGS"
+    LIB[]NAME=
+    LTLIB[]NAME=
+    LIB[]NAME[]_PREFIX=
+  fi
+  AC_SUBST([HAVE_LIB]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  AC_SUBST([LIB]NAME[_PREFIX])
+  undefine([Name])
+  undefine([NAME])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl   acl_libext,
+dnl   acl_shlibext,
+dnl   acl_hardcode_libdir_flag_spec,
+dnl   acl_hardcode_libdir_separator,
+dnl   acl_hardcode_direct,
+dnl   acl_hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+  dnl Tell automake >= 1.10 to complain if config.rpath is missing.
+  m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
+  AC_REQUIRE([AC_PROG_CC])                dnl we use $CC, $GCC, $LDFLAGS
+  AC_REQUIRE([AC_LIB_PROG_LD])            dnl we use $LD, $with_gnu_ld
+  AC_REQUIRE([AC_CANONICAL_HOST])         dnl we use $host
+  AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+  AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+  ])
+  wl="$acl_cv_wl"
+  acl_libext="$acl_cv_libext"
+  acl_shlibext="$acl_cv_shlibext"
+  acl_libname_spec="$acl_cv_libname_spec"
+  acl_library_names_spec="$acl_cv_library_names_spec"
+  acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  acl_hardcode_direct="$acl_cv_hardcode_direct"
+  acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+  dnl Determine whether the user wants rpath handling at all.
+  AC_ARG_ENABLE(rpath,
+    [  --disable-rpath         do not hardcode runtime library paths],
+    :, enable_rpath=yes)
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
+dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+                               [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+  dnl Autoconf >= 2.61 supports dots in --with options.
+  define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix],
+[  --with-lib]N_A_M_E[-prefix[=DIR]  search for lib$1 in DIR/include and DIR/lib
+  --without-lib]N_A_M_E[-prefix     don't search for lib$1 in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/$acl_libdirstem"
+      fi
+    fi
+])
+  dnl Search the library and its dependencies in $additional_libdir and
+  dnl $LDFLAGS. Using breadth-first-seach.
+  LIB[]NAME=
+  LTLIB[]NAME=
+  INC[]NAME=
+  LIB[]NAME[]_PREFIX=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='$1 $2'
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+        dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+        dnl or AC_LIB_HAVE_LINKFLAGS call.
+        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+          else
+            dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+            dnl that this library doesn't exist. So just drop it.
+            :
+          fi
+        else
+          dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+          dnl and the already constructed $LIBNAME/$LTLIBNAME.
+          found_dir=
+          found_la=
+          found_so=
+          found_a=
+          eval libname=\"$acl_libname_spec\"    # typically: libname=lib$name
+          if test -n "$acl_shlibext"; then
+            shrext=".$acl_shlibext"             # typically: shrext=.so
+          else
+            shrext=
+          fi
+          if test $use_additional = yes; then
+            dir="$additional_libdir"
+            dnl The same code as in the loop below:
+            dnl First look for a shared library.
+            if test -n "$acl_shlibext"; then
+              if test -f "$dir/$libname$shrext"; then
+                found_dir="$dir"
+                found_so="$dir/$libname$shrext"
+              else
+                if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                  ver=`(cd "$dir" && \
+                        for f in "$libname$shrext".*; do echo "$f"; done \
+                        | sed -e "s,^$libname$shrext\\\\.,," \
+                        | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                        | sed 1q ) 2>/dev/null`
+                  if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                    found_dir="$dir"
+                    found_so="$dir/$libname$shrext.$ver"
+                  fi
+                else
+                  eval library_names=\"$acl_library_names_spec\"
+                  for f in $library_names; do
+                    if test -f "$dir/$f"; then
+                      found_dir="$dir"
+                      found_so="$dir/$f"
+                      break
+                    fi
+                  done
+                fi
+              fi
+            fi
+            dnl Then look for a static library.
+            if test "X$found_dir" = "X"; then
+              if test -f "$dir/$libname.$acl_libext"; then
+                found_dir="$dir"
+                found_a="$dir/$libname.$acl_libext"
+              fi
+            fi
+            if test "X$found_dir" != "X"; then
+              if test -f "$dir/$libname.la"; then
+                found_la="$dir/$libname.la"
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIB[]NAME; do
+              AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  dnl First look for a shared library.
+                  if test -n "$acl_shlibext"; then
+                    if test -f "$dir/$libname$shrext"; then
+                      found_dir="$dir"
+                      found_so="$dir/$libname$shrext"
+                    else
+                      if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                        ver=`(cd "$dir" && \
+                              for f in "$libname$shrext".*; do echo "$f"; done \
+                              | sed -e "s,^$libname$shrext\\\\.,," \
+                              | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                              | sed 1q ) 2>/dev/null`
+                        if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                          found_dir="$dir"
+                          found_so="$dir/$libname$shrext.$ver"
+                        fi
+                      else
+                        eval library_names=\"$acl_library_names_spec\"
+                        for f in $library_names; do
+                          if test -f "$dir/$f"; then
+                            found_dir="$dir"
+                            found_so="$dir/$f"
+                            break
+                          fi
+                        done
+                      fi
+                    fi
+                  fi
+                  dnl Then look for a static library.
+                  if test "X$found_dir" = "X"; then
+                    if test -f "$dir/$libname.$acl_libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/$libname.$acl_libext"
+                    fi
+                  fi
+                  if test "X$found_dir" != "X"; then
+                    if test -f "$dir/$libname.la"; then
+                      found_la="$dir/$libname.la"
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+            dnl Found the library.
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+              dnl Linking with a shared library. We attempt to hardcode its
+              dnl directory into the executable's runpath, unless it's the
+              dnl standard /usr/lib.
+              if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
+                dnl No hardcoding is needed.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+              else
+                dnl Use an explicit option to hardcode DIR into the resulting
+                dnl binary.
+                dnl Potentially add DIR to ltrpathdirs.
+                dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                dnl The hardcoding into $LIBNAME is system dependent.
+                if test "$acl_hardcode_direct" = yes; then
+                  dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+                  dnl resulting binary.
+                  LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                else
+                  if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+                    dnl Use an explicit option to hardcode DIR into the resulting
+                    dnl binary.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    dnl Potentially add DIR to rpathdirs.
+                    dnl The rpathdirs will be appended to $LIBNAME at the end.
+                    haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                    dnl Rely on "-L$found_dir".
+                    dnl But don't add it if it's already contained in the LDFLAGS
+                    dnl or the already constructed $LIBNAME
+                    haveit=
+                    for x in $LDFLAGS $LIB[]NAME; do
+                      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+                    fi
+                    if test "$acl_hardcode_minus_L" != no; then
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    else
+                      dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
+                      dnl here, because this doesn't fit in flags passed to the
+                      dnl compiler. So give up. No hardcoding. This affects only
+                      dnl very old systems.
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                dnl Linking with a static library.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+              else
+                dnl We shouldn't come here, but anyway it's good to have a
+                dnl fallback.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+              fi
+            fi
+            dnl Assume the include files are nearby.
+            additional_includedir=
+            case "$found_dir" in
+              */$acl_libdirstem | */$acl_libdirstem/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+                LIB[]NAME[]_PREFIX="$basedir"
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+              dnl Potentially add $additional_includedir to $INCNAME.
+              dnl But don't add it
+              dnl   1. if it's the standard /usr/include,
+              dnl   2. if it's /usr/local/include and we are using GCC on Linux,
+              dnl   3. if it's already present in $CPPFLAGS or the already
+              dnl      constructed $INCNAME,
+              dnl   4. if it doesn't exist as a directory.
+              if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INC[]NAME; do
+                    AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                      dnl Really add $additional_includedir to $INCNAME.
+                      INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+            dnl Look for dependencies.
+            if test -n "$found_la"; then
+              dnl Read the .la file. It defines the variables
+              dnl dlname, library_names, old_library, dependency_libs, current,
+              dnl age, revision, installed, dlopen, dlpreopen, libdir.
+              save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+              dnl We use only dependency_libs.
+              for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                    dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+                    dnl But don't add it
+                    dnl   1. if it's the standard /usr/lib,
+                    dnl   2. if it's /usr/local/lib and we are using GCC on Linux,
+                    dnl   3. if it's already present in $LDFLAGS or the already
+                    dnl      constructed $LIBNAME,
+                    dnl   4. if it doesn't exist as a directory.
+                    if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LIBNAME.
+                            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LTLIBNAME.
+                            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -R*)
+                    dir=`echo "X$dep" | sed -e 's/^X-R//'`
+                    if test "$enable_rpath" != no; then
+                      dnl Potentially add DIR to rpathdirs.
+                      dnl The rpathdirs will be appended to $LIBNAME at the end.
+                      haveit=
+                      for x in $rpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        rpathdirs="$rpathdirs $dir"
+                      fi
+                      dnl Potentially add DIR to ltrpathdirs.
+                      dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                      haveit=
+                      for x in $ltrpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        ltrpathdirs="$ltrpathdirs $dir"
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                    dnl Handle this in the next round.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                    dnl Handle this in the next round. Throw away the .la's
+                    dnl directory; it is already contained in a preceding -L
+                    dnl option.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                    dnl Most likely an immediate library name.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+                    LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+            dnl Didn't find the library; assume it is in the system directories
+            dnl known to the linker and runtime loader. (All the system
+            dnl directories known to the linker should also be known to the
+            dnl runtime loader, otherwise the system is severely misconfigured.)
+            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$acl_hardcode_libdir_separator"; then
+      dnl Weird platform: only the last -rpath option counts, the user must
+      dnl pass all path elements in one option. We can arrange that for a
+      dnl single library, but not when more than one $LIBNAMEs are used.
+      alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+      done
+      dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
+      acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$acl_hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+    else
+      dnl The -rpath options are cumulative.
+      for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$acl_hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+    dnl When using libtool, the option that works for both libraries and
+    dnl executables is -R. The -R options are cumulative.
+    for found_dir in $ltrpathdirs; do
+      LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+    done
+  fi
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+  for element in [$2]; do
+    haveit=
+    for x in $[$1]; do
+      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      [$1]="${[$1]}${[$1]:+ }$element"
+    fi
+  done
+])
+
+dnl For those cases where a variable contains several -L and -l options
+dnl referring to unknown libraries and directories, this macro determines the
+dnl necessary additional linker options for the runtime path.
+dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
+dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
+dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
+dnl otherwise linking without libtool is assumed.
+AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
+[
+  AC_REQUIRE([AC_LIB_RPATH])
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  $1=
+  if test "$enable_rpath" != no; then
+    if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+      dnl Use an explicit option to hardcode directories into the resulting
+      dnl binary.
+      rpathdirs=
+      next=
+      for opt in $2; do
+        if test -n "$next"; then
+          dir="$next"
+          dnl No need to hardcode the standard /usr/lib.
+          if test "X$dir" != "X/usr/$acl_libdirstem"; then
+            rpathdirs="$rpathdirs $dir"
+          fi
+          next=
+        else
+          case $opt in
+            -L) next=yes ;;
+            -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
+                 dnl No need to hardcode the standard /usr/lib.
+                 if test "X$dir" != "X/usr/$acl_libdirstem"; then
+                   rpathdirs="$rpathdirs $dir"
+                 fi
+                 next= ;;
+            *) next= ;;
+          esac
+        fi
+      done
+      if test "X$rpathdirs" != "X"; then
+        if test -n ""$3""; then
+          dnl libtool is used for linking. Use -R options.
+          for dir in $rpathdirs; do
+            $1="${$1}${$1:+ }-R$dir"
+          done
+        else
+          dnl The linker is used for linking directly.
+          if test -n "$acl_hardcode_libdir_separator"; then
+            dnl Weird platform: only the last -rpath option counts, the user
+            dnl must pass all path elements in one option.
+            alldirs=
+            for dir in $rpathdirs; do
+              alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
+            done
+            acl_save_libdir="$libdir"
+            libdir="$alldirs"
+            eval flag=\"$acl_hardcode_libdir_flag_spec\"
+            libdir="$acl_save_libdir"
+            $1="$flag"
+          else
+            dnl The -rpath options are cumulative.
+            for dir in $rpathdirs; do
+              acl_save_libdir="$libdir"
+              libdir="$dir"
+              eval flag=\"$acl_hardcode_libdir_flag_spec\"
+              libdir="$acl_save_libdir"
+              $1="${$1}${$1:+ }$flag"
+            done
+          fi
+        fi
+      fi
+    fi
+  fi
+  AC_SUBST([$1])
+])
diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4
new file mode 100644
index 0000000..a8684e1
--- /dev/null
+++ b/m4/lib-prefix.m4
@@ -0,0 +1,185 @@
+# lib-prefix.m4 serial 5 (gettext-0.15)
+dnl Copyright (C) 2001-2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+  AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_LIB_ARG_WITH([lib-prefix],
+[  --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+  --without-lib-prefix    don't search for libraries in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/$acl_libdirstem"
+      fi
+    fi
+])
+  if test $use_additional = yes; then
+    dnl Potentially add $additional_includedir to $CPPFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/include,
+    dnl   2. if it's already present in $CPPFLAGS,
+    dnl   3. if it's /usr/local/include and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_includedir" != "X/usr/include"; then
+      haveit=
+      for x in $CPPFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-I$additional_includedir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_includedir" = "X/usr/local/include"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_includedir"; then
+            dnl Really add $additional_includedir to $CPPFLAGS.
+            CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+          fi
+        fi
+      fi
+    fi
+    dnl Potentially add $additional_libdir to $LDFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/lib,
+    dnl   2. if it's already present in $LDFLAGS,
+    dnl   3. if it's /usr/local/lib and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+      haveit=
+      for x in $LDFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-L$additional_libdir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux*) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_libdir"; then
+            dnl Really add $additional_libdir to $LDFLAGS.
+            LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+          fi
+        fi
+      fi
+    fi
+  fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+  dnl Unfortunately, prefix and exec_prefix get only finally determined
+  dnl at the end of configure.
+  if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  $1
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing
+dnl the basename of the libdir, either "lib" or "lib64".
+AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
+[
+  dnl There is no formal standard regarding lib and lib64. The current
+  dnl practice is that on a system supporting 32-bit and 64-bit instruction
+  dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit
+  dnl libraries go under $prefix/lib. We determine the compiler's default
+  dnl mode by looking at the compiler's library search path. If at least
+  dnl of its elements ends in /lib64 or points to a directory whose absolute
+  dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the
+  dnl default, namely "lib".
+  acl_libdirstem=lib
+  searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+  if test -n "$searchpath"; then
+    acl_save_IFS="${IFS= 	}"; IFS=":"
+    for searchdir in $searchpath; do
+      if test -d "$searchdir"; then
+        case "$searchdir" in
+          */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+          *) searchdir=`cd "$searchdir" && pwd`
+             case "$searchdir" in
+               */lib64 ) acl_libdirstem=lib64 ;;
+             esac ;;
+        esac
+      fi
+    done
+    IFS="$acl_save_IFS"
+  fi
+])
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 1e7ea47..d812584 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -1,7 +1,8 @@
 # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
 #
 #   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#                 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
+#                 Inc.
 #   Written by Gordon Matzigkeit, 1996
 #
 # This file is free software; the Free Software Foundation gives
@@ -10,7 +11,8 @@
 
 m4_define([_LT_COPYING], [dnl
 #   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#                 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
+#                 Inc.
 #   Written by Gordon Matzigkeit, 1996
 #
 #   This file is part of GNU Libtool.
@@ -37,7 +39,7 @@ m4_define([_LT_COPYING], [dnl
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 ])
 
-# serial 56 LT_INIT
+# serial 57 LT_INIT
 
 
 # LT_PREREQ(VERSION)
@@ -66,6 +68,7 @@ esac
 # ------------------
 AC_DEFUN([LT_INIT],
 [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
 AC_BEFORE([$0], [LT_LANG])dnl
 AC_BEFORE([$0], [LT_OUTPUT])dnl
 AC_BEFORE([$0], [LTDL_INIT])dnl
@@ -82,6 +85,8 @@ AC_REQUIRE([LTVERSION_VERSION])dnl
 AC_REQUIRE([LTOBSOLETE_VERSION])dnl
 m4_require([_LT_PROG_LTMAIN])dnl
 
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
 dnl Parse OPTIONS
 _LT_SET_OPTIONS([$0], [$1])
 
@@ -118,7 +123,7 @@ m4_defun([_LT_CC_BASENAME],
     *) break;;
   esac
 done
-cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
 ])
 
 
@@ -138,6 +143,9 @@ m4_defun([_LT_FILEUTILS_DEFAULTS],
 m4_defun([_LT_SETUP],
 [AC_REQUIRE([AC_CANONICAL_HOST])dnl
 AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
 _LT_DECL([], [host_alias], [0], [The host system])dnl
 _LT_DECL([], [host], [0])dnl
 _LT_DECL([], [host_os], [0])dnl
@@ -160,10 +168,13 @@ _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
 dnl
 m4_require([_LT_FILEUTILS_DEFAULTS])dnl
 m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
 m4_require([_LT_CMD_RELOAD])dnl
 m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
 m4_require([_LT_CMD_OLD_ARCHIVE])dnl
 m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
 
 _LT_CONFIG_LIBTOOL_INIT([
 # See if we are running on zsh, and set the options which allow our
@@ -179,7 +190,6 @@ fi
 _LT_CHECK_OBJDIR
 
 m4_require([_LT_TAG_COMPILER])dnl
-_LT_PROG_ECHO_BACKSLASH
 
 case $host_os in
 aix3*)
@@ -193,23 +203,6 @@ aix3*)
   ;;
 esac
 
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([["`\\]]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to delay expansion of an escaped single quote.
-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
 # Global variables:
 ofile=libtool
 can_build_shared=yes
@@ -250,6 +243,28 @@ _LT_CONFIG_COMMANDS
 ])# _LT_SETUP
 
 
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
 # _LT_PROG_LTMAIN
 # ---------------
 # Note that this code is called both from `configure', and `config.status'
@@ -408,7 +423,7 @@ m4_define([_lt_decl_all_varnames],
 # declaration there will have the same value as in `configure'.  VARNAME
 # must have a single quote delimited value for this to work.
 m4_define([_LT_CONFIG_STATUS_DECLARE],
-[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
 
 
 # _LT_CONFIG_STATUS_DECLARATIONS
@@ -418,7 +433,7 @@ m4_define([_LT_CONFIG_STATUS_DECLARE],
 # embedded single quotes properly.  In configure, this macro expands
 # each variable declared with _LT_DECL (and _LT_TAGDECL) into:
 #
-#    <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
+#    <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
 m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
 [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
     [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
@@ -517,12 +532,20 @@ LTCC='$LTCC'
 LTCFLAGS='$LTCFLAGS'
 compiler='$compiler_DEFAULT'
 
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
 # Quote evaled strings.
 for var in lt_decl_all_varnames([[ \
 ]], lt_decl_quote_varnames); do
-    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
     *[[\\\\\\\`\\"\\\$]]*)
-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
       ;;
     *)
       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
@@ -533,9 +556,9 @@ done
 # Double-quote double-evaled strings.
 for var in lt_decl_all_varnames([[ \
 ]], lt_decl_dquote_varnames); do
-    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
     *[[\\\\\\\`\\"\\\$]]*)
-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
       ;;
     *)
       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
@@ -543,16 +566,38 @@ for var in lt_decl_all_varnames([[ \
     esac
 done
 
-# Fix-up fallback echo if it was mangled by the above quoting rules.
-case \$lt_ECHO in
-*'\\\[$]0 --fallback-echo"')dnl "
-  lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
-  ;;
-esac
-
 _LT_OUTPUT_LIBTOOL_INIT
 ])
 
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable.  If COMMENT is supplied, it is inserted after the
+# `#!' sequence but before initialization text begins.  After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script.  The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test $lt_write_fail = 0 && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
 
 # LT_OUTPUT
 # ---------
@@ -562,20 +607,11 @@ _LT_OUTPUT_LIBTOOL_INIT
 AC_DEFUN([LT_OUTPUT],
 [: ${CONFIG_LT=./config.lt}
 AC_MSG_NOTICE([creating $CONFIG_LT])
-cat >"$CONFIG_LT" <<_LTEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate a libtool stub with the current configuration.
-
-lt_cl_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_LTEOF
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
 
 cat >>"$CONFIG_LT" <<\_LTEOF
-AS_SHELL_SANITIZE
-_AS_PREPARE
-
-exec AS_MESSAGE_FD>&1
+lt_cl_silent=false
 exec AS_MESSAGE_LOG_FD>>config.log
 {
   echo
@@ -601,7 +637,7 @@ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
 m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
 configured by $[0], generated by m4_PACKAGE_STRING.
 
-Copyright (C) 2008 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
 This config.lt script is free software; the Free Software Foundation
 gives unlimited permision to copy, distribute and modify it."
 
@@ -646,15 +682,13 @@ chmod +x "$CONFIG_LT"
 # appending to config.log, which fails on DOS, as config.log is still kept
 # open by configure.  Here we exec the FD to /dev/null, effectively closing
 # config.log, so it can be properly (re)opened and appended to by config.lt.
-if test "$no_create" != yes; then
-  lt_cl_success=:
-  test "$silent" = yes &&
-    lt_config_lt_args="$lt_config_lt_args --quiet"
-  exec AS_MESSAGE_LOG_FD>/dev/null
-  $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
-  exec AS_MESSAGE_LOG_FD>>config.log
-  $lt_cl_success || AS_EXIT(1)
-fi
+lt_cl_success=:
+test "$silent" = yes &&
+  lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
 ])# LT_OUTPUT
 
 
@@ -717,15 +751,12 @@ _LT_EOF
   # if finds mixed CR/LF and LF-only lines.  Since sed operates in
   # text mode, it properly converts lines to CR/LF.  This bash problem
   # is reportedly fixed, but why not run on old versions too?
-  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
-    || (rm -f "$cfgfile"; exit 1)
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
 
-  _LT_PROG_XSI_SHELLFNS
+  _LT_PROG_REPLACE_SHELLFNS
 
-  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
-    || (rm -f "$cfgfile"; exit 1)
-
-  mv -f "$cfgfile" "$ofile" ||
+   mv -f "$cfgfile" "$ofile" ||
     (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
   chmod +x "$ofile"
 ],
@@ -831,11 +862,13 @@ AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
 AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
 AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
 AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
 dnl aclocal-1.4 backwards compatibility:
 dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
 dnl AC_DEFUN([AC_LIBTOOL_F77], [])
 dnl AC_DEFUN([AC_LIBTOOL_FC], [])
 dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
 
 
 # _LT_TAG_COMPILER
@@ -940,6 +973,31 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
 	[lt_cv_ld_exported_symbols_list=no])
 	LDFLAGS="$save_LDFLAGS"
     ])
+    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+      [lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+      echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&AS_MESSAGE_LOG_FD
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+    ])
     case $host_os in
     rhapsody* | darwin1.[[012]])
       _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
@@ -967,7 +1025,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
     else
       _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
     fi
-    if test "$DSYMUTIL" != ":"; then
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
       _lt_dsymutil='~$DSYMUTIL $lib || :'
     else
       _lt_dsymutil=
@@ -987,7 +1045,11 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES],
   _LT_TAGVAR(hardcode_direct, $1)=no
   _LT_TAGVAR(hardcode_automatic, $1)=yes
   _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
-  _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+  else
+    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  fi
   _LT_TAGVAR(link_all_deplibs, $1)=yes
   _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
   case $cc_basename in
@@ -995,7 +1057,7 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES],
      *) _lt_dar_can_shared=$GCC ;;
   esac
   if test "$_lt_dar_can_shared" = "yes"; then
-    output_verbose_link_cmd=echo
+    output_verbose_link_cmd=func_echo_all
     _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
     _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
     _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
@@ -1011,203 +1073,142 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES],
   fi
 ])
 
-# _LT_SYS_MODULE_PATH_AIX
-# -----------------------
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
 # Links a minimal program and checks the executable
 # for the system default hardcoded library path. In most cases,
 # this is /usr/lib:/lib, but when the MPI compilers are used
 # the location of the communication and MPI libs are included too.
 # If we don't find anything, use the default library path according
 # to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
 m4_defun([_LT_SYS_MODULE_PATH_AIX],
 [m4_require([_LT_DECL_SED])dnl
-AC_LINK_IFELSE(AC_LANG_PROGRAM,[
-lt_aix_libpath_sed='
-    /Import File Strings/,/^$/ {
-	/^0/ {
-	    s/^0  *\(.*\)$/\1/
-	    p
-	}
-    }'
-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-# Check for a 64-bit object if we didn't find anything.
-if test -z "$aix_libpath"; then
-  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-fi],[])
-if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+  lt_aix_libpath_sed='[
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }]'
+  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi],[])
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib"
+  fi
+  ])
+  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
 ])# _LT_SYS_MODULE_PATH_AIX
 
 
 # _LT_SHELL_INIT(ARG)
 # -------------------
 m4_define([_LT_SHELL_INIT],
-[ifdef([AC_DIVERSION_NOTICE],
-	     [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
-	 [AC_DIVERT_PUSH(NOTICE)])
-$1
-AC_DIVERT_POP
-])# _LT_SHELL_INIT
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
 
 
 # _LT_PROG_ECHO_BACKSLASH
 # -----------------------
-# Add some code to the start of the generated configure script which
-# will find an echo command which doesn't interpret backslashes.
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script which will find a shell with a builtin
+# printf (which we can use as an echo command).
 m4_defun([_LT_PROG_ECHO_BACKSLASH],
-[_LT_SHELL_INIT([
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-case X$lt_ECHO in
-X*--fallback-echo)
-  # Remove one level of quotation (which was required for Make).
-  ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
-  ;;
-esac
-
-ECHO=${lt_ECHO-echo}
-if test "X[$]1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X[$]1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
-  # Yippee, $ECHO works!
-  :
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
 else
-  # Restart under the correct shell.
-  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
-fi
-
-if test "X[$]1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<_LT_EOF
-[$]*
-_LT_EOF
-  exit 0
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
 fi
 
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-if test -z "$lt_ECHO"; then
-  if test "X${echo_test_string+set}" != Xset; then
-    # find a string as large as possible, as long as the shell can cope with it
-    for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
-      # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-      if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
-	 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
-      then
-        break
-      fi
-    done
-  fi
-
-  if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
-     echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
-     test "X$echo_testing_string" = "X$echo_test_string"; then
-    :
-  else
-    # The Solaris, AIX, and Digital Unix default echo programs unquote
-    # backslashes.  This makes it impossible to quote backslashes using
-    #   echo "$something" | sed 's/\\/\\\\/g'
-    #
-    # So, first we look for a working echo in the user's PATH.
-
-    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-    for dir in $PATH /usr/ucb; do
-      IFS="$lt_save_ifs"
-      if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
-         test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
-         echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
-         test "X$echo_testing_string" = "X$echo_test_string"; then
-        ECHO="$dir/echo"
-        break
-      fi
-    done
-    IFS="$lt_save_ifs"
-
-    if test "X$ECHO" = Xecho; then
-      # We didn't find a better echo, so look for alternatives.
-      if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
-         echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
-         test "X$echo_testing_string" = "X$echo_test_string"; then
-        # This shell has a builtin print -r that does the trick.
-        ECHO='print -r'
-      elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
-	   test "X$CONFIG_SHELL" != X/bin/ksh; then
-        # If we have ksh, try running configure again with it.
-        ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
-        export ORIGINAL_CONFIG_SHELL
-        CONFIG_SHELL=/bin/ksh
-        export CONFIG_SHELL
-        exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
-      else
-        # Try using printf.
-        ECHO='printf %s\n'
-        if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
-	   echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
-	   test "X$echo_testing_string" = "X$echo_test_string"; then
-	  # Cool, printf works
-	  :
-        elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
-	     test "X$echo_testing_string" = 'X\t' &&
-	     echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
-	     test "X$echo_testing_string" = "X$echo_test_string"; then
-	  CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
-	  export CONFIG_SHELL
-	  SHELL="$CONFIG_SHELL"
-	  export SHELL
-	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
-        elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
-	     test "X$echo_testing_string" = 'X\t' &&
-	     echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
-	     test "X$echo_testing_string" = "X$echo_test_string"; then
-	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
-        else
-	  # maybe with a smaller string...
-	  prev=:
-
-	  for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
-	    if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
-	    then
-	      break
-	    fi
-	    prev="$cmd"
-	  done
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*" 
+}
 
-	  if test "$prev" != 'sed 50q "[$]0"'; then
-	    echo_test_string=`eval $prev`
-	    export echo_test_string
-	    exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
-	  else
-	    # Oops.  We lost completely, so just stick with echo.
-	    ECHO=echo
-	  fi
-        fi
-      fi
-    fi
-  fi
-fi
+case "$ECHO" in
+  printf*) AC_MSG_RESULT([printf]) ;;
+  print*) AC_MSG_RESULT([print -r]) ;;
+  *) AC_MSG_RESULT([cat]) ;;
+esac
 
-# Copy echo and quote the copy suitably for passing to libtool from
-# the Makefile, instead of quoting the original, which is used later.
-lt_ECHO=$ECHO
-if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
-   lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
-fi
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test "X`printf %s $ECHO`" = "X$ECHO" \
+      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
 
-AC_SUBST(lt_ECHO)
-])
 _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
-_LT_DECL([], [ECHO], [1],
-    [An echo program that does not interpret backslashes])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
 ])# _LT_PROG_ECHO_BACKSLASH
 
 
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[  --with-sysroot[=DIR] Search for dependent libraries within DIR
+                        (or the compiler's sysroot if not specified).],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted.  We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+   if test "$GCC" = yes; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   AC_MSG_RESULT([${with_sysroot}])
+   AC_MSG_ERROR([The sysroot must be an absolute path.])
+   ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and in which our libraries should be installed.])])
+
 # _LT_ENABLE_LOCK
 # ---------------
 m4_defun([_LT_ENABLE_LOCK],
@@ -1236,7 +1237,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
     if test "$lt_cv_prog_gnu_ld" = yes; then
       case `/usr/bin/file conftest.$ac_objext` in
@@ -1354,14 +1355,47 @@ need_locks="$enable_libtool_lock"
 ])# _LT_ENABLE_LOCK
 
 
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+  [lt_cv_ar_at_file=no
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+     [echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+      AC_TRY_EVAL([lt_ar_try])
+      if test "$ac_status" -eq 0; then
+	# Ensure the archiver fails upon bogus file names.
+	rm -f conftest.$ac_objext libconftest.a
+	AC_TRY_EVAL([lt_ar_try])
+	if test "$ac_status" -ne 0; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+     ])
+  ])
+
+if test "x$lt_cv_ar_at_file" = xno; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+  [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
 # _LT_CMD_OLD_ARCHIVE
 # -------------------
 m4_defun([_LT_CMD_OLD_ARCHIVE],
-[AC_CHECK_TOOL(AR, ar, false)
-test -z "$AR" && AR=ar
-test -z "$AR_FLAGS" && AR_FLAGS=cru
-_LT_DECL([], [AR], [1], [The archiver])
-_LT_DECL([], [AR_FLAGS], [1])
+[_LT_PROG_AR
 
 AC_CHECK_TOOL(STRIP, strip, :)
 test -z "$STRIP" && STRIP=:
@@ -1388,10 +1422,19 @@ if test -n "$RANLIB"; then
   esac
   old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
 fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
 _LT_DECL([], [old_postinstall_cmds], [2])
 _LT_DECL([], [old_postuninstall_cmds], [2])
 _LT_TAGDECL([], [old_archive_cmds], [2],
     [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+    [Whether to use a lock for old archive extraction])
 ])# _LT_CMD_OLD_ARCHIVE
 
 
@@ -1416,15 +1459,15 @@ AC_CACHE_CHECK([$1], [$2],
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&AS_MESSAGE_LOG_FD
-   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
        $2=yes
@@ -1464,7 +1507,7 @@ AC_CACHE_CHECK([$1], [$2],
      if test -s conftest.err; then
        # Append any errors to the config.log.
        cat conftest.err 1>&AS_MESSAGE_LOG_FD
-       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
        if diff conftest.exp conftest.er2 >/dev/null; then
          $2=yes
@@ -1527,6 +1570,11 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
     lt_cv_sys_max_cmd_len=8192;
     ;;
 
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
   amigaos*)
     # On AmigaOS with pdksh, this test takes hours, literally.
     # So we just punt and use a minimum line length of 8192.
@@ -1591,8 +1639,8 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
       # If test is not a shell built-in, we'll probably end up computing a
       # maximum length that is only half of the actual maximum length, but
       # we can't tell.
-      while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
-	         = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+      while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
 	      test $i != 17 # 1/2 MB should be enough
       do
         i=`expr $i + 1`
@@ -1643,7 +1691,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-[#line __oline__ "configure"
+[#line $LINENO "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -1684,7 +1732,13 @@ else
 #  endif
 #endif
 
-void fnord() { int i=42;}
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
 int main ()
 {
   void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
@@ -1693,7 +1747,11 @@ int main ()
   if (self)
     {
       if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
-      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
       /* dlclose (self); */
     }
   else
@@ -1869,16 +1927,16 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&AS_MESSAGE_LOG_FD
-   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
-     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
        _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
@@ -2037,6 +2095,7 @@ m4_require([_LT_DECL_EGREP])dnl
 m4_require([_LT_FILEUTILS_DEFAULTS])dnl
 m4_require([_LT_DECL_OBJDUMP])dnl
 m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
 AC_MSG_CHECKING([dynamic linker characteristics])
 m4_if([$1],
 	[], [
@@ -2045,16 +2104,23 @@ if test "$GCC" = yes; then
     darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
     *) lt_awk_arg="/^libraries:/" ;;
   esac
-  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
-  if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
     # if the path contains ";" then we assume it to be the separator
     # otherwise default to the standard path separator (i.e. ":") - it is
     # assumed that no part of a normal pathname contains ";" but that should
     # okay in the real world where ";" in dirpaths is itself problematic.
-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
-  else
-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
-  fi
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
   # Ok, now we have the path, separated by spaces, we can step through it
   # and add multilib dir if necessary.
   lt_tmp_lt_search_path_spec=
@@ -2067,7 +2133,7 @@ if test "$GCC" = yes; then
 	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
     fi
   done
-  lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
 BEGIN {RS=" "; FS="/|\n";} {
   lt_foo="";
   lt_count=0;
@@ -2087,7 +2153,13 @@ BEGIN {RS=" "; FS="/|\n";} {
   if (lt_foo != "") { lt_freq[[lt_foo]]++; }
   if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
 }'`
-  sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([[A-Za-z]]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
 else
   sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
 fi])
@@ -2175,7 +2247,7 @@ amigaos*)
   m68k)
     library_names_spec='$libname.ixlibrary $libname.a'
     # Create ${libname}_ixlibrary.a entries in /sys/libs.
-    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
     ;;
   esac
   ;;
@@ -2206,8 +2278,9 @@ cygwin* | mingw* | pw32* | cegcc*)
   need_version=no
   need_lib_prefix=no
 
-  case $GCC,$host_os in
-  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
     library_names_spec='$libname.dll.a'
     # DLL is installed to $(libdir)/../bin by postinstall_cmds
     postinstall_cmds='base_file=`basename \${file}`~
@@ -2228,36 +2301,83 @@ cygwin* | mingw* | pw32* | cegcc*)
     cygwin*)
       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
       soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
-      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+m4_if([$1], [],[
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
       ;;
     mingw* | cegcc*)
       # MinGW DLLs use traditional 'lib' prefix
       soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
-      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
-      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
-        # It is most probably a Windows format PATH printed by
-        # mingw gcc, but we are running on Cygwin. Gcc prints its search
-        # path with ; separators, and with drive letters. We can handle the
-        # drive letters (cygwin fileutils understands them), so leave them,
-        # especially as we might pass files found there to a mingw objdump,
-        # which wouldn't understand a cygwinified path. Ahh.
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
-      else
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
-      fi
       ;;
     pw32*)
       # pw32 DLLs use 'pw' prefix rather than 'lib'
       library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
       ;;
     esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
     ;;
 
   *)
+    # Assume MSVC wrapper
     library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
     ;;
   esac
-  dynamic_linker='Win32 ld.exe'
   # FIXME: first we should search . and the directory the executable is in
   shlibpath_var=PATH
   ;;
@@ -2344,6 +2464,19 @@ gnu*)
   hardcode_into_libs=yes
   ;;
 
+haiku*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
 hpux9* | hpux10* | hpux11*)
   # Give a soname corresponding to the major version so that dld.sl refuses to
   # link against other versions.
@@ -2386,8 +2519,10 @@ hpux9* | hpux10* | hpux11*)
     soname_spec='${libname}${release}${shared_ext}$major'
     ;;
   esac
-  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
   postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
   ;;
 
 interix[[3-9]]*)
@@ -2445,7 +2580,7 @@ linux*oldld* | linux*aout* | linux*coff*)
   ;;
 
 # This must be Linux ELF.
-linux* | k*bsd*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
   version_type=linux
   need_lib_prefix=no
   need_version=no
@@ -2454,16 +2589,21 @@ linux* | k*bsd*-gnu)
   finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
   shlibpath_var=LD_LIBRARY_PATH
   shlibpath_overrides_runpath=no
+
   # Some binutils ld are patched to set DT_RUNPATH
-  save_LDFLAGS=$LDFLAGS
-  save_libdir=$libdir
-  eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
-       LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
-  AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
-    [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
-       [shlibpath_overrides_runpath=yes])])
-  LDFLAGS=$save_LDFLAGS
-  libdir=$save_libdir
+  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+    [lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+	 LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+	 [lt_cv_shlibpath_overrides_runpath=yes])])
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+    ])
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
 
   # This implies no fast_install, which is unacceptable.
   # Some rework will be needed to allow for fast_install
@@ -2472,7 +2612,7 @@ linux* | k*bsd*-gnu)
 
   # Append ld.so.conf contents to the search path
   if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
     sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
   fi
 
@@ -2485,18 +2625,6 @@ linux* | k*bsd*-gnu)
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -2717,6 +2845,8 @@ _LT_DECL([], [library_names_spec], [1],
     The last name is the one that the linker finds with -lNAME]])
 _LT_DECL([], [soname_spec], [1],
     [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+    [Permission mode override for installation of shared libraries])
 _LT_DECL([], [postinstall_cmds], [2],
     [Command to use after installation of a shared archive])
 _LT_DECL([], [postuninstall_cmds], [2],
@@ -2829,6 +2959,7 @@ AC_REQUIRE([AC_CANONICAL_HOST])dnl
 AC_REQUIRE([AC_CANONICAL_BUILD])dnl
 m4_require([_LT_DECL_SED])dnl
 m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
 
 AC_ARG_WITH([gnu-ld],
     [AS_HELP_STRING([--with-gnu-ld],
@@ -2950,6 +3081,11 @@ case $reload_flag in
 esac
 reload_cmds='$LD$reload_flag -o $output$reload_objs'
 case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test "$GCC" != yes; then
+      reload_cmds=false
+    fi
+    ;;
   darwin*)
     if test "$GCC" = yes; then
       reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
@@ -2958,8 +3094,8 @@ case $host_os in
     fi
     ;;
 esac
-_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
-_LT_DECL([], [reload_cmds], [2])dnl
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
 ])# _LT_CMD_RELOAD
 
 
@@ -3011,16 +3147,18 @@ mingw* | pw32*)
   # Base MSYS/MinGW do not provide the 'file' command needed by
   # func_win32_libid shell function, so use a weaker test based on 'objdump',
   # unless we find 'file', for example because we are cross-compiling.
-  if ( file / ) >/dev/null 2>&1; then
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
     lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
     lt_cv_file_magic_cmd='func_win32_libid'
   else
-    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
     lt_cv_file_magic_cmd='$OBJDUMP -f'
   fi
   ;;
 
-cegcc)
+cegcc*)
   # use the weaker test based on 'objdump'. See mingw*.
   lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
   lt_cv_file_magic_cmd='$OBJDUMP -f'
@@ -3050,6 +3188,10 @@ gnu*)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
 hpux10.20* | hpux11*)
   lt_cv_file_magic_cmd=/usr/bin/file
   case $host_cpu in
@@ -3058,11 +3200,11 @@ hpux10.20* | hpux11*)
     lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
     ;;
   hppa*64*)
-    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
     lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
     ;;
   *)
-    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
     lt_cv_file_magic_test_file=/usr/lib/libc.sl
     ;;
   esac
@@ -3084,11 +3226,11 @@ irix5* | irix6* | nonstopux*)
   ;;
 
 # This must be Linux ELF.
-linux* | k*bsd*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
   else
@@ -3162,6 +3304,21 @@ tpf*)
   ;;
 esac
 ])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
 file_magic_cmd=$lt_cv_file_magic_cmd
 deplibs_check_method=$lt_cv_deplibs_check_method
 test -z "$deplibs_check_method" && deplibs_check_method=unknown
@@ -3169,7 +3326,11 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown
 _LT_DECL([], [deplibs_check_method], [1],
     [Method to check whether dependent libraries are shared objects])
 _LT_DECL([], [file_magic_cmd], [1],
-    [Command to use when deplibs_check_method == "file_magic"])
+    [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+    [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
 ])# _LT_CHECK_MAGIC_METHOD
 
 
@@ -3226,7 +3387,19 @@ if test "$lt_cv_path_NM" != "no"; then
   NM="$lt_cv_path_NM"
 else
   # Didn't find any BSD compatible name lister, look for dumpbin.
-  AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
   AC_SUBST([DUMPBIN])
   if test "$DUMPBIN" != ":"; then
     NM="$DUMPBIN"
@@ -3239,13 +3412,13 @@ _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
 AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
   [lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&AS_MESSAGE_LOG_FD
-  (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&AS_MESSAGE_LOG_FD
-  (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
+  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
   cat conftest.out >&AS_MESSAGE_LOG_FD
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -3260,26 +3433,87 @@ dnl aclocal-1.4 backwards compatibility:
 dnl AC_DEFUN([AM_PROG_NM], [])
 dnl AC_DEFUN([AC_PROG_NM], [])
 
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
 
-# LT_LIB_M
-# --------
-# check for math library
-AC_DEFUN([LT_LIB_M],
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-LIBM=
-case $host in
-*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
-  # These system don't have libm, or don't need it
-  ;;
-*-ncr-sysv4.3*)
-  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
-  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
   ;;
 *)
-  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
   ;;
 esac
-AC_SUBST([LIBM])
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+    [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+  [lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*])
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+  MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+AC_SUBST([LIBM])
 ])# LT_LIB_M
 
 # Old name:
@@ -3296,7 +3530,12 @@ m4_defun([_LT_COMPILER_NO_RTTI],
 _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
 
 if test "$GCC" = yes; then
-  _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+  case $cc_basename in
+  nvcc*)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+  esac
 
   _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
     lt_cv_prog_compiler_rtti_exceptions,
@@ -3313,6 +3552,7 @@ _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
 m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
 [AC_REQUIRE([AC_CANONICAL_HOST])dnl
 AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
 AC_REQUIRE([LT_PATH_NM])dnl
 AC_REQUIRE([LT_PATH_LD])dnl
 m4_require([_LT_DECL_SED])dnl
@@ -3380,8 +3620,8 @@ esac
 lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
 
 # Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
 
 # Handle CRLF in mingw tool chain
 opt_cr=
@@ -3417,6 +3657,7 @@ for ac_symprfx in "" "_"; do
   else
     lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
   fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
 
   # Check to see that the pipe works correctly.
   pipe_works=no
@@ -3438,7 +3679,7 @@ _LT_EOF
   if AC_TRY_EVAL(ac_compile); then
     # Now try to grab the symbols.
     nlist=conftest.nm
-    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
       # Try sorting and uniquifying the output.
       if sort "$nlist" | uniq > "$nlist"T; then
 	mv -f "$nlist"T "$nlist"
@@ -3450,6 +3691,18 @@ _LT_EOF
       if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
 	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
 	  cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT@&t at _DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT@&t at _DLSYM_CONST
+#else
+# define LT@&t at _DLSYM_CONST const
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -3461,7 +3714,7 @@ _LT_EOF
 	  cat <<_LT_EOF >> conftest.$ac_ext
 
 /* The mapping between symbol names and symbols.  */
-const struct {
+LT@&t at _DLSYM_CONST struct {
   const char *name;
   void       *address;
 }
@@ -3487,15 +3740,15 @@ static const void *lt_preloaded_setup() {
 _LT_EOF
 	  # Now try linking the two files.
 	  mv conftest.$ac_objext conftstm.$ac_objext
-	  lt_save_LIBS="$LIBS"
-	  lt_save_CFLAGS="$CFLAGS"
+	  lt_globsym_save_LIBS=$LIBS
+	  lt_globsym_save_CFLAGS=$CFLAGS
 	  LIBS="conftstm.$ac_objext"
 	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
 	  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
 	    pipe_works=yes
 	  fi
-	  LIBS="$lt_save_LIBS"
-	  CFLAGS="$lt_save_CFLAGS"
+	  LIBS=$lt_globsym_save_LIBS
+	  CFLAGS=$lt_globsym_save_CFLAGS
 	else
 	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
 	fi
@@ -3528,6 +3781,13 @@ else
   AC_MSG_RESULT(ok)
 fi
 
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
 _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
     [Take the output of nm and produce a listing of raw symbols and C names])
 _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
@@ -3538,6 +3798,8 @@ _LT_DECL([global_symbol_to_c_name_address],
 _LT_DECL([global_symbol_to_c_name_address_lib_prefix],
     [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
     [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([], [nm_file_list_spec], [1],
+    [Specify filename containing input files for $NM])
 ]) # _LT_CMD_GLOBAL_SYMBOLS
 
 
@@ -3549,7 +3811,6 @@ _LT_TAGVAR(lt_prog_compiler_wl, $1)=
 _LT_TAGVAR(lt_prog_compiler_pic, $1)=
 _LT_TAGVAR(lt_prog_compiler_static, $1)=
 
-AC_MSG_CHECKING([for $compiler option to produce PIC])
 m4_if([$1], [CXX], [
   # C++ specific cases for pic, static, wl, etc.
   if test "$GXX" = yes; then
@@ -3600,6 +3861,11 @@ m4_if([$1], [CXX], [
       # DJGPP does not support shared libraries at all
       _LT_TAGVAR(lt_prog_compiler_pic, $1)=
       ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
     interix[[3-9]]*)
       # Interix 3.x gcc -fpic/-fPIC options generate broken code.
       # Instead, we relocate shared libraries at runtime.
@@ -3649,6 +3915,12 @@ m4_if([$1], [CXX], [
 	  ;;
 	esac
 	;;
+      mingw* | cygwin* | os2* | pw32* | cegcc*)
+	# This hack is so that the source file can tell whether it is being
+	# built for inclusion in a dll (and should export symbols for example).
+	m4_if([$1], [GCJ], [],
+	  [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+	;;
       dgux*)
 	case $cc_basename in
 	  ec++*)
@@ -3705,7 +3977,7 @@ m4_if([$1], [CXX], [
 	    ;;
 	esac
 	;;
-      linux* | k*bsd*-gnu)
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
 	case $cc_basename in
 	  KCC*)
 	    # KAI C++ Compiler
@@ -3738,8 +4010,8 @@ m4_if([$1], [CXX], [
 	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
 	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
 	    ;;
-	  xlc* | xlC*)
-	    # IBM XL 8.0 on PPC
+	  xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+	    # IBM XL 8.0, 9.0 on PPC and BlueGene
 	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
 	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
 	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
@@ -3769,7 +4041,7 @@ m4_if([$1], [CXX], [
 	    ;;
 	esac
 	;;
-      netbsd* | netbsdelf*-gnu)
+      netbsd*)
 	;;
       *qnx* | *nto*)
         # QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -3801,7 +4073,7 @@ m4_if([$1], [CXX], [
 	;;
       solaris*)
 	case $cc_basename in
-	  CC*)
+	  CC* | sunCC*)
 	    # Sun C++ 4.2, 5.x and Centerline C++
 	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
 	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
@@ -3905,6 +4177,12 @@ m4_if([$1], [CXX], [
       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
       ;;
 
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+
     hpux*)
       # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
       # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
@@ -3947,6 +4225,13 @@ m4_if([$1], [CXX], [
       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
       ;;
     esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC'
+      ;;
+    esac
   else
     # PORTME Check for flag to pass linker flags through the system compiler.
     case $host_os in
@@ -3989,7 +4274,7 @@ m4_if([$1], [CXX], [
       _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
       ;;
 
-    linux* | k*bsd*-gnu)
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
       case $cc_basename in
       # old Intel for x86_64 which still supported -KPIC.
       ecc*)
@@ -4010,7 +4295,13 @@ m4_if([$1], [CXX], [
 	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
 	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
 	;;
-      pgcc* | pgf77* | pgf90* | pgf95*)
+      nagfor*)
+	# NAG Fortran compiler
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
         # Portland Group compilers (*not* the Pentium gcc compiler,
 	# which looks to be a dead project)
 	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
@@ -4022,25 +4313,25 @@ m4_if([$1], [CXX], [
         # All Alpha code is PIC.
         _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
         ;;
-      xl*)
-	# IBM XL C 8.0/Fortran 10.1 on PPC
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
 	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
 	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
 	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
 	;;
       *)
 	case `$CC -V 2>&1 | sed 5q` in
-	*Sun\ C*)
-	  # Sun C 5.9
+	*Sun\ F* | *Sun*Fortran*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
 	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
 	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
-	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
 	  ;;
-	*Sun\ F*)
-	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	*Sun\ C*)
+	  # Sun C 5.9
 	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
 	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
-	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
 	  ;;
 	esac
 	;;
@@ -4072,7 +4363,7 @@ m4_if([$1], [CXX], [
       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
       case $cc_basename in
-      f77* | f90* | f95*)
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
 	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
       *)
 	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
@@ -4129,9 +4420,11 @@ case $host_os in
     _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t at m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
     ;;
 esac
-AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
-_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
-	[How to pass a linker flag through the compiler])
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
 
 #
 # Check to make sure the PIC flag actually works.
@@ -4150,6 +4443,8 @@ fi
 _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
 	[Additional compiler flags for building library objects])
 
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+	[How to pass a linker flag through the compiler])
 #
 # Check to make sure the static flag actually works.
 #
@@ -4170,6 +4465,7 @@ _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
 m4_defun([_LT_LINKER_SHLIBS],
 [AC_REQUIRE([LT_PATH_LD])dnl
 AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
 m4_require([_LT_FILEUTILS_DEFAULTS])dnl
 m4_require([_LT_DECL_EGREP])dnl
 m4_require([_LT_DECL_SED])dnl
@@ -4178,30 +4474,35 @@ m4_require([_LT_TAG_COMPILER])dnl
 AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
 m4_if([$1], [CXX], [
   _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
   case $host_os in
   aix[[4-9]]*)
     # If we're using GNU nm, then we don't want the "-C" option.
     # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    # Also, AIX nm treats weak defined symbols like other global defined
+    # symbols, whereas GNU nm marks them as "W".
     if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
-      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
     else
       _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
     fi
     ;;
   pw32*)
     _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
-  ;;
+    ;;
   cygwin* | mingw* | cegcc*)
-    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
-  ;;
-  linux* | k*bsd*-gnu)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-  ;;
+    case $cc_basename in
+    cl*) ;;
+    *)
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+      ;;
+    esac
+    ;;
   *)
     _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
-  ;;
+    ;;
   esac
-  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
 ], [
   runpath_var=
   _LT_TAGVAR(allow_undefined_flag, $1)=
@@ -4261,13 +4562,36 @@ dnl Note also adjust exclude_expsyms for C++ above.
   openbsd*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   esac
 
   _LT_TAGVAR(ld_shlibs, $1)=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
   if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+	  *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
     # If archive_cmds runs LD, not CC, wlarc should be empty
     wlarc='${wl}'
 
@@ -4285,6 +4609,7 @@ dnl Note also adjust exclude_expsyms for C++ above.
     fi
     supports_anon_versioning=no
     case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
       *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
       *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
       *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
@@ -4300,11 +4625,12 @@ dnl Note also adjust exclude_expsyms for C++ above.
 	_LT_TAGVAR(ld_shlibs, $1)=no
 	cat <<_LT_EOF 1>&2
 
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** Warning: the GNU linker, at least up to release 2.19, is reported
 *** to be unable to reliably create shared libraries on AIX.
 *** Therefore, libtool is disabling shared libraries support.  If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
 
 _LT_EOF
       fi
@@ -4340,10 +4666,12 @@ _LT_EOF
       # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
       # as there is no search path for DLLs.
       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
       _LT_TAGVAR(always_export_symbols, $1)=no
       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
-      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
 
       if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
@@ -4361,6 +4689,11 @@ _LT_EOF
       fi
       ;;
 
+    haiku*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
     interix[[3-9]]*)
       _LT_TAGVAR(hardcode_direct, $1)=no
       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
@@ -4376,7 +4709,7 @@ _LT_EOF
       _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
       ;;
 
-    gnu* | linux* | tpf* | k*bsd*-gnu)
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
       tmp_diet=no
       if test "$host_os" = linux-dietlibc; then
 	case $cc_basename in
@@ -4386,15 +4719,16 @@ _LT_EOF
       if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
 	 && test "$tmp_diet" = no
       then
-	tmp_addflag=
+	tmp_addflag=' $pic_flag'
 	tmp_sharedflag='-shared'
 	case $cc_basename,$host_cpu in
         pgcc*)				# Portland Group C compiler
-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	  tmp_addflag=' $pic_flag'
 	  ;;
-	pgf77* | pgf90* | pgf95*)	# Portland Group f77 and f90 compilers
-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	  tmp_addflag=' $pic_flag -Mnomain' ;;
 	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
 	  tmp_addflag=' -i_dynamic' ;;
@@ -4405,13 +4739,17 @@ _LT_EOF
 	lf95*)				# Lahey Fortran 8.1
 	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
 	  tmp_sharedflag='--shared' ;;
-	xl[[cC]]*)			# IBM XL C 8.0 on PPC (deal with xlf below)
+	xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
 	  tmp_sharedflag='-qmkshrobj'
 	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  ;;
 	esac
 	case `$CC -V 2>&1 | sed 5q` in
 	*Sun\ C*)			# Sun C 5.9
-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	  _LT_TAGVAR(compiler_needs_object, $1)=yes
 	  tmp_sharedflag='-G' ;;
 	*Sun\ F*)			# Sun Fortran 8.3
@@ -4427,17 +4765,17 @@ _LT_EOF
         fi
 
 	case $cc_basename in
-	xlf*)
+	xlf* | bgf* | bgxlf* | mpixlf*)
 	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
 	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
 	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
 	  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
-	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
 	  if test "x$supports_anon_versioning" = xyes; then
 	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
 	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
 	      echo "local: *; };" >> $output_objdir/$libname.ver~
-	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	      $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
 	  fi
 	  ;;
 	esac
@@ -4446,13 +4784,13 @@ _LT_EOF
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
 	wlarc=
       else
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
       fi
       ;;
 
@@ -4470,8 +4808,8 @@ _LT_EOF
 
 _LT_EOF
       elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
       else
 	_LT_TAGVAR(ld_shlibs, $1)=no
       fi
@@ -4517,8 +4855,8 @@ _LT_EOF
 
     *)
       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
       else
 	_LT_TAGVAR(ld_shlibs, $1)=no
       fi
@@ -4558,8 +4896,10 @@ _LT_EOF
       else
 	# If we're using GNU nm, then we don't want the "-C" option.
 	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
 	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
-	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
 	else
 	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
 	fi
@@ -4621,7 +4961,6 @@ _LT_EOF
 	if test "$aix_use_runtimelinking" = yes; then
 	  shared_flag="$shared_flag "'${wl}-G'
 	fi
-	_LT_TAGVAR(link_all_deplibs, $1)=no
       else
 	# not using gcc
 	if test "$host_cpu" = ia64; then
@@ -4647,9 +4986,9 @@ _LT_EOF
 	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
         # Determine the default libpath from the value encoded in an
         # empty executable.
-        _LT_SYS_MODULE_PATH_AIX
+        _LT_SYS_MODULE_PATH_AIX([$1])
         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
-        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
       else
 	if test "$host_cpu" = ia64; then
 	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
@@ -4658,14 +4997,19 @@ _LT_EOF
 	else
 	 # Determine the default libpath from the value encoded in an
 	 # empty executable.
-	 _LT_SYS_MODULE_PATH_AIX
+	 _LT_SYS_MODULE_PATH_AIX([$1])
 	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
 	  # Warning - without using the other run time loading flags,
 	  # -berok will link without error, but may produce a broken library.
 	  _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
 	  _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
-	  # Exported symbols can be pulled into shared objects from archives
-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	  fi
 	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
 	  # This is similar to how AIX traditionally builds its shared libraries.
 	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
@@ -4697,20 +5041,63 @@ _LT_EOF
       # Microsoft Visual C++.
       # hardcode_libdir_flag_spec is actually meaningless, as there is
       # no search path for DLLs.
-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
-      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
-      # Tell ltmain to make .lib files, not .a files.
-      libext=lib
-      # Tell ltmain to make .dll files, not .so files.
-      shrext_cmds=".dll"
-      # FIXME: Setting linknames here is a bad hack.
-      _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
-      # The linker will automatically build a .lib file if we build a DLL.
-      _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
-      # FIXME: Should let the user specify the lib program.
-      _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
-      _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
-      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      case $cc_basename in
+      cl*)
+	# Native MSVC
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	_LT_TAGVAR(always_export_symbols, $1)=yes
+	_LT_TAGVAR(file_list_spec, $1)='@'
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=".dll"
+	# FIXME: Setting linknames here is a bad hack.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+	  else
+	    sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+	  fi~
+	  $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+	  linknames='
+	# The linker will not automatically build a static lib if we build a DLL.
+	# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+	# Don't use ranlib
+	_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+	_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+	  lt_tool_outputfile="@TOOL_OUTPUT@"~
+	  case $lt_outputfile in
+	    *.exe|*.EXE) ;;
+	    *)
+	      lt_outputfile="$lt_outputfile.exe"
+	      lt_tool_outputfile="$lt_tool_outputfile.exe"
+	      ;;
+	  esac~
+	  if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+	    $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+	    $RM "$lt_outputfile.manifest";
+	  fi'
+	;;
+      *)
+	# Assume MSVC wrapper
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=".dll"
+	# FIXME: Setting linknames here is a bad hack.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+	# The linker will automatically build a .lib file if we build a DLL.
+	_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+	# FIXME: Should let the user specify the lib program.
+	_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	;;
+      esac
       ;;
 
     darwin* | rhapsody*)
@@ -4748,7 +5135,7 @@ _LT_EOF
 
     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
     freebsd* | dragonfly*)
-      _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
       _LT_TAGVAR(hardcode_direct, $1)=yes
       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
@@ -4756,7 +5143,7 @@ _LT_EOF
 
     hpux9*)
       if test "$GCC" = yes; then
-	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
       else
 	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
       fi
@@ -4771,8 +5158,8 @@ _LT_EOF
       ;;
 
     hpux10*)
-      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
       else
 	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
       fi
@@ -4790,16 +5177,16 @@ _LT_EOF
       ;;
 
     hpux11*)
-      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
 	case $host_cpu in
 	hppa*64*)
 	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	*)
-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	esac
       else
@@ -4811,7 +5198,14 @@ _LT_EOF
 	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	*)
-	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	m4_if($1, [], [
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  _LT_LINKER_OPTION([if $CC understands -b],
+	    _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+	    [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+	    [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+	  [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
 	  ;;
 	esac
       fi
@@ -4839,19 +5233,34 @@ _LT_EOF
 
     irix5* | irix6* | nonstopux*)
       if test "$GCC" = yes; then
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 	# Try to use the -exported_symbol ld option, if it does not
 	# work, assume that -exports_file does not work either and
 	# implicitly export all symbols.
-        save_LDFLAGS="$LDFLAGS"
-        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
-        AC_LINK_IFELSE(int foo(void) {},
-          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
-        )
-        LDFLAGS="$save_LDFLAGS"
+	# This should be the same for all languages, so no per-tag cache variable.
+	AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+	  [lt_cv_irix_exported_symbol],
+	  [save_LDFLAGS="$LDFLAGS"
+	   LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+	   AC_LINK_IFELSE(
+	     [AC_LANG_SOURCE(
+	        [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+			      [C++], [[int foo (void) { return 0; }]],
+			      [Fortran 77], [[
+      subroutine foo
+      end]],
+			      [Fortran], [[
+      subroutine foo
+      end]])])],
+	      [lt_cv_irix_exported_symbol=yes],
+	      [lt_cv_irix_exported_symbol=no])
+           LDFLAGS="$save_LDFLAGS"])
+	if test "$lt_cv_irix_exported_symbol" = yes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+	fi
       else
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
       fi
       _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
@@ -4860,7 +5269,7 @@ _LT_EOF
       _LT_TAGVAR(link_all_deplibs, $1)=yes
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
@@ -4913,17 +5322,17 @@ _LT_EOF
       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
       _LT_TAGVAR(hardcode_minus_L, $1)=yes
       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
-      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
       _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
       ;;
 
     osf3*)
       if test "$GCC" = yes; then
 	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
       else
 	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
       fi
       _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
@@ -4933,13 +5342,13 @@ _LT_EOF
     osf4* | osf5*)	# as osf3* with the addition of -msym flag
       if test "$GCC" = yes; then
 	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
       else
 	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
-	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
 
 	# Both c and cxx compiler support -rpath directly
 	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
@@ -4952,9 +5361,9 @@ _LT_EOF
       _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
       if test "$GCC" = yes; then
 	wlarc='${wl}'
-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
 	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
       else
 	case `$CC -V 2>&1` in
 	*"Compilers 5.0"*)
@@ -5130,36 +5539,38 @@ x|xyes)
       # Test whether the compiler implicitly links with -lc since on some
       # systems, -lgcc has to come before -lc. If gcc already passes -lc
       # to ld, don't add -lc before -lgcc.
-      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
-      $RM conftest*
-      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
-      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
-        soname=conftest
-        lib=conftest
-        libobjs=conftest.$ac_objext
-        deplibs=
-        wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
-	pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
-        compiler_flags=-v
-        linker_flags=-v
-        verstring=
-        output_objdir=.
-        libname=conftest
-        lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
-        _LT_TAGVAR(allow_undefined_flag, $1)=
-        if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
-        then
-	  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
-        else
-	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
-        fi
-        _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
-      else
-        cat conftest.err 1>&5
-      fi
-      $RM conftest*
-      AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
+      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+	[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+	[$RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+	  pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+	  _LT_TAGVAR(allow_undefined_flag, $1)=
+	  if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+	  then
+	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	  else
+	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  fi
+	  _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+	])
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
       ;;
     esac
   fi
@@ -5224,8 +5635,6 @@ _LT_TAGDECL([], [inherit_rpath], [0],
     to runtime path list])
 _LT_TAGDECL([], [link_all_deplibs], [0],
     [Whether libtool must link a program against all its dependency libraries])
-_LT_TAGDECL([], [fix_srcfile_path], [1],
-    [Fix the shell variable $srcfile for the compiler])
 _LT_TAGDECL([], [always_export_symbols], [0],
     [Set to "yes" if exported symbols are required])
 _LT_TAGDECL([], [export_symbols_cmds], [2],
@@ -5236,6 +5645,8 @@ _LT_TAGDECL([], [include_expsyms], [1],
     [Symbols that must always be exported])
 _LT_TAGDECL([], [prelink_cmds], [2],
     [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+    [Commands necessary for finishing linking programs])
 _LT_TAGDECL([], [file_list_spec], [1],
     [Specify filename containing input files])
 dnl FIXME: Not yet implemented
@@ -5329,37 +5740,22 @@ CC="$lt_save_CC"
 ])# _LT_LANG_C_CONFIG
 
 
-# _LT_PROG_CXX
-# ------------
-# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
-# compiler, we have our own version here.
-m4_defun([_LT_PROG_CXX],
-[
-pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
-AC_PROG_CXX
-if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
-    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
-    (test "X$CXX" != "Xg++"))) ; then
-  AC_PROG_CXXCPP
-else
-  _lt_caught_CXX_error=yes
-fi
-popdef([AC_MSG_ERROR])
-])# _LT_PROG_CXX
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([_LT_PROG_CXX], [])
-
-
 # _LT_LANG_CXX_CONFIG([TAG])
 # --------------------------
 # Ensure that the configuration variables for a C++ compiler are suitably
 # defined.  These variables are subsequently used by _LT_CONFIG to write
 # the compiler configuration to `libtool'.
 m4_defun([_LT_LANG_CXX_CONFIG],
-[AC_REQUIRE([_LT_PROG_CXX])dnl
-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
 m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
 
 AC_LANG_PUSH(C++)
 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
@@ -5381,6 +5777,8 @@ _LT_TAGVAR(module_cmds, $1)=
 _LT_TAGVAR(module_expsym_cmds, $1)=
 _LT_TAGVAR(link_all_deplibs, $1)=unknown
 _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
 _LT_TAGVAR(no_undefined_flag, $1)=
 _LT_TAGVAR(whole_archive_flag_spec, $1)=
 _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
@@ -5412,6 +5810,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 
   # Allow CC to be a program name with arguments.
   lt_save_CC=$CC
+  lt_save_CFLAGS=$CFLAGS
   lt_save_LD=$LD
   lt_save_GCC=$GCC
   GCC=$GXX
@@ -5429,6 +5828,7 @@ if test "$_lt_caught_CXX_error" != yes; then
   fi
   test -z "${LDCXX+set}" || LD=$LDCXX
   CC=${CXX-"c++"}
+  CFLAGS=$CXXFLAGS
   compiler=$CC
   _LT_TAGVAR(compiler, $1)=$CC
   _LT_CC_BASENAME([$compiler])
@@ -5450,8 +5850,8 @@ if test "$_lt_caught_CXX_error" != yes; then
       # Check if GNU C++ uses GNU ld as the underlying linker, since the
       # archiving commands below assume that GNU ld is being used.
       if test "$with_gnu_ld" = yes; then
-        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
-        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
 
         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
         _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
@@ -5483,7 +5883,7 @@ if test "$_lt_caught_CXX_error" != yes; then
       # Commands to make compiler produce verbose output that lists
       # what "hidden" libraries, object files and flags are used when
       # linking a shared library.
-      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 
     else
       GXX=no
@@ -5592,10 +5992,10 @@ if test "$_lt_caught_CXX_error" != yes; then
           _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
           # Determine the default libpath from the value encoded in an empty
           # executable.
-          _LT_SYS_MODULE_PATH_AIX
+          _LT_SYS_MODULE_PATH_AIX([$1])
           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
 
-          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
         else
           if test "$host_cpu" = ia64; then
 	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
@@ -5604,14 +6004,19 @@ if test "$_lt_caught_CXX_error" != yes; then
           else
 	    # Determine the default libpath from the value encoded in an
 	    # empty executable.
-	    _LT_SYS_MODULE_PATH_AIX
+	    _LT_SYS_MODULE_PATH_AIX([$1])
 	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
 	    # Warning - without using the other run time loading flags,
 	    # -berok will link without error, but may produce a broken library.
 	    _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
 	    _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
-	    # Exported symbols can be pulled into shared objects from archives
-	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	    if test "$with_gnu_ld" = yes; then
+	      # We only use this code for GNU lds that support --whole-archive.
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    else
+	      # Exported symbols can be pulled into shared objects from archives
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	    fi
 	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
 	    # This is similar to how AIX traditionally builds its shared
 	    # libraries.
@@ -5641,28 +6046,75 @@ if test "$_lt_caught_CXX_error" != yes; then
         ;;
 
       cygwin* | mingw* | pw32* | cegcc*)
-        # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
-        # as there is no search path for DLLs.
-        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
-        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
-        _LT_TAGVAR(always_export_symbols, $1)=no
-        _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
-
-        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
-          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-          # If the export-symbols file already is a .def file (1st line
-          # is EXPORTS), use it as is; otherwise, prepend...
-          _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
-	    cp $export_symbols $output_objdir/$soname.def;
-          else
-	    echo EXPORTS > $output_objdir/$soname.def;
-	    cat $export_symbols >> $output_objdir/$soname.def;
-          fi~
-          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-        else
-          _LT_TAGVAR(ld_shlibs, $1)=no
-        fi
-        ;;
+	case $GXX,$cc_basename in
+	,cl* | no,cl*)
+	  # Native MSVC
+	  # hardcode_libdir_flag_spec is actually meaningless, as there is
+	  # no search path for DLLs.
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  _LT_TAGVAR(always_export_symbols, $1)=yes
+	  _LT_TAGVAR(file_list_spec, $1)='@'
+	  # Tell ltmain to make .lib files, not .a files.
+	  libext=lib
+	  # Tell ltmain to make .dll files, not .so files.
+	  shrext_cmds=".dll"
+	  # FIXME: Setting linknames here is a bad hack.
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	      $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+	    else
+	      $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+	    fi~
+	    $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+	    linknames='
+	  # The linker will not automatically build a static lib if we build a DLL.
+	  # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+	  # Don't use ranlib
+	  _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+	  _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+	    lt_tool_outputfile="@TOOL_OUTPUT@"~
+	    case $lt_outputfile in
+	      *.exe|*.EXE) ;;
+	      *)
+		lt_outputfile="$lt_outputfile.exe"
+		lt_tool_outputfile="$lt_tool_outputfile.exe"
+		;;
+	    esac~
+	    func_to_tool_file "$lt_outputfile"~
+	    if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+	      $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+	      $RM "$lt_outputfile.manifest";
+	    fi'
+	  ;;
+	*)
+	  # g++
+	  # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+	  # as there is no search path for DLLs.
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  _LT_TAGVAR(always_export_symbols, $1)=no
+	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	    # If the export-symbols file already is a .def file (1st line
+	    # is EXPORTS), use it as is; otherwise, prepend...
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	      cp $export_symbols $output_objdir/$soname.def;
+	    else
+	      echo EXPORTS > $output_objdir/$soname.def;
+	      cat $export_symbols >> $output_objdir/$soname.def;
+	    fi~
+	    $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	  else
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	  fi
+	  ;;
+	esac
+	;;
       darwin* | rhapsody*)
         _LT_DARWIN_LINKER_FEATURES($1)
 	;;
@@ -5704,6 +6156,11 @@ if test "$_lt_caught_CXX_error" != yes; then
       gnu*)
         ;;
 
+      haiku*)
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        ;;
+
       hpux9*)
         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
         _LT_TAGVAR(hardcode_libdir_separator, $1)=:
@@ -5728,11 +6185,11 @@ if test "$_lt_caught_CXX_error" != yes; then
             # explicitly linking system object files so we need to strip them
             # from the output so that they don't get included in the library
             # dependencies.
-            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
             ;;
           *)
             if test "$GXX" = yes; then
-              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
             else
               # FIXME: insert proper C++ library support
               _LT_TAGVAR(ld_shlibs, $1)=no
@@ -5793,7 +6250,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
 	    ;;
           *)
 	    if test "$GXX" = yes; then
@@ -5803,10 +6260,10 @@ if test "$_lt_caught_CXX_error" != yes; then
 	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	            ;;
 	          ia64*)
-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	            ;;
 	          *)
-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	            ;;
 	        esac
 	      fi
@@ -5836,7 +6293,7 @@ if test "$_lt_caught_CXX_error" != yes; then
         case $cc_basename in
           CC*)
 	    # SGI C++
-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 
 	    # Archives containing C++ object files must be created using
 	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
@@ -5847,9 +6304,9 @@ if test "$_lt_caught_CXX_error" != yes; then
           *)
 	    if test "$GXX" = yes; then
 	      if test "$with_gnu_ld" = no; then
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 	      else
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
 	      fi
 	    fi
 	    _LT_TAGVAR(link_all_deplibs, $1)=yes
@@ -5860,7 +6317,7 @@ if test "$_lt_caught_CXX_error" != yes; then
         _LT_TAGVAR(inherit_rpath, $1)=yes
         ;;
 
-      linux* | k*bsd*-gnu)
+      linux* | k*bsd*-gnu | kopensolaris*-gnu)
         case $cc_basename in
           KCC*)
 	    # Kuck and Associates, Inc. (KAI) C++ Compiler
@@ -5878,7 +6335,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
 
 	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
 	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
@@ -5915,26 +6372,26 @@ if test "$_lt_caught_CXX_error" != yes; then
           pgCC* | pgcpp*)
             # Portland Group C++ compiler
 	    case `$CC -V` in
-	    *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
+	    *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
 	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
-		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+		compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
 	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
-		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
 		$RANLIB $oldlib'
 	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
-		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
 	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
 		rm -rf $tpldir~
 		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
-		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 	      ;;
-	    *) # Version 6 will use weak symbols
+	    *) # Version 6 and above use weak symbols
 	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
 	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
 	      ;;
@@ -5942,7 +6399,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 
 	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
 	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
-	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
             ;;
 	  cxx*)
 	    # Compaq C++
@@ -5961,9 +6418,9 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
 	    ;;
-	  xl*)
+	  xl* | mpixl* | bgxl*)
 	    # IBM XL 8.0 on PPC, with GNU ld
 	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
 	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
@@ -5983,13 +6440,13 @@ if test "$_lt_caught_CXX_error" != yes; then
 	      _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
 	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
 	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
-	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
 	      _LT_TAGVAR(compiler_needs_object, $1)=yes
 
 	      # Not sure whether something based on
 	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
 	      # would be better.
-	      output_verbose_link_cmd='echo'
+	      output_verbose_link_cmd='func_echo_all'
 
 	      # Archives containing C++ object files must be created using
 	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
@@ -6058,7 +6515,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
 	    _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
 	  fi
-	  output_verbose_link_cmd=echo
+	  output_verbose_link_cmd=func_echo_all
 	else
 	  _LT_TAGVAR(ld_shlibs, $1)=no
 	fi
@@ -6093,15 +6550,15 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    case $host in
 	      osf3*)
 	        _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
 		;;
 	      *)
 	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
 	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
 	          echo "-hidden">> $lib.exp~
-	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
 	          $RM $lib.exp'
 	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
 		;;
@@ -6117,17 +6574,17 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    # explicitly linking system object files so we need to strip them
 	    # from the output so that they don't get included in the library
 	    # dependencies.
-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
 	    ;;
 	  *)
 	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
 	      _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
 	      case $host in
 	        osf3*)
-	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 		  ;;
 	        *)
-	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
 		  ;;
 	      esac
 
@@ -6137,7 +6594,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 	      # Commands to make compiler produce verbose output that lists
 	      # what "hidden" libraries, object files and flags are used when
 	      # linking a shared library.
-	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 
 	    else
 	      # FIXME: insert proper C++ library support
@@ -6173,7 +6630,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 
       solaris*)
         case $cc_basename in
-          CC*)
+          CC* | sunCC*)
 	    # Sun C++ 4.2, 5.x and Centerline C++
             _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
 	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
@@ -6194,7 +6651,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    esac
 	    _LT_TAGVAR(link_all_deplibs, $1)=yes
 
-	    output_verbose_link_cmd='echo'
+	    output_verbose_link_cmd='func_echo_all'
 
 	    # Archives containing C++ object files must be created using
 	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
@@ -6214,14 +6671,14 @@ if test "$_lt_caught_CXX_error" != yes; then
 	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
 	      _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
 	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
 	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+		  $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
 
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
 	        # linking a shared library.
-	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 	      else
 	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
 	        # platform.
@@ -6232,7 +6689,7 @@ if test "$_lt_caught_CXX_error" != yes; then
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
 	        # linking a shared library.
-	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
 	      fi
 
 	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
@@ -6286,6 +6743,10 @@ if test "$_lt_caught_CXX_error" != yes; then
           CC*)
 	    _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
 	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+	      '"$_LT_TAGVAR(old_archive_cmds, $1)"
+	    _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+	      '"$_LT_TAGVAR(reload_cmds, $1)"
 	    ;;
 	  *)
 	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
@@ -6341,6 +6802,7 @@ if test "$_lt_caught_CXX_error" != yes; then
   fi # test -n "$compiler"
 
   CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
   LDCXX=$LD
   LD=$lt_save_LD
   GCC=$lt_save_GCC
@@ -6355,6 +6817,29 @@ AC_LANG_POP
 ])# _LT_LANG_CXX_CONFIG
 
 
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+  case ${2} in
+  .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+  *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
 # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
 # ---------------------------------
 # Figure out "hidden" library dependencies from verbose
@@ -6363,6 +6848,7 @@ AC_LANG_POP
 # objects, libraries and library flags.
 m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
 [m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
 # Dependencies to place before and after the object being linked:
 _LT_TAGVAR(predep_objects, $1)=
 _LT_TAGVAR(postdep_objects, $1)=
@@ -6413,6 +6899,13 @@ public class foo {
 };
 _LT_EOF
 ])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+esac
+
 dnl Parse the compiler output and extract the necessary
 dnl objects, libraries and library flags.
 if AC_TRY_EVAL(ac_compile); then
@@ -6424,7 +6917,7 @@ if AC_TRY_EVAL(ac_compile); then
   pre_test_object_deps_done=no
 
   for p in `eval "$output_verbose_link_cmd"`; do
-    case $p in
+    case ${prev}${p} in
 
     -L* | -R* | -l*)
        # Some compilers place space between "-{L,R}" and the path.
@@ -6433,13 +6926,22 @@ if AC_TRY_EVAL(ac_compile); then
           test $p = "-R"; then
 	 prev=$p
 	 continue
-       else
-	 prev=
        fi
 
+       # Expand the sysroot to ease extracting the directories later.
+       if test -z "$prev"; then
+         case $p in
+         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+         esac
+       fi
+       case $p in
+       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+       esac
        if test "$pre_test_object_deps_done" = no; then
-	 case $p in
-	 -L* | -R*)
+	 case ${prev} in
+	 -L | -R)
 	   # Internal compiler library paths should come after those
 	   # provided the user.  The postdeps already come after the
 	   # user supplied libs so there is no need to process them.
@@ -6459,8 +6961,10 @@ if AC_TRY_EVAL(ac_compile); then
 	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
 	 fi
        fi
+       prev=
        ;;
 
+    *.lto.$objext) ;; # Ignore GCC LTO objects
     *.$objext)
        # This assumes that the test object file only shows up
        # once in the compiler output.
@@ -6496,6 +7000,7 @@ else
 fi
 
 $RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
 
 # PORTME: override above test on systems where it is broken
 m4_if([$1], [CXX],
@@ -6532,7 +7037,7 @@ linux*)
 
 solaris*)
   case $cc_basename in
-  CC*)
+  CC* | sunCC*)
     # The more standards-conforming stlport4 library is
     # incompatible with the Cstd library. Avoid specifying
     # it if it's in CXXFLAGS. Ignore libCrun as
@@ -6576,32 +7081,16 @@ _LT_TAGDECL([], [compiler_lib_search_path], [1],
 ])# _LT_SYS_HIDDEN_LIBDEPS
 
 
-# _LT_PROG_F77
-# ------------
-# Since AC_PROG_F77 is broken, in that it returns the empty string
-# if there is no fortran compiler, we have our own version here.
-m4_defun([_LT_PROG_F77],
-[
-pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
-AC_PROG_F77
-if test -z "$F77" || test "X$F77" = "Xno"; then
-  _lt_disable_F77=yes
-fi
-popdef([AC_MSG_ERROR])
-])# _LT_PROG_F77
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([_LT_PROG_F77], [])
-
-
 # _LT_LANG_F77_CONFIG([TAG])
 # --------------------------
 # Ensure that the configuration variables for a Fortran 77 compiler are
 # suitably defined.  These variables are subsequently used by _LT_CONFIG
 # to write the compiler configuration to `libtool'.
 m4_defun([_LT_LANG_F77_CONFIG],
-[AC_REQUIRE([_LT_PROG_F77])dnl
-AC_LANG_PUSH(Fortran 77)
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test "X$F77" = "Xno"; then
+  _lt_disable_F77=yes
+fi
 
 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
 _LT_TAGVAR(allow_undefined_flag, $1)=
@@ -6620,6 +7109,8 @@ _LT_TAGVAR(module_cmds, $1)=
 _LT_TAGVAR(module_expsym_cmds, $1)=
 _LT_TAGVAR(link_all_deplibs, $1)=unknown
 _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
 _LT_TAGVAR(no_undefined_flag, $1)=
 _LT_TAGVAR(whole_archive_flag_spec, $1)=
 _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
@@ -6659,7 +7150,9 @@ if test "$_lt_disable_F77" != yes; then
   # Allow CC to be a program name with arguments.
   lt_save_CC="$CC"
   lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
   CC=${F77-"f77"}
+  CFLAGS=$FFLAGS
   compiler=$CC
   _LT_TAGVAR(compiler, $1)=$CC
   _LT_CC_BASENAME([$compiler])
@@ -6713,38 +7206,24 @@ if test "$_lt_disable_F77" != yes; then
 
   GCC=$lt_save_GCC
   CC="$lt_save_CC"
+  CFLAGS="$lt_save_CFLAGS"
 fi # test "$_lt_disable_F77" != yes
 
 AC_LANG_POP
 ])# _LT_LANG_F77_CONFIG
 
 
-# _LT_PROG_FC
-# -----------
-# Since AC_PROG_FC is broken, in that it returns the empty string
-# if there is no fortran compiler, we have our own version here.
-m4_defun([_LT_PROG_FC],
-[
-pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
-AC_PROG_FC
-if test -z "$FC" || test "X$FC" = "Xno"; then
-  _lt_disable_FC=yes
-fi
-popdef([AC_MSG_ERROR])
-])# _LT_PROG_FC
-
-dnl aclocal-1.4 backwards compatibility:
-dnl AC_DEFUN([_LT_PROG_FC], [])
-
-
 # _LT_LANG_FC_CONFIG([TAG])
 # -------------------------
 # Ensure that the configuration variables for a Fortran compiler are
 # suitably defined.  These variables are subsequently used by _LT_CONFIG
 # to write the compiler configuration to `libtool'.
 m4_defun([_LT_LANG_FC_CONFIG],
-[AC_REQUIRE([_LT_PROG_FC])dnl
-AC_LANG_PUSH(Fortran)
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test "X$FC" = "Xno"; then
+  _lt_disable_FC=yes
+fi
 
 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
 _LT_TAGVAR(allow_undefined_flag, $1)=
@@ -6763,6 +7242,8 @@ _LT_TAGVAR(module_cmds, $1)=
 _LT_TAGVAR(module_expsym_cmds, $1)=
 _LT_TAGVAR(link_all_deplibs, $1)=unknown
 _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
 _LT_TAGVAR(no_undefined_flag, $1)=
 _LT_TAGVAR(whole_archive_flag_spec, $1)=
 _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
@@ -6802,7 +7283,9 @@ if test "$_lt_disable_FC" != yes; then
   # Allow CC to be a program name with arguments.
   lt_save_CC="$CC"
   lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
   CC=${FC-"f95"}
+  CFLAGS=$FCFLAGS
   compiler=$CC
   GCC=$ac_cv_fc_compiler_gnu
 
@@ -6858,7 +7341,8 @@ if test "$_lt_disable_FC" != yes; then
   fi # test -n "$compiler"
 
   GCC=$lt_save_GCC
-  CC="$lt_save_CC"
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
 fi # test "$_lt_disable_FC" != yes
 
 AC_LANG_POP
@@ -6895,10 +7379,12 @@ _LT_COMPILER_BOILERPLATE
 _LT_LINKER_BOILERPLATE
 
 # Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
 lt_save_GCC=$GCC
 GCC=yes
 CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
 compiler=$CC
 _LT_TAGVAR(compiler, $1)=$CC
 _LT_TAGVAR(LD, $1)="$LD"
@@ -6908,6 +7394,8 @@ _LT_CC_BASENAME([$compiler])
 _LT_TAGVAR(archive_cmds_need_lc, $1)=no
 
 _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
 
 ## CAVEAT EMPTOR:
 ## There is no encapsulation within the following macros, do not change
@@ -6927,7 +7415,8 @@ fi
 AC_LANG_RESTORE
 
 GCC=$lt_save_GCC
-CC="$lt_save_CC"
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
 ])# _LT_LANG_GCJ_CONFIG
 
 
@@ -6962,9 +7451,11 @@ _LT_LINKER_BOILERPLATE
 
 # Allow CC to be a program name with arguments.
 lt_save_CC="$CC"
+lt_save_CFLAGS=$CFLAGS
 lt_save_GCC=$GCC
 GCC=
 CC=${RC-"windres"}
+CFLAGS=
 compiler=$CC
 _LT_TAGVAR(compiler, $1)=$CC
 _LT_CC_BASENAME([$compiler])
@@ -6977,7 +7468,8 @@ fi
 
 GCC=$lt_save_GCC
 AC_LANG_RESTORE
-CC="$lt_save_CC"
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
 ])# _LT_LANG_RC_CONFIG
 
 
@@ -7036,6 +7528,15 @@ _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
 AC_SUBST([OBJDUMP])
 ])
 
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
 
 # _LT_DECL_SED
 # ------------
@@ -7129,8 +7630,8 @@ m4_defun([_LT_CHECK_SHELL_FEATURES],
 # Try some XSI features
 xsi_shell=no
 ( _lt_dummy="a/b/c"
-  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
-      = c,a/b,, \
+  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,b/c, \
     && eval 'test $(( 1 + 1 )) -eq 2 \
     && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
   && xsi_shell=yes
@@ -7169,208 +7670,162 @@ _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
 ])# _LT_CHECK_SHELL_FEATURES
 
 
-# _LT_PROG_XSI_SHELLFNS
-# ---------------------
-# Bourne and XSI compatible variants of some useful shell functions.
-m4_defun([_LT_PROG_XSI_SHELLFNS],
-[case $xsi_shell in
-  yes)
-    cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
-  case ${1} in
-    */*) func_dirname_result="${1%/*}${2}" ;;
-    *  ) func_dirname_result="${3}" ;;
-  esac
-}
-
-# func_basename file
-func_basename ()
-{
-  func_basename_result="${1##*/}"
-}
-
-# func_dirname_and_basename file append nondir_replacement
-# perform func_basename and func_dirname in a single function
-# call:
-#   dirname:  Compute the dirname of FILE.  If nonempty,
-#             add APPEND to the result, otherwise set result
-#             to NONDIR_REPLACEMENT.
-#             value returned in "$func_dirname_result"
-#   basename: Compute filename of FILE.
-#             value retuned in "$func_basename_result"
-# Implementation must be kept synchronized with func_dirname
-# and func_basename. For efficiency, we do not delegate to
-# those functions but instead duplicate the functionality here.
-func_dirname_and_basename ()
-{
-  case ${1} in
-    */*) func_dirname_result="${1%/*}${2}" ;;
-    *  ) func_dirname_result="${3}" ;;
-  esac
-  func_basename_result="${1##*/}"
-}
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-func_stripname ()
-{
-  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
-  # positional parameters, so assign one to ordinary parameter first.
-  func_stripname_result=${3}
-  func_stripname_result=${func_stripname_result#"${1}"}
-  func_stripname_result=${func_stripname_result%"${2}"}
-}
-
-# func_opt_split
-func_opt_split ()
-{
-  func_opt_split_opt=${1%%=*}
-  func_opt_split_arg=${1#*=}
-}
-
-# func_lo2o object
-func_lo2o ()
-{
-  case ${1} in
-    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
-    *)    func_lo2o_result=${1} ;;
-  esac
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
-  func_xform_result=${1%.*}.lo
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
-  func_arith_result=$(( $[*] ))
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
-  func_len_result=${#1}
-}
+# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY)
+# ------------------------------------------------------
+# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and
+# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY.
+m4_defun([_LT_PROG_FUNCTION_REPLACE],
+[dnl {
+sed -e '/^$1 ()$/,/^} # $1 /c\
+$1 ()\
+{\
+m4_bpatsubsts([$2], [$], [\\], [^\([	 ]\)], [\\\1])
+} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+])
 
-_LT_EOF
-    ;;
-  *) # Bourne compatible functions.
-    cat << \_LT_EOF >> "$cfgfile"
 
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
-  # Extract subdirectory from the argument.
-  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
-  if test "X$func_dirname_result" = "X${1}"; then
-    func_dirname_result="${3}"
-  else
-    func_dirname_result="$func_dirname_result${2}"
-  fi
-}
+# _LT_PROG_REPLACE_SHELLFNS
+# -------------------------
+# Replace existing portable implementations of several shell functions with
+# equivalent extended shell implementations where those features are available..
+m4_defun([_LT_PROG_REPLACE_SHELLFNS],
+[if test x"$xsi_shell" = xyes; then
+  _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac])
+
+  _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl
+    func_basename_result="${1##*/}"])
+
+  _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac
+    func_basename_result="${1##*/}"])
 
-# func_basename file
-func_basename ()
-{
-  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
-}
+  _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl
+    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+    # positional parameters, so assign one to ordinary parameter first.
+    func_stripname_result=${3}
+    func_stripname_result=${func_stripname_result#"${1}"}
+    func_stripname_result=${func_stripname_result%"${2}"}])
 
-dnl func_dirname_and_basename
-dnl A portable version of this function is already defined in general.m4sh
-dnl so there is no need for it here.
+  _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl
+    func_split_long_opt_name=${1%%=*}
+    func_split_long_opt_arg=${1#*=}])
 
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-# func_strip_suffix prefix name
-func_stripname ()
-{
-  case ${2} in
-    .*) func_stripname_result=`$ECHO "X${3}" \
-           | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
-    *)  func_stripname_result=`$ECHO "X${3}" \
-           | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
-  esac
-}
+  _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl
+    func_split_short_opt_arg=${1#??}
+    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}])
 
-# sed scripts:
-my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
-my_sed_long_arg='1s/^-[[^=]]*=//'
+  _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl
+    case ${1} in
+      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+      *)    func_lo2o_result=${1} ;;
+    esac])
 
-# func_opt_split
-func_opt_split ()
-{
-  func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
-  func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
-}
+  _LT_PROG_FUNCTION_REPLACE([func_xform], [    func_xform_result=${1%.*}.lo])
 
-# func_lo2o object
-func_lo2o ()
-{
-  func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
-}
+  _LT_PROG_FUNCTION_REPLACE([func_arith], [    func_arith_result=$(( $[*] ))])
 
-# func_xform libobj-or-source
-func_xform ()
-{
-  func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
-}
+  _LT_PROG_FUNCTION_REPLACE([func_len], [    func_len_result=${#1}])
+fi
 
-# func_arith arithmetic-term...
-func_arith ()
-{
-  func_arith_result=`expr "$[@]"`
-}
+if test x"$lt_shell_append" = xyes; then
+  _LT_PROG_FUNCTION_REPLACE([func_append], [    eval "${1}+=\\${2}"])
 
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
-  func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
-}
+  _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl
+    func_quote_for_eval "${2}"
+dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \
+    eval "${1}+=\\\\ \\$func_quote_for_eval_result"])
 
-_LT_EOF
-esac
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
 
-case $lt_shell_append in
-  yes)
-    cat << \_LT_EOF >> "$cfgfile"
+if test x"$_lt_function_replace_fail" = x":"; then
+  AC_MSG_WARN([Unable to substitute extended shell functions in $ofile])
+fi
+])
 
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
-  eval "$[1]+=\$[2]"
-}
-_LT_EOF
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine which file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
     ;;
-  *)
-    cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
-  eval "$[1]=\$$[1]\$[2]"
-}
-
-_LT_EOF
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
     ;;
-  esac
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+         [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
 ])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+         [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4
index 34151a3..17cfd51 100644
--- a/m4/ltoptions.m4
+++ b/m4/ltoptions.m4
@@ -1,13 +1,14 @@
 # Helper functions for option handling.                    -*- Autoconf -*-
 #
-#   Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+#   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
+#   Inc.
 #   Written by Gary V. Vaughan, 2004
 #
 # This file is free software; the Free Software Foundation gives
 # unlimited permission to copy and/or distribute it, with or without
 # modifications, as long as this notice is preserved.
 
-# serial 6 ltoptions.m4
+# serial 7 ltoptions.m4
 
 # This is to help aclocal find these macros, as it can't see m4_define.
 AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
@@ -125,7 +126,7 @@ LT_OPTION_DEFINE([LT_INIT], [win32-dll],
 [enable_win32_dll=yes
 
 case $host in
-*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
   AC_CHECK_TOOL(AS, as, false)
   AC_CHECK_TOOL(DLLTOOL, dlltool, false)
   AC_CHECK_TOOL(OBJDUMP, objdump, false)
@@ -133,13 +134,13 @@ case $host in
 esac
 
 test -z "$AS" && AS=as
-_LT_DECL([], [AS],      [0], [Assembler program])dnl
+_LT_DECL([], [AS],      [1], [Assembler program])dnl
 
 test -z "$DLLTOOL" && DLLTOOL=dlltool
-_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
 
 test -z "$OBJDUMP" && OBJDUMP=objdump
-_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
 ])# win32-dll
 
 AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
diff --git a/m4/ltversion.m4 b/m4/ltversion.m4
index b8e154f..9c7b5d4 100644
--- a/m4/ltversion.m4
+++ b/m4/ltversion.m4
@@ -7,17 +7,17 @@
 # unlimited permission to copy and/or distribute it, with or without
 # modifications, as long as this notice is preserved.
 
-# Generated from ltversion.in.
+# @configure_input@
 
-# serial 3012 ltversion.m4
+# serial 3293 ltversion.m4
 # This file is part of GNU Libtool
 
-m4_define([LT_PACKAGE_VERSION], [2.2.6])
-m4_define([LT_PACKAGE_REVISION], [1.3012])
+m4_define([LT_PACKAGE_VERSION], [2.4])
+m4_define([LT_PACKAGE_REVISION], [1.3293])
 
 AC_DEFUN([LTVERSION_VERSION],
-[macro_version='2.2.6'
-macro_revision='1.3012'
+[macro_version='2.4'
+macro_revision='1.3293'
 _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
 _LT_DECL(, macro_revision, 0)
 ])
diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4
index 637bb20..c573da9 100644
--- a/m4/lt~obsolete.m4
+++ b/m4/lt~obsolete.m4
@@ -1,13 +1,13 @@
 # lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
 #
-#   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+#   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
 #   Written by Scott James Remnant, 2004.
 #
 # This file is free software; the Free Software Foundation gives
 # unlimited permission to copy and/or distribute it, with or without
 # modifications, as long as this notice is preserved.
 
-# serial 4 lt~obsolete.m4
+# serial 5 lt~obsolete.m4
 
 # These exist entirely to fool aclocal when bootstrapping libtool.
 #
@@ -77,7 +77,6 @@ m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
 m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
 m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
 m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
-m4_ifndef([AC_LIBTOOL_RC],		[AC_DEFUN([AC_LIBTOOL_RC])])
 m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
 m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
 m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
@@ -90,3 +89,10 @@ m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
 m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
 m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
 m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],	[AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP],		[AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],	[AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77],		[AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC],		[AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX],		[AC_DEFUN([_LT_PROG_CXX])])
diff --git a/makegdal71.vcproj b/makegdal71.vcproj
index 8b3c89f..4e00353 100644
--- a/makegdal71.vcproj
+++ b/makegdal71.vcproj
@@ -16,10 +16,10 @@
 			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"/>
+				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc && nmake -f makefile.vc install"
+				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc clean && nmake -f makefile.vc && nmake -f makefile.vc install"
+				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc clean"
+				Output="gdal19.dll"/>
 		</Configuration>
 		<Configuration
 			Name="Release|Win32"
@@ -28,10 +28,10 @@
 			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"/>
+				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc && nmake -f makefile.vc install"
+				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc clean && nmake -f makefile.vc && nmake -f makefile.vc install"
+				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc clean"
+				Output="gdal19.dll"/>
 		</Configuration>
 	</Configurations>
 	<References>
@@ -82,6 +82,9 @@
 				<Filter Name="cosar" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\cosar\makefile.vc" />
 				</Filter>
+				<Filter Name="ctg" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ctg\makefile.vc" />
+				</Filter>
 				<Filter Name="dimap" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\dimap\makefile.vc" />
 				</Filter>
@@ -91,6 +94,9 @@
 				<Filter Name="dted" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\dted\makefile.vc" />
 				</Filter>
+				<Filter Name="e00grid" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\e00grid\makefile.vc" />
+				</Filter>
 				<Filter Name="ecw" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\ecw\makefile.vc" />
 				</Filter>
@@ -139,6 +145,9 @@
 				<Filter Name="gsg" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\gsg\makefile.vc" />
 				</Filter>
+				<Filter Name="gta" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\gta\makefile.vc" />
+				</Filter>
 				<Filter Name="gtiff" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\gtiff\makefile.vc" />
 					<Filter Name="libgeotiff" Filter="*.vc;*.opt    ">
@@ -160,6 +169,9 @@
 				<Filter Name="hdf5" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\hdf5\makefile.vc" />
 				</Filter>
+				<Filter Name="hf2" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\hf2\makefile.vc" />
+				</Filter>
 				<Filter Name="hfa" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\hfa\makefile.vc" />
 				</Filter>
@@ -196,6 +208,12 @@
 				<Filter Name="jpeg2000" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\jpeg2000\makefile.vc" />
 				</Filter>
+				<Filter Name="jpipkak" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\jpipkak\makefile.vc" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\makefile.vc" />
+				</Filter>
 				<Filter Name="l1b" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\l1b\makefile.vc" />
 				</Filter>
@@ -207,6 +225,10 @@
 				</Filter>
 				<Filter Name="mrsid" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\mrsid\makefile.vc" />
+					<File RelativePath=".\frmts\mrsid\nmake.opt" />
+				</Filter>
+				<Filter Name="mrsid_lidar" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\mrsid_lidar\makefile.vc" />
 				</Filter>
 				<Filter Name="msg" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\msg\makefile.vc" />
@@ -217,6 +239,9 @@
 				<Filter Name="netcdf" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\netcdf\makefile.vc" />
 				</Filter>
+				<Filter Name="ngsgeoid" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ngsgeoid\makefile.vc" />
+				</Filter>
 				<Filter Name="nitf" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\nitf\makefile.vc" />
 				</Filter>
@@ -226,6 +251,12 @@
 				<Filter Name="ogdi" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\ogdi\makefile.vc" />
 				</Filter>
+				<Filter Name="openjpeg" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\openjpeg\makefile.vc" />
+				</Filter>
+				<Filter Name="ozi" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ozi\makefile.vc" />
+				</Filter>
 				<Filter Name="pcidsk" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\pcidsk\makefile.vc" />
 					<Filter Name="sdk" Filter="*.vc;*.opt    ">
@@ -238,6 +269,9 @@
 						<File RelativePath=".\frmts\pcraster\libcsf\makefile.vc" />
 					</Filter>
 					</Filter>
+				<Filter Name="pdf" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\pdf\makefile.vc" />
+				</Filter>
 				<Filter Name="pds" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\pds\makefile.vc" />
 				</Filter>
@@ -250,9 +284,15 @@
 						<File RelativePath=".\frmts\png\libpng\makefile.vc" />
 					</Filter>
 					</Filter>
+				<Filter Name="postgisraster" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\postgisraster\makefile.vc" />
+				</Filter>
 				<Filter Name="r" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\r\makefile.vc" />
 				</Filter>
+				<Filter Name="rasdaman" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\rasdaman\makefile.vc" />
+				</Filter>
 				<Filter Name="rasterlite" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\rasterlite\makefile.vc" />
 				</Filter>
@@ -286,9 +326,6 @@
 				<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>
@@ -304,8 +341,8 @@
 				<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 Name="webp" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\webp\makefile.vc" />
 				</Filter>
 				<Filter Name="wms" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\wms\makefile.vc" />
@@ -313,9 +350,15 @@
 				<Filter Name="xpm" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\xpm\makefile.vc" />
 				</Filter>
+				<Filter Name="xyz" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\xyz\makefile.vc" />
+				</Filter>
 				<Filter Name="zlib" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\frmts\zlib\makefile.vc" />
 				</Filter>
+				<Filter Name="zmap" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\zmap\makefile.vc" />
+				</Filter>
 				</Filter>
 			<Filter Name="gcore" Filter="*.vc;*.opt  ">
 				<File RelativePath=".\gcore\makefile.vc" />
@@ -324,12 +367,24 @@
 				<File RelativePath=".\ogr\makefile.vc" />
 				<Filter Name="ogrsf_frmts" Filter="*.vc;*.opt   ">
 					<File RelativePath=".\ogr\ogrsf_frmts\makefile.vc" />
+					<Filter Name="aeronavfaa" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\makefile.vc" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\makefile.vc" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\makefile.vc" />
+					</Filter>
 					<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="couchdb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\makefile.vc" />
+					</Filter>
 					<Filter Name="csv" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\csv\makefile.vc" />
 					</Filter>
@@ -342,9 +397,18 @@
 					<Filter Name="dods" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\dods\makefile.vc" />
 					</Filter>
+					<Filter Name="dwg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\makefile.vc" />
+					</Filter>
 					<Filter Name="dxf" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\dxf\makefile.vc" />
 					</Filter>
+					<Filter Name="edigeo" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\makefile.vc" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\makefile.vc" />
+					</Filter>
 					<Filter Name="fme" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\fme\makefile.vc" />
 					</Filter>
@@ -360,24 +424,39 @@
 							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\makefile.vc" />
 						</Filter>
 						</Filter>
+					<Filter Name="geomedia" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\makefile.vc" />
+					</Filter>
 					<Filter Name="georss" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\georss\makefile.vc" />
 					</Filter>
+					<Filter Name="gft" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\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="gpsbabel" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\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="htf" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\makefile.vc" />
+					</Filter>
 					<Filter Name="idb" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\idb\makefile.vc" />
 					</Filter>
+					<Filter Name="idrisi" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\makefile.vc" />
+					</Filter>
 					<Filter Name="ili" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ili\makefile.vc" />
 						<Filter Name="iom" Filter="*.vc;*.opt     ">
@@ -387,15 +466,24 @@
 					<Filter Name="kml" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\kml\makefile.vc" />
 					</Filter>
+					<Filter Name="libkml" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\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="mssqlspatial" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\makefile.vc" />
+					</Filter>
 					<Filter Name="mysql" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\mysql\makefile.vc" />
 					</Filter>
+					<Filter Name="nas" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\makefile.vc" />
+					</Filter>
 					<Filter Name="ntf" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ntf\makefile.vc" />
 					</Filter>
@@ -408,12 +496,21 @@
 					<Filter Name="ogdi" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\makefile.vc" />
 					</Filter>
+					<Filter Name="openair" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\makefile.vc" />
+					</Filter>
 					<Filter Name="pcidsk" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\makefile.vc" />
 					</Filter>
+					<Filter Name="pds" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\makefile.vc" />
+					</Filter>
 					<Filter Name="pg" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\pg\makefile.vc" />
 					</Filter>
+					<Filter Name="pgdump" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\makefile.vc" />
+					</Filter>
 					<Filter Name="pgeo" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\makefile.vc" />
 					</Filter>
@@ -429,18 +526,42 @@
 					<Filter Name="sdts" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\sdts\makefile.vc" />
 					</Filter>
+					<Filter Name="segukooa" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\makefile.vc" />
+					</Filter>
+					<Filter Name="segy" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\makefile.vc" />
+					</Filter>
 					<Filter Name="shape" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\shape\makefile.vc" />
 					</Filter>
+					<Filter Name="sosi" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\makefile.vc" />
+					</Filter>
 					<Filter Name="sqlite" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\makefile.vc" />
 					</Filter>
+					<Filter Name="sua" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\makefile.vc" />
+					</Filter>
+					<Filter Name="svg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\makefile.vc" />
+					</Filter>
 					<Filter Name="tiger" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\tiger\makefile.vc" />
 					</Filter>
+					<Filter Name="vfk" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\makefile.vc" />
+					</Filter>
 					<Filter Name="vrt" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\vrt\makefile.vc" />
 					</Filter>
+					<Filter Name="wfs" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\makefile.vc" />
+					</Filter>
+					<Filter Name="xls" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\makefile.vc" />
+					</Filter>
 					<Filter Name="xplane" Filter="*.vc;*.opt    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\xplane\makefile.vc" />
 					</Filter>
@@ -458,11 +579,15 @@
 			<Filter Name="alg" Filter="*.h  ">
 				<File RelativePath=".\alg\gdalgrid.h" />
 				<File RelativePath=".\alg\gdalwarper.h" />
+				<File RelativePath=".\alg\gdalwarpkernel_opencl.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="apps" Filter="*.h  ">
+				<File RelativePath=".\apps\commonutils.h" />
+			</Filter>
 			<Filter Name="bridge" Filter="*.h  ">
 				<File RelativePath=".\bridge\gdalbridge.h" />
 			</Filter>
@@ -485,12 +610,15 @@
 				<Filter Name="dted" Filter="*.h   ">
 					<File RelativePath=".\frmts\dted\dted_api.h" />
 				</Filter>
+				<Filter Name="e00grid" Filter="*.h   ">
+					<File RelativePath=".\frmts\e00grid\e00compr.h" />
+				</Filter>
 				<Filter Name="ecw" Filter="*.h   ">
-					<File RelativePath=".\frmts\ecw\jp2userbox.h" />
-					<File RelativePath=".\frmts\ecw\vsiiostream.h" />
+					<File RelativePath=".\frmts\ecw\gdal_ecw.h" />
 				</Filter>
 				<Filter Name="envisat" Filter="*.h   ">
 					<File RelativePath=".\frmts\envisat\EnvisatFile.h" />
+					<File RelativePath=".\frmts\envisat\records.h" />
 				</Filter>
 				<Filter Name="ers" Filter="*.h   ">
 					<File RelativePath=".\frmts\ers\ershdrnode.h" />
@@ -505,6 +633,7 @@
 					<File RelativePath=".\frmts\georaster\oci_wrapper.h" />
 				</Filter>
 				<Filter Name="gif" Filter="*.h   ">
+					<File RelativePath=".\frmts\gif\gifabstractdataset.h" />
 					<Filter Name="giflib" Filter="*.h    ">
 						<File RelativePath=".\frmts\gif\giflib\gif_hash.h" />
 						<File RelativePath=".\frmts\gif\giflib\gif_lib.h" />
@@ -544,9 +673,16 @@
 						</Filter>
 						</Filter>
 				<Filter Name="gtiff" Filter="*.h   ">
+					<File RelativePath=".\frmts\gtiff\gtiff.h" />
+					<File RelativePath=".\frmts\gtiff\gt_citation.h" />
 					<File RelativePath=".\frmts\gtiff\gt_overview.h" />
+					<File RelativePath=".\frmts\gtiff\gt_wkt_srs.h" />
+					<File RelativePath=".\frmts\gtiff\gt_wkt_srs_for_gdal.h" />
+					<File RelativePath=".\frmts\gtiff\tifvsi.h" />
+					<File RelativePath=".\frmts\gtiff\tif_float.h" />
 					<Filter Name="libgeotiff" Filter="*.h    ">
 						<File RelativePath=".\frmts\gtiff\libgeotiff\cpl_serv.h" />
+						<File RelativePath=".\frmts\gtiff\libgeotiff\gdal_libgeotiff_symbol_rename.h" />
 						<File RelativePath=".\frmts\gtiff\libgeotiff\geokeys.h" />
 						<File RelativePath=".\frmts\gtiff\libgeotiff\geonames.h" />
 						<File RelativePath=".\frmts\gtiff\libgeotiff\geotiff.h" />
@@ -560,6 +696,7 @@
 						<File RelativePath=".\frmts\gtiff\libgeotiff\xtiffio.h" />
 					</Filter>
 					<Filter Name="libtiff" Filter="*.h    ">
+						<File RelativePath=".\frmts\gtiff\libtiff\gdal_libtiff_symbol_rename.h" />
 						<File RelativePath=".\frmts\gtiff\libtiff\t4.h" />
 						<File RelativePath=".\frmts\gtiff\libtiff\tiff.h" />
 						<File RelativePath=".\frmts\gtiff\libtiff\tiffconf.h" />
@@ -593,6 +730,9 @@
 					<File RelativePath=".\frmts\hfa\hfa.h" />
 					<File RelativePath=".\frmts\hfa\hfa_p.h" />
 				</Filter>
+				<Filter Name="idrisi" Filter="*.h   ">
+					<File RelativePath=".\frmts\idrisi\idrisi.h" />
+				</Filter>
 				<Filter Name="ilwis" Filter="*.h   ">
 					<File RelativePath=".\frmts\ilwis\ilwisdataset.h" />
 				</Filter>
@@ -641,6 +781,12 @@
 				<Filter Name="jpeg2000" Filter="*.h   ">
 					<File RelativePath=".\frmts\jpeg2000\jpeg2000_vsil_io.h" />
 				</Filter>
+				<Filter Name="jpipkak" Filter="*.h   ">
+					<File RelativePath=".\frmts\jpipkak\jpipkakdataset.h" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.h   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.h" />
+				</Filter>
 				<Filter Name="mem" Filter="*.h   ">
 					<File RelativePath=".\frmts\mem\memdataset.h" />
 				</Filter>
@@ -663,6 +809,7 @@
 				</Filter>
 				<Filter Name="nitf" Filter="*.h   ">
 					<File RelativePath=".\frmts\nitf\mgrs.h" />
+					<File RelativePath=".\frmts\nitf\nitfdataset.h" />
 					<File RelativePath=".\frmts\nitf\nitflib.h" />
 					<File RelativePath=".\frmts\nitf\rpftoclib.h" />
 				</Filter>
@@ -673,27 +820,41 @@
 					<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_ads40.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_airphoto.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_array.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_binary.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_edb.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_ephemeris.h" />
 						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_exception.h" />
 						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_file.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_gcp.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_gcpsegment.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_poly.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_rpc.h" />
 						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_segment.h" />
 						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_shape.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_tex.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_toutin.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\cexternalchannel.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\clinksegment.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" />
@@ -702,16 +863,28 @@
 							<File RelativePath=".\frmts\pcidsk\sdk\core\sysvirtualfile.h" />
 						</Filter>
 						<Filter Name="segment" Filter="*.h     ">
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskads40model.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskapmodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbinarysegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbitmap.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskephemerissegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgcp2segment.h" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.h" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpolymodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskrpcmodel.h" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsktoutinmodel.h" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_array.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_tex.h" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment.h" />
-							<File RelativePath=".\frmts\pcidsk\sdk\segment\pcidskgeorefbuilder.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\orbitstructures.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" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\toutinstructures.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegdataindex.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegheader.h" />
 						</Filter>
 						</Filter>
 						</Filter>
@@ -727,6 +900,10 @@
 						<File RelativePath=".\frmts\pcraster\libcsf\pcrtypes.h" />
 					</Filter>
 					</Filter>
+				<Filter Name="pdf" Filter="*.h   ">
+					<File RelativePath=".\frmts\pdf\pdfio.h" />
+					<File RelativePath=".\frmts\pdf\pdfobject.h" />
+				</Filter>
 				<Filter Name="pds" Filter="*.h   ">
 					<File RelativePath=".\frmts\pds\nasakeywordhandler.h" />
 				</Filter>
@@ -739,6 +916,12 @@
 						<File RelativePath=".\frmts\png\libpng\pngconf.h" />
 					</Filter>
 					</Filter>
+				<Filter Name="postgisraster" Filter="*.h   ">
+					<File RelativePath=".\frmts\postgisraster\postgisraster.h" />
+				</Filter>
+				<Filter Name="rasdaman" Filter="*.h   ">
+					<File RelativePath=".\frmts\rasdaman\rasdamandataset.h" />
+				</Filter>
 				<Filter Name="rasterlite" Filter="*.h   ">
 					<File RelativePath=".\frmts\rasterlite\rasterlitedataset.h" />
 				</Filter>
@@ -758,26 +941,22 @@
 				<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_tiled_wms.h" />
 					<File RelativePath=".\frmts\wms\minidriver_tileservice.h" />
 					<File RelativePath=".\frmts\wms\minidriver_tms.h" />
+					<File RelativePath=".\frmts\wms\minidriver_virtualearth.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" />
+					<File RelativePath=".\frmts\wms\wmsmetadataset.h" />
 				</Filter>
 				<Filter Name="zlib" Filter="*.h   ">
 					<File RelativePath=".\frmts\zlib\crc32.h" />
@@ -803,6 +982,8 @@
 				<File RelativePath=".\gcore\gdal_version.h" />
 			</Filter>
 			<Filter Name="ogr" Filter="*.h  ">
+				<File RelativePath=".\ogr\ogrgeomediageometry.h" />
+				<File RelativePath=".\ogr\ogrpgeogeometry.h" />
 				<File RelativePath=".\ogr\ogr_api.h" />
 				<File RelativePath=".\ogr\ogr_core.h" />
 				<File RelativePath=".\ogr\ogr_expat.h" />
@@ -818,6 +999,16 @@
 				<Filter Name="ogrsf_frmts" Filter="*.h   ">
 					<File RelativePath=".\ogr\ogrsf_frmts\ogrsf_frmts.h" />
 					<File RelativePath=".\ogr\ogrsf_frmts\ogr_attrind.h" />
+					<Filter Name="aeronavfaa" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ogr_aeronavfaa.h" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ogr_arcgen.h" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aoutils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\ogr_ao.h" />
+					</Filter>
 					<Filter Name="avc" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_mbyte.h" />
@@ -828,6 +1019,9 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogr_bna.h" />
 					</Filter>
+					<Filter Name="couchdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogr_couchdb.h" />
+					</Filter>
 					<Filter Name="csv" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\csv\ogr_csv.h" />
 					</Filter>
@@ -842,9 +1036,21 @@
 					<Filter Name="dods" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogr_dods.h" />
 					</Filter>
+					<Filter Name="dwg" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogr_dwg.h" />
+					</Filter>
 					<Filter Name="dxf" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_polyline_smooth.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_autocad_services.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_dxf.h" />
 					</Filter>
+					<Filter Name="edigeo" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogr_edigeo.h" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbUtils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\ogr_fgdb.h" />
+					</Filter>
 					<Filter Name="fme" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr.h" />
 					</Filter>
@@ -877,17 +1083,28 @@
 							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.h" />
 						</Filter>
 						</Filter>
+					<Filter Name="geomedia" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogr_geomedia.h" />
+					</Filter>
 					<Filter Name="georss" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\georss\ogr_georss.h" />
 					</Filter>
+					<Filter Name="gft" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogr_gft.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\gmlutils.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\gml\ogr_gml.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\parsexsd.h" />
 					</Filter>
 					<Filter Name="gmt" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\gmt\ogr_gmt.h" />
 					</Filter>
+					<Filter Name="gpsbabel" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogr_gpsbabel.h" />
+					</Filter>
 					<Filter Name="gpx" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\gpx\ogr_gpx.h" />
 					</Filter>
@@ -898,9 +1115,15 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\gtm\gtm.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\gtm\ogr_gtm.h" />
 					</Filter>
+					<Filter Name="htf" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogr_htf.h" />
+					</Filter>
 					<Filter Name="idb" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogr_idb.h" />
 					</Filter>
+					<Filter Name="idrisi" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogr_idrisi.h" />
+					</Filter>
 					<Filter Name="ili" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili1readerp.h" />
@@ -925,6 +1148,17 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\kml\kmlvector.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogr_kml.h" />
 					</Filter>
+					<Filter Name="libkml" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeature.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeaturestyle.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfield.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlgeometry.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlstyle.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogr_libkml.h" />
+					</Filter>
+					<Filter Name="mdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogr_mdb.h" />
+					</Filter>
 					<Filter Name="mem" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\mem\ogr_mem.h" />
 					</Filter>
@@ -935,9 +1169,16 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_priv.h" />
 						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.h" />
 					</Filter>
+					<Filter Name="mssqlspatial" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogr_mssqlspatial.h" />
+					</Filter>
 					<Filter Name="mysql" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogr_mysql.h" />
 					</Filter>
+					<Filter Name="nas" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nasreaderp.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogr_nas.h" />
+					</Filter>
 					<Filter Name="ntf" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntf.h" />
 					</Filter>
@@ -950,13 +1191,22 @@
 					<Filter Name="ogdi" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdi.h" />
 					</Filter>
+					<Filter Name="openair" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogr_openair.h" />
+					</Filter>
 					<Filter Name="pcidsk" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogr_pcidsk.h" />
 					</Filter>
+					<Filter Name="pds" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogr_pds.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="pgdump" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogr_pgdump.h" />
+					</Filter>
 					<Filter Name="pgeo" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogr_pgeo.h" />
 					</Filter>
@@ -974,19 +1224,45 @@
 					<Filter Name="sdts" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\sdts\ogr_sdts.h" />
 					</Filter>
+					<Filter Name="segukooa" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogr_segukooa.h" />
+					</Filter>
+					<Filter Name="segy" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogr_segy.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="sosi" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogr_sosi.h" />
+					</Filter>
 					<Filter Name="sqlite" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogr_sqlite.h" />
 					</Filter>
+					<Filter Name="sua" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogr_sua.h" />
+					</Filter>
+					<Filter Name="svg" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogr_svg.h" />
+					</Filter>
 					<Filter Name="tiger" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogr_tiger.h" />
 					</Filter>
+					<Filter Name="vfk" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogr_vfk.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreaderp.h" />
+					</Filter>
 					<Filter Name="vrt" Filter="*.h    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\vrt\ogr_vrt.h" />
 					</Filter>
+					<Filter Name="wfs" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogr_wfs.h" />
+					</Filter>
+					<Filter Name="xls" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogr_xls.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" />
@@ -1012,6 +1288,7 @@
 				<File RelativePath=".\port\cpl_minixml.h" />
 				<File RelativePath=".\port\cpl_minizip_ioapi.h" />
 				<File RelativePath=".\port\cpl_minizip_unzip.h" />
+				<File RelativePath=".\port\cpl_minizip_zip.h" />
 				<File RelativePath=".\port\cpl_multiproc.h" />
 				<File RelativePath=".\port\cpl_odbc.h" />
 				<File RelativePath=".\port\cpl_port.h" />
@@ -1022,13 +1299,16 @@
 				<File RelativePath=".\port\cpl_vsi_virtual.h" />
 				<File RelativePath=".\port\cpl_win32ce_api.h" />
 				<File RelativePath=".\port\cpl_wince.h" />
+				<File RelativePath=".\port\gdal_csv.h" />
 			</Filter>
 			</Filter>
 		<Filter Name="Source Files" Filter="*.c;*.cpp ">
 			<Filter Name="alg" Filter="*.c;*.cpp  ">
+				<File RelativePath=".\alg\gdalwarpkernel_opencl.c" />
 				<File RelativePath=".\alg\gdal_crs.c" />
 				<File RelativePath=".\alg\gdal_nrgcrs.c" />
 				<File RelativePath=".\alg\contour.cpp" />
+				<File RelativePath=".\alg\fpolygonize.cpp" />
 				<File RelativePath=".\alg\gdalchecksum.cpp" />
 				<File RelativePath=".\alg\gdalcutline.cpp" />
 				<File RelativePath=".\alg\gdaldither.cpp" />
@@ -1036,6 +1316,7 @@
 				<File RelativePath=".\alg\gdalgrid.cpp" />
 				<File RelativePath=".\alg\gdalmediancut.cpp" />
 				<File RelativePath=".\alg\gdalproximity.cpp" />
+				<File RelativePath=".\alg\gdalrasterfpolygonenumerator.cpp" />
 				<File RelativePath=".\alg\gdalrasterize.cpp" />
 				<File RelativePath=".\alg\gdalrasterpolygonenumerator.cpp" />
 				<File RelativePath=".\alg\gdalsievefilter.cpp" />
@@ -1057,12 +1338,16 @@
 				<File RelativePath=".\apps\gdalinfo.c" />
 				<File RelativePath=".\apps\gdaltindex.c" />
 				<File RelativePath=".\apps\gdalwarpsimple.c" />
+				<File RelativePath=".\apps\commonutils.cpp" />
 				<File RelativePath=".\apps\dumpoverviews.cpp" />
 				<File RelativePath=".\apps\gdaladdo.cpp" />
+				<File RelativePath=".\apps\gdalasyncread.cpp" />
 				<File RelativePath=".\apps\gdalbuildvrt.cpp" />
 				<File RelativePath=".\apps\gdaldem.cpp" />
 				<File RelativePath=".\apps\gdalenhance.cpp" />
+				<File RelativePath=".\apps\gdallocationinfo.cpp" />
 				<File RelativePath=".\apps\gdalmanage.cpp" />
+				<File RelativePath=".\apps\gdalsrsinfo.cpp" />
 				<File RelativePath=".\apps\gdaltorture.cpp" />
 				<File RelativePath=".\apps\gdaltransform.cpp" />
 				<File RelativePath=".\apps\gdalwarp.cpp" />
@@ -1077,6 +1362,7 @@
 				<File RelativePath=".\apps\ogrinfo.cpp" />
 				<File RelativePath=".\apps\ogrtindex.cpp" />
 				<File RelativePath=".\apps\testepsg.cpp" />
+				<File RelativePath=".\apps\testreprojmulti.cpp" />
 				<File RelativePath=".\apps\test_ogrsf.cpp" />
 			</Filter>
 			<Filter Name="bridge" Filter="*.c;*.cpp  ">
@@ -1133,6 +1419,9 @@
 				<Filter Name="cosar" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\cosar\cosar_dataset.cpp" />
 				</Filter>
+				<Filter Name="ctg" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ctg\ctgdataset.cpp" />
+				</Filter>
 				<Filter Name="dimap" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\dimap\dimapdataset.cpp" />
 				</Filter>
@@ -1146,7 +1435,12 @@
 					<File RelativePath=".\frmts\dted\dted_test.c" />
 					<File RelativePath=".\frmts\dted\dteddataset.cpp" />
 				</Filter>
+				<Filter Name="e00grid" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\e00grid\e00read.c" />
+					<File RelativePath=".\frmts\e00grid\e00griddataset.cpp" />
+				</Filter>
 				<Filter Name="ecw" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ecw\ecwasyncreader.cpp" />
 					<File RelativePath=".\frmts\ecw\ecwcreatecopy.cpp" />
 					<File RelativePath=".\frmts\ecw\ecwdataset.cpp" />
 					<File RelativePath=".\frmts\ecw\jp2userbox.cpp" />
@@ -1158,6 +1452,7 @@
 					<File RelativePath=".\frmts\envisat\dumpgeo.c" />
 					<File RelativePath=".\frmts\envisat\EnvisatFile.c" />
 					<File RelativePath=".\frmts\envisat\envisat_dump.c" />
+					<File RelativePath=".\frmts\envisat\records.c" />
 					<File RelativePath=".\frmts\envisat\envisatdataset.cpp" />
 				</Filter>
 				<Filter Name="epsilon" Filter="*.c;*.cpp   ">
@@ -1176,7 +1471,6 @@
 				</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" />
@@ -1186,6 +1480,7 @@
 				</Filter>
 				<Filter Name="gif" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\gif\biggifdataset.cpp" />
+					<File RelativePath=".\frmts\gif\gifabstractdataset.cpp" />
 					<File RelativePath=".\frmts\gif\gifdataset.cpp" />
 					<Filter Name="giflib" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\frmts\gif\giflib\dgif_lib.c" />
@@ -1277,6 +1572,9 @@
 					<File RelativePath=".\frmts\gsg\gsagdataset.cpp" />
 					<File RelativePath=".\frmts\gsg\gsbgdataset.cpp" />
 				</Filter>
+				<Filter Name="gta" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\gta\gtadataset.cpp" />
+				</Filter>
 				<Filter Name="gtiff" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\gtiff\tif_float.c" />
 					<File RelativePath=".\frmts\gtiff\geotiff.cpp" />
@@ -1320,6 +1618,7 @@
 						<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_lzma.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" />
@@ -1363,6 +1662,9 @@
 					<File RelativePath=".\frmts\hdf5\hdf5imagedataset.cpp" />
 					<File RelativePath=".\frmts\hdf5\iso19115_srs.cpp" />
 				</Filter>
+				<Filter Name="hf2" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\hf2\hf2dataset.cpp" />
+				</Filter>
 				<Filter Name="hfa" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\hfa\hfaband.cpp" />
 					<File RelativePath=".\frmts\hfa\hfacompress.cpp" />
@@ -1514,6 +1816,15 @@
 					<File RelativePath=".\frmts\jpeg2000\jpeg2000dataset.cpp" />
 					<File RelativePath=".\frmts\jpeg2000\jpeg2000_vsil_io.cpp" />
 				</Filter>
+				<Filter Name="jpegls" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\jpegls\jpeglsdataset.cpp" />
+				</Filter>
+				<Filter Name="jpipkak" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\jpipkak\jpipkakdataset.cpp" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.cpp" />
+				</Filter>
 				<Filter Name="l1b" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\l1b\l1bdataset.cpp" />
 				</Filter>
@@ -1527,6 +1838,9 @@
 					<File RelativePath=".\frmts\mrsid\mrsiddataset.cpp" />
 					<File RelativePath=".\frmts\mrsid\mrsidstream.cpp" />
 				</Filter>
+				<Filter Name="mrsid_lidar" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\mrsid_lidar\gdal_MG4Lidar.cpp" />
+				</Filter>
 				<Filter Name="msg" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\msg\msgcommand.cpp" />
 					<File RelativePath=".\frmts\msg\msgdataset.cpp" />
@@ -1543,16 +1857,23 @@
 					<File RelativePath=".\frmts\netcdf\gmtdataset.cpp" />
 					<File RelativePath=".\frmts\netcdf\netcdfdataset.cpp" />
 				</Filter>
+				<Filter Name="ngsgeoid" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ngsgeoid\ngsgeoiddataset.cpp" />
+				</Filter>
 				<Filter Name="nitf" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\nitf\mgrs.c" />
+					<File RelativePath=".\frmts\nitf\nitfdes.c" />
 					<File RelativePath=".\frmts\nitf\nitfdump.c" />
 					<File RelativePath=".\frmts\nitf\nitffile.c" />
 					<File RelativePath=".\frmts\nitf\nitfimage.c" />
+					<File RelativePath=".\frmts\nitf\ecrgtocdataset.cpp" />
 					<File RelativePath=".\frmts\nitf\nitfaridpcm.cpp" />
 					<File RelativePath=".\frmts\nitf\nitfbilevel.cpp" />
 					<File RelativePath=".\frmts\nitf\nitfdataset.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfrasterband.cpp" />
 					<File RelativePath=".\frmts\nitf\nitfwritejpeg.cpp" />
 					<File RelativePath=".\frmts\nitf\nitfwritejpeg_12.cpp" />
+					<File RelativePath=".\frmts\nitf\nitf_gcprpc.cpp" />
 					<File RelativePath=".\frmts\nitf\rpftocdataset.cpp" />
 					<File RelativePath=".\frmts\nitf\rpftocfile.cpp" />
 				</Filter>
@@ -1564,7 +1885,14 @@
 				<Filter Name="ogdi" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\ogdi\ogdidataset.cpp" />
 				</Filter>
+				<Filter Name="openjpeg" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\openjpeg\openjpegdataset.cpp" />
+				</Filter>
+				<Filter Name="ozi" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ozi\ozidataset.cpp" />
+				</Filter>
 				<Filter Name="pcidsk" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\pcidsk\gdal_edb.cpp" />
 					<File RelativePath=".\frmts\pcidsk\pcidskdataset.cpp" />
 					<File RelativePath=".\frmts\pcidsk\pcidskdataset2.cpp" />
 					<File RelativePath=".\frmts\pcidsk\pcidsktiledrasterband.cpp" />
@@ -1572,12 +1900,15 @@
 					<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\cexternalchannel.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\clinksegment.cpp" />
 							<File RelativePath=".\frmts\pcidsk\sdk\core\cpcidskfile.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\core\edb_pcidsk.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" />
@@ -1596,14 +1927,25 @@
 							<File RelativePath=".\frmts\pcidsk\sdk\port\win32_mutex.cpp" />
 						</Filter>
 						<Filter Name="segment" Filter="*.c;*.cpp     ">
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskads40model.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskapmodel.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbinarysegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbitmap.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskephemerissegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgcp2segment.cpp" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.cpp" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskrpcmodel.cpp" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsktoutinmodel.cpp" />
 							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment_consistencycheck.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_array.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_tex.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" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegdataindex.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegheader.cpp" />
 						</Filter>
 						</Filter>
 						</Filter>
@@ -1685,6 +2027,11 @@
 						<File RelativePath=".\frmts\pcraster\libcsf\_rputrow.c" />
 					</Filter>
 					</Filter>
+				<Filter Name="pdf" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\pdf\pdfdataset.cpp" />
+					<File RelativePath=".\frmts\pdf\pdfio.cpp" />
+					<File RelativePath=".\frmts\pdf\pdfobject.cpp" />
+				</Filter>
 				<Filter Name="pds" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\pds\isis2dataset.cpp" />
 					<File RelativePath=".\frmts\pds\isis3dataset.cpp" />
@@ -1718,16 +2065,25 @@
 						<File RelativePath=".\frmts\png\libpng\pngwutil.c" />
 					</Filter>
 					</Filter>
+				<Filter Name="postgisraster" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\postgisraster\postgisrasterdataset.cpp" />
+					<File RelativePath=".\frmts\postgisraster\postgisrasterdriver.cpp" />
+					<File RelativePath=".\frmts\postgisraster\postgisrasterrasterband.cpp" />
+				</Filter>
 				<Filter Name="r" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\r\rcreatecopy.cpp" />
 					<File RelativePath=".\frmts\r\rdataset.cpp" />
 				</Filter>
+				<Filter Name="rasdaman" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\rasdaman\rasdamandataset.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\ace2dataset.cpp" />
 					<File RelativePath=".\frmts\raw\atlsci_spheroid.cpp" />
 					<File RelativePath=".\frmts\raw\btdataset.cpp" />
 					<File RelativePath=".\frmts\raw\cpgdataset.cpp" />
@@ -1741,21 +2097,26 @@
 					<File RelativePath=".\frmts\raw\fujibasdataset.cpp" />
 					<File RelativePath=".\frmts\raw\genbindataset.cpp" />
 					<File RelativePath=".\frmts\raw\gscdataset.cpp" />
+					<File RelativePath=".\frmts\raw\gtxdataset.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\loslasdataset.cpp" />
 					<File RelativePath=".\frmts\raw\mffdataset.cpp" />
 					<File RelativePath=".\frmts\raw\ndfdataset.cpp" />
+					<File RelativePath=".\frmts\raw\ntv2dataset.cpp" />
 					<File RelativePath=".\frmts\raw\pauxdataset.cpp" />
 					<File RelativePath=".\frmts\raw\pnmdataset.cpp" />
 					<File RelativePath=".\frmts\raw\rawdataset.cpp" />
+					<File RelativePath=".\frmts\raw\snodasdataset.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\rmfdem.cpp" />
 					<File RelativePath=".\frmts\rmf\rmflzw.cpp" />
 				</Filter>
 				<Filter Name="rs2" Filter="*.c;*.cpp   ">
@@ -1793,10 +2154,6 @@
 				<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>
@@ -1822,10 +2179,8 @@
 					<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 Name="webp" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\webp\webpdataset.cpp" />
 				</Filter>
 				<Filter Name="wms" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\wms\cache.cpp" />
@@ -1833,17 +2188,23 @@
 					<File RelativePath=".\frmts\wms\gdalhttp.cpp" />
 					<File RelativePath=".\frmts\wms\md5.cpp" />
 					<File RelativePath=".\frmts\wms\minidriver.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_tiled_wms.cpp" />
 					<File RelativePath=".\frmts\wms\minidriver_tileservice.cpp" />
 					<File RelativePath=".\frmts\wms\minidriver_tms.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_virtualearth.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" />
+					<File RelativePath=".\frmts\wms\wmsmetadataset.cpp" />
 				</Filter>
 				<Filter Name="xpm" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\xpm\xpmdataset.cpp" />
 				</Filter>
+				<Filter Name="xyz" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\xyz\xyzdataset.cpp" />
+				</Filter>
 				<Filter Name="zlib" Filter="*.c;*.cpp   ">
 					<File RelativePath=".\frmts\zlib\adler32.c" />
 					<File RelativePath=".\frmts\zlib\compress.c" />
@@ -1858,12 +2219,17 @@
 					<File RelativePath=".\frmts\zlib\uncompr.c" />
 					<File RelativePath=".\frmts\zlib\zutil.c" />
 				</Filter>
+				<Filter Name="zmap" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\zmap\zmapdataset.cpp" />
+				</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\gdaldefaultasync.cpp" />
 				<File RelativePath=".\gcore\gdaldefaultoverviews.cpp" />
+				<File RelativePath=".\gcore\gdaldllmain.cpp" />
 				<File RelativePath=".\gcore\gdaldriver.cpp" />
 				<File RelativePath=".\gcore\gdaldrivermanager.cpp" />
 				<File RelativePath=".\gcore\gdalgmlcoverage.cpp" />
@@ -1889,7 +2255,6 @@
 			</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" />
@@ -1900,6 +2265,7 @@
 				<File RelativePath=".\ogr\ogrfeaturequery.cpp" />
 				<File RelativePath=".\ogr\ogrfeaturestyle.cpp" />
 				<File RelativePath=".\ogr\ogrfielddefn.cpp" />
+				<File RelativePath=".\ogr\ogrgeomediageometry.cpp" />
 				<File RelativePath=".\ogr\ogrgeometry.cpp" />
 				<File RelativePath=".\ogr\ogrgeometrycollection.cpp" />
 				<File RelativePath=".\ogr\ogrgeometryfactory.cpp" />
@@ -1908,6 +2274,7 @@
 				<File RelativePath=".\ogr\ogrmultilinestring.cpp" />
 				<File RelativePath=".\ogr\ogrmultipoint.cpp" />
 				<File RelativePath=".\ogr\ogrmultipolygon.cpp" />
+				<File RelativePath=".\ogr\ogrpgeogeometry.cpp" />
 				<File RelativePath=".\ogr\ogrpoint.cpp" />
 				<File RelativePath=".\ogr\ogrpolygon.cpp" />
 				<File RelativePath=".\ogr\ogrspatialreference.cpp" />
@@ -1928,7 +2295,29 @@
 				<File RelativePath=".\ogr\ogr_srs_usgs.cpp" />
 				<File RelativePath=".\ogr\ogr_srs_validate.cpp" />
 				<File RelativePath=".\ogr\ogr_srs_xml.cpp" />
+				<File RelativePath=".\ogr\swq.cpp" />
+				<File RelativePath=".\ogr\swq_expr_node.cpp" />
+				<File RelativePath=".\ogr\swq_op_general.cpp" />
+				<File RelativePath=".\ogr\swq_op_registrar.cpp" />
+				<File RelativePath=".\ogr\swq_parser.cpp" />
+				<File RelativePath=".\ogr\swq_select.cpp" />
 				<Filter Name="ogrsf_frmts" Filter="*.c;*.cpp   ">
+					<Filter Name="aeronavfaa" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaalayer.cpp" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgendatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgendriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgenlayer.cpp" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aodatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aodriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aolayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aoutils.cpp" />
+					</Filter>
 					<Filter Name="avc" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_bin.c" />
 						<File RelativePath=".\ogr\ogrsf_frmts\avc\avc_binwr.c" />
@@ -1954,6 +2343,13 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnalayer.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\bna\ogrbnaparser.cpp" />
 					</Filter>
+					<Filter Name="couchdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdblayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbrowslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbtablelayer.cpp" />
+					</Filter>
 					<Filter Name="csv" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdatasource.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\csv\ogrcsvdriver.cpp" />
@@ -1980,15 +2376,41 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodslayer.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogrdodssequencelayer.cpp" />
 					</Filter>
+					<Filter Name="dwg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgblockslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwglayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_blockmap.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_dimension.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_hatch.cpp" />
+					</Filter>
 					<Filter Name="dxf" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\intronurbs.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfblockslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfblockswriterlayer.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\ogrdxfreader.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" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_hatch.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_polyline_smooth.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_autocad_services.cpp" />
+					</Filter>
+					<Filter Name="edigeo" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeodatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeodriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeolayer.cpp" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbDatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbDriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbLayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbUtils.cpp" />
 					</Filter>
 					<Filter Name="fme" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\fme\fme2ogr_utils.cpp" />
@@ -2017,6 +2439,7 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\geoconcept\ogrgeoconceptlayer.cpp" />
 					</Filter>
 					<Filter Name="geojson" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geojson\ogresrijsonreader.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" />
@@ -2033,30 +2456,53 @@
 							<File RelativePath=".\ogr\ogrsf_frmts\geojson\jsonc\printbuf.c" />
 						</Filter>
 						</Filter>
+					<Filter Name="geomedia" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomedialayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediaselectlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediatablelayer.cpp" />
+					</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="gft" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftresultlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgfttablelayer.cpp" />
+					</Filter>
 					<Filter Name="gml" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\gfstemplate.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\gmlutils.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\hugefileresolver.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" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\trstring.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="gpsbabel" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabeldatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabeldriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabelfork.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabelwritedatasource.cpp" />
+					</Filter>
 					<Filter Name="gpx" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdatasource.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\gpx\ogrgpxdriver.cpp" />
@@ -2075,6 +2521,11 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmdriver.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\gtm\ogrgtmlayer.cpp" />
 					</Filter>
+					<Filter Name="htf" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtfdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtfdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtflayer.cpp" />
+					</Filter>
 					<Filter Name="idb" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdatasource.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbdriver.cpp" />
@@ -2082,6 +2533,12 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbselectlayer.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogridbtablelayer.cpp" />
 					</Filter>
+					<Filter Name="idrisi" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\generate_test_files.c" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisidatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisidriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisilayer.cpp" />
+					</Filter>
 					<Filter Name="ili" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili1reader.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\ili\ili2handler.cpp" />
@@ -2126,6 +2583,22 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmldriver.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\kml\ogrkmllayer.cpp" />
 					</Filter>
+					<Filter Name="libkml" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmldatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmldriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeature.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeaturestyle.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfield.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlgeometry.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmllayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlstyle.cpp" />
+					</Filter>
+					<Filter Name="mdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbjackcess.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdblayer.cpp" />
+					</Filter>
 					<Filter Name="mem" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdatasource.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\mem\ogrmemdriver.cpp" />
@@ -2159,6 +2632,15 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_tooldef.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\mitab\mitab_utils.cpp" />
 					</Filter>
+					<Filter Name="mssqlspatial" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlgeometryparser.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlgeometryvalidator.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatiallayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialselectlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialtablelayer.cpp" />
+					</Filter>
 					<Filter Name="mysql" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldatasource.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqldriver.cpp" />
@@ -2166,6 +2648,14 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqlresultlayer.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogrmysqltablelayer.cpp" />
 					</Filter>
+					<Filter Name="nas" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nashandler.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nasreader.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnaslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasrelationlayer.cpp" />
+					</Filter>
 					<Filter Name="ntf" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntfdump.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\ntf\ntffilereader.cpp" />
@@ -2208,18 +2698,34 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdidriver.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\ogdi\ogrogdilayer.cpp" />
 					</Filter>
+					<Filter Name="openair" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairlabellayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairlayer.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="pds" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdslayer.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" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgutility.cpp" />
+					</Filter>
+					<Filter Name="pgdump" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumpdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumpdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumplayer.cpp" />
 					</Filter>
 					<Filter Name="pgeo" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\pgeo\ogrpgeodatasource.cpp" />
@@ -2256,6 +2762,16 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtsdriver.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\sdts\ogrsdtslayer.cpp" />
 					</Filter>
+					<Filter Name="segukooa" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooalayer.cpp" />
+					</Filter>
+					<Filter Name="segy" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegydatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegydriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegylayer.cpp" />
+					</Filter>
 					<Filter Name="shape" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\shape\dbfopen.c" />
 						<File RelativePath=".\ogr\ogrsf_frmts\shape\shpopen.c" />
@@ -2266,12 +2782,31 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\shape\ogrshapelayer.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\shape\shape2ogr.cpp" />
 					</Filter>
+					<Filter Name="sosi" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\fyba_melding.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosidatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosidriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosilayer.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\ogrsqlitesinglefeaturelayer.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitevfs.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqliteviewlayer.cpp" />
+					</Filter>
+					<Filter Name="sua" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsuadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsuadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsualayer.cpp" />
+					</Filter>
+					<Filter Name="svg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvgdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvgdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvglayer.cpp" />
 					</Filter>
 					<Filter Name="tiger" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogrtigerdatasource.cpp" />
@@ -2300,11 +2835,32 @@
 						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipcodes.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\tiger\tigerzipplus4.cpp" />
 					</Filter>
+					<Filter Name="vfk" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfklayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkdatablock.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkfeature.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkproperty.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkpropertydefn.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.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="wfs" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsfilter.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfslayer.cpp" />
+					</Filter>
+					<Filter Name="xls" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlslayer.cpp" />
+					</Filter>
 					<Filter Name="xplane" Filter="*.c;*.cpp    ">
 						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedatasource.cpp" />
 						<File RelativePath=".\ogr\ogrsf_frmts\xplane\ogrxplanedriver.cpp" />
@@ -2327,7 +2883,9 @@
 				<File RelativePath=".\port\cplgetsymbol.cpp" />
 				<File RelativePath=".\port\cplkeywordparser.cpp" />
 				<File RelativePath=".\port\cplstring.cpp" />
+				<File RelativePath=".\port\cplstringlist.cpp" />
 				<File RelativePath=".\port\cpl_atomic_ops.cpp" />
+				<File RelativePath=".\port\cpl_base64.cpp" />
 				<File RelativePath=".\port\cpl_conv.cpp" />
 				<File RelativePath=".\port\cpl_csv.cpp" />
 				<File RelativePath=".\port\cpl_error.cpp" />
@@ -2339,18 +2897,29 @@
 				<File RelativePath=".\port\cpl_minixml.cpp" />
 				<File RelativePath=".\port\cpl_minizip_ioapi.cpp" />
 				<File RelativePath=".\port\cpl_minizip_unzip.cpp" />
+				<File RelativePath=".\port\cpl_minizip_zip.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.cpp" />
+				<File RelativePath=".\port\cpl_recode_iconv.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_abstract_archive.cpp" />
+				<File RelativePath=".\port\cpl_vsil_buffered_reader.cpp" />
+				<File RelativePath=".\port\cpl_vsil_cache.cpp" />
+				<File RelativePath=".\port\cpl_vsil_curl.cpp" />
 				<File RelativePath=".\port\cpl_vsil_gzip.cpp" />
 				<File RelativePath=".\port\cpl_vsil_simple.cpp" />
+				<File RelativePath=".\port\cpl_vsil_sparsefile.cpp" />
+				<File RelativePath=".\port\cpl_vsil_stdin.cpp" />
+				<File RelativePath=".\port\cpl_vsil_stdout.cpp" />
 				<File RelativePath=".\port\cpl_vsil_subfile.cpp" />
+				<File RelativePath=".\port\cpl_vsil_tar.cpp" />
 				<File RelativePath=".\port\cpl_vsil_unix_stdio_64.cpp" />
 				<File RelativePath=".\port\cpl_vsil_win32.cpp" />
 				<File RelativePath=".\port\cpl_vsisimple.cpp" />
diff --git a/makegdal80.vcproj b/makegdal80.vcproj
index 96f3373..60f4834 100644
--- a/makegdal80.vcproj
+++ b/makegdal80.vcproj
@@ -1,8257 +1,2933 @@
 <?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
+<VisualStudioProject            
 	ProjectType="Visual C++"
 	Version="8.00"
 	Name="makegdal"
 	ProjectGUID="{769DD10E-E284-46BE-9172-A35184250A3A}"
-	Keyword="MakeFileProj"
-	>
+	Keyword="MakeFileProj">
 	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
+		<Platform Name="Win32"/>
 	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
 	<Configurations>
 		<Configuration
 			Name="Debug|Win32"
 			OutputDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
+			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=""
-			/>
+				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc && nmake -f makefile.vc install"
+				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc clean && nmake -f makefile.vc && nmake -f makefile.vc install"
+				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc clean"
+				Output="gdal19.dll"/>
 		</Configuration>
 		<Configuration
 			Name="Release|Win32"
 			OutputDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
+			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=""
-			/>
+				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc && nmake -f makefile.vc install"
+				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc clean && nmake -f makefile.vc && nmake -f makefile.vc install"
+				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc clean"
+				Output="gdal19.dll"/>
 		</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 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"
-					>
-				</File>
+			<Filter Name="apps" Filter="*.vc;*.opt  ">
+				<File RelativePath=".\apps\makefile.vc" />
 			</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 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="ctg" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ctg\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="e00grid" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\e00grid\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"
-								>
-							</File>
+						<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="gta" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\gta\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="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 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="hf2" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\hf2\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="jpipkak" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\jpipkak\makefile.vc" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\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" />
+					<File RelativePath=".\frmts\mrsid\nmake.opt" />
+				</Filter>
+				<Filter Name="mrsid_lidar" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\mrsid_lidar\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="ngsgeoid" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ngsgeoid\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="openjpeg" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\openjpeg\makefile.vc" />
+				</Filter>
+				<Filter Name="ozi" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ozi\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="pdf" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\pdf\makefile.vc" />
+				</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="postgisraster" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\postgisraster\makefile.vc" />
+				</Filter>
+				<Filter Name="r" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\r\makefile.vc" />
+				</Filter>
+				<Filter Name="rasdaman" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\rasdaman\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="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="webp" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\webp\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="xyz" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\xyz\makefile.vc" />
+				</Filter>
+				<Filter Name="zlib" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\zlib\makefile.vc" />
+				</Filter>
+				<Filter Name="zmap" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\zmap\makefile.vc" />
+				</Filter>
+				</Filter>
+			<Filter Name="gcore" Filter="*.vc;*.opt  ">
+				<File RelativePath=".\gcore\makefile.vc" />
 			</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 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="aeronavfaa" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\makefile.vc" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\makefile.vc" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\makefile.vc" />
+					</Filter>
+					<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="couchdb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\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="dwg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\makefile.vc" />
+					</Filter>
+					<Filter Name="dxf" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\makefile.vc" />
+					</Filter>
+					<Filter Name="edigeo" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\makefile.vc" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\makefile.vc" />
 					</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 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="geomedia" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\makefile.vc" />
+					</Filter>
+					<Filter Name="georss" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\georss\makefile.vc" />
+					</Filter>
+					<Filter Name="gft" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\makefile.vc" />
 					</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 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="gpsbabel" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\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="htf" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\makefile.vc" />
+					</Filter>
+					<Filter Name="idb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idb\makefile.vc" />
+					</Filter>
+					<Filter Name="idrisi" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\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="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 Name="libkml" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\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="mssqlspatial" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\makefile.vc" />
+					</Filter>
+					<Filter Name="mysql" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mysql\makefile.vc" />
+					</Filter>
+					<Filter Name="nas" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\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="openair" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\makefile.vc" />
+					</Filter>
+					<Filter Name="pcidsk" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\makefile.vc" />
+					</Filter>
+					<Filter Name="pds" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\makefile.vc" />
+					</Filter>
+					<Filter Name="pg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pg\makefile.vc" />
+					</Filter>
+					<Filter Name="pgdump" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\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="segukooa" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\makefile.vc" />
+					</Filter>
+					<Filter Name="segy" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\makefile.vc" />
+					</Filter>
+					<Filter Name="shape" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\shape\makefile.vc" />
+					</Filter>
+					<Filter Name="sosi" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\makefile.vc" />
+					</Filter>
+					<Filter Name="sqlite" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\makefile.vc" />
+					</Filter>
+					<Filter Name="sua" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\makefile.vc" />
+					</Filter>
+					<Filter Name="svg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\makefile.vc" />
+					</Filter>
+					<Filter Name="tiger" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\tiger\makefile.vc" />
+					</Filter>
+					<Filter Name="vfk" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\makefile.vc" />
+					</Filter>
+					<Filter Name="vrt" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vrt\makefile.vc" />
+					</Filter>
+					<Filter Name="wfs" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\makefile.vc" />
+					</Filter>
+					<Filter Name="xls" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\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
-				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 Name="Include Files" Filter="*.h ">
+			<Filter Name="alg" Filter="*.h  ">
+				<File RelativePath=".\alg\gdalgrid.h" />
+				<File RelativePath=".\alg\gdalwarper.h" />
+				<File RelativePath=".\alg\gdalwarpkernel_opencl.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"
-					>
-				</File>
+			<Filter Name="apps" Filter="*.h  ">
+				<File RelativePath=".\apps\commonutils.h" />
 			</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 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="e00grid" Filter="*.h   ">
+					<File RelativePath=".\frmts\e00grid\e00compr.h" />
+				</Filter>
+				<Filter Name="ecw" Filter="*.h   ">
+					<File RelativePath=".\frmts\ecw\gdal_ecw.h" />
+				</Filter>
+				<Filter Name="envisat" Filter="*.h   ">
+					<File RelativePath=".\frmts\envisat\EnvisatFile.h" />
+					<File RelativePath=".\frmts\envisat\records.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   ">
+					<File RelativePath=".\frmts\gif\gifabstractdataset.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>
-							<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 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"
-						>
-					</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 Name="gtiff" Filter="*.h   ">
+					<File RelativePath=".\frmts\gtiff\gtiff.h" />
+					<File RelativePath=".\frmts\gtiff\gt_citation.h" />
+					<File RelativePath=".\frmts\gtiff\gt_overview.h" />
+					<File RelativePath=".\frmts\gtiff\gt_wkt_srs.h" />
+					<File RelativePath=".\frmts\gtiff\gt_wkt_srs_for_gdal.h" />
+					<File RelativePath=".\frmts\gtiff\tifvsi.h" />
+					<File RelativePath=".\frmts\gtiff\tif_float.h" />
+					<Filter Name="libgeotiff" Filter="*.h    ">
+						<File RelativePath=".\frmts\gtiff\libgeotiff\cpl_serv.h" />
+						<File RelativePath=".\frmts\gtiff\libgeotiff\gdal_libgeotiff_symbol_rename.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\gdal_libtiff_symbol_rename.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="idrisi" Filter="*.h   ">
+					<File RelativePath=".\frmts\idrisi\idrisi.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="jpipkak" Filter="*.h   ">
+					<File RelativePath=".\frmts\jpipkak\jpipkakdataset.h" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.h   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.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\nitfdataset.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_ads40.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_airphoto.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_array.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_binary.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_edb.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_ephemeris.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_exception.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_file.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_gcp.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_gcpsegment.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_poly.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_rpc.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_segment.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_shape.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_tex.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_toutin.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\cexternalchannel.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>
-				</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 Name="core" Filter="*.h     ">
+							<File RelativePath=".\frmts\pcidsk\sdk\core\clinksegment.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\cpcidskads40model.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskapmodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbinarysegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbitmap.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskephemerissegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgcp2segment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpolymodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskrpcmodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsktoutinmodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_array.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_tex.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\orbitstructures.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\pcidsksegmentbuilder.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\toutinstructures.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegdataindex.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegheader.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="pdf" Filter="*.h   ">
+					<File RelativePath=".\frmts\pdf\pdfio.h" />
+					<File RelativePath=".\frmts\pdf\pdfobject.h" />
+				</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="postgisraster" Filter="*.h   ">
+					<File RelativePath=".\frmts\postgisraster\postgisraster.h" />
+				</Filter>
+				<Filter Name="rasdaman" Filter="*.h   ">
+					<File RelativePath=".\frmts\rasdaman\rasdamandataset.h" />
+				</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="vrt" Filter="*.h   ">
+					<File RelativePath=".\frmts\vrt\gdal_vrt.h" />
+					<File RelativePath=".\frmts\vrt\vrtdataset.h" />
+				</Filter>
+				<Filter Name="wms" Filter="*.h   ">
+					<File RelativePath=".\frmts\wms\gdalhttp.h" />
+					<File RelativePath=".\frmts\wms\md5.h" />
+					<File RelativePath=".\frmts\wms\minidriver_tiled_wms.h" />
+					<File RelativePath=".\frmts\wms\minidriver_tileservice.h" />
+					<File RelativePath=".\frmts\wms\minidriver_tms.h" />
+					<File RelativePath=".\frmts\wms\minidriver_virtualearth.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" />
+					<File RelativePath=".\frmts\wms\wmsmetadataset.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>
-				<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 Name="ogr" Filter="*.h  ">
+				<File RelativePath=".\ogr\ogrgeomediageometry.h" />
+				<File RelativePath=".\ogr\ogrpgeogeometry.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="aeronavfaa" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ogr_aeronavfaa.h" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ogr_arcgen.h" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aoutils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\ogr_ao.h" />
+					</Filter>
+					<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="couchdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogr_couchdb.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"
-							>
-						</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 Name="dods" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogr_dods.h" />
+					</Filter>
+					<Filter Name="dwg" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogr_dwg.h" />
+					</Filter>
+					<Filter Name="dxf" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_polyline_smooth.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_autocad_services.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_dxf.h" />
+					</Filter>
+					<Filter Name="edigeo" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogr_edigeo.h" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbUtils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\ogr_fgdb.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="geomedia" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogr_geomedia.h" />
+					</Filter>
+					<Filter Name="georss" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\georss\ogr_georss.h" />
+					</Filter>
+					<Filter Name="gft" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogr_gft.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\gmlutils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\ogr_gml.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\parsexsd.h" />
+					</Filter>
+					<Filter Name="gmt" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gmt\ogr_gmt.h" />
+					</Filter>
+					<Filter Name="gpsbabel" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogr_gpsbabel.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="htf" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogr_htf.h" />
+					</Filter>
+					<Filter Name="idb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogr_idb.h" />
+					</Filter>
+					<Filter Name="idrisi" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogr_idrisi.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="libkml" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeature.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeaturestyle.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfield.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlgeometry.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlstyle.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogr_libkml.h" />
+					</Filter>
+					<Filter Name="mdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogr_mdb.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="mssqlspatial" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogr_mssqlspatial.h" />
+					</Filter>
+					<Filter Name="mysql" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogr_mysql.h" />
+					</Filter>
+					<Filter Name="nas" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nasreaderp.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogr_nas.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="openair" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogr_openair.h" />
+					</Filter>
+					<Filter Name="pcidsk" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogr_pcidsk.h" />
+					</Filter>
+					<Filter Name="pds" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogr_pds.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="pgdump" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogr_pgdump.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="segukooa" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogr_segukooa.h" />
+					</Filter>
+					<Filter Name="segy" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogr_segy.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="sosi" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogr_sosi.h" />
+					</Filter>
+					<Filter Name="sqlite" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogr_sqlite.h" />
+					</Filter>
+					<Filter Name="sua" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogr_sua.h" />
+					</Filter>
+					<Filter Name="svg" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogr_svg.h" />
+					</Filter>
+					<Filter Name="tiger" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogr_tiger.h" />
+					</Filter>
+					<Filter Name="vfk" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogr_vfk.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreaderp.h" />
+					</Filter>
+					<Filter Name="vrt" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vrt\ogr_vrt.h" />
+					</Filter>
+					<Filter Name="wfs" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogr_wfs.h" />
+					</Filter>
+					<Filter Name="xls" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogr_xls.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
-						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 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_minizip_zip.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" />
+				<File RelativePath=".\port\gdal_csv.h" />
 			</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 Name="Source Files" Filter="*.c;*.cpp ">
+			<Filter Name="alg" Filter="*.c;*.cpp  ">
+				<File RelativePath=".\alg\gdalwarpkernel_opencl.c" />
+				<File RelativePath=".\alg\gdal_crs.c" />
+				<File RelativePath=".\alg\gdal_nrgcrs.c" />
+				<File RelativePath=".\alg\contour.cpp" />
+				<File RelativePath=".\alg\fpolygonize.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\gdalrasterfpolygonenumerator.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\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 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\commonutils.cpp" />
+				<File RelativePath=".\apps\dumpoverviews.cpp" />
+				<File RelativePath=".\apps\gdaladdo.cpp" />
+				<File RelativePath=".\apps\gdalasyncread.cpp" />
+				<File RelativePath=".\apps\gdalbuildvrt.cpp" />
+				<File RelativePath=".\apps\gdaldem.cpp" />
+				<File RelativePath=".\apps\gdalenhance.cpp" />
+				<File RelativePath=".\apps\gdallocationinfo.cpp" />
+				<File RelativePath=".\apps\gdalmanage.cpp" />
+				<File RelativePath=".\apps\gdalsrsinfo.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\testreprojmulti.cpp" />
+				<File RelativePath=".\apps\test_ogrsf.cpp" />
 			</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 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"
-					>
-				</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 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="ctg" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ctg\ctgdataset.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="e00grid" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\e00grid\e00read.c" />
+					<File RelativePath=".\frmts\e00grid\e00griddataset.cpp" />
+				</Filter>
+				<Filter Name="ecw" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ecw\ecwasyncreader.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\records.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_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\gifabstractdataset.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>
-							<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 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>
-					<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 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="gta" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\gta\gtadataset.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_lzma.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="hf2" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\hf2\hf2dataset.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="jpegls" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\jpegls\jpeglsdataset.cpp" />
+				</Filter>
+				<Filter Name="jpipkak" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\jpipkak\jpipkakdataset.cpp" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.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="mrsid_lidar" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\mrsid_lidar\gdal_MG4Lidar.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="ngsgeoid" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ngsgeoid\ngsgeoiddataset.cpp" />
+				</Filter>
+				<Filter Name="nitf" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\nitf\mgrs.c" />
+					<File RelativePath=".\frmts\nitf\nitfdes.c" />
+					<File RelativePath=".\frmts\nitf\nitfdump.c" />
+					<File RelativePath=".\frmts\nitf\nitffile.c" />
+					<File RelativePath=".\frmts\nitf\nitfimage.c" />
+					<File RelativePath=".\frmts\nitf\ecrgtocdataset.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfaridpcm.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfbilevel.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfdataset.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfrasterband.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfwritejpeg.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfwritejpeg_12.cpp" />
+					<File RelativePath=".\frmts\nitf\nitf_gcprpc.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="openjpeg" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\openjpeg\openjpegdataset.cpp" />
+				</Filter>
+				<Filter Name="ozi" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ozi\ozidataset.cpp" />
+				</Filter>
+				<Filter Name="pcidsk" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\pcidsk\gdal_edb.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\cexternalchannel.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="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 Name="core" Filter="*.c;*.cpp     ">
+							<File RelativePath=".\frmts\pcidsk\sdk\core\clinksegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\core\cpcidskfile.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\core\edb_pcidsk.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>
-				</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 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\cpcidskads40model.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskapmodel.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbinarysegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbitmap.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskephemerissegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgcp2segment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskrpcmodel.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsktoutinmodel.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment_consistencycheck.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_array.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_tex.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment_p.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegdataindex.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegheader.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="pdf" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\pdf\pdfdataset.cpp" />
+					<File RelativePath=".\frmts\pdf\pdfio.cpp" />
+					<File RelativePath=".\frmts\pdf\pdfobject.cpp" />
+				</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="postgisraster" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\postgisraster\postgisrasterdataset.cpp" />
+					<File RelativePath=".\frmts\postgisraster\postgisrasterdriver.cpp" />
+					<File RelativePath=".\frmts\postgisraster\postgisrasterrasterband.cpp" />
+				</Filter>
+				<Filter Name="r" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\r\rcreatecopy.cpp" />
+					<File RelativePath=".\frmts\r\rdataset.cpp" />
+				</Filter>
+				<Filter Name="rasdaman" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\rasdaman\rasdamandataset.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\ace2dataset.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\gtxdataset.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\loslasdataset.cpp" />
+					<File RelativePath=".\frmts\raw\mffdataset.cpp" />
+					<File RelativePath=".\frmts\raw\ndfdataset.cpp" />
+					<File RelativePath=".\frmts\raw\ntv2dataset.cpp" />
+					<File RelativePath=".\frmts\raw\pauxdataset.cpp" />
+					<File RelativePath=".\frmts\raw\pnmdataset.cpp" />
+					<File RelativePath=".\frmts\raw\rawdataset.cpp" />
+					<File RelativePath=".\frmts\raw\snodasdataset.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\rmfdem.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="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="webp" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\webp\webpdataset.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_tiled_wms.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_tileservice.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_tms.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_virtualearth.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" />
+					<File RelativePath=".\frmts\wms\wmsmetadataset.cpp" />
+				</Filter>
+				<Filter Name="xpm" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\xpm\xpmdataset.cpp" />
+				</Filter>
+				<Filter Name="xyz" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\xyz\xyzdataset.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 Name="zmap" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\zmap\zmapdataset.cpp" />
+				</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\gdaldefaultasync.cpp" />
+				<File RelativePath=".\gcore\gdaldefaultoverviews.cpp" />
+				<File RelativePath=".\gcore\gdaldllmain.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\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 Name="ogr" Filter="*.c;*.cpp  ">
+				<File RelativePath=".\ogr\ogr_capi_test.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\ogrgeomediageometry.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\ogrpgeogeometry.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" />
+				<File RelativePath=".\ogr\swq.cpp" />
+				<File RelativePath=".\ogr\swq_expr_node.cpp" />
+				<File RelativePath=".\ogr\swq_op_general.cpp" />
+				<File RelativePath=".\ogr\swq_op_registrar.cpp" />
+				<File RelativePath=".\ogr\swq_parser.cpp" />
+				<File RelativePath=".\ogr\swq_select.cpp" />
+				<Filter Name="ogrsf_frmts" Filter="*.c;*.cpp   ">
+					<Filter Name="aeronavfaa" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaalayer.cpp" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgendatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgendriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgenlayer.cpp" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aodatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aodriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aolayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aoutils.cpp" />
+					</Filter>
+					<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="couchdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdblayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbrowslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbtablelayer.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>
-					<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 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="dwg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgblockslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwglayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_blockmap.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_dimension.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_hatch.cpp" />
+					</Filter>
+					<Filter Name="dxf" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\intronurbs.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfblockslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfblockswriterlayer.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\ogrdxfreader.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_hatch.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_polyline_smooth.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_autocad_services.cpp" />
+					</Filter>
+					<Filter Name="edigeo" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeodatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeodriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeolayer.cpp" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbDatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbDriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbLayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbUtils.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\ogresrijsonreader.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="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="geomedia" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomedialayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediaselectlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediatablelayer.cpp" />
+					</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="gft" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftresultlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgfttablelayer.cpp" />
+					</Filter>
+					<Filter Name="gml" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\gfstemplate.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\gmlutils.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\hugefileresolver.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\resolvexlinks.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\trstring.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="gpsbabel" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabeldatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabeldriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabelfork.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabelwritedatasource.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="htf" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtfdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtfdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtflayer.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="idrisi" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\generate_test_files.c" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisidatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisidriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisilayer.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="libkml" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmldatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmldriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeature.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeaturestyle.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfield.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlgeometry.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmllayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlstyle.cpp" />
+					</Filter>
+					<Filter Name="mdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbjackcess.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdblayer.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="mssqlspatial" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlgeometryparser.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlgeometryvalidator.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatiallayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialselectlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialtablelayer.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="nas" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nashandler.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nasreader.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnaslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasrelationlayer.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="openair" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairlabellayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairlayer.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="pds" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdslayer.cpp" />
+					</Filter>
+					<Filter Name="pg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdatasource.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" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgutility.cpp" />
+					</Filter>
+					<Filter Name="pgdump" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumpdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumpdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumplayer.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="segukooa" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooalayer.cpp" />
+					</Filter>
+					<Filter Name="segy" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegydatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegydriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegylayer.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="sosi" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\fyba_melding.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosidatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosidriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosilayer.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\ogrsqlitesinglefeaturelayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitevfs.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqliteviewlayer.cpp" />
+					</Filter>
+					<Filter Name="sua" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsuadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsuadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsualayer.cpp" />
+					</Filter>
+					<Filter Name="svg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvgdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvgdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvglayer.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="vfk" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfklayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkdatablock.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkfeature.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkproperty.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkpropertydefn.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.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="wfs" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsfilter.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfslayer.cpp" />
+					</Filter>
+					<Filter Name="xls" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlslayer.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\cplstringlist.cpp" />
+				<File RelativePath=".\port\cpl_atomic_ops.cpp" />
+				<File RelativePath=".\port\cpl_base64.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_minizip_zip.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.cpp" />
+				<File RelativePath=".\port\cpl_recode_iconv.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_abstract_archive.cpp" />
+				<File RelativePath=".\port\cpl_vsil_buffered_reader.cpp" />
+				<File RelativePath=".\port\cpl_vsil_cache.cpp" />
+				<File RelativePath=".\port\cpl_vsil_curl.cpp" />
+				<File RelativePath=".\port\cpl_vsil_gzip.cpp" />
+				<File RelativePath=".\port\cpl_vsil_simple.cpp" />
+				<File RelativePath=".\port\cpl_vsil_sparsefile.cpp" />
+				<File RelativePath=".\port\cpl_vsil_stdin.cpp" />
+				<File RelativePath=".\port\cpl_vsil_stdout.cpp" />
+				<File RelativePath=".\port\cpl_vsil_subfile.cpp" />
+				<File RelativePath=".\port\cpl_vsil_tar.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
-				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>
diff --git a/makegdal90.vcproj b/makegdal90.vcproj
index 65a7f82..abc7e69 100644
--- a/makegdal90.vcproj
+++ b/makegdal90.vcproj
@@ -1,7157 +1,2933 @@
 <?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
+<VisualStudioProject            
 	ProjectType="Visual C++"
 	Version="9.00"
-	Name="makegdal90"
+	Name="makegdal"
 	ProjectGUID="{769DD10E-E284-46BE-9172-A35184250A3A}"
-	Keyword="MakeFileProj"
-	TargetFrameworkVersion="131072"
-	>
+	Keyword="MakeFileProj">
 	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
+		<Platform Name="Win32"/>
 	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
 	<Configurations>
 		<Configuration
 			Name="Debug|Win32"
 			OutputDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
+			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=""
-			/>
+				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc && nmake -f makefile.vc install"
+				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc clean && nmake -f makefile.vc && nmake -f makefile.vc install"
+				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc clean"
+				Output="gdal19.dll"/>
 		</Configuration>
 		<Configuration
 			Name="Release|Win32"
 			OutputDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="0"
-			>
+			ConfigurationType="0">
 			<Tool
 				Name="VCNMakeTool"
-				BuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400"
-				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 clean && nmake -f makefile.vc MSVC_VER=1400"
-				CleanCommandLine="cd $(ProjectDir) && nmake -f makefile.vc MSVC_VER=1400 clean"
-				Output="gdal17.dll"
-				PreprocessorDefinitions=""
-				IncludeSearchPath=""
-				ForcedIncludes=""
-				AssemblySearchPath=""
-				ForcedUsingAssemblies=""
-				CompileAsManaged=""
-			/>
+				BuildCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc && nmake -f makefile.vc install"
+				ReBuildCommandLine="cd $(ProjectDir) && nmake -f makefile.vc clean && nmake -f makefile.vc && nmake -f makefile.vc install"
+				CleanCommandLine=  "cd $(ProjectDir) && nmake -f makefile.vc clean"
+				Output="gdal19.dll"/>
 		</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 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"
-					>
-				</File>
+			<Filter Name="apps" Filter="*.vc;*.opt  ">
+				<File RelativePath=".\apps\makefile.vc" />
 			</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 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="ctg" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ctg\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="e00grid" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\e00grid\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"
-								>
-							</File>
+						<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="gta" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\gta\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="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 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>
-			<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 Name="hf2" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\hf2\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="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 Name="libjpeg12" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\frmts\jpeg\libjpeg12\makefile.vc" />
 					</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 Name="jpeg2000" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\jpeg2000\makefile.vc" />
 				</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 Name="jpipkak" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\jpipkak\makefile.vc" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\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" />
+					<File RelativePath=".\frmts\mrsid\nmake.opt" />
+				</Filter>
+				<Filter Name="mrsid_lidar" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\mrsid_lidar\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="ngsgeoid" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ngsgeoid\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="openjpeg" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\openjpeg\makefile.vc" />
+				</Filter>
+				<Filter Name="ozi" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\ozi\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
-							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 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="pdf" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\pdf\makefile.vc" />
 				</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 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="postgisraster" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\postgisraster\makefile.vc" />
+				</Filter>
+				<Filter Name="r" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\r\makefile.vc" />
+				</Filter>
+				<Filter Name="rasdaman" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\rasdaman\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="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="webp" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\webp\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="xyz" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\xyz\makefile.vc" />
+				</Filter>
+				<Filter Name="zlib" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\zlib\makefile.vc" />
+				</Filter>
+				<Filter Name="zmap" Filter="*.vc;*.opt   ">
+					<File RelativePath=".\frmts\zmap\makefile.vc" />
+				</Filter>
+				</Filter>
+			<Filter Name="gcore" Filter="*.vc;*.opt  ">
+				<File RelativePath=".\gcore\makefile.vc" />
 			</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 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="aeronavfaa" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\makefile.vc" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\makefile.vc" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\makefile.vc" />
+					</Filter>
+					<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="couchdb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\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="dwg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\makefile.vc" />
+					</Filter>
+					<Filter Name="dxf" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\makefile.vc" />
+					</Filter>
+					<Filter Name="edigeo" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\makefile.vc" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\makefile.vc" />
+					</Filter>
+					<Filter Name="fme" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\fme\makefile.vc" />
 					</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 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="geomedia" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\makefile.vc" />
+					</Filter>
+					<Filter Name="georss" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\georss\makefile.vc" />
+					</Filter>
+					<Filter Name="gft" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\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="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 Name="gpsbabel" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\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="htf" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\makefile.vc" />
+					</Filter>
+					<Filter Name="idb" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idb\makefile.vc" />
+					</Filter>
+					<Filter Name="idrisi" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\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="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 Name="libkml" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\makefile.vc" />
 					</Filter>
-				</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="mssqlspatial" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\makefile.vc" />
+					</Filter>
+					<Filter Name="mysql" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mysql\makefile.vc" />
+					</Filter>
+					<Filter Name="nas" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\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="openair" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\makefile.vc" />
+					</Filter>
+					<Filter Name="pcidsk" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\makefile.vc" />
+					</Filter>
+					<Filter Name="pds" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\makefile.vc" />
+					</Filter>
+					<Filter Name="pg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pg\makefile.vc" />
+					</Filter>
+					<Filter Name="pgdump" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\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="segukooa" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\makefile.vc" />
+					</Filter>
+					<Filter Name="segy" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\makefile.vc" />
+					</Filter>
+					<Filter Name="shape" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\shape\makefile.vc" />
+					</Filter>
+					<Filter Name="sosi" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\makefile.vc" />
+					</Filter>
+					<Filter Name="sqlite" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\makefile.vc" />
+					</Filter>
+					<Filter Name="sua" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\makefile.vc" />
+					</Filter>
+					<Filter Name="svg" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\makefile.vc" />
+					</Filter>
+					<Filter Name="tiger" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\tiger\makefile.vc" />
+					</Filter>
+					<Filter Name="vfk" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\makefile.vc" />
+					</Filter>
+					<Filter Name="vrt" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vrt\makefile.vc" />
+					</Filter>
+					<Filter Name="wfs" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\makefile.vc" />
+					</Filter>
+					<Filter Name="xls" Filter="*.vc;*.opt    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\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
-				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 Name="Include Files" Filter="*.h ">
+			<Filter Name="alg" Filter="*.h  ">
+				<File RelativePath=".\alg\gdalgrid.h" />
+				<File RelativePath=".\alg\gdalwarper.h" />
+				<File RelativePath=".\alg\gdalwarpkernel_opencl.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="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 Name="apps" Filter="*.h  ">
+				<File RelativePath=".\apps\commonutils.h" />
 			</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 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="e00grid" Filter="*.h   ">
+					<File RelativePath=".\frmts\e00grid\e00compr.h" />
+				</Filter>
+				<Filter Name="ecw" Filter="*.h   ">
+					<File RelativePath=".\frmts\ecw\gdal_ecw.h" />
+				</Filter>
+				<Filter Name="envisat" Filter="*.h   ">
+					<File RelativePath=".\frmts\envisat\EnvisatFile.h" />
+					<File RelativePath=".\frmts\envisat\records.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   ">
+					<File RelativePath=".\frmts\gif\gifabstractdataset.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\gtiff.h" />
+					<File RelativePath=".\frmts\gtiff\gt_citation.h" />
+					<File RelativePath=".\frmts\gtiff\gt_overview.h" />
+					<File RelativePath=".\frmts\gtiff\gt_wkt_srs.h" />
+					<File RelativePath=".\frmts\gtiff\gt_wkt_srs_for_gdal.h" />
+					<File RelativePath=".\frmts\gtiff\tifvsi.h" />
+					<File RelativePath=".\frmts\gtiff\tif_float.h" />
+					<Filter Name="libgeotiff" Filter="*.h    ">
+						<File RelativePath=".\frmts\gtiff\libgeotiff\cpl_serv.h" />
+						<File RelativePath=".\frmts\gtiff\libgeotiff\gdal_libgeotiff_symbol_rename.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\gdal_libtiff_symbol_rename.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="idrisi" Filter="*.h   ">
+					<File RelativePath=".\frmts\idrisi\idrisi.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="jpipkak" Filter="*.h   ">
+					<File RelativePath=".\frmts\jpipkak\jpipkakdataset.h" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.h   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.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\nitfdataset.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_ads40.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_airphoto.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_array.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_binary.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_edb.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_ephemeris.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_exception.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_file.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_gcp.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_gcpsegment.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_poly.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_rpc.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_segment.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_shape.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_tex.h" />
+						<File RelativePath=".\frmts\pcidsk\sdk\pcidsk_toutin.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\cexternalchannel.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\clinksegment.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\cpcidskads40model.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskapmodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbinarysegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbitmap.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskephemerissegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgcp2segment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpolymodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskrpcmodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsktoutinmodel.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_array.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_tex.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\orbitstructures.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\pcidsksegmentbuilder.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\toutinstructures.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegdataindex.h" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegheader.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="pdf" Filter="*.h   ">
+					<File RelativePath=".\frmts\pdf\pdfio.h" />
+					<File RelativePath=".\frmts\pdf\pdfobject.h" />
+				</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="postgisraster" Filter="*.h   ">
+					<File RelativePath=".\frmts\postgisraster\postgisraster.h" />
+				</Filter>
+				<Filter Name="rasdaman" Filter="*.h   ">
+					<File RelativePath=".\frmts\rasdaman\rasdamandataset.h" />
+				</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="vrt" Filter="*.h   ">
+					<File RelativePath=".\frmts\vrt\gdal_vrt.h" />
+					<File RelativePath=".\frmts\vrt\vrtdataset.h" />
+				</Filter>
+				<Filter Name="wms" Filter="*.h   ">
+					<File RelativePath=".\frmts\wms\gdalhttp.h" />
+					<File RelativePath=".\frmts\wms\md5.h" />
+					<File RelativePath=".\frmts\wms\minidriver_tiled_wms.h" />
+					<File RelativePath=".\frmts\wms\minidriver_tileservice.h" />
+					<File RelativePath=".\frmts\wms\minidriver_tms.h" />
+					<File RelativePath=".\frmts\wms\minidriver_virtualearth.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" />
+					<File RelativePath=".\frmts\wms\wmsmetadataset.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="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 Name="ogr" Filter="*.h  ">
+				<File RelativePath=".\ogr\ogrgeomediageometry.h" />
+				<File RelativePath=".\ogr\ogrpgeogeometry.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="aeronavfaa" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ogr_aeronavfaa.h" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ogr_arcgen.h" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aoutils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\ogr_ao.h" />
+					</Filter>
+					<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="couchdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogr_couchdb.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
-							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 Name="dods" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dods\ogr_dods.h" />
+					</Filter>
+					<Filter Name="dwg" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogr_dwg.h" />
+					</Filter>
+					<Filter Name="dxf" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_polyline_smooth.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_autocad_services.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_dxf.h" />
+					</Filter>
+					<Filter Name="edigeo" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogr_edigeo.h" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbUtils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\ogr_fgdb.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="geomedia" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogr_geomedia.h" />
+					</Filter>
+					<Filter Name="georss" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\georss\ogr_georss.h" />
+					</Filter>
+					<Filter Name="gft" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogr_gft.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\gmlutils.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\ogr_gml.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\parsexsd.h" />
+					</Filter>
+					<Filter Name="gmt" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gmt\ogr_gmt.h" />
+					</Filter>
+					<Filter Name="gpsbabel" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogr_gpsbabel.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="htf" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogr_htf.h" />
+					</Filter>
+					<Filter Name="idb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idb\ogr_idb.h" />
+					</Filter>
+					<Filter Name="idrisi" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogr_idrisi.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="libkml" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeature.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeaturestyle.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfield.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlgeometry.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlstyle.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogr_libkml.h" />
+					</Filter>
+					<Filter Name="mdb" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogr_mdb.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="mssqlspatial" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogr_mssqlspatial.h" />
+					</Filter>
+					<Filter Name="mysql" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mysql\ogr_mysql.h" />
+					</Filter>
+					<Filter Name="nas" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nasreaderp.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogr_nas.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="openair" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogr_openair.h" />
+					</Filter>
+					<Filter Name="pcidsk" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pcidsk\ogr_pcidsk.h" />
+					</Filter>
+					<Filter Name="pds" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogr_pds.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="pgdump" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogr_pgdump.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="segukooa" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogr_segukooa.h" />
+					</Filter>
+					<Filter Name="segy" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogr_segy.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="sosi" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogr_sosi.h" />
+					</Filter>
+					<Filter Name="sqlite" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogr_sqlite.h" />
+					</Filter>
+					<Filter Name="sua" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogr_sua.h" />
+					</Filter>
+					<Filter Name="svg" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogr_svg.h" />
+					</Filter>
+					<Filter Name="tiger" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\tiger\ogr_tiger.h" />
+					</Filter>
+					<Filter Name="vfk" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogr_vfk.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.h" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreaderp.h" />
+					</Filter>
+					<Filter Name="vrt" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vrt\ogr_vrt.h" />
+					</Filter>
+					<Filter Name="wfs" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogr_wfs.h" />
+					</Filter>
+					<Filter Name="xls" Filter="*.h    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogr_xls.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="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 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_minizip_zip.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" />
+				<File RelativePath=".\port\gdal_csv.h" />
+			</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 Name="Source Files" Filter="*.c;*.cpp ">
+			<Filter Name="alg" Filter="*.c;*.cpp  ">
+				<File RelativePath=".\alg\gdalwarpkernel_opencl.c" />
+				<File RelativePath=".\alg\gdal_crs.c" />
+				<File RelativePath=".\alg\gdal_nrgcrs.c" />
+				<File RelativePath=".\alg\contour.cpp" />
+				<File RelativePath=".\alg\fpolygonize.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\gdalrasterfpolygonenumerator.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="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 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\commonutils.cpp" />
+				<File RelativePath=".\apps\dumpoverviews.cpp" />
+				<File RelativePath=".\apps\gdaladdo.cpp" />
+				<File RelativePath=".\apps\gdalasyncread.cpp" />
+				<File RelativePath=".\apps\gdalbuildvrt.cpp" />
+				<File RelativePath=".\apps\gdaldem.cpp" />
+				<File RelativePath=".\apps\gdalenhance.cpp" />
+				<File RelativePath=".\apps\gdallocationinfo.cpp" />
+				<File RelativePath=".\apps\gdalmanage.cpp" />
+				<File RelativePath=".\apps\gdalsrsinfo.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\testreprojmulti.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="ctg" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ctg\ctgdataset.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="e00grid" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\e00grid\e00read.c" />
+					<File RelativePath=".\frmts\e00grid\e00griddataset.cpp" />
+				</Filter>
+				<Filter Name="ecw" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ecw\ecwasyncreader.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\records.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_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\gifabstractdataset.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>
-					<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 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
-						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>
+				<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="gta" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\gta\gtadataset.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_lzma.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="hf2" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\hf2\hf2dataset.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="jpegls" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\jpegls\jpeglsdataset.cpp" />
+				</Filter>
+				<Filter Name="jpipkak" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\jpipkak\jpipkakdataset.cpp" />
+				</Filter>
+				<Filter Name="kmlsuperoverlay" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\kmlsuperoverlay\kmlsuperoverlaydataset.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="mrsid_lidar" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\mrsid_lidar\gdal_MG4Lidar.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="ngsgeoid" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ngsgeoid\ngsgeoiddataset.cpp" />
+				</Filter>
+				<Filter Name="nitf" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\nitf\mgrs.c" />
+					<File RelativePath=".\frmts\nitf\nitfdes.c" />
+					<File RelativePath=".\frmts\nitf\nitfdump.c" />
+					<File RelativePath=".\frmts\nitf\nitffile.c" />
+					<File RelativePath=".\frmts\nitf\nitfimage.c" />
+					<File RelativePath=".\frmts\nitf\ecrgtocdataset.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfaridpcm.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfbilevel.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfdataset.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfrasterband.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfwritejpeg.cpp" />
+					<File RelativePath=".\frmts\nitf\nitfwritejpeg_12.cpp" />
+					<File RelativePath=".\frmts\nitf\nitf_gcprpc.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="openjpeg" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\openjpeg\openjpegdataset.cpp" />
+				</Filter>
+				<Filter Name="ozi" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\ozi\ozidataset.cpp" />
+				</Filter>
+				<Filter Name="pcidsk" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\pcidsk\gdal_edb.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\cexternalchannel.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\clinksegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\core\cpcidskfile.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\core\edb_pcidsk.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\cpcidskads40model.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskapmodel.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbinarysegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskbitmap.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskephemerissegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgcp2segment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskgeoref.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskpct.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskrpcmodel.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsksegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsktoutinmodel.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidskvectorsegment_consistencycheck.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_array.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\cpcidsk_tex.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\metadatasegment_p.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\sysblockmap.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegdataindex.cpp" />
+							<File RelativePath=".\frmts\pcidsk\sdk\segment\vecsegheader.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="pdf" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\pdf\pdfdataset.cpp" />
+					<File RelativePath=".\frmts\pdf\pdfio.cpp" />
+					<File RelativePath=".\frmts\pdf\pdfobject.cpp" />
+				</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="postgisraster" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\postgisraster\postgisrasterdataset.cpp" />
+					<File RelativePath=".\frmts\postgisraster\postgisrasterdriver.cpp" />
+					<File RelativePath=".\frmts\postgisraster\postgisrasterrasterband.cpp" />
+				</Filter>
+				<Filter Name="r" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\r\rcreatecopy.cpp" />
+					<File RelativePath=".\frmts\r\rdataset.cpp" />
+				</Filter>
+				<Filter Name="rasdaman" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\rasdaman\rasdamandataset.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\ace2dataset.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\gtxdataset.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\loslasdataset.cpp" />
+					<File RelativePath=".\frmts\raw\mffdataset.cpp" />
+					<File RelativePath=".\frmts\raw\ndfdataset.cpp" />
+					<File RelativePath=".\frmts\raw\ntv2dataset.cpp" />
+					<File RelativePath=".\frmts\raw\pauxdataset.cpp" />
+					<File RelativePath=".\frmts\raw\pnmdataset.cpp" />
+					<File RelativePath=".\frmts\raw\rawdataset.cpp" />
+					<File RelativePath=".\frmts\raw\snodasdataset.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\rmfdem.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="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="webp" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\webp\webpdataset.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_tiled_wms.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_tileservice.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_tms.cpp" />
+					<File RelativePath=".\frmts\wms\minidriver_virtualearth.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" />
+					<File RelativePath=".\frmts\wms\wmsmetadataset.cpp" />
+				</Filter>
+				<Filter Name="xpm" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\xpm\xpmdataset.cpp" />
+				</Filter>
+				<Filter Name="xyz" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\xyz\xyzdataset.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 Name="zmap" Filter="*.c;*.cpp   ">
+					<File RelativePath=".\frmts\zmap\zmapdataset.cpp" />
+				</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\gdaldefaultasync.cpp" />
+				<File RelativePath=".\gcore\gdaldefaultoverviews.cpp" />
+				<File RelativePath=".\gcore\gdaldllmain.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\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\ogrgeomediageometry.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\ogrpgeogeometry.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" />
+				<File RelativePath=".\ogr\swq.cpp" />
+				<File RelativePath=".\ogr\swq_expr_node.cpp" />
+				<File RelativePath=".\ogr\swq_op_general.cpp" />
+				<File RelativePath=".\ogr\swq_op_registrar.cpp" />
+				<File RelativePath=".\ogr\swq_parser.cpp" />
+				<File RelativePath=".\ogr\swq_select.cpp" />
+				<Filter Name="ogrsf_frmts" Filter="*.c;*.cpp   ">
+					<Filter Name="aeronavfaa" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\aeronavfaa\ograeronavfaalayer.cpp" />
+					</Filter>
+					<Filter Name="arcgen" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgendatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgendriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcgen\ograrcgenlayer.cpp" />
+					</Filter>
+					<Filter Name="arcobjects" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aodatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aodriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aolayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\arcobjects\aoutils.cpp" />
+					</Filter>
+					<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="couchdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdblayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbrowslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\couchdb\ogrcouchdbtablelayer.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="dwg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgblockslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwgdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwglayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_blockmap.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_dimension.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dwg\ogrdwg_hatch.cpp" />
+					</Filter>
+					<Filter Name="dxf" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\intronurbs.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfblockslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxfblockswriterlayer.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\ogrdxfreader.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_hatch.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogrdxf_polyline_smooth.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\dxf\ogr_autocad_services.cpp" />
+					</Filter>
+					<Filter Name="edigeo" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeodatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeodriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\edigeo\ogredigeolayer.cpp" />
+					</Filter>
+					<Filter Name="filegdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbDatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbDriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbLayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\filegdb\FGdbUtils.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\ogresrijsonreader.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="geomedia" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomedialayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediaselectlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\geomedia\ogrgeomediatablelayer.cpp" />
+					</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="gft" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgftresultlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gft\ogrgfttablelayer.cpp" />
+					</Filter>
+					<Filter Name="gml" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\gfstemplate.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\gmlutils.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\hugefileresolver.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\resolvexlinks.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gml\trstring.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="gpsbabel" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabeldatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabeldriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabelfork.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\gpsbabel\ogrgpsbabelwritedatasource.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="htf" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtfdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtfdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\htf\ogrhtflayer.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="idrisi" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\generate_test_files.c" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisidatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisidriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\idrisi\ogridrisilayer.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="libkml" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmldatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmldriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeature.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfeaturestyle.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlfield.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlgeometry.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmllayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\libkml\ogrlibkmlstyle.cpp" />
+					</Filter>
+					<Filter Name="mdb" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdbjackcess.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mdb\ogrmdblayer.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="mssqlspatial" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlgeometryparser.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlgeometryvalidator.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatiallayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialselectlayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\mssqlspatial\ogrmssqlspatialtablelayer.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="nas" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nashandler.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\nasreader.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnaslayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\nas\ogrnasrelationlayer.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="openair" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairlabellayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\openair\ogropenairlayer.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="pds" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pds\ogrpdslayer.cpp" />
+					</Filter>
+					<Filter Name="pg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgdatasource.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" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pg\ogrpgutility.cpp" />
+					</Filter>
+					<Filter Name="pgdump" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumpdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumpdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\pgdump\ogrpgdumplayer.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="segukooa" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segukooa\ogrsegukooalayer.cpp" />
+					</Filter>
+					<Filter Name="segy" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegydatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegydriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\segy\ogrsegylayer.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="sosi" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\fyba_melding.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosidatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosidriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sosi\ogrsosilayer.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\ogrsqlitesinglefeaturelayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitetablelayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqlitevfs.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sqlite\ogrsqliteviewlayer.cpp" />
+					</Filter>
+					<Filter Name="sua" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsuadatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsuadriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\sua\ogrsualayer.cpp" />
+					</Filter>
+					<Filter Name="svg" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvgdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvgdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\svg\ogrsvglayer.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="vfk" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfkdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\ogrvfklayer.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkdatablock.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkfeature.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkproperty.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkpropertydefn.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\vfk\vfkreader.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="wfs" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfsfilter.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\wfs\ogrwfslayer.cpp" />
+					</Filter>
+					<Filter Name="xls" Filter="*.c;*.cpp    ">
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlsdatasource.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlsdriver.cpp" />
+						<File RelativePath=".\ogr\ogrsf_frmts\xls\ogrxlslayer.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\cplstringlist.cpp" />
+				<File RelativePath=".\port\cpl_atomic_ops.cpp" />
+				<File RelativePath=".\port\cpl_base64.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_minizip_zip.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.cpp" />
+				<File RelativePath=".\port\cpl_recode_iconv.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_abstract_archive.cpp" />
+				<File RelativePath=".\port\cpl_vsil_buffered_reader.cpp" />
+				<File RelativePath=".\port\cpl_vsil_cache.cpp" />
+				<File RelativePath=".\port\cpl_vsil_curl.cpp" />
+				<File RelativePath=".\port\cpl_vsil_gzip.cpp" />
+				<File RelativePath=".\port\cpl_vsil_simple.cpp" />
+				<File RelativePath=".\port\cpl_vsil_sparsefile.cpp" />
+				<File RelativePath=".\port\cpl_vsil_stdin.cpp" />
+				<File RelativePath=".\port\cpl_vsil_stdout.cpp" />
+				<File RelativePath=".\port\cpl_vsil_subfile.cpp" />
+				<File RelativePath=".\port\cpl_vsil_tar.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
-				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>
diff --git a/makegdal_gen.bat b/makegdal_gen.bat
index 25192fc..e6e8e7f 100644
--- a/makegdal_gen.bat
+++ b/makegdal_gen.bat
@@ -95,9 +95,9 @@ echo 			IntermediateDirectory="$(ConfigurationName)"
 echo 			ConfigurationType="0"^>
 echo 			^<Tool
 echo 				Name="VCNMakeTool"
-echo 				BuildCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% DEBUG=1 ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% DEBUG=1 install^"
-echo 				ReBuildCommandLine=^"cd $(ProjectDir) ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% DEBUG=1 clean^ ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% DEBUG=1 ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% DEBUG=1 install^"
-echo 				CleanCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% DEBUG=1 clean^"
+echo 				BuildCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
+echo 				ReBuildCommandLine=^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^ ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
+echo 				CleanCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^"
 echo 				Output="gdal%_gdalnum_%.dll"/^>
 echo 		^</Configuration^>
 echo 		^<Configuration
@@ -107,9 +107,9 @@ echo 			IntermediateDirectory="$(ConfigurationName)"
 echo 			ConfigurationType="0"^>
 echo 			^<Tool
 echo 				Name="VCNMakeTool"
-echo 				BuildCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% install^"
-echo 				ReBuildCommandLine=^"cd $(ProjectDir) ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% clean^ ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% install^"
-echo 				CleanCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% clean^"
+echo 				BuildCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
+echo 				ReBuildCommandLine=^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^ ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
+echo 				CleanCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^"
 echo 				Output="gdal%_gdalnum_%.dll"/^>
 echo 		^</Configuration^>
 echo 	^</Configurations^>
diff --git a/mkgdaldist.sh b/mkgdaldist.sh
index dc3fbce..6abc5b6 100755
--- a/mkgdaldist.sh
+++ b/mkgdaldist.sh
@@ -1,15 +1,16 @@
 #!/bin/sh
 #
-# $Id: mkgdaldist.sh 18972 2010-02-28 20:17:58Z warmerdam $
+# $Id: mkgdaldist.sh 22675 2011-07-09 16:34:23Z warmerdam $
 #
 # mkgdaldist.sh - prepares GDAL source distribution package
 #
 if [ $# -lt 1 ] ; then
-  echo "Usage: mkgdaldist.sh <version> [-date date] [-branch branch]"
+  echo "Usage: mkgdaldist.sh <version> [-date date] [-branch branch] [-rc n]"
   echo " <version> - version number used in name of generated archive."
   echo " -date     - date of package generation, current date used if not provided"
   echo " -branch   - path to SVN branch, trunk is used if not provided"
-  echo "Example: mkgdaldist.sh 1.1.4"
+  echo " -rc       - gives a release candidate id to embed in filenames"
+  echo "Example: mkgdaldist.sh 1.1.4 -branch branches/1.8 -rc RC2"
   exit
 fi
 
@@ -29,10 +30,20 @@ fi
 
 if test "$2" = "-branch"; then
   forcebranch=$3
+  shift
+  shift
 else
   forcebranch="trunk"
 fi
  
+if test "$2" = "-rc"; then
+  RC=$3
+  shift
+  shift
+else
+  RC=""
+fi
+ 
 #
 # Checkout GDAL sources from the repository
 #
@@ -106,8 +117,11 @@ cd ${CWD}
 echo "* Generating SWIG Perl interfaces..."
 CWD=${PWD}
 cd gdal/swig/perl
+
 rm *wrap*
+touch ../../GDALmake.opt
 make generate
+rm -f ../../GDALmake.opt
 cd ${CWD}
 
 #
@@ -122,11 +136,11 @@ echo $GDAL_VERSION > gdal/VERSION
 
 mv gdal gdal-${GDAL_VERSION}
 
-rm -f ../gdal-${GDAL_VERSION}.tar.gz ../gdal${COMPRESSED_VERSION}.zip
+rm -f ../gdal-${GDAL_VERSION}${RC}.tar.gz ../gdal${COMPRESSED_VERSION}${RC}.zip
 
-tar cf ../gdal-${GDAL_VERSION}.tar gdal-${GDAL_VERSION}
-gzip -9 ../gdal-${GDAL_VERSION}.tar
-zip -r ../gdal${COMPRESSED_VERSION}.zip gdal-${GDAL_VERSION}
+tar cf ../gdal-${GDAL_VERSION}${RC}.tar gdal-${GDAL_VERSION}
+gzip -9 ../gdal-${GDAL_VERSION}${RC}.tar
+zip -r ../gdal${COMPRESSED_VERSION}${RC}.zip gdal-${GDAL_VERSION}
 
 echo "* Generating MD5 sums ..."
 
@@ -137,8 +151,8 @@ else
 MD5=md5sum
 fi
 
-$MD5 ../gdal-${GDAL_VERSION}.tar.gz > ../gdal-${GDAL_VERSION}.tar.gz.md5
-$MD5 ../gdal${COMPRESSED_VERSION}.zip > ../gdal${COMPRESSED_VERSION}.zip.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 ..
diff --git a/nmake.opt b/nmake.opt
index 2e5a009..c44ff9f 100644
--- a/nmake.opt
+++ b/nmake.opt
@@ -1,4 +1,4 @@
-# $Id: nmake.opt 22529 2011-06-13 15:32:56Z warmerdam $
+# $Id: nmake.opt 23610 2011-12-20 01:17:29Z warmerdam $
 #
 # nmake.opt - main configuration file for NMAKE makefiles.
 #
@@ -25,6 +25,8 @@
 # Check version of Visual C++ compiler:
 # nmake -f makefile.vc MSVC_VER=xxxx
 # where xxxx is one of following:
+# 1700 = 11.0(2011)
+# 1600 = 10.0(2010)
 # 1500 = 9.0 (2008)
 # 1400 = 8.0 (2005) - specific compilation flags, different from older VC++
 # 1310 = 7.1 (2003)
@@ -33,7 +35,7 @@
 #
 !IFNDEF MSVC_VER
 #assume msvc VS2008.
-MSVC_VER=1600
+MSVC_VER=1500
 !ENDIF
 
 ###############################################################################
@@ -107,19 +109,32 @@ CXX_ANALYZE_FLAGS=
 !IFNDEF OPTFLAGS
 !IF $(MSVC_VER) >= 1400
 !IFNDEF DEBUG
-OPTFLAGS= $(CXX_ANALYZE_FLAGS) /nologo /MD /EHsc /Ox /W3 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DNDEBUG
+OPTFLAGS= $(CXX_ANALYZE_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 /W4 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /Fd$(GDAL_ROOT)\gdal$(VERSION).pdb /DDEBUG
+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
 !ENDIF
 !ELSE
 !IFNDEF DEBUG
-OPTFLAGS=	/nologo /MD /EHsc /GR /Ox /W3 /DNDEBUG
+OPTFLAGS=	/nologo /MD /EHsc /GR /Ox /DNDEBUG
 !ELSE
-OPTFLAGS=	/nologo /MD /EHsc /GR /Zi /W4 /Fd$(GDAL_ROOT)\gdal$(VERSION).pdb  /DDEBUG
+OPTFLAGS=	/nologo /MD /EHsc /GR /Zi /Fd$(GDAL_ROOT)\gdal$(VERSION).pdb  /DDEBUG
 !ENDIF
 !ENDIF  #MSVC_VER
 !ENDIF  # OPTFLAGS
 
+# 
+# Set flags controlling warnings level, and supression of some warnings.
+# 
+!IFNDEF WARNFLAGS
+WARNFLAGS =	/W4 /wd4127 /wd4251 /wd4275 /wd4786 /wd4100 /wd4245 /wd4206 /wd4018 /wd4389
+!ENDIF
+
+# The followin are extra disables that can be applied to external source
+# not under our control that we wish to use less stringent warnings with.
+!IFNDEF SOFTWARNFLAGS
+SOFTWARNFLAGS= /wd4244 /wd4702 /wd4701 /wd4013 /wd4706 /wd4057 /wd4210 /wd4305
+!ENDIF
+
 # Linker debug options
 !IFDEF DEBUG
 LDEBUG= /debug
@@ -136,7 +151,7 @@ LDEBUG= /debug
 STDCALL=YES
 
 # Version number embedded in DLL name. 
-VERSION =	18
+VERSION =	19
 
 # Comment the following out if you want PAM supported disabled
 # by default.  
@@ -157,6 +172,18 @@ INCLUDE_OGR_FRMTS = YES
 # programs to be able to expand wildcards. 
 #SETARGV =	$(VCDIR)\lib\setargv.obj
 
+# Uncomment to build with libiconv library to support extended character
+# recoding capabilities. GDAL's internal stub implementation supports
+# latin1<->utf-8 translations only.
+# Depending on your libiconv build you may need to set ICONV_CONST macro to
+# const or leave it empty. Take a look on your iconv() declaration in iconv.h.
+# If the second parameter declared as const char** then you need to define
+# ICONV_CONST=const otherwise leave it empty.
+#LIBICONV_DIR = "C:\Program Files\GnuWin32"
+#LIBICONV_INCLUDE = -I$(LIBICONV_DIR)\include
+#LIBICONV_LIBRARY = $(LIBICONV_DIR)\lib\libiconv.lib
+#LIBICONV_CFLAGS = -DICONV_CONST=const
+
 # Comment out the following to disable BSB support.
 BSB_SUPPORTED = 1
 
@@ -211,8 +238,8 @@ JPEG12_SUPPORTED = 1
 #ECWDIR  = 	"c:/Program Files/ERDAS/ERDAS ECW JPEG2000 Read SDK"
 #ECWFLAGS =	-DECWSDK_VERSION=41 \
 #		-I$(ECWDIR)\include \
-#		-I$(ECWDIR)\include/ecw/api -I$(ECWDIR)\include/ecw/jp2 \
-#		-I$(ECWDIR)\include/ecw/ecw
+#		-I$(ECWDIR)\include/NCSECW/api -I$(ECWDIR)\include/NCSECW/jp2 \
+#		-I$(ECWDIR)\include/NCSECW/ecw
 #ECWLIB  = 	$(ECWDIR)\lib\vc90\win32\NCSEcw4_RO.lib \
 #		$(ECWDIR)\lib\vc90\win32\NCSUtil4.lib \
 #		$(ECWDIR)\lib\vc90\win32\NCScnet4.lib
@@ -235,6 +262,13 @@ JPEG12_SUPPORTED = 1
 #		/D_MBCS /D_UNICODE /DUNICODE /D_WINDOWS \
 #		/DLIBECWJ2 /DWIN32 /D_WINDLL -DNO_X86_MMI
 
+# DWG support using the Open Design Alliance Teigha Libraries
+
+#TD_BASE = C:\warmerda\pkg\td_vc9
+#TD_FLAGS = -D_TOOLKIT_IN_DLL_
+#TD_INCLUDE = -I$(TD_BASE)\TD\Include -I$(TD_BASE)\TD\Extensions\ExServices
+#TD_LIBDIR = $(TD_BASE)\lib\vc9dll
+
 # DWG/DXF support via DWGdirect from Open Design Alliance
 
 #DWGDIRECT=C:\warmerda\DWGdirect
@@ -322,7 +356,9 @@ PCIDSK_SETTING=INTERNAL
 #SQLITE_INC=-IN:\pkg\sqlite-win32
 #SQLITE_LIB=N:\pkg\sqlite-win32\sqlite3_i.lib
 # For spatialite support, try this instead (assuming you grab the libspatialite-amalgamation-2.3.1 and installed it in osgeo4w):
-#SQLITE_INC=-IC:\osgeo4w\include -DHAVE_SPATIALITE
+# The -DSPATIALITE_AMALGAMATION, which cause "spatialite/sqlite3.h" to be included instead of "sqlite3.h" might not be necessary
+# depending on the layout of the include directories. In case of compilation errors, remove it.
+#SQLITE_INC=-IC:\osgeo4w\include -DHAVE_SPATIALITE -DSPATIALITE_AMALGAMATION
 #SQLITE_LIB=C:\osgeo4w\lib\spatialite_i.lib
 
 # Informix Data Blade
@@ -348,6 +384,11 @@ GRIB_SETTING=yes
 #NETCDF_SETTING=yes
 #NETCDF_LIB=C:\Software\netcdf\lib\netcdf.lib
 #NETCDF_INC_DIR=C:\Software\netcdf\include
+
+# Uncomment the following to add NC4 and HDF4 support
+#NETCDF_HAS_NC4 = yes
+#NETCDF_HAS_HDF4 = yes
+
 # PROJ.4 stuff
 # Uncomment the following lines to link PROJ.4 library statically. Otherwise
 # it will be linked dynamically during runtime.
@@ -375,6 +416,14 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 #SDE_LIB = $(SDE_SDK)\lib\pe$(SDE_VERSION).lib \
 #          $(SDE_SDK)\lib\sde$(SDE_VERSION).lib $(SDE_SDK)\lib\sg$(SDE_VERSION).lib      
 
+
+#FGDB_ENABLED = YES
+#FGDB_PLUGIN = YES
+#FGDB_SDK = C:\Users\rburhum\Desktop\FileGDB_API_VS2008_1_0beta3
+#FGDB_INC = $(FGDB_SDK)\include 
+#FGDB_LIB = $(FGDB_SDK)\lib\FileGDBAPI.lib
+
+
 #uncomment to use ArcObjects
 #ARCOBJECTS_ENABLED = YES
 #ARCOBJECTS_PLUGIN = YES
@@ -387,7 +436,7 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 
 
 # Uncomment to use libcurl (DLL by default)
-# The cURL library is used for WCS, WMS, GeoJSON, SRS call importFromUrl(), etc.
+# The cURL library is used for WCS, WMS, GeoJSON, SRS call importFromUrl(), WFS, GFT, CouchDB, /vsicurl/ etc.
 #CURL_DIR=C:\curl-7.15.0
 #CURL_INC = -I$(CURL_DIR)/include
 # Uncoment following line to use libcurl as dynamic library
@@ -425,10 +474,35 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 #POPPLER_BASE_STREAM_HAS_TWO_ARGS = YES
 #POPPLER_LIBS = e:/kde/lib/poppler.lib e:/kde/lib/freetype.lib e:/kde/lib/liblcms-1.lib advapi32.lib gdi32.lib
 
+# Uncomment for PDF support
+#PODOFO_ENABLED = YES
+#PODOFO_CFLAGS = -Ie:/podofo-svn/install/include -Ie:/podofo-svn/install/include/podofo
+#PODOFO_LIBS = e:/podofo-svn/install/lib/podofo.lib E:/release-1500-dev/release-1500/lib/freetype239.lib gdi32.lib
+
 # Uncomment for LZMA TIFF support
 #LZMA_CFLAGS = -IC:/gdal_trunk/xz-5.0.0-windows/include
 #LZMA_LIBS = C:/gdal_trunk/xz-5.0.0-windows/bin_i486/liblzma.lib
 
+# Uncomment for WEBP support
+#WEBP_ENABLED = YES
+#WEBP_CFLAGS = -IE:/libwebp-0.1-windows/dev/Include
+#WEBP_LIBS = e:/libwebp-0.1-windows/dev/lib/libwebp_a.lib
+
+# Uncomment for freexl support
+#
+# Note: Currently there is no MSVC makefile to build freexl.
+# Here's the procedure I've followed (from root of freexl source tree)
+# cl /c src/freexl.c /Iheaders /IE:\release-1500-dev\release-1500\include /DDLL_EXPORT
+# link /dll E:\release-1500-dev\release-1500\lib\iconv.lib freexl.obj /out:freexl.dll /implib:freexl_i.lib
+#
+#FREEXL_CFLAGS = -Ie:/freexl-1.0.0a/headers
+#FREEXL_LIBS = e:/freexl-1.0.0a/freexl_i.lib
+
+# Uncomment for libgta support
+#
+#GTA_CFLAGS = -IC:/gdal_trunk/libgta-1.0.0-w32/include -IC:/gdal_trunk/libgta-1.0.0-w32/include/gta
+#GTA_LIBS = C:/gdal_trunk/libgta-1.0.0-w32/lib/libgta.dll.a
+
 # Any extra libraries needed on this platform?
 ADD_LIBS	= 
 
@@ -462,7 +536,7 @@ OGR_FLAG = -DOGR_ENABLED
 LINKER_FLAGS = $(MSVC_VLD_LIB) $(LDEBUG)
 
 
-CFLAGS	=	$(OPTFLAGS) $(INC) $(EXTRAFLAGS) $(OGR_FLAG) $(MSVC_VLD_FLAGS)
+CFLAGS	=	$(OPTFLAGS) $(WARNFLAGS) $(INC) $(EXTRAFLAGS) $(OGR_FLAG) $(MSVC_VLD_FLAGS)
 MAKE	=	nmake /nologo
 
 CC	=	cl
@@ -529,6 +603,14 @@ HDF5_LIB_LINK =
 !ENDIF
 !ENDIF
 
+!IFDEF FGDB_LIB
+!IF "$(FGDB_PLUGIN)" != "YES"
+FGDB_LIB_LINK = $(FGDB_LIB)
+!ELSE
+FGDB_LIB_LINK =
+!ENDIF
+!ENDIF
+
 !IFDEF XERCES_DIR
 NAS_ENABLED = YES
 !ENDIF
@@ -548,7 +630,8 @@ EXTERNAL_LIBS =	$(OGDILIB) $(XERCES_LIB) $(EXPAT_LIB) $(OCI_LIB) $(PG_LIB) \
 	$(MYSQL_LIB) $(GEOS_LIB) $(HDF5_LIB_LINK) $(SDE_LIB) $(ARCOBJECTS_LIB) $(DWG_LIB) \
 	$(IDB_LIB) $(CURL_LIB) $(DODS_LIB) $(KAKLIB) $(PCIDSK_LIB) \
 	$(ODBCLIB) $(JASPER_LIB) $(PNG_LIB) $(ADD_LIBS) $(OPENJPEG_LIB) \
-	$(MRSID_LIDAR_LIB) $(LIBKML_LIBS) $(SOSI_LIBS) $(POPPLER_LIBS) $(LZMA_LIBS)
+	$(MRSID_LIDAR_LIB) $(LIBKML_LIBS) $(SOSI_LIBS) $(POPPLER_LIBS) $(PODOFO_LIBS) $(LZMA_LIBS) \
+	$(LIBICONV_LIBRARY) $(WEBP_LIBS) $(FGDB_LIB_LINK) $(FREEXL_LIBS) $(GTA_LIBS)
 		
 .c.obj:	
 	$(CC) $(CFLAGS) /c $*.c
diff --git a/ogr/Doxyfile b/ogr/Doxyfile
index e55ef18..f47028b 100644
--- a/ogr/Doxyfile
+++ b/ogr/Doxyfile
@@ -1008,7 +1008,8 @@ PREDEFINED             = HAVE_DLFCN_H \
                          CPL_C_START \
                          CPL_C_END \
                          __cplusplus \
-                         DOXYGEN_SKIP 
+                         DOXYGEN_SKIP \
+                         HAVE_CURL
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
diff --git a/ogr/GNUmakefile b/ogr/GNUmakefile
index ded3c67..67eddfa 100644
--- a/ogr/GNUmakefile
+++ b/ogr/GNUmakefile
@@ -19,7 +19,13 @@ ifeq ($(HAVE_EXPAT),yes)
 CPPFLAGS 	:=	-DHAVE_EXPAT $(EXPAT_INCLUDE) $(CPPFLAGS)
 endif
 
-CPPFLAGS	:=	-Iogrsf_frmts -I. $(GDAL_INCLUDE) $(PROJ_INCLUDE) $(PROJ_FLAGS) $(CPPFLAGS)
+ifeq ($(LIBZ_SETTING),internal)
+ZLIB_XTRA_OPT =      -I../frmts/zlib
+else
+ZLIB_XTRA_OPT =
+endif
+
+CPPFLAGS	:=	-Iogrsf_frmts -I. $(GDAL_INCLUDE) $(PROJ_INCLUDE) $(PROJ_FLAGS) $(CPPFLAGS) $(ZLIB_XTRA_OPT)
 
 default:	lib
 
diff --git a/ogr/file.lst b/ogr/file.lst
index 608a44f..c989fb7 100644
--- a/ogr/file.lst
+++ b/ogr/file.lst
@@ -41,5 +41,7 @@ OBJ =	ogrgeometryfactory.o \
 	ograssemblepolygon.o \
 	ogr2gmlgeometry.o \
 	gml2ogrgeometry.o \
-	ogr_expat.o
+	ogr_expat.o \
+	ogrpgeogeometry.o \
+	ogrgeomediageometry.o
 	
diff --git a/ogr/gml2ogrgeometry.cpp b/ogr/gml2ogrgeometry.cpp
index ffba696..6f2e407 100644
--- a/ogr/gml2ogrgeometry.cpp
+++ b/ogr/gml2ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gml2ogrgeometry.cpp 21605 2011-01-30 12:33:48Z rouault $
+ * $Id: gml2ogrgeometry.cpp 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Code to translate between GML and OGR geometry forms.
@@ -50,6 +50,42 @@
 #define PI  3.14159265358979323846
 #endif
 
+
+/************************************************************************/
+/*                        GMLGetCoordTokenPos()                         */
+/************************************************************************/
+
+static const char* GMLGetCoordTokenPos(const char* pszStr,
+                                       const char** ppszNextToken)
+{
+    char ch;
+    while(TRUE)
+    {
+        ch = *pszStr;
+        if (ch == '\0')
+        {
+            *ppszNextToken = NULL;
+            return NULL;
+        }
+        else if (!(ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' || ch == ','))
+            break;
+        pszStr ++;
+    }
+
+    const char* pszToken = pszStr;
+    while((ch = *pszStr) != '\0')
+    {
+        if (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' || ch == ',')
+        {
+            *ppszNextToken = pszStr;
+            return pszToken;
+        }
+        pszStr ++;
+    }
+    *ppszNextToken = NULL;
+    return pszToken;
+}
+
 /************************************************************************/
 /*                           BareGMLElement()                           */
 /*                                                                      */
@@ -120,6 +156,29 @@ static const char *GetElementText( const CPLXMLNode *psElement )
 }
 
 /************************************************************************/
+/*                           GetChildElement()                          */
+/************************************************************************/
+
+static const CPLXMLNode *GetChildElement( const CPLXMLNode *psElement )
+
+{
+    if( psElement == NULL )
+        return NULL;
+
+    const CPLXMLNode *psChild = psElement->psChild;
+
+    while( psChild != NULL )
+    {
+        if( psChild->eType == CXT_Element )
+            return psChild;
+
+        psChild = psChild->psNext;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
 /*                    GetElementOrientation()                           */
 /*     Returns true for positive orientation.                           */
 /************************************************************************/
@@ -153,12 +212,12 @@ static int AddPoint( OGRGeometry *poGeometry,
                      double dfX, double dfY, double dfZ, int nDimension )
 
 {
-    if( poGeometry->getGeometryType() == wkbPoint 
-        || poGeometry->getGeometryType() == wkbPoint25D )
+    OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
+    if( eType == wkbPoint )
     {
         OGRPoint *poPoint = (OGRPoint *) poGeometry;
 
-        if( poPoint->getX() != 0.0 || poPoint->getY() != 0.0 )
+        if( !poPoint->IsEmpty() )
         {
             CPLError( CE_Failure, CPLE_AppDefined, 
                       "More than one coordinate for <Point> element.");
@@ -173,8 +232,7 @@ static int AddPoint( OGRGeometry *poGeometry,
         return TRUE;
     }
                 
-    else if( poGeometry->getGeometryType() == wkbLineString
-             || poGeometry->getGeometryType() == wkbLineString25D )
+    else if( eType == wkbLineString )
     {
         if( nDimension == 3 )
             ((OGRLineString *) poGeometry)->addPoint( dfX, dfY, dfZ );
@@ -207,6 +265,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
     if( psCoordinates != NULL )
     {
         const char *pszCoordString = GetElementText( psCoordinates );
+        char chCS = ',';
 
         if( pszCoordString == NULL )
         {
@@ -227,42 +286,20 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                    && !isspace((unsigned char)*pszCoordString) )
                 pszCoordString++;
 
-            if( *pszCoordString == '\0' || isspace((unsigned char)*pszCoordString) )
+            if( *pszCoordString == '\0' )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Corrupt <coordinates> value." );
+                return FALSE;
+            }
+            else if( chCS == ',' && isspace((unsigned char)*pszCoordString) )
             {
-                /* In theory, the coordinates inside a 2 or 3 tuple should be */
+                /* In theory, the coordinates inside a coordinate tuple should be */
                 /* separated by a comma. However it has been found in the wild */
-                /* that for <gml:Point>, the coordinates are in rare cases separated by a space */
+                /* that the coordinates are in rare cases separated by a space, and the tuples by a comma */
                 /* See https://52north.org/twiki/bin/view/Processing/WPS-IDWExtension-ObservationCollectionExample */
                 /* or http://agisdemo.faa.gov/aixmServices/getAllFeaturesByLocatorId?locatorId=DFW */
-                if ( poGeometry->getGeometryType() == wkbPoint )
-                {
-                    char **papszTokens = CSLTokenizeStringComplex(
-                        GetElementText( psCoordinates ), " ,", FALSE, FALSE );
-                    int bSuccess = FALSE;
-
-                    if( CSLCount( papszTokens ) == 3 )
-                    {
-                        bSuccess = AddPoint( poGeometry,
-                                            OGRFastAtof(papszTokens[0]),
-                                            OGRFastAtof(papszTokens[1]),
-                                            OGRFastAtof(papszTokens[2]), 3 );
-                    }
-                    else if( CSLCount( papszTokens ) == 2 )
-                    {
-                        bSuccess = AddPoint( poGeometry,
-                                            OGRFastAtof(papszTokens[0]),
-                                            OGRFastAtof(papszTokens[1]),
-                                            0.0, 2 );
-                    }
-
-                    CSLDestroy(papszTokens);
-                    if (bSuccess)
-                        return TRUE;
-                }
-
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Corrupt <coordinates> value." );
-                return FALSE;
+                chCS = ' ';
             }
 
             pszCoordString++;
@@ -272,7 +309,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                    && !isspace((unsigned char)*pszCoordString) )
                 pszCoordString++;
 
-            if( *pszCoordString == ',' )
+            if( *pszCoordString == chCS )
             {
                 pszCoordString++;
                 dfZ = OGRFastAtof( pszCoordString );
@@ -283,6 +320,11 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
                 pszCoordString++;
             }
 
+            if ( chCS == ' ' && *pszCoordString == ',' )
+            {
+                pszCoordString++;
+            }
+
             while( isspace((unsigned char)*pszCoordString) )
                 pszCoordString++;
 
@@ -304,50 +346,76 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
     const CPLXMLNode *psPos;
     
     int bHasFoundPosElement = FALSE;
-    for( psPos = psGeomNode->psChild; 
+    for( psPos = psGeomNode->psChild;
          psPos != NULL;
          psPos = psPos->psNext )
     {
-        if( psPos->eType != CXT_Element 
-            || !EQUAL(BareGMLElement(psPos->pszValue),"pos") )
+        if( psPos->eType != CXT_Element  )
             continue;
-        
-        char **papszTokens = CSLTokenizeStringComplex( 
-            GetElementText( psPos ), " ,", FALSE, FALSE );
-        int bSuccess = FALSE;
 
-        if( CSLCount( papszTokens ) > 2 )
-        {
-            bSuccess = AddPoint( poGeometry, 
-                                 OGRFastAtof(papszTokens[0]), 
-                                 OGRFastAtof(papszTokens[1]),
-                                 OGRFastAtof(papszTokens[2]), 3 );
-        }
-        else if( CSLCount( papszTokens ) > 1 )
+        const char* pszSubElement = BareGMLElement(psPos->pszValue);
+
+        if( EQUAL(pszSubElement, "pointProperty") )
         {
-            bSuccess = AddPoint( poGeometry, 
-                                 OGRFastAtof(papszTokens[0]), 
-                                 OGRFastAtof(papszTokens[1]),
-                                 0.0, 2 );
+            const CPLXMLNode *psPointPropertyIter;
+            for( psPointPropertyIter = psPos->psChild;
+                 psPointPropertyIter != NULL;
+                 psPointPropertyIter = psPointPropertyIter->psNext )
+            {
+                if( psPointPropertyIter->eType != CXT_Element  )
+                    continue;
+
+                if (EQUAL(BareGMLElement(psPointPropertyIter->pszValue),"Point") )
+                {
+                    OGRPoint oPoint;
+                    if( ParseGMLCoordinates( psPointPropertyIter, &oPoint ) )
+                    {
+                        int bSuccess = AddPoint( poGeometry, oPoint.getX(),
+                                                 oPoint.getY(), oPoint.getZ(),
+                                                 oPoint.getCoordinateDimension() );
+                        if (bSuccess)
+                            bHasFoundPosElement = TRUE;
+                        else
+                            return FALSE;
+                    }
+                }
+            }
+            continue;
         }
-        else
+
+        if( !EQUAL(pszSubElement,"pos") )
+            continue;
+
+        const char* pszPos = GetElementText( psPos );
+        const char* pszCur = pszPos;
+        const char* pszX = (pszCur != NULL) ?
+                            GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
+        const char* pszY = (pszCur != NULL) ?
+                            GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
+        const char* pszZ = (pszCur != NULL) ?
+                            GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
+
+        if (pszY == NULL)
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Did not get 2+ values in <gml:pos>%s</gml:pos> tuple.",
-                      GetElementText( psPos ) ? GetElementText( psPos ) : "" );
+                      pszPos ? pszPos : "" );
+            return FALSE;
         }
 
-        CSLDestroy( papszTokens );
-        
+        double dfX = OGRFastAtof(pszX);
+        double dfY = OGRFastAtof(pszY);
+        double dfZ = (pszZ != NULL) ? OGRFastAtof(pszZ) : 0.0;
+        int bSuccess = AddPoint( poGeometry, dfX, dfY, dfZ, (pszZ != NULL) ? 3 : 2 );
+
         if (bSuccess)
             bHasFoundPosElement = TRUE;
         else
             return FALSE;
     }
-    
+
     if (bHasFoundPosElement)
         return TRUE;
-    
 
 /* -------------------------------------------------------------------- */
 /*      Is this a "posList"?  GML 3 construct (SF profile).             */
@@ -356,9 +424,7 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
     
     if( psPosList != NULL )
     {
-        char **papszTokens;
         int bSuccess = FALSE;
-        int i=0, nCount=0;
         const CPLXMLNode* psChild;
         int nDimension = 2;
 
@@ -388,31 +454,44 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
             return FALSE;
         }
 
-        papszTokens = CSLTokenizeStringComplex( 
-            GetElementText( psPosList ), " ,\t", FALSE, FALSE );
-
-        nCount = CSLCount( papszTokens );
-
-        if (nCount < nDimension  || (nCount % nDimension) != 0)
+        const char* pszPosList = GetElementText( psPosList );
+        if (pszPosList == NULL)
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Did not get at least %d values or invalid number of \n"
                       "set of coordinates <gml:posList>%s</gml:posList>",
-                      nDimension, GetElementText( psPosList ) ? GetElementText( psPosList ) : "");
+                      nDimension, pszPosList ? pszPosList : "");
+            return FALSE;
         }
-        else
+
+        const char* pszCur = pszPosList;
+        while (TRUE)
         {
-            i=0;
-            while (i<nCount)
+            const char* pszX = GMLGetCoordTokenPos(pszCur, &pszCur);
+            if (pszX == NULL && bSuccess)
+                break;
+            const char* pszY = (pszCur != NULL) ?
+                    GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
+            const char* pszZ = (nDimension == 3 && pszCur != NULL) ?
+                    GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
+
+            if (pszY == NULL || (nDimension == 3 && pszZ == NULL))
             {
-                bSuccess = AddPoint( poGeometry, 
-                                     OGRFastAtof(papszTokens[i]), 
-                                     OGRFastAtof(papszTokens[i+1]),
-                                     (nDimension == 3) ? OGRFastAtof(papszTokens[i+2]) : 0.0, nDimension );
-                i+=nDimension;
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Did not get at least %d values or invalid number of \n"
+                        "set of coordinates <gml:posList>%s</gml:posList>",
+                        nDimension, pszPosList ? pszPosList : "");
+                return FALSE;
             }
+
+            double dfX = OGRFastAtof(pszX);
+            double dfY = OGRFastAtof(pszY);
+            double dfZ = (pszZ != NULL) ? OGRFastAtof(pszZ) : 0.0;
+            bSuccess = AddPoint( poGeometry, dfX, dfY, dfZ, nDimension );
+
+            if (bSuccess == FALSE || pszCur == NULL)
+                break;
         }
-        CSLDestroy( papszTokens );
 
         return bSuccess;
     }
@@ -468,6 +547,76 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
     return iCoord > 0.0;
 }
 
+#ifdef HAVE_GEOS
+/************************************************************************/
+/*                         GML2FaceExtRing()                            */
+/*                                                                      */
+/*      Identifies the "good" Polygon whithin the collection returned   */
+/*      by GEOSPolygonize()                                             */
+/*      short rationale: GEOSPolygonize() will possibily return a       */
+/*      collection of many Polygons; only one is the "good" one,        */
+/*      (including both exterior- and interior-rings)                   */
+/*      any other simply represents a single "hole", and should be      */
+/*      consequently ignored at all.                                    */
+/************************************************************************/
+
+static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
+{
+    OGRPolygon *poPolygon = NULL;
+	int bError = FALSE;
+    OGRGeometryCollection *poColl = (OGRGeometryCollection *)poGeom;
+    int iCount = poColl->getNumGeometries();
+	int iExterior = 0;
+	int iInterior = 0;
+
+    for( int ig = 0; ig < iCount; ig++)
+    {
+        /* a collection of Polygons is expected to be found */
+        OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
+        if( poChild == NULL)
+        {
+            bError = TRUE;
+            continue;
+        }
+        if( wkbFlatten( poChild->getGeometryType()) == wkbPolygon )
+        {
+            OGRPolygon *poPg = (OGRPolygon *)poChild;
+            if( poPg->getNumInteriorRings() > 0 )
+                iExterior++;
+            else
+                iInterior++;
+        }
+        else
+            bError = TRUE;
+    }
+
+    if( bError == FALSE && iCount > 0 )
+    {
+       if( iCount == 1 && iExterior == 0 && iInterior == 1)
+        {
+            /* there is a single Polygon within the collection */
+            OGRPolygon * poPg = (OGRPolygon*)poColl->getGeometryRef(0 );
+            poPolygon = (OGRPolygon *)poPg->clone();
+        }
+        else
+        {
+            if( iExterior == 1 && iInterior == iCount - 1 )
+            {
+                /* searching the unique Polygon containing holes */
+                for ( int ig = 0; ig < iCount; ig++)
+                {
+                    OGRPolygon * poPg = (OGRPolygon*)poColl->getGeometryRef(ig);
+                    if( poPg->getNumInteriorRings() > 0 )
+                        poPolygon = (OGRPolygon *)poPg->clone();
+                }
+            }
+        }
+    }
+
+    return poPolygon;
+}
+#endif
+
 /************************************************************************/
 /*                      GML2OGRGeometry_XMLNode()                       */
 /*                                                                      */
@@ -476,15 +625,27 @@ static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeo
 /*      collections.                                                    */
 /************************************************************************/
 
-static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
-                                             int bIgnoreGSG = FALSE,
-                                             int bOrientation = TRUE )
+OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
+                                      int bGetSecondaryGeometryOption,
+                                      int nRecLevel,
+                                      int bIgnoreGSG,
+                                      int bOrientation,
+                                      int bFaceHoleNegative ) 
 
 {
     const char *pszBaseGeometry = BareGMLElement( psNode->pszValue );
-    int bGetSecondaryGeometry =
-            bIgnoreGSG ? FALSE :
-            CSLTestBoolean(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
+    if (bGetSecondaryGeometryOption < 0)
+        bGetSecondaryGeometryOption = CSLTestBoolean(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
+    int bGetSecondaryGeometry = bIgnoreGSG ? FALSE : bGetSecondaryGeometryOption;
+
+    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    if( nRecLevel == 32 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Too many recursiong level (%d) while parsing GML geometry.",
+                    nRecLevel );
+        return NULL;
+    }
 
     if( bGetSecondaryGeometry )
         if( !( EQUAL(pszBaseGeometry,"directedEdge") ||
@@ -518,7 +679,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
 
         // Translate outer ring and add to polygon.
         poRing = (OGRLinearRing *) 
-            GML2OGRGeometry_XMLNode( psChild->psChild );
+            GML2OGRGeometry_XMLNode( psChild->psChild, bGetSecondaryGeometryOption,
+                                     nRecLevel + 1 );
         if( poRing == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined, "Invalid exterior ring");
@@ -549,7 +711,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             {
                 if (psChild->psChild != NULL)
                     poRing = (OGRLinearRing *) 
-                        GML2OGRGeometry_XMLNode( psChild->psChild );
+                        GML2OGRGeometry_XMLNode( psChild->psChild, bGetSecondaryGeometryOption,
+                                                 nRecLevel + 1);
                 else
                     poRing = NULL;
                 if (poRing == NULL)
@@ -605,10 +768,12 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
             {
+                const CPLXMLNode* psCurveChild = GetChildElement(psChild);
                 OGRLineString *poLS;
-                if (psChild->psChild)
+                if (psCurveChild != NULL)
                     poLS = (OGRLineString *) 
-                        GML2OGRGeometry_XMLNode( psChild->psChild );
+                        GML2OGRGeometry_XMLNode( psCurveChild, bGetSecondaryGeometryOption,
+                                                 nRecLevel + 1);
                 else
                     poLS = NULL;
 
@@ -818,11 +983,13 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 && (EQUAL(BareGMLElement(psChild->pszValue),"polygonMember") ||
                     EQUAL(BareGMLElement(psChild->pszValue),"surfaceMember")) )
             {
+                const CPLXMLNode* psSurfaceChild = GetChildElement(psChild);
                 OGRPolygon *poPolygon;
 
-                if (psChild->psChild != NULL)
+                if (psSurfaceChild != NULL)
                     poPolygon = (OGRPolygon *) 
-                        GML2OGRGeometry_XMLNode( psChild->psChild );
+                        GML2OGRGeometry_XMLNode( psSurfaceChild, bGetSecondaryGeometryOption,
+                                                 nRecLevel + 1);
                 else
                     poPolygon = NULL;
 
@@ -859,7 +1026,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                             EQUAL(BareGMLElement(psChild2->pszValue),"Polygon") ||
                             EQUAL(BareGMLElement(psChild2->pszValue),"PolygonPatch")) )
                     {
-                        OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psChild2 );
+                        OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psChild2, bGetSecondaryGeometryOption,
+                                                                       nRecLevel + 1);
                         if (poGeom == NULL)
                         {
                             CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
@@ -915,11 +1083,13 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"pointMember") )
             {
+                const CPLXMLNode* psPointChild = GetChildElement(psChild);
                 OGRPoint *poPoint;
 
-                if (psChild->psChild != NULL)
+                if (psPointChild != NULL)
                     poPoint = (OGRPoint *) 
-                        GML2OGRGeometry_XMLNode( psChild->psChild );
+                        GML2OGRGeometry_XMLNode( psPointChild, bGetSecondaryGeometryOption,
+                                                 nRecLevel + 1);
                 else
                     poPoint = NULL;
                 if( poPoint == NULL 
@@ -946,7 +1116,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                     if( psChild2->eType == CXT_Element
                         && (EQUAL(BareGMLElement(psChild2->pszValue),"Point")) )
                     {
-                        OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psChild2 );
+                        OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psChild2, bGetSecondaryGeometryOption,
+                                                                       nRecLevel + 1);
                         if (poGeom == NULL)
                         {
                             CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
@@ -992,10 +1163,12 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"lineStringMember") )
             {
+                const CPLXMLNode* psLineStringChild = GetChildElement(psChild);
                 OGRGeometry *poGeom;
 
-                if (psChild->psChild != NULL)
-                    poGeom = GML2OGRGeometry_XMLNode( psChild->psChild );
+                if (psLineStringChild != NULL)
+                    poGeom = GML2OGRGeometry_XMLNode( psLineStringChild, bGetSecondaryGeometryOption,
+                                                      nRecLevel + 1);
                 else
                     poGeom = NULL;
                 if( poGeom == NULL 
@@ -1047,7 +1220,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                     delete poMLS;
                     return NULL;
                 }
-                poGeom = GML2OGRGeometry_XMLNode( psCurve );
+                poGeom = GML2OGRGeometry_XMLNode( psCurve, bGetSecondaryGeometryOption,
+                                                  nRecLevel + 1);
                 if( poGeom == NULL ||
                     ( wkbFlatten(poGeom->getGeometryType()) != wkbLineString ) )
                 {
@@ -1072,7 +1246,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                     if( psChild2->eType == CXT_Element
                         && (EQUAL(BareGMLElement(psChild2->pszValue),"LineString")) )
                     {
-                        OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psChild2 );
+                        OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psChild2, bGetSecondaryGeometryOption,
+                                                                       nRecLevel + 1);
                         if (poGeom == NULL)
                         {
                             CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
@@ -1118,7 +1293,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
 
         OGRGeometry *poGeom;
 
-        poGeom = GML2OGRGeometry_XMLNode( psChild );
+        poGeom = GML2OGRGeometry_XMLNode( psChild, bGetSecondaryGeometryOption,
+                                          nRecLevel + 1);
         if( poGeom == NULL ||
             wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
         {
@@ -1152,7 +1328,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             {
                 OGRGeometry *poGeom;
 
-                poGeom = GML2OGRGeometry_XMLNode( psChild );
+                poGeom = GML2OGRGeometry_XMLNode( psChild, bGetSecondaryGeometryOption,
+                                                  nRecLevel + 1);
                 if( poGeom != NULL &&
                     wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
                 {
@@ -1194,10 +1371,12 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             if( psChild->eType == CXT_Element
                 && EQUAL(BareGMLElement(psChild->pszValue),"geometryMember") )
             {
+                const CPLXMLNode* psGeometryChild = GetChildElement(psChild);
                 OGRGeometry *poGeom;
 
-                if (psChild->psChild != NULL)
-                    poGeom = GML2OGRGeometry_XMLNode( psChild->psChild );
+                if (psGeometryChild != NULL)
+                    poGeom = GML2OGRGeometry_XMLNode( psGeometryChild, bGetSecondaryGeometryOption,
+                                                      nRecLevel + 1 );
                 else
                     poGeom = NULL;
                 if( poGeom == NULL )
@@ -1266,7 +1445,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 psPoint = FindBareXMLChild(pspointProperty,"ConnectionPoint");
             if( psPoint == NULL ) goto nonode;
 
-            poGeom = GML2OGRGeometry_XMLNode( psPoint, TRUE );
+            poGeom = GML2OGRGeometry_XMLNode( psPoint, bGetSecondaryGeometryOption,
+                                              nRecLevel + 1, TRUE );
             if( poGeom == NULL
                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
             {
@@ -1305,7 +1485,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 psPoint = FindBareXMLChild(pspointProperty,"ConnectionPoint");
             if( psPoint == NULL ) goto nonode;
 
-            poGeom = GML2OGRGeometry_XMLNode( psPoint, TRUE );
+            poGeom = GML2OGRGeometry_XMLNode( psPoint, bGetSecondaryGeometryOption,
+                                              nRecLevel + 1, TRUE );
             if( poGeom == NULL
                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
             {
@@ -1349,7 +1530,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             return NULL;
         }
 
-        poLineString = (OGRLineString *)GML2OGRGeometry_XMLNode( psCurve, TRUE );
+        poLineString = (OGRLineString *)GML2OGRGeometry_XMLNode( psCurve, bGetSecondaryGeometryOption,
+                                                                 nRecLevel + 1, TRUE );
         if( poLineString == NULL 
             || wkbFlatten(poLineString->getGeometryType()) != wkbLineString )
         {
@@ -1433,7 +1615,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             {
                 OGRGeometry *poGeom;
 
-                poGeom = GML2OGRGeometry_XMLNode( psChild );
+                poGeom = GML2OGRGeometry_XMLNode( psChild, bGetSecondaryGeometryOption,
+                                                  nRecLevel + 1 );
                 if( poGeom == NULL )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1494,6 +1677,175 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
     if( EQUAL(pszBaseGeometry,"TopoSurface") )
     {
+        /****************************************************************/
+        /* applying the FaceHoleNegative = FALSE rules                  */
+        /*                                                              */
+        /* - each <TopoSurface> is expected to represent a MultiPolygon */
+        /* - each <Face> is expected to represent a distinct Polygon,   */
+        /*   this including any possible Interior Ring (holes);         */
+        /*   orientation="+/-" plays no role at all to identify "holes" */
+        /* - each <Edge> within a <Face> may indifferently represent    */
+        /*   an element of the Exterior or Interior Boundary; relative  */
+        /*   order of <Egdes> is absolutely irrelevant.                 */
+        /****************************************************************/
+        /* Contributor: Alessandro Furieri, a.furieri at lqt.it            */
+        /* Developed for Faunalia (http://www.faunalia.it)              */
+        /* with funding from Regione Toscana -                          */
+        /* Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE       */
+        /****************************************************************/
+        if(bFaceHoleNegative != TRUE)
+        {
+            if( bGetSecondaryGeometry )
+                return NULL;
+
+#ifndef HAVE_GEOS
+            static int bWarningAlreadyEmitted = FALSE;
+            if (!bWarningAlreadyEmitted)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Interpreating that GML TopoSurface geometry requires GDAL to be built with GEOS support.\n"
+                        "As a workaround, you can try defining the GML_FACE_HOLE_NEGATIVE configuration option\n"
+                        "to YES, so that the 'old' interpretation algorithm is used. But be warned that\n"
+                        "the result might be incorrect.\n");
+                bWarningAlreadyEmitted = TRUE;
+            }
+            return NULL;
+#else
+            const CPLXMLNode *psChild, *psFaceChild, *psDirectedEdgeChild;
+            OGRMultiPolygon *poTS = new OGRMultiPolygon();
+
+            // collect directed faces
+            for( psChild = psNode->psChild; 
+                psChild != NULL;
+            psChild = psChild->psNext ) 
+            {
+              if( psChild->eType == CXT_Element
+              && EQUAL(BareGMLElement(psChild->pszValue),"directedFace") )
+              {
+                // collect next face (psChild->psChild)
+                psFaceChild = psChild->psChild;
+	
+                while( psFaceChild != NULL &&
+                       !(psFaceChild->eType == CXT_Element &&
+                         EQUAL(BareGMLElement(psFaceChild->pszValue),"Face")) )
+                        psFaceChild = psFaceChild->psNext;
+
+                if( psFaceChild == NULL )
+                  continue;
+
+                OGRMultiLineString *poCollectedGeom = new OGRMultiLineString();
+
+                // collect directed edges of the face
+                for( psDirectedEdgeChild = psFaceChild->psChild;
+                     psDirectedEdgeChild != NULL;
+                     psDirectedEdgeChild = psDirectedEdgeChild->psNext )
+                {
+                  if( psDirectedEdgeChild->eType == CXT_Element &&
+                      EQUAL(BareGMLElement(psDirectedEdgeChild->pszValue),"directedEdge") )
+                  {
+                    OGRGeometry *poEdgeGeom;
+
+                    poEdgeGeom = GML2OGRGeometry_XMLNode( psDirectedEdgeChild,
+                                                          bGetSecondaryGeometryOption,
+                                                          TRUE );
+
+                    if( poEdgeGeom == NULL ||
+                        wkbFlatten(poEdgeGeom->getGeometryType()) != wkbLineString )
+                    {
+                      CPLError( CE_Failure, CPLE_AppDefined, 
+                                "Failed to get geometry in directedEdge" );
+                      delete poEdgeGeom;
+                      delete poCollectedGeom;
+                      delete poTS;
+                      return NULL;
+                    }
+
+                    poCollectedGeom->addGeometryDirectly( poEdgeGeom );
+                  }
+                }
+
+                OGRGeometry *poFaceCollectionGeom = NULL;
+                OGRPolygon *poFaceGeom = NULL;
+
+//#ifdef HAVE_GEOS
+                poFaceCollectionGeom = poCollectedGeom->Polygonize();
+                if( poFaceCollectionGeom == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Failed to assemble Edges in Face" );
+                    delete poCollectedGeom;
+                    delete poTS;
+                    return NULL;
+                }
+
+                poFaceGeom = GML2FaceExtRing( poFaceCollectionGeom );
+//#else
+//                poFaceGeom = (OGRPolygon*) OGRBuildPolygonFromEdges(
+//                    (OGRGeometryH) poCollectedGeom,
+//                    FALSE, TRUE, 0, NULL);
+//#endif
+
+                if( poFaceGeom == NULL )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                                "Failed to build Polygon for Face" );
+                    delete poCollectedGeom;
+                    delete poTS;
+                    return NULL;
+                }
+                else
+                {
+                    int iCount = poTS->getNumGeometries();
+                    if( iCount == 0)
+                    {
+                        /* inserting the first Polygon */
+                        poTS->addGeometryDirectly( poFaceGeom );
+                    }
+                    else
+                    {
+                        /* using Union to add the current Polygon */
+                        OGRGeometry *poUnion = poTS->Union( poFaceGeom );
+                        delete poFaceGeom;
+                        delete poTS;
+                        if( poUnion == NULL )
+                        {
+                            CPLError( CE_Failure, CPLE_AppDefined,
+                                        "Failed Union for TopoSurface" );
+                            return NULL;
+                        }
+                        poTS = (OGRMultiPolygon *)poUnion;
+                    }
+                }
+                delete poFaceCollectionGeom;
+                delete poCollectedGeom;
+              }
+            }
+
+            if( wkbFlatten( poTS->getGeometryType()) == wkbPolygon )
+            {
+                /* forcing to be a MultiPolygon */
+                OGRGeometry *poOldTS = poTS;
+                poTS = new OGRMultiPolygon();
+                poTS->addGeometryDirectly(poOldTS);
+            }
+
+            return poTS;
+#endif // HAVE_GEOS
+        }
+
+        /****************************************************************/
+        /* applying the FaceHoleNegative = TRUE rules                   */
+        /*                                                              */
+        /* - each <TopoSurface> is expected to represent a MultiPolygon */
+        /* - any <Face> declaring orientation="+" is expected to        */
+        /*   represent an Exterior Ring (no holes are allowed)          */
+        /* - any <Face> declaring orientation="-" is expected to        */
+        /*   represent an Interior Ring (hole) belonging to the latest  */
+        /*   Exterior Ring.                                             */
+        /* - <Egdes> within the same <Face> are expected to be          */
+        /*   arranged in geometrically adjacent and consecutive         */
+        /*   sequence.                                                  */
+        /****************************************************************/
         if( bGetSecondaryGeometry )
             return NULL;
         const CPLXMLNode *psChild, *psFaceChild, *psDirectedEdgeChild;
@@ -1508,8 +1860,6 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
           if( psChild->eType == CXT_Element
               && EQUAL(BareGMLElement(psChild->pszValue),"directedFace") )
           {
-            OGRLinearRing *poFaceGeom = new OGRLinearRing();
-
             bFaceOrientation = GetElementOrientation(psChild);
 
             // collect next face (psChild->psChild)
@@ -1521,6 +1871,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             if( psFaceChild == NULL )
               continue;
 
+            OGRLinearRing *poFaceGeom = new OGRLinearRing();
+
             // collect directed edges of the face
             for( psDirectedEdgeChild = psFaceChild->psChild;
                  psDirectedEdgeChild != NULL;
@@ -1532,6 +1884,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 OGRGeometry *poEdgeGeom;
 
                 poEdgeGeom = GML2OGRGeometry_XMLNode( psDirectedEdgeChild,
+                                                      bGetSecondaryGeometryOption,
+                                                      nRecLevel + 1,
                                                       TRUE,
                                                       bFaceOrientation );
 
@@ -1541,6 +1895,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                   CPLError( CE_Failure, CPLE_AppDefined, 
                             "Failed to get geometry in directedEdge" );
                   delete poEdgeGeom;
+                  delete poFaceGeom;
+                  delete poTS;
                   return NULL;
                 }
 
@@ -1609,7 +1965,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                     EQUAL(BareGMLElement(psChild->pszValue),"Rectangle")))
             {
                 OGRPolygon *poPolygon = (OGRPolygon *) 
-                    GML2OGRGeometry_XMLNode( psChild );
+                    GML2OGRGeometry_XMLNode( psChild, bGetSecondaryGeometryOption,
+                                             nRecLevel + 1 );
                 if( poPolygon == NULL )
                     return NULL;
                 
@@ -1660,7 +2017,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                 && EQUAL(BareGMLElement(psChild->pszValue),"Triangle") )
             {
                 OGRPolygon *poPolygon = (OGRPolygon *)
-                    GML2OGRGeometry_XMLNode( psChild );
+                    GML2OGRGeometry_XMLNode( psChild, bGetSecondaryGeometryOption,
+                                             nRecLevel + 1 );
                 if( poPolygon == NULL )
                     return NULL;
 
@@ -1702,7 +2060,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
         }
 
         // Get the geometry inside <exterior>
-        poGeom = GML2OGRGeometry_XMLNode( psChild->psChild );
+        poGeom = GML2OGRGeometry_XMLNode( psChild->psChild, bGetSecondaryGeometryOption,
+                                          nRecLevel + 1 );
         if( poGeom == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined, "Invalid exterior element");
@@ -1742,7 +2101,8 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
             return NULL;
         }
 
-        return GML2OGRGeometry_XMLNode( psChild->psChild );
+        return GML2OGRGeometry_XMLNode( psChild->psChild, bGetSecondaryGeometryOption,
+                                        nRecLevel + 1 );
     }
 
     CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1759,7 +2119,7 @@ static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
 OGRGeometryH OGR_G_CreateFromGMLTree( const CPLXMLNode *psTree )
 
 {
-    return (OGRGeometryH) GML2OGRGeometry_XMLNode( psTree );
+    return (OGRGeometryH) GML2OGRGeometry_XMLNode( psTree, -1 );
 }
 
 /************************************************************************/
@@ -1817,7 +2177,9 @@ OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
 /* -------------------------------------------------------------------- */
     OGRGeometry *poGeometry;
 
-    poGeometry = GML2OGRGeometry_XMLNode( psGML );
+    /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
+    int bFaceHoleNegative = CSLTestBoolean(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
+    poGeometry = GML2OGRGeometry_XMLNode( psGML, -1, 0, FALSE, TRUE, bFaceHoleNegative );
 
     CPLDestroyXMLNode( psGML );
     
diff --git a/ogr/makefile.vc b/ogr/makefile.vc
index 8fb762d..ed5c110 100644
--- a/ogr/makefile.vc
+++ b/ogr/makefile.vc
@@ -1,6 +1,6 @@
 
 LINKFLAGS =	/Zi /MTd
-EXTRAFLAGS =	-DWIN32 -I. -Iogrsf_frmts -I..\frmts\gtiff\libgeotiff \
+EXTRAFLAGS =	-DWIN32 -I. -Iogrsf_frmts -I..\frmts\gtiff\libgeotiff -I..\frmts\zlib \
 		$(PROJ_FLAGS) $(PROJ_INCLUDE) $(GEOS_CFLAGS)
 
 GDAL_ROOT = 	..
@@ -30,7 +30,8 @@ OBJ_OGR	=	ogrgeometryfactory.obj ogrpoint.obj ogrcurve.obj ogr_api.obj \
 		ogr_srs_usgs.obj ogr_srs_dict.obj ogr_srs_panorama.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
+		swq_op_general.obj swq_expr_node.obj ogrpgeogeometry.obj \
+		ogrgeomediageometry.obj
 
 default:        ogr.lib 
 
@@ -61,3 +62,8 @@ allclean:	clean
 	$(MAKE) /f makefile.vc clean
 	cd ..
 
+# special override to avoid some warnings with this generated code.
+
+swq_parser.obj:	swq_parser.cpp
+	$(CC) $(CFLAGS) $(SOFTWARNFLAGS) /c $*.cpp
+
diff --git a/ogr/ogr2gmlgeometry.cpp b/ogr/ogr2gmlgeometry.cpp
index 6a16305..374da95 100644
--- a/ogr/ogr2gmlgeometry.cpp
+++ b/ogr/ogr2gmlgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2gmlgeometry.cpp 21023 2010-10-30 19:48:23Z rouault $
+ * $Id: ogr2gmlgeometry.cpp 23502 2011-12-09 18:49:24Z rouault $
  *
  * Project:  GML Translator
  * Purpose:  Code to translate OGRGeometry to GML string representation.
@@ -176,8 +176,8 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
 
     // Buffer for srsName attribute (srsName="...")
-    char szSrsName[30] = { 0 }; 
-    int nSrsNameLength = 0;
+    char szAttributes[30] = { 0 };
+    int nAttrsLength = 0;
 
     const OGRSpatialReference* poSRS = NULL;
     poSRS = poGeometry->getSpatialReference();
@@ -201,10 +201,10 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
                 pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
                 if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
                 {
-                    sprintf( szSrsName, " srsName=\"%s:%s\"",
+                    sprintf( szAttributes, " srsName=\"%s:%s\"",
                             pszAuthName, pszAuthCode );
 
-                    nSrsNameLength = strlen(szSrsName);
+                    nAttrsLength = strlen(szAttributes);
                 }
             }
         }
@@ -221,12 +221,12 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         MakeGMLCoordinate( szCoordinate, 
                            poPoint->getX(), poPoint->getY(), 0.0, FALSE );
 
-        _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nSrsNameLength, 
+        _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
                      ppszText, pnMaxLength );
 
         sprintf( *ppszText + *pnLength, 
                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
-                 szSrsName, szCoordinate );
+                 szAttributes, szCoordinate );
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -242,12 +242,12 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
                            poPoint->getX(), poPoint->getY(), poPoint->getZ(), 
                            TRUE );
                            
-        _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nSrsNameLength, 
+        _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
                      ppszText, pnMaxLength );
 
         sprintf( *ppszText + *pnLength, 
                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
-                 szSrsName, szCoordinate );
+                 szAttributes, szCoordinate );
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -263,18 +263,18 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         // Buffer for tag name + srsName attribute if set
         const size_t nLineTagLength = 16;
         char* pszLineTagName = NULL;
-        pszLineTagName = (char *) CPLMalloc( nLineTagLength + nSrsNameLength + 1 );
+        pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
 
         if( bRing )
         {
-            sprintf( pszLineTagName, "<gml:LinearRing%s>", szSrsName );
+            sprintf( pszLineTagName, "<gml:LinearRing%s>", szAttributes );
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           pszLineTagName );
         }
         else
         {
-            sprintf( pszLineTagName, "<gml:LineString%s>", szSrsName );
+            sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           pszLineTagName );
@@ -305,10 +305,10 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         // Buffer for polygon tag name + srsName attribute if set
         const size_t nPolyTagLength = 13;
         char* pszPolyTagName = NULL;
-        pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nSrsNameLength + 1 );
+        pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
 
         // Compose Polygon tag with or without srsName attribute
-        sprintf( pszPolyTagName, "<gml:Polygon%s>", szSrsName );
+        sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
 
         AppendString( ppszText, pnLength, pnMaxLength,
                       pszPolyTagName );
@@ -371,32 +371,32 @@ static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 
         if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
         {
-            pszElemOpen = (char *) CPLMalloc( 13 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiPolygon%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiPolygon%s>", szAttributes );
 
             pszElemClose = "MultiPolygon>";
             pszMemberElem = "polygonMember>";
         }
         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
         {
-            pszElemOpen = (char *) CPLMalloc( 16 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiLineString%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiLineString%s>", szAttributes );
 
             pszElemClose = "MultiLineString>";
             pszMemberElem = "lineStringMember>";
         }
         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
         {
-            pszElemOpen = (char *) CPLMalloc( 11 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiPoint%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
 
             pszElemClose = "MultiPoint>";
             pszMemberElem = "pointMember>";
         }
         else
         {
-            pszElemOpen = (char *) CPLMalloc( 19 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiGeometry%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
 
             pszElemClose = "MultiGeometry>";
             pszMemberElem = "geometryMember>";
@@ -556,7 +556,8 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
                                   int *pnMaxLength,
                                   int bIsSubGeometry,
                                   int bLongSRS,
-                                  int bLineStringAsCurve)
+                                  int bLineStringAsCurve,
+                                  const char* pszGMLId = NULL)
 
 {
 
@@ -564,9 +565,11 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
 /*      Check for Spatial Reference System attached to given geometry   */
 /* -------------------------------------------------------------------- */
 
-    // Buffer for srsName attribute (srsName="...")
-    char szSrsName[50] = { 0 };
-    int nSrsNameLength = 0;
+    // Buffer for srsName and gml:id attributes (srsName="..." gml:id="...")
+    char szAttributes[256];
+    int nAttrsLength = 0;
+
+    szAttributes[0] = 0;
 
     const OGRSpatialReference* poSRS = NULL;
     if (poParentSRS)
@@ -609,22 +612,32 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
                     {
                         if (bLongSRS)
                         {
-                            sprintf( szSrsName, " srsName=\"urn:ogc:def:crs:%s::%s\"",
-                                pszAuthName, pszAuthCode );
+                            snprintf( szAttributes, sizeof(szAttributes),
+                                      " srsName=\"urn:ogc:def:crs:%s::%s\"",
+                                      pszAuthName, pszAuthCode );
                         }
                         else
                         {
-                            sprintf( szSrsName, " srsName=\"%s:%s\"",
-                                    pszAuthName, pszAuthCode );
+                            snprintf( szAttributes, sizeof(szAttributes),
+                                      " srsName=\"%s:%s\"",
+                                      pszAuthName, pszAuthCode );
                         }
 
-                        nSrsNameLength = strlen(szSrsName);
+                        nAttrsLength = strlen(szAttributes);
                     }
                 }
             }
         }
     }
 
+    if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes))
+    {
+        strcat(szAttributes, " gml:id=\"");
+        strcat(szAttributes, pszGMLId);
+        strcat(szAttributes, "\"");
+        nAttrsLength = strlen(szAttributes);
+    }
+
 /* -------------------------------------------------------------------- */
 /*      2D Point                                                        */
 /* -------------------------------------------------------------------- */
@@ -640,12 +653,12 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
             OGRMakeWktCoordinate( szCoordinate,
                            poPoint->getX(), poPoint->getY(), 0.0, 2 );
 
-        _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nSrsNameLength,
+        _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
                      ppszText, pnMaxLength );
 
         sprintf( *ppszText + *pnLength,
                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
-                 szSrsName, szCoordinate );
+                 szAttributes, szCoordinate );
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -664,12 +677,12 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
             OGRMakeWktCoordinate( szCoordinate,
                            poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 );
 
-        _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nSrsNameLength,
+        _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
                      ppszText, pnMaxLength );
 
         sprintf( *ppszText + *pnLength,
                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
-                 szSrsName, szCoordinate );
+                 szAttributes, szCoordinate );
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -686,7 +699,7 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
             AppendString( ppszText, pnLength, pnMaxLength,
                             "<gml:Curve" );
             AppendString( ppszText, pnLength, pnMaxLength,
-                            szSrsName );
+                            szAttributes );
             AppendString( ppszText, pnLength, pnMaxLength,
                             "><gml:segments><gml:LineStringSegment>" );
             AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
@@ -699,7 +712,7 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
             // Buffer for tag name + srsName attribute if set
             const size_t nLineTagLength = 16;
             char* pszLineTagName = NULL;
-            pszLineTagName = (char *) CPLMalloc( nLineTagLength + nSrsNameLength + 1 );
+            pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
 
             if( bRing )
             {
@@ -709,7 +722,7 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
             }
             else
             {
-                sprintf( pszLineTagName, "<gml:LineString%s>", szSrsName );
+                sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
 
                 AppendString( ppszText, pnLength, pnMaxLength,
                             pszLineTagName );
@@ -741,10 +754,10 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
         // Buffer for polygon tag name + srsName attribute if set
         const size_t nPolyTagLength = 13;
         char* pszPolyTagName = NULL;
-        pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nSrsNameLength + 1 );
+        pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
 
         // Compose Polygon tag with or without srsName attribute
-        sprintf( pszPolyTagName, "<gml:Polygon%s>", szSrsName );
+        sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
 
         AppendString( ppszText, pnLength, pnMaxLength,
                       pszPolyTagName );
@@ -807,32 +820,32 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
 
         if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
         {
-            pszElemOpen = (char *) CPLMalloc( 13 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiSurface%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiSurface%s>", szAttributes );
 
             pszElemClose = "MultiSurface>";
             pszMemberElem = "surfaceMember>";
         }
         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
         {
-            pszElemOpen = (char *) CPLMalloc( 16 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiCurve%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiCurve%s>", szAttributes );
 
             pszElemClose = "MultiCurve>";
             pszMemberElem = "curveMember>";
         }
         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
         {
-            pszElemOpen = (char *) CPLMalloc( 11 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiPoint%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
 
             pszElemClose = "MultiPoint>";
             pszMemberElem = "pointMember>";
         }
         else
         {
-            pszElemOpen = (char *) CPLMalloc( 19 + nSrsNameLength + 1 );
-            sprintf( pszElemOpen, "MultiGeometry%s>", szSrsName );
+            pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
+            sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
 
             pszElemClose = "MultiGeometry>";
             pszMemberElem = "geometryMember>";
@@ -848,13 +861,21 @@ static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
             AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
 
+            char* pszGMLIdSub = NULL;
+            if (pszGMLId != NULL)
+                pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember));
+
             if( !OGR2GML3GeometryAppend( poMember, poSRS,
                                         ppszText, pnLength, pnMaxLength,
-                                        TRUE, bLongSRS, bLineStringAsCurve ) )
+                                        TRUE, bLongSRS, bLineStringAsCurve,
+                                         pszGMLIdSub) )
             {
+                CPLFree(pszGMLIdSub);
                 return FALSE;
             }
 
+            CPLFree(pszGMLIdSub);
+
             AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
         }
@@ -938,6 +959,8 @@ char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
  *      In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
  *      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.
+ * <li> GMLID=astring. If specified, a gml:id attribute will be written in the top-level geometry element with the provided value.
+ *      Required for GML 3.2 compatibility.
  * </ul>
  *
  * This method is the same as the C++ method OGRGeometry::exportToGML().
@@ -967,8 +990,9 @@ char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
         const char* pszLineStringElement = CSLFetchNameValue(papszOptions, "GML3_LINESTRING_ELEMENT");
         int bLineStringAsCurve = (pszLineStringElement && EQUAL(pszLineStringElement, "curve"));
         int bLongSRS = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GML3_LONGSRS", "YES"));
+        const char* pszGMLId = CSLFetchNameValue(papszOptions, "GMLID");
         if( !OGR2GML3GeometryAppend( (OGRGeometry *) hGeometry, NULL, &pszText,
-                                    &nLength, &nMaxLength, FALSE, bLongSRS, bLineStringAsCurve ))
+                                    &nLength, &nMaxLength, FALSE, bLongSRS, bLineStringAsCurve, pszGMLId ))
         {
             CPLFree( pszText );
             return NULL;
diff --git a/ogr/ogr_api.cpp b/ogr/ogr_api.cpp
index 34b9077..1e0fd8e 100644
--- a/ogr/ogr_api.cpp
+++ b/ogr/ogr_api.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_api.cpp 20555 2010-09-10 18:54:34Z rouault $
+ * $Id: ogr_api.cpp 22416 2011-05-22 20:19:45Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API Functions that don't correspond one-to-one with C++ 
@@ -207,6 +207,65 @@ double OGR_G_GetZ( OGRGeometryH hGeom, int i )
 }
 
 /************************************************************************/
+/*                          OGR_G_GetPoints()                           */
+/************************************************************************/
+
+/**
+ * \brief Returns all points of line string.
+ *
+ * This method copies all points into user arrays. The user provides the
+ * stride between 2 consecutives elements of the array.
+ *
+ * On some CPU architectures, care must be taken so that the arrays are properly aligned.
+ *
+ * @param hGeom handle to the geometry from which to get the coordinates.
+ * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
+ * @param nXStride the number of bytes between 2 elements of pabyX.
+ * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
+ * @param nYStride the number of bytes between 2 elements of pabyY.
+ * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
+ * @param nZStride the number of bytes between 2 elements of pabyZ.
+ *
+ * @return the number of points
+ *
+ * @since OGR 1.9.0
+ */
+
+int OGR_G_GetPoints( OGRGeometryH hGeom,
+                     void* pabyX, int nXStride,
+                     void* pabyY, int nYStride,
+                     void* pabyZ, int nZStride)
+{
+    VALIDATE_POINTER1( hGeom, "OGR_G_GetPoints", 0 );
+
+    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    {
+      case wkbPoint:
+      {
+        if (pabyX) *((double*)pabyX) = ((OGRPoint *)hGeom)->getX();
+        if (pabyY) *((double*)pabyY) = ((OGRPoint *)hGeom)->getY();
+        if (pabyZ) *((double*)pabyZ) = ((OGRPoint *)hGeom)->getZ();
+        return 1;
+      }
+      break;
+
+      case wkbLineString:
+      {
+          OGRLineString* poLS = (OGRLineString *) hGeom;
+          poLS->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride);
+          return poLS->getNumPoints();
+      }
+      break;
+
+      default:
+        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        return 0;
+        break;
+    }
+}
+
+
+/************************************************************************/
 /*                           OGR_G_GetPoint()                           */
 /************************************************************************/
 
diff --git a/ogr/ogr_api.h b/ogr/ogr_api.h
index a70f6f6..f4b3bc5 100644
--- a/ogr/ogr_api.h
+++ b/ogr/ogr_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_api.h 21270 2010-12-15 22:48:30Z warmerdam $
+ * $Id: ogr_api.h 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API for OGR Geometry, Feature, Layers, DataSource and drivers.
@@ -94,6 +94,7 @@ int    CPL_DLL OGR_G_GetCoordinateDimension( OGRGeometryH );
 void   CPL_DLL OGR_G_SetCoordinateDimension( OGRGeometryH, int );
 OGRGeometryH CPL_DLL OGR_G_Clone( OGRGeometryH );
 void   CPL_DLL OGR_G_GetEnvelope( OGRGeometryH, OGREnvelope * );
+void   CPL_DLL OGR_G_GetEnvelope3D( OGRGeometryH, OGREnvelope3D * );
 OGRErr CPL_DLL OGR_G_ImportFromWkb( OGRGeometryH, unsigned char *, int );
 OGRErr CPL_DLL OGR_G_ExportToWkb( OGRGeometryH, OGRwkbByteOrder, unsigned char*);
 int    CPL_DLL OGR_G_WkbSize( OGRGeometryH hGeom );
@@ -118,6 +119,7 @@ CPLXMLNode CPL_DLL *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH );
 char   CPL_DLL *OGR_G_ExportToKML( OGRGeometryH, const char* pszAltitudeMode );
 
 char   CPL_DLL *OGR_G_ExportToJson( OGRGeometryH );
+char   CPL_DLL *OGR_G_ExportToJsonEx( OGRGeometryH, char** papszOptions );
 OGRGeometryH CPL_DLL OGR_G_CreateGeometryFromJson( const char* );
 
 void   CPL_DLL OGR_G_AssignSpatialReference( OGRGeometryH, 
@@ -127,7 +129,7 @@ OGRErr CPL_DLL OGR_G_Transform( OGRGeometryH, OGRCoordinateTransformationH );
 OGRErr CPL_DLL OGR_G_TransformTo( OGRGeometryH, OGRSpatialReferenceH );
 
 OGRGeometryH CPL_DLL OGR_G_Simplify( OGRGeometryH hThis, double tolerance );
-/*OGRGeometryH CPL_DLL OGR_G_TopologyPreserveSimplify( OGRGeometryH hThis, double tolerance );*/
+OGRGeometryH CPL_DLL OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double tolerance );
 
 void   CPL_DLL OGR_G_Segmentize(OGRGeometryH hGeom, double dfMaxLength );
 int    CPL_DLL OGR_G_Intersects( OGRGeometryH, OGRGeometryH );
@@ -164,6 +166,8 @@ int    CPL_DLL OGR_G_IsValid( OGRGeometryH );
 /*char    CPL_DLL *OGR_G_IsValidReason( OGRGeometryH );*/
 int    CPL_DLL OGR_G_IsSimple( OGRGeometryH );
 int    CPL_DLL OGR_G_IsRing( OGRGeometryH );
+ 
+OGRGeometryH CPL_DLL OGR_G_Polygonize( OGRGeometryH );
 
 /* backward compatibility (non-standard methods) */
 int    CPL_DLL OGR_G_Intersect( OGRGeometryH, OGRGeometryH );
@@ -174,6 +178,10 @@ OGRGeometryH CPL_DLL OGR_G_GetBoundary( OGRGeometryH );
 
 /* Methods for getting/setting vertices in points, line strings and rings */
 int    CPL_DLL OGR_G_GetPointCount( OGRGeometryH );
+int    CPL_DLL OGR_G_GetPoints( OGRGeometryH hGeom,
+                                void* pabyX, int nXStride,
+                                void* pabyY, int nYStride,
+                                void* pabyZ, int nZStride);
 double CPL_DLL OGR_G_GetX( OGRGeometryH, int );
 double CPL_DLL OGR_G_GetY( OGRGeometryH, int );
 double CPL_DLL OGR_G_GetZ( OGRGeometryH, int );
@@ -223,7 +231,7 @@ typedef void *OGRStyleTableH;
 
 /* OGRFieldDefn */
 
-OGRFieldDefnH CPL_DLL OGR_Fld_Create( const char *, OGRFieldType );
+OGRFieldDefnH CPL_DLL OGR_Fld_Create( const char *, OGRFieldType ) CPL_WARN_UNUSED_RESULT;
 void   CPL_DLL OGR_Fld_Destroy( OGRFieldDefnH );
 
 void   CPL_DLL OGR_Fld_SetName( OGRFieldDefnH, const char * );
@@ -245,7 +253,7 @@ const char CPL_DLL *OGR_GetFieldTypeName( OGRFieldType );
 
 /* OGRFeatureDefn */
 
-OGRFeatureDefnH CPL_DLL OGR_FD_Create( const char * );
+OGRFeatureDefnH CPL_DLL OGR_FD_Create( const char * ) CPL_WARN_UNUSED_RESULT;
 void   CPL_DLL OGR_FD_Destroy( OGRFeatureDefnH );
 void   CPL_DLL OGR_FD_Release( OGRFeatureDefnH );
 const char CPL_DLL *OGR_FD_GetName( OGRFeatureDefnH );
@@ -253,6 +261,8 @@ int    CPL_DLL OGR_FD_GetFieldCount( OGRFeatureDefnH );
 OGRFieldDefnH CPL_DLL OGR_FD_GetFieldDefn( OGRFeatureDefnH, int );
 int    CPL_DLL OGR_FD_GetFieldIndex( OGRFeatureDefnH, const char * );
 void   CPL_DLL OGR_FD_AddFieldDefn( OGRFeatureDefnH, OGRFieldDefnH );
+OGRErr CPL_DLL OGR_FD_DeleteFieldDefn( OGRFeatureDefnH hDefn, int iField );
+OGRErr CPL_DLL OGR_FD_ReorderFieldDefns( OGRFeatureDefnH hDefn, int* panMap );
 OGRwkbGeometryType CPL_DLL OGR_FD_GetGeomType( OGRFeatureDefnH );
 void   CPL_DLL OGR_FD_SetGeomType( OGRFeatureDefnH, OGRwkbGeometryType );
 int    CPL_DLL OGR_FD_IsGeometryIgnored( OGRFeatureDefnH );
@@ -265,7 +275,7 @@ int    CPL_DLL OGR_FD_GetReferenceCount( OGRFeatureDefnH );
 
 /* OGRFeature */
 
-OGRFeatureH CPL_DLL OGR_F_Create( OGRFeatureDefnH );
+OGRFeatureH CPL_DLL OGR_F_Create( OGRFeatureDefnH ) CPL_WARN_UNUSED_RESULT;
 void   CPL_DLL OGR_F_Destroy( OGRFeatureH );
 OGRFeatureDefnH CPL_DLL OGR_F_GetDefnRef( OGRFeatureH );
 
@@ -354,6 +364,10 @@ int    CPL_DLL OGR_L_GetFeatureCount( OGRLayerH, int );
 OGRErr CPL_DLL OGR_L_GetExtent( OGRLayerH, OGREnvelope *, int );
 int    CPL_DLL OGR_L_TestCapability( OGRLayerH, const char * );
 OGRErr CPL_DLL OGR_L_CreateField( OGRLayerH, OGRFieldDefnH, int );
+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 );
+OGRErr CPL_DLL OGR_L_AlterFieldDefn( OGRLayerH, int iField, OGRFieldDefnH hNewFieldDefn, int nFlags );
 OGRErr CPL_DLL OGR_L_StartTransaction( OGRLayerH );
 OGRErr CPL_DLL OGR_L_CommitTransaction( OGRLayerH );
 OGRErr CPL_DLL OGR_L_RollbackTransaction( OGRLayerH );
@@ -399,18 +413,18 @@ void   CPL_DLL OGR_DS_SetStyleTable( OGRDataSourceH, OGRStyleTableH );
 /* OGRSFDriver */
 
 const char CPL_DLL *OGR_Dr_GetName( OGRSFDriverH );
-OGRDataSourceH CPL_DLL OGR_Dr_Open( OGRSFDriverH, const char *, int );
+OGRDataSourceH CPL_DLL OGR_Dr_Open( OGRSFDriverH, const char *, int ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL OGR_Dr_TestCapability( OGRSFDriverH, const char * );
 OGRDataSourceH CPL_DLL OGR_Dr_CreateDataSource( OGRSFDriverH, const char *,
-                                                char ** );
+                                                char ** ) CPL_WARN_UNUSED_RESULT;
 OGRDataSourceH CPL_DLL OGR_Dr_CopyDataSource( OGRSFDriverH,  OGRDataSourceH, 
-                                              const char *, char ** );
+                                              const char *, char ** ) CPL_WARN_UNUSED_RESULT;
 OGRErr CPL_DLL OGR_Dr_DeleteDataSource( OGRSFDriverH, const char * );
 
 /* OGRSFDriverRegistrar */
 
-OGRDataSourceH CPL_DLL OGROpen( const char *, int, OGRSFDriverH * );
-OGRDataSourceH CPL_DLL OGROpenShared( const char *, int, OGRSFDriverH * );
+OGRDataSourceH CPL_DLL OGROpen( const char *, int, OGRSFDriverH * ) CPL_WARN_UNUSED_RESULT;
+OGRDataSourceH CPL_DLL OGROpenShared( const char *, int, OGRSFDriverH * ) CPL_WARN_UNUSED_RESULT;
 OGRErr  CPL_DLL OGRReleaseDataSource( OGRDataSourceH );
 void    CPL_DLL OGRRegisterDriver( OGRSFDriverH );
 void    CPL_DLL OGRDeregisterDriver( OGRSFDriverH );
@@ -439,7 +453,7 @@ typedef void *OGRStyleToolH;
 
 /* OGRStyleMgr */
 
-OGRStyleMgrH CPL_DLL OGR_SM_Create(OGRStyleTableH hStyleTable);
+OGRStyleMgrH CPL_DLL OGR_SM_Create(OGRStyleTableH hStyleTable) CPL_WARN_UNUSED_RESULT;
 void    CPL_DLL OGR_SM_Destroy(OGRStyleMgrH hSM);
 
 const char CPL_DLL *OGR_SM_InitFromFeature(OGRStyleMgrH hSM, 
@@ -456,7 +470,7 @@ int     CPL_DLL OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName,
 
 /* OGRStyleTool */
 
-OGRStyleToolH CPL_DLL OGR_ST_Create(OGRSTClassId eClassId);
+OGRStyleToolH CPL_DLL OGR_ST_Create(OGRSTClassId eClassId) CPL_WARN_UNUSED_RESULT;
 void    CPL_DLL OGR_ST_Destroy(OGRStyleToolH hST);
 
 OGRSTClassId CPL_DLL OGR_ST_GetType(OGRStyleToolH hST);
@@ -479,7 +493,7 @@ int CPL_DLL OGR_ST_GetRGBFromString(OGRStyleToolH hST, const char *pszColor,
 
 /* OGRStyleTable */
 
-OGRStyleTableH  CPL_DLL OGR_STBL_Create( void );
+OGRStyleTableH  CPL_DLL OGR_STBL_Create( void ) CPL_WARN_UNUSED_RESULT;
 void    CPL_DLL OGR_STBL_Destroy( OGRStyleTableH hSTBL ); 
 int     CPL_DLL OGR_STBL_SaveStyleTable( OGRStyleTableH hStyleTable,
                                          const char *pszFilename );
diff --git a/ogr/ogr_core.h b/ogr/ogr_core.h
index d98845c..44a39fb 100644
--- a/ogr/ogr_core.h
+++ b/ogr/ogr_core.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_core.h 20885 2010-10-19 00:16:08Z warmerdam $
+ * $Id: ogr_core.h 22448 2011-05-28 18:49:54Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Define some core portability services for cross-platform OGR code.
@@ -47,9 +47,8 @@
 class CPL_DLL OGREnvelope
 {
   public:
-        OGREnvelope()
+        OGREnvelope() : MinX(0.0), MaxX(0.0), MinY(0.0), MaxY(0.0)
         {
-                MinX = MaxX = MinY = MaxY = 0;
         }
     double      MinX;
     double      MaxX;
@@ -137,6 +136,121 @@ typedef struct
 } OGREnvelope;
 #endif
 
+
+/**
+ * Simple container for a bounding region in 3D.
+ */
+
+#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
+class CPL_DLL OGREnvelope3D : public OGREnvelope
+{
+  public:
+        OGREnvelope3D() : OGREnvelope(), MinZ(0.0), MaxZ(0.0)
+        {
+        }
+
+    double      MinZ;
+    double      MaxZ;
+
+    int  IsInit() const { return MinX != 0 || MinY != 0 || MaxX != 0 || MaxY != 0 || MinZ != 0 || MaxZ != 0; }
+    void Merge( OGREnvelope3D const& sOther ) {
+        if( IsInit() )
+        {
+            MinX = MIN(MinX,sOther.MinX);
+            MaxX = MAX(MaxX,sOther.MaxX);
+            MinY = MIN(MinY,sOther.MinY);
+            MaxY = MAX(MaxY,sOther.MaxY);
+            MinZ = MIN(MinZ,sOther.MinZ);
+            MaxZ = MAX(MaxZ,sOther.MaxZ);
+        }
+        else
+        {
+            MinX = sOther.MinX;
+            MaxX = sOther.MaxX;
+            MinY = sOther.MinY;
+            MaxY = sOther.MaxY;
+            MinZ = sOther.MinZ;
+            MaxZ = sOther.MaxZ;
+        }
+    }
+    void Merge( double dfX, double dfY, double dfZ ) {
+        if( IsInit() )
+        {
+            MinX = MIN(MinX,dfX);
+            MaxX = MAX(MaxX,dfX);
+            MinY = MIN(MinY,dfY);
+            MaxY = MAX(MaxY,dfY);
+            MinZ = MIN(MinZ,dfZ);
+            MaxZ = MAX(MaxZ,dfZ);
+        }
+        else
+        {
+            MinX = MaxX = dfX;
+            MinY = MaxY = dfY;
+            MinZ = MaxZ = dfZ;
+        }
+    }
+
+    void Intersect( OGREnvelope3D const& sOther ) {
+        if(Intersects(sOther))
+        {
+            if( IsInit() )
+            {
+                MinX = MAX(MinX,sOther.MinX);
+                MaxX = MIN(MaxX,sOther.MaxX);
+                MinY = MAX(MinY,sOther.MinY);
+                MaxY = MIN(MaxY,sOther.MaxY);
+                MinZ = MAX(MinZ,sOther.MinZ);
+                MaxZ = MIN(MaxZ,sOther.MaxZ);
+            }
+            else
+            {
+                MinX = sOther.MinX;
+                MaxX = sOther.MaxX;
+                MinY = sOther.MinY;
+                MaxY = sOther.MaxY;
+                MinZ = sOther.MinZ;
+                MaxZ = sOther.MaxZ;
+            }
+        }
+        else
+        {
+            MinX = 0;
+            MaxX = 0;
+            MinY = 0;
+            MaxY = 0;
+            MinZ = 0;
+            MaxZ = 0;
+        }
+    }
+
+    int Intersects(OGREnvelope3D const& other) const
+    {
+        return MinX <= other.MaxX && MaxX >= other.MinX &&
+               MinY <= other.MaxY && MaxY >= other.MinY &&
+               MinZ <= other.MaxZ && MaxZ >= other.MinZ;
+    }
+
+    int Contains(OGREnvelope3D const& other) const
+    {
+        return MinX <= other.MinX && MinY <= other.MinY &&
+               MaxX >= other.MaxX && MaxY >= other.MaxY &&
+               MaxZ >= other.MaxZ && MaxZ >= other.MaxZ;
+    }
+};
+#else
+typedef struct
+{
+    double      MinX;
+    double      MaxX;
+    double      MinY;
+    double      MaxY;
+    double      MinZ;
+    double      MaxZ;
+} OGREnvelope3D;
+#endif
+
+
 CPL_C_START
 
 void CPL_DLL *OGRMalloc( size_t );
@@ -220,6 +334,11 @@ typedef enum
 #  define DB2_V72_UNFIX_BYTE_ORDER(x) (x)
 #endif
 
+#define ALTER_NAME_FLAG            0x1
+#define ALTER_TYPE_FLAG            0x2
+#define ALTER_WIDTH_PRECISION_FLAG 0x4
+#define ALTER_ALL_FLAG             (ALTER_NAME_FLAG | ALTER_TYPE_FLAG | ALTER_WIDTH_PRECISION_FLAG)
+
 /************************************************************************/
 /*                  ogr_feature.h related definitions.                  */
 /************************************************************************/
@@ -324,6 +443,9 @@ int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
 #define OLCFastFeatureCount    "FastFeatureCount"
 #define OLCFastGetExtent       "FastGetExtent"
 #define OLCCreateField         "CreateField"
+#define OLCDeleteField         "DeleteField"
+#define OLCReorderFields       "ReorderFields"
+#define OLCAlterFieldDefn      "AlterFieldDefn"
 #define OLCTransactions        "Transactions"
 #define OLCDeleteFeature       "DeleteFeature"
 #define OLCFastSetNextByIndex  "FastSetNextByIndex"
diff --git a/ogr/ogr_feature.h b/ogr/ogr_feature.h
index cef5492..18c4acc 100644
--- a/ogr/ogr_feature.h
+++ b/ogr/ogr_feature.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_feature.h 20885 2010-10-19 00:16:08Z warmerdam $
+ * $Id: ogr_feature.h 22368 2011-05-13 17:59:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Class for representing a whole feature, and layer schemas.
@@ -141,6 +141,8 @@ class CPL_DLL OGRFeatureDefn
     int         GetFieldIndex( const char * );
 
     void        AddFieldDefn( OGRFieldDefn * );
+    OGRErr      DeleteFieldDefn( int iField );
+    OGRErr      ReorderFieldDefns( int* panMap );
 
     OGRwkbGeometryType GetGeomType() { return eGeomType; }
     void        SetGeomType( OGRwkbGeometryType );
diff --git a/ogr/ogr_feature_style.html b/ogr/ogr_feature_style.html
index 3d085e9..bf12786 100644
--- a/ogr/ogr_feature_style.html
+++ b/ogr/ogr_feature_style.html
@@ -10,12 +10,14 @@
 OGR - Feature Style Specification</H1></CENTER>
 
 <CENTER>
-  <H2>DRAFT V0.012 - 2008/07/21</H2>
+  <H2>DRAFT V0.014 - 2011-07-24</H2>
 </CENTER>
 
 <HR WIDTH=50%>
 <H2>REVISION HISTORY</H2>
 <UL>
+<LI><B>Version 0.014 - 2011-07-24 - Even Rouault</B><BR>
+    Mention the escaping of double-quote characters in the text string of a LABEL (ticket #3675)
 <LI><B>Version 0.013 - 2008-07-29 - Daniel Morissette</B><BR>
     Added 'o:' for font point symbol outline color (ticket #2509)
 <LI><B>Version 0.012 - 2008-07-21 - Daniel Morissette</B><BR>
@@ -744,12 +746,15 @@ this list can eventually grow and all parameters are optional:
   <TR>
     <TD ALIGN=CENTER>t</TD>
     <TD><B>Text String</B> - Can be a constant string, or a reference to an
-attribute field's value.
+attribute field's value. If a double-quote character is present in the string,
+it is escaped with a antislash (\) character before it.
 <BR>
       Examples:
 <BR>
       LABEL(f:"Arial, Helvetica", s:12pt, t:"Hello World!")
 <BR>
+      LABEL(f:"Arial, Helvetica", s:12pt, t:"Hello World with escaped double-quote(\") character!")
+<BR>
       LABEL(f:"Arial, Helvetica", s:12pt, t:{text_value})</TD>
   </TR>
 
diff --git a/ogr/ogr_fromepsg.cpp b/ogr/ogr_fromepsg.cpp
index 4cb5dfd..4a83995 100644
--- a/ogr/ogr_fromepsg.cpp
+++ b/ogr/ogr_fromepsg.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_fromepsg.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: ogr_fromepsg.cpp 23396 2011-11-19 19:52:17Z etourigny $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Generate an OGRSpatialReference object based on an EPSG
@@ -32,12 +32,14 @@
 #include "ogr_p.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_fromepsg.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: ogr_fromepsg.cpp 23396 2011-11-19 19:52:17Z etourigny $");
 
 #ifndef PI
 #  define PI 3.14159265358979323846
 #endif
 
+void OGRPrintDouble( char * pszStrBuf, double dfValue );
+
 static const char *papszDatumEquiv[] =
 {
     "Militar_Geographische_Institut",
@@ -269,6 +271,15 @@ int EPSGGetUOMAngleInfo( int nUOMAngleCode,
             dfInDegrees = 180.0 / PI;
             break;
 
+          case 9102:
+          case 9107:
+          case 9108:
+          case 9110:
+          case 9122:
+            pszUOMName = "degree";
+            dfInDegrees = 1.0;
+            break;
+
           case 9103:
             pszUOMName = "arc-minute";
             dfInDegrees = 1 / 60.0;
@@ -750,6 +761,7 @@ OSRGetEllipsoidInfo( int nCode, char ** ppszName,
     return OGRERR_NONE;
 }
 
+#define CoLatConeAxis        1036 /* see #4223 */
 #define NatOriginLat         8801
 #define NatOriginLong        8802
 #define NatOriginScaleFactor 8805
@@ -869,7 +881,9 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
         else /* really we should consider looking up other scaling factors */
         {
             if( nUOM != 9201 )
-                CPLDebug( "OGR", "Non-unity scale factor units!" );
+                CPLDebug( "OGR", 
+                          "Non-unity scale factor units! (UOM=%d, PCS=%d)",
+                          nUOM, nPCS );
             adfProjParms[i] = CPLAtof(pszValue);
         }
 
@@ -1562,8 +1576,12 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
           if( dfCenterLong == 0.0 ) // See ticket #2559
               dfCenterLong = OGR_FP( PolarLongOrigin );
 
+          double dfAzimuth = OGR_FP( CoLatConeAxis ); // See ticket #4223
+          if( dfAzimuth == 0.0 ) 
+              dfAzimuth = OGR_FP( Azimuth );
+
           poSRS->SetKrovak( OGR_FP( ProjCenterLat ), dfCenterLong,
-                            OGR_FP( Azimuth ), 
+                            dfAzimuth, 
                             OGR_FP( PseudoStdParallelLat ),
                             OGR_FP( PseudoStdParallelScaleFactor ),
                             OGR_FP( ProjCenterEasting ), 
@@ -1572,14 +1590,15 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
       break;
 
       case 9820:
+      case 1027: /* used by EPSG:2163, 3408, 3409, 3973 and 3974 */
         poSRS->SetLAEA( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
                         OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
-      case 9821: /* this is the spherical form, and really needs different
+      case 9821: /* DEPREACTED : this is the spherical form, and really needs different
                     equations which give different results but PROJ.4 doesn't
                     seem to support the spherical form. */
-        poSRS->SetLAEA( OGR_FP( SphericalOriginLat ), 
+        poSRS->SetLAEA( OGR_FP( SphericalOriginLat ),
                         OGR_FP( SphericalOriginLong ),
                         OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
@@ -1663,24 +1682,20 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
     if( papszRecord == NULL )
         return OGRERR_UNSUPPORTED_SRS;
 
+
 /* -------------------------------------------------------------------- */
-/*      Set the VERT_CS node with a name.                               */
+/*      Setup the basic VERT_CS.                                        */
 /* -------------------------------------------------------------------- */
-    poSRS->SetNode( "VERT_CS", 
-                    CSLGetField( papszRecord,
-                                 CSVGetFileFieldId(pszFilename,
-                                                   "COORD_REF_SYS_NAME")) );
-
+    poSRS->SetVertCS( 
+        CSLGetField( papszRecord,
+                     CSVGetFileFieldId(pszFilename,
+                                       "COORD_REF_SYS_NAME")),
+        CSLGetField( papszRecord,
+                     CSVGetFileFieldId(pszFilename,
+                                       "DATUM_NAME")) );
 /* -------------------------------------------------------------------- */
 /*      Setup the VERT_DATUM node.                                      */
 /* -------------------------------------------------------------------- */
-    poSRS->SetNode( "VERT_CS|VERT_DATUM", 
-                    CSLGetField( papszRecord,
-                                 CSVGetFileFieldId(pszFilename,
-                                                   "DATUM_NAME")) );
-    poSRS->GetAttrNode( "VERT_CS|VERT_DATUM" )->
-        AddChild( new OGR_SRSNode( "2005" ) );
-
     poSRS->SetAuthority( "VERT_CS|VERT_DATUM", "EPSG",
                          atoi(CSLGetField( papszRecord,
                                            CSVGetFileFieldId(pszFilename,
@@ -1717,23 +1732,13 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
     }
     else
     {
-        poSRS->SetLinearUnits( pszUOMLengthName, dfInMeters );
+        poSRS->SetTargetLinearUnits( "VERT_CS", pszUOMLengthName, dfInMeters );
         poSRS->SetAuthority( "VERT_CS|UNIT", "EPSG", nUOM_CODE );
 
         CPLFree( pszUOMLengthName );
     }
 
 /* -------------------------------------------------------------------- */
-/*      Set axes                                                        */
-/* -------------------------------------------------------------------- */
-    OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
-
-    poAxis->AddChild( new OGR_SRSNode( "Up" ) );
-    poAxis->AddChild( new OGR_SRSNode( "UP" ) );
-
-    poSRS->GetRoot()->AddChild( poAxis );
-    
-/* -------------------------------------------------------------------- */
 /*      Set overall authority code.                                     */
 /* -------------------------------------------------------------------- */
     poSRS->SetAuthority( "VERT_CS", "EPSG", nVertCSCode );
@@ -1834,6 +1839,218 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
 }
 
 /************************************************************************/
+/*                           SetEPSGGeocCS()                            */
+/************************************************************************/
+
+static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Fetch record from the geoccs.csv or override file.              */
+/* -------------------------------------------------------------------- */
+    char        **papszRecord = NULL;
+    char        szSearchKey[24];
+    const char  *pszFilename;
+    
+    sprintf( szSearchKey, "%d", nGCSCode );
+
+// So far no override file needed.    
+//    pszFilename = CSVFilename( "compdcs.override.csv" );
+//    papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
+//                                     szSearchKey, CC_Integer );
+
+    //if( papszRecord == NULL )
+    {
+        pszFilename = CSVFilename( "geoccs.csv" );
+        papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
+                                         szSearchKey, CC_Integer );
+        
+    }
+
+    if( papszRecord == NULL )
+        return OGRERR_UNSUPPORTED_SRS;
+
+/* -------------------------------------------------------------------- */
+/*      Set the GEOCCS node with a name.                                */
+/* -------------------------------------------------------------------- */
+    poSRS->Clear();
+    poSRS->SetGeocCS( CSLGetField( papszRecord,
+                                   CSVGetFileFieldId(pszFilename,
+                                                     "COORD_REF_SYS_NAME")) );
+
+/* -------------------------------------------------------------------- */
+/*      Get datum related information.                                  */
+/* -------------------------------------------------------------------- */
+    int nDatumCode, nEllipsoidCode, nPMCode;
+    char *pszDatumName;
+    
+    nDatumCode = atoi(CSLGetField( papszRecord,
+                                   CSVGetFileFieldId(pszFilename,
+                                                     "DATUM_CODE")));
+    
+    pszDatumName = 
+        CPLStrdup( CSLGetField( papszRecord,
+                                CSVGetFileFieldId(pszFilename,"DATUM_NAME") ) );
+    OGREPSGDatumNameMassage( &pszDatumName );
+
+
+    nEllipsoidCode = atoi(CSLGetField( papszRecord,
+                                   CSVGetFileFieldId(pszFilename,
+                                                     "ELLIPSOID_CODE")));
+    
+    nPMCode = atoi(CSLGetField( papszRecord,
+                                CSVGetFileFieldId(pszFilename,
+                                                  "PRIME_MERIDIAN_CODE")));
+    
+/* -------------------------------------------------------------------- */
+/*      Get prime meridian information.                                 */
+/* -------------------------------------------------------------------- */
+    char *pszPMName = NULL;
+    double dfPMOffset = 0.0;
+
+    if( !EPSGGetPMInfo( nPMCode, &pszPMName, &dfPMOffset ) )
+    {
+        CPLFree( pszDatumName );
+        return OGRERR_UNSUPPORTED_SRS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get the ellipsoid information.                                  */
+/* -------------------------------------------------------------------- */
+    char *pszEllipsoidName = NULL;
+    double dfSemiMajor, dfInvFlattening; 
+
+    if( OSRGetEllipsoidInfo( nEllipsoidCode, &pszEllipsoidName, 
+                             &dfSemiMajor, &dfInvFlattening ) != OGRERR_NONE )
+    {
+        CPLFree( pszDatumName );
+        CPLFree( pszPMName );
+        return OGRERR_UNSUPPORTED_SRS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Setup the spheroid.                                             */
+/* -------------------------------------------------------------------- */
+    char                szValue[128];
+
+    OGR_SRSNode *poSpheroid = new OGR_SRSNode( "SPHEROID" );
+    poSpheroid->AddChild( new OGR_SRSNode( pszEllipsoidName ) );
+
+    OGRPrintDouble( szValue, dfSemiMajor );
+    poSpheroid->AddChild( new OGR_SRSNode(szValue) );
+
+    OGRPrintDouble( szValue, dfInvFlattening );
+    poSpheroid->AddChild( new OGR_SRSNode(szValue) );
+
+    CPLFree( pszEllipsoidName );
+
+/* -------------------------------------------------------------------- */
+/*      Setup the Datum.                                                */
+/* -------------------------------------------------------------------- */
+    OGR_SRSNode *poDatum = new OGR_SRSNode( "DATUM" );
+    poDatum->AddChild( new OGR_SRSNode(pszDatumName) );
+    poDatum->AddChild( poSpheroid );
+
+    poSRS->GetRoot()->AddChild( poDatum );
+
+    CPLFree( pszDatumName );
+
+/* -------------------------------------------------------------------- */
+/*      Setup the prime meridian.                                       */
+/* -------------------------------------------------------------------- */
+    if( dfPMOffset == 0.0 )
+        strcpy( szValue, "0" );
+    else
+        OGRPrintDouble( szValue, dfPMOffset );
+    
+    OGR_SRSNode *poPM = new OGR_SRSNode( "PRIMEM" );
+    poPM->AddChild( new OGR_SRSNode( pszPMName ) );
+    poPM->AddChild( new OGR_SRSNode( szValue ) );
+
+    poSRS->GetRoot()->AddChild( poPM );
+
+    CPLFree( pszPMName );
+
+/* -------------------------------------------------------------------- */
+/*      Should we try to lookup a datum transform?                      */
+/* -------------------------------------------------------------------- */
+#ifdef notdef
+    if( EPSGGetWGS84Transform( nGeogCS, adfBursaTransform ) )
+    {
+        OGR_SRSNode     *poWGS84;
+        char            szValue[100];
+
+        poWGS84 = new OGR_SRSNode( "TOWGS84" );
+
+        for( int iCoeff = 0; iCoeff < 7; iCoeff++ )
+        {
+            sprintf( szValue, "%g", adfBursaTransform[iCoeff] );
+            poWGS84->AddChild( new OGR_SRSNode( szValue ) );
+        }
+
+        poSRS->GetAttrNode( "DATUM" )->AddChild( poWGS84 );
+    }
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Set linear units.                                               */
+/* -------------------------------------------------------------------- */
+    char *pszUOMLengthName = NULL;
+    double dfInMeters = 1.0;
+    int nUOMLength = atoi(CSLGetField( papszRecord,
+                                       CSVGetFileFieldId(pszFilename,
+                                                         "UOM_CODE")));
+    
+    if( !EPSGGetUOMLengthInfo( nUOMLength, &pszUOMLengthName, &dfInMeters ) )
+    {
+        return OGRERR_UNSUPPORTED_SRS;
+    }
+
+    poSRS->SetLinearUnits( pszUOMLengthName, dfInMeters );
+    poSRS->SetAuthority( "GEOCCS|UNIT", "EPSG", nUOMLength );
+
+    CPLFree( pszUOMLengthName );
+
+/* -------------------------------------------------------------------- */
+/*      Set axes                                                        */
+/* -------------------------------------------------------------------- */
+    OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
+
+    poAxis->AddChild( new OGR_SRSNode( "Geocentric X" ) );
+    poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(OAO_Other) ) );
+
+    poSRS->GetRoot()->AddChild( poAxis );
+    
+    poAxis = new OGR_SRSNode( "AXIS" );
+
+    poAxis->AddChild( new OGR_SRSNode( "Geocentric Y" ) );
+    poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(OAO_Other) ) );
+
+    poSRS->GetRoot()->AddChild( poAxis );
+    
+    poAxis = new OGR_SRSNode( "AXIS" );
+
+    poAxis->AddChild( new OGR_SRSNode( "Geocentric Z" ) );
+    poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(OAO_North) ) );
+
+    poSRS->GetRoot()->AddChild( poAxis );
+
+/* -------------------------------------------------------------------- */
+/*      Set the authority codes.                                        */
+/* -------------------------------------------------------------------- */
+    poSRS->SetAuthority( "DATUM", "EPSG", nDatumCode );
+    poSRS->SetAuthority( "SPHEROID", "EPSG", nEllipsoidCode );
+    poSRS->SetAuthority( "PRIMEM", "EPSG", nPMCode );
+
+//    if( nUOMAngle > 0 )
+//        poSRS->SetAuthority( "GEOGCS|UNIT", "EPSG", nUOMAngle );
+
+    poSRS->SetAuthority( "GEOCCS", "EPSG", nGCSCode );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                           importFromEPSG()                           */
 /************************************************************************/
 
@@ -1928,6 +2145,7 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 
 {
     OGRErr  eErr;
+    CPLLocaleC  oLocaleForcer;
 
     bNormInfoSet = FALSE;
 
@@ -1965,6 +2183,8 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
         eErr = SetEPSGVertCS( this, nCode );
     if( eErr == OGRERR_UNSUPPORTED_SRS )
         eErr = SetEPSGCompdCS( this, nCode );
+    if( eErr == OGRERR_UNSUPPORTED_SRS )
+        eErr = SetEPSGGeocCS( this, nCode );
 
 /* -------------------------------------------------------------------- */
 /*      If we get it as an unsupported code, try looking it up in       */
@@ -2014,8 +2234,6 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
             SetAuthority( "PROJCS", "EPSG", nCode );
         else if( IsGeographic() )
             SetAuthority( "GEOGCS", "EPSG", nCode );
-
-        eErr = FixupOrdering();
     }
 
 /* -------------------------------------------------------------------- */
@@ -2028,6 +2246,16 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
                   nCode );
     }
 
+/* -------------------------------------------------------------------- */
+/*      To the extent possible, we want to return the results in as     */
+/*      close to standard OGC format as possible, so we fixup the       */
+/*      ordering.                                                       */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE )
+    {    
+        eErr = FixupOrdering();
+    }
+
     return eErr;
 }
 
diff --git a/ogr/ogr_geometry.h b/ogr/ogr_geometry.h
index b7f8c52..05b407c 100644
--- a/ogr/ogr_geometry.h
+++ b/ogr/ogr_geometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geometry.h 21023 2010-10-30 19:48:23Z rouault $
+ * $Id: ogr_geometry.h 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating simple features that is not specific
@@ -96,6 +96,7 @@ class CPL_DLL OGRGeometry
     virtual void        empty() = 0;
     virtual OGRGeometry *clone() const = 0;
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const = 0;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const = 0;
 
     // IWks Interface
     virtual int WkbSize() const = 0;
@@ -147,6 +148,9 @@ class CPL_DLL OGRGeometry
     virtual OGRGeometry *SymDifference( const OGRGeometry * ) const;
     virtual OGRErr       Centroid( OGRPoint * poPoint ) const;
     virtual OGRGeometry *Simplify(double dTolerance) const;
+    OGRGeometry *SimplifyPreserveTopology(double dTolerance) const;
+
+    virtual OGRGeometry *Polygonize() const;
 
     // backward compatibility to non-standard method names. 
     OGRBoolean  Intersect( OGRGeometry * ) const;
@@ -194,6 +198,7 @@ class CPL_DLL OGRPoint : public OGRGeometry
     virtual OGRGeometry *clone() const;
     virtual void empty();
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
     virtual OGRBoolean  IsEmpty() const;
 
     // IPoint
@@ -275,6 +280,7 @@ class CPL_DLL OGRLineString : public OGRCurve
     virtual OGRGeometry *clone() const;
     virtual void empty();
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
     virtual OGRBoolean  IsEmpty() const;
 
     // ICurve methods
@@ -307,6 +313,9 @@ class CPL_DLL OGRLineString : public OGRCurve
     void        addPoint( double, double, double );
 
     void        getPoints( OGRRawPoint *, double * = NULL ) const;
+    void        getPoints( void* pabyX, int nXStride,
+                           void* pabyY, int nYStride,
+                           void* pabyZ = NULL, int nZStride = 0 ) const;
 
     void        addSubLineString( const OGRLineString *, 
                                   int nStartVertex = 0, int nEndVertex = -1 );
@@ -439,6 +448,7 @@ class CPL_DLL OGRPolygon : public OGRSurface
     // IGeometry
     virtual int getDimension() const;
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
 
     // ISpatialRelation
     virtual OGRBoolean  Equals( OGRGeometry * ) const;
@@ -478,6 +488,9 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry
     int         nGeomCount;
     OGRGeometry **papoGeoms;
 
+    OGRErr      importFromWkbInternal( unsigned char * pabyData, int nSize, int nRecLevel );
+    OGRErr      importFromWktInternal( char **ppszInput, int nRecLevel );
+
   public:
                 OGRGeometryCollection();
     virtual     ~OGRGeometryCollection();
@@ -505,6 +518,7 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry
     // IGeometry methods
     virtual int getDimension() const;
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
 
     // IGeometryCollection
     int         getNumGeometries() const;
@@ -614,6 +628,12 @@ class CPL_DLL OGRMultiLineString : public OGRGeometryCollection
 
 class CPL_DLL OGRGeometryFactory
 {
+    static OGRErr createFromFgfInternal( unsigned char *pabyData,
+                                         OGRSpatialReference * poSR,
+                                         OGRGeometry **ppoReturn,
+                                         int nBytes,
+                                         int *pnBytesConsumed,
+                                         int nRecLevel );
   public:
     static OGRErr createFromWkb( unsigned char *, OGRSpatialReference *,
                                  OGRGeometry **, int = -1 );
diff --git a/ogr/ogr_opt.cpp b/ogr/ogr_opt.cpp
index cf042b0..526d1df 100644
--- a/ogr/ogr_opt.cpp
+++ b/ogr/ogr_opt.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_opt.cpp 19782 2010-05-31 13:03:17Z dron $
+ * $Id: ogr_opt.cpp 22332 2011-05-08 15:32:37Z rouault $
  *
  * Project:  OpenGIS Simple Features
  * Purpose:  Functions for getting list of projection types, and their parms.
@@ -30,7 +30,7 @@
 #include "ogr_srs_api.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogr_opt.cpp 19782 2010-05-31 13:03:17Z dron $");
+CPL_CVSID("$Id: ogr_opt.cpp 22332 2011-05-08 15:32:37Z rouault $");
 
 static const char *papszParameterDefinitions[] = {
     SRS_PP_CENTRAL_MERIDIAN,    "Central Meridian",     "Long",  "0.0",
@@ -210,6 +210,10 @@ static const char *papszProjectionDefinitions[] = {
     SRS_PP_FALSE_NORTHING,
 
     "*",
+    SRS_PT_IGH,
+    "Interrupted Goode Homolosine",
+
+    "*",
     SRS_PT_GEOSTATIONARY_SATELLITE,
     "Geostationary Satellite",
     SRS_PP_CENTRAL_MERIDIAN, 
@@ -540,6 +544,8 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
                                           papszProjectionDefinitions[i] );
                 i++;
             }
+            if( papszList == NULL) /* IGH has no parameter, so return an empty list instead of NULL */
+                papszList = (char**) CPLCalloc(1, sizeof(char*));
             return papszList;
         }
     }
diff --git a/ogr/ogr_p.h b/ogr/ogr_p.h
index 88196cb..4734327 100644
--- a/ogr/ogr_p.h
+++ b/ogr/ogr_p.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_p.h 20616 2010-09-15 01:20:36Z warmerdam $
+ * $Id: ogr_p.h 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Some private helper functions and stuff for OGR implementation.
@@ -37,8 +37,10 @@
 
 #include "cpl_string.h"
 #include "cpl_conv.h"
+#include "cpl_minixml.h"
 
 #include "ogr_core.h"
+#include "ogr_geometry.h"
 
 #ifdef CPL_MSB 
 #  define OGR_SWAP(x)   (x == wkbNDR)
@@ -117,4 +119,15 @@ OGRErr CPL_DLL OSRGetEllipsoidInfo( int, char **, double *, double *);
 /* Fast atof function */
 double OGRFastAtof(const char* pszStr);
 
+OGRErr CPL_DLL OGRCheckPermutation(int* panPermutation, int nSize);
+
+/* GML related */
+
+OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
+                                      int bGetSecondaryGeometryOption,
+                                      int nRecLevel = 0,
+                                      int bIgnoreGSG = FALSE,
+                                      int bOrientation = TRUE,
+                                      int bFaceHoleNegative = FALSE );
+
 #endif /* ndef OGR_P_H_INCLUDED */
diff --git a/ogr/ogr_spatialref.h b/ogr/ogr_spatialref.h
index c875ae9..a104915 100644
--- a/ogr/ogr_spatialref.h
+++ b/ogr/ogr_spatialref.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_spatialref.h 21467 2011-01-12 20:19:38Z warmerdam $
+ * $Id: ogr_spatialref.h 22952 2011-08-19 21:08:31Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating spatial reference systems in a
@@ -65,7 +65,6 @@ class CPL_DLL OGR_SRSNode
 
     int         nChildren;
 
-    void        ClearChildren();
     int         NeedsQuoting() const;
     
   public:
@@ -85,6 +84,7 @@ class CPL_DLL OGR_SRSNode
     void        AddChild( OGR_SRSNode * );
     int         FindChild( const char * ) const;
     void        DestroyChild( int );
+    void        ClearChildren();
     void        StripNodes( const char * );
 
     const char  *GetValue() const { return pszValue; }
@@ -144,6 +144,9 @@ class CPL_DLL OGRSpatialReference
     static int  IsAliasFor( const char *, const char * );
     void        GetNormInfo() const;
 
+    OGRErr      importFromURNPart(const char* pszAuthority,
+                                  const char* pszCode,
+                                  const char* pszURN);
   public:
                 OGRSpatialReference(const OGRSpatialReference&);
                 OGRSpatialReference(const char * = NULL);
@@ -227,7 +230,11 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetLinearUnitsAndUpdateParameters( const char *pszName, 
                                                    double dfInMeters );
     OGRErr      SetLinearUnits( const char *pszName, double dfInMeters );
+    OGRErr      SetTargetLinearUnits( const char *pszTargetKey,
+                                      const char *pszName, double dfInMeters );
     double      GetLinearUnits( char ** = NULL ) const;
+    double      GetTargetLinearUnits( const char *pszTargetKey,
+                                      char ** ppszRetName = NULL ) const;
 
     OGRErr      SetAngularUnits( const char *pszName, double dfInRadians );
     double      GetAngularUnits( char ** = NULL ) const;
@@ -236,8 +243,10 @@ class CPL_DLL OGRSpatialReference
 
     int         IsGeographic() const;
     int         IsProjected() const;
+    int         IsGeocentric() const;
     int         IsLocal() const;
     int         IsVertical() const;
+    int         IsCompound() const;
     int         IsSameGeogCS( const OGRSpatialReference * ) const;
     int         IsSameVertCS( const OGRSpatialReference * ) const;
     int         IsSame( const OGRSpatialReference * ) const;
@@ -246,6 +255,7 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetLocalCS( const char * );
     OGRErr      SetProjCS( const char * );
     OGRErr      SetProjection( const char * );
+    OGRErr      SetGeocCS( const char * pszGeocName );
     OGRErr      SetGeogCS( const char * pszGeogName,
                            const char * pszDatumName,
                            const char * pszEllipsoidName,
@@ -256,6 +266,12 @@ class CPL_DLL OGRSpatialReference
                            double dfConvertToRadians = 0.0 );
     OGRErr      SetWellKnownGeogCS( const char * );
     OGRErr      CopyGeogCSFrom( const OGRSpatialReference * poSrcSRS );
+    OGRErr      SetVertCS( const char *pszVertCSName,
+                           const char *pszVertDatumName, 
+                           int nVertDatumClass = 2005 );
+    OGRErr      SetCompoundCS( const char *pszName, 
+                               const OGRSpatialReference *poHorizSRS,
+                               const OGRSpatialReference *poVertSRS );
 
     OGRErr      SetFromUserInput( const char * );
 
@@ -349,6 +365,9 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetGH( double dfCentralMeridian, 
                        double dfFalseEasting, double dfFalseNorthing );
 
+    /** Interrupted Goode Homolosine */
+    OGRErr      SetIGH();
+
     /** Gall Stereograpic */
     OGRErr      SetGS( double dfCentralMeridian,
                        double dfFalseEasting, double dfFalseNorthing );
@@ -502,6 +521,13 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetStatePlane( int nZone, int bNAD83 = TRUE,
                                const char *pszOverrideUnitName = NULL,
                                double dfOverrideUnit = 0.0 );
+
+    OGRErr      ImportFromESRIStatePlaneWKT( 
+        int nCode, const char* pszDatumName, const char* pszUnitsName, 
+        int nPCSCode, const char* pszCSName = 0 );
+    OGRErr      ImportFromESRIWisconsinWKT( 
+        const char* pszPrjName, double dfCentralMeridian, double dfLatOfOrigin, 
+        const char* pszUnitsName, const char* pszCSName = 0 );
 };
 
 /************************************************************************/
diff --git a/ogr/ogr_sql.dox b/ogr/ogr_sql.dox
index 8d0518e..f01a08f 100644
--- a/ogr/ogr_sql.dox
+++ b/ogr/ogr_sql.dox
@@ -93,16 +93,25 @@ SELECT MIN(prop_value), MAX(prop_value), AVG(prop_value), SUM(prop_value),
        COUNT(prop_value) FROM polylayer WHERE prov_name = "Ontario"
 \endcode
 
-As a special case, the COUNT() operator can be given a "*" argument instead
-of a field name which is a short form for count all the records though it
-would get the same result as giving it any of the column names.   It is
-also possible to apply the COUNT() operator to a DISTINCT SELECT to get
+It is also possible to apply the COUNT() operator to a DISTINCT SELECT to get
 a count of distinct values, for instance:
 
 \code
 SELECT COUNT(DISTINCT areacode) FROM polylayer
 \endcode
 
+Note: prior to OGR 1.9.0, null values were counted in COUNT(column_name) or
+COUNT(DISTINCT column_name), which was not conformant with the SQL standard. Since
+OGR 1.9.0, only non-null values are counted.
+
+As a special case, the COUNT() operator can be given a "*" argument instead
+of a field name which is a short form for count all the records.
+
+\code
+SELECT COUNT(*) FROM polylayer
+\endcode
+
+
 Field names can also be prefixed by a table name though this is only 
 really meaningful when performing joins.  It is further demonstrated in 
 the JOIN section.
@@ -121,6 +130,25 @@ or
 SELECT CONCAT(owner_first_name,' ',owner_last_name) from properties
 \endcode
 
+\subsubsection ogr_sql_functions Functions
+
+Starting with OGR 1.8.2, the SUBSTR function can be used to extract a substring from a string.
+Its syntax is the following one : SUBSTR(string_expr, start_offset [, length]). It extracts a substring of string_expr,
+starting at offset start_offset (1 being the first character of string_expr, 2 the second one, etc...).
+If start_offset is a negative value, the substring is extracted from the end of the string (-1 is the
+last character of the string, -2 the character before the last character, ...).
+If length is specified, up to length characters are extracted from the string. Otherwise the
+remainder of the string is extracted.
+
+Note: for the time being, the character as considered to be equivalent to bytes, which may not be
+appropriate for multi-byte encodings like UTF-8.
+
+\code
+SELECT SUBSTR('abcdef',1,2) FROM xxx   --> 'ab'
+SELECT SUBSTR('abcdef',4)   FROM xxx   --> 'def'
+SELECT SUBSTR('abcdef',-2)  FROM xxx   --> 'ef'
+\endcode
+
 \subsubsection ogr_sql_fname_alias Using the field name alias
 
 OGR SQL supports renaming the fields following the SQL92 specification by
@@ -202,7 +230,9 @@ case insensitive, but the <b><</b>, <b>></b>, <b><=</b> and <b>>=</b
 
 The value argument to the <b>LIKE</b> operator is a pattern against which
 the value string is matched.  In this pattern percent (%) matches any number of
-characters, and underscore ( _ ) matches any one character.
+characters, and underscore ( _ ) matches any one character. An optional ESCAPE escape_char
+clause can be added so that the percent or underscore characters can be searched
+as regular characters, by being preceded with the escape_char.
 
 \code
     String             Pattern       Matches?
@@ -500,6 +530,39 @@ DROP INDEX ON nation USING nation_id
 DROP INDEX ON nation
 \endcode
 
+\section ogr_sql_alter_table ALTER TABLE
+
+(OGR >= 1.9.0)
+
+The following OGR SQL ALTER TABLE commands can be used.
+
+<ol>
+<li>"ALTER TABLE tablename ADD [COLUMN] columnname columntype" to add a new field. Supported if the layer declares the OLCCreateField capability.
+<li>"ALTER TABLE tablename RENAME [COLUMN] oldcolumnname TO newcolumnname" to rename an existing field. Supported if the layer declares the OLCAlterFieldDefn capability.
+<li>"ALTER TABLE tablename ALTER [COLUMN] columnname TYPE columntype" to change the type of an existing field. Supported if the layer declares the OLCAlterFieldDefn capability.
+<li>"ALTER TABLE tablename DROP [COLUMN] columnname" to delete an existing field. Supported if the layer declares the OLCDeleteField capability.
+</ol>
+
+The columntype value follows the syntax of the types supported by the CAST operator descrived above.
+
+\code
+ALTER TABLE nation ADD COLUMN myfield integer
+ALTER TABLE nation RENAME COLUMN myfield TO myfield2
+ALTER TABLE nation ALTER COLUMN myfield2 TYPE character(15)
+ALTER TABLE nation DROP COLUMN myfield2
+\endcode
+
+\section ogr_sql_drop_table DROP TABLE
+
+(OGR >= 1.9.0)
+
+The OGR SQL DROP TABLE command can be used to delete a table. This is only
+supported on datasources that declare the ODsCDeleteLayer capability.
+
+\code
+DROP TABLE nation
+\endcode
+
 \section ogr_sql_exec_sql ExecuteSQL()
 
 SQL is executed against an OGRDataSource, not against a specific layer.  The
@@ -532,8 +595,9 @@ All OGR drivers for database systems: <a href="/ogr/drv_mysql.html">MySQL</a>,
 PostgreSQL and PostGIS (<a href="/ogr/drv_pg.html">PG</a>), 
 Oracle (<a href="/ogr/drv_oci.html">OCI</a>), 
 <a href="/ogr/drv_sqlite.html">SQLite</a>, 
-<a href="/ogr/drv_odbc.html">ODBC</a> 
-and ESRI Personal Geodatabase (<a href="/ogr/drv_pgeo.html">PGeo</a>) 
+<a href="/ogr/drv_odbc.html">ODBC</a>,
+ESRI Personal Geodatabase (<a href="/ogr/drv_pgeo.html">PGeo</a>) and
+MS SQL Spatial (<a href="/ogr/drv_mssqlspatial.html">MSSQLSpatial</a>),
 override the OGRDataSource::ExecuteSQL() function with dedicated implementation 
 and, by default, pass the SQL statements directly to the underlying RDBMS. 
 In these cases the SQL syntax varies in some particulars from OGR SQL.
diff --git a/ogr/ogr_srs_api.h b/ogr/ogr_srs_api.h
index 40f6336..74977e3 100644
--- a/ogr/ogr_srs_api.h
+++ b/ogr/ogr_srs_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_api.h 21005 2010-10-29 14:50:50Z dron $
+ * $Id: ogr_srs_api.h 22514 2011-06-08 12:57:26Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API and constant declarations for OGR Spatial References.
@@ -115,6 +115,7 @@ typedef enum {
 #define SRS_PT_GEOSTATIONARY_SATELLITE                                  \
                                 "Geostationary_Satellite"
 #define SRS_PT_GOODE_HOMOLOSINE "Goode_Homolosine"
+#define SRS_PT_IGH              "Interrupted_Goode_Homolosine"
 #define SRS_PT_GNOMONIC         "Gnomonic"
 #define SRS_PT_HOTINE_OBLIQUE_MERCATOR                                  \
                                 "Hotine_Oblique_Mercator"
@@ -223,6 +224,8 @@ typedef enum {
 #define SRS_UL_CHAIN_CONV                   "20.116684023368047"
 #define SRS_UL_ROD              "Rod"           /* based on US Foot */
 #define SRS_UL_ROD_CONV                     "5.02921005842012"
+#define SRS_UL_LINK_Clarke      "Link_Clarke"          
+#define SRS_UL_LINK_Clarke_CONV              "0.2011661949"
 
 #define SRS_UA_DEGREE           "degree"
 #define SRS_UA_DEGREE_CONV                  "0.0174532925199433"
@@ -317,22 +320,27 @@ const char CPL_DLL * CPL_STDCALL OSRGetAttrValue( OGRSpatialReferenceH hSRS,
 OGRErr CPL_DLL OSRSetAngularUnits( OGRSpatialReferenceH, const char *, double );
 double CPL_DLL OSRGetAngularUnits( OGRSpatialReferenceH, char ** );
 OGRErr CPL_DLL OSRSetLinearUnits( OGRSpatialReferenceH, const char *, double );
+OGRErr CPL_DLL OSRSetTargetLinearUnits( OGRSpatialReferenceH, const char *, const char *, double );
 OGRErr CPL_DLL OSRSetLinearUnitsAndUpdateParameters( 
     OGRSpatialReferenceH, const char *, double );
 double CPL_DLL OSRGetLinearUnits( OGRSpatialReferenceH, char ** );
+double CPL_DLL OSRGetTargetLinearUnits( OGRSpatialReferenceH, const char *, char ** );
 
 double CPL_DLL OSRGetPrimeMeridian( OGRSpatialReferenceH, char ** );
 
 int CPL_DLL OSRIsGeographic( OGRSpatialReferenceH );
 int CPL_DLL OSRIsLocal( OGRSpatialReferenceH );
 int CPL_DLL OSRIsProjected( OGRSpatialReferenceH );
+int CPL_DLL OSRIsCompound( OGRSpatialReferenceH );
+int CPL_DLL OSRIsGeocentric( OGRSpatialReferenceH );
 int CPL_DLL OSRIsVertical( OGRSpatialReferenceH );
 int CPL_DLL OSRIsSameGeogCS( OGRSpatialReferenceH, OGRSpatialReferenceH );
-int CPL_DLL OSRIsVertCS( OGRSpatialReferenceH, OGRSpatialReferenceH );
+int CPL_DLL OSRIsSameVertCS( OGRSpatialReferenceH, OGRSpatialReferenceH );
 int CPL_DLL OSRIsSame( OGRSpatialReferenceH, OGRSpatialReferenceH );
 
 OGRErr CPL_DLL OSRSetLocalCS( OGRSpatialReferenceH hSRS, const char *pszName );
 OGRErr CPL_DLL OSRSetProjCS( OGRSpatialReferenceH hSRS, const char * pszName );
+OGRErr CPL_DLL OSRSetGeocCS( OGRSpatialReferenceH hSRS, const char * pszName );
 OGRErr CPL_DLL OSRSetWellKnownGeogCS( OGRSpatialReferenceH hSRS,
                                       const char * pszName );
 OGRErr CPL_DLL CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS, 
@@ -345,6 +353,10 @@ OGRErr CPL_DLL OSRSetTOWGS84( OGRSpatialReferenceH hSRS,
 OGRErr CPL_DLL OSRGetTOWGS84( OGRSpatialReferenceH hSRS, double *, int );
                         
 
+OGRErr CPL_DLL OSRSetCompoundCS( OGRSpatialReferenceH hSRS,
+                                 const char *pszName,
+                                 OGRSpatialReferenceH hHorizSRS,
+                                 OGRSpatialReferenceH hVertSRS );
 OGRErr CPL_DLL OSRSetGeogCS( OGRSpatialReferenceH hSRS,
                       const char * pszGeogName,
                       const char * pszDatumName,
@@ -355,6 +367,11 @@ OGRErr CPL_DLL OSRSetGeogCS( OGRSpatialReferenceH hSRS,
                       const char * pszUnits /* = NULL */,
                       double dfConvertToRadians /* = 0.0 */ );
 
+OGRErr CPL_DLL OSRSetVertCS( OGRSpatialReferenceH hSRS,
+                      const char * pszVertCSName,
+                      const char * pszVertDatumName,
+                      int nVertDatumType );
+
 double CPL_DLL OSRGetSemiMajor( OGRSpatialReferenceH, OGRErr * /* = NULL */ );
 double CPL_DLL OSRGetSemiMinor( OGRSpatialReferenceH, OGRErr * /* = NULL */ );
 double CPL_DLL OSRGetInvFlattening( OGRSpatialReferenceH, OGRErr * /*=NULL*/);
@@ -457,6 +474,9 @@ OGRErr CPL_DLL OSRSetGS( OGRSpatialReferenceH hSRS, double dfCentralMeridian,
 /** Goode Homolosine */
 OGRErr CPL_DLL OSRSetGH( OGRSpatialReferenceH hSRS, double dfCentralMeridian,
                          double dfFalseEasting, double dfFalseNorthing );
+
+/** Interrupted Goode Homolosine */
+OGRErr CPL_DLL OSRSetIGH( OGRSpatialReferenceH hSRS );
     
 /** GEOS - Geostationary Satellite View */
 OGRErr CPL_DLL OSRSetGEOS( OGRSpatialReferenceH hSRS, 
diff --git a/ogr/ogr_srs_erm.cpp b/ogr/ogr_srs_erm.cpp
index 801f9c1..14028b9 100644
--- a/ogr/ogr_srs_erm.cpp
+++ b/ogr/ogr_srs_erm.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_erm.cpp 21667 2011-02-09 22:55:10Z warmerdam $
+ * $Id: ogr_srs_erm.cpp 22996 2011-08-28 09:27:35Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implement ERMapper projection conversions.
@@ -30,7 +30,7 @@
 #include "ogr_spatialref.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogr_srs_erm.cpp 21667 2011-02-09 22:55:10Z warmerdam $");
+CPL_CVSID("$Id: ogr_srs_erm.cpp 22996 2011-08-28 09:27:35Z rouault $");
 
 /************************************************************************/
 /*                         OSRImportFromERM()                           */
@@ -219,45 +219,48 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
 /* -------------------------------------------------------------------- */
     if( EQUAL(pszDatum,"RAW") )
     {
-        nEPSGCode = GetEPSGGeogCS();
+        int nEPSGGCSCode = GetEPSGGeogCS();
 
-        if( nEPSGCode == 4326 )
+        if( nEPSGGCSCode == 4326 )
             strcpy( pszDatum, "WGS84" );
 
-        else if( nEPSGCode == 4322 )
+        else if( nEPSGGCSCode == 4322 )
             strcpy( pszDatum, "WGS72DOD" );
         
-        else if( nEPSGCode == 4267 )
+        else if( nEPSGGCSCode == 4267 )
             strcpy( pszDatum, "NAD27" );
         
-        else if( nEPSGCode == 4269 )
+        else if( nEPSGGCSCode == 4269 )
             strcpy( pszDatum, "NAD83" );
 
-        else if( nEPSGCode == 4277 )
+        else if( nEPSGGCSCode == 4277 )
             strcpy( pszDatum, "OSGB36" );
 
-        else if( nEPSGCode == 4278 )
+        else if( nEPSGGCSCode == 4278 )
             strcpy( pszDatum, "OSGB78" );
 
-        else if( nEPSGCode == 4201 )
+        else if( nEPSGGCSCode == 4201 )
             strcpy( pszDatum, "ADINDAN" );
 
-        else if( nEPSGCode == 4202 )
+        else if( nEPSGGCSCode == 4202 )
             strcpy( pszDatum, "AGD66" );
 
-        else if( nEPSGCode == 4203 )
+        else if( nEPSGGCSCode == 4203 )
             strcpy( pszDatum, "AGD84" );
 
-        else if( nEPSGCode == 4209 )
+        else if( nEPSGGCSCode == 4209 )
             strcpy( pszDatum, "ARC1950" );
 
-        else if( nEPSGCode == 4210 )
+        else if( nEPSGGCSCode == 4210 )
             strcpy( pszDatum, "ARC1960" );
 
-        else if( nEPSGCode == 4275 )
+        else if( nEPSGGCSCode == 4275 )
             strcpy( pszDatum, "NTF" );
 
-        else if( nEPSGCode == 4284 )
+        else if( nEPSGGCSCode == 4283 )
+            strcpy( pszDatum, "GDA94" );
+
+        else if( nEPSGGCSCode == 4284 )
             strcpy( pszDatum, "PULKOVO" );
     }
 
@@ -284,10 +287,17 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     nZone = GetUTMZone( &bNorth );
     if( nZone > 0 )
     {
-        if( bNorth )
-            sprintf( pszProj, "NUTM%02d", nZone );
+        if( EQUAL(pszDatum,"GDA94") && !bNorth && nZone >= 48 && nZone <= 58)
+        {
+            sprintf( pszProj, "MGA%02d", nZone );
+        }
         else
-            sprintf( pszProj, "SUTM%02d", nZone );
+        {
+            if( bNorth )
+                sprintf( pszProj, "NUTM%02d", nZone );
+            else
+                sprintf( pszProj, "SUTM%02d", nZone );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -307,6 +317,16 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     }
 
 /* -------------------------------------------------------------------- */
+/*      If we have not translated it yet, but we have an EPSG code      */
+/*      then use EPSG:n notation.                                       */
+/* -------------------------------------------------------------------- */
+    if( (EQUAL(pszDatum,"RAW") || EQUAL(pszProj,"RAW")) && nEPSGCode != 0 )
+    {
+        sprintf( pszProj, "EPSG:%d", nEPSGCode );
+        sprintf( pszDatum, "EPSG:%d", nEPSGCode );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Handle the units.                                               */
 /* -------------------------------------------------------------------- */
     double dfUnits = GetLinearUnits();
diff --git a/ogr/ogr_srs_esri.cpp b/ogr/ogr_srs_esri.cpp
index 59db86f..e171204 100644
--- a/ogr/ogr_srs_esri.cpp
+++ b/ogr/ogr_srs_esri.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_esri.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: ogr_srs_esri.cpp 23636 2011-12-22 20:18:16Z etourigny $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from ESRI .prj definitions.
@@ -33,7 +33,7 @@
 
 #include "ogr_srs_esri_names.h"
 
-CPL_CVSID("$Id: ogr_srs_esri.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: ogr_srs_esri.cpp 23636 2011-12-22 20:18:16Z etourigny $");
 
 void  SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName );
 int   RemapImgWGSProjcsName(OGRSpatialReference* pOgr, const char* pszProjCSName, 
@@ -55,6 +55,8 @@ int   AddParamBasedOnPrjName( OGRSpatialReference* pOgr,
                              const char* pszProjectionName, char **mappingTable);
 int   RemapGeogCSName(OGRSpatialReference* pOgr, const char *pszGeogCSName);
 
+static int   FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code );
+
 static const char *apszProjMapping[] = {
     "Albers", SRS_PT_ALBERS_CONIC_EQUAL_AREA,
     "Cassini", SRS_PT_CASSINI_SOLDNER,
@@ -91,6 +93,11 @@ static const char *apszPolarStereographicMapping[] = {
     SRS_PP_STANDARD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN,
     NULL, NULL };
 
+static const char *apszOrthographicMapping[] = {
+    "Longitude_Of_Center", SRS_PP_CENTRAL_MERIDIAN,
+    "Latitude_Of_Center", SRS_PP_LATITUDE_OF_ORIGIN,
+    NULL, NULL };
+
 static char **papszDatumMapping = NULL;
  
 static const char *apszDefaultDatumMapping[] = {
@@ -98,6 +105,13 @@ static const char *apszDefaultDatumMapping[] = {
     "6269", "North_American_1983", SRS_DN_NAD83,
     NULL, NULL, NULL }; 
 
+static const char *apszSpheroidMapping[] = {
+    "WGS_84", "WGS_1984",
+    "WGS_72", "WGS_1972",
+    "GRS_1967_Modified", "GRS_1967_Truncated",
+    "Krassowsky_1940", "Krasovsky_1940",
+    NULL, NULL }; 
+ 
 static const char *apszUnitMapping[] = {
     "Meter", "meter",
     "Meter", "metre",
@@ -259,24 +273,25 @@ static const int anUsgsEsriZones[] =
  5400,    0
 };
 
-void OGREPSGDatumNameMassage( char ** ppszDatum );
+/* -------------------------------------------------------------------- */
+/*      Datum Mapping functions and definitions                         */
+/* -------------------------------------------------------------------- */
+/* TODO adapt existing code and test */
+#define DM_IDX_EPSG_CODE            0
+#define DM_IDX_ESRI_NAME            1
+#define DM_IDX_EPSG_NAME            2
+#define DM_ELT_SIZE                 3
 
-/************************************************************************/
-/*                           RemapSpheroidName()                        */
-/*                                                                      */
-/*      Convert Spheroid name to ESRI style name                        */
-/************************************************************************/
+#define DM_GET_EPSG_CODE(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_CODE]
+#define DM_GET_ESRI_NAME(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_ESRI_NAME]
+#define DM_GET_EPSG_NAME(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_NAME]
 
-static const char* RemapSpheroidName(const char* pszName)
-{
-  if (strcmp(pszName, "WGS 84") == 0)
-    return "WGS 1984";
+char *DMGetEPSGCode(int i) { return DM_GET_EPSG_CODE(papszDatumMapping, i); }
+char *DMGetESRIName(int i) { return DM_GET_ESRI_NAME(papszDatumMapping, i); }
+char *DMGetEPSGName(int i) { return DM_GET_EPSG_NAME(papszDatumMapping, i); }
 
-  if (strcmp(pszName, "WGS 72") == 0)
-    return "WGS 1972";
 
-  return pszName;
-}
+void OGREPSGDatumNameMassage( char ** ppszDatum );
 
 /************************************************************************/
 /*                           ESRIToUSGSZone()                           */
@@ -406,6 +421,7 @@ static void InitDatumMappingTable()
                   "Failed to find required field in gdal_datum.csv in InitDatumMappingTable(), using default table setup." );
         
         papszDatumMapping = (char **)apszDefaultDatumMapping;
+        VSIFClose( fp );
         return;
     }
     
@@ -520,9 +536,15 @@ static double OSR_GDV( char **papszNV, const char * pszField,
             papszTokens = CSLTokenizeString(papszNV[iLine]);
             if( CSLCount(papszTokens) == 3 )
             {
+                /* http://agdcftp1.wr.usgs.gov/pub/projects/lcc/akcan_lcc/akcan.tar.gz contains */
+                /* weird values for the second. Ignore it and the result looks correct */
+                double dfSecond = atof(papszTokens[2]);
+                if (dfSecond < 0.0 || dfSecond >= 60.0)
+                    dfSecond = 0.0;
+
                 dfValue = ABS(atof(papszTokens[0]))
                     + atof(papszTokens[1]) / 60.0
-                    + atof(papszTokens[2]) / 3600.0;
+                    + dfSecond / 3600.0;
 
                 if( atof(papszTokens[0]) < 0.0 )
                     dfValue *= -1;
@@ -606,8 +628,8 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
  * importFromESRI() by an automatical call to morphFromESRI(). 
  *
  * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS, 
- * EQUIDISTANT_CONIC, and TRANSVERSE (mercator) projections are supported
- * from old style files. 
+ * EQUIDISTANT_CONIC, TRANSVERSE (mercator), POLAR, MERCATOR and POLYCONIC
+ * projections are supported from old style files.
  *
  * At this time there is no equivelent exportToESRI() method.  Writing old
  * style .prj files is not supported by OGRSpatialReference. However the
@@ -740,6 +762,14 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                 OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
     }
 
+    else if( EQUAL(osProj,"LAMBERT_AZIMUTHAL") )
+    {
+        SetLAEA( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+                 OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
+                 OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
+                 OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
+    }
+
     else if( EQUAL(osProj,"EQUIDISTANT_CONIC") )
     {
         int     nStdPCount = (int) OSR_GDV( papszPrj, "PARAM_1", 0.0 );
@@ -791,6 +821,14 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                      OSR_GDV( papszPrj, "PARAM_3", 0.0 ) );
     }
 
+    else if( EQUAL(osProj,"POLYCONIC") )
+    {
+        SetPolyconic( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
+                      OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
+                      OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
+                      OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
+    }
+
     else
     {
         CPLDebug( "OGR_ESRI", "Unsupported projection: %s", osProj.c_str() );
@@ -852,7 +890,8 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                 CopyGeogCSFrom( &oGCS );
             }
             else if( EQUAL(osSpheroid,"KRASOVSKY") 
-                     || EQUAL(osSpheroid,"KRASSOVSKY") )
+                     || EQUAL(osSpheroid,"KRASSOVSKY")
+                     || EQUAL(osSpheroid,"KRASSOWSKY") )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( 4024 );
@@ -993,12 +1032,12 @@ OGRErr OGRSpatialReference::morphToESRI()
     }
 
 /* -------------------------------------------------------------------- */
-/*      OBLIQUE_STEREOGRAPHIC maps to ESRI Stereographic                */
+/*      OBLIQUE_STEREOGRAPHIC maps to ESRI Double_Stereographic         */
 /* -------------------------------------------------------------------- */
     if( pszProjection != NULL
         && ( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) ))
     {
-        SetNode( "PROJCS|PROJECTION", "Stereographic" );
+        SetNode( "PROJCS|PROJECTION", "Double_Stereographic" );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1250,12 +1289,17 @@ OGRErr OGRSpatialReference::morphToESRI()
 
     if( poSpheroidChild != NULL )
     {
-        char *pszNewValue = CPLStrdup(RemapSpheroidName(poSpheroidChild->GetValue()));
+//        char *pszNewValue = CPLStrdup(RemapSpheroidName(poSpheroidChild->GetValue()));
+        char *pszNewValue = CPLStrdup(poSpheroidChild->GetValue());
 
         MorphNameToESRI( &pszNewValue );
 
         poSpheroidChild->SetValue( pszNewValue );
         CPLFree( pszNewValue );
+
+        GetRoot()->applyRemapper( "SPHEROID", 
+                                  (char **) apszSpheroidMapping+0,
+                                  (char **) apszSpheroidMapping+1, 2 );
     }
 
     if( poSpheroid != NULL )
@@ -1401,6 +1445,28 @@ OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
  * datums to "standard" names, as defined by Adam Gawne-Cain's reference
  * translation of EPSG to WKT for the CT specification.
  *
+ * Starting with GDAL 1.9.0, missing parameters in TOWGS84, DATUM or GEOGCS
+ * nodes can be added to the WKT, comparing existing WKT parameters to GDAL's 
+ * databases.  Note that this optional procedure is very conservative and should
+ * not introduce false information into the WKT defintion (altough caution
+ * should be advised when activating it). Needs the Configuration Option 
+ * GDAL_FIX_ESRI_WKT be set to one of the following values (TOWGS84 is
+ * recommended for proper datum shift calculations):
+ *
+ * <b>GDAL_FIX_ESRI_WKT values</b>
+ * <table border=0>
+ * <tr><td>  </td><td><b>TOWGS84</b></td><td>  </td><td>
+ * Adds missing TOWGS84 parameters (necessary for datum transformations),
+ * based on named datum and spheroid values.</td></tr>
+ * <tr><td>  </td><td><b>DATUM</b></td><td>  </td><td>
+ * Adds ESPG AUTHORITY nodes and sets SPHEROID name to OGR spec.</td></tr>
+ * <tr><td>  </td><td><b>GEOGCS</b></td><td>  </td><td>
+ * Adds ESPG AUTHORITY nodes and sets GEOGCS, DATUM and SPHEROID
+ * names to OGR spec. Effectively replaces GEOGCS node with the result of
+ * importFromEPSG(n), using EPSG code n corresponding to the existing GEOGCS. 
+ * Does not impact PROJCS values.</td></tr>
+ * </table>
+ *
  * This does the same as the C function OSRMorphFromESRI().
  *
  * @return OGRERR_NONE unless something goes badly wrong.
@@ -1410,15 +1476,27 @@ OGRErr OGRSpatialReference::morphFromESRI()
 
 {
     OGRErr      eErr = OGRERR_NONE;
+    OGR_SRSNode *poDatum;
+    char        *pszDatumOrig = NULL;
 
     if( GetRoot() == NULL )
         return OGRERR_NONE;
 
+    InitDatumMappingTable();
+
+/* -------------------------------------------------------------------- */
+/*      Save original datum name for later                              */
+/* -------------------------------------------------------------------- */
+    poDatum = GetAttrNode( "DATUM" );
+    if( poDatum != NULL ) 
+    {
+        poDatum = poDatum->GetChild(0);
+        pszDatumOrig = CPLStrdup( poDatum->GetValue() );
+    }
+    
 /* -------------------------------------------------------------------- */
 /*      Translate DATUM keywords that are oddly named.                  */
 /* -------------------------------------------------------------------- */
-    InitDatumMappingTable();
-
     GetRoot()->applyRemapper( "DATUM", 
                               (char **)papszDatumMapping+1,
                               (char **)papszDatumMapping+2, 3 );
@@ -1426,8 +1504,6 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
 /*      Try to remove any D_ in front of the datum name.                */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode *poDatum;
-
     poDatum = GetAttrNode( "DATUM" );
     if( poDatum != NULL )
         poDatum = poDatum->GetChild(0);
@@ -1443,6 +1519,13 @@ OGRErr OGRSpatialReference::morphFromESRI()
     }
 
 /* -------------------------------------------------------------------- */
+/*      Translate some SPHEROID keywords that are oddly named.          */
+/* -------------------------------------------------------------------- */
+    GetRoot()->applyRemapper( "SPHEROID", 
+                              (char **)apszSpheroidMapping+1,
+                              (char **)apszSpheroidMapping+0, 2 );
+
+/* -------------------------------------------------------------------- */
 /*      Split Lambert_Conformal_Conic into 1SP or 2SP form.             */
 /*                                                                      */
 /*      See bugzilla.remotesensing.org/show_bug.cgi?id=187              */
@@ -1504,6 +1587,11 @@ OGRErr OGRSpatialReference::morphFromESRI()
             (char **)apszMercatorMapping + 0,
             (char **)apszMercatorMapping + 1, 2 );
 
+    if( pszProjection != NULL && EQUAL(pszProjection,"Orthographic") )
+        GetRoot()->applyRemapper( 
+            "PARAMETER", (char **)apszOrthographicMapping + 0,
+            (char **)apszOrthographicMapping + 1, 2 );
+
     if( pszProjection != NULL 
         && EQUALN(pszProjection,"Stereographic_",14) 
         && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
@@ -1524,6 +1612,16 @@ OGRErr OGRSpatialReference::morphFromESRI()
     }
 
 /* -------------------------------------------------------------------- */
+/*      Remap Double_Stereographic to Oblique_Stereographic.            */
+/* -------------------------------------------------------------------- */
+    if( pszProjection != NULL
+        && EQUAL(pszProjection,"Double_Stereographic") )
+    {
+        SetNode( "PROJCS|PROJECTION", SRS_PT_OBLIQUE_STEREOGRAPHIC );
+        pszProjection = GetAttrValue("PROJECTION");
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Remap Equidistant_Cylindrical parameter. It is same as          */
 /*      Stereographic                                                   */
 /* -------------------------------------------------------------------- */
@@ -1551,6 +1649,162 @@ OGRErr OGRSpatialReference::morphFromESRI()
                               (char **)papszDatumMapping+1,
                               (char **)papszDatumMapping+2, 3 );
 
+/* -------------------------------------------------------------------- */
+/*      Fix TOWGS84, DATUM or GEOGCS                                    */
+/* -------------------------------------------------------------------- */
+    /* TODO test more ESRI WKT; also add PROJCS */
+
+    /* Check GDAL_FIX_ESRI_WKT config option (default=NO); if YES, set to DATUM */
+    const char *pszFixWktConfig=CPLGetConfigOption( "GDAL_FIX_ESRI_WKT", "NO" );
+    if ( EQUAL(pszFixWktConfig,"YES") )
+        pszFixWktConfig = "DATUM";
+
+    if( !EQUAL(pszFixWktConfig, "NO") && poDatum != NULL )
+    { 
+        CPLDebug( "OGR_ESRI", 
+                  "morphFromESRI() looking for missing TOWGS84, datum=%s, config=%s",
+                  pszDatumOrig, pszFixWktConfig );
+
+        /* Special case for WGS84 and other common GCS? */
+
+        for( int i = 0; DMGetESRIName(i) != NULL; i++ )
+        {
+            /* we found the ESRI datum name in the map */
+            if( EQUAL(DMGetESRIName(i),pszDatumOrig) )
+            {
+                int nGeogCS;
+                int bDeprecated;
+                const char *pszFilename = NULL;
+                char **papszRecord = NULL;
+                OGR_SRSNode *poNode = NULL;
+                const char *pszThisValue = NULL;
+                char *pszOtherValue = NULL;
+                
+                /* look for GEOGCS corresponding to this datum */
+                pszFilename = CSVFilename("gcs.csv");
+                papszRecord = CSVScanFileByName( pszFilename, "DATUM_CODE",  
+                                                 DMGetEPSGCode(i), CC_Integer );
+                if ( papszRecord != NULL )
+                {
+                    /* make sure we got a valid EPSG code and it is not DEPRECATED */
+                    nGeogCS = atoi( CSLGetField( papszRecord,
+                                                 CSVGetFileFieldId(pszFilename,"COORD_REF_SYS_CODE")) );
+                    bDeprecated = atoi( CSLGetField( papszRecord,
+                                                     CSVGetFileFieldId(pszFilename,"DEPRECATED")) );
+                    
+                    // if ( nGeogCS >= 1 && bDeprecated == 0 )
+                    if ( nGeogCS >= 1 )
+                    {
+                        OGRSpatialReference oSRSTemp;
+                        if ( oSRSTemp.importFromEPSG( nGeogCS ) == OGRERR_NONE )
+                        {                        
+                            /* make clone of GEOGCS and strip CT parms for testing */
+                            OGRSpatialReference *poSRSTemp2 = NULL;
+                            int bIsSame = FALSE;
+                            poSRSTemp2 = oSRSTemp.CloneGeogCS();
+                            poSRSTemp2->StripCTParms();
+                            bIsSame = this->IsSameGeogCS( poSRSTemp2 );
+                            delete poSRSTemp2;
+
+                            /* clone GEOGCS from original if they match and if allowed */
+                            if ( EQUAL(pszFixWktConfig,"GEOGCS")
+                                 && bIsSame )
+                            {
+                                this->CopyGeogCSFrom( &oSRSTemp );
+                                CPLDebug( "OGR_ESRI", 
+                                          "morphFromESRI() cloned GEOGCS from EPSG:%d",
+                                          nGeogCS );
+                                /* exit loop */
+                                break;
+                            }   
+                            /* else try to copy only DATUM or TOWGS84 
+                               we got here either because of config option or 
+                               GEOGCS are not strictly equal */
+                            else if ( EQUAL(pszFixWktConfig,"GEOGCS") || 
+                                      EQUAL(pszFixWktConfig,"DATUM") ||
+                                      EQUAL(pszFixWktConfig,"TOWGS84") )
+                            {
+                                /* test for matching SPHEROID, because there can be 2 datums with same ESRI name 
+                                   but different spheroids (e.g. EPSG:4618 and EPSG:4291) - see bug #4345 */
+                                pszThisValue = pszOtherValue = NULL;                                
+                                pszThisValue = this->GetAttrValue( "DATUM|SPHEROID", 0 );
+                                if ( oSRSTemp.GetAttrValue( "DATUM|SPHEROID", 0 ) )
+                                {                                   
+                                    pszOtherValue = CPLStrdup(oSRSTemp.GetAttrValue( "DATUM|SPHEROID", 0 ) );
+                                    MorphNameToESRI( &pszOtherValue ); /* morph spheroid name to ESRI */
+                                }
+                                if ( EQUAL( pszThisValue, pszOtherValue ) )
+                                    bIsSame = TRUE;
+                                else 
+                                    bIsSame = FALSE;
+                                if (pszOtherValue) CPLFree(pszOtherValue);
+
+                                if ( bIsSame )
+                                {
+                                    /* test for matching PRIMEM, because there can be 2 datums with same ESRI name 
+                                       but different prime meridian (e.g. EPSG:4218 and EPSG:4802)  - see bug #4378 */
+                                    pszThisValue = pszOtherValue = NULL;                                
+                                    pszThisValue = this->GetAttrValue( "PRIMEM", 0 );
+                                    if ( oSRSTemp.GetAttrValue( "PRIMEM", 0 ) )
+                                    {                                   
+                                        pszOtherValue = CPLStrdup(oSRSTemp.GetAttrValue( "PRIMEM", 0 ) );
+                                    }
+                                    if ( EQUAL( pszThisValue, pszOtherValue )  )
+                                        bIsSame = TRUE;
+                                    else 
+                                        bIsSame = FALSE;
+                                    if (pszOtherValue) CPLFree(pszOtherValue);
+                                }
+                
+                                /* found a matching spheroid */ 
+                                if ( bIsSame )
+                                {
+                                    /* clone DATUM */
+                                    if ( EQUAL(pszFixWktConfig,"GEOGCS") || 
+                                         EQUAL(pszFixWktConfig,"DATUM")  )
+                                    {
+                                        OGR_SRSNode *poGeogCS = this->GetAttrNode( "GEOGCS" ); 
+                                        const OGR_SRSNode *poDatumOther = oSRSTemp.GetAttrNode( "DATUM" );  
+                                        if ( poGeogCS && poDatumOther ) 
+                                        {
+                                            /* make sure we preserve the position of the DATUM node */
+                                            int nPos = poGeogCS->FindChild( "DATUM" );
+                                            if ( nPos >= 0 )
+                                            {
+                                                poGeogCS->DestroyChild( nPos );
+                                                poGeogCS->InsertChild( poDatumOther->Clone(), nPos );
+                                                CPLDebug( "OGR_ESRI", 
+                                                          "morphFromESRI() cloned DATUM from EPSG:%d",
+                                                          nGeogCS );
+                                            }
+                                        }
+                                    } 
+                                    /* just copy TOWGS84 */
+                                    else if ( EQUAL(pszFixWktConfig,"TOWGS84") )
+                                    { 
+                                        poNode=oSRSTemp.GetAttrNode( "DATUM|TOWGS84" );
+                                        if ( poNode ) 
+                                        {
+                                            poNode=poNode->Clone();
+                                            GetAttrNode( "DATUM" )->AddChild( poNode );
+                                            CPLDebug( "OGR_ESRI", 
+                                                      "morphFromESRI() found missing TOWGS84 from EPSG:%d",
+                                                      nGeogCS );
+                                        }
+                                    }
+                                    /* exit loop */
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }         
+        }
+    }
+
+    CPLFree( pszDatumOrig );
+
     return eErr;
 }
 
@@ -1669,12 +1923,11 @@ int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName, cons
 int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName, const char* pszkeyName, 
                                                  char **mappingTable )
 {
-  long i, n;
+  long i;
   long iIndex = -1;
   for( i = 0; mappingTable[i] != NULL; i += 2 )
   {
-    n = strlen(pszName);
-    if( EQUALN(pszName, mappingTable[i],n) )
+    if( EQUAL(pszName, mappingTable[i]) )
     {
       iIndex = i;
       break;
@@ -1924,3 +2177,214 @@ int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
   return ret;
 }
 
+/************************************************************************/
+/*                    ImportFromESRIStatePlaneWKT()                     */
+/*                                                                      */
+/*      Search a ESRI State Plane WKT and import it.                    */
+/************************************************************************/
+
+OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(  int code, const char* datumName, const char* unitsName, int pcsCode, const char* csName )
+{
+  int i;
+  long searchCode = -1;
+
+  /* if the CS name is known */
+  if (code == 0 && !datumName && !unitsName && pcsCode == 32767 && csName)
+  {
+    char codeS[10];
+    if (FindCodeFromDict( "esri_StatePlane_extra.wkt", csName, codeS ) != OGRERR_NONE)
+      return OGRERR_FAILURE;
+    return importFromDict( "esri_StatePlane_extra.wkt", codeS);
+  }
+
+  /* Find state plane prj str by pcs code only */
+  if( code == 0 && !datumName && pcsCode != 32767 )
+  {
+
+    int unitCode = 1;
+    if( EQUAL(unitsName, "international_feet") )
+      unitCode = 3;
+    else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
+      unitCode = 2;
+   for(i=0; statePlanePcsCodeToZoneCode[i] != 0; i+=2)
+    {
+      if( pcsCode == statePlanePcsCodeToZoneCode[i] )
+      {
+        searchCode = statePlanePcsCodeToZoneCode[i+1];
+        int unitIndex =  searchCode % 10;
+        if( (unitCode == 1 && !(unitIndex == 0 || unitIndex == 1)) 
+            || (unitCode == 2 && !(unitIndex == 2 || unitIndex == 3 || unitIndex == 4 ))
+            || (unitCode == 3 && !(unitIndex == 5 || unitIndex == 6 )) )
+        {
+          searchCode -= unitIndex; 
+          switch (unitIndex)
+          {
+          case 0:
+          case 3:
+          case 5:
+            if(unitCode == 2)
+              searchCode += 3;
+            else if(unitCode == 3)
+              searchCode += 5;
+            break;
+          case 1:
+          case 2:
+          case 6:
+            if(unitCode == 1)
+              searchCode += 1;
+            if(unitCode == 2)
+              searchCode += 2;
+            else if(unitCode == 3)
+              searchCode += 6;
+           break;
+          case 4:
+            if(unitCode == 2)
+              searchCode += 4;
+            break;
+          }
+        }
+        break;
+      }
+    }
+  }
+  else /* Find state plane prj str by all inputs. */
+  {
+    /* Need to have a specail EPSG-ESRI zone code mapping first. */
+    for(i=0; statePlaneZoneMapping[i] != 0; i+=3)
+    {
+      if( code == statePlaneZoneMapping[i] 
+       && (statePlaneZoneMapping[i+1] == -1 || pcsCode == statePlaneZoneMapping[i+1]))
+      {
+        code = statePlaneZoneMapping[i+2];
+        break;
+      }
+    }
+    searchCode = (long)code * 10;
+    if(EQUAL(datumName, "HARN"))
+    {
+      if( EQUAL(unitsName, "international_feet") )
+        searchCode += 5;
+      else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
+        searchCode += 3;
+    }
+    else if(strstr(datumName, "NAD") && strstr(datumName, "83"))
+    {
+      if( EQUAL(unitsName, "meters") )
+         searchCode += 1;
+      else if( EQUAL(unitsName, "international_feet") )
+        searchCode += 6;
+      else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
+         searchCode += 2;
+    }
+    else if(strstr(datumName, "NAD") && strstr(datumName, "27") && !EQUAL(unitsName, "meters"))
+    {
+      searchCode += 4;
+    }
+    else
+      searchCode = -1;
+  }
+  if(searchCode > 0)
+  {
+    char codeS[10];
+    sprintf(codeS, "%d", (int)searchCode);
+    return importFromDict( "esri_StatePlane_extra.wkt", codeS);
+  }
+  return OGRERR_FAILURE;
+}
+
+/************************************************************************/
+/*                     ImportFromESRIWisconsinWKT()                     */
+/*                                                                      */
+/*      Search a ESRI State Plane WKT and import it.                    */
+/************************************************************************/
+
+OGRErr OGRSpatialReference::ImportFromESRIWisconsinWKT( const char* prjName, double centralMeridian, double latOfOrigin, const char* unitsName, const char* csName )
+{
+  /* if the CS name is known */
+  if (!prjName && !unitsName && csName)
+  {
+    char codeS[10];
+    if (FindCodeFromDict( "esri_Wisconsin_extra.wkt", csName, codeS ) != OGRERR_NONE)
+      return OGRERR_FAILURE;
+    return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
+  }
+  double* tableWISCRS;
+  if(EQUALN(prjName, "Lambert_Conformal_Conic", 22))
+    tableWISCRS = apszWISCRS_LCC_meter;
+  else if(EQUAL(prjName, SRS_PT_TRANSVERSE_MERCATOR))
+    tableWISCRS = apszWISCRS_TM_meter;
+  else
+    return OGRERR_FAILURE;
+  int k = -1;
+  for(int i=0; tableWISCRS[i] != 0; i+=3)
+  {
+    if( fabs(centralMeridian - tableWISCRS[i]) <= 0.0000000001 && fabs(latOfOrigin - tableWISCRS[i+1]) <= 0.0000000001) 
+    {
+      k = (long)tableWISCRS[i+2];
+      break;
+    }
+  }
+  if(k > 0)
+  {
+    if(!EQUAL(unitsName, "meters"))
+      k += 100;
+    char codeS[10];
+    sprintf(codeS, "%d", k);
+    return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
+  }
+  return OGRERR_FAILURE;
+}
+
+/************************************************************************/
+/*                       FindCodeFromDict()                             */
+/*                                                                      */
+/*      Find the code from a dict file.                                 */
+/************************************************************************/
+static int FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code )
+{
+    const char *pszFilename;
+    FILE *fp;
+    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
+
+/* -------------------------------------------------------------------- */
+/*      Find and open file.                                             */
+/* -------------------------------------------------------------------- */
+    pszFilename = CPLFindFile( "gdal", pszDictFile );
+    if( pszFilename == NULL )
+        return OGRERR_UNSUPPORTED_SRS;
+
+    fp = VSIFOpen( pszFilename, "rb" );
+    if( fp == NULL )
+        return OGRERR_UNSUPPORTED_SRS;
+
+/* -------------------------------------------------------------------- */
+/*      Process lines.                                                  */
+/* -------------------------------------------------------------------- */
+    const char *pszLine;
+
+    while( (pszLine = CPLReadLine(fp)) != NULL )
+
+    {
+        if( pszLine[0] == '#' )
+            /* do nothing */;
+
+        else if( strstr(pszLine,CSName) )
+        {
+          const char* pComma = strchr(pszLine, ',');
+          if( pComma )
+          {
+            strncpy( code, pszLine, pComma - pszLine);
+            code[pComma - pszLine] = '\0';
+            eErr = OGRERR_NONE;  
+          }
+          break;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    VSIFClose( fp );
+    
+    return eErr;
+}
diff --git a/ogr/ogr_srs_esri_names.h b/ogr/ogr_srs_esri_names.h
index 7493004..8c82f84 100644
--- a/ogr/ogr_srs_esri_names.h
+++ b/ogr/ogr_srs_esri_names.h
@@ -2,7 +2,6 @@ static const char *apszGcsNameMapping[] = {
 "North_American_Datum_1983", "GCS_North_American_1983",
 "North_American_Datum_1927", "GCS_North_American_1927",
 "NAD27_CONUS", "GCS_North_American_1927",
-"NAD27[CONUS]", "GCS_North_American_1927",
 "Reseau_Geodesique_de_Nouvelle_Caledonie_1991-93", "GCS_RGNC_1991-93",
 "Reseau_Geodesique_de_la_Polynesie_Francaise", "GCS_RGPF",
 "Rauenberg_1983", "GCS_RD/83",
@@ -20,60 +19,171 @@ static const char *apszGcsNameMapping[] = {
 "Azores_Oriental_Islands_1940", "GCS_Azores_Oriental_1940",
 "Lithuania_1994", "GCS_LKS_1994",
 "Libyan_Geodetic_Datum_2006", "GCS_LGD2006",
-"Lisbon", "GCS_Lisbon_Lisbon",
+//"Lisbon", "GCS_Lisbon_Lisbon",
 "Stockholm_1938", "GCS_RT38",
 "Latvia_1992", "GCS_LKS_1992",
 "Azores_Oriental_Islands_1995", "GCS_Azores_Oriental_1995",
 "Azores_Central_Islands_1948", "GCS_Azores_Central_1948", 
 "Azores_Central_Islands_1995", "GCS_Azores_Central_1995",
 "ATF", "GCS_ATF_Paris",
-"ITRF_2000", "GCS_MONREF_1997",
+//"ITRF_2000", "GCS_MONREF_1997",
 "Faroe_Datum_1954", "GCS_FD_1954",
 "Vietnam_2000", "GCS_VN_2000",
-"Belge_1950", "GCS_Belge_1950_Brussels",
+//"Belge_1950", "GCS_Belge_1950_Brussels",
 "Qatar_1948", "GCS_Qatar_1948",
 "Qatar", "GCS_Qatar_1974",
 "Kuwait_Utility", "GCS_KUDAMS",
+"ED_1950_16", "GCS_European_1950",
+"SAD_1969_Mean", "GCS_South_American_1969",
+"Sphere_of_Radius_6370997m", "GCS_Sphere_ARC_INFO",
+"Australian_Geodetic_1966", "GCS_Australian_1966",
+"Australian_Geodetic_1984", "GCS_Australian_1984",
+"AGD84", "GCS_Australian_1984",
+"AGD66", "GCS_Australian_1966",
+"Rome_1940", "GCS_Monte_Mario",
+"Tokyo_Japan", "GCS_Tokyo",
+"Graciosa_Base_SW_1948_1", "GCS_Graciosa_Base_SW_1948",
+"Datum_Lisboa_Bessel_1", "GCS_Datum_Lisboa_Bessel",
+"Datum_Lisboa_Hayford_1", "GCS_Datum_Lisboa_Hayford",
+"Observatorio_Metereo_1939_Grupo_Ocidental", "GCS_Observ_Meteorologico_1939",
+"Porto_Santo_1936_1", "GCS_Porto_Santo_1936",
+"Sao_Braz_1", "GCS_Sao_Braz",
+"GDA94", "GCS_GDA_1994",
+"HARN", "GCS_North_American_1983_HARN",
+"NAD83_HARN", "GCS_North_American_1983_HARN",
+"Voirol_1875", "GCS_Voirol_1875",
+"Voirol_1960", "GCS_Voirol_Unifie_1960",
+"Ain_el_Abd_1970_Bahrain", "GCS_Ain_el_Abd_1970",
+"ED_1950_ED77", "GCS_European_1950_ED77",
+"Naparima_1955_2", "GCS_Naparima_1955",
+"Aratu_Brazil_Campos_Espirito_Santo_and_Santos_basins", "GCS_Aratu",
+"Camacupa_Angola_1", "GCS_Camacupa",
+"Cape_1", "GCS_Cape",
+"Carthage_Tunisia", "GCS_Carthage",
+"Deir_ez_Zor_2", "GCS_Deir_ez_Zor",
+"Old_Egyptian_1907", "GCS_Egypt_1907",
+"PSAD56", "GCS_Provisional_S_American_1956", 
+"Indian 1975", "GCS_Indian_1975",
+"Indian_1960_1", "GCS_Indian_1960",
+"Kalianpur_1937_1", "GCS_Kalianpur_1937",
+"Kertau_1948", "GCS_Kertau",
+"Kertau_1968", "GCS_Kertau",
+"Luzon", "GCS_Luzon_1911",
+"Malongo_1987_1", "GCS_Malongo_1987",
+"Minna_Cameroon", "GCS_Minna",
+"Mporaloko_1", "GCS_Mporaloko",
+"Nahrwan_Oman", "GCS_Nahrwan_1967",
+"Naparima_BWI", "GCS_Naparima_1972",
+"Geodetic_Datum_1949", "GCS_New_Zealand_1949",
+"Qatar_National", "GCS_Qatar_1974",
+"SAD_1969_Mean", "GCS_South_American_1969",
+"Tananarive_Observatory_1925", "GCS_Tananarive_1925",
+"Tananarive", "GCS_Tananarive_1925",
+"Ireland_1965", "GCS_TM65",
+"DE_DHDN_whole_country_2001_to_ETRS89", "GCS_Deutsches_Hauptdreiecksnetz",
+"Belge_1972_1", "GCS_Belge_1972",
+"WGS_72", "GCS_WGS_1972",
+"JGD2000", "GCS_JGD_2000",
+"NZGD49", "GCS_New_Zealand_1949",
+"CH1903_1", "GCS_CH1903",
+"DE_42/83_to_ETRS89", "GCS_Pulkovo_1942",
+"DE_42_83_to_ETRS89", "GCS_Pulkovo_1942",
+"Amersfoort_1", "GCS_Amersfoort",
+"CH1903+_L+T1997", "GCS_CH1903+",
+"Ord_Survey_G_Britain_1936", "GCS_OSGB_1936",
+"European_Datum_1950", "GCS_European_1950",
+"Geocentric_Datum_of_Australia_1994", "GCS_GDA_1994",
+"NAD83_High_Accuracy_Regional_Network", "GCS_North_American_1983_HARN",
+"Bogota_1975", "GCS_Bogota",
+"North_American_Datum_1927_CGQ77", "GCS_NAD_1927_CGQ77",
+"North_American_Datum_1927_1976", "GCS_NAD_1927_Definition_1976",
+"European_Datum_1950_1977", "GCS_European_1950_ED77",
+"WGS_1972_Transit_Broadcast_Ephemeris", "GCS_WGS_1972_BE",
+"Greek_Geodetic_Reference_System_1987", "GCS_GGRS_1987",
+"Militar_Geographische_Institute", "GCS_MGI",
+"ED50", "GCS_European_1950",
 NULL, NULL};
 
 static const char *apszGcsNameMappingBasedOnProjCS[] = {
 "EUREF_FIN_TM35FIN", "GCS_ETRS_1989", "GCS_EUREF_FIN",
+"Nord_Maroc_Degree", "GCS_Merchich", "GCS_Merchich_Degree",
+"Sahara_Degree", "GCS_Merchich", "GCS_Merchich_Degree",
+"Sud_Maroc_Degree", "GCS_Merchich", "GCS_Merchich_Degree",
+"Merchich_Degree_UTM_Zone_28N", "GCS_Merchich", "GCS_Merchich_Degree",
+"Lambert_Conformal_Conic", "GCS_Merchich", "GCS_Merchich_Degree",
+"UTM", "GCS_Merchich", "GCS_Merchich_Degree",
+"UTM_Zone_28_Northern_Hemisphere", "GCS_Merchich", "GCS_Merchich_Degree",
+"Portuguese_National_Grid", "GCS_Lisbon", "GCS_Lisbon_Lisbon",
+"Belge_Lambert_1950", "GCS_Belge_1950", "GCS_Belge_1950_Brussels",
+"MONREF_1997_UTM_Zone_46N", "GCS_ITRF_2000", "GCS_MONREF_1997",
+"MONREF_1997_UTM_Zone_47N", "GCS_ITRF_2000", "GCS_MONREF_1997",
 NULL, NULL, NULL};
 
+
+
 static const char *apszGcsNameMappingBasedOnUnit[] = {
-"Merchich", "Degree", "GCS_Merchich_Degree",
 "Voirol_Unifie_1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
+"Voirol_1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
+"Voirol 1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
+"Voirol_1875", "Degree", "GCS_Voirol_1875_Degree",
+"Voirol 1875", "Degree", "GCS_Voirol_1875_Degree",
 "NTF", "Grad", "GCS_NTF_Paris",
 NULL, NULL, NULL};
 
 static const char *apszGcsNameMappingBasedPrime[] = {
-"S_JTSK", "Ferro", "GCS_S_JTSK_Ferro",
-"MGI", "Ferro", "GCS_MGI_Ferro",
+"Bern_1898", "Bern", "GCS_Bern_1898_Bern",
 "Madrid_1870", "Madrid", "GCS_Madrid_1870_Madrid",
+"MGI", "Ferro", "GCS_MGI_Ferro",
+"MGI", "Stockholm", "GCS_RT38_Stockholm",
 "Monte_Mario", "Rome", "GCS_Monte_Mario_Rome",
 "NGO_1948", "Oslo", "GCS_NGO_1948_Oslo",
-"MGI", "Stockholm", "GCS_RT38_Stockholm",
+"S_JTSK", "Ferro", "GCS_S_JTSK_Ferro",
 "Stockholm_1938", "Stockholm", "GCS_RT38_Stockholm",
-"Bern_1898", "Bern", "GCS_Bern_1898_Bern",
 NULL, NULL, NULL};
 
 static const char *apszInvFlatteningMapping[] = {
 "293.464999999", "293.465", 
+"293.465000003", "293.465",
+"293.465073361", "293.465",
 "293.466020000", "293.46602",
-"294.26067636900", "294.260676369", 
+"293.466021293", "293.46602",
+"293.4663077168286", "293.466307656",
+"293.4664236085404", "293.466307656",
+"294.2606763690", "294.260676369", 
 "294.9786981999", "294.9786982", 
 "294.978698213", "294.9786982",
 "295.9999999999", "296.0", 
 "297.0000000000", "297.0",
+"297.0000000284", "297.0",
+"297.0000535480", "297.0",
+"298.2499972761", "298.25",
+"298.2500000654", "298.25",
+"298.2500112226", "298.25",
 "298.256999999", "298.257",
 "298.2600000000", "298.26",
+"298.2571643544962", "298.257223563",
+"298.25716435449", "298.257222101",
+"298.257222096042", "298.257222101",
 "298.25722210100", "298.257222101",
 "298.25722356299", "298.257223563",
+"298.25722356300", "298.257223563",
+"298.25999858999", "298.26",
 "298.2684109950054", "298.268410995005",
-"298.299999999", "298.3",
+"298.2999", "298.3",
+"298.3000", "298.3",
+"299.1527033239203", "299.1528128",
 "299.15281280000", "299.1528128",
+"299.15281283", "299.1528128",
+"299.15281310607", "299.1528128",
+"299.15281327254", "299.1528128",
+"299.32496460000", "299.3249646",
+"299.32496405862", "299.3249646",
+"299.32497531503", "299.3249646",
+"300.80158474106", "300.8017",
+"300.80169943849", "300.8017", 
 "300.80169999999", "300.8017",
 "300.80170000000", "300.8017",
+"300.80170009712", "300.8017",
 NULL, NULL};
 
 static const char *apszParamValueMapping[] = {
@@ -85,6 +195,13 @@ static const char *apszParamValueMapping[] = {
 "Transverse_Mercator", "false_easting", "299999.4798609", "300000.0", 
 "Transverse_Mercator", "false_northing", "399999.30648", "400000.0",
 "Transverse_Mercator", "false_northing", "499999.1331", "500000.0",
+"Transverse_Mercator", "central_meridian","51.21666666666668", "51.21666666666667",
+"Transverse_Mercator", "Scale_Factor", "0.999601272", "0.9996012717",
+"Lambert_Conformal_Conic", "central_meridian", "-90.33333333333334", "-90.33333333333333",
+"Lambert_Conformal_Conic", "central_meridian", "-76.83333333333334", "-76.83333333333333",
+"Krovak", "longitude_of_center", "24.83333333333334", "24.83333333333333",
+"Hotine_Oblique_Mercator_Azimuth_Center", "longitude_of_center", "7.439583333333334", "7.439583333333333",
+"Hotine_Oblique_Mercator_Azimuth_Center", "latitude_of_center",	"46.95240555555557", "46.95240555555556",
 NULL, NULL, NULL, NULL};
 
 static const char *apszParamNameMapping[] = {
@@ -104,6 +221,7 @@ static const char *apszDeleteParametersBasedOnProjection[] = {
 "Mercator", "scale_factor",
 "Miller_Cylindrical", "latitude_of_center",
 "Equidistant_Cylindrical", "pseudo_standard_parallel_1", 
+"Equidistant_Cylindrical", "latitude_of_origin", 
 "Plate_Carree", "latitude_of_origin",
 "Plate_Carree", "pseudo_standard_parallel_1",
 "Plate_Carree", "standard_parallel_1",
@@ -113,6 +231,482 @@ NULL, NULL};
 
 static const char *apszAddParametersBasedOnProjection[] = {
 "Cassini", "scale_factor", "1.0", 
-"Lambert_Conformal_Conic", "scale_factor", "1.0",
 "Mercator", "standard_parallel_1", "0.0", 
 NULL, NULL, NULL};
+
+static int statePlaneZoneMapping[] = {
+/* old zone code, prj code, new zone code */
+ 3126, -1,    101,
+ 3151, -1,    102,
+ 3176, -1,    202,
+ 3201, -1,    203, 
+ 3226, -1,    301, 
+ 3251, -1,    302, 
+ 3326, -1,    403, 
+ 3351, -1,    404, 
+ 3376, 26945, 405,
+ 3426, -1,    407, 
+ 3451, -1,    501, 
+ 3476, -1,    502, 
+ 3526, -1,    600, 
+ 3551, -1,    700, 
+ 3576, -1,    903, 
+ 3626, -1,    902, 
+ 3651, -1,    1001, 
+ 3676, -1,    1002, 
+ 3726, -1,    1102, 
+ 3751, -1,    1103, 
+ 3776, -1,    1201, 
+ 3801, -1,    1202, 
+ 3826, -1,    1301, 
+ 3851, -1,    1302, 
+ 3876, -1,    1401, 
+ 3926, -1,    1501, 
+ 3951, -1,    1502, 
+ 3976, -1,    1601, 
+ 4026, -1,    1701, 
+ 6426, -1,    1703, 
+ 4076, -1,    1801, 
+ 4101, -1,    1802, 
+ 4126, -1,    1900,
+ 4151, -1,    2001, 
+ 4176, -1,    2002, 
+ 4226, -1,    2102, 
+ 4251, -1,    2103, 
+ 6351, -1,    2111, 
+ 6376, -1,    2112, 
+ 6401, -1,    2113, 
+ 4276, -1,    2201, 
+ 4326, -1,    2203, 
+ 4351, -1,    2301, 
+ 4376, -1,    2302, 
+ 4400, 32045, 3400,
+ 4401, -1,    2401, 
+ 4426, -1,    2402, 
+ 4451, -1,    2403, 
+ 4476, 32100, 2500,
+ 4476, -1,    2501,
+ 4701, 32111,	2900,
+ 4801, 2260,  3101,
+ 4801, 32115, 3101,
+ 4526, -1,    2503, 
+ 4551, -1,    2601, 
+ 4576, -1,    2602, 
+ 4626, -1,    2702, 
+ 4651, -1,    2703, 
+ 4676, -1,    2800, 
+ 4726, -1,    3001, 
+ 4751, -1,    3002, 
+ 4776, -1,    3003, 
+ 4826, -1,    3102, 
+ 4851, -1,    3103, 
+ 4876, -1,    3104, 
+ 4926, -1,    3301, 
+ 4951, -1,    3302, 
+ 4976, -1,    3401, 
+ 5026, -1,    3501, 
+ 5051, -1,    3502, 
+ 5076, -1,    3601, 
+ 5126, -1,    3701, 
+ 5151, -1,    3702, 
+ 5176, -1,    3800, 
+ 5226, -1,    3902, 
+ 5251, -1,    4001, 
+ 5276, -1,    4002, 
+ 5301, -1,    4100, 
+ 5326, -1,    4201, 
+ 5351, -1,    4202, 
+ 5376, -1,    4203, 
+ 5401, -1,    4204, 
+ 5426, -1,    4205, 
+ 5451, -1,    4301, 
+ 5476, -1,    4302, 
+ 5501, -1,    4303, 
+ 5526, -1,    4400, 
+ 5551, -1,    4501, 
+ 5576, -1,    4502, 
+ 5601, -1,    4601, 
+ 5626, -1,    4602, 
+ 5651, -1,    4701, 
+ 5676, -1,    4702, 
+ 5701, -1,    4801, 
+ 5726, -1,    4802, 
+ 5751, -1,    4803, 
+ 5776, -1,    4901, 
+ 5801, -1,    4902, 
+ 5826, -1,    4903, 
+ 5851, -1,    4904, 
+ 6101, -1,    5001, 
+ 6126, -1,    5002, 
+ 6151, -1,    5003, 
+ 6176, -1,    5004, 
+ 6201, -1,    5005, 
+ 6226, -1,    5006, 
+ 6251, -1,    5007, 
+ 6276, -1,    5008, 
+ 6301, -1,    5009, 
+ 6326, -1,    5010, 
+ 5876, -1,    5101, 
+ 5901, -1,    5102, 
+ 5926, -1,    5103, 
+ 5951, -1,    5104, 
+ 5976, -1,    5105, 
+ 6001, -1,    5201, 
+ 6026, -1,    5200, 
+ 6076, -1,    5200, 
+ 6051, -1,    5202, 
+ 0,    0,     0 
+ }; 
+
+/* This is not a complete mapping. Need to add more. */
+static int statePlanePcsCodeToZoneCode[] = {
+/* pcs code, state plane prj str index*/
+2222, 2016,
+2223, 2026,
+2224, 2036,
+2225, 4012,
+2226, 4022,
+2227, 4032,
+2228, 4042,
+2229, 4052,
+2230, 4062,
+2231, 5012,
+2232, 5022,
+2233, 5032,
+2234, 6002,
+2235, 7002,
+2236, 9012,
+2237, 9022,
+2238, 9032,
+2239, 10012,
+2240, 10022,
+2241, 11012,
+2242, 11022,
+2243, 11032,
+2251, 21116,
+2252, 21126,
+2253, 21136,
+2256, 25006,
+2265, 33016,
+2266, 33026,
+2965, 13012,
+2966, 13022,
+2246, 16012,
+2247, 16022,
+2248, 19002,
+2249, 20012,
+2250, 20022,
+2254, 23012,
+2255, 23022,
+2257, 30012,
+2258, 30022,
+2259, 30032,
+2260, 31012,
+2261, 31022,
+2262, 31032,
+2263, 31042,
+2264, 32002,
+2267, 35012,
+2268, 35022,
+2269, 36016,
+2270, 36026,
+2271, 37012,
+2272, 37022,
+2273, 39006,
+2274, 41002,
+2275, 42012,
+2276, 42022,
+2277, 42032,
+2278, 42042,
+2279, 42052,
+2280, 43016,
+2281, 43026,
+2282, 43036,
+2283, 45012,
+2284, 45022,
+2285, 46012,
+2286, 46022,
+2287, 48012,
+2288, 48022,
+2289, 48032,
+2867, 2015,
+2868, 2025,
+2869, 2035,
+2896, 21115,
+2897, 21125,
+2898, 21135,
+2901, 25005,
+2909, 33015,
+2910, 33025,
+2913, 36015,
+2914, 36025,
+2921, 43015,
+2922, 43025,
+2923, 43035,
+2870, 4013,
+2871, 4023,
+2872, 4033,
+2873, 4043,
+2874, 4053,
+2875, 4063,
+2876, 5013,
+2877, 5023,
+2878, 5033,
+2879, 6003,
+2880, 7003,
+2881, 9013,
+2882, 9023,
+2883, 9033,
+2884, 10013,
+2885, 10023,
+2886, 11013,
+2887, 11023,
+2888, 11033,
+2967, 13013,
+2968, 13023,
+2891, 16013,
+2892, 16023,
+2893, 19003,
+2894, 20013,
+2895, 20023,
+2899, 23013,
+2900, 23023,
+2902, 30013,
+2903, 30023,
+2904, 30033,
+2905, 31013,
+2906, 31023,
+2907, 31033,
+2908, 31043,
+2911, 35013,
+2912, 35023,
+2915, 41003,
+2916, 42013,
+2917, 42023,
+2918, 42033,
+2919, 42043,
+2920, 42053,
+2924, 45013,
+2925, 45023,
+2926, 46013,
+2927, 46023,
+2928, 48013,
+2929, 48023,
+2930, 48033,
+// following are state systems (not complete)
+2964, 102965,
+2991, 102991,
+2992, 102992,
+2993, 102993,
+2994, 102994, 
+// following are NAD 1983 SPCS Zone  
+26929, 1011,      
+26930, 1021,      
+26931, 50011,          
+26932, 50021,          
+26933, 50031,          
+26934, 50041,          
+26935, 50051,          
+26936, 50061,          
+26937, 50071,          
+26938, 50081,          
+26939, 50091,          
+26940, 50101,         
+26948, 2011,      
+26949, 2021,   
+26950, 2031,      
+26951, 3011,    
+26952, 3021,    
+26941, 4011,      
+26942, 4021,     
+26943, 4031,    
+26944, 4041,     
+26945, 4051,      
+26946, 4061,     
+26953, 5011,    
+26954, 5021,  
+26955, 5031,    
+26956, 6001,       
+26957, 7001,          
+26958, 9011,      
+26959, 9021,      
+26960, 9031,     
+26966, 10011,      
+26967, 10021,      
+26961, 51011,     
+26962, 51021,     
+26963, 51031,     
+26964, 51041,     
+26965, 51051,     
+26968, 11011,        
+26969, 11021,     
+26970, 11031,        
+26971, 12011,     
+26972, 12021,     
+26973, 13011,      
+26974, 13021,      
+26975, 14011,        
+26976, 14021,        
+26977, 15011,      
+26978, 15021,      
+26979, 16011,    
+26980, 16021,    
+26981, 17011,   
+26982, 17021,   
+26983, 18011,        
+26984, 18021,        
+26985, 19001,          
+26986, 20011,    
+26987, 20021,      
+26988, 21111,    
+26989, 21121,  
+26990, 21131,    
+26991, 22011,   
+26992, 22021, 
+26993, 22031,   
+26994, 23011,  
+26995, 23021,  
+26996, 24011,     
+26997, 24021,  
+26998, 24031,     
+32100, 25001,           
+32104, 26001,          
+32107, 27011,       
+32108, 27021,    
+32109, 27031,       
+32110, 28001,     
+32111, 29001,        
+32112, 30011,   
+32113, 30021,  
+32114, 30031,   
+32115, 31011,     
+32116, 31021,  
+32117, 31031,     
+32118, 31041,    
+32119, 32001, 
+32120, 33011,    
+32121, 33021,    
+32122, 34011,        
+32123, 34021,        
+32124, 35011,    
+32125, 35021,    
+32126, 36011,      
+32127, 36021,      
+32128, 37011,    
+32129, 37021,    
+32130, 38001,      
+32133, 39001,    
+32134, 40011,    
+32135, 40021,    
+32136, 41001,         
+32137, 42011,       
+32138, 42021, 
+32139, 42031,     
+32140, 42041, 
+32141, 42051,       
+32142, 43011,        
+32143, 43021,      
+32144, 43031,        
+32145, 44001,           
+32146, 45011,    
+32147, 45021,    
+32148, 46011,  
+32149, 46021,  
+32150, 47011,   
+32151, 47021,   
+32152, 48011,   
+32153, 48021, 
+32154, 48031,   
+32155, 49011,    
+32156, 49021,     
+32157, 49031,    
+32158, 49041,   
+32161, 52000,    
+65161, 54001,  
+0,     0
+};
+
+/* ==================================================================== */
+/*      WISCRS Table                                                    */
+/* ==================================================================== */
+static double apszWISCRS_LCC_meter[] = {
+// Central_Meridian, Latitude_Of_Origin, SR code
+   -91.1527777777, 46.6696483772, 103303.0, 
+   -92.4577777777, 45.8987148658, 103306.0, 
+   -91.2944444444, 44.9778568986, 103308.0, 
+   -89.3944444444, 43.4625466458, 103310.0, 
+   -90.9388888888, 43.2000556050, 103311.0, 
+   -89.4222222222, 43.0695160375, 103312.0, 
+   -91.2888888888, 45.8722811263, 103317.0, 
+   -89.8388888888, 42.6375622769, 103322.0, 
+   -89.2416666666, 43.8070001177, 103323.0, 
+   -89.8388888888, 42.6375622769, 103332.0, 
+   -89.0333333333, 45.1542371052, 103333.0, 
+   -89.7700000000, 44.9009044236, 103336.0, 
+   -89.2416666666, 43.8070001177, 103338.0, 
+   -90.6416666666, 44.0000739286, 103341.0, 
+   -89.5444444444, 45.7042237702, 103343.0, 
+   -92.2277777777, 44.6361488719, 103346.0, 
+   -92.2277777777, 44.6361488719, 103347.0, 
+   -89.5000000000, 44.4168239752, 103349.0, 
+   -90.4305555555, 43.3223129275, 103352.0, 
+   -91.1166666666, 45.9000991313, 103356.0, 
+   -90.4833333333, 45.1778220858, 103360.0, 
+   -90.7833333333, 43.5750329397, 103362.0, 
+   -89.4888888888, 46.0778440905, 103363.0, 
+   -88.5416666667, 42.6694620969, 103364.0, 
+   -91.7833333333, 45.9612198333, 103365.0, 
+   -89.2416666666, 44.1139440458, 103369.0, 
+   -90.0000000000, 44.3625954694, 103371.0, 
+   0.0, 0,0, 0,0
+};
+
+static double apszWISCRS_TM_meter[] = {
+// Central_Meridian, Latitude_Of_Origin, SR code 
+   -90.0000000000, 43.3666666666, 103300.0, 
+   -90.6222222222, 45.7061111111, 103301.0, 
+   -91.8500000000, 45.1333333333, 103302.0, 
+   -88.0000000000, 43.0000000000, 103304.0, 
+   -91.7972222222, 43.4813888888, 103305.0, 
+   -88.5000000000, 42.7194444444, 103307.0, 
+   -90.7083333333, 43.6000000000, 103309.0, 
+   -88.7750000000, 41.4722222222, 103313.0, 
+   -87.2722222222, 44.4000000000, 103314.0, 
+   -91.9166666666, 45.8833333333, 103315.0, 
+   -91.8944444444, 44.4083333333, 103316.0, 
+   -88.1416666666, 45.4388888888, 103318.0, 
+   -88.5000000000, 42.7194444444, 103319.0, 
+   -88.6333333333, 44.0055555556, 103320.0, 
+   -90.8000000000, 41.4111111111, 103321.0, 
+   -90.1611111111, 42.5388888888, 103324.0, 
+   -90.2555555555, 45.4333333333, 103325.0, 
+   -90.8442965194, 44.2533351277, 103326.0, 
+   -88.7750000000, 41.4722222222, 103327.0, 
+   -90.0000000000, 43.3666666666, 103328.0, 
+   -87.8944444444, 42.2166666666, 103329.0, 
+   -87.5500000000, 43.2666666666, 103330.0, 
+   -91.3166666666, 43.4511111111, 103331.0, 
+   -89.7333333333, 44.8444444444, 103334.0, 
+   -87.5500000000, 43.2666666666, 103335.0, 
+   -87.7111111111, 44.6916666666, 103337.0, 
+   -88.4166666666, 44.7166666666, 103339.0, 
+   -87.8944444444, 42.2166666666, 103340.0, 
+   -87.9083333333, 44.3972222222, 103342.0, 
+   -88.5000000000, 42.7194444444, 103344.0, 
+   -87.8944444444, 42.2166666666, 103345.0, 
+   -92.6333333333, 44.6611111111, 103348.0, 
+   -90.4888888889, 44.5555555556, 103350.0, 
+   -87.8944444444, 42.2166666666, 103351.0, 
+   -89.0722222222, 41.9444444444, 103353.0, 
+   -91.0666666666, 43.9194444444, 103354.0, 
+   -89.9000000000, 42.8194444444, 103355.0, 
+   -88.6055555556, 44.0361111111, 103357.0, 
+   -87.5500000000, 43.2666666666, 103358.0, 
+   -92.6333333333, 44.0361111111, 103359.0, 
+   -91.3666666666, 43.1611111111, 103361.0, 
+   -88.0638888888, 42.9180555555, 103366.0, 
+   -88.2250000000, 42.5694444444, 103367.0, 
+   -88.8166666666, 43.4202777777, 103368.0, 
+   -88.5000000000, 42.7194444444, 103370.0, 
+   0.0, 0,0, 0,0
+};
diff --git a/ogr/ogr_srs_ozi.cpp b/ogr/ogr_srs_ozi.cpp
index 2628bb9..5d49a32 100644
--- a/ogr/ogr_srs_ozi.cpp
+++ b/ogr/ogr_srs_ozi.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_ozi.cpp 21264 2010-12-14 22:55:01Z rouault $
+ * $Id: ogr_srs_ozi.cpp 22510 2011-06-07 13:33:40Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation from OziExplorer
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_ozi.cpp 21264 2010-12-14 22:55:01Z rouault $");
+CPL_CVSID("$Id: ogr_srs_ozi.cpp 22510 2011-06-07 13:33:40Z warmerdam $");
 
 /************************************************************************/
 /*  Correspondence between Ozi and EPSG datum codes.                    */
@@ -51,6 +51,7 @@ static const OZIDatums aoDatums[] =
     { "Pulkovo 1942 (1)", 4284 },   // Pulkovo 1942
     { "Pulkovo 1942 (2)", 4284 },   // Pulkovo 1942, XXX: What is a difference
                                     // with the previous one?
+    { "Potsdam Rauenberg DHDN", 31467 }, // Gauss-Krueger GK3 Central_Meridian 9 deg
     { NULL, 0 }
 };
 
diff --git a/ogr/ogr_srs_pci.cpp b/ogr/ogr_srs_pci.cpp
index 7cc133b..b5c811d 100644
--- a/ogr/ogr_srs_pci.cpp
+++ b/ogr/ogr_srs_pci.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_pci.cpp 21468 2011-01-12 20:35:14Z warmerdam $
+ * $Id: ogr_srs_pci.cpp 22898 2011-08-07 20:31:33Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from PCI georeferencing
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogr_srs_pci.cpp 21468 2011-01-12 20:35:14Z warmerdam $");
+CPL_CVSID("$Id: ogr_srs_pci.cpp 22898 2011-08-07 20:31:33Z rouault $");
 
 typedef struct 
 {
@@ -630,6 +630,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                         }
                         CSLDestroy( papszLineItems );
                     }
+                    CSLDestroy( papszLineItems );
                     
                     VSIFClose( fp );
                 }
@@ -718,6 +719,8 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                             CPLAtof(papszDatumDefn[5]) );
             }
         }
+
+        CSLDestroy(papszDatumDefn);
     }
 
 /* -------------------------------------------------------------------- */
@@ -1208,6 +1211,8 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
                         strncpy( szEarthModel, papszLineItems[0], 5 );
                         break;
                     }
+
+                    CSLDestroy( papszLineItems );
                 }
 
                 CSLDestroy( papszLineItems );
diff --git a/ogr/ogr_srs_proj4.cpp b/ogr/ogr_srs_proj4.cpp
index 3f85cb5..978dce7 100644
--- a/ogr/ogr_srs_proj4.cpp
+++ b/ogr/ogr_srs_proj4.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_proj4.cpp 20655 2010-09-20 16:26:08Z warmerdam $
+ * $Id: ogr_srs_proj4.cpp 23620 2011-12-20 23:14:29Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference interface to PROJ.4.
@@ -33,7 +33,7 @@
 
 extern int EPSGGetWGS84Transform( int nGeogCS, double *padfTransform );
 
-CPL_CVSID("$Id: ogr_srs_proj4.cpp 20655 2010-09-20 16:26:08Z warmerdam $");
+CPL_CVSID("$Id: ogr_srs_proj4.cpp 23620 2011-12-20 23:14:29Z rouault $");
 
 /* -------------------------------------------------------------------- */
 /*      The following list comes from osrs/proj/src/pj_ellps.c          */
@@ -456,6 +456,11 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     {
     }
     
+    else if( EQUAL(pszProj,"geocent") )
+    {
+        SetGeocCS( "Geocentric" );
+    }
+    
     else if( EQUAL(pszProj,"bonne") )
     {
         SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ), 
@@ -551,8 +556,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
-    else if( EQUALN(pszProj,"stere",5) /* mostly sterea */
-             && CSLFetchNameValue(papszNV,"k") != NULL )
+    else if( EQUAL(pszProj,"sterea") )
     {
         SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
                OSR_GDV( papszNV, "lon_0", 0.0 ), 
@@ -565,7 +569,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     {
         SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
                           OSR_GDV( papszNV, "lon_0", 0.0 ), 
-                          1.0, 
+                          OSR_GDV( papszNV, "k", 1.0 ),  
                           OSR_GDV( papszNV, "x_0", 0.0 ), 
                           OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
@@ -713,6 +717,11 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
 
+    else if( EQUAL(pszProj,"igh") )
+    {
+        SetIGH();
+    }
+
     else if( EQUAL(pszProj,"geos") )
     {
         SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
@@ -1026,7 +1035,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /* -------------------------------------------------------------------- */
 /*      Linear units translation                                        */
 /* -------------------------------------------------------------------- */
-    if( IsProjected() || IsLocal() )
+    if( IsProjected() || IsLocal() || IsGeocentric() )
     {
         pszValue = CSLFetchNameValue(papszNV, "to_meter");
 
@@ -1123,6 +1132,83 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Handle vertical units.                                          */
+/* -------------------------------------------------------------------- */
+    if( GetRoot()->GetNode( "VERT_CS" ) != NULL )
+    {
+        const char *pszUnitName = NULL;
+        const char *pszUnitConv = NULL;
+
+        pszValue = CSLFetchNameValue(papszNV, "vto_meter");
+
+        if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
+        {
+            double dfValue = CPLAtofM(pszValue);
+
+            if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
+            {
+                pszUnitName = SRS_UL_US_FOOT;
+                pszUnitConv = SRS_UL_US_FOOT_CONV;
+            }
+            else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
+            {
+                pszUnitName = SRS_UL_FOOT;
+                pszUnitConv = SRS_UL_FOOT_CONV;
+            }
+            else if( dfValue == 1.0 )
+            {
+                pszUnitName = SRS_UL_METER;
+                pszUnitConv = "1.0";
+            }
+            else
+            {
+                pszUnitName = "unknown";
+                pszUnitConv = pszValue;
+            }
+        }
+        else if( (pszValue = CSLFetchNameValue(papszNV, "vunits")) != NULL )
+        {
+            if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") )
+            {
+                pszUnitName = SRS_UL_METER;
+                pszUnitConv = "1.0";
+            }
+            else if( EQUAL(pszValue,"us-ft" ) )
+            {
+                pszUnitName = SRS_UL_US_FOOT;
+                pszUnitConv = SRS_UL_US_FOOT_CONV;
+            }
+            else if( EQUAL(pszValue,"ft" ) )
+            {
+                pszUnitName = SRS_UL_FOOT;
+                pszUnitConv = SRS_UL_FOOT_CONV;
+            }
+            else if( EQUAL(pszValue,"yd" ) )
+            {
+                pszUnitName = "Yard";
+                pszUnitConv = "0.9144";
+            }
+            else if( EQUAL(pszValue,"us-yd" ) )
+            {
+                pszUnitName = "US Yard";
+                pszUnitConv = "0.914401828803658";
+            }
+        }
+
+        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 );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      do we want to insert a PROJ.4 EXTENSION item?                   */
 /* -------------------------------------------------------------------- */
     if( strstr(pszProj4,"wktext") != NULL )
@@ -1133,6 +1219,53 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     return OGRERR_NONE;
 }
 
+/************************************************************************/
+/*                           LinearToProj4()                            */
+/************************************************************************/
+
+static const char *LinearToProj4( double dfLinearConv, 
+                                  const char *pszLinearUnits )
+
+{
+    if( dfLinearConv == 1.0 )
+        return "m";
+
+    else if( dfLinearConv == 1000.0 )
+        return "km";
+    
+    else if( dfLinearConv == 0.0254 )
+        return "in";
+    
+    else if( EQUAL(pszLinearUnits,SRS_UL_FOOT) 
+             || fabs(dfLinearConv - atof(SRS_UL_FOOT_CONV)) < 0.000000001 )
+        return "ft";
+    
+    else if( EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 )
+        return "yd";
+
+    else if( dfLinearConv == 0.914401828803658 )
+        return "us-yd";
+    
+    else if( dfLinearConv == 0.001 )
+        return "mm";
+    
+    else if( dfLinearConv == 0.01 )
+        return "cm";
+
+    else if( EQUAL(pszLinearUnits,SRS_UL_US_FOOT) 
+             || fabs(dfLinearConv - atof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
+        return "us-ft";
+
+    else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
+        return "kmi";
+
+    else if( EQUAL(pszLinearUnits,"Mile") 
+             || EQUAL(pszLinearUnits,"IMILE") )
+        return "mi";
+    else
+        return NULL;
+}
+
 
 /************************************************************************/
 /*                          OSRExportToProj4()                          */
@@ -1157,6 +1290,13 @@ OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS,
 /*                           exportToProj4()                            */
 /************************************************************************/
 
+#define SAFE_PROJ4_STRCAT(szNewStr)  do { \
+    if(CPLStrlcat(szProj4, szNewStr, sizeof(szProj4)) >= sizeof(szProj4)) { \
+        CPLError(CE_Failure, CPLE_AppDefined, "String overflow when formatting proj.4 string"); \
+        *ppszProj4 = CPLStrdup(""); \
+        return OGRERR_FAILURE; \
+    } } while(0);
+
 /**
  * \brief Export coordinate system in PROJ.4 format.
  *
@@ -1175,13 +1315,6 @@ OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS,
  * @return OGRERR_NONE on success or an error code on failure. 
  */
 
-#define SAFE_PROJ4_STRCAT(szNewStr)  do { \
-    if(CPLStrlcat(szProj4, szNewStr, sizeof(szProj4)) >= sizeof(szProj4)) { \
-        CPLError(CE_Failure, CPLE_AppDefined, "String overflow when formatting proj.4 string"); \
-        *ppszProj4 = CPLStrdup(""); \
-        return OGRERR_FAILURE; \
-    } } while(0);
-
 OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
 {
@@ -1230,6 +1363,11 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     {
         sprintf( szProj4+strlen(szProj4), "+proj=longlat " );
     }
+    else if( IsGeocentric() )
+    {
+        sprintf( szProj4+strlen(szProj4), "+proj=geocent " );
+    }
+
     else if( pszProjection == NULL && !IsGeographic() )
     {
         // LOCAL_CS, or incompletely initialized coordinate systems.
@@ -1613,6 +1751,11 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
     }
 
+    else if( EQUAL(pszProjection,SRS_PT_IGH) )
+    {
+        sprintf( szProj4+strlen(szProj4), "+proj=igh " );
+    }
+
     else if( EQUAL(pszProjection,SRS_PT_GEOSTATIONARY_SATELLITE) )
     {
         sprintf( szProj4+strlen(szProj4),
@@ -1920,12 +2063,12 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     {
         pszPROJ4Ellipse = "WGS84";
     }
-    else if( EQUAL(pszDatum,"North_American_Datum_1927") )
+    else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1927") )
     {
 //        pszPROJ4Ellipse = "clrk66:+datum=nad27"; /* NAD 27 */
         pszPROJ4Ellipse = "clrk66";
     }
-    else if( EQUAL(pszDatum,"North_American_Datum_1983") )
+    else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1983") )
     {
 //        pszPROJ4Ellipse = "GRS80:+datum=nad83";       /* NAD 83 */
         pszPROJ4Ellipse = "GRS80";
@@ -2110,47 +2253,18 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         
     if( strstr(szProj4,"longlat") != NULL )
         pszPROJ4Units = NULL;
-    
-    else if( dfLinearConv == 1.0 )
-        pszPROJ4Units = "m";
-
-    else if( dfLinearConv == 1000.0 )
-        pszPROJ4Units = "km";
-    
-    else if( dfLinearConv == 0.0254 )
-        pszPROJ4Units = "in";
-    
-    else if( EQUAL(pszLinearUnits,SRS_UL_FOOT) 
-             || fabs(dfLinearConv - atof(SRS_UL_FOOT_CONV)) < 0.000000001 )
-        pszPROJ4Units = "ft";
-    
-    else if( EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 )
-        pszPROJ4Units = "yd";
-    
-    else if( dfLinearConv == 0.001 )
-        pszPROJ4Units = "mm";
-    
-    else if( dfLinearConv == 0.01 )
-        pszPROJ4Units = "cm";
-
-    else if( EQUAL(pszLinearUnits,SRS_UL_US_FOOT) 
-             || fabs(dfLinearConv - atof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
-        pszPROJ4Units = "us-ft";
-
-    else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
-        pszPROJ4Units = "kmi";
-
-    else if( EQUAL(pszLinearUnits,"Mile") 
-             || EQUAL(pszLinearUnits,"IMILE") )
-        pszPROJ4Units = "mi";
-
-    else
+    else 
     {
-        char szLinearConv[128];
-        sprintf( szLinearConv, "%.16g", dfLinearConv );
-        SAFE_PROJ4_STRCAT( "+to_meter=" );
-        SAFE_PROJ4_STRCAT( szLinearConv );
-        SAFE_PROJ4_STRCAT( " " );
+        pszPROJ4Units = LinearToProj4( dfLinearConv, pszLinearUnits );
+
+        if( pszPROJ4Units == NULL )
+        {
+            char szLinearConv[128];
+            sprintf( szLinearConv, "%.16g", dfLinearConv );
+            SAFE_PROJ4_STRCAT( "+to_meter=" );
+            SAFE_PROJ4_STRCAT( szLinearConv );
+            SAFE_PROJ4_STRCAT( " " );
+        }
     }
 
     if( pszPROJ4Units != NULL )
@@ -2173,6 +2287,40 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     }    
 
 /* -------------------------------------------------------------------- */
+/*      Handle vertical units, but only if we have them.                */
+/* -------------------------------------------------------------------- */
+    const OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
+    const OGR_SRSNode *poVUNITS = NULL;
+
+    if( poVERT_CS != NULL )
+        poVUNITS = poVERT_CS->GetNode( "UNIT" );
+
+    if( poVUNITS != NULL && poVUNITS->GetChildCount() >= 2 )
+    {
+        pszPROJ4Units = NULL;
+
+        dfLinearConv = CPLAtof( poVUNITS->GetChild(1)->GetValue() );
+        
+        pszPROJ4Units = LinearToProj4( dfLinearConv,
+                                       poVUNITS->GetChild(0)->GetValue() );
+            
+        if( pszPROJ4Units == NULL )
+        {
+            char szLinearConv[128];
+            sprintf( szLinearConv, "%.16g", dfLinearConv );
+            SAFE_PROJ4_STRCAT( "+vto_meter=" );
+            SAFE_PROJ4_STRCAT( szLinearConv );
+            SAFE_PROJ4_STRCAT( " " );
+        }
+        else
+        {
+            SAFE_PROJ4_STRCAT( "+vunits=");
+            SAFE_PROJ4_STRCAT( pszPROJ4Units );
+            SAFE_PROJ4_STRCAT( " " );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Add the no_defs flag to ensure that no values from              */
 /*      proj_def.dat are implicitly used with our definitions.          */
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogr_srs_validate.cpp b/ogr/ogr_srs_validate.cpp
index 4672b78..dc844ae 100644
--- a/ogr/ogr_srs_validate.cpp
+++ b/ogr/ogr_srs_validate.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_validate.cpp 20665 2010-09-21 19:15:11Z rouault $
+ * $Id: ogr_srs_validate.cpp 22786 2011-07-23 21:17:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of the OGRSpatialReference::Validate() method and
@@ -31,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogr_srs_validate.cpp 20665 2010-09-21 19:15:11Z rouault $");
+CPL_CVSID("$Id: ogr_srs_validate.cpp 22786 2011-07-23 21:17:24Z rouault $");
 
 /* why would fipszone and zone be paramers when they relate to a composite
    projection which renders done into a non-zoned projection? */
@@ -89,6 +89,7 @@ static const char *papszProjectionSupported[] =
     SRS_PT_ECKERT_VI,
     SRS_PT_MERCATOR_1SP,
     SRS_PT_MERCATOR_2SP,
+    SRS_PT_MOLLWEIDE,
     SRS_PT_ROBINSON,
     SRS_PT_ALBERS_CONIC_EQUAL_AREA,
     SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
@@ -109,6 +110,7 @@ static const char *papszProjectionSupported[] =
     SRS_PT_SINUSOIDAL,
     SRS_PT_STEREOGRAPHIC,
     SRS_PT_GNOMONIC,
+    SRS_PT_GALL_STEREOGRAPHIC,
     SRS_PT_ORTHOGRAPHIC,
     SRS_PT_POLYCONIC,
     SRS_PT_VANDERGRINTEN,
@@ -125,6 +127,8 @@ static const char *papszProjectionSupported[] =
     SRS_PT_GAUSSSCHREIBERTMERCATOR,
     SRS_PT_KROVAK,
     SRS_PT_CYLINDRICAL_EQUAL_AREA,
+    SRS_PT_GOODE_HOMOLOSINE, 
+    SRS_PT_IGH,
     NULL
 };
 
@@ -209,12 +213,36 @@ static const char *papszProjWithParms[] = {
     SRS_PP_FALSE_NORTHING,
     NULL,
 
+    SRS_PT_ECKERT_I,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
+    SRS_PP_FALSE_NORTHING,
+    NULL,
+
+    SRS_PT_ECKERT_II,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
+    SRS_PP_FALSE_NORTHING,
+    NULL,
+
+    SRS_PT_ECKERT_III,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
+    SRS_PP_FALSE_NORTHING,
+    NULL,
+
     SRS_PT_ECKERT_IV,
     SRS_PP_CENTRAL_MERIDIAN,
     SRS_PP_FALSE_EASTING,
     SRS_PP_FALSE_NORTHING,
     NULL,
 
+    SRS_PT_ECKERT_V,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
+    SRS_PP_FALSE_NORTHING,
+    NULL,
+
     SRS_PT_ECKERT_VI,
     SRS_PP_CENTRAL_MERIDIAN,
     SRS_PP_FALSE_EASTING,
@@ -473,6 +501,15 @@ static const char *papszProjWithParms[] = {
     SRS_PP_FALSE_NORTHING,
     NULL,
 
+    SRS_PT_GOODE_HOMOLOSINE,
+    SRS_PP_CENTRAL_MERIDIAN,
+    SRS_PP_FALSE_EASTING,
+    SRS_PP_FALSE_NORTHING,
+    NULL,
+
+    SRS_PT_IGH,
+    NULL,
+
     NULL
 };
 
@@ -659,6 +696,104 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
     }
 
 /* -------------------------------------------------------------------- */
+/*      Validate GEOCCS                                                 */
+/* -------------------------------------------------------------------- */
+    if( EQUAL(poRoot->GetValue(),"GEOCCS") )
+    {
+        OGR_SRSNode     *poNode;
+        int             i;
+        int             bGotDatum = FALSE;
+        int             bGotPrimeM = FALSE;
+        int             bGotUnit = FALSE;
+        int             nCountAxis = 0;
+
+        for( i = 1; i < poRoot->GetChildCount(); i++ )
+        {
+            poNode = poRoot->GetChild(i);
+
+            if( EQUAL(poNode->GetValue(),"DATUM") )
+            {
+                bGotDatum = TRUE;
+            }
+            else if( EQUAL(poNode->GetValue(),"PRIMEM") )
+            {
+                bGotPrimeM = TRUE;
+
+                if( poNode->GetChildCount() < 2 
+                    || poNode->GetChildCount() > 3 )
+                {
+                    CPLDebug( "OGRSpatialReference::Validate",
+                              "PRIMEM has wrong number of children (%d),"
+                              "not 2 or 3 as expected.\n",
+                              poNode->GetChildCount() );
+                    
+                    return OGRERR_CORRUPT_DATA;
+                }
+            }
+            else if( EQUAL(poNode->GetValue(),"UNIT") )
+            {
+                OGRErr eErr = ValidateUnit(poNode);
+                if (eErr != OGRERR_NONE)
+                    return eErr;
+                bGotUnit = TRUE;
+            }
+            else if( EQUAL(poNode->GetValue(),"AXIS") )
+            {
+                OGRErr eErr = ValidateAxis(poNode);
+                if (eErr != OGRERR_NONE)
+                    return eErr;
+                nCountAxis ++;
+            }
+            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+            {
+                OGRErr eErr = ValidateAuthority(poNode);
+                if (eErr != OGRERR_NONE)
+                    return eErr;
+            }
+            else
+            {
+                CPLDebug( "OGRSpatialReference::Validate",
+                          "Unexpected child for GEOCCS `%s'.\n",
+                          poNode->GetValue() );
+
+                return OGRERR_CORRUPT_DATA;
+            }
+        }
+
+        if (!bGotDatum)
+        {
+            CPLDebug( "OGRSpatialReference::Validate",
+                      "No DATUM child in GEOCCS.\n" );
+
+            return OGRERR_CORRUPT_DATA;
+        }
+
+        if (!bGotPrimeM)
+        {
+            CPLDebug( "OGRSpatialReference::Validate",
+                      "No PRIMEM child in GEOCCS.\n" );
+
+            return OGRERR_CORRUPT_DATA;
+        }
+
+        if (!bGotUnit)
+        {
+            CPLDebug( "OGRSpatialReference::Validate",
+                      "No UNIT child in GEOCCS.\n" );
+
+            return OGRERR_CORRUPT_DATA;
+        }
+
+        if (nCountAxis != 0 && nCountAxis != 3 )
+        {
+            CPLDebug( "OGRSpatialReference::Validate",
+                      "Wrong number of AXIS children in GEOCCS.\n" );
+
+            return OGRERR_CORRUPT_DATA;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      For a PROJCS, validate subparameters (other than GEOGCS).       */
 /* -------------------------------------------------------------------- */
     if( EQUAL(poRoot->GetValue(),"PROJCS") )
@@ -941,12 +1076,6 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
     if( eErr != OGRERR_NONE )
         return eErr;
 
-/* -------------------------------------------------------------------- */
-/*      Final check.                                                    */
-/* -------------------------------------------------------------------- */
-    if( EQUAL(poRoot->GetValue(),"GEOCCS") )
-        return OGRERR_UNSUPPORTED_SRS;
-
     return OGRERR_NONE;
 }
 
diff --git a/ogr/ogr_srsnode.cpp b/ogr/ogr_srsnode.cpp
index 0cb8bba..3cdc601 100644
--- a/ogr/ogr_srsnode.cpp
+++ b/ogr/ogr_srsnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srsnode.cpp 20835 2010-10-15 20:00:50Z rouault $
+ * $Id: ogr_srsnode.cpp 23521 2011-12-10 23:04:17Z etourigny $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGR_SRSNode class.
@@ -30,7 +30,7 @@
 #include "ogr_spatialref.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogr_srsnode.cpp 20835 2010-10-15 20:00:50Z rouault $");
+CPL_CVSID("$Id: ogr_srsnode.cpp 23521 2011-12-10 23:04:17Z etourigny $");
 
 /************************************************************************/
 /*                            OGR_SRSNode()                             */
@@ -646,6 +646,10 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput )
 
             AddChild( poNewChild );
             
+            // swallow whitespace
+            while( isspace(*pszInput) ) 
+                pszInput++;
+
         } while( *pszInput == ',' );
 
         if( *pszInput != ')' && *pszInput != ']' )
@@ -765,7 +769,8 @@ OGRErr OGR_SRSNode::applyRemapper( const char *pszNode,
     {
         for( i = 0; papszSrcValues[i] != NULL; i += nStepSize )
         {
-            if( EQUAL(papszSrcValues[i],pszValue) )
+            if( EQUAL(papszSrcValues[i],pszValue) && 
+                ! EQUAL(papszDstValues[i],"") )
             {
                 SetValue( papszDstValues[i] );
                 break;
@@ -850,8 +855,11 @@ static const char * const apszDATUMRule[] =
 static const char * const apszGEOGCSRule[] = 
 { "GEOGCS", "DATUM", "PRIMEM", "UNIT", "AXIS", "AUTHORITY", NULL };
 
+static const char * const apszGEOCCSRule[] = 
+{ "GEOCCS", "DATUM", "PRIMEM", "UNIT", "AXIS", "AUTHORITY", NULL };
+
 static const char * const *apszOrderingRules[] = {
-    apszPROJCSRule, apszGEOGCSRule, apszDATUMRule, NULL };
+    apszPROJCSRule, apszGEOGCSRule, apszDATUMRule, apszGEOCCSRule, NULL };
 
 OGRErr OGR_SRSNode::FixupOrdering()
 
diff --git a/ogr/ograssemblepolygon.cpp b/ogr/ograssemblepolygon.cpp
index 3b7ee6b..dace951 100644
--- a/ogr/ograssemblepolygon.cpp
+++ b/ogr/ograssemblepolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograssemblepolygon.cpp 19790 2010-06-01 15:46:20Z warmerdam $
+ * $Id: ograssemblepolygon.cpp 23327 2011-11-05 20:03:42Z rouault $
  *
  * Project:  S-57 Reader
  * Purpose:  Implements polygon assembly from a bunch of arcs.
@@ -27,11 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include <vector>
 #include "ogr_geometry.h"
 #include "ogr_api.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograssemblepolygon.cpp 19790 2010-06-01 15:46:20Z warmerdam $");
+CPL_CVSID("$Id: ograssemblepolygon.cpp 23327 2011-11-05 20:03:42Z rouault $");
 
 /************************************************************************/
 /*                            CheckPoints()                             */
@@ -178,7 +179,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 
     int         bSuccess = TRUE;
     OGRGeometryCollection *poLines = (OGRGeometryCollection *) hLines;
-    OGRPolygon  *poPolygon = new OGRPolygon();
+    std::vector<OGRLinearRing*> aoRings;
 
     (void) bBestEffort;
 
@@ -206,6 +207,14 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 
         poLine = (OGRLineString *) poLines->getGeometryRef(iEdge);
 
+        panEdgeConsumed[iEdge] = TRUE;
+        nRemainingEdges--;
+
+        if (poLine->getNumPoints() < 2)
+        {
+            continue;
+        }
+
 /* -------------------------------------------------------------------- */
 /*      Start a new ring, copying in the current line directly          */
 /* -------------------------------------------------------------------- */
@@ -213,9 +222,6 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
         
         AddEdgeToRing( poRing, poLine, FALSE );
 
-        panEdgeConsumed[iEdge] = TRUE;
-        nRemainingEdges--;
-        
 /* ==================================================================== */
 /*      Loop adding edges to this ring until we make a whole pass       */
 /*      within finding anything to add.                                 */
@@ -244,7 +250,9 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
                     continue;
 
                 poLine = (OGRLineString *) poLines->getGeometryRef(iEdge);
-                
+                if (poLine->getNumPoints() < 2)
+                    continue;
+
                 if( CheckPoints(poLine,0,poRing,poRing->getNumPoints()-1,
                                 &dfBestDist) )
                 {
@@ -288,7 +296,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
             CPLDebug( "OGR", 
                       "Failed to close ring %d.\n"
                       "End Points are: (%.8f,%.7f) and (%.7f,%.7f)\n",
-                      poPolygon->getNumInteriorRings()+1,
+                      (int)aoRings.size(),
                       poRing->getX(0), poRing->getY(0), 
                       poRing->getX(poRing->getNumPoints()-1), 
                       poRing->getY(poRing->getNumPoints()-1) );
@@ -307,7 +315,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
                               poRing->getZ(0));
         }
 
-        poPolygon->addRingDirectly( poRing );
+        aoRings.push_back(poRing);
     } /* next ring */
 
 /* -------------------------------------------------------------------- */
@@ -318,40 +326,33 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 /* -------------------------------------------------------------------- */
 /*      Identify exterior ring - it will be the largest.  #3610         */
 /* -------------------------------------------------------------------- */
-    double maxarea, tarea;
-    int maxring = -1, rn, rcount;
+    double maxarea = 0.0;
+    int maxring = -1, rn;
     OGREnvelope tenv;
-    OGRLinearRing *tring;
-
-    tring = poPolygon->getExteriorRing();
-    if (tring) tring->getEnvelope(&tenv);
-    maxarea = (tenv.MaxX - tenv.MinX) * (tenv.MaxY - tenv.MinY);
-
-    rcount = poPolygon->getNumInteriorRings();
-    for (rn = 0; rn < rcount; ++rn) {
-        tring = poPolygon->getInteriorRing(rn);
-        tring->getEnvelope(&tenv);
-        tarea = (tenv.MaxX - tenv.MinX) * (tenv.MaxY - tenv.MinY);
-        if (tarea > maxarea) {
+
+    for (rn = 0; rn < (int)aoRings.size(); ++rn)
+    {
+        aoRings[rn]->getEnvelope(&tenv);
+        double tarea = (tenv.MaxX - tenv.MinX) * (tenv.MaxY - tenv.MinY);
+        if (tarea > maxarea)
+        {
             maxarea = tarea;
             maxring = rn;
         }
     }
 
-    if (maxring != -1) {
-        OGRPolygon  *poNewPoly = new OGRPolygon();
+    OGRPolygon  *poPolygon = new OGRPolygon();
 
-        poNewPoly->addRing(poPolygon->getInteriorRing(maxring));
-        poNewPoly->addRing(poPolygon->getExteriorRing());
-        for (rn = 0; rn < rcount; ++rn) {
+    if (maxring != -1)
+    {
+        poPolygon->addRingDirectly(aoRings[maxring]);
+        for (rn = 0; rn < (int)aoRings.size(); ++rn)
+        {
             if (rn == maxring) continue;
-            poNewPoly->addRing(poPolygon->getInteriorRing(rn));
+            poPolygon->addRingDirectly(aoRings[rn]);
         }
+    }
 
-        delete poPolygon;
-        poPolygon = poNewPoly;
-    } 
-      
     if( peErr != NULL )
     {
         if( bSuccess )
diff --git a/ogr/ogrfeature.cpp b/ogr/ogrfeature.cpp
index c96f353..9af2281 100644
--- a/ogr/ogrfeature.cpp
+++ b/ogr/ogrfeature.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeature.cpp 21270 2010-12-15 22:48:30Z warmerdam $
+ * $Id: ogrfeature.cpp 23606 2011-12-19 23:55:18Z warmerdam $
  * 
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFeature class implementation. 
@@ -32,7 +32,7 @@
 #include "ogr_p.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrfeature.cpp 21270 2010-12-15 22:48:30Z warmerdam $");
+CPL_CVSID("$Id: ogrfeature.cpp 23606 2011-12-19 23:55:18Z warmerdam $");
 
 /************************************************************************/
 /*                             OGRFeature()                             */
@@ -763,7 +763,6 @@ void OGRFeature::UnsetField( int iField )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL || !IsFieldSet(iField) )
         return;
     
@@ -898,7 +897,6 @@ int OGRFeature::GetFieldAsInteger( int iField )
     
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
     
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return 0;
     
@@ -989,7 +987,6 @@ double OGRFeature::GetFieldAsDouble( int iField )
     
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
     
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return 0.0;
 
@@ -1114,7 +1111,6 @@ const char *OGRFeature::GetFieldAsString( int iField )
     
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
     
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return "";
     
@@ -1375,7 +1371,6 @@ const int *OGRFeature::GetFieldAsIntegerList( int iField, int *pnCount )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn != NULL && IsFieldSet(iField) &&
         poFDefn->GetType() == OFTIntegerList )
     {
@@ -1447,7 +1442,6 @@ const double *OGRFeature::GetFieldAsDoubleList( int iField, int *pnCount )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn != NULL && IsFieldSet(iField) &&
         poFDefn->GetType() == OFTRealList )
     {
@@ -1520,7 +1514,6 @@ char **OGRFeature::GetFieldAsStringList( int iField ) const
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return NULL;
     
@@ -1592,7 +1585,6 @@ GByte *OGRFeature::GetFieldAsBinary( int iField, int *pnBytes )
 
     *pnBytes = 0;
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return NULL;
     
@@ -1670,7 +1662,6 @@ int OGRFeature::GetFieldAsDateTime( int iField,
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return FALSE;
     
@@ -1767,10 +1758,9 @@ void OGRFeature::SetField( int iField, int nValue )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
-    
+
     if( poFDefn->GetType() == OFTInteger )
     {
         pauFields[iField].Integer = nValue;
@@ -1780,6 +1770,15 @@ void OGRFeature::SetField( int iField, int nValue )
     {
         pauFields[iField].Real = nValue;
     }
+    else if( poFDefn->GetType() == OFTIntegerList )
+    {
+        SetField( iField, 1, &nValue );
+    }
+    else if( poFDefn->GetType() == OFTRealList )
+    {
+        double dfValue = nValue;
+        SetField( iField, 1, &dfValue );
+    }
     else if( poFDefn->GetType() == OFTString )
     {
         char    szTempBuffer[64];
@@ -1845,7 +1844,6 @@ void OGRFeature::SetField( int iField, double dfValue )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -1858,6 +1856,15 @@ void OGRFeature::SetField( int iField, double dfValue )
         pauFields[iField].Integer = (int) dfValue;
         pauFields[iField].Set.nMarker2 = 0;
     }
+    else if( poFDefn->GetType() == OFTRealList )
+    {
+        SetField( iField, 1, &dfValue );
+    }
+    else if( poFDefn->GetType() == OFTIntegerList )
+    {
+        int nValue = (int) dfValue;
+        SetField( iField, 1, &nValue );
+    }
     else if( poFDefn->GetType() == OFTString )
     {
         char    szTempBuffer[128];
@@ -1922,7 +1929,6 @@ void OGRFeature::SetField( int iField, const char * pszValue )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -1982,7 +1988,7 @@ void OGRFeature::SetField( int iField, const char * pszValue )
             std::vector<double> adfValues;
 
             for( i=0; i < nCount; i++ )
-                adfValues.push_back( atoi(papszValueList[i+1]) );
+                adfValues.push_back( atof(papszValueList[i+1]) );
             SetField( iField, nCount, &(adfValues[0]) );
         }
 
@@ -2039,7 +2045,6 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -2053,6 +2058,20 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
 
         SetField( iField, &uField );
     }
+    else if( poFDefn->GetType() == OFTRealList )
+    {
+        std::vector<double> adfValues;
+
+        for( int i=0; i < nCount; i++ )
+            adfValues.push_back( (double) panValues[i] );
+
+        SetField( iField, nCount, &adfValues[0] );
+    }
+    else if( (poFDefn->GetType() == OFTInteger || poFDefn->GetType() == OFTReal)
+             && nCount == 1 )
+    {
+        SetField( iField, panValues[0] );
+    }
 }
 
 /************************************************************************/
@@ -2102,7 +2121,6 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -2116,6 +2134,20 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
         
         SetField( iField, &uField );
     }
+    else if( poFDefn->GetType() == OFTIntegerList )
+    {
+        std::vector<int> anValues;
+
+        for( int i=0; i < nCount; i++ )
+            anValues.push_back( (int) padfValues[i] );
+
+        SetField( iField, nCount, &anValues[0] );
+    }
+    else if( (poFDefn->GetType() == OFTInteger || poFDefn->GetType() == OFTReal)
+             && nCount == 1 )
+    {
+        SetField( iField, padfValues[0] );
+    }
 }
 
 /************************************************************************/
@@ -2164,7 +2196,6 @@ void OGRFeature::SetField( int iField, char ** papszValues )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -2226,7 +2257,6 @@ void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -2297,7 +2327,6 @@ void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -2372,7 +2401,6 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
 {
     OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
 
-    CPLAssert( poFDefn != NULL || iField == -1 );
     if( poFDefn == NULL )
         return;
     
@@ -3065,7 +3093,7 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
 
         if( iDstField < 0 )
             continue;
-            
+
         if( GetFieldCount() <= iDstField )
             return OGRERR_FAILURE;
 
@@ -3089,6 +3117,36 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
             SetField( iDstField, poSrcFeature->GetFieldAsString( iField ) );
             break;
 
+          case OFTIntegerList:
+          {
+              if (GetFieldDefnRef(iDstField)->GetType() == OFTString)
+              {
+                  SetField( iDstField, poSrcFeature->GetFieldAsString(iField) );
+              }
+              else
+              {
+                  int nCount;
+                  const int *panValues = poSrcFeature->GetFieldAsIntegerList( iField, &nCount);
+                  SetField( iDstField, nCount, (int*) panValues );
+              }
+          }
+          break;
+
+          case OFTRealList:
+          {
+              if (GetFieldDefnRef(iDstField)->GetType() == OFTString)
+              {
+                  SetField( iDstField, poSrcFeature->GetFieldAsString(iField) );
+              }
+              else
+              {
+                  int nCount;
+                  const double *padfValues = poSrcFeature->GetFieldAsDoubleList( iField, &nCount);
+                  SetField( iDstField, nCount, (double*) padfValues );
+              }
+          }
+          break;
+
           case OFTDate:
           case OFTDateTime:
           case OFTTime:
@@ -3188,16 +3246,16 @@ OGRErr OGR_F_SetFromWithMap( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
 
 const char *OGRFeature::GetStyleString()
 {
-	int  iStyleFieldIndex;
+    int  iStyleFieldIndex;
 
-	if (m_pszStyleString)
-       return m_pszStyleString;
+    if (m_pszStyleString)
+        return m_pszStyleString;
 
-	iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
-	if (iStyleFieldIndex >= 0)
-       return GetFieldAsString(iStyleFieldIndex);
+    iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
+    if (iStyleFieldIndex >= 0)
+        return GetFieldAsString(iStyleFieldIndex);
 
-	return NULL;
+    return NULL;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrfeaturedefn.cpp b/ogr/ogrfeaturedefn.cpp
index e1f7d9a..67b5f66 100644
--- a/ogr/ogrfeaturedefn.cpp
+++ b/ogr/ogrfeaturedefn.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturedefn.cpp 21018 2010-10-30 11:30:51Z rouault $
+ * $Id: ogrfeaturedefn.cpp 22900 2011-08-07 20:47:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFeatureDefn class implementation.
@@ -31,7 +31,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrfeaturedefn.cpp 21018 2010-10-30 11:30:51Z rouault $");
+CPL_CVSID("$Id: ogrfeaturedefn.cpp 22900 2011-08-07 20:47:41Z rouault $");
 
 /************************************************************************/
 /*                           OGRFeatureDefn()                           */
@@ -324,6 +324,9 @@ OGRFieldDefnH OGR_FD_GetFieldDefn( OGRFeatureDefnH hDefn, int iField )
 /**
  * \brief Add a new field definition.
  *
+ * To add a new field definition to a layer definition, do not use this
+ * function directly, but use OGRLayer::CreateField() instead.
+ *
  * This method should only be called while there are no OGRFeature
  * objects in existance based on this OGRFeatureDefn.  The OGRFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
@@ -350,11 +353,14 @@ void OGRFeatureDefn::AddFieldDefn( OGRFieldDefn * poNewDefn )
 /**
  * \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_CreateField() instead.
+ *
  * This function  should only be called while there are no OGRFeature
  * objects in existance based on this OGRFeatureDefn.  The OGRFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
- * This function is the same as the C++ method OGRFeatureDefn::AddFieldDefn.
+ * This function is the same as the C++ method OGRFeatureDefn::AddFieldDefn().
  *
  * @param hDefn handle to the feature definition to add the field definition
  * to.
@@ -368,6 +374,151 @@ void OGR_FD_AddFieldDefn( OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField )
 }
 
 /************************************************************************/
+/*                           DeleteFieldDefn()                          */
+/************************************************************************/
+
+/**
+ * \brief Delete an existing field definition.
+ *
+ * To delete an existing field definition from a layer definition, do not use this
+ * function directly, but use OGRLayer::DeleteField() 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_DeleteFieldDefn().
+ *
+ * @param iField the index of the field defintion.
+ * @return OGRERR_NONE in case of success.
+ * @since OGR 1.9.0
+ */
+
+OGRErr OGRFeatureDefn::DeleteFieldDefn( int iField )
+
+{
+    if (iField < 0 || iField >= nFieldCount)
+        return OGRERR_FAILURE;
+
+    delete papoFieldDefn[iField];
+    papoFieldDefn[iField] = NULL;
+
+    if (iField < nFieldCount - 1)
+    {
+        memmove(papoFieldDefn + iField,
+                papoFieldDefn + iField + 1,
+                (nFieldCount - 1 - iField) * sizeof(void*));
+    }
+
+    nFieldCount--;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                       OGR_FD_DeleteFieldDefn()                       */
+/************************************************************************/
+
+/**
+ * \brief Delete an existing field definition.
+ *
+ * To delete an existing field definition from a layer definition, do not use this
+ * function directly, but use OGR_L_DeleteField() 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++ method OGRFeatureDefn::DeleteFieldDefn().
+ *
+ * @param hDefn handle to the feature definition.
+ * @param iField the index of the field defintion.
+ * @return OGRERR_NONE in case of success.
+ * @since OGR 1.9.0
+ */
+
+OGRErr OGR_FD_DeleteFieldDefn( OGRFeatureDefnH hDefn, int iField )
+
+{
+    return ((OGRFeatureDefn *) hDefn)->DeleteFieldDefn( iField );
+}
+
+/************************************************************************/
+/*                         ReorderFieldDefns()                          */
+/************************************************************************/
+
+/**
+ * \brief Reorder the field definitions in the array of the feature definition
+ *
+ * To reorder the field definitions in a layer definition, do not use this
+ * function directly, but use OGR_L_ReorderFields() 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_ReorderFieldDefns().
+ *
+ * @param panMap an array of GetFieldCount() elements which
+ * is a permutation of [0, GetFieldCount()-1]. panMap is such that,
+ * for each field definition at position i after reordering,
+ * its position before reordering was panMap[i].
+ * @return OGRERR_NONE in case of success.
+ * @since OGR 1.9.0
+ */
+
+OGRErr OGRFeatureDefn::ReorderFieldDefns( int* panMap )
+
+{
+    if (nFieldCount == 0)
+        return OGRERR_NONE;
+
+    OGRErr eErr = OGRCheckPermutation(panMap, nFieldCount);
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+    OGRFieldDefn** papoFieldDefnNew = (OGRFieldDefn**)
+        CPLMalloc(sizeof(OGRFieldDefn*) * nFieldCount);
+
+    for(int i=0;i<nFieldCount;i++)
+    {
+        papoFieldDefnNew[i] = papoFieldDefn[panMap[i]];
+    }
+
+    CPLFree(papoFieldDefn);
+    papoFieldDefn = papoFieldDefnNew;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                     OGR_FD_ReorderFieldDefns()                       */
+/************************************************************************/
+
+/**
+ * \brief Reorder the field definitions in the array of the feature definition
+ *
+ * To reorder the field definitions in a layer definition, do not use this
+ * function directly, but use OGR_L_ReorderFields() 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++ method OGRFeatureDefn::ReorderFieldDefns().
+ *
+ * @param hDefn handle to the feature definition.
+ * @param panMap an array of GetFieldCount() elements which
+ * is a permutation of [0, GetFieldCount()-1]. panMap is such that,
+ * for each field definition at position i after reordering,
+ * its position before reordering was panMap[i].
+ * @return OGRERR_NONE in case of success.
+ * @since OGR 1.9.0
+ */
+
+OGRErr OGR_FD_ReorderFieldDefn( OGRFeatureDefnH hDefn, int* panMap )
+
+{
+    return ((OGRFeatureDefn *) hDefn)->ReorderFieldDefns( panMap );
+}
+
+/************************************************************************/
 /*                            GetGeomType()                             */
 /************************************************************************/
 
diff --git a/ogr/ogrfeaturequery.cpp b/ogr/ogrfeaturequery.cpp
index 84c2f89..527d7d7 100644
--- a/ogr/ogrfeaturequery.cpp
+++ b/ogr/ogrfeaturequery.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturequery.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: ogrfeaturequery.cpp 23309 2011-11-03 20:58:33Z rouault $
  * 
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of simple SQL WHERE style attributes queries
@@ -34,7 +34,7 @@
 #include "ogr_p.h"
 #include "ogr_attrind.h"
 
-CPL_CVSID("$Id: ogrfeaturequery.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: ogrfeaturequery.cpp 23309 2011-11-03 20:58:33Z rouault $");
 
 /************************************************************************/
 /*     Support for special attributes (feature query and selection)     */
@@ -293,7 +293,10 @@ long *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer,
             switch( poFieldDefn->GetType() )
             {
               case OFTInteger:
-                sValue.Integer = psExpr->papoSubExpr[iIN]->int_value;
+                if (psExpr->papoSubExpr[iIN]->field_type == SWQ_FLOAT)
+                    sValue.Integer = (int) psExpr->papoSubExpr[iIN]->float_value;
+                else
+                    sValue.Integer = psExpr->papoSubExpr[iIN]->int_value;
                 break;
 
               case OFTReal:
@@ -326,7 +329,10 @@ long *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer,
     switch( poFieldDefn->GetType() )
     {
       case OFTInteger:
-        sValue.Integer = poValue->int_value;
+        if (poValue->field_type == SWQ_FLOAT)
+            sValue.Integer = (int) poValue->float_value;
+        else
+            sValue.Integer = poValue->int_value;
         break;
         
       case OFTReal:
diff --git a/ogr/ogrfeaturestyle.cpp b/ogr/ogrfeaturestyle.cpp
index d3380b2..f696947 100644
--- a/ogr/ogrfeaturestyle.cpp
+++ b/ogr/ogrfeaturestyle.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrfeaturestyle.cpp 21193 2010-12-04 17:13:26Z rouault $
+ * $Id: ogrfeaturestyle.cpp 23051 2011-09-04 17:59:02Z winkey $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Feature Representation string API
@@ -33,7 +33,7 @@
 #include "ogr_featurestyle.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrfeaturestyle.cpp 21193 2010-12-04 17:13:26Z rouault $");
+CPL_CVSID("$Id: ogrfeaturestyle.cpp 23051 2011-09-04 17:59:02Z winkey $");
 
 CPL_C_START
 void OGRFeatureStylePuller() {}
@@ -435,7 +435,7 @@ GBool OGRStyleMgr::AddStyle(const char *pszStyleName,
 /************************************************************************/
 
 /**
- * Add a style to the current style table.
+ * \brief Add a style to the current style table.
  *
  * This function is the same as the C++ method OGRStyleMgr::AddStyle().
  *
@@ -462,6 +462,19 @@ int OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName,
 /*                                                                          */
 /****************************************************************************/
 
+/**
+ * \brief Get the style string from the style manager.
+ *
+ * @param poFeature feature object from which to read the style or NULL to
+ *                  get the style string stored in the manager.
+ *
+ * @return the style string stored in the feature or the style string stored
+ *          in the style manager if poFeature is NULL
+ *
+ * NOTE: this method will call OGRStyleMgr::InitFromFeature() if poFeature is
+ *       not NULL and replace the style string stored in the style manager
+ */
+
 const char *OGRStyleMgr::GetStyleString(OGRFeature *poFeature)
 {
     if (poFeature == NULL)
@@ -470,6 +483,19 @@ const char *OGRStyleMgr::GetStyleString(OGRFeature *poFeature)
       return InitFromFeature(poFeature);
 }
 
+/****************************************************************************/
+/*            GBool OGRStyleMgr::AddPart(const char *pszPart)               */
+/*            Add a new part in the current style                           */
+/****************************************************************************/
+
+/**
+ * \brief Add a part (style string) to the current style.
+ *
+ * @param pszPart the style string defining the part to add.
+ *
+ * @return TRUE on success, FALSE on errors. 
+ */
+
 GBool OGRStyleMgr::AddPart(const char *pszPart)
 {
     char *pszTmp; 
@@ -1755,9 +1781,12 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
     for ( i = 0; i < nElements; i++ )
     {
         char    **papszStylePair =
-            CSLTokenizeString2( papszToken2[i], ":", CSLT_HONOURSTRINGS
-                                                     | CSLT_STRIPLEADSPACES
-                                                     | CSLT_STRIPENDSPACES );
+            CSLTokenizeString2( papszToken2[i], ":", 
+                                CSLT_HONOURSTRINGS 
+                                | CSLT_STRIPLEADSPACES
+                                | CSLT_STRIPENDSPACES 
+                                | CSLT_ALLOWEMPTYTOKENS );
+
         int     j, nTokens = CSLCount(papszStylePair);
 
         if ( nTokens < 1 || nTokens > 2 )
diff --git a/ogr/ogrgeomediageometry.cpp b/ogr/ogrgeomediageometry.cpp
new file mode 100644
index 0000000..e5bfb33
--- /dev/null
+++ b/ogr/ogrgeomediageometry.cpp
@@ -0,0 +1,404 @@
+/******************************************************************************
+ * $Id: ogrgeomediageometry.cpp 21561 2011-01-23 12:22:58Z 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>
+ *
+ * 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 "ogrgeomediageometry.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogrgeomediageometry.cpp 21561 2011-01-23 12:22:58Z rouault $");
+
+#define GEOMEDIA_POINT          0xC0
+#define GEOMEDIA_ORIENTED_POINT 0xC8
+#define GEOMEDIA_POLYLINE       0xC2
+#define GEOMEDIA_POLYGON        0xC3
+#define GEOMEDIA_BOUNDARY       0xC5
+#define GEOMEDIA_COLLECTION     0xC6
+#define GEOMEDIA_MULTILINE      0xCB
+#define GEOMEDIA_MULTIPOLYGON   0xCC
+
+/************************************************************************/
+/*                       OGRCreateFromGeomedia()                        */
+/************************************************************************/
+
+OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
+                              OGRGeometry **ppoGeom,
+                              int nBytes )
+
+{
+    *ppoGeom = NULL;
+
+    if( nBytes < 16 )
+        return OGRERR_FAILURE;
+
+    if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
+        return OGRERR_FAILURE;
+
+    int nGeomType = pabyGeom[0];
+    pabyGeom += 16;
+    nBytes -= 16;
+
+    if( nGeomType == GEOMEDIA_POINT ||
+        nGeomType == GEOMEDIA_ORIENTED_POINT )
+    {
+        if (nBytes < 3 * 8)
+            return OGRERR_FAILURE;
+
+        double dfX, dfY, dfZ;
+        memcpy(&dfX, pabyGeom, 8);
+        CPL_LSBPTR64(&dfX);
+        memcpy(&dfY, pabyGeom + 8, 8);
+        CPL_LSBPTR64(&dfY);
+        memcpy(&dfZ, pabyGeom + 16, 8);
+        CPL_LSBPTR64(&dfZ);
+
+        *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
+
+         return OGRERR_NONE;
+    }
+    else if ( nGeomType == GEOMEDIA_POLYLINE )
+    {
+        if (nBytes < 4)
+            return OGRERR_FAILURE;
+
+        int nPoints;
+        memcpy(&nPoints, pabyGeom, 4);
+        CPL_LSBPTR32(&nPoints);
+
+        pabyGeom += 4;
+        nBytes -= 4;
+
+        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
+            return OGRERR_FAILURE;
+
+        OGRLineString* poLS = new OGRLineString();
+        poLS->setNumPoints(nPoints);
+        int i;
+        for(i=0;i<nPoints;i++)
+        {
+            double dfX, dfY, dfZ;
+            memcpy(&dfX, pabyGeom, 8);
+            CPL_LSBPTR64(&dfX);
+            memcpy(&dfY, pabyGeom + 8, 8);
+            CPL_LSBPTR64(&dfY);
+            memcpy(&dfZ, pabyGeom + 16, 8);
+            CPL_LSBPTR64(&dfZ);
+
+            poLS->setPoint(i, dfX, dfY, dfZ);
+
+            pabyGeom += 24;
+        }
+
+        *ppoGeom = poLS;
+
+        return OGRERR_NONE;
+    }
+    else if ( nGeomType == GEOMEDIA_POLYGON )
+    {
+        if (nBytes < 4)
+            return OGRERR_FAILURE;
+
+        int nPoints;
+        memcpy(&nPoints, pabyGeom, 4);
+        CPL_LSBPTR32(&nPoints);
+
+        pabyGeom += 4;
+        nBytes -= 4;
+
+        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
+            return OGRERR_FAILURE;
+
+        OGRLinearRing* poRing = new OGRLinearRing();
+        poRing->setNumPoints(nPoints);
+        int i;
+        for(i=0;i<nPoints;i++)
+        {
+            double dfX, dfY, dfZ;
+            memcpy(&dfX, pabyGeom, 8);
+            CPL_LSBPTR64(&dfX);
+            memcpy(&dfY, pabyGeom + 8, 8);
+            CPL_LSBPTR64(&dfY);
+            memcpy(&dfZ, pabyGeom + 16, 8);
+            CPL_LSBPTR64(&dfZ);
+
+            poRing->setPoint(i, dfX, dfY, dfZ);
+
+            pabyGeom += 24;
+        }
+
+        OGRPolygon* poPoly = new OGRPolygon();
+        poPoly->addRingDirectly(poRing);
+        *ppoGeom = poPoly;
+
+        return OGRERR_NONE;
+    }
+    else if ( nGeomType == GEOMEDIA_BOUNDARY )
+    {
+        if (nBytes < 4)
+            return OGRERR_FAILURE;
+
+        int nExteriorSize;
+        memcpy(&nExteriorSize, pabyGeom, 4);
+        CPL_LSBPTR32(&nExteriorSize);
+
+        pabyGeom += 4;
+        nBytes -= 4;
+
+        if (nBytes < nExteriorSize)
+            return OGRERR_FAILURE;
+
+        OGRGeometry* poExteriorGeom = NULL;
+        if (OGRCreateFromGeomedia( pabyGeom, &poExteriorGeom, nExteriorSize ) != OGRERR_NONE)
+            return OGRERR_FAILURE;
+
+        if (poExteriorGeom->getGeometryType() != wkbPolygon)
+        {
+            delete poExteriorGeom;
+            return OGRERR_FAILURE;
+        }
+
+        pabyGeom += nExteriorSize;
+        nBytes -= nExteriorSize;
+
+        if (nBytes < 4)
+        {
+            delete poExteriorGeom;
+            return OGRERR_FAILURE;
+        }
+
+        int nInteriorSize;
+        memcpy(&nInteriorSize, pabyGeom, 4);
+        CPL_LSBPTR32(&nInteriorSize);
+
+        pabyGeom += 4;
+        nBytes -= 4;
+
+        if (nBytes < nInteriorSize)
+        {
+            delete poExteriorGeom;
+            return OGRERR_FAILURE;
+        }
+
+        OGRGeometry* poInteriorGeom = NULL;
+        if (OGRCreateFromGeomedia( pabyGeom, &poInteriorGeom, nInteriorSize ) != OGRERR_NONE)
+        {
+            delete poExteriorGeom;
+            return OGRERR_FAILURE;
+        }
+
+        if (poInteriorGeom->getGeometryType() == wkbPolygon)
+        {
+            ((OGRPolygon*)poExteriorGeom)->addRing(((OGRPolygon*)poInteriorGeom)->getExteriorRing());
+            delete poInteriorGeom;
+            *ppoGeom = poExteriorGeom;
+        }
+        else
+        {
+            delete poExteriorGeom;
+            delete poInteriorGeom;
+            return OGRERR_FAILURE;
+        }
+
+        return OGRERR_NONE;
+    }
+    else if ( nGeomType == GEOMEDIA_COLLECTION ||
+              nGeomType == GEOMEDIA_MULTILINE ||
+              nGeomType == GEOMEDIA_MULTIPOLYGON )
+    {
+        if (nBytes < 4)
+            return OGRERR_FAILURE;
+
+        int i;
+        int nParts;
+        memcpy(&nParts, pabyGeom, 4);
+        CPL_LSBPTR32(&nParts);
+
+        pabyGeom += 4;
+        nBytes -= 4;
+
+        if (nParts < 0 || nParts > INT_MAX / (4 + 16) || nBytes < nParts * (4 + 16))
+            return OGRERR_FAILURE;
+
+        /* Can this collection be considered as a multipolyline or multipolygon ? */
+        if ( nGeomType == GEOMEDIA_COLLECTION )
+        {
+            GByte* pabyGeomBackup = pabyGeom;
+            int nBytesBackup = nBytes;
+
+            int bAllPolyline = TRUE;
+            int bAllPolygon = TRUE;
+
+            for(i=0;i<nParts;i++)
+            {
+                if (nBytes < 4)
+                    return OGRERR_FAILURE;
+                int nSubBytes;
+                memcpy(&nSubBytes, pabyGeom, 4);
+                CPL_LSBPTR32(&nSubBytes);
+
+                if (nSubBytes < 0)
+                {
+                    return OGRERR_FAILURE;
+                }
+
+                pabyGeom += 4;
+                nBytes -= 4;
+
+                if (nBytes < nSubBytes)
+                {
+                    return OGRERR_FAILURE;
+                }
+
+                if( nSubBytes < 16 )
+                    return OGRERR_FAILURE;
+
+                if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
+                    return OGRERR_FAILURE;
+
+                int nSubGeomType = pabyGeom[0];
+                if ( nSubGeomType != GEOMEDIA_POLYLINE )
+                    bAllPolyline = FALSE;
+                if ( nSubGeomType != GEOMEDIA_POLYGON )
+                    bAllPolygon = FALSE;
+
+                pabyGeom += nSubBytes;
+                nBytes -= nSubBytes;
+            }
+
+            pabyGeom = pabyGeomBackup;
+            nBytes = nBytesBackup;
+
+            if (bAllPolyline)
+                nGeomType = GEOMEDIA_MULTILINE;
+            else if (bAllPolygon)
+                nGeomType = GEOMEDIA_MULTIPOLYGON;
+        }
+
+        OGRGeometryCollection* poColl = (nGeomType == GEOMEDIA_MULTILINE) ? new OGRMultiLineString() :
+                                        (nGeomType == GEOMEDIA_MULTIPOLYGON) ? new OGRMultiPolygon() :
+                                                              new OGRGeometryCollection();
+
+        for(i=0;i<nParts;i++)
+        {
+            if (nBytes < 4)
+                return OGRERR_FAILURE;
+            int nSubBytes;
+            memcpy(&nSubBytes, pabyGeom, 4);
+            CPL_LSBPTR32(&nSubBytes);
+
+            if (nSubBytes < 0)
+            {
+                delete poColl;
+                return OGRERR_FAILURE;
+            }
+
+            pabyGeom += 4;
+            nBytes -= 4;
+
+            if (nBytes < nSubBytes)
+            {
+                delete poColl;
+                return OGRERR_FAILURE;
+            }
+
+            OGRGeometry* poSubGeom = NULL;
+            if (OGRCreateFromGeomedia( pabyGeom, &poSubGeom, nSubBytes ) == OGRERR_NONE)
+            {
+                if (wkbFlatten(poColl->getGeometryType()) == wkbMultiPolygon &&
+                    wkbFlatten(poSubGeom->getGeometryType()) == wkbLineString)
+                {
+                    OGRPolygon* poPoly = new OGRPolygon();
+                    OGRLinearRing* poRing = new OGRLinearRing();
+                    poRing->addSubLineString((OGRLineString*)poSubGeom);
+                    poPoly->addRingDirectly(poRing);
+                    delete poSubGeom;
+                    poSubGeom = poPoly;
+                }
+
+                if (poColl->addGeometryDirectly(poSubGeom) != OGRERR_NONE)
+                {
+                    //printf("%d %d\n", poColl->getGeometryType() & ~wkb25DBit, poSubGeom->getGeometryType() & ~wkb25DBit);
+                    delete poSubGeom;
+                }
+            }
+
+            pabyGeom += nSubBytes;
+            nBytes -= nSubBytes;
+        }
+
+        *ppoGeom = poColl;
+
+        return OGRERR_NONE;
+    }
+    else
+    {
+        CPLDebug("GEOMEDIA", "Unhandled type %d", nGeomType);
+    }
+
+    return OGRERR_FAILURE;
+}
+
+
+/************************************************************************/
+/*                         OGRGetGeomediaSRS()                          */
+/************************************************************************/
+
+OGRSpatialReference* OGRGetGeomediaSRS(OGRFeature* poFeature)
+{
+    if (poFeature == NULL)
+        return NULL;
+
+    int nGeodeticDatum = poFeature->GetFieldAsInteger("GeodeticDatum");
+    int nEllipsoid = poFeature->GetFieldAsInteger("Ellipsoid");
+    int nProjAlgorithm = poFeature->GetFieldAsInteger("ProjAlgorithm");
+
+    if (nGeodeticDatum == 17 && nEllipsoid == 22)
+    {
+        if (nProjAlgorithm == 12)
+        {
+            OGRSpatialReference* poSRS = new OGRSpatialReference();
+
+            const char* pszDescription = poFeature->GetFieldAsString("Description");
+            if (pszDescription && pszDescription[0] != 0)
+                poSRS->SetNode( "PROJCS", pszDescription );
+            poSRS->SetWellKnownGeogCS("WGS84");
+
+            double dfStdP1 = poFeature->GetFieldAsDouble("StandPar1");
+            double dfStdP2 = poFeature->GetFieldAsDouble("StandPar2");
+            double dfCenterLat = poFeature->GetFieldAsDouble("LatOfOrigin");
+            double dfCenterLong = poFeature->GetFieldAsDouble("LonOfOrigin");
+            double dfFalseEasting = poFeature->GetFieldAsDouble("FalseX");
+            double dfFalseNorthing = poFeature->GetFieldAsDouble("FalseY");
+            poSRS->SetACEA( dfStdP1, dfStdP2,
+                            dfCenterLat, dfCenterLong,
+                            dfFalseEasting, dfFalseNorthing );
+            return poSRS;
+        }
+    }
+
+    return NULL;
+}
diff --git a/ogr/ogrgeomediageometry.h b/ogr/ogrgeomediageometry.h
new file mode 100644
index 0000000..1e7dc4a
--- /dev/null
+++ b/ogr/ogrgeomediageometry.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ * $Id: ogrgeomediageometry.h 21557 2011-01-22 23:42:14Z 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>
+ *
+ * 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_GEOMEDIAGEOMETRY_H_INCLUDED
+#define _OGR_GEOMEDIAGEOMETRY_H_INCLUDED
+
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
+#include "ogr_feature.h"
+
+OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
+                              OGRGeometry **ppoGeom,
+                              int nBytes );
+
+OGRSpatialReference* OGRGetGeomediaSRS(OGRFeature* poFeature);
+
+#endif
diff --git a/ogr/ogrgeometry.cpp b/ogr/ogrgeometry.cpp
index fc812a5..5afdf86 100644
--- a/ogr/ogrgeometry.cpp
+++ b/ogr/ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometry.cpp 21919 2011-03-09 19:40:15Z rouault $
+ * $Id: ogrgeometry.cpp 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements a few base methods on OGRGeometry.
@@ -34,7 +34,7 @@
 #include "cpl_multiproc.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: ogrgeometry.cpp 21919 2011-03-09 19:40:15Z rouault $");
+CPL_CVSID("$Id: ogrgeometry.cpp 23638 2011-12-22 21:02:56Z rouault $");
 
 int OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = FALSE;
 
@@ -337,24 +337,19 @@ OGRBoolean OGRGeometry::Intersects( OGRGeometry *poOtherGeom ) const
     hThisGeosGeom = exportToGEOS();
     hOtherGeosGeom = poOtherGeom->exportToGEOS();
     
+    OGRBoolean bResult = FALSE;
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        OGRBoolean bResult;
-        
         if( GEOSIntersects( hThisGeosGeom, hOtherGeosGeom ) != 0 )
             bResult = TRUE;
         else
             bResult = FALSE;
-        
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
-
-        return bResult;
-    }
-    else
-    {
-        return TRUE;
     }
+
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
+
+    return bResult;
 #endif /* HAVE_GEOS */
 }
 
@@ -656,8 +651,8 @@ int OGR_G_GetDimension( OGRGeometryH hGeom )
  *
  * This method is the same as the C function OGR_G_GetCoordinateDimension().
  *
- * @return in practice this always returns 2 indicating that coordinates are
- * specified within a two dimensional space.
+ * @return in practice this will return 2 or 3. It can also return 0 in the
+ * case of an empty point.
  */
 
 int OGRGeometry::getCoordinateDimension() const
@@ -680,8 +675,9 @@ int OGRGeometry::getCoordinateDimension() const
  *
  * @param hGeom handle on the geometry to get the dimension of the 
  * coordinates from.
- * @return in practice this always returns 2 indicating that coordinates are
- * specified within a two dimensional space.
+ *
+ * @return in practice this will return 2 or 3. It can also return 0 in the
+ * case of an empty point.
  */
 
 int OGR_G_GetCoordinateDimension( OGRGeometryH hGeom )
@@ -878,6 +874,40 @@ void OGR_G_GetEnvelope( OGRGeometryH hGeom, OGREnvelope *psEnvelope )
 }
 
 /**
+ * \fn void OGRGeometry::getEnvelope(OGREnvelope3D *psEnvelope) const;
+ *
+ * \brief Computes and returns the bounding envelope (3D) for this geometry in the passed psEnvelope structure.
+ *
+ * This method is the same as the C function OGR_G_GetEnvelope3D().
+ *
+ * @param psEnvelope the structure in which to place the results.
+ *
+ * @since OGR 1.9.0
+ */
+
+/************************************************************************/
+/*                        OGR_G_GetEnvelope3D()                         */
+/************************************************************************/
+/**
+ * \brief Computes and returns the bounding envelope (3D) for this geometry in the passed psEnvelope structure.
+ *
+ * This function is the same as the CPP method OGRGeometry::getEnvelope().
+ *
+ * @param hGeom handle of the geometry to get envelope from.
+ * @param psEnvelope the structure in which to place the results.
+ *
+ * @since OGR 1.9.0
+ */
+
+void OGR_G_GetEnvelope3D( OGRGeometryH hGeom, OGREnvelope3D *psEnvelope )
+
+{
+    VALIDATE_POINTER0( hGeom, "OGR_G_GetEnvelope3D" );
+
+    ((OGRGeometry *) hGeom)->getEnvelope( psEnvelope );
+}
+
+/**
  * \fn OGRErr OGRGeometry::importFromWkb( unsigned char * pabyData, int nSize);
  *
  * \brief Assign geometry from well known binary data.
@@ -2374,8 +2404,6 @@ OGRGeometry *OGRGeometry::Intersection( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         hGeosProduct = GEOSIntersection( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
@@ -2383,6 +2411,8 @@ OGRGeometry *OGRGeometry::Intersection( const OGRGeometry *poOtherGeom ) const
             GEOSGeom_destroy( hGeosProduct );
         }
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return poOGRProduct;
 
@@ -2466,8 +2496,6 @@ OGRGeometry *OGRGeometry::Union( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         hGeosProduct = GEOSUnion( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
@@ -2475,6 +2503,8 @@ OGRGeometry *OGRGeometry::Union( const OGRGeometry *poOtherGeom ) const
             GEOSGeom_destroy( hGeosProduct );
         }
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return poOGRProduct;
 
@@ -2642,8 +2672,6 @@ OGRGeometry *OGRGeometry::Difference( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         hGeosProduct = GEOSDifference( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
@@ -2651,6 +2679,8 @@ OGRGeometry *OGRGeometry::Difference( const OGRGeometry *poOtherGeom ) const
             GEOSGeom_destroy( hGeosProduct );
         }
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return poOGRProduct;
 
@@ -2737,8 +2767,6 @@ OGRGeometry::SymDifference( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         hGeosProduct = GEOSSymDifference( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
@@ -2746,6 +2774,8 @@ OGRGeometry::SymDifference( const OGRGeometry *poOtherGeom ) const
             GEOSGeom_destroy( hGeosProduct );
         }
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return poOGRProduct;
 
@@ -2860,9 +2890,9 @@ OGRGeometry::Disjoint( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         bResult = GEOSDisjoint( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return bResult;
 
@@ -2941,9 +2971,9 @@ OGRGeometry::Touches( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         bResult = GEOSTouches( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return bResult;
 
@@ -3022,9 +3052,9 @@ OGRGeometry::Crosses( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         bResult = GEOSCrosses( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return bResult;
 
@@ -3102,9 +3132,9 @@ OGRGeometry::Within( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         bResult = GEOSWithin( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return bResult;
 
@@ -3182,9 +3212,9 @@ OGRGeometry::Contains( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         bResult = GEOSContains( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return bResult;
 
@@ -3263,9 +3293,9 @@ OGRGeometry::Overlaps( const OGRGeometry *poOtherGeom ) const
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
         bResult = GEOSOverlaps( hThisGeosGeom, hOtherGeosGeom );
-        GEOSGeom_destroy( hThisGeosGeom );
-        GEOSGeom_destroy( hOtherGeosGeom );
     }
+    GEOSGeom_destroy( hThisGeosGeom );
+    GEOSGeom_destroy( hOtherGeosGeom );
 
     return bResult;
 
@@ -3514,13 +3544,13 @@ OGRGeometry *OGRGeometry::Simplify(double dTolerance) const
     hThisGeosGeom = exportToGEOS();
     if( hThisGeosGeom != NULL ) 
     {
-	hGeosProduct = GEOSSimplify( hThisGeosGeom, dTolerance );
-	GEOSGeom_destroy( hThisGeosGeom );
-	if( hGeosProduct != NULL )
-	{
-	    poOGRProduct = OGRGeometryFactory::createFromGEOS( hGeosProduct );
+        hGeosProduct = GEOSSimplify( hThisGeosGeom, dTolerance );
+        GEOSGeom_destroy( hThisGeosGeom );
+        if( hGeosProduct != NULL )
+        {
+            poOGRProduct = OGRGeometryFactory::createFromGEOS( hGeosProduct );
             GEOSGeom_destroy( hGeosProduct );
-	}
+        }
     }
     return poOGRProduct;
 
@@ -3562,6 +3592,222 @@ OGRGeometryH OGR_G_Simplify( OGRGeometryH hThis, double dTolerance )
 }
 
 /************************************************************************/
+/*                         SimplifyPreserveTopology()                   */
+/************************************************************************/
+
+/**
+ * \brief Simplify the geometry while preserving topology.
+ *
+ * This function is the same as the C function OGR_G_SimplifyPreserveTopology().
+ *
+ * This function is built on the GEOS library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
+ *
+ * @param dTolerance the distance tolerance for the simplification.
+ *
+ * @return the simplified geometry or NULL if an error occurs.
+ *
+ * @since OGR 1.9.0
+ */
+
+OGRGeometry *OGRGeometry::SimplifyPreserveTopology(double dTolerance) const
+
+{
+#ifndef HAVE_GEOS
+
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "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)
+
+    GEOSGeom hThisGeosGeom = NULL;
+    GEOSGeom hGeosProduct = NULL;
+    OGRGeometry *poOGRProduct = NULL;
+
+    hThisGeosGeom = exportToGEOS();
+    if( hThisGeosGeom != NULL )
+    {
+        hGeosProduct = GEOSTopologyPreserveSimplify( hThisGeosGeom, dTolerance );
+        GEOSGeom_destroy( hThisGeosGeom );
+        if( hGeosProduct != NULL )
+        {
+            poOGRProduct = OGRGeometryFactory::createFromGEOS( hGeosProduct );
+            GEOSGeom_destroy( hGeosProduct );
+        }
+    }
+    return poOGRProduct;
+
+#else
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "GEOS >= 3.0.0 required for SimplifyPreserveTopology() support." );
+    return NULL;
+#endif /* HAVE_GEOS */
+
+}
+
+/************************************************************************/
+/*                     OGR_G_SimplifyPreserveTopology()                 */
+/************************************************************************/
+
+/**
+ * \brief Simplify the geometry while preserving topology.
+ *
+ * This function is the same as the C++ method OGRGeometry::SimplifyPreserveTopology().
+ *
+ * This function is built on the GEOS library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
+ *
+ * @param hThis the geometry.
+ * @param dTolerance the distance tolerance for the simplification.
+ *
+ * @return the simplified geometry or NULL if an error occurs.
+ *
+ * @since OGR 1.9.0
+ */
+
+OGRGeometryH OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double dTolerance )
+
+{
+    VALIDATE_POINTER1( hThis, "OGR_G_SimplifyPreserveTopology", NULL );
+    return (OGRGeometryH) ((OGRGeometry *) hThis)->SimplifyPreserveTopology( dTolerance );
+}
+
+/************************************************************************/
+/*                             Polygonize()                             */
+/************************************************************************/
+/* Contributor: Alessandro Furieri, a.furieri at lqt.it                    */
+/* Developed for Faunalia (http://www.faunalia.it) with funding from    */
+/* Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED        */
+/*                   AMBIENTALE                                         */
+/************************************************************************/
+
+/**
+ * \brief Polygonizes a set of sparse edges.
+ *
+ * A new geometry object is created and returned containing a collection
+ * of reassembled Polygons: NULL will be returned if the input collection
+ * doesn't corresponds to a MultiLinestring, or when reassembling Edges
+ * into Polygons is impossible due to topogical inconsistencies.
+ *
+ * This method is the same as the C function OGR_G_Polygonize().
+ *
+ * This method is built on the GEOS library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the GEOS library, this method will always fail, 
+ * issuing a CPLE_NotSupported error. 
+ *
+ * @return a newly allocated geometry now owned by the caller, or NULL on failure.
+ *
+ * @since OGR 1.9.0
+ */
+
+OGRGeometry *OGRGeometry::Polygonize() const
+
+{
+#ifndef HAVE_GEOS
+
+    CPLError( CE_Failure, CPLE_NotSupported, 
+              "GEOS support not enabled." );
+    return NULL;
+
+#else
+
+    OGRGeometryCollection *poColl = NULL;
+    if( wkbFlatten(getGeometryType()) == wkbGeometryCollection ||
+        wkbFlatten(getGeometryType()) == wkbMultiLineString )
+        poColl = (OGRGeometryCollection *)this;
+    else
+        return NULL;
+
+    int iCount = poColl->getNumGeometries();
+
+    GEOSGeom *hGeosGeomList = NULL;
+    GEOSGeom hGeosPolygs = NULL;
+    OGRGeometry *poPolygsOGRGeom = NULL;
+    int bError = FALSE;
+
+    hGeosGeomList = new GEOSGeom [iCount];
+    for ( int ig = 0; ig < iCount; ig++)
+    {
+        GEOSGeom hGeosGeom = NULL;
+        OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
+        if( poChild == NULL ||
+            wkbFlatten(poChild->getGeometryType()) != wkbLineString )
+            bError = TRUE;
+        else
+        {
+            hGeosGeom = poChild->exportToGEOS();
+            if( hGeosGeom == NULL)
+                bError = TRUE;
+        }
+        *(hGeosGeomList + ig) = hGeosGeom;
+    }
+
+    if( bError == FALSE )
+    {
+        hGeosPolygs = GEOSPolygonize( hGeosGeomList, iCount );
+
+        if( hGeosPolygs != NULL )
+        {
+            poPolygsOGRGeom = OGRGeometryFactory::createFromGEOS(hGeosPolygs);
+            GEOSGeom_destroy( hGeosPolygs);
+        }
+    }
+
+    for ( int ig = 0; ig < iCount; ig++)
+    {
+        GEOSGeom hGeosGeom = *(hGeosGeomList + ig);
+        if( hGeosGeom != NULL)
+            GEOSGeom_destroy( hGeosGeom );
+    }
+    delete [] hGeosGeomList;
+
+    return poPolygsOGRGeom;
+
+#endif /* HAVE_GEOS */
+}
+
+/************************************************************************/
+/*                          OGR_G_Polygonize()                          */
+/************************************************************************/
+/**
+ * \brief Polygonizes a set of sparse edges.
+ *
+ * A new geometry object is created and returned containing a collection
+ * of reassembled Polygons: NULL will be returned if the input collection
+ * doesn't corresponds to a MultiLinestring, or when reassembling Edges
+ * into Polygons is impossible due to topogical inconsistencies.  
+ *
+ * This function is the same as the C++ method OGRGeometry::Polygonize().
+ *
+ * This function is built on the GEOS library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the GEOS library, this function will always fail, 
+ * issuing a CPLE_NotSupported error. 
+ *
+ * @param hTarget The Geometry to be polygonized.
+ *
+ * @return a handle to a newly allocated geometry now owned by the caller,
+ *         or NULL on failure.
+ *
+ * @since OGR 1.9.0
+ */
+
+OGRGeometryH OGR_G_Polygonize( OGRGeometryH hTarget )
+
+{
+    VALIDATE_POINTER1( hTarget, "OGR_G_Polygonize", NULL );
+
+    return (OGRGeometryH) ((OGRGeometry *) hTarget)->Polygonize();
+}
+
+/************************************************************************/
 /*                               swapXY()                               */
 /************************************************************************/
 
diff --git a/ogr/ogrgeometrycollection.cpp b/ogr/ogrgeometrycollection.cpp
index eceb038..91e4211 100644
--- a/ogr/ogrgeometrycollection.cpp
+++ b/ogr/ogrgeometrycollection.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometrycollection.cpp 21310 2010-12-23 12:40:27Z rouault $
+ * $Id: ogrgeometrycollection.cpp 23589 2011-12-17 14:21:01Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRGeometryCollection class.
@@ -30,7 +30,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeometrycollection.cpp 21310 2010-12-23 12:40:27Z rouault $");
+CPL_CVSID("$Id: ogrgeometrycollection.cpp 23589 2011-12-17 14:21:01Z rouault $");
 
 /************************************************************************/
 /*                       OGRGeometryCollection()                        */
@@ -352,18 +352,24 @@ int OGRGeometryCollection::WkbSize() const
 }
 
 /************************************************************************/
-/*                           importFromWkb()                            */
-/*                                                                      */
-/*      Initialize from serialized stream in well known binary          */
-/*      format.                                                         */
+/*                       importFromWkbInternal()                        */
 /************************************************************************/
 
-OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
-                                             int nSize )
+OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
+                                                     int nSize, int nRecLevel )
 
 {
     OGRwkbByteOrder     eByteOrder;
     int                 nDataOffset;
+
+    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    if( nRecLevel == 32 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Too many recursiong level (%d) while parsing WKB geometry.",
+                    nRecLevel );
+        return OGRERR_CORRUPT_DATA;
+    }
     
     if( nSize < 9 && nSize != -1 )
         return OGRERR_NOT_ENOUGH_DATA;
@@ -441,9 +447,41 @@ OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
         OGRErr  eErr;
         OGRGeometry* poSubGeom = NULL;
 
-        eErr = OGRGeometryFactory::
-            createFromWkb( pabyData + nDataOffset, NULL,
-                           &poSubGeom, nSize );
+        /* Parses sub-geometry */
+        unsigned char* pabySubData = pabyData + nDataOffset;
+        if( nSize < 9 && nSize != -1 )
+            return OGRERR_NOT_ENOUGH_DATA;
+        OGRwkbByteOrder eSubGeomByteOrder =
+            DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabySubData);
+
+        if( eSubGeomByteOrder != wkbXDR && eSubGeomByteOrder != wkbNDR )
+            return OGRERR_CORRUPT_DATA;
+
+        OGRwkbGeometryType eSubGeomType;
+        if( eSubGeomByteOrder == wkbNDR )
+            eSubGeomType = (OGRwkbGeometryType) pabySubData[1];
+        else
+            eSubGeomType = (OGRwkbGeometryType) pabySubData[4];
+
+        if( eSubGeomType == wkbPoint ||
+            eSubGeomType == wkbLineString ||
+            eSubGeomType == wkbPolygon)
+        {
+            eErr = OGRGeometryFactory::
+                createFromWkb( pabySubData, NULL,
+                               &poSubGeom, nSize );
+        }
+        else if (eSubGeomType == wkbGeometryCollection ||
+                 eSubGeomType == wkbMultiPolygon ||
+                 eSubGeomType == wkbMultiPoint ||
+                 eSubGeomType == wkbMultiLineString)
+        {
+            poSubGeom = OGRGeometryFactory::createGeometry( eSubGeomType );
+            eErr = ((OGRGeometryCollection*)poSubGeom)->
+                        importFromWkbInternal( pabySubData, nSize, nRecLevel + 1 );
+        }
+        else
+            return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
         if( eErr != OGRERR_NONE )
         {
@@ -451,7 +489,6 @@ OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
             return eErr;
         }
 
-        OGRwkbGeometryType eSubGeomType = wkbFlatten(poSubGeom->getGeometryType());
         if( (eGeometryType == wkbMultiPoint && eSubGeomType != wkbPoint) ||
             (eGeometryType == wkbMultiLineString && eSubGeomType != wkbLineString) ||
             (eGeometryType == wkbMultiPolygon && eSubGeomType != wkbPolygon) )
@@ -479,6 +516,20 @@ OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
 }
 
 /************************************************************************/
+/*                           importFromWkb()                            */
+/*                                                                      */
+/*      Initialize from serialized stream in well known binary          */
+/*      format.                                                         */
+/************************************************************************/
+
+OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
+                                             int nSize )
+
+{
+    return importFromWkbInternal(pabyData, nSize, 0);
+}
+
+/************************************************************************/
 /*                            exportToWkb()                             */
 /*                                                                      */
 /*      Build a well known binary representation of this object.        */
@@ -539,16 +590,26 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
 }
 
 /************************************************************************/
-/*                           importFromWkt()                            */
+/*                       importFromWktInternal()                        */
 /************************************************************************/
 
-OGRErr OGRGeometryCollection::importFromWkt( char ** ppszInput )
+OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRecLevel )
 
 {
 
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
 
+
+    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    if( nRecLevel == 32 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Too many recursiong level (%d) while parsing WKT geometry.",
+                    nRecLevel );
+        return OGRERR_CORRUPT_DATA;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Clear existing Geoms.                                           */
 /* -------------------------------------------------------------------- */
@@ -641,8 +702,25 @@ OGRErr OGRGeometryCollection::importFromWkt( char ** ppszInput )
         OGRGeometry *poGeom = NULL;
         OGRErr      eErr;
 
-        eErr = OGRGeometryFactory::createFromWkt( (char **) &pszInput,
-                                                  NULL, &poGeom );
+    /* -------------------------------------------------------------------- */
+    /*      Get the first token, which should be the geometry type.         */
+    /* -------------------------------------------------------------------- */
+        if( OGRWktReadToken( pszInput, szToken ) == NULL )
+            return OGRERR_CORRUPT_DATA;
+
+    /* -------------------------------------------------------------------- */
+    /*      Do the import.                                                  */
+    /* -------------------------------------------------------------------- */
+        if (EQUAL(szToken,"GEOMETRYCOLLECTION"))
+        {
+            poGeom = new OGRGeometryCollection();
+            eErr = ((OGRGeometryCollection*)poGeom)->
+                        importFromWktInternal( (char **) &pszInput, nRecLevel + 1 );
+        }
+        else
+            eErr = OGRGeometryFactory::createFromWkt( (char **) &pszInput,
+                                                       NULL, &poGeom );
+
         if( eErr != OGRERR_NONE )
             return eErr;
 
@@ -668,6 +746,16 @@ OGRErr OGRGeometryCollection::importFromWkt( char ** ppszInput )
 }
 
 /************************************************************************/
+/*                           importFromWkt()                            */
+/************************************************************************/
+
+OGRErr OGRGeometryCollection::importFromWkt( char ** ppszInput )
+
+{
+    return importFromWktInternal(ppszInput, 0);
+}
+
+/************************************************************************/
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
@@ -787,6 +875,53 @@ void OGRGeometryCollection::getEnvelope( OGREnvelope * psEnvelope ) const
 }
 
 /************************************************************************/
+/*                            getEnvelope()                             */
+/************************************************************************/
+
+void OGRGeometryCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
+
+{
+    OGREnvelope3D       oGeomEnv;
+    int                 bExtentSet = FALSE;
+
+    for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
+    {
+        if (!papoGeoms[iGeom]->IsEmpty())
+        {
+            if (!bExtentSet)
+            {
+                papoGeoms[iGeom]->getEnvelope( psEnvelope );
+                bExtentSet = TRUE;
+            }
+            else
+            {
+                papoGeoms[iGeom]->getEnvelope( &oGeomEnv );
+
+                if( psEnvelope->MinX > oGeomEnv.MinX )
+                    psEnvelope->MinX = oGeomEnv.MinX;
+                if( psEnvelope->MinY > oGeomEnv.MinY )
+                    psEnvelope->MinY = oGeomEnv.MinY;
+                if( psEnvelope->MaxX < oGeomEnv.MaxX )
+                    psEnvelope->MaxX = oGeomEnv.MaxX;
+                if( psEnvelope->MaxY < oGeomEnv.MaxY )
+                    psEnvelope->MaxY = oGeomEnv.MaxY;
+
+                if( psEnvelope->MinZ > oGeomEnv.MinZ )
+                    psEnvelope->MinZ = oGeomEnv.MinZ;
+                if( psEnvelope->MaxZ < oGeomEnv.MaxZ )
+                    psEnvelope->MaxZ = oGeomEnv.MaxZ;
+            }
+        }
+    }
+
+    if (!bExtentSet)
+    {
+        psEnvelope->MinX = psEnvelope->MinY = psEnvelope->MinZ = 0;
+        psEnvelope->MaxX = psEnvelope->MaxY = psEnvelope->MaxZ = 0;
+    }
+}
+
+/************************************************************************/
 /*                               Equals()                               */
 /************************************************************************/
 
diff --git a/ogr/ogrgeometryfactory.cpp b/ogr/ogrgeometryfactory.cpp
index 75f700d..6f7eec4 100644
--- a/ogr/ogrgeometryfactory.cpp
+++ b/ogr/ogrgeometryfactory.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometryfactory.cpp 21322 2010-12-27 17:54:52Z rouault $
+ * $Id: ogrgeometryfactory.cpp 23589 2011-12-17 14:21:01Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Factory for converting geometry to and from well known binary
@@ -33,7 +33,7 @@
 #include "ogr_p.h"
 #include "ogr_geos.h"
 
-CPL_CVSID("$Id: ogrgeometryfactory.cpp 21322 2010-12-27 17:54:52Z rouault $");
+CPL_CVSID("$Id: ogrgeometryfactory.cpp 23589 2011-12-17 14:21:01Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -218,7 +218,7 @@ OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *pabyData,
  *    const char* wkt= "POINT(0 0)";
  *  
  *    // cast because OGR_G_CreateFromWkt will move the pointer 
- *    char* pszWkt = (char*) wkt.c_str(); 
+ *    char* pszWkt = (char*) wkt;
  *    OGRSpatialReferenceH ref = OSRNewSpatialReference(NULL);
  *    OGRGeometryH new_geom;
  *    OGRErr err = OGR_G_CreateFromWkt(&pszWkt, ref, &new_geom);
@@ -1588,6 +1588,22 @@ OGRErr OGRGeometryFactory::createFromFgf( unsigned char *pabyData,
                                           int *pnBytesConsumed )
 
 {
+    return createFromFgfInternal(pabyData, poSR, ppoReturn, nBytes,
+                                 pnBytesConsumed, 0);
+}
+
+
+/************************************************************************/
+/*                       createFromFgfInternal()                        */
+/************************************************************************/
+
+OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
+                                                  OGRSpatialReference * poSR,
+                                                  OGRGeometry **ppoReturn,
+                                                  int nBytes,
+                                                  int *pnBytesConsumed,
+                                                  int nRecLevel )
+{
     OGRErr       eErr = OGRERR_NONE;
     OGRGeometry *poGeom = NULL;
     GInt32       nGType, nGDim;
@@ -1596,6 +1612,15 @@ OGRErr OGRGeometryFactory::createFromFgf( unsigned char *pabyData,
     
     (void) iOrdinal;
 
+    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    if( nRecLevel == 32 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Too many recursiong level (%d) while parsing FGF geometry.",
+                    nRecLevel );
+        return OGRERR_CORRUPT_DATA;
+    }
+
     *ppoReturn = NULL;
 
     if( nBytes < 4 )
@@ -1837,8 +1862,8 @@ OGRErr OGRGeometryFactory::createFromFgf( unsigned char *pabyData,
             int nThisGeomSize;
             OGRGeometry *poThisGeom = NULL;
          
-            eErr = createFromFgf( pabyData + nBytesUsed, poSR, &poThisGeom,
-                                  nBytes - nBytesUsed, &nThisGeomSize);
+            eErr = createFromFgfInternal( pabyData + nBytesUsed, poSR, &poThisGeom,
+                                  nBytes - nBytesUsed, &nThisGeomSize, nRecLevel + 1);
             if( eErr != OGRERR_NONE )
             {
                 delete poGC;
diff --git a/ogr/ogrlinearring.cpp b/ogr/ogrlinearring.cpp
index 406157f..18527fe 100644
--- a/ogr/ogrlinearring.cpp
+++ b/ogr/ogrlinearring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlinearring.cpp 22556 2011-06-22 12:17:11Z rouault $
+ * $Id: ogrlinearring.cpp 22555 2011-06-22 12:16:54Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRLinearRing geometry class.
@@ -30,7 +30,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrlinearring.cpp 22556 2011-06-22 12:17:11Z rouault $");
+CPL_CVSID("$Id: ogrlinearring.cpp 22555 2011-06-22 12:16:54Z rouault $");
 
 /************************************************************************/
 /*                           OGRLinearRing()                            */
diff --git a/ogr/ogrlinestring.cpp b/ogr/ogrlinestring.cpp
index 68bd157..98288b4 100644
--- a/ogr/ogrlinestring.cpp
+++ b/ogr/ogrlinestring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlinestring.cpp 20652 2010-09-19 21:52:52Z rouault $
+ * $Id: ogrlinestring.cpp 22464 2011-05-29 21:33:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRLineString geometry class.
@@ -31,7 +31,7 @@
 #include "ogr_p.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: ogrlinestring.cpp 20652 2010-09-19 21:52:52Z rouault $");
+CPL_CVSID("$Id: ogrlinestring.cpp 22464 2011-05-29 21:33:41Z rouault $");
 
 /************************************************************************/
 /*                           OGRLineString()                            */
@@ -447,7 +447,10 @@ void OGRLineString::setPoint( int iPoint, double xIn, double yIn )
 void OGRLineString::addPoint( OGRPoint * poPoint )
 
 {
-    setPoint( nPointCount, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
+    if ( poPoint->getCoordinateDimension() < 3 )
+        setPoint( nPointCount, poPoint->getX(), poPoint->getY() );
+    else
+        setPoint( nPointCount, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
 }
 
 /************************************************************************/
@@ -609,6 +612,64 @@ void OGRLineString::getPoints( OGRRawPoint * paoPointsOut, double * padfZ ) cons
 
 
 /************************************************************************/
+/*                          getPoints()                                 */
+/************************************************************************/
+
+/**
+ * \brief Returns all points of line string.
+ *
+ * This method copies all points into user arrays. The user provides the
+ * stride between 2 consecutives elements of the array.
+ *
+ * On some CPU architectures, care must be taken so that the arrays are properly aligned.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
+ * @param nXStride the number of bytes between 2 elements of pabyX.
+ * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
+ * @param nYStride the number of bytes between 2 elements of pabyY.
+ * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
+ * @param nZStride the number of bytes between 2 elements of pabyZ.
+ *
+ * @since OGR 1.9.0
+ */
+
+void OGRLineString::getPoints( void* pabyX, int nXStride,
+                               void* pabyY, int nYStride,
+                               void* pabyZ, int nZStride)  const
+{
+    int i;
+    if (pabyX != NULL && nXStride == 0)
+        return;
+    if (pabyY != NULL && nYStride == 0)
+        return;
+    if (pabyZ != NULL && nZStride == 0)
+        return;
+    if (nXStride == 2 * sizeof(double) &&
+        nYStride == 2 * sizeof(double) &&
+        (char*)pabyY == (char*)pabyX + sizeof(double) &&
+        (pabyZ == NULL || nZStride == sizeof(double)))
+    {
+        getPoints((OGRRawPoint *)pabyX, (double*)pabyZ);
+        return;
+    }
+    for(i=0;i<nPointCount;i++)
+    {
+        if (pabyX) *(double*)((char*)pabyX + i * nXStride) = paoPoints[i].x;
+        if (pabyY) *(double*)((char*)pabyY + i * nYStride) = paoPoints[i].y;
+    }
+
+    if (pabyZ)
+    {
+        for(i=0;i<nPointCount;i++)
+        {
+            *(double*)((char*)pabyZ + i * nZStride) = (padfZ) ? padfZ[i] : 0.0;
+        }
+    }
+}
+
+/************************************************************************/
 /*                          addSubLineString()                          */
 /************************************************************************/
 
@@ -902,16 +963,7 @@ OGRErr OGRLineString::importFromWkt( char ** ppszInput )
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
 
-    if( paoPoints != NULL )
-    {
-        nPointCount = 0;
-
-        CPLFree( paoPoints );
-        paoPoints = NULL;
-        
-        CPLFree( padfZ );
-        padfZ = NULL;
-    }
+    empty();
 
 /* -------------------------------------------------------------------- */
 /*      Read and verify the ``LINESTRING'' keyword token.               */
@@ -1229,6 +1281,39 @@ void OGRLineString::getEnvelope( OGREnvelope * psEnvelope ) const
     psEnvelope->MaxY = dfMaxY;
 }
 
+
+/************************************************************************/
+/*                            getEnvelope()                             */
+/************************************************************************/
+
+void OGRLineString::getEnvelope( OGREnvelope3D * psEnvelope ) const
+
+{
+    getEnvelope((OGREnvelope*)psEnvelope);
+
+    double      dfMinZ, dfMaxZ;
+
+    if( nPointCount == 0 || padfZ == NULL )
+    {
+        psEnvelope->MinZ = 0;
+        psEnvelope->MaxZ = 0;
+        return;
+    }
+
+    dfMinZ = dfMaxZ = padfZ[0];
+
+    for( int iPoint = 1; iPoint < nPointCount; iPoint++ )
+    {
+        if( dfMinZ > padfZ[iPoint] )
+            dfMinZ = padfZ[iPoint];
+        if( dfMaxZ < padfZ[iPoint] )
+            dfMaxZ = padfZ[iPoint];
+    }
+
+    psEnvelope->MinZ = dfMinZ;
+    psEnvelope->MaxZ = dfMaxZ;
+}
+
 /************************************************************************/
 /*                               Equals()                                */
 /************************************************************************/
diff --git a/ogr/ogrpgeogeometry.cpp b/ogr/ogrpgeogeometry.cpp
new file mode 100644
index 0000000..d1390fd
--- /dev/null
+++ b/ogr/ogrpgeogeometry.cpp
@@ -0,0 +1,1408 @@
+/******************************************************************************
+ * $Id: ogrpgeogeometry.cpp 22752 2011-07-18 17:42:07Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements decoder of shapebin geometry for PGeo
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *           Paul Ramsey, pramsey at cleverelephant.ca
+ *
+ ******************************************************************************
+ * Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ *
+ * 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 "ogrpgeogeometry.h"
+#include "ogr_p.h"
+#include "cpl_string.h"
+#include "zlib.h"
+
+CPL_CVSID("$Id: ogrpgeogeometry.cpp 22752 2011-07-18 17:42:07Z rouault $");
+
+#define SHPP_TRISTRIP   0
+#define SHPP_TRIFAN     1
+#define SHPP_OUTERRING  2
+#define SHPP_INNERRING  3
+#define SHPP_FIRSTRING  4
+#define SHPP_RING       5
+#define SHPP_TRIANGLES  6 /* Multipatch 9.0 specific */
+
+
+/************************************************************************/
+/*                     OGRCreateFromMultiPatch()                        */
+/*                                                                      */
+/*      Translate a multipatch representation to an OGR geometry        */
+/*      Mostly copied from shape2ogr.cpp                                */
+/************************************************************************/
+
+static OGRGeometry* OGRCreateFromMultiPatch(int nParts,
+                                            GInt32* panPartStart,
+                                            GInt32* panPartType,
+                                            int nPoints,
+                                            double* padfX,
+                                            double* padfY,
+                                            double* padfZ)
+{
+    OGRMultiPolygon *poMP = new OGRMultiPolygon();
+    int iPart;
+    OGRPolygon *poLastPoly = NULL;
+
+    for( iPart = 0; iPart < nParts; iPart++ )
+    {
+        int nPartPoints, nPartStart;
+
+        // Figure out details about this part's vertex list.
+        if( panPartStart == NULL )
+        {
+            nPartPoints = nPoints;
+            nPartStart = 0;
+        }
+        else
+        {
+
+            if( iPart == nParts - 1 )
+                nPartPoints =
+                    nPoints - panPartStart[iPart];
+            else
+                nPartPoints = panPartStart[iPart+1]
+                    - panPartStart[iPart];
+            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] );
+    }
+
+    if( poLastPoly != NULL )
+    {
+        poMP->addGeometryDirectly( poLastPoly );
+        poLastPoly = NULL;
+    }
+
+    return poMP;
+}
+
+
+/************************************************************************/
+/*                      OGRWriteToShapeBin()                            */
+/*                                                                      */
+/*      Translate OGR geometry to a shapefile binary representation     */
+/************************************************************************/
+
+OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom, 
+                           GByte **ppabyShape,
+                           int *pnBytes )
+{
+    GUInt32 nGType = SHPT_NULL;
+    int nShpSize = 4; /* All types start with integer type number */
+    int nShpZSize = 0; /* Z gets tacked onto the end */
+    GUInt32 nPoints = 0;
+    GUInt32 nParts = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Null or Empty input maps to SHPT_NULL.                          */
+/* -------------------------------------------------------------------- */
+    if ( ! poGeom || poGeom->IsEmpty() )
+    {
+        *ppabyShape = (GByte*)VSIMalloc(nShpSize);
+        GUInt32 zero = SHPT_NULL;
+        memcpy(*ppabyShape, &zero, nShpSize);
+        *pnBytes = nShpSize;
+        return OGRERR_NONE;
+    }
+
+    OGRwkbGeometryType nOGRType = wkbFlatten(poGeom->getGeometryType());
+    int b3d = (poGeom->getGeometryType() & wkb25DBit);
+    int nCoordDims = b3d ? 3 : 2;
+
+/* -------------------------------------------------------------------- */
+/*      Calculate the shape buffer size                                 */
+/* -------------------------------------------------------------------- */
+    if ( nOGRType == wkbPoint )
+    {
+        nShpSize += 8 * nCoordDims;
+    }
+    else if ( nOGRType == wkbLineString )
+    {
+        OGRLineString *poLine = (OGRLineString*)poGeom;
+        nPoints = poLine->getNumPoints();
+        nParts = 1;
+        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 4; /* nparts */
+        nShpSize += 4; /* npoints */
+        nShpSize += 4; /* parts[1] */
+        nShpSize += 8 * nCoordDims * nPoints; /* points */
+        nShpZSize = 16 + 8 * nPoints;
+    }
+    else if ( nOGRType == wkbPolygon )
+    {
+        poGeom->closeRings();
+        OGRPolygon *poPoly = (OGRPolygon*)poGeom;
+        nParts = poPoly->getNumInteriorRings() + 1;
+        for ( GUInt32 i = 0; i < nParts; i++ )
+        {
+            OGRLinearRing *poRing;
+            if ( i == 0 )
+                poRing = poPoly->getExteriorRing();
+            else
+                poRing = poPoly->getInteriorRing(i-1);
+            nPoints += poRing->getNumPoints();
+        }
+        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 4; /* nparts */
+        nShpSize += 4; /* npoints */
+        nShpSize += 4 * nParts; /* parts[nparts] */
+        nShpSize += 8 * nCoordDims * nPoints; /* points */    
+        nShpZSize = 16 + 8 * nPoints;
+    }
+    else if ( nOGRType == wkbMultiPoint )
+    {
+        OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
+        for ( int i = 0; i < poMPoint->getNumGeometries(); i++ )
+        {
+            OGRPoint *poPoint = (OGRPoint*)(poMPoint->getGeometryRef(i));
+            if ( poPoint->IsEmpty() ) 
+                continue;
+            nPoints++;
+        }
+        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 4; /* npoints */
+        nShpSize += 8 * nCoordDims * nPoints; /* points */    
+        nShpZSize = 16 + 8 * nPoints;
+    }
+    else if ( nOGRType == wkbMultiLineString )
+    {
+        OGRMultiLineString *poMLine = (OGRMultiLineString*)poGeom;
+        for ( int i = 0; i < poMLine->getNumGeometries(); i++ )
+        {
+            OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
+            /* Skip empties */
+            if ( poLine->IsEmpty() ) 
+                continue;
+            nParts++;
+            nPoints += poLine->getNumPoints();
+        }
+        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 4; /* nparts */
+        nShpSize += 4; /* npoints */
+        nShpSize += 4 * nParts; /* parts[nparts] */
+        nShpSize += 8 * nCoordDims * nPoints ; /* points */    
+        nShpZSize = 16 + 8 * nPoints;
+    }
+    else if ( nOGRType == wkbMultiPolygon )
+    {
+        poGeom->closeRings();
+        OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
+        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;
+
+            nParts += nRings;
+            for ( int i = 0; i < nRings; i++ )
+            {
+                OGRLinearRing *poRing;
+                if ( i == 0 )
+                    poRing = poPoly->getExteriorRing();
+                else
+                    poRing = poPoly->getInteriorRing(i-1);
+                nPoints += poRing->getNumPoints();
+            }
+        }
+        nShpSize += 16 * nCoordDims; /* xy(z) box */ 
+        nShpSize += 4; /* nparts */
+        nShpSize += 4; /* npoints */
+        nShpSize += 4 * nParts; /* parts[nparts] */
+        nShpSize += 8 * nCoordDims * nPoints ; /* points */  
+        nShpZSize = 16 + 8 * nPoints;
+    }
+    else
+    {
+        return OGRERR_UNSUPPORTED_OPERATION;
+    }
+
+    /* Allocate our shape buffer */
+    *ppabyShape = (GByte*)VSIMalloc(nShpSize);
+    if ( ! *ppabyShape )
+        return OGRERR_FAILURE;
+
+    /* Fill in the output size. */
+    *pnBytes = nShpSize;
+
+    /* Set up write pointers */
+    unsigned char *pabyPtr = *ppabyShape;
+    unsigned char *pabyPtrZ = NULL;
+    if ( b3d )
+        pabyPtrZ = pabyPtr + nShpSize - nShpZSize;
+
+/* -------------------------------------------------------------------- */
+/*      Write in the Shape type number now                              */
+/* -------------------------------------------------------------------- */
+    switch(nOGRType)
+    {
+        case wkbPoint:
+        {
+            nGType = b3d ? SHPT_POINTZ : SHPT_POINT;
+            break;
+        }
+        case wkbMultiPoint:
+        {
+            nGType = b3d ? SHPT_MULTIPOINTZ : SHPT_MULTIPOINT;
+            break;
+        }
+        case wkbLineString:
+        case wkbMultiLineString:
+        {
+            nGType = b3d ? SHPT_ARCZ : SHPT_ARC;
+            break;
+        }
+        case wkbPolygon:
+        case wkbMultiPolygon:
+        {
+            nGType = b3d ? SHPT_POLYGONZ : SHPT_POLYGON;
+            break;
+        }
+        default:
+        {
+            return OGRERR_UNSUPPORTED_OPERATION;
+        }
+    }
+    /* Write in the type number and advance the pointer */
+    nGType = CPL_LSBWORD32( nGType );
+    memcpy( pabyPtr, &nGType, 4 );
+    pabyPtr += 4;
+
+
+/* -------------------------------------------------------------------- */
+/*      POINT and POINTZ                                                */
+/* -------------------------------------------------------------------- */
+    if ( nOGRType == wkbPoint )
+    {
+        OGRPoint *poPoint = (OGRPoint*)poGeom;
+        double x = poPoint->getX();
+        double y = poPoint->getY();
+
+        /* Copy in the raw data. */
+        memcpy( pabyPtr, &x, 8 );
+        memcpy( pabyPtr+8, &y, 8 );
+        if( b3d )
+        {
+            double z = poPoint->getZ();
+            memcpy( pabyPtr+8+8, &z, 8 );
+        }
+
+        /* Swap if needed. Shape doubles always LSB */
+        if( OGR_SWAP( wkbNDR ) )
+        {
+            CPL_SWAPDOUBLE( pabyPtr );
+            CPL_SWAPDOUBLE( pabyPtr+8 );
+            if( b3d )
+                CPL_SWAPDOUBLE( pabyPtr+8+8 );
+        }
+
+        return OGRERR_NONE;    
+    }
+
+/* -------------------------------------------------------------------- */
+/*      All the non-POINT types require an envelope next                */
+/* -------------------------------------------------------------------- */
+    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 );
+
+    /* Swap box if needed. Shape doubles are always LSB */
+    if( OGR_SWAP( wkbNDR ) )
+    {
+        for ( int i = 0; i < 4; i++ )
+            CPL_SWAPDOUBLE( pabyPtr + 8*i );
+    }
+    pabyPtr += 32;
+
+    /* Write in the Z bounds at the end of the XY buffer */
+    if ( b3d )
+    {
+        memcpy( pabyPtrZ, &(envelope.MinZ), 8 );
+        memcpy( pabyPtrZ+8, &(envelope.MaxZ), 8 );
+
+        /* Swap Z bounds if necessary */
+        if( OGR_SWAP( wkbNDR ) )
+        {
+            for ( int i = 0; i < 2; i++ )
+                CPL_SWAPDOUBLE( pabyPtrZ + 8*i );
+        } 
+        pabyPtrZ += 16;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      LINESTRING and LINESTRINGZ                                      */
+/* -------------------------------------------------------------------- */
+    if ( nOGRType == wkbLineString )
+    {
+        const OGRLineString *poLine = (OGRLineString*)poGeom;
+
+        /* Write in the nparts (1) */
+        GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
+        memcpy( pabyPtr, &nPartsLsb, 4 );
+        pabyPtr += 4;
+
+        /* Write in the npoints */
+        GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
+        memcpy( pabyPtr, &nPointsLsb, 4 );
+        pabyPtr += 4;
+
+        /* Write in the part index (0) */
+        GUInt32 nPartIndex = 0;
+        memcpy( pabyPtr, &nPartIndex, 4 );
+        pabyPtr += 4;
+
+        /* Write in the point data */
+        poLine->getPoints((OGRRawPoint*)pabyPtr, (double*)pabyPtrZ);
+
+        /* Swap if necessary */
+        if( OGR_SWAP( wkbNDR ) )
+        {
+            for( GUInt32 k = 0; k < nPoints; k++ )
+            {
+                CPL_SWAPDOUBLE( pabyPtr + 16*k );
+                CPL_SWAPDOUBLE( pabyPtr + 16*k + 8 );
+                if( b3d )
+                    CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+            }
+        }
+        return OGRERR_NONE;    
+
+    }
+/* -------------------------------------------------------------------- */
+/*      POLYGON and POLYGONZ                                            */
+/* -------------------------------------------------------------------- */
+    else if ( nOGRType == wkbPolygon )
+    {
+        OGRPolygon *poPoly = (OGRPolygon*)poGeom;
+
+        /* 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;
+
+/* -------------------------------------------------------------------- */
+/*      Now we have to visit each ring and write an index number into   */
+/*      the parts list, and the coordinates into the points list.       */
+/*      to do it in one pass, we will use three write pointers.         */
+/*      pabyPtr writes the part indexes                                 */
+/*      pabyPoints writes the xy coordinates                            */
+/*      pabyPtrZ writes the z coordinates                               */
+/* -------------------------------------------------------------------- */
+
+        /* Just past the partindex[nparts] array */
+        unsigned char* pabyPoints = pabyPtr + 4*nParts; 
+
+        int nPointIndexCount = 0;
+
+        for( GUInt32 i = 0; i < nParts; i++ )
+        {
+            /* Check our Ring and condition it */
+            OGRLinearRing *poRing;
+            if ( i == 0 ) 
+            {
+                poRing = poPoly->getExteriorRing();
+                /* Outer ring must be clockwise */
+                if ( ! poRing->isClockwise() )
+                    poRing->reverseWindingOrder();
+            }
+            else
+            {
+                poRing = poPoly->getInteriorRing(i-1);
+                /* Inner rings should be anti-clockwise */
+                if ( poRing->isClockwise() )
+                    poRing->reverseWindingOrder();
+            }
+
+            int nRingNumPoints = poRing->getNumPoints();
+
+            /* Cannot write un-closed rings to shape */
+            if( nRingNumPoints <= 2 || ! poRing->get_IsClosed() )
+                return OGRERR_FAILURE;
+
+            /* Write in the part index */
+            GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
+            memcpy( pabyPtr, &nPartIndex, 4 );
+
+            /* Write in the point data */
+            poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
+
+            /* Swap if necessary */
+            if( OGR_SWAP( wkbNDR ) )
+            {
+                for( int k = 0; k < nRingNumPoints; k++ )
+                {
+                    CPL_SWAPDOUBLE( pabyPoints + 16*k );
+                    CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
+                    if( b3d )
+                        CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+                }
+            }
+
+            nPointIndexCount += nRingNumPoints;
+            /* Advance the write pointers */
+            pabyPtr += 4;
+            pabyPoints += 16 * nRingNumPoints;
+            if ( b3d )
+                pabyPtrZ += 8 * nRingNumPoints; 
+        }
+
+        return OGRERR_NONE;
+
+    }
+/* -------------------------------------------------------------------- */
+/*      MULTIPOINT and MULTIPOINTZ                                      */
+/* -------------------------------------------------------------------- */
+    else if ( nOGRType == wkbMultiPoint )
+    {
+        OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
+
+        /* Write in the total point count */
+        GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
+        memcpy( pabyPtr, &nPointsLsb, 4 );
+        pabyPtr += 4;
+
+/* -------------------------------------------------------------------- */
+/*      Now we have to visit each point write it into the points list   */
+/*      We will use two write pointers.                                 */
+/*      pabyPtr writes the xy coordinates                               */
+/*      pabyPtrZ writes the z coordinates                               */
+/* -------------------------------------------------------------------- */
+
+        for( GUInt32 i = 0; i < nPoints; i++ )
+        {
+            const OGRPoint *poPt = (OGRPoint*)(poMPoint->getGeometryRef(i));
+
+            /* Skip empties */
+            if ( poPt->IsEmpty() ) 
+                continue;
+
+            /* Write the coordinates */
+            double x = poPt->getX();
+            double y = poPt->getY();
+            memcpy(pabyPtr, &x, 8);
+            memcpy(pabyPtr+8, &y, 8);
+            if ( b3d )
+            {
+                double z = poPt->getZ();
+                memcpy(pabyPtrZ, &z, 8);
+            }
+
+            /* Swap if necessary */
+            if( OGR_SWAP( wkbNDR ) )
+            {
+                CPL_SWAPDOUBLE( pabyPtr );
+                CPL_SWAPDOUBLE( pabyPtr + 8 );
+                if( b3d )
+                    CPL_SWAPDOUBLE( pabyPtrZ );
+            }
+
+            /* Advance the write pointers */
+            pabyPtr += 16;
+            if ( b3d )
+                pabyPtrZ += 8; 
+        }    
+
+        return OGRERR_NONE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      MULTILINESTRING and MULTILINESTRINGZ                            */
+/* -------------------------------------------------------------------- */
+    else if ( nOGRType == wkbMultiLineString )
+    {
+        OGRMultiLineString *poMLine = (OGRMultiLineString*)poGeom;
+
+        /* 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;
+
+        /* Just past the partindex[nparts] array */
+        unsigned char* pabyPoints = pabyPtr + 4*nParts; 
+
+        int nPointIndexCount = 0;
+
+        for( GUInt32 i = 0; i < nParts; i++ )
+        {
+            const OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
+
+            /* Skip empties */
+            if ( poLine->IsEmpty() ) 
+                continue;
+
+            int nLineNumPoints = poLine->getNumPoints();
+
+            /* Write in the part index */
+            GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
+            memcpy( pabyPtr, &nPartIndex, 4 );
+
+            /* Write in the point data */
+            poLine->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
+
+            /* Swap if necessary */
+            if( OGR_SWAP( wkbNDR ) )
+            {
+                for( int k = 0; k < nLineNumPoints; k++ )
+                {
+                    CPL_SWAPDOUBLE( pabyPoints + 16*k );
+                    CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
+                    if( b3d )
+                        CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+                }
+            }
+
+            nPointIndexCount += nLineNumPoints;
+
+            /* Advance the write pointers */
+            pabyPtr += 4;
+            pabyPoints += 16 * nLineNumPoints;
+            if ( b3d )
+                pabyPtrZ += 8 * nLineNumPoints; 
+        }
+
+        return OGRERR_NONE;      
+
+    }
+/* -------------------------------------------------------------------- */
+/*      MULTIPOLYGON and MULTIPOLYGONZ                                  */
+/* -------------------------------------------------------------------- */
+    else if ( nOGRType == wkbMultiPolygon )
+    {
+        OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
+
+        /* 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;
+
+/* -------------------------------------------------------------------- */
+/*      Now we have to visit each ring and write an index number into   */
+/*      the parts list, and the coordinates into the points list.       */
+/*      to do it in one pass, we will use three write pointers.         */
+/*      pabyPtr writes the part indexes                                 */
+/*      pabyPoints writes the xy coordinates                            */
+/*      pabyPtrZ writes the z coordinates                               */
+/* -------------------------------------------------------------------- */
+
+        /* Just past the partindex[nparts] array */
+        unsigned char* pabyPoints = pabyPtr + 4*nParts; 
+
+        int nPointIndexCount = 0;
+
+        for( int i = 0; i < poMPoly->getNumGeometries(); i++ )
+        {
+            OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(i));
+
+            /* Skip empties */
+            if ( poPoly->IsEmpty() ) 
+                continue;
+
+            int nRings = 1 + poPoly->getNumInteriorRings();
+
+            for( int j = 0; j < nRings; j++ )
+            {
+                /* Check our Ring and condition it */
+                OGRLinearRing *poRing;
+                if ( j == 0 )
+                {
+                    poRing = poPoly->getExteriorRing();
+                    /* Outer ring must be clockwise */
+                    if ( ! poRing->isClockwise() )
+                        poRing->reverseWindingOrder();
+                }
+                else
+                {
+                    poRing = poPoly->getInteriorRing(j-1);
+                    /* Inner rings should be anti-clockwise */
+                    if ( poRing->isClockwise() )
+                        poRing->reverseWindingOrder();
+                }
+
+                int nRingNumPoints = poRing->getNumPoints();
+
+                /* Cannot write closed rings to shape */
+                if( nRingNumPoints <= 2 || ! poRing->get_IsClosed() )
+                    return OGRERR_FAILURE;
+
+                /* Write in the part index */
+                GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
+                memcpy( pabyPtr, &nPartIndex, 4 );
+
+                /* Write in the point data */
+                poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
+
+                /* Swap if necessary */
+                if( OGR_SWAP( wkbNDR ) )
+                {
+                    for( int k = 0; k < nRingNumPoints; k++ )
+                    {
+                        CPL_SWAPDOUBLE( pabyPoints + 16*k );
+                        CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
+                        if( b3d )
+                            CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
+                    }
+                }
+
+                nPointIndexCount += nRingNumPoints;
+                /* Advance the write pointers */
+                pabyPtr += 4;
+                pabyPoints += 16 * nRingNumPoints;
+                if ( b3d )
+                    pabyPtrZ += 8 * nRingNumPoints; 
+            }
+        }
+
+        return OGRERR_NONE;
+
+    }
+    else
+    {
+        return OGRERR_UNSUPPORTED_OPERATION;
+    }
+
+}  
+
+
+/************************************************************************/
+/*                      OGRCreateFromShapeBin()                         */
+/*                                                                      */
+/*      Translate shapefile binary representation to an OGR             */
+/*      geometry.                                                       */
+/************************************************************************/
+
+OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
+                              OGRGeometry **ppoGeom,
+                              int nBytes )
+
+{
+    *ppoGeom = NULL;
+
+    if( nBytes < 4 )
+    {    
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Shape buffer size (%d) too small",
+                 nBytes);
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*  Detect zlib compressed shapes and uncompress buffer if necessary    */
+/*  NOTE: this seems to be an undocumented feature, even in the         */
+/*  extended_shapefile_format.pdf found in the FileGDB API documentation*/
+/* -------------------------------------------------------------------- */
+    if( nBytes >= 14 &&
+        pabyShape[12] == 0x78 && pabyShape[13] == 0xDA /* zlib marker */)
+    {
+        GInt32 nUncompressedSize, nCompressedSize;
+        memcpy( &nUncompressedSize, pabyShape + 4, 4 );
+        memcpy( &nCompressedSize, pabyShape + 8, 4 );
+        CPL_LSBPTR32( &nUncompressedSize );
+        CPL_LSBPTR32( &nCompressedSize );
+        if (nCompressedSize + 12 == nBytes &&
+            nUncompressedSize > 0)
+        {
+            GByte* pabyUncompressedBuffer = (GByte*)VSIMalloc(nUncompressedSize);
+            if (pabyUncompressedBuffer == NULL)
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory,
+                         "Cannot allocate %d bytes to uncompress zlib buffer",
+                         nUncompressedSize);
+                return OGRERR_FAILURE;
+            }
+
+            z_stream      stream;
+            stream.zalloc = (alloc_func)0;
+            stream.zfree = (free_func)0;
+            stream.opaque = (voidpf)0;
+            stream.next_in = pabyShape + 12;
+            stream.next_out = pabyUncompressedBuffer;
+            stream.avail_in = nCompressedSize;
+            stream.avail_out = nUncompressedSize;
+            int err;
+            if ( (err = inflateInit(&stream)) != Z_OK )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "inflateInit() failed : err code = %d", err);
+                VSIFree(pabyUncompressedBuffer);
+                return OGRERR_FAILURE;
+            }
+            if ( (err = inflate(&stream, Z_NO_FLUSH)) != Z_STREAM_END )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "inflate() failed : err code = %d", err);
+                VSIFree(pabyUncompressedBuffer);
+                inflateEnd(&stream);
+                return OGRERR_FAILURE;
+            }
+            if (stream.avail_in != 0)
+            {
+                CPLDebug("OGR", "%d remaining in bytes after zlib uncompression",
+                         stream.avail_in);
+            }
+            if (stream.avail_out != 0)
+            {
+                CPLDebug("OGR", "%d remaining out bytes after zlib uncompression",
+                         stream.avail_out);
+            }
+
+            inflateEnd(&stream);
+
+            OGRErr eErr = OGRCreateFromShapeBin(pabyUncompressedBuffer,
+                                                ppoGeom,
+                                                nUncompressedSize - stream.avail_out);
+
+            VSIFree(pabyUncompressedBuffer);
+
+            return eErr;
+        }
+    }
+
+    int nSHPType = pabyShape[0];
+
+/* -------------------------------------------------------------------- */
+/*      Return a NULL geometry when SHPT_NULL is encountered.           */
+/*      Watch out, null return does not mean "bad data" it means        */
+/*      "no geometry here". Watch the OGRErr for the error status       */
+/* -------------------------------------------------------------------- */
+    if ( nSHPType == SHPT_NULL )
+    {
+      *ppoGeom = NULL;
+      return OGRERR_NONE;
+    }
+
+//    CPLDebug( "PGeo",
+//              "Shape type read from PGeo data is nSHPType = %d",
+//              nSHPType );
+
+/* -------------------------------------------------------------------- */
+/*      TODO: These types include additional attributes including       */
+/*      non-linear segments and such. They should be handled.           */
+/*      This is documented in the extended_shapefile_format.pdf         */
+/*      from the FileGDB API                                            */
+/* -------------------------------------------------------------------- */
+    switch( nSHPType )
+    {
+      case SHPT_GENERALPOLYLINE:
+        nSHPType = SHPT_ARC;
+        break;
+      case SHPT_GENERALPOLYGON:
+        nSHPType = SHPT_POLYGON;
+        break;
+      case SHPT_GENERALPOINT:
+        nSHPType = SHPT_POINT;
+        break;
+      case SHPT_GENERALMULTIPOINT:
+        nSHPType = SHPT_MULTIPOINT;
+        break;
+      case SHPT_GENERALMULTIPATCH:
+        nSHPType = SHPT_MULTIPATCH;
+    }
+
+/* ==================================================================== */
+/*  Extract vertices for a Polygon or Arc.              */
+/* ==================================================================== */
+    if(    nSHPType == SHPT_ARC
+        || nSHPType == SHPT_ARCZ
+        || nSHPType == SHPT_ARCM
+        || nSHPType == SHPT_ARCZM
+        || nSHPType == SHPT_POLYGON
+        || nSHPType == SHPT_POLYGONZ
+        || nSHPType == SHPT_POLYGONM
+        || nSHPType == SHPT_POLYGONZM
+        || nSHPType == SHPT_MULTIPATCH
+        || nSHPType == SHPT_MULTIPATCHM)
+    {
+        GInt32         nPoints, nParts;
+        int            i, nOffset;
+        GInt32         *panPartStart;
+        GInt32         *panPartType = NULL;
+
+        if (nBytes < 44)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
+            return OGRERR_FAILURE;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Extract part/point count, and build vertex and part arrays      */
+/*      to proper size.                                                 */
+/* -------------------------------------------------------------------- */
+        memcpy( &nPoints, pabyShape + 40, 4 );
+        memcpy( &nParts, pabyShape + 36, 4 );
+
+        CPL_LSBPTR32( &nPoints );
+        CPL_LSBPTR32( &nParts );
+
+        if (nPoints < 0 || nParts < 0 ||
+            nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d.",
+                     nPoints, nParts);
+            return OGRERR_FAILURE;
+        }
+
+        int bHasZ = (  nSHPType == SHPT_POLYGONZ
+                    || nSHPType == SHPT_POLYGONZM
+                    || nSHPType == SHPT_ARCZ
+                    || nSHPType == SHPT_ARCZM
+                    || nSHPType == SHPT_MULTIPATCH
+                    || nSHPType == SHPT_MULTIPATCHM );
+
+        int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM );
+
+        /* With the previous checks on nPoints and nParts, */
+        /* we should not overflow here and after */
+        /* since 50 M * (16 + 8 + 8) = 1 600 MB */
+        int nRequiredSize = 44 + 4 * nParts + 16 * nPoints;
+        if ( bHasZ )
+        {
+            nRequiredSize += 16 + 8 * nPoints;
+        }
+        if( bIsMultiPatch )
+        {
+            nRequiredSize += 4 * nParts;
+        }
+        if (nRequiredSize > nBytes)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d",
+                     nPoints, nParts, nBytes, nSHPType);
+            return OGRERR_FAILURE;
+        }
+
+        panPartStart = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
+        if (panPartStart == NULL)
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory,
+                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
+            return OGRERR_FAILURE;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Copy out the part array from the record.                        */
+/* -------------------------------------------------------------------- */
+        memcpy( panPartStart, pabyShape + 44, 4 * nParts );
+        for( i = 0; i < nParts; i++ )
+        {
+            CPL_LSBPTR32( panPartStart + i );
+
+            /* We check that the offset is inside the vertex array */
+            if (panPartStart[i] < 0 ||
+                panPartStart[i] >= nPoints)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d",
+                        i, panPartStart[i], nPoints);
+                CPLFree(panPartStart);
+                return OGRERR_FAILURE;
+            }
+            if (i > 0 && panPartStart[i] <= panPartStart[i-1])
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Corrupted Shape : panPartStart[%d] = %d, panPartStart[%d] = %d",
+                        i, panPartStart[i], i - 1, panPartStart[i - 1]);
+                CPLFree(panPartStart);
+                return OGRERR_FAILURE;
+            }
+        }
+
+        nOffset = 44 + 4*nParts;
+
+/* -------------------------------------------------------------------- */
+/*      If this is a multipatch, we will also have parts types.         */
+/* -------------------------------------------------------------------- */
+        if( bIsMultiPatch )
+        {
+            panPartType = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
+            if (panPartType == NULL)
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory,
+                        "Not enough memory for panPartType for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
+                CPLFree(panPartStart);
+                return OGRERR_FAILURE;
+            }
+
+            memcpy( panPartType, pabyShape + nOffset, 4*nParts );
+            for( i = 0; i < nParts; i++ )
+            {
+                CPL_LSBPTR32( panPartType + i );
+            }
+            nOffset += 4*nParts;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Copy out the vertices from the record.                          */
+/* -------------------------------------------------------------------- */
+        double *padfX = (double *) VSIMalloc(sizeof(double)*nPoints);
+        double *padfY = (double *) VSIMalloc(sizeof(double)*nPoints);
+        double *padfZ = (double *) VSICalloc(sizeof(double),nPoints);
+        if (padfX == NULL || padfY == NULL || padfZ == NULL)
+        {
+            CPLFree( panPartStart );
+            CPLFree( panPartType );
+            CPLFree( padfX );
+            CPLFree( padfY );
+            CPLFree( padfZ );
+            CPLError(CE_Failure, CPLE_OutOfMemory,
+                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
+            return OGRERR_FAILURE;
+        }
+
+        for( i = 0; i < nPoints; i++ )
+        {
+            memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
+            memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
+            CPL_LSBPTR64( padfX + i );
+            CPL_LSBPTR64( padfY + i );
+        }
+
+        nOffset += 16*nPoints;
+
+/* -------------------------------------------------------------------- */
+/*      If we have a Z coordinate, collect that now.                    */
+/* -------------------------------------------------------------------- */
+        if( bHasZ )
+        {
+            for( i = 0; i < nPoints; i++ )
+            {
+                memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
+                CPL_LSBPTR64( padfZ + i );
+            }
+
+            nOffset += 16 + 8*nPoints;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Build corresponding OGR objects.                                */
+/* -------------------------------------------------------------------- */
+        if(    nSHPType == SHPT_ARC
+            || nSHPType == SHPT_ARCZ
+            || nSHPType == SHPT_ARCM
+            || nSHPType == SHPT_ARCZM )
+        {
+/* -------------------------------------------------------------------- */
+/*      Arc - As LineString                                             */
+/* -------------------------------------------------------------------- */
+            if( nParts == 1 )
+            {
+                OGRLineString *poLine = new OGRLineString();
+                *ppoGeom = poLine;
+
+                poLine->setPoints( nPoints, padfX, padfY, padfZ );
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Arc - As MultiLineString                                        */
+/* -------------------------------------------------------------------- */
+            else
+            {
+                OGRMultiLineString *poMulti = new OGRMultiLineString;
+                *ppoGeom = poMulti;
+
+                for( i = 0; i < nParts; i++ )
+                {
+                    OGRLineString *poLine = new OGRLineString;
+                    int nVerticesInThisPart;
+
+                    if( i == nParts-1 )
+                        nVerticesInThisPart = nPoints - panPartStart[i];
+                    else
+                        nVerticesInThisPart =
+                            panPartStart[i+1] - panPartStart[i];
+
+                    poLine->setPoints( nVerticesInThisPart,
+                                       padfX + panPartStart[i],
+                                       padfY + panPartStart[i],
+                                       padfZ + panPartStart[i] );
+
+                    poMulti->addGeometryDirectly( poLine );
+                }
+            }
+        } /* ARC */
+
+/* -------------------------------------------------------------------- */
+/*      Polygon                                                         */
+/* -------------------------------------------------------------------- */
+        else if(    nSHPType == SHPT_POLYGON
+                 || nSHPType == SHPT_POLYGONZ
+                 || nSHPType == SHPT_POLYGONM
+                 || nSHPType == SHPT_POLYGONZM )
+        {
+            if (nParts != 0)
+            {
+                if (nParts == 1)
+                {
+                    OGRPolygon *poOGRPoly = new OGRPolygon;
+                    *ppoGeom = poOGRPoly;
+                    OGRLinearRing *poRing = new OGRLinearRing;
+                    int nVerticesInThisPart = nPoints - panPartStart[0];
+
+                    poRing->setPoints( nVerticesInThisPart,
+                                       padfX + panPartStart[0],
+                                       padfY + panPartStart[0],
+                                       padfZ + panPartStart[0] );
+
+                    poOGRPoly->addRingDirectly( poRing );
+                }
+                else
+                {
+                    OGRGeometry *poOGR = NULL;
+                    OGRPolygon** tabPolygons = new OGRPolygon*[nParts];
+
+                    for( i = 0; i < nParts; i++ )
+                    {
+                        tabPolygons[i] = new OGRPolygon();
+                        OGRLinearRing *poRing = new OGRLinearRing;
+                        int nVerticesInThisPart;
+
+                        if( i == nParts-1 )
+                            nVerticesInThisPart = nPoints - panPartStart[i];
+                        else
+                            nVerticesInThisPart =
+                                panPartStart[i+1] - panPartStart[i];
+
+                        poRing->setPoints( nVerticesInThisPart,
+                                           padfX + panPartStart[i],
+                                           padfY + panPartStart[i],
+                                           padfZ + panPartStart[i] );
+                        tabPolygons[i]->addRingDirectly(poRing);
+                    }
+
+                    int isValidGeometry;
+                    const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
+                    poOGR = OGRGeometryFactory::organizePolygons(
+                        (OGRGeometry**)tabPolygons, nParts, &isValidGeometry, papszOptions );
+
+                    if (!isValidGeometry)
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Geometry of polygon cannot be translated to Simple Geometry. "
+                                 "All polygons will be contained in a multipolygon.\n");
+                    }
+
+                    *ppoGeom = poOGR;
+                    delete[] tabPolygons;
+                }
+            }
+        } /* polygon */
+
+/* -------------------------------------------------------------------- */
+/*      Multipatch                                                      */
+/* -------------------------------------------------------------------- */
+        else if( bIsMultiPatch )
+        {
+            *ppoGeom = OGRCreateFromMultiPatch( nParts,
+                                                panPartStart,
+                                                panPartType,
+                                                nPoints,
+                                                padfX,
+                                                padfY,
+                                                padfZ );
+        }
+
+        CPLFree( panPartStart );
+        CPLFree( panPartType );
+        CPLFree( padfX );
+        CPLFree( padfY );
+        CPLFree( padfZ );
+
+        (*ppoGeom)->setCoordinateDimension( bHasZ ? 3 : 2 );
+
+        return OGRERR_NONE;
+    }
+
+/* ==================================================================== */
+/*  Extract vertices for a MultiPoint.                  */
+/* ==================================================================== */
+    else if(    nSHPType == SHPT_MULTIPOINT
+             || nSHPType == SHPT_MULTIPOINTM
+             || nSHPType == SHPT_MULTIPOINTZ
+             || nSHPType == SHPT_MULTIPOINTZM )
+    {
+      GInt32 nPoints;
+      GInt32 nOffsetZ;
+      int i;
+
+      int bHasZ = (  nSHPType == SHPT_MULTIPOINTZ
+                  || nSHPType == SHPT_MULTIPOINTZM );
+
+                
+      memcpy( &nPoints, pabyShape + 36, 4 );
+      CPL_LSBPTR32( &nPoints );
+
+      if (nPoints < 0 || nPoints > 50 * 1000 * 1000 )
+      {
+          CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d.",
+                   nPoints);
+          return OGRERR_FAILURE;
+      }
+
+      nOffsetZ = 40 + 2*8*nPoints + 2*8;
+    
+      OGRMultiPoint *poMultiPt = new OGRMultiPoint;
+      *ppoGeom = poMultiPt;
+
+      for( i = 0; i < nPoints; i++ )
+      {
+          double x, y, z;
+          OGRPoint *poPt = new OGRPoint;
+        
+          /* Copy X */
+          memcpy(&x, pabyShape + 40 + i*16, 8);
+          CPL_LSBPTR64(&x);
+          poPt->setX(x);
+        
+          /* Copy Y */
+          memcpy(&y, pabyShape + 40 + i*16 + 8, 8);
+          CPL_LSBPTR64(&y);
+          poPt->setY(y);
+        
+          /* Copy Z */
+          if ( bHasZ )
+          {
+            memcpy(&z, pabyShape + nOffsetZ + i*8, 8);
+            CPL_LSBPTR64(&z);
+            poPt->setZ(z);
+          }
+        
+          poMultiPt->addGeometryDirectly( poPt );
+      }
+      
+      poMultiPt->setCoordinateDimension( bHasZ ? 3 : 2 );
+      
+      return OGRERR_NONE;
+    }
+
+/* ==================================================================== */
+/*      Extract vertices for a point.                                   */
+/* ==================================================================== */
+    else if(    nSHPType == SHPT_POINT
+             || nSHPType == SHPT_POINTM
+             || nSHPType == SHPT_POINTZ
+             || nSHPType == SHPT_POINTZM )
+    {
+        int nOffset;
+        double  dfX, dfY, dfZ = 0;
+
+        int bHasZ = (nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM);
+
+        if (nBytes < 4 + 8 + 8 + ((bHasZ) ? 8 : 0))
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
+            return OGRERR_FAILURE;
+        }
+
+        memcpy( &dfX, pabyShape + 4, 8 );
+        memcpy( &dfY, pabyShape + 4 + 8, 8 );
+
+        CPL_LSBPTR64( &dfX );
+        CPL_LSBPTR64( &dfY );
+        nOffset = 20 + 8;
+
+        if( bHasZ )
+        {
+            memcpy( &dfZ, pabyShape + 4 + 16, 8 );
+            CPL_LSBPTR64( &dfZ );
+        }
+
+        *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
+        (*ppoGeom)->setCoordinateDimension( bHasZ ? 3 : 2 );
+
+        return OGRERR_NONE;
+    }
+
+    CPLError(CE_Failure, CPLE_AppDefined,
+             "Unsupported geometry type: %d", 
+              nSHPType );
+
+    return OGRERR_FAILURE;
+}
diff --git a/ogr/ogrpgeogeometry.h b/ogr/ogrpgeogeometry.h
new file mode 100644
index 0000000..cd2f188
--- /dev/null
+++ b/ogr/ogrpgeogeometry.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * $Id: ogrpgeogeometry.h 22525 2011-06-11 02:18:49Z rburhum $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements decoder of shapebin geometry for PGeo
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2005, 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_PGEOGEOMETRY_H_INCLUDED
+#define _OGR_PGEOGEOMETRY_H_INCLUDED
+
+#include "ogr_geometry.h"
+
+#define SHPT_NULL          0
+
+#define SHPT_POINT         1
+#define SHPT_POINTM       21
+#define SHPT_POINTZM      11
+#define SHPT_POINTZ        9
+
+#define SHPT_MULTIPOINT    8
+#define SHPT_MULTIPOINTM  28
+#define SHPT_MULTIPOINTZM 18
+#define SHPT_MULTIPOINTZ  20
+
+#define SHPT_ARC           3
+#define SHPT_ARCM         23
+#define SHPT_ARCZM        13
+#define SHPT_ARCZ         10
+
+#define SHPT_POLYGON       5
+#define SHPT_POLYGONM     25
+#define SHPT_POLYGONZM    15
+#define SHPT_POLYGONZ     19
+
+#define SHPT_MULTIPATCHM  31
+#define SHPT_MULTIPATCH   32
+
+#define SHPT_GENERALPOLYLINE    50
+#define SHPT_GENERALPOLYGON     51
+#define SHPT_GENERALPOINT       52
+#define SHPT_GENERALMULTIPOINT  53
+#define SHPT_GENERALMULTIPATCH  54
+
+/* The following are layers geometry type */
+/* They are different from the above shape types */
+#define ESRI_LAYERGEOMTYPE_NULL          0
+#define ESRI_LAYERGEOMTYPE_POINT         1
+#define ESRI_LAYERGEOMTYPE_MULTIPOINT    2
+#define ESRI_LAYERGEOMTYPE_POLYLINE      3
+#define ESRI_LAYERGEOMTYPE_POLYGON       4
+#define ESRI_LAYERGEOMTYPE_MULTIPATCH    9
+
+
+OGRErr CPL_DLL OGRCreateFromShapeBin( GByte *pabyShape,
+                              OGRGeometry **ppoGeom,
+                              int nBytes );
+
+OGRErr CPL_DLL OGRWriteToShapeBin( OGRGeometry *poGeom, 
+                           GByte **ppabyShape,
+                           int *pnBytes );
+
+
+#endif
diff --git a/ogr/ogrpoint.cpp b/ogr/ogrpoint.cpp
index 4697c8c..f4121cf 100644
--- a/ogr/ogrpoint.cpp
+++ b/ogr/ogrpoint.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpoint.cpp 20260 2010-08-11 20:39:54Z rouault $
+ * $Id: ogrpoint.cpp 22448 2011-05-28 18:49:54Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The Point geometry class.
@@ -30,7 +30,7 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpoint.cpp 20260 2010-08-11 20:39:54Z rouault $");
+CPL_CVSID("$Id: ogrpoint.cpp 22448 2011-05-28 18:49:54Z rouault $");
 
 /************************************************************************/
 /*                              OGRPoint()                              */
@@ -487,6 +487,17 @@ void OGRPoint::getEnvelope( OGREnvelope * psEnvelope ) const
     psEnvelope->MinY = psEnvelope->MaxY = getY();
 }
 
+/************************************************************************/
+/*                            getEnvelope()                             */
+/************************************************************************/
+
+void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
+
+{
+    psEnvelope->MinX = psEnvelope->MaxX = getX();
+    psEnvelope->MinY = psEnvelope->MaxY = getY();
+    psEnvelope->MinZ = psEnvelope->MaxZ = getZ();
+}
 
 
 /**
diff --git a/ogr/ogrpolygon.cpp b/ogr/ogrpolygon.cpp
index ea40b53..d2c085c 100644
--- a/ogr/ogrpolygon.cpp
+++ b/ogr/ogrpolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpolygon.cpp 20260 2010-08-11 20:39:54Z rouault $
+ * $Id: ogrpolygon.cpp 22466 2011-05-30 09:24:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRPolygon geometry class.
@@ -32,7 +32,7 @@
 #include "ogr_geos.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrpolygon.cpp 20260 2010-08-11 20:39:54Z rouault $");
+CPL_CVSID("$Id: ogrpolygon.cpp 22466 2011-05-30 09:24:55Z rouault $");
 
 /************************************************************************/
 /*                             OGRPolygon()                             */
@@ -522,19 +522,11 @@ OGRErr OGRPolygon::importFromWkt( char ** ppszInput )
 {
     char        szToken[OGR_WKT_TOKEN_MAX];
     const char  *pszInput = *ppszInput;
-    int         iRing;
 
 /* -------------------------------------------------------------------- */
 /*      Clear existing rings.                                           */
 /* -------------------------------------------------------------------- */
-    if( nRingCount > 0 )
-    {
-        for( iRing = 0; iRing < nRingCount; iRing++ )
-            delete papoRings[iRing];
-        
-        nRingCount = 0;
-        CPLFree( papoRings );
-    }
+    empty();
 
 /* -------------------------------------------------------------------- */
 /*      Read and verify the ``POLYGON'' keyword token.                  */
@@ -869,7 +861,7 @@ int OGRPolygon::PointOnSurface( OGRPoint *poPoint ) const
 /************************************************************************/
 /*                            getEnvelope()                             */
 /************************************************************************/
- 
+
 void OGRPolygon::getEnvelope( OGREnvelope * psEnvelope ) const
 
 {
@@ -909,6 +901,53 @@ void OGRPolygon::getEnvelope( OGREnvelope * psEnvelope ) const
 }
 
 /************************************************************************/
+/*                            getEnvelope()                             */
+/************************************************************************/
+ 
+void OGRPolygon::getEnvelope( OGREnvelope3D * psEnvelope ) const
+
+{
+    OGREnvelope3D       oRingEnv;
+    int                 bExtentSet = FALSE;
+
+    for( int iRing = 0; iRing < nRingCount; iRing++ )
+    {
+        if (!papoRings[iRing]->IsEmpty())
+        {
+            if (!bExtentSet)
+            {
+                papoRings[iRing]->getEnvelope( psEnvelope );
+                bExtentSet = TRUE;
+            }
+            else
+            {
+                papoRings[iRing]->getEnvelope( &oRingEnv );
+
+                if( psEnvelope->MinX > oRingEnv.MinX )
+                    psEnvelope->MinX = oRingEnv.MinX;
+                if( psEnvelope->MinY > oRingEnv.MinY )
+                    psEnvelope->MinY = oRingEnv.MinY;
+                if( psEnvelope->MaxX < oRingEnv.MaxX )
+                    psEnvelope->MaxX = oRingEnv.MaxX;
+                if( psEnvelope->MaxY < oRingEnv.MaxY )
+                    psEnvelope->MaxY = oRingEnv.MaxY;
+
+                if( psEnvelope->MinZ > oRingEnv.MinZ )
+                    psEnvelope->MinZ = oRingEnv.MinZ;
+                if( psEnvelope->MaxZ < oRingEnv.MaxZ )
+                    psEnvelope->MaxZ = oRingEnv.MaxZ;
+            }
+        }
+    }
+
+    if (!bExtentSet)
+    {
+        psEnvelope->MinX = psEnvelope->MinY = psEnvelope->MinZ = 0;
+        psEnvelope->MaxX = psEnvelope->MaxY = psEnvelope->MaxZ = 0;
+    }
+}
+
+/************************************************************************/
 /*                               Equal()                                */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/GNUmakefile b/ogr/ogrsf_frmts/GNUmakefile
index 1a3ae9d..d3a9205 100644
--- a/ogr/ogrsf_frmts/GNUmakefile
+++ b/ogr/ogrsf_frmts/GNUmakefile
@@ -5,7 +5,8 @@ SUBDIRS-yes	:= \
 	generic avc bna csv dgn geojson gml gmt mem kml \
 	mitab ntf gpx rec s57 sdts shape tiger vrt \
 	geoconcept xplane georss gtm dxf pgdump gpsbabel \
-	sua openair pds htf aeronavfaa
+	sua openair pds htf aeronavfaa edigeo svg idrisi \
+	arcgen segukooa segy
 
 SUBDIRS-$(HAVE_DODS)	+= dods
 SUBDIRS-$(HAVE_DWGDIRECT) += dxfdwg
@@ -15,17 +16,22 @@ SUBDIRS-$(HAVE_IDB)	+= idb
 SUBDIRS-$(HAVE_XERCES)	+= ili
 SUBDIRS-$(HAVE_NAS)	+= nas
 SUBDIRS-$(HAVE_MYSQL)	+= mysql
-SUBDIRS-$(ODBC_SETTING)	+= odbc pgeo mssqlspatial
+SUBDIRS-$(ODBC_SETTING)	+= odbc pgeo mssqlspatial geomedia
 SUBDIRS-$(HAVE_OGDI)	+= ogdi
 SUBDIRS-$(HAVE_OCI)	+= oci
 SUBDIRS-$(HAVE_OGR_PG)	+= pg
 SUBDIRS-$(HAVE_SQLITE)	+= sqlite
 SUBDIRS-$(HAVE_SDE)     += sde
+SUBDIRS-$(HAVE_FGDB)    += filegdb
 SUBDIRS-$(HAVE_ARCOBJECTS)  += arcobjects
 SUBDIRS-$(HAVE_INGRES)  += ingres
 SUBDIRS-$(HAVE_VFK)     += vfk
 SUBDIRS-$(HAVE_LIBKML)  += libkml
 SUBDIRS-$(CURL_SETTING) += wfs
+SUBDIRS-$(MDB_ENABLED)  += mdb
+SUBDIRS-$(CURL_SETTING) += gft
+SUBDIRS-$(CURL_SETTING) += couchdb
+SUBDIRS-$(HAVE_FREEXL)  += xls
 
 ifeq ($(PCIDSK_SETTING),internal)
 SUBDIRS-yes  += pcidsk
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
index 77bff67..b0c7d17 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograeronavfaadatasource.cpp 21376 2011-01-02 18:28:40Z rouault $
+ * $Id: ograeronavfaadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAADataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ograeronavfaadatasource.cpp 21376 2011-01-02 18:28:40Z rouault $");
+CPL_CVSID("$Id: ograeronavfaadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
 
 /************************************************************************/
 /*                      OGRAeronavFAADataSource()                       */
@@ -97,19 +97,11 @@ int OGRAeronavFAADataSource::Open( const char * pszFilename, int bUpdateIn)
 
     pszName = CPLStrdup( pszFilename );
 
-/* -------------------------------------------------------------------- */
-/*      Determine what sort of object this is.                          */
-/* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
-
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 ||
-        !VSI_ISREG(sStatBuf.st_mode) ||
-        !EQUAL(CPLGetExtension(pszFilename), "dat") )
-        return FALSE;
-    
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 //      Does this appear to be a .dat file?
 // --------------------------------------------------------------------
+    if( !EQUAL(CPLGetExtension(pszFilename), "dat") )
+        return FALSE;
 
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     if (fp == NULL)
diff --git a/ogr/ogrsf_frmts/arcgen/GNUmakefile b/ogr/ogrsf_frmts/arcgen/GNUmakefile
new file mode 100644
index 0000000..1856074
--- /dev/null
+++ b/ogr/ogrsf_frmts/arcgen/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ograrcgendriver.o ograrcgendatasource.o ograrcgenlayer.o
+
+CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_arcgen.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/arcgen/drv_arcgen.html b/ogr/ogrsf_frmts/arcgen/drv_arcgen.html
new file mode 100644
index 0000000..3f6bd9f
--- /dev/null
+++ b/ogr/ogrsf_frmts/arcgen/drv_arcgen.html
@@ -0,0 +1,23 @@
+<html>
+<head>
+<title>ARCGEN - Arc/Info Generate</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ARCGEN - Arc/Info Generate</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver reads files in Arc/Info Generate format. Those files are simple
+ASCII files that contain points, lines or polygons (one type of geometry per
+file).<p>
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="http://courses.washington.edu/gis250/lessons/data_export/index.html#generate">Description of Arc/Info Generate format</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/arcgen/makefile.vc b/ogr/ogrsf_frmts/arcgen/makefile.vc
new file mode 100644
index 0000000..be9cf5d
--- /dev/null
+++ b/ogr/ogrsf_frmts/arcgen/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ograrcgendriver.obj ograrcgendatasource.obj ograrcgenlayer.obj
+EXTRAFLAGS =	-I.. -I..\..
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
new file mode 100644
index 0000000..2744246
--- /dev/null
+++ b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
@@ -0,0 +1,108 @@
+/******************************************************************************
+ * $Id: ogr_arcgen.h 23148 2011-10-01 11:55:08Z 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>
+ *
+ * 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, DAMARCGENS 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_ARCGEN_H_INCLUDED
+#define _OGR_ARCGEN_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+/************************************************************************/
+/*                             OGRARCGENLayer                              */
+/************************************************************************/
+
+class OGRARCGENLayer : public OGRLayer
+{
+    OGRFeatureDefn*    poFeatureDefn;
+
+    VSILFILE*          fp;
+    int                bEOF;
+
+    int                nNextFID;
+
+    OGRFeature *       GetNextRawFeature();
+
+  public:
+                        OGRARCGENLayer(const char* pszFilename,
+                                    VSILFILE* fp, OGRwkbGeometryType eType);
+                        ~OGRARCGENLayer();
+
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    virtual int                 TestCapability( const char * );
+
+    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
+
+};
+
+/************************************************************************/
+/*                           OGRARCGENDataSource                           */
+/************************************************************************/
+
+class OGRARCGENDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+  public:
+                        OGRARCGENDataSource();
+                        ~OGRARCGENDataSource();
+
+    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 * );
+};
+
+/************************************************************************/
+/*                             OGRARCGENDriver                             */
+/************************************************************************/
+
+class OGRARCGENDriver : public OGRSFDriver
+{
+  public:
+                ~OGRARCGENDriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual int                 TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_ARCGEN_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
new file mode 100644
index 0000000..6462b9b
--- /dev/null
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
@@ -0,0 +1,261 @@
+/******************************************************************************
+ * $Id: ograrcgendatasource.cpp 23339 2011-11-06 12:36:29Z 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>
+ *
+ * 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, DAMARCGENS 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_arcgen.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ograrcgendatasource.cpp 23339 2011-11-06 12:36:29Z rouault $");
+
+/************************************************************************/
+/*                          OGRARCGENDataSource()                          */
+/************************************************************************/
+
+OGRARCGENDataSource::OGRARCGENDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+}
+
+/************************************************************************/
+/*                         ~OGRARCGENDataSource()                          */
+/************************************************************************/
+
+OGRARCGENDataSource::~OGRARCGENDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRARCGENDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRARCGENDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRARCGENDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (bUpdateIn)
+    {
+        return FALSE;
+    }
+
+    pszName = CPLStrdup( pszFilename );
+
+// -------------------------------------------------------------------- 
+//      Does this appear to be a Arc/Info generate file?
+// --------------------------------------------------------------------
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+    if (fp == NULL)
+        return FALSE;
+
+    /* Check that the first line is compatible with a generate file */
+    /* and in particular contain >= 32 && <= 127 bytes */
+    char szFirstLine[256+1];
+    int nRet = VSIFReadL(szFirstLine, 1, 256, fp);
+    szFirstLine[nRet] = '\0';
+
+    int i;
+    int bFoundEOL = FALSE;
+    for(i=0;szFirstLine[i] != '\0';i++)
+    {
+        if (szFirstLine[i] == '\n' || szFirstLine[i] == '\r')
+        {
+            bFoundEOL = TRUE;
+            szFirstLine[i] = '\0';
+            break;
+        }
+        if (szFirstLine[i] < 32)
+        {
+            VSIFCloseL(fp);
+            return FALSE;
+        }
+    }
+
+    if (!bFoundEOL)
+    {
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+
+    char** papszTokens = CSLTokenizeString2( szFirstLine, " ,", 0 );
+    int nTokens = CSLCount(papszTokens);
+    CSLDestroy(papszTokens);
+    if (nTokens != 1 && nTokens != 3 && nTokens != 4)
+    {
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+
+    /* Go to end of file, and count the number of END keywords */
+    /* If there's 1, it's a point layer */
+    /* If there's 2, it's a linestring or polygon layer */
+    VSIFSeekL( fp, 0, SEEK_END );
+    vsi_l_offset nSize = VSIFTellL(fp);
+    if (nSize < 10)
+    {
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+    char szBuffer[10+1];
+    VSIFSeekL( fp, nSize - 10, SEEK_SET );
+    VSIFReadL( szBuffer, 1, 10, fp );
+    szBuffer[10] = '\0';
+
+    VSIFSeekL( fp, 0, SEEK_SET );
+
+    OGRwkbGeometryType eType;
+    const char* szPtr = szBuffer;
+    const char* szEnd = strstr(szPtr, "END");
+    if (szEnd == NULL) szEnd = strstr(szPtr, "end");
+    if (szEnd == NULL)
+    {
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+    szPtr = szEnd + 3;
+    szEnd = strstr(szPtr, "END");
+    if (szEnd == NULL) szEnd = strstr(szPtr, "end");
+    if (szEnd == NULL)
+    {
+        const char* pszLine = CPLReadLine2L(fp,256,NULL);
+        if (pszLine == NULL)
+        {
+            VSIFCloseL(fp);
+            return FALSE;
+        }
+        char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
+        int nTokens = CSLCount(papszTokens);
+        CSLDestroy(papszTokens);
+
+        if (nTokens == 3)
+            eType = wkbPoint;
+        else if (nTokens == 4)
+            eType = wkbPoint25D;
+        else
+        {
+            VSIFCloseL(fp);
+            return FALSE;
+        }
+    }
+    else
+    {
+        int nLineNumber = 0;
+        eType = wkbUnknown;
+        CPLString osFirstX, osFirstY;
+        CPLString osLastX, osLastY;
+        int bIs3D = FALSE;
+        const char* pszLine;
+        while((pszLine = CPLReadLine2L(fp,256,NULL)) != NULL)
+        {
+            nLineNumber ++;
+            if (nLineNumber == 2)
+            {
+                char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
+                int nTokens = CSLCount(papszTokens);
+                if (nTokens == 2 || nTokens == 3)
+                {
+                    if (nTokens == 3)
+                        bIs3D = TRUE;
+                    osFirstX = papszTokens[0];
+                    osFirstY = papszTokens[1];
+                }
+                CSLDestroy(papszTokens);
+                if (nTokens != 2 && nTokens != 3)
+                    break;
+            }
+            else if (nLineNumber > 2)
+            {
+                if (EQUAL(pszLine, "END"))
+                {
+                    if (osFirstX.compare(osLastX) == 0 &&
+                        osFirstY.compare(osLastY) == 0)
+                        eType = (bIs3D) ? wkbPolygon25D : wkbPolygon;
+                    else
+                        eType = (bIs3D) ? wkbLineString25D : wkbLineString;
+                    break;
+                }
+
+                char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
+                int nTokens = CSLCount(papszTokens);
+                if (nTokens == 2 || nTokens == 3)
+                {
+                    osLastX = papszTokens[0];
+                    osLastY = papszTokens[1];
+                }
+                CSLDestroy(papszTokens);
+                if (nTokens != 2 && nTokens != 3)
+                    break;
+            }
+        }
+        if (eType == wkbUnknown)
+        {
+            VSIFCloseL(fp);
+            return FALSE;
+        }
+    }
+
+    VSIFSeekL( fp, 0, SEEK_SET );
+
+    nLayers = 1;
+    papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+    papoLayers[0] = new OGRARCGENLayer(pszName, fp, eType);
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
new file mode 100644
index 0000000..7fbd735
--- /dev/null
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * $Id: ograrcgendriver.cpp 23148 2011-10-01 11:55:08Z 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>
+ *
+ * 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, DAMARCGENS 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_arcgen.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ograrcgendriver.cpp 23148 2011-10-01 11:55:08Z rouault $");
+
+extern "C" void RegisterOGRARCGEN();
+
+/************************************************************************/
+/*                           ~OGRARCGENDriver()                            */
+/************************************************************************/
+
+OGRARCGENDriver::~OGRARCGENDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRARCGENDriver::GetName()
+
+{
+    return "ARCGEN";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRARCGENDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRARCGENDataSource   *poDS = new OGRARCGENDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRARCGENDriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRARCGEN()                           */
+/************************************************************************/
+
+void RegisterOGRARCGEN()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRARCGENDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
new file mode 100644
index 0000000..b04f47e
--- /dev/null
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
@@ -0,0 +1,233 @@
+/******************************************************************************
+ * $Id: ograrcgenlayer.cpp 23148 2011-10-01 11:55:08Z 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>
+ *
+ * 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, DAMARCGENS 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_arcgen.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_p.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: ograrcgenlayer.cpp 23148 2011-10-01 11:55:08Z rouault $");
+
+/************************************************************************/
+/*                            OGRARCGENLayer()                             */
+/************************************************************************/
+
+OGRARCGENLayer::OGRARCGENLayer( const char* pszFilename,
+                          VSILFILE* fp, OGRwkbGeometryType eType )
+
+{
+    this->fp = fp;
+    nNextFID = 0;
+    bEOF = FALSE;
+
+    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( eType );
+
+    OGRFieldDefn    oField1( "ID", OFTInteger);
+    poFeatureDefn->AddFieldDefn( &oField1 );
+}
+
+/************************************************************************/
+/*                            ~OGRARCGENLayer()                            */
+/************************************************************************/
+
+OGRARCGENLayer::~OGRARCGENLayer()
+
+{
+    poFeatureDefn->Release();
+
+    VSIFCloseL( fp );
+}
+
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRARCGENLayer::ResetReading()
+
+{
+    nNextFID = 0;
+    bEOF = FALSE;
+    VSIFSeekL( fp, 0, SEEK_SET );
+}
+
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRARCGENLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    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 *OGRARCGENLayer::GetNextRawFeature()
+{
+    if (bEOF)
+        return NULL;
+
+    const char* pszLine;
+    OGRwkbGeometryType eType = poFeatureDefn->GetGeomType();
+
+    if (wkbFlatten(eType) == wkbPoint)
+    {
+        while(TRUE)
+        {
+            pszLine = CPLReadLine2L(fp,256,NULL);
+            if (pszLine == NULL || EQUAL(pszLine, "END"))
+            {
+                bEOF = TRUE;
+                return NULL;
+            }
+            char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
+            int nTokens = CSLCount(papszTokens);
+            if (nTokens == 3 || nTokens == 4)
+            {
+                OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+                poFeature->SetFID(nNextFID ++);
+                poFeature->SetField(0, papszTokens[0]);
+                if (nTokens == 3)
+                    poFeature->SetGeometryDirectly(
+                        new OGRPoint(atof(papszTokens[1]),
+                                     atof(papszTokens[2])));
+                else
+                    poFeature->SetGeometryDirectly(
+                        new OGRPoint(atof(papszTokens[1]),
+                                     atof(papszTokens[2]),
+                                     atof(papszTokens[3])));
+                CSLDestroy(papszTokens);
+                return poFeature;
+            }
+            else
+                CSLDestroy(papszTokens);
+        }
+    }
+
+    CPLString osID;
+    OGRLinearRing* poLR =
+        (wkbFlatten(eType) == wkbPolygon) ? new OGRLinearRing() : NULL;
+    OGRLineString* poLS =
+        (wkbFlatten(eType) == wkbLineString) ? new OGRLineString() : poLR;
+    while(TRUE)
+    {
+        pszLine = CPLReadLine2L(fp,256,NULL);
+        if (pszLine == NULL)
+            break;
+
+        if (EQUAL(pszLine, "END"))
+        {
+            if (osID.size() == 0)
+                break;
+
+            OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+            poFeature->SetFID(nNextFID ++);
+            poFeature->SetField(0, osID.c_str());
+            if (wkbFlatten(eType) == wkbPolygon)
+            {
+                OGRPolygon* poPoly = new OGRPolygon();
+                poPoly->addRingDirectly(poLR);
+                poFeature->SetGeometryDirectly(poPoly);
+            }
+            else
+                poFeature->SetGeometryDirectly(poLS);
+            return poFeature;
+        }
+
+        char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
+        int nTokens = CSLCount(papszTokens);
+        if (osID.size() == 0)
+        {
+            if (nTokens >= 1)
+                osID = papszTokens[0];
+            else
+            {
+                CSLDestroy(papszTokens);
+                break;
+            }
+        }
+        else
+        {
+            if (nTokens == 2)
+            {
+                poLS->addPoint(atof(papszTokens[0]),
+                               atof(papszTokens[1]));
+            }
+            else if (nTokens == 3)
+            {
+                poLS->addPoint(atof(papszTokens[0]),
+                               atof(papszTokens[1]),
+                               atof(papszTokens[2]));
+            }
+            else
+            {
+                CSLDestroy(papszTokens);
+                break;
+            }
+        }
+        CSLDestroy(papszTokens);
+    }
+
+    bEOF = TRUE;
+    delete poLS;
+    return NULL;
+}
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRARCGENLayer::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
diff --git a/ogr/ogrsf_frmts/bna/GNUmakefile b/ogr/ogrsf_frmts/bna/GNUmakefile
index 1d516eb..8ba39c3 100644
--- a/ogr/ogrsf_frmts/bna/GNUmakefile
+++ b/ogr/ogrsf_frmts/bna/GNUmakefile
@@ -4,10 +4,6 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrbnadriver.o ogrbnadatasource.o ogrbnalayer.o ogrbnaparser.o
 
-ifeq ($(HAVE_GEOS),yes)
-CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
-endif
-
 CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/ogr/ogrsf_frmts/bna/drv_bna.html b/ogr/ogrsf_frmts/bna/drv_bna.html
index 49e4f7f..20b33d7 100644
--- a/ogr/ogrsf_frmts/bna/drv_bna.html
+++ b/ogr/ogrsf_frmts/bna/drv_bna.html
@@ -65,9 +65,16 @@ this option may be used to limit the number of coordinate pairs per line in mult
 this option may be used to set the number of decimal for coordinates. Default value is 10.<p>
 <p>
 
+</ul>
 
+<h2>VSI Virtual File System API support</h2>
 
-</ul>
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
 
 <h2>Example</h2>
 
diff --git a/ogr/ogrsf_frmts/bna/makefile.vc b/ogr/ogrsf_frmts/bna/makefile.vc
index 67a426b..c7ae1c8 100644
--- a/ogr/ogrsf_frmts/bna/makefile.vc
+++ b/ogr/ogrsf_frmts/bna/makefile.vc
@@ -2,7 +2,7 @@
 OBJ	=	ogrbnadriver.obj ogrbnadatasource.obj ogrbnalayer.obj \
 		ogrbnaparser.obj
 
-EXTRAFLAGS =	-I.. -I..\.. $(GEOS_CFLAGS)
+EXTRAFLAGS =	-I.. -I..\..
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
index 54f3ed3..414f903 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrbnadatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrbnadatasource.cpp 23244 2011-10-16 21:52:16Z rouault $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNADataSource class
@@ -163,7 +163,7 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
 /* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
 
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
+    if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0 )
         return FALSE;
     
 // -------------------------------------------------------------------- 
@@ -204,7 +204,7 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
 
         while(1)
         {
-            int offset = VSIFTellL(fp);
+            int offset = (int) VSIFTellL(fp);
             int line = curLine;
             record =  BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
             if (ok == FALSE)
@@ -278,6 +278,9 @@ int OGRBNADataSource::Create( const char *pszFilename,
         return FALSE;
     }
 
+    if( strcmp(pszFilename,"/dev/stdout") == 0 )
+        pszFilename = "/vsistdout/";
+
 /* -------------------------------------------------------------------- */
 /*     Do not override exiting file.                                    */
 /* -------------------------------------------------------------------- */
@@ -291,10 +294,7 @@ int OGRBNADataSource::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
     pszName = CPLStrdup( pszFilename );
 
-    if( EQUAL(pszFilename,"stdout") )
-        fpOutput = VSIFOpenL( "/vsistdout/", "wb" );
-    else
-        fpOutput = VSIFOpenL( pszFilename, "wb" );
+    fpOutput = VSIFOpenL( pszFilename, "wb" );
     if( fpOutput == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
diff --git a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
index 40b51d7..2f00959 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrbnalayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrbnalayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNALayer class.
@@ -169,7 +169,7 @@ OGRFeature *OGRBNALayer::GetNextFeature()
     while(1)
     {
         int ok = FALSE;
-        offset = VSIFTellL(fpBNA);
+        offset = (int) VSIFTellL(fpBNA);
         line = curLine;
         if (nNextFID < nFeatures)
         {
@@ -787,7 +787,7 @@ void OGRBNALayer::FastParseUntil ( int interestFID)
         while(1)
         {
             int ok = FALSE;
-            int offset = VSIFTellL(fpBNA);
+            int offset = (int) VSIFTellL(fpBNA);
             int line = curLine;
             record =  BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, BNA_READ_NONE);
             if (ok == FALSE)
diff --git a/ogr/ogrsf_frmts/couchdb/GNUmakefile b/ogr/ogrsf_frmts/couchdb/GNUmakefile
new file mode 100644
index 0000000..d34074b
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+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)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_couchdb.h ../geojson/ogrgeojsonreader.h ../geojson/ogrgeojsonwriter.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/couchdb/drv_couchdb.html b/ogr/ogrsf_frmts/couchdb/drv_couchdb.html
new file mode 100644
index 0000000..3eaa65e
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/drv_couchdb.html
@@ -0,0 +1,114 @@
+<html>
+<head>
+<title>CouchDB - CouchDB/GeoCouch</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>CouchDB - CouchDB/GeoCouch</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver can connect to the a CouchDB service, potentially enabled with the GeoCouch spatial extension.<p>
+GDAL/OGR must be built with Curl support in order to the CouchDB driver to be compiled.<p>
+The driver supports read and write operations.<p>
+
+<h2>CouchDB vs OGR concepts</h2>
+
+A CouchDB database is considered as a OGR layer. A CouchDB document is considered as a OGR feature.<p>
+
+OGR handles preferably CouchDB documents following the GeoJSON specification.<p>
+
+<h2>Dataset name syntax</h2>
+
+The syntax to open a CouchDB datasource is : <pre>couchdb:http://example.com[/layername]</pre> where
+http://example.com points to the root of a CouchDB repository and, optionaly, layername is the name of a CouchDB database.<p>
+
+It is also possible to directly open a view : <pre>couchdb:http://example.com/layername/_design/adesigndoc/_view/aview[?include_docs=true]</pre>
+The include_docs=true might be needed depending on the value returned by the emit() call in the map() function.<p>
+
+<h2>Authentication</h2>
+
+Some operations, in particular write operations, require authentication. The authentication can
+be passed with the <i>COUCHDB_USERPWD</i> environment variable set to user:password or directly in the URL.<p>
+
+<h2>Filtering</h2>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to the server when GeoCouch extension
+is available. It also makes the same for (very simple) attribute filters set with SetAttributeFilter(). When
+server-side filtering fails, it will default back to client-side filtering.<p>
+
+By default, the driver will try the following spatial filter function "_design/ogr_spatial/_spatial/spatial",
+which is the valid spatial filter function for layers created by OGR. If that filter function does not exist,
+but another one exists, you can specify it with the COUCHDB_SPATIAL_FILTER configuration option.<p>
+
+Note that the first time an attribute request is issued, it might require write permissions in the database
+to create a new index view.<p>
+
+<h2>Paging</h2>
+
+Features are retrieved from the server by chunks of 500 by default. This number can be altered with the COUCHDB_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>
+
+When inserting a new feature with CreateFeature(), and if the command is successfull, OGR will fetch the
+returned _id and _rev and use them.<p>
+
+<h2>Write support and OGR transactions</h2>
+
+The CreateFeature()/SetFeature() 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()/SetFeature() operations between OGRLayer::StartTransaction() and OGRLayer::CommitTransaction().
+The operations will be stored into memory and only executed at the time CommitTransaction() is called.<p>
+
+<h2>Layer creation options</h2>
+
+The following layer creation options are supported:
+<ul>
+<li><b>UPDATE_PERMISSIONS</b> = LOGGED_USER|ALL|ADMIN|function(...)|DEFAULT : Update permissions for the new layer.
+<ul>
+<li>If set to LOGGED_USER (the default), only logged users will be able to make changes in the layer.</li>
+<li>If set to ALL, all users will be able to make changes in the layer.</li>
+<li>If set to ADMIN, only administrators will be able to make changes in the layer.</li>
+<li>If beginning with "function(", the value of the creation option will be used as the content of the <a href="http://guide.couchdb.org/draft/validation.html">validate_doc_update function</a>.</li>
+<li>Otherwise, all users will be allowed to make changes in non-design documents.</li>
+</ul>
+</li>
+<li><b>GEOJSON</b> = YES|NO : Set to NO to avoid writting documents as GeoJSON documents. Default to YES.</li>
+<li><b>COORDINATE_PRECISION</b> = int_number : Maximum number of figures after decimal separator to write in coordinates.
+Default to 15. "Smart" truncation will occur to remove trailing zeros.
+Note: when opening a dataset in update mode, the OGR_COUCHDB_COORDINATE_PRECISION configuration option can be set to have a similar role.</li>
+</ul>
+
+<h2>Examples</h2>
+
+<li>
+Listing the tables of a CouchDB repository:
+<pre>
+ogrinfo -ro "couchdb:http://some_account.some_couchdb_server.com"
+</pre>
+<p>
+
+<li>
+Creating and populating a table from a shapefile:
+<pre>
+ogr2ogr -f couchdb "couchdb:http://some_account.some_couchdb_server.com" shapefile.shp
+</pre>
+<p>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="http://wiki.apache.org/couchdb/Reference">CouchDB reference</a><p>
+<li> <a href="http://github.com/couchbase/geocouch">GeoCouch source code repository</a><p>
+<li> <a href="http://guide.couchdb.org/draft/validation.html">Documentation for 'validate_doc_update' function</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/couchdb/makefile.vc b/ogr/ogrsf_frmts/couchdb/makefile.vc
new file mode 100644
index 0000000..a839631
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrcouchdbdriver.obj ogrcouchdbdatasource.obj ogrcouchdblayer.obj ogrcouchdbtablelayer.obj ogrcouchdbrowslayer.obj
+EXTRAFLAGS =	-I.. -I..\..  -I..\geojson -I..\geojson\jsonc
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
new file mode 100644
index 0000000..f3988dd
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
@@ -0,0 +1,316 @@
+/******************************************************************************
+ * $Id: ogr_couchdb.h 23324 2011-11-05 16:17:33Z 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>
+ *
+ * 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_COUCHDB_H_INCLUDED
+#define _OGR_COUCHDB_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_http.h"
+#include "json.h"
+
+#include <vector>
+#include <map>
+
+#define _ID_FIELD       0
+#define _REV_FIELD      1
+#define FIRST_FIELD     2
+
+typedef enum
+{
+    COUCHDB_TABLE_LAYER,
+    COUCHDB_ROWS_LAYER
+} CouchDBLayerType;
+
+/************************************************************************/
+/*                           OGRCouchDBLayer                            */
+/************************************************************************/
+class OGRCouchDBDataSource;
+
+class OGRCouchDBLayer : public OGRLayer
+{
+protected:
+    OGRCouchDBDataSource*       poDS;
+
+    OGRFeatureDefn*             poFeatureDefn;
+    OGRSpatialReference*        poSRS;
+
+    int                         nNextInSeq;
+    int                         nOffset;
+    int                         bEOF;
+
+    json_object*                poFeatures;
+    std::vector<json_object*>   aoFeatures;
+
+    OGRFeature*                 GetNextRawFeature();
+    OGRFeature*                 TranslateFeature( json_object* poObj );
+    void                        ParseFieldValue(OGRFeature* poFeature,
+                                                const char* pszKey,
+                                                json_object* poValue);
+
+    int                         FetchNextRowsAnalyseDocs(json_object* poAnswerObj);
+   virtual int                  FetchNextRows() = 0;
+
+   int                          bGeoJSONDocument;
+
+   void                         BuildFeatureDefnFromDoc(json_object* poDoc);
+   int                          BuildFeatureDefnFromRows(json_object* poAnswerObj);
+
+    int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("COUCHDB_PAGE_SIZE", "500")); }
+
+  public:
+                         OGRCouchDBLayer(OGRCouchDBDataSource* poDS);
+                        ~OGRCouchDBLayer();
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+
+    virtual int                 TestCapability( const char * );
+
+    virtual OGRSpatialReference*GetSpatialRef();
+
+    virtual CouchDBLayerType    GetLayerType() = 0;
+
+    virtual OGRErr              SetNextByIndex( long nIndex );
+};
+
+/************************************************************************/
+/*                      OGRCouchDBTableLayer                            */
+/************************************************************************/
+
+class OGRCouchDBTableLayer : public OGRCouchDBLayer
+{
+    CPLString                 osName;
+    CPLString                 osEscapedName;
+
+    int                       nNextFIDForCreate;
+    int                       bInTransaction;
+    std::vector<json_object*> aoTransactionFeatures;
+
+    OGRwkbGeometryType        eGeomType;
+
+    int                       bHasLoadedMetadata;
+    int                       bMustWriteMetadata;
+    CPLString                 osMetadataRev;
+    void                      LoadMetadata();
+    void                      WriteMetadata();
+
+    virtual int               FetchNextRows();
+
+    int                       bHasOGRSpatial;
+    int                       bHasGeocouchUtilsMinimalSpatialView;
+    int                       bServerSideSpatialFilteringWorks;
+    int                       bMustRunSpatialFilter;
+    std::vector<CPLString>    aosIdsToFetch;
+    int                       RunSpatialFilterQueryIfNecessary();
+    int                       FetchNextRowsSpatialFilter();
+
+    int                       bHasInstalledAttributeFilter;
+    int                       bServerSideAttributeFilteringWorks;
+    CPLString                 osURIAttributeFilter;
+    std::map<CPLString, int>  oMapFilterFields;
+    CPLString                 BuildAttrQueryURI(int& bOutHasStrictComparisons);
+    int                       FetchNextRowsAttributeFilter();
+
+    int                       GetTotalFeatureCount();
+    int                       GetMaximumId();
+
+    int                       nUpdateSeq;
+    int                       bAlwaysValid;
+    int                       FetchUpdateSeq();
+
+    int                       bExtentValid;
+    int                       bExtentSet;
+    double                    dfMinX;
+    double                    dfMinY;
+    double                    dfMaxX;
+    double                    dfMaxY;
+
+    int                       nCoordPrecision;
+
+    OGRFeature*               GetFeature( const char* pszId );
+    OGRErr                    DeleteFeature( OGRFeature* poFeature );
+
+    public:
+            OGRCouchDBTableLayer(OGRCouchDBDataSource* poDS,
+                                 const char* pszName);
+            ~OGRCouchDBTableLayer();
+
+    virtual void                ResetReading();
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+
+    virtual const char *        GetName() { return osName.c_str(); }
+
+    virtual int                 GetFeatureCount( int bForce = TRUE );
+    virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+
+    virtual OGRFeature *        GetFeature( long nFID );
+
+    virtual void                SetSpatialFilter( OGRGeometry * );
+    virtual OGRErr              SetAttributeFilter( 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 OGRErr              StartTransaction();
+    virtual OGRErr              CommitTransaction();
+    virtual OGRErr              RollbackTransaction();
+
+    virtual int                 TestCapability( const char * );
+
+    virtual OGRSpatialReference*GetSpatialRef();
+
+    void                        SetInfoAfterCreation(OGRwkbGeometryType eGType,
+                                             OGRSpatialReference* poSRSIn,
+                                             int nUpdateSeqIn,
+                                             int bGeoJSONDocumentIn);
+
+    void                        SetUpdateSeq(int nUpdateSeqIn) { nUpdateSeq = nUpdateSeqIn; };
+
+    int                       HasFilterOnFieldOrCreateIfNecessary(const char* pszFieldName);
+
+    void                        SetCoordinatePrecision(int nCoordPrecision) { this->nCoordPrecision = nCoordPrecision; }
+
+    virtual CouchDBLayerType    GetLayerType() { return COUCHDB_TABLE_LAYER; }
+
+    OGRErr            DeleteFeature( const char* pszId );
+};
+
+/************************************************************************/
+/*                       OGRCouchDBRowsLayer                            */
+/************************************************************************/
+
+class OGRCouchDBRowsLayer : public OGRCouchDBLayer
+{
+    int                       bAllInOne;
+
+    virtual int               FetchNextRows();
+
+    public:
+            OGRCouchDBRowsLayer(OGRCouchDBDataSource* poDS);
+            ~OGRCouchDBRowsLayer();
+
+    virtual void                ResetReading();
+
+    int                         BuildFeatureDefn();
+
+    virtual CouchDBLayerType    GetLayerType() { return COUCHDB_TABLE_LAYER; }
+};
+
+/************************************************************************/
+/*                         OGRCouchDBDataSource                         */
+/************************************************************************/
+
+class OGRCouchDBDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+    int                 bReadWrite;
+
+    int                 bMustCleanPersistant;
+
+    CPLString           osURL;
+    CPLString           osUserPwd;
+
+    json_object*        REQUEST(const char* pszVerb,
+                                const char* pszURI,
+                                const char* pszData);
+
+    OGRLayer*           OpenDatabase(const char* pszLayerName = NULL);
+    OGRLayer*           OpenView();
+    void                DeleteLayer( const char *pszLayerName );
+
+    OGRLayer *          ExecuteSQLStats( const char *pszSQLCommand );
+
+  public:
+                        OGRCouchDBDataSource();
+                        ~OGRCouchDBDataSource();
+
+    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 );
+
+    int                         IsReadWrite() const { return bReadWrite; }
+
+    json_object*                GET(const char* pszURI);
+    json_object*                PUT(const char* pszURI, const char* pszData);
+    json_object*                POST(const char* pszURI, const char* pszData);
+    json_object*                DELETE(const char* pszURI);
+
+    const CPLString&            GetURL() const { return osURL; }
+
+    static int                  IsError(json_object* poAnswerObj,
+                                        const char* pszErrorMsg);
+    static int                  IsOK   (json_object* poAnswerObj,
+                                        const char* pszErrorMsg);
+};
+
+/************************************************************************/
+/*                           OGRCouchDBDriver                           */
+/************************************************************************/
+
+class OGRCouchDBDriver : public OGRSFDriver
+{
+  public:
+                ~OGRCouchDBDriver();
+
+    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_COUCHDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
new file mode 100644
index 0000000..0157484
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
@@ -0,0 +1,1192 @@
+/******************************************************************************
+ * $Id: ogrcouchdbdatasource.cpp 22871 2011-08-06 20:29:35Z 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>
+ *
+ * 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_couchdb.h"
+#include "swq.h"
+
+CPL_CVSID("$Id: ogrcouchdbdatasource.cpp 22871 2011-08-06 20:29:35Z rouault $");
+
+/************************************************************************/
+/*                        OGRCouchDBDataSource()                        */
+/************************************************************************/
+
+OGRCouchDBDataSource::OGRCouchDBDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+
+    bReadWrite = FALSE;
+
+    bMustCleanPersistant = FALSE;
+}
+
+/************************************************************************/
+/*                       ~OGRCouchDBDataSource()                        */
+/************************************************************************/
+
+OGRCouchDBDataSource::~OGRCouchDBDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    if (bMustCleanPersistant)
+    {
+        char** papszOptions = CSLAddString(NULL,
+                          CPLSPrintf("CLOSE_PERSISTENT=CouchDB:%p", this));
+        CPLHTTPFetch( osURL, papszOptions);
+        CSLDestroy(papszOptions);
+    }
+
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRCouchDBDataSource::TestCapability( const char * pszCap )
+
+{
+    if( bReadWrite && EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+    else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRCouchDBDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRCouchDBDataSource::GetLayerByName(const char * pszLayerName)
+{
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszLayerName);
+    if (poLayer)
+        return poLayer;
+
+    return OpenDatabase(pszLayerName);
+}
+
+/************************************************************************/
+/*                             OpenDatabase()                           */
+/************************************************************************/
+
+OGRLayer* OGRCouchDBDataSource::OpenDatabase(const char* pszLayerName)
+{
+    CPLString osTableName;
+    CPLString osEscapedName;
+    if (pszLayerName)
+    {
+        osTableName = pszLayerName;
+        char* pszEscapedName = CPLEscapeString(pszLayerName, -1, CPLES_URL);
+        osEscapedName = pszEscapedName;
+        CPLFree(pszEscapedName);
+    }
+    else
+    {
+        char* pszURL = CPLStrdup(osURL);
+        char* pszLastSlash = strrchr(pszURL, '/');
+        if (pszLastSlash)
+        {
+            osEscapedName = pszLastSlash + 1;
+            char* pszName = CPLUnescapeString(osEscapedName, NULL, CPLES_URL);
+            osTableName = pszName;
+            CPLFree(pszName);
+            *pszLastSlash = 0;
+        }
+        osURL = pszURL;
+        CPLFree(pszURL);
+        pszURL = NULL;
+
+        if (pszLastSlash == NULL)
+            return NULL;
+    }
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+
+    json_object* poAnswerObj = GET(osURI);
+    if (poAnswerObj == NULL)
+        return NULL;
+
+    if ( !json_object_is_type(poAnswerObj, json_type_object) ||
+            json_object_object_get(poAnswerObj, "db_name") == NULL )
+    {
+        IsError(poAnswerObj, "Database opening failed");
+
+        json_object_put(poAnswerObj);
+        return NULL;
+    }
+
+    OGRCouchDBTableLayer* poLayer = new OGRCouchDBTableLayer(this, osTableName);
+
+    if ( json_object_object_get(poAnswerObj, "update_seq") != NULL )
+    {
+        int nUpdateSeq = json_object_get_int(json_object_object_get(poAnswerObj, "update_seq"));
+        poLayer->SetUpdateSeq(nUpdateSeq);
+    }
+
+    json_object_put(poAnswerObj);
+
+    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                               OpenView()                             */
+/************************************************************************/
+
+OGRLayer* OGRCouchDBDataSource::OpenView()
+{
+    OGRCouchDBRowsLayer* poLayer = new OGRCouchDBRowsLayer(this);
+    if (!poLayer->BuildFeatureDefn())
+    {
+        delete poLayer;
+        return NULL;
+    }
+
+    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRCouchDBDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    int bHTTP = FALSE;
+    if (strncmp(pszFilename, "http://", 7) == 0 ||
+        strncmp(pszFilename, "https://", 8) == 0)
+        bHTTP = TRUE;
+    else if (!EQUALN(pszFilename, "CouchDB:", 8))
+        return FALSE;
+
+    bReadWrite = bUpdateIn;
+
+    pszName = CPLStrdup( pszFilename );
+
+    if (bHTTP)
+        osURL = pszFilename;
+    else
+        osURL = pszFilename + 8;
+    if (osURL.size() > 0 && osURL[osURL.size() - 1] == '/')
+        osURL.resize(osURL.size() - 1);
+
+    const char* pszUserPwd = CPLGetConfigOption("COUCHDB_USERPWD", NULL);
+    if (pszUserPwd)
+        osUserPwd = pszUserPwd;
+
+
+    if ((strstr(osURL, "/_design/") && strstr(osURL, "/_view/")) ||
+        strstr(osURL, "/_all_docs"))
+    {
+        return OpenView() != NULL;
+    }
+
+    /* If passed with http://useraccount.knownprovider.com/database, do not */
+    /* try to issue /all_dbs, but directly open the database */
+    const char* pszKnowProvider = strstr(osURL, ".iriscouch.com/");
+    if (pszKnowProvider != NULL &&
+        strchr(pszKnowProvider + strlen(".iriscouch.com/"), '/' ) == NULL)
+    {
+        return OpenDatabase() != NULL;
+    }
+    pszKnowProvider = strstr(osURL, ".cloudant.com/");
+    if (pszKnowProvider != NULL &&
+        strchr(pszKnowProvider + strlen(".cloudant.com/"), '/' ) == NULL)
+    {
+        return OpenDatabase() != NULL;
+    }
+
+    /* Get list of tables */
+    json_object* poAnswerObj = GET("/_all_dbs");
+
+    if (poAnswerObj == NULL)
+        return FALSE;
+
+    if ( !json_object_is_type(poAnswerObj, json_type_array) )
+    {
+        if ( json_object_is_type(poAnswerObj, json_type_object) )
+        {
+            json_object* poError = json_object_object_get(poAnswerObj, "error");
+            json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+
+            const char* pszError = json_object_get_string(poError);
+            const char* pszReason = json_object_get_string(poReason);
+
+            if (pszError && pszReason && strcmp(pszError, "not_found") == 0 &&
+                strcmp(pszReason, "missing") == 0)
+            {
+                json_object_put(poAnswerObj);
+                poAnswerObj = NULL;
+
+                CPLErrorReset();
+
+                return OpenDatabase() != NULL;
+            }
+        }
+        if (poAnswerObj)
+        {
+            IsError(poAnswerObj, "Database listing failed");
+
+            json_object_put(poAnswerObj);
+            return FALSE;
+        }
+    }
+
+    int nTables = json_object_array_length(poAnswerObj);
+    for(int i=0;i<nTables;i++)
+    {
+        json_object* poAnswerObjDBName = json_object_array_get_idx(poAnswerObj, i);
+        if ( json_object_is_type(poAnswerObjDBName, json_type_string) )
+        {
+            const char* pszDBName = json_object_get_string(poAnswerObjDBName);
+            if ( strcmp(pszDBName, "_users") != 0 &&
+                 strcmp(pszDBName, "_replicator") != 0 )
+            {
+                papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+                papoLayers[nLayers ++] = new OGRCouchDBTableLayer(this, pszDBName);
+            }
+        }
+    }
+
+    json_object_put(poAnswerObj);
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                           CreateLayer()                              */
+/************************************************************************/
+
+OGRLayer   *OGRCouchDBDataSource::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( pszName );
+                break;
+            }
+            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;
+            }
+        }
+    }
+
+    char* pszEscapedName = CPLEscapeString(pszName, -1, CPLES_URL);
+    CPLString osEscapedName = pszEscapedName;
+    CPLFree(pszEscapedName);
+
+/* -------------------------------------------------------------------- */
+/*      Create "database"                                               */
+/* -------------------------------------------------------------------- */
+    CPLString osURI;
+    osURI = "/";
+    osURI += osEscapedName;
+    json_object* poAnswerObj = PUT(osURI, NULL);
+
+    if (poAnswerObj == NULL)
+        return FALSE;
+
+    if (!IsOK(poAnswerObj, "Layer creation failed"))
+    {
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    json_object_put(poAnswerObj);
+
+/* -------------------------------------------------------------------- */
+/*      Create "spatial index"                                          */
+/* -------------------------------------------------------------------- */
+    int nUpdateSeq = 0;
+    if (eGType != wkbNone)
+    {
+        osURI = "/";
+        osURI += osEscapedName;
+        osURI += "/_design/ogr_spatial";
+
+        CPLString osContent("{ \"spatial\": { \"spatial\" : \"function(doc) { if (doc.geometry && doc.geometry.coordinates && doc.geometry.coordinates.length != 0) { emit(doc.geometry, null); } } \" } }");
+
+        poAnswerObj = PUT(osURI, osContent);
+
+        if (IsOK(poAnswerObj, "Spatial index creation failed"))
+            nUpdateSeq ++;
+
+        json_object_put(poAnswerObj);
+    }
+
+
+/* -------------------------------------------------------------------- */
+/*      Create validation function                                      */
+/* -------------------------------------------------------------------- */
+    const char* pszUpdatePermissions = CSLFetchNameValueDef(papszOptions, "UPDATE_PERMISSIONS", "LOGGED_USER");
+    CPLString osValidation;
+    if (EQUAL(pszUpdatePermissions, "LOGGED_USER"))
+    {
+        osValidation = "{\"validate_doc_update\": \"function(new_doc, old_doc, userCtx) { if(!userCtx.name) { throw({forbidden: \\\"Please log in first.\\\"}); } }\" }";
+    }
+    else if (EQUAL(pszUpdatePermissions, "ALL"))
+    {
+        osValidation = "{\"validate_doc_update\": \"function(new_doc, old_doc, userCtx) {  }\" }";
+    }
+    else if (EQUAL(pszUpdatePermissions, "ADMIN"))
+    {
+        osValidation = "{\"validate_doc_update\": \"function(new_doc, old_doc, userCtx) {if (userCtx.roles.indexOf('_admin') === -1) { throw({forbidden: \\\"No changes allowed except by admin.\\\"}); } }\" }";
+    }
+    else if (strncmp(pszUpdatePermissions, "function(", 9) == 0)
+    {
+        osValidation = "{\"validate_doc_update\": \"";
+        osValidation += pszUpdatePermissions;
+        osValidation += "\"}";
+    }
+
+    if (osValidation.size())
+    {
+        osURI = "/";
+        osURI += osEscapedName;
+        osURI += "/_design/ogr_validation";
+
+        poAnswerObj = PUT(osURI, osValidation);
+
+        if (IsOK(poAnswerObj, "Validation function creation failed"))
+            nUpdateSeq ++;
+
+        json_object_put(poAnswerObj);
+    }
+
+    int bGeoJSONDocument = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
+    int nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
+
+    OGRCouchDBTableLayer* poLayer = new OGRCouchDBTableLayer(this, pszName);
+    if (nCoordPrecision != -1)
+        poLayer->SetCoordinatePrecision(nCoordPrecision);
+    poLayer->SetInfoAfterCreation(eGType, poSpatialRef, nUpdateSeq, bGeoJSONDocument);
+    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+    return poLayer;
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+void OGRCouchDBDataSource::DeleteLayer( const char *pszLayerName )
+
+{
+    int iLayer;
+
+/* -------------------------------------------------------------------- */
+/*      Try to find layer.                                              */
+/* -------------------------------------------------------------------- */
+    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    {
+        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
+            break;
+    }
+
+    if( iLayer == nLayers )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to delete layer '%s', but this layer is not known to OGR.",
+                  pszLayerName );
+        return;
+    }
+
+    DeleteLayer(iLayer);
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr OGRCouchDBDataSource::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;
+    }
+
+    CPLString osLayerName = GetLayer(iLayer)->GetName();
+
+/* -------------------------------------------------------------------- */
+/*      Blow away our OGR structures related to the layer.  This is     */
+/*      pretty dangerous if anything has a reference to this layer!     */
+/* -------------------------------------------------------------------- */
+    CPLDebug( "CouchDB", "DeleteLayer(%s)", osLayerName.c_str() );
+
+    delete papoLayers[iLayer];
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
+             sizeof(void *) * (nLayers - iLayer - 1) );
+    nLayers--;
+
+/* -------------------------------------------------------------------- */
+/*      Remove from the database.                                       */
+/* -------------------------------------------------------------------- */
+
+    char* pszEscapedName = CPLEscapeString(osLayerName, -1, CPLES_URL);
+    CPLString osEscapedName = pszEscapedName;
+    CPLFree(pszEscapedName);
+
+    CPLString osURI;
+    osURI = "/";
+    osURI += osEscapedName;
+    json_object* poAnswerObj = DELETE(osURI);
+
+    if (poAnswerObj == NULL)
+        return OGRERR_FAILURE;
+
+    if (!IsOK(poAnswerObj, "Layer deletion failed"))
+    {
+        json_object_put(poAnswerObj);
+        return OGRERR_FAILURE;
+    }
+
+    json_object_put(poAnswerObj);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                          OGRGeometry *poSpatialFilter,
+                                          const char *pszDialect )
+
+{
+    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
+                                          pszDialect );
+
+/* -------------------------------------------------------------------- */
+/*      Special case DELLAYER: command.                                 */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    {
+        const char *pszLayerName = pszSQLCommand + 9;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        DeleteLayer( pszLayerName );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case 'COMPACT ON ' command.                             */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand,"COMPACT ON ",11) )
+    {
+        const char *pszLayerName = pszSQLCommand + 11;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        CPLString osURI("/");
+        osURI += pszLayerName;
+        osURI += "/_compact";
+
+        json_object* poAnswerObj = POST(osURI, NULL);
+        IsError(poAnswerObj, "Database compaction failed");
+        json_object_put(poAnswerObj);
+
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case 'VIEW CLEANUP ON ' command.                        */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand,"VIEW CLEANUP ON ",16) )
+    {
+        const char *pszLayerName = pszSQLCommand + 16;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        CPLString osURI("/");
+        osURI += pszLayerName;
+        osURI += "/_view_cleanup";
+
+        json_object* poAnswerObj = POST(osURI, NULL);
+        IsError(poAnswerObj, "View cleanup failed");
+        json_object_put(poAnswerObj);
+
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Deal with "DELETE FROM layer_name WHERE expression" statement   */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand, "DELETE FROM ", 12) )
+    {
+        const char* pszIter = pszSQLCommand + 12;
+        while(*pszIter && *pszIter != ' ')
+            pszIter ++;
+        if (*pszIter == 0)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid statement");
+            return NULL;
+        }
+
+        CPLString osName = pszSQLCommand + 12;
+        osName.resize(pszIter - (pszSQLCommand + 12));
+        OGRCouchDBLayer* poLayer = (OGRCouchDBLayer*)GetLayerByName(osName);
+        if (poLayer == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unknown layer : %s", osName.c_str());
+            return NULL;
+        }
+        if (poLayer->GetLayerType() != COUCHDB_TABLE_LAYER)
+            return NULL;
+        OGRCouchDBTableLayer* poTableLayer = (OGRCouchDBTableLayer*)poLayer;
+
+        while(*pszIter && *pszIter == ' ')
+            pszIter ++;
+        if (!EQUALN(pszIter, "WHERE ", 5))
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "WHERE clause missing");
+            return NULL;
+        }
+        pszIter += 5;
+
+        const char* pszQuery = pszIter;
+
+        /* Check with the generic SQL engine that this is a valid WHERE clause */
+        OGRFeatureQuery oQuery;
+        OGRErr eErr = oQuery.Compile( poLayer->GetLayerDefn(), pszQuery );
+        if( eErr != OGRERR_NONE )
+        {
+            return NULL;
+        }
+
+        swq_expr_node * pNode = (swq_expr_node *) oQuery.GetSWGExpr();
+        if (pNode->eNodeType == SNT_OPERATION &&
+            pNode->nOperation == SWQ_EQ &&
+            pNode->nSubExprCount == 2 &&
+            pNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+            pNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+            pNode->papoSubExpr[0]->field_index == _ID_FIELD &&
+            pNode->papoSubExpr[1]->field_type == SWQ_STRING)
+        {
+            poTableLayer->DeleteFeature(pNode->papoSubExpr[1]->string_value);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid WHERE clause. Expecting '_id' = 'a_value'");
+            return NULL;
+        }
+
+
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try an optimized implementation when doing only stats           */
+/* -------------------------------------------------------------------- */
+    if (poSpatialFilter == NULL && EQUALN(pszSQLCommand, "SELECT", 6))
+    {
+        OGRLayer* poRet = ExecuteSQLStats(pszSQLCommand);
+        if (poRet)
+            return poRet;
+    }
+
+    return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                        poSpatialFilter,
+                                        pszDialect );
+}
+
+/************************************************************************/
+/*                         ExecuteSQLStats()                            */
+/************************************************************************/
+
+class PointerAutoFree
+{
+        void ** m_pp;
+    public:
+        PointerAutoFree(void** pp) { m_pp = pp; }
+        ~PointerAutoFree() { CPLFree(*m_pp); *m_pp = NULL; }
+};
+
+class OGRCouchDBOneLineLayer : public OGRLayer
+{
+    public:
+        OGRFeature* poFeature;
+        OGRFeatureDefn* poFeatureDefn;
+        int bEnd;
+
+        OGRCouchDBOneLineLayer() { poFeature = NULL; poFeatureDefn = NULL; bEnd = FALSE; }
+        ~OGRCouchDBOneLineLayer()
+        {
+            delete poFeature;
+            if( poFeatureDefn != NULL )
+                poFeatureDefn->Release();
+        }
+
+        virtual void        ResetReading() { bEnd = FALSE;}
+        virtual OGRFeature *GetNextFeature()
+        {
+            if (bEnd) return NULL;
+            bEnd = TRUE;
+            return poFeature->Clone();
+        }
+        virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
+        virtual int         TestCapability( const char * ) { return FALSE; }
+};
+
+OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
+{
+    swq_select sSelectInfo;
+    if( sSelectInfo.preparse( pszSQLCommand ) != CPLE_None )
+    {
+        return NULL;
+    }
+
+    if (sSelectInfo.table_count != 1)
+    {
+        return NULL;
+    }
+
+    swq_table_def *psTableDef = &sSelectInfo.table_defs[0];
+    if( psTableDef->data_source != NULL )
+    {
+        return NULL;
+    }
+
+    OGRCouchDBLayer* _poSrcLayer =
+        (OGRCouchDBLayer* )GetLayerByName( psTableDef->table_name );
+    if (_poSrcLayer == NULL)
+    {
+        return NULL;
+    }
+    if (_poSrcLayer->GetLayerType() != COUCHDB_TABLE_LAYER)
+        return NULL;
+
+    OGRCouchDBTableLayer* poSrcLayer = (OGRCouchDBTableLayer* ) _poSrcLayer;
+
+    int nFieldCount = poSrcLayer->GetLayerDefn()->GetFieldCount();
+
+    swq_field_list sFieldList;
+    memset( &sFieldList, 0, sizeof(sFieldList) );
+    sFieldList.table_count = sSelectInfo.table_count;
+    sFieldList.table_defs = sSelectInfo.table_defs;
+
+    sFieldList.count = 0;
+    sFieldList.names = (char **) CPLMalloc( sizeof(char *) * nFieldCount );
+    sFieldList.types = (swq_field_type *)
+        CPLMalloc( sizeof(swq_field_type) * nFieldCount );
+    sFieldList.table_ids = (int *)
+        CPLMalloc( sizeof(int) * nFieldCount );
+    sFieldList.ids = (int *)
+        CPLMalloc( sizeof(int) * nFieldCount );
+
+    PointerAutoFree oHolderNames((void**)&(sFieldList.names));
+    PointerAutoFree oHolderTypes((void**)&(sFieldList.types));
+    PointerAutoFree oHolderTableIds((void**)&(sFieldList.table_ids));
+    PointerAutoFree oHolderIds((void**)&(sFieldList.ids));
+
+    int iField;
+    for( iField = 0;
+         iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
+         iField++ )
+    {
+        OGRFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
+        int iOutField = sFieldList.count++;
+        sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef();
+        if( poFDefn->GetType() == OFTInteger )
+            sFieldList.types[iOutField] = SWQ_INTEGER;
+        else if( poFDefn->GetType() == OFTReal )
+            sFieldList.types[iOutField] = SWQ_FLOAT;
+        else if( poFDefn->GetType() == OFTString )
+            sFieldList.types[iOutField] = SWQ_STRING;
+        else
+            sFieldList.types[iOutField] = SWQ_OTHER;
+
+        sFieldList.table_ids[iOutField] = 0;
+        sFieldList.ids[iOutField] = iField;
+    }
+
+    CPLString osLastFieldName;
+    for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+    {
+        swq_col_def *psColDef = sSelectInfo.column_defs + iField;
+        if (psColDef->field_name == NULL)
+            return NULL;
+
+        if (strcmp(psColDef->field_name, "*") != 0)
+        {
+            if (osLastFieldName.size() == 0)
+                osLastFieldName = psColDef->field_name;
+            else if (strcmp(osLastFieldName, psColDef->field_name) != 0)
+                return NULL;
+
+            if (poSrcLayer->GetLayerDefn()->GetFieldIndex(psColDef->field_name) == -1)
+                return NULL;
+        }
+
+        if (!(psColDef->col_func == SWQCF_AVG ||
+              psColDef->col_func == SWQCF_MIN ||
+              psColDef->col_func == SWQCF_MAX ||
+              psColDef->col_func == SWQCF_COUNT ||
+              psColDef->col_func == SWQCF_SUM))
+            return NULL;
+
+        if (psColDef->distinct_flag) /* TODO: could perhaps be relaxed */
+            return NULL;
+    }
+
+    if (osLastFieldName.size() == 0)
+        return NULL;
+
+    /* Normalize field name */
+    int nIndex = poSrcLayer->GetLayerDefn()->GetFieldIndex(osLastFieldName);
+    osLastFieldName = poSrcLayer->GetLayerDefn()->GetFieldDefn(nIndex)->GetNameRef();
+
+/* -------------------------------------------------------------------- */
+/*      Finish the parse operation.                                     */
+/* -------------------------------------------------------------------- */
+
+    if( sSelectInfo.parse( &sFieldList, 0 ) != CE_None )
+    {
+        return NULL;
+    }
+
+    if (sSelectInfo.join_defs != NULL ||
+        sSelectInfo.where_expr != NULL ||
+        sSelectInfo.order_defs != NULL ||
+        sSelectInfo.query_mode != SWQM_SUMMARY_RECORD)
+    {
+        return NULL;
+    }
+
+    for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+    {
+        swq_col_def *psColDef = sSelectInfo.column_defs + iField;
+        if (psColDef->field_index == -1)
+        {
+            if (psColDef->col_func == SWQCF_COUNT)
+                continue;
+
+            return NULL;
+        }
+        if (psColDef->field_type != SWQ_INTEGER &&
+            psColDef->field_type != SWQ_FLOAT)
+        {
+            return NULL;
+        }
+    }
+
+    int bFoundFilter = poSrcLayer->HasFilterOnFieldOrCreateIfNecessary(osLastFieldName);
+    if (!bFoundFilter)
+        return NULL;
+
+    CPLString osURI = "/";
+    osURI += poSrcLayer->GetName();
+    osURI += "/_design/ogr_filter_";
+    osURI += osLastFieldName;
+    osURI += "/_view/filter?reduce=true";
+
+    json_object* poAnswerObj = GET(osURI);
+    json_object* poRows = NULL;
+    if (!(poAnswerObj != NULL &&
+          json_object_is_type(poAnswerObj, json_type_object) &&
+          (poRows = json_object_object_get(poAnswerObj, "rows")) != NULL &&
+          json_object_is_type(poRows, json_type_array)))
+    {
+        json_object_put(poAnswerObj);
+        return NULL;
+    }
+
+    int nLength = json_object_array_length(poRows);
+    if (nLength != 1)
+    {
+        json_object_put(poAnswerObj);
+        return NULL;
+    }
+
+    json_object* poRow = json_object_array_get_idx(poRows, 0);
+    if (!(poRow && json_object_is_type(poRow, json_type_object)))
+    {
+        json_object_put(poAnswerObj);
+        return NULL;
+    }
+
+    json_object* poValue = json_object_object_get(poRow, "value");
+    if (!(poValue != NULL && json_object_is_type(poValue, json_type_object)))
+    {
+        json_object_put(poAnswerObj);
+        return NULL;
+    }
+
+    json_object* poSum = json_object_object_get(poValue, "sum");
+    json_object* poCount = json_object_object_get(poValue, "count");
+    json_object* poMin = json_object_object_get(poValue, "min");
+    json_object* poMax = json_object_object_get(poValue, "max");
+    if (poSum != NULL && (json_object_is_type(poSum, json_type_int) ||
+                            json_object_is_type(poSum, json_type_double)) &&
+        poCount != NULL && (json_object_is_type(poCount, json_type_int) ||
+                            json_object_is_type(poCount, json_type_double)) &&
+        poMin != NULL && (json_object_is_type(poMin, json_type_int) ||
+                            json_object_is_type(poMin, json_type_double)) &&
+        poMax != NULL && (json_object_is_type(poMax, json_type_int) ||
+                            json_object_is_type(poMax, json_type_double)) )
+    {
+        double dfSum = json_object_get_double(poSum);
+        int nCount = json_object_get_int(poCount);
+        double dfMin = json_object_get_double(poMin);
+        double dfMax = json_object_get_double(poMax);
+        json_object_put(poAnswerObj);
+
+        //CPLDebug("CouchDB", "sum=%f, count=%d, min=%f, max=%f",
+        //         dfSum, nCount, dfMin, dfMax);
+
+        OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(poSrcLayer->GetName());
+        poFeatureDefn->Reference();
+
+        for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+        {
+            swq_col_def *psColDef = sSelectInfo.column_defs + iField;
+            OGRFieldDefn oFDefn( "", OFTInteger );
+
+            if( psColDef->field_alias != NULL )
+            {
+                oFDefn.SetName(psColDef->field_alias);
+            }
+            else
+            {
+                const swq_operation *op = swq_op_registrar::GetOperator(
+                    (swq_op) psColDef->col_func );
+                oFDefn.SetName( CPLSPrintf( "%s_%s",
+                                            op->osName.c_str(),
+                                            psColDef->field_name ) );
+            }
+
+            if( psColDef->col_func == SWQCF_COUNT )
+                oFDefn.SetType( OFTInteger );
+            else if (psColDef->field_type == SWQ_INTEGER)
+                oFDefn.SetType( OFTInteger );
+            else if (psColDef->field_type == SWQ_FLOAT)
+                oFDefn.SetType( OFTReal );
+
+            poFeatureDefn->AddFieldDefn(&oFDefn);
+        }
+
+        OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+
+        for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+        {
+            swq_col_def *psColDef = sSelectInfo.column_defs + iField;
+            switch(psColDef->col_func)
+            {
+                case SWQCF_AVG:
+                    if (nCount)
+                        poFeature->SetField(iField, dfSum / nCount);
+                    break;
+                case SWQCF_MIN:
+                    poFeature->SetField(iField, dfMin);
+                    break;
+                case SWQCF_MAX:
+                    poFeature->SetField(iField, dfMax);
+                    break;
+                case SWQCF_COUNT:
+                    poFeature->SetField(iField, nCount);
+                    break;
+                case SWQCF_SUM:
+                    poFeature->SetField(iField, dfSum);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        poFeature->SetFID(0);
+
+        OGRCouchDBOneLineLayer* poAnswerLayer = new OGRCouchDBOneLineLayer();
+        poAnswerLayer->poFeatureDefn = poFeatureDefn;
+        poAnswerLayer->poFeature = poFeature;
+        return poAnswerLayer;
+    }
+    json_object_put(poAnswerObj);
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRCouchDBDataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
+
+/************************************************************************/
+/*                             REQUEST()                                */
+/************************************************************************/
+
+json_object* OGRCouchDBDataSource::REQUEST(const char* pszVerb,
+                                           const char* pszURI,
+                                           const char* pszData)
+{
+    bMustCleanPersistant = TRUE;
+
+    char** papszOptions = NULL;
+    papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=CouchDB:%p", this));
+
+    CPLString osCustomRequest("CUSTOMREQUEST=");
+    osCustomRequest += pszVerb;
+    papszOptions = CSLAddString(papszOptions, osCustomRequest);
+
+    CPLString osPOSTFIELDS("POSTFIELDS=");
+    if (pszData)
+        osPOSTFIELDS += pszData;
+    papszOptions = CSLAddString(papszOptions, osPOSTFIELDS);
+
+    papszOptions = CSLAddString(papszOptions, "HEADERS=Content-Type: application/json");
+
+    if (osUserPwd.size())
+    {
+        CPLString osUserPwdOption("USERPWD=");
+        osUserPwdOption += osUserPwd;
+        papszOptions = CSLAddString(papszOptions, osUserPwdOption);
+    }
+
+    CPLDebug("CouchDB", "%s %s", pszVerb, pszURI);
+    CPLString osFullURL(osURL);
+    osFullURL += pszURI;
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    CPLHTTPResult * psResult = CPLHTTPFetch( osFullURL, papszOptions);
+    CPLPopErrorHandler();
+    CSLDestroy(papszOptions);
+    if (psResult == NULL)
+        return NULL;
+
+    const char* pszServer = CSLFetchNameValue(psResult->papszHeaders, "Server");
+    if (pszServer == NULL || !EQUALN(pszServer, "CouchDB", 7))
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    if (psResult->nDataLen == 0)
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    json_tokener* jstok = NULL;
+    json_object* jsobj = NULL;
+
+    jstok = json_tokener_new();
+    jsobj = 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);
+    return jsobj;
+}
+
+/************************************************************************/
+/*                               GET()                                  */
+/************************************************************************/
+
+json_object* OGRCouchDBDataSource::GET(const char* pszURI)
+{
+    return REQUEST("GET", pszURI, NULL);
+}
+
+/************************************************************************/
+/*                               PUT()                                  */
+/************************************************************************/
+
+json_object* OGRCouchDBDataSource::PUT(const char* pszURI, const char* pszData)
+{
+    return REQUEST("PUT", pszURI, pszData);
+}
+
+/************************************************************************/
+/*                               POST()                                 */
+/************************************************************************/
+
+json_object* OGRCouchDBDataSource::POST(const char* pszURI, const char* pszData)
+{
+    return REQUEST("POST", pszURI, pszData);
+}
+
+/************************************************************************/
+/*                             DELETE()                                 */
+/************************************************************************/
+
+json_object* OGRCouchDBDataSource::DELETE(const char* pszURI)
+{
+    return REQUEST("DELETE", pszURI, NULL);
+}
+
+/************************************************************************/
+/*                            IsError()                                 */
+/************************************************************************/
+
+int OGRCouchDBDataSource::IsError(json_object* poAnswerObj,
+                                  const char* pszErrorMsg)
+{
+    if ( poAnswerObj == NULL ||
+        !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        return FALSE;
+    }
+
+    json_object* poError = json_object_object_get(poAnswerObj, "error");
+    json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+
+    const char* pszError = json_object_get_string(poError);
+    const char* pszReason = json_object_get_string(poReason);
+    if (pszError != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s : %s, %s",
+                 pszErrorMsg,
+                 pszError ? pszError : "",
+                 pszReason ? pszReason : "");
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              IsOK()                                  */
+/************************************************************************/
+
+int OGRCouchDBDataSource::IsOK(json_object* poAnswerObj,
+                               const char* pszErrorMsg)
+{
+    if ( poAnswerObj == NULL ||
+        !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                 pszErrorMsg);
+
+        return FALSE;
+    }
+
+    json_object* poOK = json_object_object_get(poAnswerObj, "ok");
+    if ( !poOK )
+    {
+        IsError(poAnswerObj, pszErrorMsg);
+
+        return FALSE;
+    }
+
+    const char* pszOK = json_object_get_string(poOK);
+    if ( !pszOK || !CSLTestBoolean(pszOK) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMsg);
+
+        return FALSE;
+    }
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
new file mode 100644
index 0000000..686e0ef
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
@@ -0,0 +1,117 @@
+/******************************************************************************
+ * $Id: ogrcouchdbdriver.cpp 22229 2011-04-25 17:44:28Z 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>
+ *
+ * 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_couchdb.h"
+
+// 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 $");
+
+extern "C" void RegisterOGRCouchDB();
+
+/************************************************************************/
+/*                         ~OGRCouchDBDriver()                          */
+/************************************************************************/
+
+OGRCouchDBDriver::~OGRCouchDBDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRCouchDBDriver::GetName()
+
+{
+    return "CouchDB";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRCouchDBDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRCouchDBDataSource   *poDS = new OGRCouchDBDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+
+/************************************************************************/
+/*                          CreateDataSource()                          */
+/************************************************************************/
+
+OGRDataSource *OGRCouchDBDriver::CreateDataSource( const char * pszName,
+                                               char **papszOptions )
+
+{
+    OGRCouchDBDataSource   *poDS = new OGRCouchDBDataSource();
+
+    if( !poDS->Open( pszName, TRUE ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRCouchDBDriver::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap, ODrCCreateDataSource))
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         RegisterOGRCouchDB()                         */
+/************************************************************************/
+
+void RegisterOGRCouchDB()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRCouchDBDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
new file mode 100644
index 0000000..1e69f00
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
@@ -0,0 +1,550 @@
+/******************************************************************************
+ * $Id: ogrcouchdblayer.cpp 22283 2011-05-01 22:14:25Z 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>
+ *
+ * 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_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 $");
+
+/************************************************************************/
+/*                            OGRCouchDBLayer()                             */
+/************************************************************************/
+
+OGRCouchDBLayer::OGRCouchDBLayer(OGRCouchDBDataSource* poDS)
+
+{
+    this->poDS = poDS;
+
+    nNextInSeq = 0;
+
+    poSRS = NULL;
+
+    poFeatureDefn = NULL;
+
+    nOffset = 0;
+    bEOF = FALSE;
+
+    poFeatures = NULL;
+
+    bGeoJSONDocument = TRUE;
+}
+
+/************************************************************************/
+/*                            ~OGRCouchDBLayer()                            */
+/************************************************************************/
+
+OGRCouchDBLayer::~OGRCouchDBLayer()
+
+{
+    if( poSRS != NULL )
+        poSRS->Release();
+
+    if( poFeatureDefn != NULL )
+        poFeatureDefn->Release();
+
+    json_object_put(poFeatures);
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRCouchDBLayer::ResetReading()
+
+{
+    nNextInSeq = 0;
+    nOffset = 0;
+    bEOF = FALSE;
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRCouchDBLayer::GetLayerDefn()
+{
+    CPLAssert(poFeatureDefn);
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRCouchDBLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    GetLayerDefn();
+
+    while(TRUE)
+    {
+        if (nNextInSeq < nOffset ||
+            nNextInSeq >= nOffset + (int)aoFeatures.size())
+        {
+            if (bEOF)
+                return NULL;
+
+            nOffset += aoFeatures.size();
+            if (!FetchNextRows())
+                return NULL;
+        }
+
+        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 *OGRCouchDBLayer::GetNextRawFeature()
+{
+    if (nNextInSeq < nOffset ||
+        nNextInSeq - nOffset >= (int)aoFeatures.size())
+        return NULL;
+
+    OGRFeature* poFeature = TranslateFeature(aoFeatures[nNextInSeq - nOffset]);
+    if (poFeature != NULL && poFeature->GetFID() == OGRNullFID)
+        poFeature->SetFID(nNextInSeq);
+
+    nNextInSeq ++;
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          SetNextByIndex()                            */
+/************************************************************************/
+
+OGRErr OGRCouchDBLayer::SetNextByIndex( long nIndex )
+{
+    if (nIndex < 0)
+        return OGRERR_FAILURE;
+    bEOF = FALSE;
+    nNextInSeq = nIndex;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRCouchDBLayer::TestCapability( const char * pszCap )
+
+{
+    if ( EQUAL(pszCap, OLCStringsAsUTF8) )
+        return TRUE;
+    else if ( EQUAL(pszCap, OLCFastSetNextByIndex) )
+        return TRUE;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          GetSpatialRef()                             */
+/************************************************************************/
+
+OGRSpatialReference* OGRCouchDBLayer::GetSpatialRef()
+{
+    GetLayerDefn();
+
+    return poSRS;
+}
+
+/************************************************************************/
+/*                         TranslateFeature()                            */
+/************************************************************************/
+
+OGRFeature* OGRCouchDBLayer::TranslateFeature( json_object* poObj )
+{
+    OGRFeature* poFeature = NULL;
+    poFeature = new OGRFeature( GetLayerDefn() );
+
+    json_object* poId = json_object_object_get(poObj, "_id");
+    const char* pszId = json_object_get_string(poId);
+    if (pszId)
+    {
+        poFeature->SetField(_ID_FIELD, pszId);
+
+        int nFID = atoi(pszId);
+        const char* pszFID = CPLSPrintf("%09d", nFID);
+        if (strcmp(pszId, pszFID) == 0)
+            poFeature->SetFID(nFID);
+    }
+
+    json_object* poRev = json_object_object_get(poObj, "_rev");
+    const char* pszRev = json_object_get_string(poRev);
+    if (pszRev)
+        poFeature->SetField(_REV_FIELD, pszRev);
+
+/* -------------------------------------------------------------------- */
+/*      Translate GeoJSON "properties" object to feature attributes.    */
+/* -------------------------------------------------------------------- */
+
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    if( bGeoJSONDocument )
+    {
+        json_object* poObjProps = json_object_object_get( poObj, "properties" );
+        if ( NULL != poObjProps &&
+             json_object_get_type(poObjProps ) == json_type_object )
+        {
+            json_object_object_foreachC( poObjProps, it )
+            {
+                ParseFieldValue(poFeature, it.key, it.val);
+            }
+        }
+    }
+    else
+    {
+        json_object_object_foreachC( poObj, it )
+        {
+            if( strcmp(it.key, "_id") != 0 &&
+                strcmp(it.key, "_rev") != 0 &&
+                strcmp(it.key, "geometry") != 0 )
+            {
+                ParseFieldValue(poFeature, it.key, it.val);
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Translate geometry sub-object of GeoJSON Feature.               */
+/* -------------------------------------------------------------------- */
+
+    json_object* poObjGeom = json_object_object_get( poObj, "geometry" );
+    if (poObjGeom != NULL)
+    {
+        OGRGeometry* poGeometry = OGRGeoJSONReadGeometry( poObjGeom );
+        if( NULL != poGeometry )
+        {
+            if (poSRS)
+                poGeometry->assignSpatialReference(poSRS);
+            poFeature->SetGeometryDirectly( poGeometry );
+        }
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                         ParseFieldValue()                            */
+/************************************************************************/
+
+void OGRCouchDBLayer::ParseFieldValue(OGRFeature* poFeature,
+                                      const char* pszKey,
+                                      json_object* poValue)
+{
+    int nField = poFeature->GetFieldIndex(pszKey);
+    if (nField < 0)
+    {
+        CPLDebug("CouchDB",
+                    "Found field '%s' which is not in the layer definition. "
+                    "Ignoring its value",
+                    pszKey);
+    }
+    else if (poValue != NULL)
+    {
+        OGRFieldDefn* poFieldDefn = poFeature->GetFieldDefnRef(nField);
+        CPLAssert(poFieldDefn != NULL);
+        OGRFieldType eType = poFieldDefn->GetType();
+
+        if( OFTInteger == eType )
+        {
+            poFeature->SetField( nField, json_object_get_int(poValue) );
+        }
+        else if( OFTReal == eType )
+        {
+            poFeature->SetField( nField, json_object_get_double(poValue) );
+        }
+        else if( OFTIntegerList == eType )
+        {
+            if ( json_object_get_type(poValue) == json_type_array )
+            {
+                int nLength = json_object_array_length(poValue);
+                int* panVal = (int*)CPLMalloc(sizeof(int) * nLength);
+                for(int i=0;i<nLength;i++)
+                {
+                    json_object* poRow = json_object_array_get_idx(poValue, i);
+                    panVal[i] = json_object_get_int(poRow);
+                }
+                poFeature->SetField( nField, nLength, panVal );
+                CPLFree(panVal);
+            }
+        }
+        else if( OFTRealList == eType )
+        {
+            if ( json_object_get_type(poValue) == json_type_array )
+            {
+                int nLength = json_object_array_length(poValue);
+                double* padfVal = (double*)CPLMalloc(sizeof(double) * nLength);
+                for(int i=0;i<nLength;i++)
+                {
+                    json_object* poRow = json_object_array_get_idx(poValue, i);
+                    padfVal[i] = json_object_get_double(poRow);
+                }
+                poFeature->SetField( nField, nLength, padfVal );
+                CPLFree(padfVal);
+            }
+        }
+        else if( OFTStringList == eType )
+        {
+            if ( json_object_get_type(poValue) == json_type_array )
+            {
+                int nLength = json_object_array_length(poValue);
+                char** papszVal = (char**)CPLMalloc(sizeof(char*) * (nLength+1));
+                int i;
+                for(i=0;i<nLength;i++)
+                {
+                    json_object* poRow = json_object_array_get_idx(poValue, i);
+                    const char* pszVal = json_object_get_string(poRow);
+                    if (pszVal == NULL)
+                        break;
+                    papszVal[i] = CPLStrdup(pszVal);
+                }
+                papszVal[i] = NULL;
+                poFeature->SetField( nField, papszVal );
+                CSLDestroy(papszVal);
+            }
+        }
+        else
+        {
+            poFeature->SetField( nField, json_object_get_string(poValue) );
+        }
+    }
+}
+
+
+/************************************************************************/
+/*                      BuildFeatureDefnFromDoc()                       */
+/************************************************************************/
+
+void OGRCouchDBLayer::BuildFeatureDefnFromDoc(json_object* poDoc)
+{
+/* -------------------------------------------------------------------- */
+/*      Read collection of properties.                                  */
+/* -------------------------------------------------------------------- */
+    json_object* poObjProps = json_object_object_get( poDoc,
+                                                        "properties" );
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    if( NULL != poObjProps && json_object_get_type(poObjProps) == json_type_object )
+    {
+        json_object_object_foreachC( poObjProps, it )
+        {
+            if( -1 == poFeatureDefn->GetFieldIndex( it.key ) )
+            {
+                OGRFieldDefn fldDefn( it.key,
+                    GeoJSONPropertyToFieldType( it.val ) );
+                poFeatureDefn->AddFieldDefn( &fldDefn );
+            }
+        }
+    }
+    else
+    {
+        bGeoJSONDocument = FALSE;
+
+        json_object_object_foreachC( poDoc, it )
+        {
+            if( strcmp(it.key, "_id") != 0 &&
+                strcmp(it.key, "_rev") != 0 &&
+                strcmp(it.key, "geometry") != 0 &&
+                -1 == poFeatureDefn->GetFieldIndex( it.key ) )
+            {
+                OGRFieldDefn fldDefn( it.key,
+                    GeoJSONPropertyToFieldType( it.val ) );
+                poFeatureDefn->AddFieldDefn( &fldDefn );
+            }
+        }
+    }
+
+    if( json_object_object_get( poDoc, "geometry" ) == NULL )
+    {
+        poFeatureDefn->SetGeomType(wkbNone);
+    }
+}
+
+
+/************************************************************************/
+/*                      BuildFeatureDefnFromRows()                      */
+/************************************************************************/
+
+int OGRCouchDBLayer::BuildFeatureDefnFromRows(json_object* poAnswerObj)
+{
+    if ( !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Layer definition creation failed");
+        return FALSE;
+    }
+
+    if (poDS->IsError(poAnswerObj, "Layer definition creation failed"))
+    {
+        return FALSE;
+    }
+
+    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    if (poRows == NULL ||
+        !json_object_is_type(poRows, json_type_array))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Layer definition creation failed");
+        return FALSE;
+    }
+
+    int nRows = json_object_array_length(poRows);
+
+    json_object* poRow = NULL;
+    for(int i=0;i<nRows;i++)
+    {
+        json_object* poTmpRow = json_object_array_get_idx(poRows, i);
+        if (poTmpRow != NULL &&
+            json_object_is_type(poTmpRow, json_type_object))
+        {
+            json_object* poId = json_object_object_get(poTmpRow, "id");
+            const char* pszId = json_object_get_string(poId);
+            if (pszId != NULL && pszId[0] != '_')
+            {
+                poRow = poTmpRow;
+                break;
+            }
+        }
+    }
+
+    if ( poRow == NULL )
+    {
+        return FALSE;
+    }
+
+    json_object* poDoc = json_object_object_get(poRow, "doc");
+    if ( poDoc == NULL )
+        poDoc = json_object_object_get(poRow, "value");
+    if ( poDoc == NULL ||
+            !json_object_is_type(poDoc, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Layer definition creation failed");
+        return FALSE;
+    }
+
+    BuildFeatureDefnFromDoc(poDoc);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                   FetchNextRowsAnalyseDocs()                         */
+/************************************************************************/
+
+int OGRCouchDBLayer::FetchNextRowsAnalyseDocs(json_object* poAnswerObj)
+{
+    if (poAnswerObj == NULL)
+        return FALSE;
+
+    if ( !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "FetchNextRowsAnalyseDocs() failed");
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    if (poDS->IsError(poAnswerObj, "FetchNextRowsAnalyseDocs() failed"))
+    {
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    if (poRows == NULL ||
+        !json_object_is_type(poRows, json_type_array))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "FetchNextRowsAnalyseDocs() failed");
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    int nRows = json_object_array_length(poRows);
+    for(int i=0;i<nRows;i++)
+    {
+        json_object* poRow = json_object_array_get_idx(poRows, i);
+        if ( poRow == NULL ||
+             !json_object_is_type(poRow, json_type_object) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "FetchNextRowsAnalyseDocs() failed");
+            json_object_put(poAnswerObj);
+            return FALSE;
+        }
+
+        json_object* poDoc = json_object_object_get(poRow, "doc");
+        if ( poDoc == NULL )
+            poDoc = json_object_object_get(poRow, "value");
+        if ( poDoc == NULL ||
+             !json_object_is_type(poDoc, json_type_object) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "FetchNextRowsAnalyseDocs() failed");
+            json_object_put(poAnswerObj);
+            return FALSE;
+        }
+
+        json_object* poId = json_object_object_get(poDoc, "_id");
+        const char* pszId = json_object_get_string(poId);
+        if (pszId != NULL && strncmp(pszId, "_design/", 8) != 0)
+        {
+            aoFeatures.push_back(poDoc);
+        }
+    }
+
+    bEOF = nRows < GetFeaturesToFetch();
+
+    poFeatures = poAnswerObj;
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
new file mode 100644
index 0000000..daa5a7b
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
@@ -0,0 +1,140 @@
+/******************************************************************************
+ * $Id: ogrcouchdbrowslayer.cpp 22252 2011-04-28 20:59:51Z 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>
+ *
+ * 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_couchdb.h"
+
+CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 22252 2011-04-28 20:59:51Z rouault $");
+
+/************************************************************************/
+/*                         OGRCouchDBRowsLayer()                        */
+/************************************************************************/
+
+OGRCouchDBRowsLayer::OGRCouchDBRowsLayer(OGRCouchDBDataSource* poDS) :
+                                                    OGRCouchDBLayer(poDS)
+
+{
+    poFeatureDefn = new OGRFeatureDefn( "rows" );
+    poFeatureDefn->Reference();
+
+    OGRFieldDefn oFieldId("_id", OFTString);
+    poFeatureDefn->AddFieldDefn(&oFieldId);
+
+    OGRFieldDefn oFieldRev("_rev", OFTString);
+    poFeatureDefn->AddFieldDefn(&oFieldRev);
+
+    bAllInOne = FALSE;
+}
+
+/************************************************************************/
+/*                        ~OGRCouchDBRowsLayer()                        */
+/************************************************************************/
+
+OGRCouchDBRowsLayer::~OGRCouchDBRowsLayer()
+
+{
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRCouchDBRowsLayer::ResetReading()
+
+{
+    OGRCouchDBLayer::ResetReading();
+
+    if (!bAllInOne)
+    {
+        json_object_put(poFeatures);
+        poFeatures = NULL;
+        aoFeatures.resize(0);
+    }
+}
+
+/************************************************************************/
+/*                           FetchNextRows()                            */
+/************************************************************************/
+
+int OGRCouchDBRowsLayer::FetchNextRows()
+{
+    if (bAllInOne)
+        return FALSE;
+
+    json_object_put(poFeatures);
+    poFeatures = NULL;
+    aoFeatures.resize(0);
+
+    int bHasEsperluet = (strstr(poDS->GetURL(), "?") != NULL);
+
+    CPLString osURI;
+    if (strstr(poDS->GetURL(), "limit=") == NULL &&
+        strstr(poDS->GetURL(), "skip=") == NULL)
+    {
+        if (!bHasEsperluet)
+        {
+            bHasEsperluet = TRUE;
+            osURI += "?";
+        }
+
+        osURI += CPLSPrintf("&limit=%d&skip=%d",
+                            GetFeaturesToFetch(), nOffset);
+    }
+    if (strstr(poDS->GetURL(), "reduce=") == NULL)
+    {
+        if (!bHasEsperluet)
+        {
+            bHasEsperluet = TRUE;
+            osURI += "?";
+        }
+
+        osURI += "&reduce=false";
+    }
+    json_object* poAnswerObj = poDS->GET(osURI);
+    return FetchNextRowsAnalyseDocs(poAnswerObj);
+}
+
+/************************************************************************/
+/*                         BuildFeatureDefn()                           */
+/************************************************************************/
+
+int OGRCouchDBRowsLayer::BuildFeatureDefn()
+{
+    int bRet = FetchNextRows();
+    if (!bRet)
+        return FALSE;
+
+    bRet = BuildFeatureDefnFromRows(poFeatures);
+    if (!bRet)
+        return FALSE;
+
+    if ( bEOF )
+        bAllInOne = TRUE;
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
new file mode 100644
index 0000000..f070bda
--- /dev/null
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
@@ -0,0 +1,2109 @@
+/******************************************************************************
+ * $Id: ogrcouchdbtablelayer.cpp 23437 2011-11-28 23:03:56Z 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>
+ *
+ * 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_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 $");
+
+/************************************************************************/
+/*                       OGRCouchDBTableLayer()                         */
+/************************************************************************/
+
+OGRCouchDBTableLayer::OGRCouchDBTableLayer(OGRCouchDBDataSource* poDS,
+                                           const char* pszName) :
+                                                        OGRCouchDBLayer(poDS)
+
+{
+    osName = pszName;
+    char* pszEscapedName = CPLEscapeString(pszName, -1, CPLES_URL);
+    osEscapedName = pszEscapedName;
+    CPLFree(pszEscapedName);
+
+    bInTransaction = FALSE;
+
+    eGeomType = wkbUnknown;
+
+    nNextFIDForCreate = -1;
+    bHasLoadedMetadata = FALSE;
+    bMustWriteMetadata = FALSE;
+
+    bMustRunSpatialFilter = FALSE;
+    bServerSideSpatialFilteringWorks = TRUE;
+    bHasOGRSpatial = -1;
+    bHasGeocouchUtilsMinimalSpatialView = FALSE;
+
+    bServerSideAttributeFilteringWorks = TRUE;
+    bHasInstalledAttributeFilter = FALSE;
+
+    nUpdateSeq = -1;
+    bAlwaysValid = FALSE;
+
+    bExtentValid = FALSE;
+    bExtentSet = FALSE;
+    dfMinX = 0;
+    dfMinY = 0;
+    dfMaxX = 0;
+    dfMaxY = 0;
+
+    nCoordPrecision = atoi(CPLGetConfigOption("OGR_COUCHDB_COORDINATE_PRECISION", "-1"));
+}
+
+/************************************************************************/
+/*                      ~OGRCouchDBTableLayer()                         */
+/************************************************************************/
+
+OGRCouchDBTableLayer::~OGRCouchDBTableLayer()
+
+{
+    if( bMustWriteMetadata )
+        WriteMetadata();
+
+    for(int i=0;i<(int)aoTransactionFeatures.size();i++)
+    {
+        json_object_put(aoTransactionFeatures[i]);
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRCouchDBTableLayer::ResetReading()
+
+{
+    OGRCouchDBLayer::ResetReading();
+
+    json_object_put(poFeatures);
+    poFeatures = NULL;
+    aoFeatures.resize(0);
+
+    bMustRunSpatialFilter = m_poFilterGeom != NULL;
+    aosIdsToFetch.resize(0);
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
+
+    else if( EQUAL(pszCap,OLCFastGetExtent) )
+        return bExtentValid;
+
+    else if( EQUAL(pszCap,OLCRandomRead) )
+        return TRUE;
+
+    else if( EQUAL(pszCap,OLCSequentialWrite)
+             || EQUAL(pszCap,OLCRandomWrite)
+             || EQUAL(pszCap,OLCDeleteFeature) )
+        return poDS->IsReadWrite();
+
+    else if( EQUAL(pszCap,OLCCreateField) )
+        return poDS->IsReadWrite();
+
+    else if( EQUAL(pszCap, OLCTransactions) )
+        return poDS->IsReadWrite();
+
+    return OGRCouchDBLayer::TestCapability(pszCap);
+}
+
+/************************************************************************/
+/*                   RunSpatialFilterQueryIfNecessary()                 */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
+{
+    if (!bMustRunSpatialFilter)
+        return TRUE;
+
+    bMustRunSpatialFilter = FALSE;
+
+    CPLAssert(nOffset == 0);
+
+    aosIdsToFetch.resize(0);
+
+    const char* pszSpatialFilter = NULL;
+    if (bHasOGRSpatial < 0 || bHasOGRSpatial == FALSE)
+    {
+        pszSpatialFilter = CPLGetConfigOption("COUCHDB_SPATIAL_FILTER" , NULL);
+        if (pszSpatialFilter)
+            bHasOGRSpatial = FALSE;
+    }
+
+    if (bHasOGRSpatial < 0)
+    {
+        CPLString osURI("/");
+        osURI += osEscapedName;
+        osURI += "/_design/ogr_spatial";
+
+        json_object* poAnswerObj = poDS->GET(osURI);
+        bHasOGRSpatial = (poAnswerObj != NULL &&
+            json_object_is_type(poAnswerObj, json_type_object) &&
+            json_object_object_get(poAnswerObj, "spatial") != NULL);
+        json_object_put(poAnswerObj);
+
+        if (!bHasOGRSpatial)
+        {
+            /* Test if we have the 'minimal' spatial view provided by https://github.com/maxogden/geocouch-utils */
+            osURI = "/";
+            osURI += osEscapedName;
+            osURI += "/_design/geo";
+
+            json_object* poSpatialObj;
+            poAnswerObj = poDS->GET(osURI);
+            bHasGeocouchUtilsMinimalSpatialView = (poAnswerObj != NULL &&
+                json_object_is_type(poAnswerObj, json_type_object) &&
+                (poSpatialObj = json_object_object_get(poAnswerObj, "spatial")) != NULL &&
+                json_object_is_type(poSpatialObj, json_type_object) &&
+                json_object_object_get(poSpatialObj, "minimal") != NULL);
+            json_object_put(poAnswerObj);
+
+            if (!bHasGeocouchUtilsMinimalSpatialView)
+            {
+                CPLDebug("CouchDB",
+                            "Geocouch not working --> client-side spatial filtering");
+                bServerSideSpatialFilteringWorks = FALSE;
+                return FALSE;
+            }
+        }
+    }
+
+    OGREnvelope sEnvelope;
+    m_poFilterGeom->getEnvelope( &sEnvelope );
+
+    if (bHasOGRSpatial)
+        pszSpatialFilter = "_design/ogr_spatial/_spatial/spatial";
+    else if (bHasGeocouchUtilsMinimalSpatialView)
+        pszSpatialFilter = "_design/geo/_spatial/minimal";
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/";
+    osURI += pszSpatialFilter;
+    osURI += "?bbox=";
+    osURI += CPLSPrintf("%.9f,%.9f,%.9f,%.9f",
+                        sEnvelope.MinX, sEnvelope.MinY,
+                        sEnvelope.MaxX, sEnvelope.MaxY);
+
+    json_object* poAnswerObj = poDS->GET(osURI);
+    if (poAnswerObj == NULL)
+    {
+        CPLDebug("CouchDB",
+                    "Geocouch not working --> client-side spatial filtering");
+        bServerSideSpatialFilteringWorks = FALSE;
+        return FALSE;
+    }
+
+    if ( !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        CPLDebug("CouchDB",
+                    "Geocouch not working --> client-side spatial filtering");
+        bServerSideSpatialFilteringWorks = FALSE;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "FetchNextRowsSpatialFilter() failed");
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    /* Catch error for a non geocouch database */
+    json_object* poError = json_object_object_get(poAnswerObj, "error");
+    json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+
+    const char* pszError = json_object_get_string(poError);
+    const char* pszReason = json_object_get_string(poReason);
+
+    if (pszError && pszReason && strcmp(pszError, "not_found") == 0 &&
+        strcmp(pszReason, "Document is missing attachment") == 0)
+    {
+        CPLDebug("CouchDB",
+                    "Geocouch not working --> client-side spatial filtering");
+        bServerSideSpatialFilteringWorks = FALSE;
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    if (poDS->IsError(poAnswerObj, "FetchNextRowsSpatialFilter() failed"))
+    {
+        CPLDebug("CouchDB",
+                    "Geocouch not working --> client-side spatial filtering");
+        bServerSideSpatialFilteringWorks = FALSE;
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    if (poRows == NULL ||
+        !json_object_is_type(poRows, json_type_array))
+    {
+        CPLDebug("CouchDB",
+                    "Geocouch not working --> client-side spatial filtering");
+        bServerSideSpatialFilteringWorks = FALSE;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "FetchNextRowsSpatialFilter() failed");
+        json_object_put(poAnswerObj);
+        return FALSE;
+    }
+
+    int nRows = json_object_array_length(poRows);
+    for(int i=0;i<nRows;i++)
+    {
+        json_object* poRow = json_object_array_get_idx(poRows, i);
+        if ( poRow == NULL ||
+            !json_object_is_type(poRow, json_type_object) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "FetchNextRowsSpatialFilter() failed");
+            json_object_put(poAnswerObj);
+            return FALSE;
+        }
+
+        json_object* poId = json_object_object_get(poRow, "id");
+        const char* pszId = json_object_get_string(poId);
+        if (pszId != NULL)
+        {
+            aosIdsToFetch.push_back(pszId);
+        }
+    }
+
+    std::sort(aosIdsToFetch.begin(), aosIdsToFetch.end());
+
+    json_object_put(poAnswerObj);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                   FetchNextRowsSpatialFilter()                       */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::FetchNextRowsSpatialFilter()
+{
+    if (!RunSpatialFilterQueryIfNecessary())
+        return FALSE;
+
+    CPLString osContent("{\"keys\":[");
+    int nLimit = MIN(nOffset + GetFeaturesToFetch(), (int)aosIdsToFetch.size());
+    for(int i=nOffset;i<nLimit;i++)
+    {
+        if (i > nOffset)
+            osContent += ",";
+        osContent += "\"";
+        osContent += aosIdsToFetch[i];
+        osContent += "\"";
+    }
+    osContent += "]}";
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/_all_docs?include_docs=true";
+    json_object* poAnswerObj = poDS->POST(osURI, osContent);
+    return FetchNextRowsAnalyseDocs(poAnswerObj);
+}
+
+/************************************************************************/
+/*                HasFilterOnFieldOrCreateIfNecessary()                 */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::HasFilterOnFieldOrCreateIfNecessary(const char* pszFieldName)
+{
+    std::map<CPLString, int>::iterator oIter = oMapFilterFields.find(pszFieldName);
+    if (oIter != oMapFilterFields.end())
+        return oIter->second;
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/_design/ogr_filter_";
+    osURI += pszFieldName;
+
+    int bFoundFilter = FALSE;
+
+    json_object* poAnswerObj = poDS->GET(osURI);
+    if (poAnswerObj &&
+        json_object_is_type(poAnswerObj, json_type_object) &&
+        json_object_object_get(poAnswerObj, "views") != NULL)
+    {
+        bFoundFilter = TRUE;
+    }
+    json_object_put(poAnswerObj);
+
+    if (!bFoundFilter)
+    {
+        json_object* poDoc = json_object_new_object();
+        json_object* poViews = json_object_new_object();
+        json_object* poFilter = json_object_new_object();
+
+        CPLString osMap;
+
+        OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(
+                            poFeatureDefn->GetFieldIndex(pszFieldName));
+        CPLAssert(poFieldDefn);
+        int bIsNumeric = poFieldDefn->GetType() == OFTInteger ||
+                         poFieldDefn->GetType() == OFTReal;
+
+        if (bGeoJSONDocument)
+        {
+            osMap = "function(doc) { if (doc.properties && doc.properties.";
+            osMap += pszFieldName;
+            if (bIsNumeric)
+            {
+                osMap += " && typeof doc.properties.";
+                osMap += pszFieldName;
+                osMap += " == \"number\"";
+            }
+            osMap += ") emit(";
+            osMap += "doc.properties.";
+            osMap += pszFieldName;
+            osMap +=", ";
+            if (bIsNumeric)
+            {
+                osMap += "doc.properties.";
+                osMap += pszFieldName;
+            }
+            else
+                osMap +="null";
+            osMap += "); }";
+        }
+        else
+        {
+            osMap = "function(doc) { if (doc.";
+            osMap += pszFieldName;
+            if (bIsNumeric)
+            {
+                osMap += " && typeof doc.";
+                osMap += pszFieldName;
+                osMap += " == \"number\"";
+            }
+            osMap += ") emit(";
+            osMap += "doc.";
+            osMap += pszFieldName;
+            osMap +=", ";
+            if (bIsNumeric)
+            {
+                osMap += "doc.";
+                osMap += pszFieldName;
+            }
+            else
+                osMap +="null";
+            osMap += "); }";
+        }
+
+        json_object_object_add(poDoc, "views", poViews);
+        json_object_object_add(poViews, "filter", poFilter);
+        json_object_object_add(poFilter, "map", json_object_new_string(osMap));
+
+        if (bIsNumeric)
+            json_object_object_add(poFilter, "reduce", json_object_new_string("_stats"));
+        else
+            json_object_object_add(poFilter, "reduce", json_object_new_string("_count"));
+
+        json_object* poAnswerObj = poDS->PUT(osURI,
+                                            json_object_to_json_string(poDoc));
+
+        json_object_put(poDoc);
+
+        if (poDS->IsOK(poAnswerObj, "Filter creation failed"))
+        {
+            bFoundFilter = TRUE;
+            if (!bAlwaysValid)
+                bMustWriteMetadata = TRUE;
+            nUpdateSeq++;
+        }
+
+        json_object_put(poAnswerObj);
+    }
+
+    oMapFilterFields[pszFieldName] = bFoundFilter;
+
+    return bFoundFilter;
+}
+
+/************************************************************************/
+/*                         OGRCouchDBGetOpStr()                         */
+/************************************************************************/
+
+static const char* OGRCouchDBGetOpStr(int nOperation,
+                                      int& bOutHasStrictComparisons)
+{
+    bOutHasStrictComparisons = FALSE;
+
+    switch(nOperation)
+    {
+        case SWQ_EQ: return "=";
+        case SWQ_GE: return ">=";
+        case SWQ_LE: return "<=";
+        case SWQ_GT: bOutHasStrictComparisons = TRUE; return ">";
+        case SWQ_LT: bOutHasStrictComparisons = TRUE; return "<";
+        default:     return "unknown op";
+    }
+}
+
+/************************************************************************/
+/*                        OGRCouchDBGetValue()                          */
+/************************************************************************/
+
+static CPLString OGRCouchDBGetValue(swq_field_type eType,
+                                    swq_expr_node* poNode)
+{
+    if (eType == SWQ_STRING)
+    {
+        CPLString osVal("\"");
+        osVal += poNode->string_value;
+        osVal += "\"";
+        return osVal;
+    }
+    else if (eType == SWQ_INTEGER)
+    {
+        return CPLSPrintf("%d", poNode->int_value);
+    }
+    else if (eType == SWQ_FLOAT)
+    {
+        return CPLSPrintf("%.9f", poNode->float_value);
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Handled case! File a bug!");
+        return "";
+    }
+}
+
+/************************************************************************/
+/*                        OGRCouchDBGetKeyName()                          */
+/************************************************************************/
+
+static const char* OGRCouchDBGetKeyName(int nOperation)
+{
+    if (nOperation == SWQ_EQ)
+    {
+        return "key";
+    }
+    else if (nOperation == SWQ_GE ||
+             nOperation == SWQ_GT)
+    {
+        return "startkey";
+    }
+    else if (nOperation == SWQ_LE ||
+             nOperation == SWQ_LT)
+    {
+        return "endkey";
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Handled case! File a bug!");
+        return "";
+    }
+}
+/************************************************************************/
+/*                         BuildAttrQueryURI()                          */
+/************************************************************************/
+
+CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
+{
+    CPLString osURI = "";
+
+    bOutHasStrictComparisons = FALSE;
+
+    int bCanHandleFilter = FALSE;
+
+    swq_expr_node * pNode = (swq_expr_node *) m_poAttrQuery->GetSWGExpr();
+    if (pNode->eNodeType == SNT_OPERATION &&
+        (pNode->nOperation == SWQ_EQ ||
+            pNode->nOperation == SWQ_GE ||
+            pNode->nOperation == SWQ_LE ||
+            pNode->nOperation == SWQ_GT ||
+            pNode->nOperation == SWQ_LT) &&
+        pNode->nSubExprCount == 2 &&
+        pNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+        pNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT)
+    {
+        int nIndex = pNode->papoSubExpr[0]->field_index;
+        swq_field_type eType = pNode->papoSubExpr[1]->field_type;
+        const char* pszFieldName = poFeatureDefn->GetFieldDefn(nIndex)->GetNameRef();
+
+        if (pNode->nOperation == SWQ_EQ &&
+            nIndex == _ID_FIELD && eType == SWQ_STRING)
+        {
+            bCanHandleFilter = TRUE;
+
+            osURI = "/";
+            osURI += osEscapedName;
+            osURI += "/_all_docs?";
+        }
+        else if (nIndex >= FIRST_FIELD &&
+            (eType == SWQ_STRING || eType == SWQ_INTEGER || eType == SWQ_FLOAT))
+        {
+            int bFoundFilter = HasFilterOnFieldOrCreateIfNecessary(pszFieldName);
+            if (bFoundFilter)
+            {
+                bCanHandleFilter = TRUE;
+
+                osURI = "/";
+                osURI += osEscapedName;
+                osURI += "/_design/ogr_filter_";
+                osURI += pszFieldName;
+                osURI += "/_view/filter?";
+            }
+        }
+
+        if (bCanHandleFilter)
+        {
+            const char* pszOp = OGRCouchDBGetOpStr(pNode->nOperation, bOutHasStrictComparisons);
+            CPLString osVal = OGRCouchDBGetValue(eType, pNode->papoSubExpr[1]);
+            CPLDebug("CouchDB", "Evaluating %s %s %s", pszFieldName, pszOp, osVal.c_str());
+
+            osURI += OGRCouchDBGetKeyName(pNode->nOperation);
+            osURI += "=";
+            osURI += osVal;
+        }
+    }
+    else if (pNode->eNodeType == SNT_OPERATION &&
+                pNode->nOperation == SWQ_AND &&
+                pNode->nSubExprCount == 2 &&
+                pNode->papoSubExpr[0]->eNodeType == SNT_OPERATION &&
+                pNode->papoSubExpr[1]->eNodeType == SNT_OPERATION &&
+                (((pNode->papoSubExpr[0]->nOperation == SWQ_GE ||
+                pNode->papoSubExpr[0]->nOperation == SWQ_GT) &&
+                (pNode->papoSubExpr[1]->nOperation == SWQ_LE ||
+                pNode->papoSubExpr[1]->nOperation == SWQ_LT)) ||
+                ((pNode->papoSubExpr[0]->nOperation == SWQ_LE ||
+                pNode->papoSubExpr[0]->nOperation == SWQ_LT) &&
+                (pNode->papoSubExpr[1]->nOperation == SWQ_GE ||
+                pNode->papoSubExpr[1]->nOperation == SWQ_GT))) &&
+            pNode->papoSubExpr[0]->nSubExprCount == 2 &&
+            pNode->papoSubExpr[1]->nSubExprCount == 2 &&
+            pNode->papoSubExpr[0]->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+            pNode->papoSubExpr[0]->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+            pNode->papoSubExpr[1]->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+            pNode->papoSubExpr[1]->papoSubExpr[1]->eNodeType == SNT_CONSTANT)
+    {
+        int nIndex0 = pNode->papoSubExpr[0]->papoSubExpr[0]->field_index;
+        swq_field_type eType0 = pNode->papoSubExpr[0]->papoSubExpr[1]->field_type;
+        int nIndex1 = pNode->papoSubExpr[1]->papoSubExpr[0]->field_index;
+        swq_field_type eType1 = pNode->papoSubExpr[1]->papoSubExpr[1]->field_type;
+        const char* pszFieldName = poFeatureDefn->GetFieldDefn(nIndex0)->GetNameRef();
+
+        if (nIndex0 == nIndex1 && eType0 == eType1 &&
+            nIndex0 == _ID_FIELD && eType0 == SWQ_STRING)
+        {
+            bCanHandleFilter = TRUE;
+
+            osURI = "/";
+            osURI += osEscapedName;
+            osURI += "/_all_docs?";
+        }
+        else if (nIndex0 == nIndex1 && eType0 == eType1 &&
+            nIndex0 >= FIRST_FIELD &&
+            (eType0 == SWQ_STRING || eType0 == SWQ_INTEGER || eType0 == SWQ_FLOAT))
+        {
+            int bFoundFilter = HasFilterOnFieldOrCreateIfNecessary(pszFieldName);
+            if (bFoundFilter)
+            {
+                bCanHandleFilter = TRUE;
+
+                osURI = "/";
+                osURI += osEscapedName;
+                osURI += "/_design/ogr_filter_";
+                osURI += pszFieldName;
+                osURI += "/_view/filter?";
+            }
+        }
+
+        if (bCanHandleFilter)
+        {
+            swq_field_type eType = eType0;
+            CPLString osVal0 = OGRCouchDBGetValue(eType, pNode->papoSubExpr[0]->papoSubExpr[1]);
+            CPLString osVal1 = OGRCouchDBGetValue(eType, pNode->papoSubExpr[1]->papoSubExpr[1]);
+
+            int nOperation0 = pNode->papoSubExpr[0]->nOperation;
+            int nOperation1 = pNode->papoSubExpr[1]->nOperation;
+
+            const char* pszOp0 = OGRCouchDBGetOpStr(nOperation0, bOutHasStrictComparisons);
+            const char* pszOp1 = OGRCouchDBGetOpStr(nOperation1, bOutHasStrictComparisons);
+
+            CPLDebug("CouchDB", "Evaluating %s %s %s AND %s %s %s",
+                            pszFieldName, pszOp0, osVal0.c_str(),
+                            pszFieldName, pszOp1, osVal1.c_str());
+
+            osURI += OGRCouchDBGetKeyName(nOperation0);
+            osURI += "=";
+            osURI += osVal0;
+            osURI += "&";
+            osURI += OGRCouchDBGetKeyName(nOperation1);
+            osURI += "=";
+            osURI += osVal1;
+        }
+    }
+    else if (pNode->eNodeType == SNT_OPERATION &&
+                pNode->nOperation == SWQ_BETWEEN &&
+                pNode->nSubExprCount == 3 &&
+                pNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+                pNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+                pNode->papoSubExpr[2]->eNodeType == SNT_CONSTANT)
+    {
+        int nIndex = pNode->papoSubExpr[0]->field_index;
+        swq_field_type eType = pNode->papoSubExpr[0]->field_type;
+        const char* pszFieldName = poFeatureDefn->GetFieldDefn(nIndex)->GetNameRef();
+
+        if (nIndex == _ID_FIELD && eType == SWQ_STRING)
+        {
+            bCanHandleFilter = TRUE;
+
+            osURI = "/";
+            osURI += osEscapedName;
+            osURI += "/_all_docs?";
+        }
+        else if (nIndex >= FIRST_FIELD &&
+            (eType == SWQ_STRING || eType == SWQ_INTEGER || eType == SWQ_FLOAT))
+        {
+            int bFoundFilter = HasFilterOnFieldOrCreateIfNecessary(pszFieldName);
+            if (bFoundFilter)
+            {
+                bCanHandleFilter = TRUE;
+
+                osURI = "/";
+                osURI += osEscapedName;
+                osURI += "/_design/ogr_filter_";
+                osURI += pszFieldName;
+                osURI += "/_view/filter?";
+            }
+        }
+
+        if (bCanHandleFilter)
+        {
+            CPLString osVal0 = OGRCouchDBGetValue(eType, pNode->papoSubExpr[1]);
+            CPLString osVal1 = OGRCouchDBGetValue(eType, pNode->papoSubExpr[2]);
+
+            CPLDebug("CouchDB", "Evaluating %s BETWEEN %s AND %s",
+                        pszFieldName, osVal0.c_str(), osVal1.c_str());
+
+            osURI += OGRCouchDBGetKeyName(SWQ_GE);
+            osURI += "=";
+            osURI += osVal0;
+            osURI += "&";
+            osURI += OGRCouchDBGetKeyName(SWQ_LE);
+            osURI += "=";
+            osURI += osVal1;
+        }
+    }
+
+    return osURI;
+}
+
+/************************************************************************/
+/*                   FetchNextRowsAttributeFilter()                     */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::FetchNextRowsAttributeFilter()
+{
+    if (bHasInstalledAttributeFilter)
+    {
+        bHasInstalledAttributeFilter = FALSE;
+
+        CPLAssert(nOffset == 0);
+
+        int bOutHasStrictComparisons = FALSE;
+        osURIAttributeFilter = BuildAttrQueryURI(bOutHasStrictComparisons);
+
+        if (osURIAttributeFilter.size() == 0)
+        {
+            CPLDebug("CouchDB",
+                     "Turning to client-side attribute filtering");
+            bServerSideAttributeFilteringWorks = FALSE;
+            return FALSE;
+        }
+    }
+
+    CPLString osURI(osURIAttributeFilter);
+    osURI += CPLSPrintf("&limit=%d&skip=%d&include_docs=true",
+                        GetFeaturesToFetch(), nOffset);
+    if (strstr(osURI, "/_all_docs?") == NULL)
+        osURI += "&reduce=false";
+    json_object* poAnswerObj = poDS->GET(osURI);
+    return FetchNextRowsAnalyseDocs(poAnswerObj);
+}
+
+/************************************************************************/
+/*                           FetchNextRows()                            */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::FetchNextRows()
+{
+    json_object_put(poFeatures);
+    poFeatures = NULL;
+    aoFeatures.resize(0);
+
+    if( m_poFilterGeom != NULL && bServerSideSpatialFilteringWorks )
+    {
+        int bRet = FetchNextRowsSpatialFilter();
+        if (bRet || bServerSideSpatialFilteringWorks)
+            return bRet;
+    }
+
+    if( m_poAttrQuery != NULL && bServerSideAttributeFilteringWorks )
+    {
+        int bRet = FetchNextRowsAttributeFilter();
+        if (bRet || bServerSideAttributeFilteringWorks)
+            return bRet;
+    }
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += CPLSPrintf("/_all_docs?limit=%d&skip=%d&include_docs=true",
+                        GetFeaturesToFetch(), nOffset);
+    json_object* poAnswerObj = poDS->GET(osURI);
+    return FetchNextRowsAnalyseDocs(poAnswerObj);
+}
+
+
+/************************************************************************/
+/*                            GetFeature()                              */
+/************************************************************************/
+
+OGRFeature * OGRCouchDBTableLayer::GetFeature( long nFID )
+{
+    GetLayerDefn();
+
+    return GetFeature(CPLSPrintf("%09d", (int)nFID));
+}
+
+/************************************************************************/
+/*                            GetFeature()                              */
+/************************************************************************/
+
+OGRFeature * OGRCouchDBTableLayer::GetFeature( const char* pszId )
+{
+    GetLayerDefn();
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/";
+    osURI += pszId;
+    json_object* poAnswerObj = poDS->GET(osURI);
+    if (poAnswerObj == NULL)
+        return NULL;
+
+    if ( !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GetFeature(%s) failed",
+                 pszId);
+        json_object_put(poAnswerObj);
+        return NULL;
+    }
+
+    if ( poDS->IsError(poAnswerObj, CPLSPrintf("GetFeature(%s) failed", pszId)) )
+    {
+        json_object_put(poAnswerObj);
+        return NULL;
+    }
+
+    OGRFeature* poFeature = TranslateFeature( poAnswerObj );
+
+    json_object_put( poAnswerObj );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRCouchDBTableLayer::GetLayerDefn()
+{
+    if (poFeatureDefn == NULL)
+        LoadMetadata();
+
+    if (poFeatureDefn == NULL)
+    {
+        poFeatureDefn = new OGRFeatureDefn( osName );
+        poFeatureDefn->Reference();
+
+        poFeatureDefn->SetGeomType(eGeomType);
+
+        OGRFieldDefn oFieldId("_id", OFTString);
+        poFeatureDefn->AddFieldDefn(&oFieldId);
+
+        OGRFieldDefn oFieldRev("_rev", OFTString);
+        poFeatureDefn->AddFieldDefn(&oFieldRev);
+
+        if (nNextFIDForCreate == 0)
+        {
+            return poFeatureDefn;
+        }
+
+        CPLString osURI("/");
+        osURI += osEscapedName;
+        osURI += "/_all_docs?limit=10&include_docs=true";
+        json_object* poAnswerObj = poDS->GET(osURI);
+        if (poAnswerObj == NULL)
+            return poFeatureDefn;
+
+        BuildFeatureDefnFromRows(poAnswerObj);
+
+        eGeomType = poFeatureDefn->GetGeomType();
+
+        json_object_put(poAnswerObj);
+    }
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::GetFeatureCount(int bForce)
+{
+    GetLayerDefn();
+
+    if (m_poFilterGeom == NULL && m_poAttrQuery != NULL)
+    {
+        int bOutHasStrictComparisons = FALSE;
+        CPLString osURI = BuildAttrQueryURI(bOutHasStrictComparisons);
+        if (!bOutHasStrictComparisons && osURI.size() != 0 &&
+            strstr(osURI, "/_all_docs?") == NULL)
+        {
+            osURI += "&reduce=true";
+            json_object* poAnswerObj = poDS->GET(osURI);
+            json_object* poRows = NULL;
+            if (poAnswerObj != NULL &&
+                json_object_is_type(poAnswerObj, json_type_object) &&
+                (poRows = json_object_object_get(poAnswerObj, "rows")) != NULL &&
+                json_object_is_type(poRows, json_type_array))
+            {
+                int nLength = json_object_array_length(poRows);
+                if (nLength == 0)
+                {
+                    json_object_put(poAnswerObj);
+                    return 0;
+                }
+                else if (nLength == 1)
+                {
+                    json_object* poRow = json_object_array_get_idx(poRows, 0);
+                    if (poRow && json_object_is_type(poRow, json_type_object))
+                    {
+                        /* for string fields */
+                        json_object* poValue = json_object_object_get(poRow, "value");
+                        if (poValue != NULL && json_object_is_type(poValue, json_type_int))
+                        {
+                            int nVal = json_object_get_int(poValue);
+                            json_object_put(poAnswerObj);
+                            return nVal;
+                        }
+                        else if (poValue != NULL && json_object_is_type(poValue, json_type_object))
+                        {
+                            /* for numeric fields */
+                            json_object* poCount = json_object_object_get(poValue, "count");
+                            if (poCount != NULL && json_object_is_type(poCount, json_type_int))
+                            {
+                                int nVal = json_object_get_int(poCount);
+                                json_object_put(poAnswerObj);
+                                return nVal;
+                            }
+                        }
+                    }
+                }
+            }
+            json_object_put(poAnswerObj);
+        }
+    }
+
+    if (m_poFilterGeom != NULL && m_poAttrQuery == NULL &&
+        wkbFlatten(eGeomType) == wkbPoint)
+    {
+        /* Only optimize for wkbPoint case. Otherwise the result might be higher */
+        /* than the real value since the intersection of the bounding box of the */
+        /* geometry of a feature does not necessary mean the intersection of the */
+        /* geometry itself */
+        RunSpatialFilterQueryIfNecessary();
+        if (bServerSideSpatialFilteringWorks)
+        {
+            return (int)aosIdsToFetch.size();
+        }
+    }
+
+    if (m_poFilterGeom != NULL || m_poAttrQuery != NULL)
+        return OGRCouchDBLayer::GetFeatureCount(bForce);
+
+    return GetTotalFeatureCount();
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::GetTotalFeatureCount()
+{
+    int nTotalRows = -1;
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/_all_docs?startkey_docid=_&endkey_docid=_zzzzzzzzzzzzzzz";
+    json_object* poAnswerObj = poDS->GET(osURI);
+    if (poAnswerObj == NULL)
+        return nTotalRows;
+
+    if ( !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        json_object_put(poAnswerObj);
+        return nTotalRows;
+    }
+
+    json_object* poTotalRows = json_object_object_get(poAnswerObj,
+                                                        "total_rows");
+    if (poTotalRows != NULL &&
+        json_object_is_type(poTotalRows, json_type_int))
+    {
+        nTotalRows = json_object_get_int(poTotalRows);
+    }
+
+    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    if (poRows == NULL ||
+        !json_object_is_type(poRows, json_type_array))
+    {
+        json_object_put(poAnswerObj);
+        return nTotalRows;
+    }
+
+    bHasOGRSpatial = FALSE;
+
+    int nSpecialRows = json_object_array_length(poRows);
+    for(int i=0;i<nSpecialRows;i++)
+    {
+        json_object* poRow = json_object_array_get_idx(poRows, i);
+        if ( poRow != NULL &&
+             json_object_is_type(poRow, json_type_object) )
+        {
+            json_object* poId = json_object_object_get(poRow, "id");
+            const char* pszId = json_object_get_string(poId);
+            if ( pszId && strcmp(pszId, "_design/ogr_spatial") == 0)
+            {
+                bHasOGRSpatial = TRUE;
+            }
+        }
+    }
+
+    if (!bHasOGRSpatial)
+    {
+        bServerSideSpatialFilteringWorks = FALSE;
+    }
+
+    if (nTotalRows >= nSpecialRows)
+        nTotalRows -= nSpecialRows;
+
+    json_object_put(poAnswerObj);
+
+    return nTotalRows;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::CreateField( OGRFieldDefn *poField,
+                                 int bApproxOK )
+{
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    GetLayerDefn();
+
+    poFeatureDefn->AddFieldDefn(poField);
+
+    bMustWriteMetadata = TRUE;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         OGRCouchDBWriteFeature                       */
+/************************************************************************/
+
+static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
+                                            OGRwkbGeometryType eGeomType,
+                                            int bGeoJSONDocument,
+                                            int nCoordPrecision )
+{
+    CPLAssert( NULL != poFeature );
+
+    json_object* poObj = json_object_new_object();
+    CPLAssert( NULL != poObj );
+
+    if (poFeature->IsFieldSet(_ID_FIELD))
+    {
+        const char* pszId = poFeature->GetFieldAsString(_ID_FIELD);
+        json_object_object_add( poObj, "_id",
+                                json_object_new_string(pszId) );
+
+        if ( poFeature->GetFID() != OGRNullFID &&
+             strcmp(CPLSPrintf("%09ld", poFeature->GetFID()), pszId) != 0 )
+        {
+            CPLDebug("CouchDB",
+                     "_id field = %s, but FID = %09ld --> taking into account _id field only",
+                     pszId,
+                     poFeature->GetFID());
+        }
+    }
+    else if ( poFeature->GetFID() != OGRNullFID )
+    {
+        json_object_object_add( poObj, "_id",
+                                json_object_new_string(CPLSPrintf("%09ld", poFeature->GetFID())) );
+    }
+
+    if (poFeature->IsFieldSet(_REV_FIELD))
+    {
+        const char* pszRev = poFeature->GetFieldAsString(_REV_FIELD);
+        json_object_object_add( poObj, "_rev",
+                                json_object_new_string(pszRev) );
+    }
+
+    if (bGeoJSONDocument)
+    {
+        json_object_object_add( poObj, "type",
+                                json_object_new_string("Feature") );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write feature attributes to GeoJSON "properties" object.        */
+/* -------------------------------------------------------------------- */
+    json_object* poObjProps = NULL;
+
+    poObjProps = OGRGeoJSONWriteAttributes( poFeature );
+    if (poObjProps)
+    {
+        json_object_object_del(poObjProps, "_id");
+        json_object_object_del(poObjProps, "_rev");
+    }
+
+    if (bGeoJSONDocument)
+    {
+        json_object_object_add( poObj, "properties", poObjProps );
+    }
+    else
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        json_object_object_foreachC( poObjProps, it )
+        {
+            json_object_object_add( poObj, it.key, json_object_get(it.val) );
+        }
+        json_object_put(poObjProps);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write feature geometry to GeoJSON "geometry" object.            */
+/*      Null geometries are allowed, according to the GeoJSON Spec.     */
+/* -------------------------------------------------------------------- */
+    if (eGeomType != wkbNone)
+    {
+        json_object* poObjGeom = NULL;
+
+        OGRGeometry* poGeometry = poFeature->GetGeometryRef();
+        if ( NULL != poGeometry )
+        {
+            poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision );
+            if ( poObjGeom != NULL &&
+                 wkbFlatten(poGeometry->getGeometryType()) != wkbPoint &&
+                 !poGeometry->IsEmpty() )
+            {
+                OGREnvelope sEnvelope;
+                poGeometry->getEnvelope(&sEnvelope);
+
+                json_object* bbox = json_object_new_array();
+                json_object_array_add(bbox, json_object_new_double_with_precision(sEnvelope.MinX, nCoordPrecision));
+                json_object_array_add(bbox, json_object_new_double_with_precision(sEnvelope.MinY, nCoordPrecision));
+                json_object_array_add(bbox, json_object_new_double_with_precision(sEnvelope.MaxX, nCoordPrecision));
+                json_object_array_add(bbox, json_object_new_double_with_precision(sEnvelope.MaxY, nCoordPrecision));
+                json_object_object_add( poObjGeom, "bbox", bbox );
+            }
+        }
+
+        json_object_object_add( poObj, "geometry", poObjGeom );
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                           GetMaximumId()                             */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::GetMaximumId()
+{
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/_all_docs?startkey_docid=999999999&endkey_docid=000000000&descending=true&limit=1";
+    json_object* poAnswerObj = poDS->GET(osURI);
+    if (poAnswerObj == NULL)
+        return -1;
+
+    if ( !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GetMaximumId() failed");
+        json_object_put(poAnswerObj);
+        return -1;
+    }
+
+    if (poDS->IsError(poAnswerObj, "GetMaximumId() failed"))
+    {
+        json_object_put(poAnswerObj);
+        return -1;
+    }
+
+    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    if (poRows == NULL ||
+        !json_object_is_type(poRows, json_type_array))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GetMaximumId() failed");
+        json_object_put(poAnswerObj);
+        return -1;
+    }
+
+    int nRows = json_object_array_length(poRows);
+    if (nRows != 1)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GetMaximumId() failed");
+        json_object_put(poAnswerObj);
+        return -1;
+    }
+    
+    json_object* poRow = json_object_array_get_idx(poRows, 0);
+    if ( poRow == NULL ||
+            !json_object_is_type(poRow, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GetMaximumId() failed");
+        json_object_put(poAnswerObj);
+        return -1;
+    }
+
+    json_object* poId = json_object_object_get(poRow, "id");
+    const char* pszId = json_object_get_string(poId);
+    if (pszId != NULL)
+    {
+        int nId = atoi(pszId);
+        json_object_put(poAnswerObj);
+        return nId;
+    }
+
+    json_object_put(poAnswerObj);
+    return -1;
+}
+
+/************************************************************************/
+/*                           CreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::CreateFeature( OGRFeature *poFeature )
+
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeature->IsFieldSet(_REV_FIELD))
+    {
+        static int bOnce = FALSE;
+        if (!bOnce)
+        {
+            bOnce = TRUE;
+            CPLDebug("CouchDB", "CreateFeature() should be called with an unset _rev field. Ignoring it");
+        }
+        poFeature->UnsetField(_REV_FIELD);
+    }
+
+    if (nNextFIDForCreate < 0)
+    {
+        nNextFIDForCreate = GetMaximumId();
+        if (nNextFIDForCreate >= 0)
+            nNextFIDForCreate ++;
+        else
+            nNextFIDForCreate = GetTotalFeatureCount();
+    }
+
+    OGRGeometry* poGeom = poFeature->GetGeometryRef();
+    if (bExtentValid && poGeom != NULL && !poGeom->IsEmpty())
+    {
+        OGREnvelope sEnvelope;
+        poGeom->getEnvelope(&sEnvelope);
+        if (!bExtentSet)
+        {
+            dfMinX = sEnvelope.MinX;
+            dfMinY = sEnvelope.MinY;
+            dfMaxX = sEnvelope.MaxX;
+            dfMaxY = sEnvelope.MaxY;
+            bExtentSet = TRUE;
+        }
+        if (sEnvelope.MinX < dfMinX)
+            dfMinX = sEnvelope.MinX;
+        if (sEnvelope.MinY < dfMinY)
+            dfMinY = sEnvelope.MinY;
+        if (sEnvelope.MaxX > dfMaxX)
+            dfMaxX = sEnvelope.MaxX;
+        if (sEnvelope.MaxY > dfMaxY)
+            dfMaxY = sEnvelope.MaxY;
+    }
+
+    if (bExtentValid && eGeomType != wkbNone)
+        bMustWriteMetadata = TRUE;
+
+    int nFID = nNextFIDForCreate ++;
+    CPLString osFID;
+    if (!poFeature->IsFieldSet(_ID_FIELD) ||
+        !CSLTestBoolean(CPLGetConfigOption("COUCHDB_PRESERVE_ID_ON_INSERT", "FALSE")))
+    {
+        if (poFeature->GetFID() != OGRNullFID)
+        {
+            nFID = (int)poFeature->GetFID();
+        }
+        osFID = CPLSPrintf("%09d", nFID);
+
+        poFeature->SetField(_ID_FIELD, osFID);
+        poFeature->SetFID(nFID);
+    }
+    else
+    {
+        const char* pszId = poFeature->GetFieldAsString(_ID_FIELD);
+        osFID = pszId;
+    }
+
+    json_object* poObj = OGRCouchDBWriteFeature(poFeature, eGeomType,
+                                                bGeoJSONDocument,
+                                                nCoordPrecision);
+
+    if (bInTransaction)
+    {
+        aoTransactionFeatures.push_back(poObj);
+
+        return OGRERR_NONE;
+    }
+
+    const char* pszJson = json_object_to_json_string( poObj );
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/";
+    osURI += osFID;
+    json_object* poAnswerObj = poDS->PUT(osURI, pszJson);
+    json_object_put( poObj );
+
+    if (poAnswerObj == NULL)
+        return OGRERR_FAILURE;
+
+    if (!poDS->IsOK(poAnswerObj, "Feature creation failed"))
+    {
+        json_object_put(poAnswerObj);
+        return OGRERR_FAILURE;
+    }
+
+    json_object* poId = json_object_object_get(poAnswerObj, "id");
+    json_object* poRev = json_object_object_get(poAnswerObj, "rev");
+
+    const char* pszId = json_object_get_string(poId);
+    const char* pszRev = json_object_get_string(poRev);
+
+    if (pszId)
+    {
+        poFeature->SetField(_ID_FIELD, pszId);
+
+        int nFID = atoi(pszId);
+        const char* pszFID = CPLSPrintf("%09d", nFID);
+        if (strcmp(pszId, pszFID) == 0)
+            poFeature->SetFID(nFID);
+        else
+            poFeature->SetFID(-1);
+    }
+    if (pszRev)
+    {
+        poFeature->SetField(_REV_FIELD, pszRev);
+    }
+
+    json_object_put(poAnswerObj);
+
+    nUpdateSeq ++;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           SetFeature()                               */
+/************************************************************************/
+
+OGRErr      OGRCouchDBTableLayer::SetFeature( OGRFeature *poFeature )
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (!poFeature->IsFieldSet(_ID_FIELD))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "SetFeature() requires non null _id field");
+        return OGRERR_FAILURE;
+    }
+
+    json_object* poObj = OGRCouchDBWriteFeature(poFeature, eGeomType,
+                                                bGeoJSONDocument,
+                                                nCoordPrecision);
+
+    const char* pszJson = json_object_to_json_string( poObj );
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/";
+    osURI += poFeature->GetFieldAsString(_ID_FIELD);
+    json_object* poAnswerObj = poDS->PUT(osURI, pszJson);
+    json_object_put( poObj );
+
+    if (poAnswerObj == NULL)
+        return OGRERR_FAILURE;
+
+    if (!poDS->IsOK(poAnswerObj, "Feature update failed"))
+    {
+        json_object_put(poAnswerObj);
+        return OGRERR_FAILURE;
+    }
+
+    json_object* poRev = json_object_object_get(poAnswerObj, "rev");
+    const char* pszRev = json_object_get_string(poRev);
+    poFeature->SetField(_REV_FIELD, pszRev);
+
+    json_object_put(poAnswerObj);
+
+    if (bExtentValid && eGeomType != wkbNone)
+    {
+        bExtentValid = FALSE;
+        bMustWriteMetadata = TRUE;
+    }
+    nUpdateSeq ++;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::DeleteFeature( long nFID )
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    OGRFeature* poFeature = GetFeature(nFID);
+    if (poFeature == NULL)
+        return OGRERR_FAILURE;
+
+    return DeleteFeature(poFeature);
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::DeleteFeature( const char* pszId )
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    OGRFeature* poFeature = GetFeature(pszId);
+    if (poFeature == NULL)
+        return OGRERR_FAILURE;
+
+    return DeleteFeature(poFeature);
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::DeleteFeature( OGRFeature* poFeature )
+{
+    if (!poFeature->IsFieldSet(_ID_FIELD) ||
+        !poFeature->IsFieldSet(_REV_FIELD))
+    {
+        delete poFeature;
+        return OGRERR_FAILURE;
+    }
+
+    const char* pszId = poFeature->GetFieldAsString(_ID_FIELD);
+    const char* pszRev = poFeature->GetFieldAsString(_REV_FIELD);
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/";
+    osURI += CPLSPrintf("%s?rev=%s", pszId, pszRev);
+
+    if (bExtentValid && eGeomType != wkbNone)
+        bMustWriteMetadata = TRUE;
+
+    OGRGeometry* poGeom = poFeature->GetGeometryRef();
+    if (bExtentValid && bExtentSet && poGeom != NULL && !poGeom->IsEmpty())
+    {
+        OGREnvelope sEnvelope;
+        poGeom->getEnvelope(&sEnvelope);
+        if (dfMinX == sEnvelope.MinX ||
+            dfMinY == sEnvelope.MinY ||
+            dfMaxX == sEnvelope.MaxX ||
+            dfMaxY == sEnvelope.MaxY)
+        {
+            bExtentValid = FALSE;
+        }
+    }
+
+    delete poFeature;
+
+    json_object* poAnswerObj = poDS->DELETE(osURI);
+
+    if (poAnswerObj == NULL)
+        return OGRERR_FAILURE;
+
+    if (!poDS->IsOK(poAnswerObj, "Feature deletion failed"))
+    {
+        json_object_put(poAnswerObj);
+        return OGRERR_FAILURE;
+    }
+
+    nUpdateSeq ++;
+
+    json_object_put(poAnswerObj);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         StartTransaction()                           */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::StartTransaction()
+{
+    GetLayerDefn();
+
+    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 OGRCouchDBTableLayer::CommitTransaction()
+{
+    GetLayerDefn();
+
+    if (!bInTransaction)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
+        return OGRERR_FAILURE;
+    }
+
+    bInTransaction = FALSE;
+
+    if (aoTransactionFeatures.size() == 0)
+        return OGRERR_NONE;
+
+    CPLString osPost("{ \"docs\": [");
+    for(int i=0;i<(int)aoTransactionFeatures.size();i++)
+    {
+        if (i>0) osPost += ",";
+        const char* pszJson = json_object_to_json_string( aoTransactionFeatures[i] );
+        osPost += pszJson;
+        json_object_put(aoTransactionFeatures[i]);
+    }
+    osPost += "] }";
+    aoTransactionFeatures.resize(0);
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/_bulk_docs";
+    json_object* poAnswerObj = poDS->POST(osURI, osPost);
+
+    if (poAnswerObj == NULL)
+        return OGRERR_FAILURE;
+
+    if ( json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        poDS->IsError(poAnswerObj, "Bulk feature creation failed");
+
+        json_object_put(poAnswerObj);
+        return OGRERR_FAILURE;
+    }
+
+    if ( !json_object_is_type(poAnswerObj, json_type_array) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Bulk feature creation failed");
+        json_object_put(poAnswerObj);
+
+        return OGRERR_FAILURE;
+    }
+
+    int nRows = json_object_array_length(poAnswerObj);
+    for(int i=0;i<nRows;i++)
+    {
+        json_object* poRow = json_object_array_get_idx(poAnswerObj, i);
+        if ( poRow != NULL &&
+             json_object_is_type(poRow, json_type_object) )
+        {
+            json_object* poId = json_object_object_get(poRow, "id");
+            json_object* poRev = json_object_object_get(poRow, "rev");
+            json_object* poError = json_object_object_get(poRow, "error");
+            json_object* poReason = json_object_object_get(poRow, "reason");
+
+            const char* pszId = json_object_get_string(poId);
+
+            if (poError != NULL)
+            {
+                const char* pszError = json_object_get_string(poError);
+                const char* pszReason = json_object_get_string(poReason);
+
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Bulk feature creation failed : for %s: %s, %s",
+                         pszId ? pszId : "",
+                         pszError ? pszError : "",
+                         pszReason ? pszReason : "");
+            }
+            else if (poRev != NULL)
+            {
+                /*const char* pszRev = json_object_get_string(poRev);
+                CPLDebug("CouchDB", "id = %s, rev = %s",
+                         pszId ? pszId : "", pszRev ? pszRev : "");*/
+
+                nUpdateSeq ++;
+            }
+        }
+    }
+
+    json_object_put(poAnswerObj);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::RollbackTransaction()
+{
+    GetLayerDefn();
+
+    if (!bInTransaction)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
+        return OGRERR_FAILURE;
+    }
+    bInTransaction = FALSE;
+    for(int i=0;i<(int)aoTransactionFeatures.size();i++)
+    {
+        json_object_put(aoTransactionFeatures[i]);
+    }
+    aoTransactionFeatures.resize(0);
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    GetLayerDefn();
+
+    bServerSideAttributeFilteringWorks = TRUE;
+
+    OGRErr eErr = OGRCouchDBLayer::SetAttributeFilter(pszQuery);
+
+    if (eErr == OGRERR_NONE)
+    {
+        bHasInstalledAttributeFilter = TRUE;
+    }
+
+    return eErr;
+}
+
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRCouchDBTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
+
+{
+    GetLayerDefn();
+
+    if( InstallFilter( poGeomIn ) )
+    {
+        bMustRunSpatialFilter = TRUE;
+
+        ResetReading();
+    }
+}
+
+/************************************************************************/
+/*                          SetInfoAfterCreation()                      */
+/************************************************************************/
+
+void OGRCouchDBTableLayer::SetInfoAfterCreation(OGRwkbGeometryType eGType,
+                                                OGRSpatialReference* poSRSIn,
+                                                int nUpdateSeqIn,
+                                                int bGeoJSONDocumentIn)
+{
+    eGeomType = eGType;
+    nNextFIDForCreate = 0;
+    bMustWriteMetadata = TRUE;
+    bExtentValid = TRUE;
+    bHasLoadedMetadata = TRUE;
+    nUpdateSeq = nUpdateSeqIn;
+    bGeoJSONDocument = bGeoJSONDocumentIn;
+
+    CPLAssert(poSRS == NULL);
+    poSRS = poSRSIn;
+    if (poSRS)
+        poSRS->Reference();
+}
+
+/************************************************************************/
+/*                          GetSpatialRef()                             */
+/************************************************************************/
+
+OGRSpatialReference* OGRCouchDBTableLayer::GetSpatialRef()
+{
+    LoadMetadata();
+
+    return poSRS;
+}
+
+/************************************************************************/
+/*                     OGRCouchDBIsNumericObject()                      */
+/************************************************************************/
+
+static int OGRCouchDBIsNumericObject(json_object* poObj)
+{
+    int iType = json_object_get_type(poObj);
+    return iType == json_type_int || iType == json_type_double;
+}
+
+/************************************************************************/
+/*                          LoadMetadata()                              */
+/************************************************************************/
+
+void OGRCouchDBTableLayer::LoadMetadata()
+{
+    if (bHasLoadedMetadata)
+        return;
+
+    bHasLoadedMetadata = TRUE;
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/_design/ogr_metadata";
+    json_object* poAnswerObj = poDS->GET(osURI);
+    if (poAnswerObj == NULL)
+        return;
+
+    if ( !json_object_is_type(poAnswerObj, json_type_object) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "LoadMetadata() failed");
+        json_object_put(poAnswerObj);
+        return;
+    }
+
+    json_object* poRev = json_object_object_get(poAnswerObj, "_rev");
+    const char* pszRev = json_object_get_string(poRev);
+    if (pszRev)
+        osMetadataRev = pszRev;
+
+    json_object* poError = json_object_object_get(poAnswerObj, "error");
+    const char* pszError = json_object_get_string(poError);
+    if (pszError && strcmp(pszError, "not_found") == 0)
+    {
+        json_object_put(poAnswerObj);
+        return;
+    }
+
+    if (poDS->IsError(poAnswerObj, "LoadMetadata() failed"))
+    {
+        json_object_put(poAnswerObj);
+        return;
+    }
+
+    json_object* poJsonSRS = json_object_object_get(poAnswerObj, "srs");
+    const char* pszSRS = json_object_get_string(poJsonSRS);
+    if (pszSRS != NULL)
+    {
+        poSRS = new OGRSpatialReference();
+        if (poSRS->importFromWkt((char**)&pszSRS) != OGRERR_NONE)
+        {
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+
+    json_object* poGeomType = json_object_object_get(poAnswerObj, "geomtype");
+    const char* pszGeomType = json_object_get_string(poGeomType);
+
+    if (pszGeomType)
+    {
+        if (EQUAL(pszGeomType, "NONE"))
+        {
+            eGeomType = wkbNone;
+            bExtentValid = TRUE;
+        }
+        else
+        {
+            eGeomType = OGRFromOGCGeomType(pszGeomType);
+
+            json_object* poIs25D = json_object_object_get(poAnswerObj, "is_25D");
+            if (poIs25D && json_object_get_boolean(poIs25D))
+                eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
+
+            json_object* poExtent = json_object_object_get(poAnswerObj, "extent");
+            if (poExtent && json_object_get_type(poExtent) == json_type_object)
+            {
+                json_object* poUpdateSeq =
+                    json_object_object_get(poExtent, "validity_update_seq");
+                if (poUpdateSeq && json_object_get_type(poUpdateSeq) == json_type_int)
+                {
+                    int nValidityUpdateSeq = json_object_get_int(poUpdateSeq);
+                    if (nValidityUpdateSeq <= 0)
+                    {
+                        bAlwaysValid = TRUE;
+                    }
+                    else
+                    {
+                        if (nUpdateSeq < 0)
+                            nUpdateSeq = FetchUpdateSeq();
+                        if (nUpdateSeq != nValidityUpdateSeq)
+                        {
+                            CPLDebug("CouchDB",
+                                    "_design/ogr_metadata.extent.validity_update_seq "
+                                    "doesn't match database update_seq --> ignoring stored extent");
+                            poUpdateSeq = NULL;
+                        }
+                    }
+                }
+                else
+                    poUpdateSeq = NULL;
+
+                json_object* poBbox = json_object_object_get(poExtent, "bbox");
+                if (poUpdateSeq && poBbox &&
+                    json_object_get_type(poBbox) == json_type_array &&
+                    json_object_array_length(poBbox) == 4 &&
+                    OGRCouchDBIsNumericObject(json_object_array_get_idx(poBbox, 0)) &&
+                    OGRCouchDBIsNumericObject(json_object_array_get_idx(poBbox, 1)) &&
+                    OGRCouchDBIsNumericObject(json_object_array_get_idx(poBbox, 2)) &&
+                    OGRCouchDBIsNumericObject(json_object_array_get_idx(poBbox, 3)))
+                {
+                    dfMinX = json_object_get_double(json_object_array_get_idx(poBbox, 0));
+                    dfMinY = json_object_get_double(json_object_array_get_idx(poBbox, 1));
+                    dfMaxX = json_object_get_double(json_object_array_get_idx(poBbox, 2));
+                    dfMaxY = json_object_get_double(json_object_array_get_idx(poBbox, 3));
+                    bExtentValid = bExtentSet = TRUE;
+                }
+            }
+        }
+    }
+
+    json_object* poGeoJSON = json_object_object_get(poAnswerObj, "geojson_documents");
+    if (poGeoJSON && json_object_is_type(poGeoJSON, json_type_boolean))
+        bGeoJSONDocument = json_object_get_boolean(poGeoJSON);
+
+    json_object* poFields = json_object_object_get(poAnswerObj, "fields");
+    if (poFields && json_object_is_type(poFields, json_type_array))
+    {
+        poFeatureDefn = new OGRFeatureDefn( osName );
+        poFeatureDefn->Reference();
+
+        poFeatureDefn->SetGeomType(eGeomType);
+
+        OGRFieldDefn oFieldId("_id", OFTString);
+        poFeatureDefn->AddFieldDefn(&oFieldId);
+
+        OGRFieldDefn oFieldRev("_rev", OFTString);
+        poFeatureDefn->AddFieldDefn(&oFieldRev);
+
+        int nFields = json_object_array_length(poFields);
+        for(int i=0;i<nFields;i++)
+        {
+            json_object* poField = json_object_array_get_idx(poFields, i);
+            if (poField && json_object_is_type(poField, json_type_object))
+            {
+                json_object* poName = json_object_object_get(poField, "name");
+                const char* pszName = json_object_get_string(poName);
+                if (pszName)
+                {
+                    json_object* poType = json_object_object_get(poField, "type");
+                    const char* pszType = json_object_get_string(poType);
+                    OGRFieldType eType = OFTString;
+                    if (pszType)
+                    {
+                        if (strcmp(pszType, "integer") == 0)
+                            eType = OFTInteger;
+                        else if (strcmp(pszType, "integerlist") == 0)
+                            eType = OFTIntegerList;
+                        else if (strcmp(pszType, "real") == 0)
+                            eType = OFTReal;
+                        else if (strcmp(pszType, "reallist") == 0)
+                            eType = OFTRealList;
+                        else if (strcmp(pszType, "string") == 0)
+                            eType = OFTString;
+                        else if (strcmp(pszType, "stringlist") == 0)
+                            eType = OFTStringList;
+                    }
+
+                    OGRFieldDefn oField(pszName, eType);
+                    poFeatureDefn->AddFieldDefn(&oField);
+                }
+            }
+        }
+    }
+
+    json_object_put(poAnswerObj);
+
+    return;
+}
+
+/************************************************************************/
+/*                          WriteMetadata()                             */
+/************************************************************************/
+
+void OGRCouchDBTableLayer::WriteMetadata()
+{
+    GetLayerDefn();
+
+    CPLString osURI;
+    osURI = "/";
+    osURI += osEscapedName;
+    osURI += "/_design/ogr_metadata";
+
+    json_object* poDoc = json_object_new_object();
+
+    if (osMetadataRev.size() > 0)
+    {
+        json_object_object_add(poDoc, "_rev",
+                               json_object_new_string(osMetadataRev));
+    }
+
+    if (poSRS)
+    {
+        char* pszWKT = NULL;
+        poSRS->exportToWkt(&pszWKT);
+        if (pszWKT)
+        {
+            json_object_object_add(poDoc, "srs",
+                                   json_object_new_string(pszWKT));
+            CPLFree(pszWKT);
+        }
+    }
+
+    if (eGeomType != wkbNone)
+    {
+        json_object_object_add(poDoc, "geomtype",
+                    json_object_new_string(OGRToOGCGeomType(eGeomType)));
+        if (poFeatureDefn->GetGeomType() & wkb25DBit)
+        {
+            json_object_object_add(poDoc, "is_25D",
+                               json_object_new_boolean(TRUE));
+        }
+
+        if (bExtentValid && bExtentSet && nUpdateSeq >= 0)
+        {
+            json_object* poExtent = json_object_new_object();
+            json_object_object_add(poDoc, "extent", poExtent);
+
+            json_object_object_add(poExtent, "validity_update_seq",
+                                   json_object_new_int((bAlwaysValid) ? -1 : nUpdateSeq + 1));
+
+            json_object* poBbox = json_object_new_array();
+            json_object_object_add(poExtent, "bbox", poBbox);
+            json_object_array_add(poBbox, json_object_new_double_with_precision(dfMinX, nCoordPrecision));
+            json_object_array_add(poBbox, json_object_new_double_with_precision(dfMinY, nCoordPrecision));
+            json_object_array_add(poBbox, json_object_new_double_with_precision(dfMaxX, nCoordPrecision));
+            json_object_array_add(poBbox, json_object_new_double_with_precision(dfMaxY, nCoordPrecision));
+        }
+    }
+    else
+    {
+        json_object_object_add(poDoc, "geomtype",
+                               json_object_new_string("NONE"));
+    }
+
+    json_object_object_add(poDoc, "geojson_documents",
+                           json_object_new_boolean(bGeoJSONDocument));
+
+    json_object* poFields = json_object_new_array();
+    json_object_object_add(poDoc, "fields", poFields);
+
+
+    for(int i=FIRST_FIELD;i<poFeatureDefn->GetFieldCount();i++)
+    {
+        json_object* poField = json_object_new_object();
+        json_object_array_add(poFields, poField);
+
+        json_object_object_add(poField, "name",
+            json_object_new_string(poFeatureDefn->GetFieldDefn(i)->GetNameRef()));
+
+        const char* pszType = NULL;
+        switch (poFeatureDefn->GetFieldDefn(i)->GetType())
+        {
+            case OFTInteger: pszType = "integer"; break;
+            case OFTReal: pszType = "real"; break;
+            case OFTString: pszType = "string"; break;
+            case OFTIntegerList: pszType = "integerlist"; break;
+            case OFTRealList: pszType = "reallist"; break;
+            case OFTStringList: pszType = "stringlist"; break;
+            default: pszType = "string"; break;
+        }
+
+        json_object_object_add(poField, "type",
+                               json_object_new_string(pszType));
+    }
+
+    json_object* poAnswerObj = poDS->PUT(osURI,
+                                         json_object_to_json_string(poDoc));
+
+    json_object_put(poDoc);
+
+    if (poDS->IsOK(poAnswerObj, "Metadata creation failed"))
+    {
+        nUpdateSeq++;
+
+        json_object* poRev = json_object_object_get(poAnswerObj, "_rev");
+        const char* pszRev = json_object_get_string(poRev);
+        if (pszRev)
+            osMetadataRev = pszRev;
+    }
+
+    json_object_put(poAnswerObj);
+}
+
+/************************************************************************/
+/*                            GetExtent()                               */
+/************************************************************************/
+
+OGRErr OGRCouchDBTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    LoadMetadata();
+
+    if (!bExtentValid)
+        return OGRCouchDBLayer::GetExtent(psExtent, bForce);
+
+    psExtent->MinX = 0.0;
+    psExtent->MaxX = 0.0;
+    psExtent->MinY = 0.0;
+    psExtent->MaxY = 0.0;
+
+    if (!bExtentSet)
+        return OGRERR_FAILURE;
+
+    psExtent->MinX = dfMinX;
+    psExtent->MaxX = dfMaxX;
+    psExtent->MinY = dfMinY;
+    psExtent->MaxY = dfMaxY;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          FetchUpdateSeq()                            */
+/************************************************************************/
+
+int OGRCouchDBTableLayer::FetchUpdateSeq()
+{
+    if (nUpdateSeq >= 0)
+        return nUpdateSeq;
+
+    CPLString osURI("/");
+    osURI += osEscapedName;
+    osURI += "/";
+
+    json_object* poAnswerObj = poDS->GET(osURI);
+    if (poAnswerObj != NULL &&
+        json_object_is_type(poAnswerObj, json_type_object) &&
+        json_object_object_get(poAnswerObj, "update_seq") != NULL)
+    {
+        nUpdateSeq = json_object_get_int(json_object_object_get(poAnswerObj,
+                                                                "update_seq"));
+    }
+    else
+    {
+        poDS->IsError(poAnswerObj, "FetchUpdateSeq() failed");
+    }
+
+    json_object_put(poAnswerObj);
+
+    return nUpdateSeq;
+}
diff --git a/ogr/ogrsf_frmts/csv/drv_csv.html b/ogr/ogrsf_frmts/csv/drv_csv.html
index f0ef31e..922a2ea 100644
--- a/ogr/ogrsf_frmts/csv/drv_csv.html
+++ b/ogr/ogrsf_frmts/csv/drv_csv.html
@@ -59,7 +59,9 @@ the quoted string should be doubled up to "escape" them.</p>
 names for all the fields. However, if one or more of the names is all 
 numeric it is assumed that the first line is actually data values and
 dummy field names are generated internally (field_1 through field_n) and
-the first record is treated as a feature.</p>
+the first record is treated as a feature. Starting with GDAL 1.9.0 
+numeric values are treated as field names if they are enclosed in double quotes. 
+</p>
 
 Example (employee.csv):
 <pre>
@@ -155,6 +157,15 @@ to describe the type of each column of the layer and its optional width and prec
 </ul>
 </p>
 
+<h2>VSI Virtual File System API support</h2>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-only) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
+
 <h3>Examples</h3>
 
 <ul>
@@ -163,6 +174,16 @@ to describe the type of each column of the layer and its optional width and prec
 </li>
 </ul>
 
+<h2>Particular datasources</h2>
+
+The CSV driver can also read files whose structure is close to CSV files :
+<ul>
+<li>Airport data files NfdcFacilities.xls, NfdcRunways.xls, NfdcRemarks.xls and NfdcSchedules.xls
+    found on tha <a href="http://www.faa.gov/airports/airport_safety/airportdata_5010/menu/index.cfm">FAA website</a> (OGR >= 1.8.0)</li>
+<li>Files from the <a href="http://geonames.usgs.gov/domestic/download_data.htm">USGS GNIS</a> (Geographic Names Information System) (OGR >= 1.9.0)</li>
+<li>The allCountries file from <a href="http://www.geonames.org">GeoNames</a> (OGR >= 1.9.0 for direct import)</li>
+</ul>
+
 <h2>Other Notes</h2>
 
 <p>
diff --git a/ogr/ogrsf_frmts/csv/makefile.vc b/ogr/ogrsf_frmts/csv/makefile.vc
index f4bec0d..b8b9c05 100644
--- a/ogr/ogrsf_frmts/csv/makefile.vc
+++ b/ogr/ogrsf_frmts/csv/makefile.vc
@@ -1,6 +1,5 @@
 
-OBJ	=	ogrcsvdriver.obj ogrcsvdatasource.obj ogrcsvlayer.obj \
-
+OBJ	=	ogrcsvdriver.obj ogrcsvdatasource.obj ogrcsvlayer.obj
 EXTRAFLAGS =	-I.. -I..\..
 
 GDAL_ROOT	=	..\..\..
diff --git a/ogr/ogrsf_frmts/csv/ogr_csv.h b/ogr/ogrsf_frmts/csv/ogr_csv.h
index 54f6370..5c6697f 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 21373 2011-01-02 00:41:43Z rouault $
+ * $Id: ogr_csv.h 21806 2011-02-22 22:57:12Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Definition of classes for OGR .csv driver.
@@ -78,9 +78,16 @@ class OGRCSVLayer : public OGRLayer
     int                 iNfdcLatitudeS, iNfdcLongitudeS;
     int                 bDontHonourStrings;
 
+    /* GNIS specific */
+    int                 iLongitudeField, iLatitudeField;
+
+    int                 nTotalFeatures;
+
   public:
     OGRCSVLayer( const char *pszName, VSILFILE *fp, const char *pszFilename,
-                 int bNew, int bInWriteMode, char chDelimiter, const char* pszNfdcRunwaysGeomField );
+                 int bNew, int bInWriteMode, char chDelimiter,
+                 const char* pszNfdcRunwaysGeomField,
+                 const char* pszGeonamesGeomFieldPrefix );
   ~OGRCSVLayer();
 
     void                ResetReading();
@@ -98,6 +105,8 @@ class OGRCSVLayer : public OGRLayer
     void                SetCRLF(int);
     void                SetWriteGeometry(OGRCSVGeometryFormat eGeometryFormat);
     void                SetCreateCSVT(int bCreateCSVT);
+
+    virtual int         GetFeatureCount( int bForce = TRUE );
 };
 
 /************************************************************************/
@@ -121,7 +130,9 @@ class OGRCSVDataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename,
                               int bUpdate, int bForceAccept );
-    int                 OpenTable( const char * pszFilename, const char* pszNfdcRunwaysGeomField = NULL );
+    int                 OpenTable( const char * pszFilename,
+                                   const char* pszNfdcRunwaysGeomField = NULL,
+                                   const char* pszGeonamesGeomFieldPrefix = NULL);
     
     const char          *GetName() { return pszName; }
 
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
index 123e578..93c88a9 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdatasource.cpp 21373 2011-01-02 00:41:43Z rouault $
+ * $Id: ogrcsvdatasource.cpp 23244 2011-10-16 21:52:16Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDataSource class
@@ -31,8 +31,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_csv.h"
+#include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: ogrcsvdatasource.cpp 21373 2011-01-02 00:41:43Z rouault $");
+CPL_CVSID("$Id: ogrcsvdatasource.cpp 23244 2011-10-16 21:52:16Z rouault $");
 
 /************************************************************************/
 /*                          OGRCSVDataSource()                          */
@@ -108,67 +109,138 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
     /* For writable /vsizip/, do nothing more */
     if (bUpdateIn && bForceOpen && strncmp(pszFilename, "/vsizip/", 8) == 0)
         return TRUE;
-    
-    int bIgnoreExtension = EQUALN(pszFilename, "CSV:", 4);
+
+    CPLString osFilename(pszFilename);
+    CPLString osBaseFilename = CPLGetFilename(pszFilename);
+    CPLString osExt = CPLGetExtension(osFilename);
+    pszFilename = NULL;
+
+    int bIgnoreExtension = EQUALN(osFilename, "CSV:", 4);
+    int bUSGeonamesFile = FALSE;
+    int bGeonamesOrgFile = FALSE;
     if (bIgnoreExtension)
-        pszFilename += 4;
+    {
+        osFilename = osFilename + 4;
+    }
 
     /* Those are *not* real .XLS files, but text file with tab as column separator */
-    else if (EQUAL(CPLGetFilename(pszFilename), "NfdcFacilities.xls") ||
-             EQUAL(CPLGetFilename(pszFilename), "NfdcRunways.xls") ||
-             EQUAL(CPLGetFilename(pszFilename), "NfdcRemarks.xls") ||
-             EQUAL(CPLGetFilename(pszFilename), "NfdcSchedules.xls"))
+    if (EQUAL(osBaseFilename, "NfdcFacilities.xls") ||
+        EQUAL(osBaseFilename, "NfdcRunways.xls") ||
+        EQUAL(osBaseFilename, "NfdcRemarks.xls") ||
+        EQUAL(osBaseFilename, "NfdcSchedules.xls"))
     {
         if (bUpdateIn)
             return FALSE;
         bIgnoreExtension = TRUE;
     }
+    else if ((EQUALN(osBaseFilename, "NationalFile_", 13) ||
+              EQUALN(osBaseFilename, "POP_PLACES_", 11) ||
+              EQUALN(osBaseFilename, "HIST_FEATURES_", 14) ||
+              EQUALN(osBaseFilename, "US_CONCISE_", 11) ||
+              EQUALN(osBaseFilename, "AllNames_", 9) ||
+              EQUALN(osBaseFilename, "Feature_Description_History_", 28) ||
+              EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
+              EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
+              EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
+              EQUALN(osBaseFilename, "AllStates_", 10) ||
+              EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
+              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_Features_", 10)) ||
+              (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) &&
+             (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
+    {
+        if (bUpdateIn)
+            return FALSE;
+        bIgnoreExtension = TRUE;
+        bUSGeonamesFile = TRUE;
+
+        if (EQUAL(osExt, "zip") &&
+            strstr(osFilename, "/vsizip/") == NULL )
+        {
+            osFilename = "/vsizip/" + osFilename;
+        }
+    }
+    else if (EQUAL(osBaseFilename, "allCountries.txt") ||
+             EQUAL(osBaseFilename, "allCountries.zip"))
+    {
+        if (bUpdateIn)
+            return FALSE;
+        bIgnoreExtension = TRUE;
+        bGeonamesOrgFile = TRUE;
+
+        if (EQUAL(osExt, "zip") &&
+            strstr(osFilename, "/vsizip/") == NULL )
+        {
+            osFilename = "/vsizip/" + osFilename;
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Determine what sort of object this is.                          */
 /* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
 
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
+    if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0 )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Is this a single CSV file?                                      */
 /* -------------------------------------------------------------------- */
     if( VSI_ISREG(sStatBuf.st_mode)
-        && (bIgnoreExtension || EQUAL(CPLGetExtension(pszFilename),"csv")) )
+        && (bIgnoreExtension || EQUAL(osExt,"csv")) )
     {
-        if (EQUAL(CPLGetFilename(pszFilename), "NfdcFacilities.xls"))
+        if (EQUAL(CPLGetFilename(osFilename), "NfdcFacilities.xls"))
         {
-            return OpenTable( pszFilename, "ARP");
+            return OpenTable( osFilename, "ARP");
         }
-        else if (EQUAL(CPLGetFilename(pszFilename), "NfdcRunways.xls"))
+        else if (EQUAL(CPLGetFilename(osFilename), "NfdcRunways.xls"))
         {
-            OpenTable( pszFilename, "BaseEndPhysical");
-            OpenTable( pszFilename, "BaseEndDisplaced");
-            OpenTable( pszFilename, "ReciprocalEndPhysical");
-            OpenTable( pszFilename, "ReciprocalEndDisplaced");
+            OpenTable( osFilename, "BaseEndPhysical");
+            OpenTable( osFilename, "BaseEndDisplaced");
+            OpenTable( osFilename, "ReciprocalEndPhysical");
+            OpenTable( osFilename, "ReciprocalEndDisplaced");
+            return nLayers != 0;
+        }
+        else if (bUSGeonamesFile)
+        {
+            /* GNIS specific */
+            if (EQUALN(osBaseFilename, "NationalFedCodes_", 17) ||
+                EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) ||
+                EQUALN(osBaseFilename, "ANTARCTICA_", 11) ||
+                (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10)))
+            {
+                OpenTable( osFilename, NULL, "PRIMARY");
+            }
+            else if (EQUALN(osBaseFilename, "GOVT_UNITS_", 11) ||
+                     EQUALN(osBaseFilename, "Feature_Description_History_", 28))
+            {
+                OpenTable( osFilename, NULL, "");
+            }
+            else
+            {
+                OpenTable( osFilename, NULL, "PRIM");
+                OpenTable( osFilename, NULL, "SOURCE");
+            }
             return nLayers != 0;
         }
 
-        return OpenTable( pszFilename );
+        return OpenTable( osFilename );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is this a single a ZIP file with only a CSV file inside ?       */
 /* -------------------------------------------------------------------- */
-    if( strncmp(pszFilename, "/vsizip/", 8) == 0 &&
-        EQUAL(CPLGetExtension(pszFilename), "zip") &&
+    if( strncmp(osFilename, "/vsizip/", 8) == 0 &&
+        EQUAL(osExt, "zip") &&
         VSI_ISREG(sStatBuf.st_mode) )
     {
-        char** papszFiles = VSIReadDir(pszFilename);
+        char** papszFiles = VSIReadDir(osFilename);
         if (CSLCount(papszFiles) != 1 ||
             !EQUAL(CPLGetExtension(papszFiles[0]), "CSV"))
         {
             CSLDestroy(papszFiles);
             return FALSE;
         }
-        CPLString osFilename = CPLFormFilename(pszFilename, papszFiles[0], NULL);
+        CPLString osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL);
         CSLDestroy(papszFiles);
         return OpenTable( osFilename );
     }
@@ -183,12 +255,12 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 /*      Scan through for entries ending in .csv.                        */
 /* -------------------------------------------------------------------- */
     int nNotCSVCount = 0, i;
-    char **papszNames = CPLReadDir( pszFilename );
+    char **papszNames = CPLReadDir( osFilename );
 
     for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ )
     {
         CPLString oSubFilename = 
-            CPLFormFilename( pszFilename, papszNames[i], NULL );
+            CPLFormFilename( osFilename, papszNames[i], NULL );
 
         if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") )
             continue;
@@ -197,18 +269,52 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
             continue;
 
         if( VSIStatL( oSubFilename, &sStatBuf ) != 0 
-            || !VSI_ISREG(sStatBuf.st_mode) 
-            || !EQUAL(CPLGetExtension(oSubFilename),"csv") )
+            || !VSI_ISREG(sStatBuf.st_mode) )
         {
             nNotCSVCount++;
             continue;
         }
 
-        if( !OpenTable( oSubFilename ) )
+        if (EQUAL(CPLGetExtension(oSubFilename),"csv"))
+        {
+            if( !OpenTable( oSubFilename ) )
+            {
+                CSLDestroy( papszNames );
+                nNotCSVCount++;
+                return FALSE;
+            }
+        }
+
+        /* GNIS specific */
+        else if ( strlen(papszNames[i]) > 2 &&
+                  EQUALN(papszNames[i]+2, "_Features_", 10) &&
+                  EQUAL(CPLGetExtension(papszNames[i]), "txt") )
+        {
+            int bRet = OpenTable( oSubFilename, NULL, "PRIM");
+            bRet |= OpenTable( oSubFilename, NULL, "SOURCE");
+            if ( !bRet )
+            {
+                CSLDestroy( papszNames );
+                nNotCSVCount++;
+                return FALSE;
+            }
+        }
+        /* GNIS specific */
+        else if ( strlen(papszNames[i]) > 2 &&
+                  EQUALN(papszNames[i]+2, "_FedCodes_", 10) &&
+                  EQUAL(CPLGetExtension(papszNames[i]), "txt") )
+        {
+            if ( !OpenTable( oSubFilename, NULL, "PRIMARY") )
+            {
+                CSLDestroy( papszNames );
+                nNotCSVCount++;
+                return FALSE;
+            }
+        }
+        else
         {
-            CSLDestroy( papszNames );
             nNotCSVCount++;
-            return FALSE;
+            continue;
         }
     }
 
@@ -225,7 +331,9 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 /*                              OpenTable()                             */
 /************************************************************************/
 
-int OGRCSVDataSource::OpenTable( const char * pszFilename, const char* pszNfdcRunwaysGeomField )
+int OGRCSVDataSource::OpenTable( const char * pszFilename,
+                                 const char* pszNfdcRunwaysGeomField,
+                                 const char* pszGeonamesGeomFieldPrefix)
 
 {
 /* -------------------------------------------------------------------- */
@@ -245,6 +353,10 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename, const char* pszNfdcRu
         return FALSE;
     }
 
+    if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL &&
+        strstr(pszFilename, "/vsizip/") == NULL )
+        fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);
+
 /* -------------------------------------------------------------------- */
 /*      Read and parse a line.  Did we get multiple fields?             */
 /* -------------------------------------------------------------------- */
@@ -258,6 +370,11 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename, const char* pszNfdcRu
     char chDelimiter = CSVDetectSeperator(pszLine);
     VSIRewindL( fp );
 
+    /* GNIS specific */
+    if (pszGeonamesGeomFieldPrefix != NULL &&
+        strchr(pszLine, '|') != NULL)
+        chDelimiter = '|';
+
     char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, FALSE );
 						
     if( CSLCount(papszFields) < 2 )
@@ -283,10 +400,17 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename, const char* pszNfdcRu
         osLayerName += "_";
         osLayerName += pszNfdcRunwaysGeomField;
     }
+    else if (pszGeonamesGeomFieldPrefix != NULL &&
+             !EQUAL(pszGeonamesGeomFieldPrefix, ""))
+    {
+        osLayerName += "_";
+        osLayerName += pszGeonamesGeomFieldPrefix;
+    }
     if (EQUAL(pszFilename, "/vsistdin/"))
         osLayerName = "layer";
     papoLayers[nLayers-1] = 
-        new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate, chDelimiter, pszNfdcRunwaysGeomField );
+        new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate,
+                         chDelimiter, pszNfdcRunwaysGeomField, pszGeonamesGeomFieldPrefix );
 
     return TRUE;
 }
@@ -388,7 +512,8 @@ OGRCSVDataSource::CreateLayer( const char *pszLayerName,
     papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, 
                                              sizeof(void*) * nLayers);
     
-    papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, NULL, osFilename, TRUE, TRUE, chDelimiter, NULL );
+    papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, NULL, osFilename,
+                                             TRUE, TRUE, chDelimiter, NULL, NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Was a partiuclar CRLF order requested?                          */
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
index d27a80c..8ea9812 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdriver.cpp 20869 2010-10-17 20:03:01Z rouault $
+ * $Id: ogrcsvdriver.cpp 23016 2011-08-31 21:24:12Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDriver.
@@ -30,7 +30,7 @@
 #include "ogr_csv.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrcsvdriver.cpp 20869 2010-10-17 20:03:01Z rouault $");
+CPL_CVSID("$Id: ogrcsvdriver.cpp 23016 2011-08-31 21:24:12Z rouault $");
 
 /************************************************************************/
 /*                           ~OGRCSVDriver()                            */
@@ -82,6 +82,9 @@ OGRDataSource *OGRCSVDriver::CreateDataSource( const char * pszName,
 /* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
 
+    if (strcmp(pszName, "/dev/stdout") == 0)
+        pszName = "/vsistdout/";
+
     if( VSIStatL( pszName, &sStatBuf ) == 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
index dafd9ea..0db49e0 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvlayer.cpp 21374 2011-01-02 00:46:52Z rouault $
+ * $Id: ogrcsvlayer.cpp 23503 2011-12-09 20:40:35Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVLayer class.
@@ -33,7 +33,7 @@
 #include "cpl_csv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcsvlayer.cpp 21374 2011-01-02 00:46:52Z rouault $");
+CPL_CVSID("$Id: ogrcsvlayer.cpp 23503 2011-12-09 20:40:35Z rouault $");
 
 
 
@@ -134,6 +134,11 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter, int bDontHonourStr
     if( pszLine == NULL )
         return( NULL );
 
+    /* Skip BOM */
+    GByte* pabyData = (GByte*) pszLine;
+    if (pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF)
+        pszLine += 3;
+
     /* Special fix to read NdfcFacilities.xls that has non-balanced double quotes */
     if (chDelimiter == '\t' && bDontHonourStrings)
     {
@@ -202,13 +207,15 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter, int bDontHonourStr
 
 OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn, 
                           VSILFILE * fp, const char *pszFilename, int bNew, int bInWriteMode,
-                          char chDelimiter, const char* pszNfdcGeomField)
+                          char chDelimiter, const char* pszNfdcGeomField,
+                          const char* pszGeonamesGeomFieldPrefix)
 
 {
     fpCSV = fp;
 
     iWktGeomReadField = -1;
     iNfdcLatitudeS = iNfdcLongitudeS = -1;
+    iLatitudeField = iLongitudeField = -1;
     this->bInWriteMode = bInWriteMode;
     this->bNew = bNew;
     this->pszFilename = CPLStrdup(pszFilename);
@@ -228,11 +235,13 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
     bCreateCSVT = FALSE;
     bDontHonourStrings = FALSE;
 
+    nTotalFeatures = -1;
+
 /* -------------------------------------------------------------------- */
 /*      If this is not a new file, read ahead to establish if it is     */
 /*      already in CRLF (DOS) mode, or just a normal unix CR mode.      */
 /* -------------------------------------------------------------------- */
-    if( !bNew )
+    if( !bNew && bInWriteMode )
     {
         int nBytesRead = 0;
         char chNewByte;
@@ -244,6 +253,7 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
                 bUseCRLF = TRUE;
                 break;
             }
+            nBytesRead ++;
         }
         VSIRewindL( fpCSV );
     }
@@ -255,39 +265,103 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
 /* -------------------------------------------------------------------- */
     char **papszTokens = NULL;
     int nFieldCount=0, iField;
+    CPLValueType eType;
 
     if( !bNew )
     {
-        papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, FALSE );
-        nFieldCount = CSLCount( papszTokens );
-        bHasFieldNames = TRUE;
+        const char *pszLine = NULL;
+        char szDelimiter[2];
+        szDelimiter[0] = chDelimiter; szDelimiter[1] = '\0';
+
+        pszLine = CPLReadLineL( fpCSV );
+        if ( pszLine != NULL )
+        {
+            /* tokenize the strings and preserve quotes, so we can separate string from numeric */
+            /* this is only used in the test for bHasFeldNames (bug #4361) */
+            papszTokens = CSLTokenizeString2( pszLine, szDelimiter, 
+                                              CSLT_HONOURSTRINGS | CSLT_PRESERVEQUOTES );
+            nFieldCount = CSLCount( papszTokens );
+            bHasFieldNames = TRUE;
+
+            for( iField = 0; iField < nFieldCount && bHasFieldNames; iField++ )
+            {
+                eType = CPLGetValueType(papszTokens[iField]);
+                if ( (eType == CPL_VALUE_INTEGER ||
+                      eType == CPL_VALUE_REAL) ) {
+                    /* we have a numeric field, therefore do not consider the first line as field names */
+                    bHasFieldNames = FALSE;
+                }
+            }
+
+            /* tokenize without quotes to get the actual values */
+            CSLDestroy( papszTokens );
+            // papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, FALSE );   
+            papszTokens = CSLTokenizeString2( pszLine, szDelimiter, 
+                                              CSLT_HONOURSTRINGS);
+            nFieldCount = CSLCount( papszTokens );
+        }
     }
     else
         bHasFieldNames = FALSE;
 
-    for( iField = 0; iField < nFieldCount && bHasFieldNames; iField++ )
-    {
-        const char *pszToken = papszTokens[iField];
-        int bAllNumeric = TRUE;
+    if( !bNew && !bHasFieldNames )
+        VSIRewindL( fpCSV );
 
-        if (*pszToken != '\0')
+/* -------------------------------------------------------------------- */
+/*      Check for geonames.org tables                                   */
+/* -------------------------------------------------------------------- */
+    if( !bHasFieldNames && nFieldCount == 19 )
+    {
+        if (CPLGetValueType(papszTokens[0]) == CPL_VALUE_INTEGER &&
+            CPLGetValueType(papszTokens[4]) == CPL_VALUE_REAL &&
+            CPLGetValueType(papszTokens[5]) == CPL_VALUE_REAL &&
+            CPLAtof(papszTokens[4]) >= -90 && CPLAtof(papszTokens[4]) <= 90 &&
+            CPLAtof(papszTokens[5]) >= -180 && CPLAtof(papszTokens[4]) <= 180)
         {
-            while( *pszToken != '\0' && bAllNumeric )
+            bHasFieldNames = TRUE;
+            CSLDestroy(papszTokens);
+            papszTokens = NULL;
+
+            static const struct {
+                const char* pszName;
+                OGRFieldType eType;
+            }
+            asGeonamesFieldDesc[] =
             {
-                if( *pszToken != '.' && *pszToken != '-'
-                    && (*pszToken < '0' || *pszToken > '9') )
-                    bAllNumeric = FALSE;
-                pszToken++;
+                { "GEONAMEID", OFTString },
+                { "NAME", OFTString },
+                { "ASCIINAME", OFTString },
+                { "ALTNAMES", OFTString },
+                { "LATITUDE", OFTReal },
+                { "LONGITUDE", OFTReal },
+                { "FEATCLASS", OFTString },
+                { "FEATCODE", OFTString },
+                { "COUNTRY", OFTString },
+                { "CC2", OFTString },
+                { "ADMIN1", OFTString },
+                { "ADMIN2", OFTString },
+                { "ADMIN3", OFTString },
+                { "ADMIN4", OFTString },
+                { "POPULATION", OFTReal },
+                { "ELEVATION", OFTInteger },
+                { "GTOPO30", OFTInteger },
+                { "TIMEZONE", OFTString },
+                { "MODDATE", OFTString }
+            };
+            for(iField = 0; iField < nFieldCount; iField++)
+            {
+                OGRFieldDefn oFieldDefn(asGeonamesFieldDesc[iField].pszName,
+                                        asGeonamesFieldDesc[iField].eType);
+                poFeatureDefn->AddFieldDefn(&oFieldDefn);
             }
 
-            if( bAllNumeric )
-                bHasFieldNames = FALSE;
+            iLatitudeField = 4;
+            iLongitudeField = 5;
+
+            nFieldCount = 0;
         }
     }
 
-    if( !bNew && !bHasFieldNames )
-        VSIRewindL( fpCSV );
-
 
 /* -------------------------------------------------------------------- */
 /*      Search a csvt file for types                                */
@@ -378,8 +452,6 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
                 CPLError(CE_Warning, CPLE_NotSupported, "Unknown type : %s", papszFieldTypes[iField]);
         }
 
-        poFeatureDefn->AddFieldDefn( &oField );
-
         if( EQUAL(oField.GetNameRef(),"WKT")
             && oField.GetType() == OFTString 
             && iWktGeomReadField == -1 )
@@ -397,13 +469,40 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
                   EQUALN(oField.GetNameRef(), pszNfdcGeomField, strlen(pszNfdcGeomField)) &&
                   EQUAL(oField.GetNameRef() + strlen(pszNfdcGeomField), "LongitudeS") )
             iNfdcLongitudeS = iField;
+
+        /* GNIS specific */
+        else if ( pszGeonamesGeomFieldPrefix != NULL &&
+                  EQUALN(oField.GetNameRef(), pszGeonamesGeomFieldPrefix, strlen(pszGeonamesGeomFieldPrefix)) &&
+                  (EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LAT_DEC") ||
+                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LATITUDE_DEC") ||
+                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LATITUDE")) )
+        {
+            oField.SetType(OFTReal);
+            iLatitudeField = iField;
+        }
+        else if ( pszGeonamesGeomFieldPrefix != NULL &&
+                  EQUALN(oField.GetNameRef(), pszGeonamesGeomFieldPrefix, strlen(pszGeonamesGeomFieldPrefix)) &&
+                  (EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LONG_DEC") ||
+                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LONGITUDE_DEC") ||
+                   EQUAL(oField.GetNameRef() + strlen(pszGeonamesGeomFieldPrefix), "_LONGITUDE")) )
+        {
+            oField.SetType(OFTReal);
+            iLongitudeField = iField;
+        }
+
+        poFeatureDefn->AddFieldDefn( &oField );
+
     }
 
-    if ( iNfdcLatitudeS != -1 && iNfdcLongitudeS )
+    if ( iNfdcLatitudeS != -1 && iNfdcLongitudeS != -1 )
     {
         bDontHonourStrings = TRUE;
         poFeatureDefn->SetGeomType( wkbPoint );
     }
+    else if ( iLatitudeField != -1 && iLongitudeField != -1 )
+    {
+        poFeatureDefn->SetGeomType( wkbPoint );
+    }
     
     CSLDestroy( papszTokens );
     CSLDestroy( papszFieldTypes );
@@ -488,6 +587,7 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
     int         iAttr;
     int         nAttrCount = MIN(CSLCount(papszTokens),
                                  poFeatureDefn->GetFieldCount() );
+    CPLValueType eType;
     
     for( iAttr = 0; iAttr < nAttrCount; iAttr++)
     {
@@ -501,12 +601,22 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                 poFeature->SetGeometryDirectly( poGeom );
         }
 
-        if (poFeatureDefn->GetFieldDefn(iAttr)->GetType() == OFTReal)
+        OGRFieldType eFieldType = poFeatureDefn->GetFieldDefn(iAttr)->GetType();
+        if ( eFieldType == OFTReal || eFieldType == OFTInteger )
         {
-            if (papszTokens[iAttr][0] != '\0')
+            if (chDelimiter == ';' && eFieldType == OFTReal)
+            {
+                char* chComma = strchr(papszTokens[iAttr], ',');
+                if (chComma)
+                    *chComma = '.';
+            }
+            eType = CPLGetValueType(papszTokens[iAttr]);
+            if ( (papszTokens[iAttr][0] != '\0') &&
+                 ( eType == CPL_VALUE_INTEGER ||
+                   eType == CPL_VALUE_REAL ) )
                 poFeature->SetField( iAttr, CPLAtof(papszTokens[iAttr]) );
         }
-        else if (poFeatureDefn->GetFieldDefn(iAttr)->GetType() != OFTString)
+        else if (eFieldType != OFTString)
         {
             if (papszTokens[iAttr][0] != '\0')
                 poFeature->SetField( iAttr, papszTokens[iAttr] );
@@ -536,6 +646,28 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
         poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
     }
 
+/* -------------------------------------------------------------------- */
+/*      GNIS specific                                                   */
+/* -------------------------------------------------------------------- */
+    else if ( iLatitudeField != -1 &&
+              iLongitudeField != -1 &&
+              nAttrCount > iLatitudeField &&
+              nAttrCount > iLongitudeField  &&
+              papszTokens[iLongitudeField][0] != 0 &&
+              papszTokens[iLatitudeField][0] != 0)
+    {
+        /* Some records have dummy 0,0 value */
+        if (papszTokens[iLongitudeField][0] != '0' ||
+            papszTokens[iLongitudeField][1] != '\0' ||
+            papszTokens[iLatitudeField][0] != '0' ||
+            papszTokens[iLatitudeField][1] != '\0')
+        {
+            double dfLon = atof(papszTokens[iLongitudeField]);
+            double dfLat = atof(papszTokens[iLatitudeField]);
+            poFeature->SetGeometryDirectly( new OGRPoint(dfLon, dfLat) );
+        }
+    }
+
     CSLDestroy( papszTokens );
 
 /* -------------------------------------------------------------------- */
@@ -722,8 +854,7 @@ OGRErr OGRCSVLayer::CreateFeature( OGRFeature *poNewFeature )
                 CPLError( CE_Failure, CPLE_OpenFailed,
                         "Failed to create %s:\n%s",
                         pszFilename, VSIStrerror( errno ) );
-
-                return NULL;
+                return OGRERR_FAILURE;
             }
         }
 
@@ -962,3 +1093,39 @@ void OGRCSVLayer::SetCreateCSVT(int bCreateCSVT)
 {
     this->bCreateCSVT = bCreateCSVT;
 }
+
+/************************************************************************/
+/*                        GetFeatureCount()                             */
+/************************************************************************/
+
+int OGRCSVLayer::GetFeatureCount( int bForce )
+{
+    if (bInWriteMode || m_poFilterGeom != NULL || m_poAttrQuery != NULL)
+        return OGRLayer::GetFeatureCount(bForce);
+
+    if (nTotalFeatures >= 0)
+        return nTotalFeatures;
+
+    if (fpCSV == NULL)
+        return 0;
+
+    ResetReading();
+
+    char **papszTokens;
+    nTotalFeatures = 0;
+    while(TRUE)
+    {
+        papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, bDontHonourStrings );
+        if( papszTokens == NULL )
+            break;
+
+        if( papszTokens[0] != NULL )
+            nTotalFeatures ++;
+
+        CSLDestroy(papszTokens);
+    }
+
+    ResetReading();
+
+    return nTotalFeatures;
+}
diff --git a/ogr/ogrsf_frmts/dgn/dgnlibp.h b/ogr/ogrsf_frmts/dgn/dgnlibp.h
index 2994b24..189e151 100644
--- a/ogr/ogrsf_frmts/dgn/dgnlibp.h
+++ b/ogr/ogrsf_frmts/dgn/dgnlibp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnlibp.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: dgnlibp.h 22381 2011-05-16 21:14:22Z rouault $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Internal (privatE) datastructures, and prototypes for DGN Access 
@@ -87,9 +87,9 @@ typedef struct {
 } DGNInfo;
 
 #define DGN_INT32( p )  ((p)[2] \
-                        + (p)[3]*256 \
-                        + (p)[1]*65536*256 \
-                        + (p)[0]*65536)
+                        + ((p)[3] << 8) \
+                        + ((p)[1] << 24) \
+                        + ((p)[0] << 16))
 #define DGN_WRITE_INT32( n, p ) { GInt32 nMacroWork = (n);                   \
  ((unsigned char *)p)[0] = (unsigned char)((nMacroWork & 0x00ff0000) >> 16); \
  ((unsigned char *)p)[1] = (unsigned char)((nMacroWork & 0xff000000) >> 24); \
diff --git a/ogr/ogrsf_frmts/dgn/dgnread.cpp b/ogr/ogrsf_frmts/dgn/dgnread.cpp
index cefd62a..7a3c74b 100644
--- a/ogr/ogrsf_frmts/dgn/dgnread.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnread.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnread.cpp 20117 2010-07-22 14:07:43Z dron $
+ * $Id: dgnread.cpp 21684 2011-02-11 22:14:01Z warmerdam $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access Library element reading code.
@@ -29,7 +29,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnread.cpp 20117 2010-07-22 14:07:43Z dron $");
+CPL_CVSID("$Id: dgnread.cpp 21684 2011-02-11 22:14:01Z warmerdam $");
 
 static DGNElemCore *DGNParseTCB( DGNInfo * );
 static DGNElemCore *DGNParseColorTable( DGNInfo * );
@@ -926,7 +926,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       case DGNT_BSPLINE_SURFACE_BOUNDARY:
         {
           DGNElemBSplineSurfaceBoundary *psBounds;
-          int numverts = psDGN->abyElem[38] + psDGN->abyElem[39]*256;
+          short numverts = psDGN->abyElem[38] + psDGN->abyElem[39]*256;
 
           psBounds = (DGNElemBSplineSurfaceBoundary *)
             CPLCalloc(sizeof(DGNElemBSplineSurfaceBoundary)+
diff --git a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
index ef22857..9c343c6 100644
--- a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnwrite.cpp 19572 2010-04-29 13:44:07Z warmerdam $
+ * $Id: dgnwrite.cpp 22623 2011-06-29 21:44:00Z rouault $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access functions related to writing DGN elements.
@@ -29,7 +29,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnwrite.cpp 19572 2010-04-29 13:44:07Z warmerdam $");
+CPL_CVSID("$Id: dgnwrite.cpp 22623 2011-06-29 21:44:00Z rouault $");
 
 static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint, 
                            unsigned char *pabyTarget );
@@ -1593,7 +1593,7 @@ DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag,
 /* -------------------------------------------------------------------- */
 /*      Setup Raw data for the color table specific portion.            */
 /* -------------------------------------------------------------------- */
-    psCore->raw_bytes = 806;
+    psCore->raw_bytes = 806; /* FIXME: this is invalid : 806 < 41 + 783 (see below lines) */
     psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);
 
     psCore->raw_data[36] = (unsigned char) (nScreenFlag % 256);
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp b/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
index 0ebc9c9..4f829d2 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdgndatasource.cpp 12822 2007-11-16 22:52:15Z rouault $
+ * $Id: ogrdgndatasource.cpp 23431 2011-11-27 15:02:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdgndatasource.cpp 12822 2007-11-16 22:52:15Z rouault $");
+CPL_CVSID("$Id: ogrdgndatasource.cpp 23431 2011-11-27 15:02:24Z rouault $");
 
 /************************************************************************/
 /*                         OGRDGNDataSource()                           */
@@ -224,7 +224,7 @@ OGRLayer *OGRDGNDataSource::CreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Parse out various creation options.                             */
 /* -------------------------------------------------------------------- */
-    CSLInsertStrings( papszOptions, 0, papszExtraOptions );
+    papszOptions = CSLInsertStrings( papszOptions, 0, papszExtraOptions );
 
     b3DRequested = CSLFetchBoolean( papszOptions, "3D", 
                                     (((int) eGeomType) & wkb25DBit) );
diff --git a/ogr/ogrsf_frmts/dwg/GNUmakefile b/ogr/ogrsf_frmts/dwg/GNUmakefile
new file mode 100644
index 0000000..e25c753
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/GNUmakefile
@@ -0,0 +1,53 @@
+TD_ROOT = /home/warmerda/pkg/td_4.2
+TDLIB_ROOT = $(TD_ROOT)/lib/lnxX64_4.2pic
+TDXXFLAGS = \
+	-I$(TD_ROOT)/TD/Include \
+	-I$(TD_ROOT)/TD/Extensions/ExServices \
+	-I$(TD_ROOT)/TD/Examples/Common
+
+TD_LIBS =	$(TDLIB_ROOT)/libModelerGeometry.a \
+	$(TDLIB_ROOT)/libTD_BrepRenderer.a \
+	$(TDLIB_ROOT)/libTD_Br.a \
+        $(TDLIB_ROOT)/libTD_AcisBuilder.a \
+        $(TDLIB_ROOT)/libTD_DynBlocks.a \
+        $(TDLIB_ROOT)/libTD_Db.a \
+        $(TDLIB_ROOT)/libTD_DbRoot.a \
+        $(TDLIB_ROOT)/libTD_Gs.a \
+        $(TDLIB_ROOT)/libTD_SpatialIndex.a \
+        $(TDLIB_ROOT)/libTD_Ave.a \
+        $(TDLIB_ROOT)/libTD_Root.a \
+        $(TDLIB_ROOT)/libTD_Gi.a \
+        $(TDLIB_ROOT)/libTD_Ge.a \
+        $(TDLIB_ROOT)/libTD_FT.a \
+        $(TDLIB_ROOT)/libTD_Alloc.a \
+        $(TDLIB_ROOT)/libRxRasterServices.a \
+        $(TDLIB_ROOT)/libJpeg.a \
+        $(TDLIB_ROOT)/libRecomputeDimBlock.a \
+        $(TDLIB_ROOT)/libExFieldEvaluator.a \
+        $(TDLIB_ROOT)/libOdBagFiler.a \
+        $(TDLIB_ROOT)/libRasterProcessor.a \
+	$(TDLIB_ROOT)/libTD_ExamplesCommon.a
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrdwgdriver.o ogrdwgdatasource.o ogrdwglayer.o \
+		ogrdwg_dimension.o ogrdwg_hatch.o ogrdwgblockslayer.o \
+		ogrdwg_blockmap.o
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) -I../dxf $(TDXXFLAGS) $(CPPFLAGS)
+
+PLUGIN_SO	=	ogr_DWG.so
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ) $(PLUGIN_SO)
+
+$(O_OBJ) $(OBJ):	ogr_dwg.h 
+
+plugin: $(PLUGIN_SO)
+
+$(PLUGIN_SO):	$(OBJ) 
+	gcc -shared $(LNK_FLAGS) $(OBJ) $(CONFIG_LIBS_INS) $(EXTRA_LIBS) $(TD_LIBS) \
+		-o $(PLUGIN_SO)
diff --git a/ogr/ogrsf_frmts/dwg/drv_dwg.html b/ogr/ogrsf_frmts/dwg/drv_dwg.html
new file mode 100644
index 0000000..f64fb33
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/drv_dwg.html
@@ -0,0 +1,71 @@
+<html>
+<head>
+<title>AutoCAD DWG</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>AutoCAD DWG</h1>
+
+OGR supports reading most versions of AutoCAD DWG when built with the Open
+Design Alliance Teiga library.  DWG is an binary working format
+used for AutoCAD drawings.  A reasonable effort has been made to make the
+OGR DWG driver work similarly to the OGR DXF driver which shares a common
+data model.  The entire contents of the .dwg file is
+represented as a single layer named "entities". <p>
+
+DWG files are considered to have no georeferencing information through OGR.
+Features will all have the following generic attributes:
+
+<ul>
+<li> Layer: The name of the DXF layer.  The default layer is "0".
+<li> SubClasses: Where available, a list of classes to which an element belongs.
+<li> ExtendedEntity: Where available, extended entity attributes all appended to form a single text attribute.
+<li> Linetype: Where available, the line type used for this entity.
+<li> EntityHandle: The hexadecimal entity handle.  A sort of feature id.
+<li> Text: The text of labels.
+</ul>
+
+A reasonable attempt is made to preserve line color, line width, text size
+and orientation via OGR feature styling information when translating elements.
+Currently no effort is made to preserve fill styles or complex line style
+attributes.<p>
+
+The approximation of arcs, ellipses, circles and rounded polylines as
+linestrings is done by splitting the arcs into subarcs of no more than a
+threshhold angle.  This angle is the OGR_ARC_STEPSIZE.  This defaults to
+four degrees, but may be overridden by setting the configuration variable
+OGR_ARC_STEPSIZE.<p>
+
+<h2>DWG_INLINE_BLOCKS</h2>
+
+The default behavior is for block references to be expanded with the
+geometry of the block they reference.  However, if the DWG_INLINE_BLOCKS
+configuration option is set to the value FALSE, then the behavior is different
+as described here.
+
+<ul>
+<li> A new layer will be available called blocks.  It will contain one or
+more features for each block defined in the file.  In addition to the usual
+attributes, they will also have a BlockName attribute indicate what block
+they are part of.
+<li> The entities layer will have new attributes BlockName, BlockScale,
+and BlockAngle.
+<li> block referencesd will populate these new fields with the corresponding
+information (they are null for all other entities).
+<li> block references will not have block geometry inlined - instead they will
+have a point geometry for the insertion point.
+</ul>
+
+The intention is that with DWG_INLINE_BLOCKS disabled, the block references
+will remain as references and the original block definitions will be
+available via the blocks layer.<p>
+
+<h2>Building</h2>
+
+Currently DWG building is somewhat adhoc.  On linux the normal practice is
+to hand edit gdal/ogr/ogrsf_frmts/dwg/GNUmakefile, update paths, and then
+build the driver as a plugin using the "make plugin" target.<p>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/dwg/makefile.vc b/ogr/ogrsf_frmts/dwg/makefile.vc
new file mode 100755
index 0000000..4a3dd93
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/makefile.vc
@@ -0,0 +1,64 @@
+
+OBJ =	\
+    ogrdwgdriver.obj \
+    ogrdwgdatasource.obj \
+    ogrdwglayer.obj \
+    ogrdwgblockslayer.obj \
+    ogrdwg_blockmap.obj \
+    ogrdwg_dimension.obj \
+    ogrdwg_hatch.obj 
+
+DXF_OBJ = ..\dxf\intronurbs.obj ..\dxf\ogrdxf_polyline_smooth.obj 
+
+PLUGINDLL = ogr_DWG.dll
+
+GDAL_ROOT	=	..\..\..
+
+TD_LIBS =  \
+	$(TD_LIBDIR)/TD_ExamplesCommon.lib \
+	$(TD_LIBDIR)/TD_Key.lib \
+	$(TD_LIBDIR)/ModelerGeometry.lib \
+	$(TD_LIBDIR)/TD_BrepRenderer.lib \
+	$(TD_LIBDIR)/TD_Br.lib \
+	$(TD_LIBDIR)/TD_AcisBuilder.lib \
+	$(TD_LIBDIR)/TD_DynBlocks.lib \
+	$(TD_LIBDIR)/TD_Db.lib \
+	$(TD_LIBDIR)/TD_DbRoot.lib \
+	$(TD_LIBDIR)/TD_Gs.lib \
+	$(TD_LIBDIR)/TD_SpatialIndex.lib \
+	$(TD_LIBDIR)/TD_Ave.lib \
+	$(TD_LIBDIR)/TD_Root.lib \
+	$(TD_LIBDIR)/TD_Gi.lib \
+	$(TD_LIBDIR)/TD_Ge.lib \
+	$(TD_LIBDIR)/TD_FT.lib \
+	$(TD_LIBDIR)/TD_Alloc.lib \
+	$(TD_LIBDIR)/RxRasterServices.lib \
+	$(TD_LIBDIR)/Jpeg.lib \
+	$(TD_LIBDIR)/RecomputeDimBlock.lib \
+	$(TD_LIBDIR)/ExFieldEvaluator.lib \
+	$(TD_LIBDIR)/OdBagFiler.lib \
+	$(TD_LIBDIR)/RasterProcessor.lib \
+	advapi32.lib
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+
+EXTRAFLAGS = -I.. -I..\.. $(TD_FLAGS) $(TD_INCLUDE) -I..\dxf
+
+default:	$(OBJ)
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb
+	-del *.dll
+
+plugin:	 $(PLUGINDLL)
+
+$(PLUGINDLL):	$(OBJ)
+	link /dll $(LDEBUG) /out:$(PLUGINDLL) $(OBJ) $(DXF_OBJ) \
+		$(GDAL_ROOT)/gdal_i.lib $(TD_LIBS)
+	if exist $(PLUGINDLL).manifest mt -manifest $(PLUGINDLL).manifest \
+		-outputresource:$(PLUGINDLL);2
+
+
+
diff --git a/ogr/ogrsf_frmts/dwg/ogr_dwg.h b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
new file mode 100644
index 0000000..a8c2713
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
@@ -0,0 +1,278 @@
+/******************************************************************************
+ * $Id: ogr_dxf.h 22008 2011-03-22 19:45:20Z warmerdam $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Definition of classes for OGR .dwg driver.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011,  Frank Warmerdam
+ *
+ * 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_DWG_H_INCLUDED
+#define _OGR_DWG_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_conv.h"
+#include <vector>
+#include <map>
+#include <set>
+#include <queue>
+
+#include "ogr_autocad_services.h"
+
+#include "OdaCommon.h"
+#include "diagnostics.h"
+#include "DbDatabase.h"
+#include "DbEntity.h"
+#include "DbDimAssoc.h"
+#include "DbObjectIterator.h"
+#include "DbBlockTable.h"
+#include "DbBlockTableRecord.h"
+#include "DbSymbolTable.h"
+
+#include "OdCharMapper.h"
+#include "RxObjectImpl.h"
+
+#include "ExSystemServices.h"
+#include "ExHostAppServices.h"
+#include "OdFileBuf.h"
+#include "RxDynamicModule.h"
+#include "FdField.h"
+
+class OGRDWGDataSource;
+class OGRDWGServices;
+
+/************************************************************************/
+/*                          DWGBlockDefinition                          */
+/*                                                                      */
+/*      Container for info about a block.                               */
+/************************************************************************/
+
+class DWGBlockDefinition
+{
+public:
+    DWGBlockDefinition() : poGeometry(NULL) {}
+    ~DWGBlockDefinition();
+
+    OGRGeometry                *poGeometry;
+    std::vector<OGRFeature *>  apoFeatures;
+};
+
+/************************************************************************/
+/*                         OGRDWGBlocksLayer()                          */
+/************************************************************************/
+
+class OGRDWGBlocksLayer : public OGRLayer
+{
+    OGRDWGDataSource   *poDS;
+
+    OGRFeatureDefn     *poFeatureDefn;
+    
+    int                 iNextFID;
+    unsigned int        iNextSubFeature;
+
+    std::map<CPLString,DWGBlockDefinition>::iterator oIt;
+
+  public:
+    OGRDWGBlocksLayer( OGRDWGDataSource *poDS );
+    ~OGRDWGBlocksLayer();
+
+    void                ResetReading();
+    OGRFeature *        GetNextFeature();
+
+    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    int                 TestCapability( const char * );
+
+    OGRFeature *        GetNextUnfilteredFeature();
+};
+
+/************************************************************************/
+/*                             OGRDWGLayer                              */
+/************************************************************************/
+class OGRDWGLayer : public OGRLayer
+{
+    OGRDWGDataSource   *poDS;
+
+    OGRFeatureDefn     *poFeatureDefn;
+    int                 iNextFID;
+
+    std::set<CPLString> oIgnoredEntities;
+
+    std::queue<OGRFeature*> apoPendingFeatures;
+    void                ClearPendingFeatures();
+
+    std::map<CPLString,CPLString> oStyleProperties;
+    
+    void                TranslateGenericProperties( OGRFeature *poFeature, 
+                                                    OdDbEntityPtr poEntity );
+    void                PrepareLineStyle( OGRFeature *poFeature );
+//    void                ApplyOCSTransformer( OGRGeometry * );
+
+    OGRFeature *        TranslatePOINT( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateLINE( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateLWPOLYLINE( OdDbEntityPtr poEntity );
+    OGRFeature *        Translate2DPOLYLINE( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateELLIPSE( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateARC( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateMTEXT( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateDIMENSION( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateCIRCLE( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateSPLINE( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateHATCH( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateTEXT( OdDbEntityPtr poEntity );
+    OGRFeature *        TranslateINSERT( OdDbEntityPtr poEntity );
+
+    void                FormatDimension( CPLString &osText, double dfValue );
+
+    CPLString           TextUnescape( OdString oString);
+
+    OdDbBlockTableRecordPtr poBlock;
+    OdDbObjectIteratorPtr   poEntIter;
+
+  public:
+    OGRDWGLayer( OGRDWGDataSource *poDS );
+    ~OGRDWGLayer();
+
+    void                ResetReading();
+    OGRFeature *        GetNextFeature();
+
+    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    int                 TestCapability( const char * );
+
+    OGRFeature *        GetNextUnfilteredFeature();
+
+    // internal
+    void                SetBlockTable( OdDbBlockTableRecordPtr );
+    static double       AngleCorrect( double dfAngle, double dfRatio );
+};
+
+/************************************************************************/
+/*                           OGRDWGDataSource                           */
+/************************************************************************/
+
+class OGRDWGDataSource : public OGRDataSource
+{
+    VSILFILE           *fp;
+
+    CPLString           osName;
+    std::vector<OGRLayer*> apoLayers;
+
+    int                 iEntitiesSectionOffset;
+
+    std::map<CPLString,DWGBlockDefinition> oBlockMap;
+    std::map<CPLString,CPLString> oHeaderVariables;
+
+    CPLString           osEncoding;
+
+    // indexed by layer name, then by property name.
+    std::map< CPLString, std::map<CPLString,CPLString> > 
+                        oLayerTable;
+
+    std::map<CPLString,CPLString> oLineTypeTable;
+
+    int                 bInlineBlocks;
+
+    OGRDWGServices     *poServices;
+    OdDbDatabasePtr     poDb;
+
+  public:
+                        OGRDWGDataSource();
+                        ~OGRDWGDataSource();
+
+    OdDbDatabasePtr     GetDB() { return poDb; }
+
+    int                 Open( OGRDWGServices *poServices,
+                              const char * pszFilename, int bHeaderOnly=FALSE );
+
+    const char          *GetName() { return osName; }
+
+    int                 GetLayerCount() { return apoLayers.size(); }
+    OGRLayer            *GetLayer( int );
+
+    int                 TestCapability( const char * );
+
+    // The following is only used by OGRDWGLayer
+
+    int                 InlineBlocks() { return bInlineBlocks; }
+    void                AddStandardFields( OGRFeatureDefn *poDef );
+
+    // Implemented in ogrdxf_blockmap.cpp
+    void                ReadBlocksSection();
+    OGRGeometry        *SimplifyBlockGeometry( OGRGeometryCollection * );
+    DWGBlockDefinition *LookupBlock( const char *pszName );
+    std::map<CPLString,DWGBlockDefinition> &GetBlockMap() { return oBlockMap; }
+
+    // Layer and other Table Handling (ogrdatasource.cpp)
+    void                ReadLayerDefinitions();
+    void                ReadLineTypeDefinitions();
+    const char         *LookupLayerProperty( const char *pszLayer, 
+                                             const char *pszProperty );
+    const char         *LookupLineType( const char *pszName );
+
+    // Header variables. 
+    void                ReadHeaderSection();
+    const char         *GetVariable(const char *pszName, 
+                                    const char *pszDefault=NULL );
+
+    const char         *GetEncoding() { return osEncoding; }
+};
+
+/************************************************************************/
+/*                            OGRDWGServices                            */
+/*                                                                      */
+/*      Services implementation for OGR.  Eventually we should          */
+/*      override the ExSystemServices IO to use VSI*L.                  */
+/************************************************************************/
+class OGRDWGServices : public ExSystemServices, public ExHostAppServices
+{
+protected:
+  ODRX_USING_HEAP_OPERATORS(ExSystemServices);
+};
+
+/************************************************************************/
+/*                             OGRDWGDriver                             */
+/************************************************************************/
+
+class OGRDWGDriver : public OGRSFDriver
+{
+    int     bInitialized;
+    void    Initialize();
+    
+    OdStaticRxObject<OGRDWGServices> oServices;
+
+    static void ErrorHandler( OdResult oRes );
+
+  public:
+    OGRDWGDriver();
+    ~OGRDWGDriver();
+
+    OGRDWGServices *GetServices() { return &oServices; }
+
+    const char *GetName();
+    OGRDataSource *Open( const char *, int );
+    int         TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_DWG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
new file mode 100644
index 0000000..0cebe23
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
@@ -0,0 +1,173 @@
+/******************************************************************************
+ * $Id: ogrdwg_blockmap.cpp 22011 2011-03-22 20:13:38Z warmerdam $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Implements BlockMap reading and management portion of 
+ *           OGRDWGDataSource class
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, 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_dwg.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "cpl_csv.h"
+
+CPL_CVSID("$Id: ogrdwg_blockmap.cpp 22011 2011-03-22 20:13:38Z warmerdam $");
+
+/************************************************************************/
+/*                          ReadBlockSection()                          */
+/************************************************************************/
+
+void OGRDWGDataSource::ReadBlocksSection()
+
+{
+    OGRDWGLayer *poReaderLayer = (OGRDWGLayer *) GetLayerByName( "Entities" );
+    int bMergeBlockGeometries = CSLTestBoolean(
+        CPLGetConfigOption( "DWG_MERGE_BLOCK_GEOMETRIES", "TRUE" ) );
+
+/* -------------------------------------------------------------------- */
+/*      Loop over all the block tables, skipping *Model_Space which     */
+/*      we assume is primary entities.                                  */
+/* -------------------------------------------------------------------- */
+    OdDbBlockTableRecordPtr  poModelSpace, poBlock;
+    OdDbBlockTablePtr pTable = GetDB()->getBlockTableId().safeOpenObject();
+    OdDbSymbolTableIteratorPtr pBlkIter = pTable->newIterator();
+    
+    for (pBlkIter->start(); ! pBlkIter->done(); pBlkIter->step())
+    {
+        poBlock = pBlkIter->getRecordId().safeOpenObject();
+        CPLString osBlockName = (const char *) poBlock->getName();
+
+        if( EQUAL(osBlockName,"*Model_Space") )
+        {
+            poModelSpace = poBlock;
+            continue;
+        }
+
+        poReaderLayer->SetBlockTable( poBlock );
+
+        // Now we will process entities till we run out.
+        // We aggregate the geometries of the features into a multi-geometry,
+        // but throw away other stuff attached to the features.
+
+        OGRFeature *poFeature;
+        OGRGeometryCollection *poColl = new OGRGeometryCollection();
+        std::vector<OGRFeature*> apoFeatures;
+
+        while( (poFeature = poReaderLayer->GetNextUnfilteredFeature()) != NULL )
+        {
+            if( (poFeature->GetStyleString() != NULL
+                 && strstr(poFeature->GetStyleString(),"LABEL") != NULL)
+                || !bMergeBlockGeometries )
+            {
+                apoFeatures.push_back( poFeature );
+            }
+            else
+            {
+                poColl->addGeometryDirectly( poFeature->StealGeometry() );
+                delete poFeature;
+            }
+        }
+
+        if( poColl->getNumGeometries() == 0 )
+            delete poColl;
+        else
+            oBlockMap[osBlockName].poGeometry = SimplifyBlockGeometry(poColl);
+
+        if( apoFeatures.size() > 0 )
+            oBlockMap[osBlockName].apoFeatures = apoFeatures;
+    }
+
+    CPLDebug( "DWG", "Read %d blocks with meaningful geometry.", 
+              (int) oBlockMap.size() );
+
+    poReaderLayer->SetBlockTable( poModelSpace );
+}
+
+/************************************************************************/
+/*                       SimplifyBlockGeometry()                        */
+/************************************************************************/
+
+OGRGeometry *OGRDWGDataSource::SimplifyBlockGeometry( 
+    OGRGeometryCollection *poCollection )
+
+{
+/* -------------------------------------------------------------------- */
+/*      If there is only one geometry in the collection, just return    */
+/*      it.                                                             */
+/* -------------------------------------------------------------------- */
+    if( poCollection->getNumGeometries() == 1 )
+    {
+        OGRGeometry *poReturn = poCollection->getGeometryRef(0);
+        poCollection->removeGeometry(0,FALSE);
+        delete poCollection;
+        return poReturn;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Eventually we likely ought to have logic to convert to          */
+/*      polygon, multipolygon, multilinestring or multipoint but        */
+/*      I'll put that off till it would be meaningful.                  */
+/* -------------------------------------------------------------------- */
+    
+    return poCollection;
+}
+
+/************************************************************************/
+/*                            LookupBlock()                             */
+/*                                                                      */
+/*      Find the geometry collection corresponding to a name if it      */
+/*      exists.  Note that the returned geometry pointer is to a        */
+/*      geometry that continues to be owned by the datasource.  It      */
+/*      should be cloned for use.                                       */
+/************************************************************************/
+
+DWGBlockDefinition *OGRDWGDataSource::LookupBlock( const char *pszName )
+
+{
+    CPLString osName = pszName;
+
+    if( oBlockMap.count( osName ) == 0 )
+        return NULL;
+    else
+        return &(oBlockMap[osName]);
+}
+
+/************************************************************************/
+/*                        ~DWGBlockDefinition()                         */
+/*                                                                      */
+/*      Safe cleanup of a block definition.                             */
+/************************************************************************/
+
+DWGBlockDefinition::~DWGBlockDefinition()
+
+{
+    delete poGeometry;
+
+    while( !apoFeatures.empty() )
+    {
+        delete apoFeatures.back();
+        apoFeatures.pop_back();
+    }
+}
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
new file mode 100644
index 0000000..ebe8a30
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
@@ -0,0 +1,383 @@
+/******************************************************************************
+ * $Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Implements translation support for DIMENSION elements as a part
+ *           of the OGRDWGLayer class.  
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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_dwg.h"
+#include "cpl_conv.h"
+
+#include "DbDimension.h"
+#include "DbRotatedDimension.h"
+#include "DbAlignedDimension.h"
+
+CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
+
+#ifndef PI
+#define PI  3.14159265358979323846
+#endif 
+
+/************************************************************************/
+/*                         TranslateDIMENSION()                         */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateDIMENSION( OdDbEntityPtr poEntity )
+
+{
+    OdDbDimensionPtr poDim = OdDbDimension::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    double dfHeight = CPLAtof(poDS->GetVariable("$DIMTXT", "2.5"));
+    OdGePoint3d oTextPos, oTarget1, oTarget2, oArrow1;
+    CPLString osText;
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Generic Dimension stuff.                                        */
+/* -------------------------------------------------------------------- */
+    osText = (const char *) poDim->dimensionText();
+
+    oTextPos = poDim->textPosition();
+
+/* -------------------------------------------------------------------- */
+/*      Specific based on the subtype.                                  */
+/* -------------------------------------------------------------------- */
+    OdRxClass *poClass = poEntity->isA();
+    const OdString osName = poClass->name();
+    const char *pszEntityClassName = (const char *) osName;
+    
+    if( EQUAL(pszEntityClassName,"AcDbRotatedDimension") )
+    {
+        OdDbRotatedDimensionPtr poRDim = OdDbDimension::cast( poEntity );
+
+        oTarget2 = poRDim->xLine1Point();
+        oTarget1 = poRDim->xLine2Point();
+        oArrow1 = poRDim->dimLinePoint();
+    }
+    
+    else if( EQUAL(pszEntityClassName,"AcDbAlignedDimension") )
+    {
+        OdDbAlignedDimensionPtr poADim = OdDbDimension::cast( poEntity );
+
+        oTarget2 = poADim->xLine1Point();
+        oTarget1 = poADim->xLine2Point();
+        oArrow1 = poADim->dimLinePoint();
+    }
+
+/*************************************************************************
+
+   DIMENSION geometry layout 
+
+                  (11,21)(text center point)
+        |          DimText                  |
+(10,20) X<--------------------------------->X (Arrow2 - computed)
+(Arrow1)|                                   |
+        |                                   |
+        |                                   X (13,23) (Target2)
+        |
+        X (14,24) (Target1)
+
+
+Given:
+  Locations Arrow1, Target1, and Target2 we need to compute Arrow2.
+ 
+Steps:
+ 1) Compute direction vector from Target1 to Arrow1 (Vec1).
+ 2) Compute direction vector for arrow as perpendicular to Vec1 (call Vec2).
+ 3) Compute Arrow2 location as intersection between line defined by 
+    Vec2 and Arrow1 and line defined by Target2 and direction Vec1 (call Arrow2)
+
+Then we can draw lines for the various components.  
+
+Note that Vec1 and Vec2 may be horizontal, vertical or on an angle but
+the approach is as above in all these cases.
+
+*************************************************************************/
+
+/* -------------------------------------------------------------------- */
+/*      Step 1, compute direction vector between Target1 and Arrow1.    */
+/* -------------------------------------------------------------------- */
+    double dfVec1X, dfVec1Y;
+
+    dfVec1X = (oArrow1.x - oTarget1.x);
+    dfVec1Y = (oArrow1.y - oTarget1.y);
+    
+/* -------------------------------------------------------------------- */
+/*      Step 2, compute the direction vector from Arrow1 to Arrow2      */
+/*      as a perpendicluar to Vec1.                                     */
+/* -------------------------------------------------------------------- */
+    double dfVec2X, dfVec2Y;
+    
+    dfVec2X = dfVec1Y;
+    dfVec2Y = -dfVec1X;
+
+/* -------------------------------------------------------------------- */
+/*      Step 3, compute intersection of line from target2 along         */
+/*      direction vector 1, with the line through Arrow1 and            */
+/*      direction vector 2.                                             */
+/* -------------------------------------------------------------------- */
+    double dfL1M, dfL1B, dfL2M, dfL2B;
+    double dfArrowX2, dfArrowY2;
+    
+    // special case if vec1 is vertical.
+    if( dfVec1X == 0.0 )
+    {
+        dfArrowX2 = oTarget2.x;
+        dfArrowY2 = oArrow1.y;
+    }
+
+    // special case if vec2 is horizontal.
+    else if( dfVec1Y == 0.0 )
+    {
+        dfArrowX2 = oArrow1.x;
+        dfArrowY2 = oTarget2.y;
+    }
+
+    else // General case for diagonal vectors.
+    {
+        // first convert vec1 + target2 into y = mx + b format: call this L1
+
+        dfL1M = dfVec1Y / dfVec1X;
+        dfL1B = oTarget2.y - dfL1M * oTarget2.x;
+
+        // convert vec2 + Arrow1 into y = mx + b format, call this L2
+        
+        dfL2M = dfVec2Y / dfVec2X;
+        dfL2B = oArrow1.y - dfL2M * oArrow1.x;
+        
+        // Compute intersection x = (b2-b1) / (m1-m2)
+        
+        dfArrowX2 = (dfL2B - dfL1B) / (dfL1M-dfL2M);
+        dfArrowY2 = dfL2M * dfArrowX2 + dfL2B;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute the text angle.                                         */
+/* -------------------------------------------------------------------- */
+    double dfAngle = 0.0;
+
+    dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / PI;
+
+/* -------------------------------------------------------------------- */
+/*      Rescale the direction vectors so we can use them in             */
+/*      constructing arrowheads.  We want them to be about 3% of the    */
+/*      length of line on which the arrows will be drawn.               */
+/* -------------------------------------------------------------------- */
+#define VECTOR_LEN(x,y) sqrt( (x)*(x) + (y)*(y) )
+#define POINT_DIST(x1,y1,x2,y2)  VECTOR_LEN((x2-x1),(y2-y1))
+
+    double dfBaselineLength = POINT_DIST(oArrow1.x,oArrow1.y,
+                                         dfArrowX2,dfArrowY2);
+    double dfTargetLength = dfBaselineLength * 0.03;
+    double dfScaleFactor;
+
+    // recompute vector 2 to ensure the direction is regular
+    dfVec2X = (dfArrowX2 - oArrow1.x);
+    dfVec2Y = (dfArrowY2 - oArrow1.y);
+
+    // vector 1
+    dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec1X,dfVec1Y);
+    dfVec1X *= dfScaleFactor;
+    dfVec1Y *= dfScaleFactor;
+    
+    // vector 2
+    dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec2X,dfVec2Y);
+    dfVec2X *= dfScaleFactor;
+    dfVec2Y *= dfScaleFactor;
+
+/* -------------------------------------------------------------------- */
+/*      Create geometries for the different components of the           */
+/*      dimension object.                                               */
+/* -------------------------------------------------------------------- */
+    OGRMultiLineString *poMLS = new OGRMultiLineString();
+    OGRLineString oLine;
+
+    // main arrow line between Arrow1 and Arrow2
+    oLine.setPoint( 0, oArrow1.x, oArrow1.y );
+    oLine.setPoint( 1, dfArrowX2, dfArrowY2 );
+    poMLS->addGeometry( &oLine );
+
+    // dimension line from Target1 to Arrow1 with a small extension.
+    oLine.setPoint( 0, oTarget1.x, oTarget1.y );
+    oLine.setPoint( 1, oArrow1.x + dfVec1X, oArrow1.y + dfVec1Y );
+    poMLS->addGeometry( &oLine );
+    
+    // dimension line from Target2 to Arrow2 with a small extension.
+    oLine.setPoint( 0, oTarget2.x, oTarget2.y );
+    oLine.setPoint( 1, dfArrowX2 + dfVec1X, dfArrowY2 + dfVec1Y );
+    poMLS->addGeometry( &oLine );
+
+    // add arrow1 arrow head.
+
+    oLine.setPoint( 0, oArrow1.x, oArrow1.y );
+    oLine.setPoint( 1, 
+                    oArrow1.x + dfVec2X*3 + dfVec1X,
+                    oArrow1.y + dfVec2Y*3 + dfVec1Y );
+    poMLS->addGeometry( &oLine );
+
+    oLine.setPoint( 0, oArrow1.x, oArrow1.y );
+    oLine.setPoint( 1, 
+                    oArrow1.x + dfVec2X*3 - dfVec1X,
+                    oArrow1.y + dfVec2Y*3 - dfVec1Y );
+    poMLS->addGeometry( &oLine );
+
+    // add arrow2 arrow head.
+
+    oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
+    oLine.setPoint( 1, 
+                    dfArrowX2 - dfVec2X*3 + dfVec1X,
+                    dfArrowY2 - dfVec2Y*3 + dfVec1Y );
+    poMLS->addGeometry( &oLine );
+
+    oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
+    oLine.setPoint( 1, 
+                    dfArrowX2 - dfVec2X*3 - dfVec1X,
+                    dfArrowY2 - dfVec2Y*3 - dfVec1Y );
+    poMLS->addGeometry( &oLine );
+
+    poFeature->SetGeometryDirectly( poMLS );
+
+    PrepareLineStyle( poFeature );
+
+/* -------------------------------------------------------------------- */
+/*      Is the layer disabled/hidden/frozen/off?                        */
+/* -------------------------------------------------------------------- */
+    CPLString osLayer = poFeature->GetFieldAsString("Layer");
+
+    int bHidden = 
+        EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
+
+/* -------------------------------------------------------------------- */
+/*      Work out the color for this feature.                            */
+/* -------------------------------------------------------------------- */
+    int nColor = 256;
+
+    if( oStyleProperties.count("Color") > 0 )
+        nColor = atoi(oStyleProperties["Color"]);
+
+    // Use layer color? 
+    if( nColor < 1 || nColor > 255 )
+    {
+        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
+        if( pszValue != NULL )
+            nColor = atoi(pszValue);
+    }
+        
+    if( nColor < 1 || nColor > 255 )
+        nColor = 8;
+
+/* -------------------------------------------------------------------- */
+/*      Prepare a new feature to serve as the dimension text label      */
+/*      feature.  We will push it onto the layer as a pending           */
+/*      feature for the next feature read.                              */
+/* -------------------------------------------------------------------- */
+
+    // a single space supresses labelling.
+    if( osText == " " )
+        return poFeature;
+
+    OGRFeature *poLabelFeature = poFeature->Clone();
+
+    poLabelFeature->SetGeometryDirectly( new OGRPoint( oTextPos.x, oTextPos.y ) );
+
+    // Do we need to compute the dimension value?
+    if( osText.size() == 0 )
+    {
+        FormatDimension( osText, POINT_DIST( oArrow1.x, oArrow1.y, 
+                                             dfArrowX2, dfArrowY2 ) );
+    }
+
+    CPLString osStyle;
+    char szBuffer[64];
+    char* pszComma;
+
+    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",p:5",osText.c_str());
+
+    if( dfAngle != 0.0 )
+    {
+        snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfAngle);
+        pszComma = strchr(szBuffer, ',');
+        if (pszComma)
+            *pszComma = '.';
+        osStyle += CPLString().Printf(",a:%s", szBuffer);
+    }
+
+    if( dfHeight != 0.0 )
+    {
+        snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfHeight);
+        pszComma = strchr(szBuffer, ',');
+        if (pszComma)
+            *pszComma = '.';
+        osStyle += CPLString().Printf(",s:%sg", szBuffer);
+    }
+
+    const unsigned char *pabyDWGColors = ACGetColorTable();
+
+    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x", 
+              pabyDWGColors[nColor*3+0],
+              pabyDWGColors[nColor*3+1],
+              pabyDWGColors[nColor*3+2] );
+    osStyle += szBuffer;
+
+    if( bHidden )
+        osStyle += "00"; 
+
+    osStyle += ")";
+
+    poLabelFeature->SetStyleString( osStyle );
+
+    apoPendingFeatures.push( poLabelFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          FormatDimension()                           */
+/*                                                                      */
+/*      Format a dimension number according to the current files        */
+/*      formatting conventions.                                         */
+/************************************************************************/
+
+void OGRDWGLayer::FormatDimension( CPLString &osText, double dfValue )
+
+{
+    int nPrecision = atoi(poDS->GetVariable("$LUPREC","4"));
+    char szFormat[32];
+    char szBuffer[64];
+
+    // we could do a significantly more precise formatting if we want
+    // to spend the effort.  See QCAD's rs_dimlinear.cpp and related files
+    // for example.  
+
+    sprintf(szFormat, "%%.%df", nPrecision );
+    snprintf(szBuffer, sizeof(szBuffer), szFormat, dfValue);
+    char* pszComma = strchr(szBuffer, ',');
+    if (pszComma)
+        *pszComma = '.';
+    osText = szBuffer;
+}
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
new file mode 100644
index 0000000..c8cbf38
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
@@ -0,0 +1,249 @@
+/******************************************************************************
+ * $Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Implements translation support for HATCH elements as part
+ *           of the OGRDWGLayer class.  
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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_dwg.h"
+#include "cpl_conv.h"
+#include "ogr_api.h"
+
+#include "DbHatch.h"
+
+#include "ogrdxf_polyline_smooth.h"
+
+#include "Ge/GePoint2dArray.h"
+#include "Ge/GeCurve2d.h"
+#include "Ge/GeCircArc2d.h"
+#include "Ge/GeEllipArc2d.h"
+
+CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
+
+#ifndef PI
+#define PI  3.14159265358979323846
+#endif 
+
+static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
+                                      OGRGeometryCollection *poGC );
+
+/************************************************************************/
+/*                           TranslateHATCH()                           */
+/*                                                                      */
+/*      We mostly just try to convert hatch objects as polygons or      */
+/*      multipolygons representing the hatched area.  It is hard to     */
+/*      preserve the actual details of the hatching.                    */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateHATCH( OdDbEntityPtr poEntity )
+
+{
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    OdDbHatchPtr poHatch = OdDbHatch::cast( poEntity );
+    OGRGeometryCollection oGC;
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+    poFeature->SetField( "Text", 
+                         (const char *) poHatch->patternName() );
+
+/* -------------------------------------------------------------------- */
+/*      Collect the loops.                                              */
+/* -------------------------------------------------------------------- */
+    for( int i = 0; i < poHatch->numLoops(); i++ )
+    {
+        DWGCollectBoundaryLoop( poHatch, i, &oGC );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to turn the set of lines into something useful.             */
+/* -------------------------------------------------------------------- */
+    OGRErr eErr;
+
+    OGRGeometryH hFinalGeom = 
+        OGRBuildPolygonFromEdges( (OGRGeometryH) &oGC,
+                                  TRUE, TRUE, 0.0000001, &eErr );
+
+    poFeature->SetGeometryDirectly( (OGRGeometry *) hFinalGeom );
+
+/* -------------------------------------------------------------------- */
+/*      Work out the color for this feature.  For now we just assume    */
+/*      solid fill.  We cannot trivially translate the various sorts    */
+/*      of hatching.                                                    */
+/* -------------------------------------------------------------------- */
+    CPLString osLayer = poFeature->GetFieldAsString("Layer");
+
+    int nColor = 256;
+
+    if( oStyleProperties.count("Color") > 0 )
+        nColor = atoi(oStyleProperties["Color"]);
+
+    // Use layer color? 
+    if( nColor < 1 || nColor > 255 )
+    {
+        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
+        if( pszValue != NULL )
+            nColor = atoi(pszValue);
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      Setup the style string.                                         */
+/* -------------------------------------------------------------------- */
+    if( nColor >= 1 && nColor <= 255 )
+    {
+        CPLString osStyle;
+        const unsigned char *pabyDWGColors = ACGetColorTable();
+        
+        osStyle.Printf( "BRUSH(fc:#%02x%02x%02x)",
+                        pabyDWGColors[nColor*3+0],
+                        pabyDWGColors[nColor*3+1],
+                        pabyDWGColors[nColor*3+2] );
+        
+        poFeature->SetStyleString( osStyle );
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                        CollectBoundaryLoop()                         */
+/************************************************************************/
+
+static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
+                                      OGRGeometryCollection *poGC )
+
+{
+    int i;
+
+/* -------------------------------------------------------------------- */
+/*      Handle simple polyline loops.                                   */
+/* -------------------------------------------------------------------- */
+    if( poHatch->loopTypeAt( iLoop ) & OdDbHatch::kPolyline )
+    {
+        DXFSmoothPolyline   oSmoothPolyline;
+        OdGePoint2dArray vertices;
+        OdGeDoubleArray bulges;
+
+        poHatch->getLoopAt (iLoop, vertices, bulges);
+
+        for (i = 0; i < (int) vertices.size(); i++)
+        {
+            if( i >= (int) bulges.size() )
+                oSmoothPolyline.AddPoint( vertices[i].x, vertices[i].y, 0.0, 
+                                          0.0 );
+            else
+                oSmoothPolyline.AddPoint( vertices[i].x, vertices[i].y, 0.0, 
+                                          bulges[i] );
+        }
+
+        oSmoothPolyline.Close();
+
+        OGRLineString *poLS = (OGRLineString *) oSmoothPolyline.Tesselate();
+        poGC->addGeometryDirectly( poLS );
+
+        return OGRERR_NONE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle an edges array.                                          */
+/* -------------------------------------------------------------------- */
+    EdgeArray oEdges;
+    poHatch->getLoopAt( iLoop, oEdges );
+
+    for( i = 0; i < (int) oEdges.size(); i++ )
+    {
+        OdGeCurve2d* poEdge = oEdges[i];
+
+        if( poEdge->type() == OdGe::kLineSeg2d )
+        {
+            OGRLineString *poLS = new OGRLineString();
+            OdGePoint2d oStart = poEdge->evalPoint(0.0);
+            OdGePoint2d oEnd = poEdge->evalPoint(1.0);
+
+            poLS->addPoint( oStart.x, oStart.y );
+            poLS->addPoint( oEnd.x, oEnd.y );
+            poGC->addGeometryDirectly( poLS );
+        }
+        else if( poEdge->type() == OdGe::kCircArc2d )
+        {
+            OdGeCircArc2d* poCircArc = (OdGeCircArc2d*) poEdge;
+            OdGePoint2d oCenter = poCircArc->center();
+            double dfStartAngle = poCircArc->endAng() * 180 / PI;
+            double dfEndAngle = poCircArc->startAng() * 180 / PI;
+            
+            if( !poCircArc->isClockWise() )
+            {
+                dfStartAngle *= -1;
+                dfEndAngle *= -1;
+//                double dfTemp = dfStartAngle;
+//                dfStartAngle = dfEndAngle;
+//                dfEndAngle = dfTemp;
+            }
+
+            if( dfStartAngle > dfEndAngle )
+                dfEndAngle += 360.0;
+
+            OGRLineString *poLS = (OGRLineString *) 
+                OGRGeometryFactory::approximateArcAngles( 
+                    oCenter.x, oCenter.y, 0.0,
+                    poCircArc->radius(), poCircArc->radius(), 0.0,
+                    dfStartAngle, dfEndAngle, 0.0 );
+
+            poGC->addGeometryDirectly( poLS );
+        }
+        else if( poEdge->type() == OdGe::kEllipArc2d )
+        {
+            OdGeEllipArc2d* poArc = (OdGeEllipArc2d*) poEdge;
+            OdGePoint2d oCenter = poArc->center();
+            double dfRatio = poArc->minorRadius() / poArc->majorRadius();
+            OdGeVector2d oMajorAxis = poArc->majorAxis();
+            double dfRotation;
+            double dfStartAng, dfEndAng;
+
+            dfRotation = -1 * atan2( oMajorAxis.y, oMajorAxis.x ) * 180 / PI;
+
+            dfStartAng = -1 * poArc->endAng()*180/PI;
+            dfEndAng = -1 * poArc->startAng()*180/PI;
+
+            OGRLineString *poLS = (OGRLineString *) 
+                OGRGeometryFactory::approximateArcAngles( 
+                    oCenter.x, oCenter.y, 0.0,
+                    poArc->majorRadius(), poArc->minorRadius(), dfRotation,
+                    OGRDWGLayer::AngleCorrect(dfStartAng,dfRatio),
+                    OGRDWGLayer::AngleCorrect(dfEndAng,dfRatio),
+                    0.0 );
+            poGC->addGeometryDirectly( poLS );
+        }
+        else
+            CPLDebug( "DWG", "Unsupported edge type (%d) in hatch loop.",
+                      (int) poEdge->type() );
+
+        //case OdGe::kNurbCurve2d : dumpNurbCurveEdge(indent + 1, pEdge);    
+    }
+
+    return OGRERR_NONE;
+}
+
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
new file mode 100644
index 0000000..8911732
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
@@ -0,0 +1,189 @@
+/******************************************************************************
+ * $Id: ogrdwglayer.cpp 19643 2010-05-08 21:56:18Z rouault $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Implements OGRDWGBlocksLayer class.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, 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_dwg.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrdwglayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
+
+/************************************************************************/
+/*                         OGRDWGBlocksLayer()                          */
+/************************************************************************/
+
+OGRDWGBlocksLayer::OGRDWGBlocksLayer( OGRDWGDataSource *poDS )
+
+{
+    this->poDS = poDS;
+
+    ResetReading();
+
+    poFeatureDefn = new OGRFeatureDefn( "blocks" );
+    poFeatureDefn->Reference();
+
+    poDS->AddStandardFields( poFeatureDefn );
+}
+
+/************************************************************************/
+/*                         ~OGRDWGBlocksLayer()                         */
+/************************************************************************/
+
+OGRDWGBlocksLayer::~OGRDWGBlocksLayer()
+
+{
+    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    {
+        CPLDebug( "DWG", "%d features read on layer '%s'.",
+                  (int) m_nFeaturesRead, 
+                  poFeatureDefn->GetName() );
+    }
+
+    if( poFeatureDefn )
+        poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRDWGBlocksLayer::ResetReading()
+
+{
+    iNextFID = 0;
+    iNextSubFeature = 0;
+    oIt = poDS->GetBlockMap().begin();
+}
+
+/************************************************************************/
+/*                      GetNextUnfilteredFeature()                      */
+/************************************************************************/
+
+OGRFeature *OGRDWGBlocksLayer::GetNextUnfilteredFeature()
+
+{
+    OGRFeature *poFeature = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Are we out of features?                                         */
+/* -------------------------------------------------------------------- */
+    if( oIt == poDS->GetBlockMap().end() )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Are we done reading the current blocks features?                */
+/* -------------------------------------------------------------------- */
+    DWGBlockDefinition *psBlock = &(oIt->second);
+    unsigned int nSubFeatureCount = psBlock->apoFeatures.size();
+
+    if( psBlock->poGeometry != NULL )
+        nSubFeatureCount++;
+
+    if( iNextSubFeature >= nSubFeatureCount )
+    {
+        oIt++;
+
+        iNextSubFeature = 0;
+
+        if( oIt == poDS->GetBlockMap().end() )
+            return NULL;
+
+        psBlock = &(oIt->second);
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      Is this a geometry based block?                                 */
+/* -------------------------------------------------------------------- */
+    if( psBlock->poGeometry != NULL
+        && iNextSubFeature == psBlock->apoFeatures.size() )
+    {
+        poFeature = new OGRFeature( poFeatureDefn );
+        poFeature->SetGeometry( psBlock->poGeometry );
+        iNextSubFeature++;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Otherwise duplicate the next sub-feature.                       */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        poFeature = new OGRFeature( poFeatureDefn );
+        poFeature->SetFrom( psBlock->apoFeatures[iNextSubFeature] );
+        iNextSubFeature++;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set FID and block name.                                         */
+/* -------------------------------------------------------------------- */
+    poFeature->SetFID( iNextFID++ );
+
+    poFeature->SetField( "BlockName", oIt->first.c_str() );
+
+    m_nFeaturesRead++;
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRDWGBlocksLayer::GetNextFeature()
+
+{
+    while( TRUE )
+    {
+        OGRFeature *poFeature = GetNextUnfilteredFeature();
+
+        if( poFeature == NULL )
+            return NULL;
+
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature ) ) )
+        {
+            return poFeature;
+        }
+
+        delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDWGBlocksLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
new file mode 100644
index 0000000..5ef139e
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
@@ -0,0 +1,369 @@
+/******************************************************************************
+ * $Id: ogrdxfdatasource.cpp 22009 2011-03-22 20:01:34Z warmerdam $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Implements OGRDWGDataSource class
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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_dwg.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+#include "DbSymbolTable.h"
+#include "DbLayerTable.h"
+#include "DbLayerTableRecord.h"
+#include "DbLinetypeTable.h"
+#include "DbLinetypeTableRecord.h"
+
+CPL_CVSID("$Id: ogrdxfdatasource.cpp 22009 2011-03-22 20:01:34Z warmerdam $");
+
+/************************************************************************/
+/*                          OGRDWGDataSource()                          */
+/************************************************************************/
+
+OGRDWGDataSource::OGRDWGDataSource()
+
+{
+    poDb = NULL;
+}
+
+/************************************************************************/
+/*                         ~OGRDWGDataSource()                          */
+/************************************************************************/
+
+OGRDWGDataSource::~OGRDWGDataSource()
+
+{
+/* -------------------------------------------------------------------- */
+/*      Destroy layers.                                                 */
+/* -------------------------------------------------------------------- */
+    while( apoLayers.size() > 0 )
+    {
+        delete apoLayers.back();
+        apoLayers.pop_back();
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDWGDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+
+OGRLayer *OGRDWGDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= (int) apoLayers.size() )
+        return NULL;
+    else
+        return apoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRDWGDataSource::Open( OGRDWGServices *poServices,
+                            const char * pszFilename, int bHeaderOnly )
+
+{
+    if( !EQUAL(CPLGetExtension(pszFilename),"dwg") )
+        return FALSE;
+
+    this->poServices = poServices;
+
+    osEncoding = CPL_ENC_ISO8859_1;
+
+    osName = pszFilename;
+
+    bInlineBlocks = CSLTestBoolean(
+        CPLGetConfigOption( "DWG_INLINE_BLOCKS", "TRUE" ) );
+
+/* -------------------------------------------------------------------- */
+/*      Open the file.                                                  */
+/* -------------------------------------------------------------------- */
+    try 
+    {
+        OdString f(pszFilename);
+        poDb = poServices->readFile(f.c_str(), true, false, Oda::kShareDenyNo); 
+    }
+    catch( OdError& e )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "%s",
+                  (const char *) poServices->getErrorDescription(e.code()) );
+    }
+    catch( ... )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "DWG readFile(%s) failed with generic exception.", 
+                  pszFilename );
+    }
+
+    if( poDb.isNull() )
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Process the header, picking up a few useful pieces of           */
+/*      information.                                                    */
+/* -------------------------------------------------------------------- */
+    ReadHeaderSection();
+    ReadLineTypeDefinitions();
+    ReadLayerDefinitions();
+
+/* -------------------------------------------------------------------- */
+/*      Create a blocks layer if we are not in inlining mode.           */
+/* -------------------------------------------------------------------- */
+    if( !bInlineBlocks )
+        apoLayers.push_back( new OGRDWGBlocksLayer( this ) );
+
+/* -------------------------------------------------------------------- */
+/*      Create out layer object - we will need it when interpreting     */
+/*      blocks.                                                         */
+/* -------------------------------------------------------------------- */
+    apoLayers.push_back( new OGRDWGLayer( this ) );
+
+    ReadBlocksSection();
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        ReadLayerDefinitions()                        */
+/************************************************************************/
+
+void OGRDWGDataSource::ReadLayerDefinitions()
+
+{
+    OdDbLayerTablePtr poLT = poDb->getLayerTableId().safeOpenObject();
+    OdDbSymbolTableIteratorPtr poIter = poLT->newIterator();
+
+    for (poIter->start(); !poIter->done(); poIter->step())
+    {
+        CPLString osValue;
+        OdDbLayerTableRecordPtr poLD = poIter->getRecordId().safeOpenObject();
+        std::map<CPLString,CPLString> oLayerProperties;
+
+        CPLString osLayerName = ACTextUnescape(poLD->getName(),GetEncoding());
+        
+        oLayerProperties["Exists"] = "1";
+        
+        OdDbLinetypeTableRecordPtr poLT = poLD->linetypeObjectId().safeOpenObject();
+        oLayerProperties["Linetype"] = 
+            ACTextUnescape(poLT->getName(),GetEncoding());
+
+        osValue.Printf( "%d", poLD->colorIndex() );
+        oLayerProperties["Color"] = osValue;
+            
+        osValue.Printf( "%d", (int) poLD->lineWeight() );
+        oLayerProperties["LineWeight"] = osValue;
+
+        if( poLD->isFrozen() || poLD->isHidden() || poLD->isOff() )
+            oLayerProperties["Hidden"] = "1";
+        else
+            oLayerProperties["Hidden"] = "0";
+
+        oLayerTable[osLayerName] = oLayerProperties;
+    }
+
+    CPLDebug( "DWG", "Read %d layer definitions.", 
+              (int) oLayerTable.size() );
+}
+
+/************************************************************************/
+/*                        LookupLayerProperty()                         */
+/************************************************************************/
+
+const char *OGRDWGDataSource::LookupLayerProperty( const char *pszLayer,
+                                                   const char *pszProperty )
+
+{
+    if( pszLayer == NULL )
+        return NULL;
+
+    try {
+        return (oLayerTable[pszLayer])[pszProperty];
+    } catch( ... ) {
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                       ReadLineTypeDefinitions()                      */
+/************************************************************************/
+
+void OGRDWGDataSource::ReadLineTypeDefinitions()
+
+{
+    OdDbLinetypeTablePtr poTable = poDb->getLinetypeTableId().safeOpenObject();
+    OdDbSymbolTableIteratorPtr poIter = poTable->newIterator();
+    
+    for (poIter->start(); !poIter->done(); poIter->step())
+    {
+        CPLString osLineTypeName;
+        CPLString osLineTypeDef;
+        OdDbLinetypeTableRecordPtr poLT = poIter->getRecordId().safeOpenObject();
+
+        osLineTypeName = ACTextUnescape(poLT->getName(),GetEncoding());
+
+        if (poLT->numDashes()) 
+        {
+            for (int i=0; i < poLT->numDashes(); i++) 
+            {
+                if( i > 0 )
+                    osLineTypeDef += " ";
+
+                CPLString osValue;
+                osValue.Printf( "%g", fabs(poLT->dashLengthAt(i)) );
+                osLineTypeDef += osValue;
+
+                osLineTypeDef += "g";
+            }
+
+            oLineTypeTable[osLineTypeName] = osLineTypeDef;
+            CPLDebug( "DWG", "LineType '%s' = '%s'",
+                       osLineTypeName.c_str(), 
+                       osLineTypeDef.c_str() );
+        }
+    }
+}
+
+/************************************************************************/
+/*                           LookupLineType()                           */
+/************************************************************************/
+
+const char *OGRDWGDataSource::LookupLineType( const char *pszName )
+
+{
+    if( oLineTypeTable.count(pszName) > 0 )
+        return oLineTypeTable[pszName];
+    else
+        return NULL;
+}
+
+/************************************************************************/
+/*                         ReadHeaderSection()                          */
+/************************************************************************/
+
+void OGRDWGDataSource::ReadHeaderSection()
+
+{
+    // using: DWGCODEPAGE, DIMTXT, LUPREC
+
+    CPLString osValue;
+
+    osValue.Printf( "%d", poDb->getLUPREC() );
+    oHeaderVariables["$LUPREC"] = osValue;
+
+    osValue.Printf( "%g", poDb->dimtxt() );
+    oHeaderVariables["$DIMTXT"] = osValue;
+
+    CPLDebug( "DWG", "Read %d header variables.", 
+              (int) oHeaderVariables.size() );
+
+/* -------------------------------------------------------------------- */
+/*      Decide on what CPLRecode() name to use for the files            */
+/*      encoding or allow the encoding to be overridden.                */
+/* -------------------------------------------------------------------- */
+    CPLString osCodepage = GetVariable( "$DWGCODEPAGE", "ANSI_1252" );
+
+    // not strictly accurate but works even without iconv.
+    if( osCodepage == "ANSI_1252" )
+        osEncoding = CPL_ENC_ISO8859_1; 
+    else if( EQUALN(osCodepage,"ANSI_",5) )
+    {
+        osEncoding = "CP";
+        osEncoding += osCodepage + 5;
+    }
+    else
+    {
+        // fallback to the default 
+        osEncoding = CPL_ENC_ISO8859_1;
+    }
+                                       
+    if( CPLGetConfigOption( "DWG_ENCODING", NULL ) != NULL )
+        osEncoding = CPLGetConfigOption( "DWG_ENCODING", NULL );
+
+    if( osEncoding != CPL_ENC_ISO8859_1 )
+        CPLDebug( "DWG", "Treating DWG as encoding '%s', $DWGCODEPAGE='%s'", 
+                  osEncoding.c_str(), osCodepage.c_str() );
+}
+
+/************************************************************************/
+/*                            GetVariable()                             */
+/*                                                                      */
+/*      Fetch a variable that came from the HEADER section.             */
+/************************************************************************/
+
+const char *OGRDWGDataSource::GetVariable( const char *pszName, 
+                                           const char *pszDefault )
+
+{
+    if( oHeaderVariables.count(pszName) == 0 )
+        return pszDefault;
+    else 
+        return oHeaderVariables[pszName];
+}
+
+/************************************************************************/
+/*                         AddStandardFields()                          */
+/************************************************************************/
+
+void OGRDWGDataSource::AddStandardFields( OGRFeatureDefn *poFeatureDefn )
+
+{
+    OGRFieldDefn  oLayerField( "Layer", OFTString );
+    poFeatureDefn->AddFieldDefn( &oLayerField );
+
+    OGRFieldDefn  oClassField( "SubClasses", OFTString );
+    poFeatureDefn->AddFieldDefn( &oClassField );
+
+    OGRFieldDefn  oExtendedField( "ExtendedEntity", OFTString );
+    poFeatureDefn->AddFieldDefn( &oExtendedField );
+
+    OGRFieldDefn  oLinetypeField( "Linetype", OFTString );
+    poFeatureDefn->AddFieldDefn( &oLinetypeField );
+
+    OGRFieldDefn  oEntityHandleField( "EntityHandle", OFTString );
+    poFeatureDefn->AddFieldDefn( &oEntityHandleField );
+
+    OGRFieldDefn  oTextField( "Text", OFTString );
+    poFeatureDefn->AddFieldDefn( &oTextField );
+
+    if( !bInlineBlocks )
+    {
+        OGRFieldDefn  oTextField( "BlockName", OFTString );
+        poFeatureDefn->AddFieldDefn( &oTextField );
+    }
+}
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
new file mode 100644
index 0000000..ab179dd
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
@@ -0,0 +1,150 @@
+/******************************************************************************
+ * $Id: ogrdxfdriver.cpp 18535 2010-01-12 01:40:32Z warmerdam $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Implements OGRDWGDriver.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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_dwg.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrdxfdriver.cpp 18535 2010-01-12 01:40:32Z warmerdam $");
+
+CPL_C_START
+void CPL_DLL RegisterOGRDWG();
+CPL_C_END
+
+/************************************************************************/
+/*                            OGRDWGDriver()                            */
+/************************************************************************/
+
+OGRDWGDriver::OGRDWGDriver()
+
+{
+    bInitialized = FALSE;
+}
+
+/************************************************************************/
+/*                          ~OGRDWGDriver()                          */
+/************************************************************************/
+
+OGRDWGDriver::~OGRDWGDriver()
+
+{
+    if( bInitialized )
+    {
+        bInitialized = FALSE;
+        odUninitialize();
+    }
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+void OGRDWGDriver::Initialize()
+
+{
+    if( bInitialized )
+        return;
+
+    bInitialized = TRUE;
+    
+    OdGeContext::gErrorFunc = ErrorHandler;
+
+    odInitialize(&oServices);
+    oServices.disableOutput( true );
+
+    /********************************************************************/
+    /* Find the data file and and initialize the character mapper       */
+    /********************************************************************/
+    OdString iniFile = oServices.findFile(OD_T("adinit.dat"));
+    if (!iniFile.isEmpty())
+      OdCharMapper::initialize(iniFile);
+
+}
+
+/************************************************************************/
+/*                            ErrorHandler()                            */
+/************************************************************************/
+
+void OGRDWGDriver::ErrorHandler( OdResult oResult )
+
+{
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "GeError:%s", 
+              (const char *) OdError(oResult).description().c_str() );
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRDWGDriver::GetName()
+
+{
+    return "DWG";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRDWGDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    Initialize();
+    
+    OGRDWGDataSource   *poDS = new OGRDWGDataSource();
+
+    if( !poDS->Open( &oServices, pszFilename ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDWGDriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRDWG()                           */
+/************************************************************************/
+
+void RegisterOGRDWG()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRDWGDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
new file mode 100644
index 0000000..452659f
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
@@ -0,0 +1,1422 @@
+/******************************************************************************
+ * $Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $
+ *
+ * Project:  DWG Translator
+ * Purpose:  Implements OGRDWGLayer class.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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_dwg.h"
+#include "cpl_conv.h"
+
+#include "ogrdxf_polyline_smooth.h"
+
+#include "DbPolyline.h"
+#include "Db2dPolyline.h"
+#include "DbLine.h"
+#include "DbPoint.h"
+#include "DbEllipse.h"
+#include "DbArc.h"
+#include "DbMText.h"
+#include "DbText.h"
+#include "DbCircle.h"
+#include "DbSpline.h"
+#include "DbBlockReference.h"
+#include "DbAttribute.h"
+#include "DbFiler.h"
+#include "Ge/GeScale3d.h"
+
+CPL_CVSID("$Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $");
+
+#ifndef PI
+#define PI  3.14159265358979323846
+#endif 
+
+/************************************************************************/
+/*                            OGRDWGLayer()                             */
+/************************************************************************/
+
+OGRDWGLayer::OGRDWGLayer( OGRDWGDataSource *poDS )
+
+{
+    this->poDS = poDS;
+
+    iNextFID = 0;
+
+    poFeatureDefn = new OGRFeatureDefn( "entities" );
+    poFeatureDefn->Reference();
+
+    poDS->AddStandardFields( poFeatureDefn );
+
+    if( !poDS->InlineBlocks() )
+    {
+        OGRFieldDefn  oScaleField( "BlockScale", OFTRealList );
+        poFeatureDefn->AddFieldDefn( &oScaleField );
+
+        OGRFieldDefn  oBlockAngleField( "BlockAngle", OFTReal );
+        poFeatureDefn->AddFieldDefn( &oBlockAngleField );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the *Paper_Space block, which seems to contain all the     */
+/*      regular entities.                                               */
+/* -------------------------------------------------------------------- */
+    OdDbBlockTablePtr pTable = poDS->GetDB()->getBlockTableId().safeOpenObject();
+    OdDbSymbolTableIteratorPtr pBlkIter = pTable->newIterator();
+    
+    for (pBlkIter->start(); ! pBlkIter->done(); pBlkIter->step())
+    {
+        poBlock = pBlkIter->getRecordId().safeOpenObject();
+
+        if( EQUAL(poBlock->getName(),"*Model_Space") )
+            break;
+        else
+            poBlock = NULL;
+    }
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                           ~OGRDWGLayer()                           */
+/************************************************************************/
+
+OGRDWGLayer::~OGRDWGLayer()
+
+{
+    ClearPendingFeatures();
+    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    {
+        CPLDebug( "DWG", "%d features read on layer '%s'.",
+                  (int) m_nFeaturesRead, 
+                  poFeatureDefn->GetName() );
+    }
+
+    if( poFeatureDefn )
+        poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            TextUnescape()                            */
+/************************************************************************/
+
+CPLString OGRDWGLayer::TextUnescape( OdString oString )
+
+{ 
+    return ACTextUnescape( (const char *) oString, poDS->GetEncoding() );
+}
+
+/************************************************************************/
+/*                           SetBlockTable()                            */
+/*                                                                      */
+/*      Set what block table to read features from.  This layer         */
+/*      object is used to read blocks features as well as generic       */
+/*      entities.                                                       */
+/************************************************************************/
+
+void OGRDWGLayer::SetBlockTable( OdDbBlockTableRecordPtr poNewBlock )
+
+{
+    poBlock = poNewBlock;
+
+    ResetReading();
+}
+
+
+/************************************************************************/
+/*                        ClearPendingFeatures()                        */
+/************************************************************************/
+
+void OGRDWGLayer::ClearPendingFeatures()
+
+{
+    while( !apoPendingFeatures.empty() )
+    {
+        delete apoPendingFeatures.front();
+        apoPendingFeatures.pop();
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRDWGLayer::ResetReading()
+
+{
+    iNextFID = 0;
+    ClearPendingFeatures();
+
+    if( !poBlock.isNull() )
+        poEntIter = poBlock->newIterator();
+}
+
+/************************************************************************/
+/*                     TranslateGenericProperties()                     */
+/*                                                                      */
+/*      Try and convert entity properties handled similarly for most    */
+/*      or all entity types                                             */
+/************************************************************************/
+
+void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature, 
+                                              OdDbEntityPtr poEntity )
+
+{
+    poFeature->SetField( "Layer", TextUnescape(poEntity->layer()) );
+    poFeature->SetField( "Linetype", TextUnescape(poEntity->layer()) );
+
+    CPLString osValue;
+    osValue.Printf( "%d", (int) poEntity->lineWeight() );
+    oStyleProperties["LineWeight"] = osValue;
+
+    OdDbHandle oHandle = poEntity->getDbHandle();
+    poFeature->SetField( "EntityHandle", (const char *) oHandle.ascii() );
+
+    
+    if( poEntity->colorIndex() != 256 )
+    {
+        osValue.Printf( "%d", poEntity->colorIndex() );
+        oStyleProperties["Color"] = osValue.c_str();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect the subclasses.                                         */
+/* -------------------------------------------------------------------- */
+    CPLString osSubClasses;
+    OdRxClass *poClass = poEntity->isA();
+
+    while( poClass != NULL )
+    {
+        if( osSubClasses.size() > 0 )
+            osSubClasses = ":" + osSubClasses;
+        
+        osSubClasses = ((const char *) poClass->name()) + osSubClasses;
+        if( EQUAL(poClass->name(),"AcDbEntity") )
+            break;
+
+        poClass = poClass->myParent();
+    }
+    
+    poFeature->SetField( "SubClasses", osSubClasses.c_str() );
+
+/* -------------------------------------------------------------------- */
+/*      Collect Xdata.                                                  */
+/* -------------------------------------------------------------------- */
+    OdResBufPtr poResBufBase = poEntity->xData();
+    OdResBuf *poResBuf = poResBufBase;
+    CPLString osFullXData;
+
+    for ( ; poResBuf != NULL; poResBuf = poResBuf->next() )
+    {
+        CPLString osXDataItem;
+    
+        switch (OdDxfCode::_getType(poResBuf->restype()))
+        {
+          case OdDxfCode::Name:
+          case OdDxfCode::String:
+          case OdDxfCode::LayerName:
+            osXDataItem = (const char *) poResBuf->getString();
+            break;
+
+          case OdDxfCode::Bool:
+            if( poResBuf->getBool() )
+                osXDataItem = "true";
+            else
+                osXDataItem = "false";
+            break;
+            
+          case OdDxfCode::Integer8:
+            osXDataItem.Printf( "%d", (int) poResBuf->getInt8() );
+            break;
+            
+          case OdDxfCode::Integer16:
+            osXDataItem.Printf( "%d", (int) poResBuf->getInt16() );
+            break;
+            
+          case OdDxfCode::Integer32:
+            osXDataItem.Printf( "%d", (int) poResBuf->getInt32() );
+            break;
+            
+          case OdDxfCode::Double:
+          case OdDxfCode::Angle:
+            osXDataItem.Printf( "%g", poResBuf->getDouble() );
+            break;
+            
+          case OdDxfCode::Point:
+          {
+              OdGePoint3d oPoint = poResBuf->getPoint3d();
+              osXDataItem.Printf( "(%g,%g,%g)", oPoint.x, oPoint.y, oPoint.z );
+          }
+          break;
+          
+          case OdDxfCode::BinaryChunk:
+          {
+              OdBinaryData oBinData = poResBuf->getBinaryChunk();
+              char *pszAsHex = CPLBinaryToHex( oBinData.size(),
+                                               (GByte*) oBinData.asArrayPtr() );
+              osXDataItem = pszAsHex;
+              CPLFree( pszAsHex );
+          }
+          break;
+            
+          case OdDxfCode::ObjectId:
+          case OdDxfCode::SoftPointerId:
+          case OdDxfCode::HardPointerId:
+          case OdDxfCode::SoftOwnershipId:
+          case OdDxfCode::HardOwnershipId:
+          case OdDxfCode::Handle:
+            osXDataItem = (const char *) poResBuf->getHandle().ascii();
+            break;
+            
+          default:
+            break;
+        }
+
+        if( osFullXData.size() > 0 )
+            osFullXData += " ";
+        osFullXData += (const char *) osXDataItem;
+    }
+    
+    poFeature->SetField( "ExtendedEntity", osFullXData );
+
+
+#ifdef notdef
+      // OCS vector.
+      case 210:
+        oStyleProperties["210_N.dX"] = pszValue;
+        break;
+        
+      case 220:
+        oStyleProperties["220_N.dY"] = pszValue;
+        break;
+        
+      case 230:
+        oStyleProperties["230_N.dZ"] = pszValue;
+        break;
+
+
+      default:
+        break;
+    }
+#endif
+}
+
+/************************************************************************/
+/*                          PrepareLineStyle()                          */
+/************************************************************************/
+
+void OGRDWGLayer::PrepareLineStyle( OGRFeature *poFeature )
+
+{
+    CPLString osLayer = poFeature->GetFieldAsString("Layer");
+
+/* -------------------------------------------------------------------- */
+/*      Is the layer disabled/hidden/frozen/off?                        */
+/* -------------------------------------------------------------------- */
+    int bHidden = 
+        EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
+
+/* -------------------------------------------------------------------- */
+/*      Work out the color for this feature.                            */
+/* -------------------------------------------------------------------- */
+    int nColor = 256;
+
+    if( oStyleProperties.count("Color") > 0 )
+        nColor = atoi(oStyleProperties["Color"]);
+
+    // Use layer color? 
+    if( nColor < 1 || nColor > 255 )
+    {
+        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
+        if( pszValue != NULL )
+            nColor = atoi(pszValue);
+    }
+        
+    if( nColor < 1 || nColor > 255 )
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Get line weight if available.                                   */
+/* -------------------------------------------------------------------- */
+    double dfWeight = 0.0;
+
+    if( oStyleProperties.count("LineWeight") > 0 )
+    {
+        CPLString osWeight = oStyleProperties["LineWeight"];
+
+        if( osWeight == "-1" )
+            osWeight = poDS->LookupLayerProperty(osLayer,"LineWeight");
+
+        dfWeight = CPLAtof(osWeight) / 100.0;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a dash/dot line style?                               */
+/* -------------------------------------------------------------------- */
+    const char *pszPattern = poDS->LookupLineType(
+        poFeature->GetFieldAsString("Linetype") );
+
+/* -------------------------------------------------------------------- */
+/*      Format the style string.                                        */
+/* -------------------------------------------------------------------- */
+    CPLString osStyle;
+    const unsigned char *pabyDWGColors = ACGetColorTable();
+
+    osStyle.Printf( "PEN(c:#%02x%02x%02x", 
+                    pabyDWGColors[nColor*3+0],
+                    pabyDWGColors[nColor*3+1],
+                    pabyDWGColors[nColor*3+2] );
+
+    if( bHidden )
+        osStyle += "00"; 
+
+    if( dfWeight > 0.0 )
+    {
+        char szBuffer[64];
+        snprintf(szBuffer, sizeof(szBuffer), "%.2g", dfWeight);
+        char* pszComma = strchr(szBuffer, ',');
+        if (pszComma)
+            *pszComma = '.';
+        osStyle += CPLString().Printf( ",w:%sg", szBuffer );
+    }
+
+    if( pszPattern )
+    {
+        osStyle += ",p:\"";
+        osStyle += pszPattern;
+        osStyle += "\"";
+    }
+
+    osStyle += ")";
+    
+    poFeature->SetStyleString( osStyle );
+}
+
+/************************************************************************/
+/*                           TranslateMTEXT()                           */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateMTEXT( OdDbEntityPtr poEntity )
+
+{
+    OdDbMTextPtr poMTE = OdDbMText::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Set the location.                                               */
+/* -------------------------------------------------------------------- */
+    OdGePoint3d oLocation = poMTE->location();
+
+    poFeature->SetGeometryDirectly( 
+        new OGRPoint( oLocation.x, oLocation.y, oLocation.z ) );
+
+/* -------------------------------------------------------------------- */
+/*      Apply text after stripping off any extra terminating newline.   */
+/* -------------------------------------------------------------------- */
+    CPLString osText = TextUnescape( poMTE->contents() );
+
+    if( osText != "" && osText[osText.size()-1] == '\n' )
+        osText.resize( osText.size() - 1 );
+
+    poFeature->SetField( "Text", osText );
+
+/* -------------------------------------------------------------------- */
+/*      We need to escape double quotes with backslashes before they    */
+/*      can be inserted in the style string.                            */
+/* -------------------------------------------------------------------- */
+    if( strchr( osText, '"') != NULL )
+    {
+        CPLString osEscaped;
+        size_t iC;
+
+        for( iC = 0; iC < osText.size(); iC++ )
+        {
+            if( osText[iC] == '"' )
+                osEscaped += "\\\"";
+            else
+                osEscaped += osText[iC];
+        }
+        osText = osEscaped;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Work out the color for this feature.                            */
+/* -------------------------------------------------------------------- */
+    int nColor = 256;
+
+    if( oStyleProperties.count("Color") > 0 )
+        nColor = atoi(oStyleProperties["Color"]);
+
+    // Use layer color? 
+    if( nColor < 1 || nColor > 255 )
+    {
+        CPLString osLayer = poFeature->GetFieldAsString("Layer");
+        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
+        if( pszValue != NULL )
+            nColor = atoi(pszValue);
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      Prepare style string.                                           */
+/* -------------------------------------------------------------------- */
+    double dfAngle = poMTE->rotation() * 180 / PI;
+    double dfHeight = poMTE->textHeight();
+    int nAttachmentPoint = (int) poMTE->attachment();
+
+    CPLString osStyle;
+    char szBuffer[64];
+    char* pszComma;
+
+    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
+
+    if( dfAngle != 0.0 )
+    {
+        snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfAngle);
+        pszComma = strchr(szBuffer, ',');
+        if (pszComma)
+            *pszComma = '.';
+        osStyle += CPLString().Printf(",a:%s", szBuffer);
+    }
+
+    if( dfHeight != 0.0 )
+    {
+        snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfHeight);
+        pszComma = strchr(szBuffer, ',');
+        if (pszComma)
+            *pszComma = '.';
+        osStyle += CPLString().Printf(",s:%sg", szBuffer);
+    }
+
+    if( nAttachmentPoint >= 0 && nAttachmentPoint <= 9 )
+    {
+        const static int anAttachmentMap[10] = 
+            { -1, 7, 8, 9, 4, 5, 6, 1, 2, 3 };
+        
+        osStyle += 
+            CPLString().Printf(",p:%d", anAttachmentMap[nAttachmentPoint]);
+    }
+
+    if( nColor > 0 && nColor < 256 )
+    {
+        const unsigned char *pabyDWGColors = ACGetColorTable();
+        osStyle += 
+            CPLString().Printf( ",c:#%02x%02x%02x", 
+                                pabyDWGColors[nColor*3+0],
+                                pabyDWGColors[nColor*3+1],
+                                pabyDWGColors[nColor*3+2] );
+    }
+
+    osStyle += ")";
+
+    poFeature->SetStyleString( osStyle );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           TranslateTEXT()                            */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateTEXT( OdDbEntityPtr poEntity )
+
+{
+    OdDbTextPtr poText = OdDbText::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Set the location.                                               */
+/* -------------------------------------------------------------------- */
+    OdGePoint3d oLocation = poText->position();
+
+    poFeature->SetGeometryDirectly( 
+        new OGRPoint( oLocation.x, oLocation.y, oLocation.z ) );
+
+/* -------------------------------------------------------------------- */
+/*      Apply text after stripping off any extra terminating newline.   */
+/* -------------------------------------------------------------------- */
+    CPLString osText = TextUnescape( poText->textString() );
+
+    if( osText != "" && osText[osText.size()-1] == '\n' )
+        osText.resize( osText.size() - 1 );
+
+    poFeature->SetField( "Text", osText );
+
+/* -------------------------------------------------------------------- */
+/*      We need to escape double quotes with backslashes before they    */
+/*      can be inserted in the style string.                            */
+/* -------------------------------------------------------------------- */
+    if( strchr( osText, '"') != NULL )
+    {
+        CPLString osEscaped;
+        size_t iC;
+
+        for( iC = 0; iC < osText.size(); iC++ )
+        {
+            if( osText[iC] == '"' )
+                osEscaped += "\\\"";
+            else
+                osEscaped += osText[iC];
+        }
+        osText = osEscaped;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Is the layer disabled/hidden/frozen/off?                        */
+/* -------------------------------------------------------------------- */
+    CPLString osLayer = poFeature->GetFieldAsString("Layer");
+
+    int bHidden = 
+        EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
+
+/* -------------------------------------------------------------------- */
+/*      Work out the color for this feature.                            */
+/* -------------------------------------------------------------------- */
+    int nColor = 256;
+
+    if( oStyleProperties.count("Color") > 0 )
+        nColor = atoi(oStyleProperties["Color"]);
+
+    // Use layer color? 
+    if( nColor < 1 || nColor > 255 )
+    {
+        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
+        if( pszValue != NULL )
+            nColor = atoi(pszValue);
+    }
+        
+    if( nColor < 1 || nColor > 255 )
+        nColor = 8;
+
+/* -------------------------------------------------------------------- */
+/*      Prepare style string.                                           */
+/* -------------------------------------------------------------------- */
+    double dfAngle = poText->rotation() * 180 / PI;
+    double dfHeight = poText->height();
+
+    CPLString osStyle;
+    char szBuffer[64];
+    char* pszComma;
+
+    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
+
+    if( dfAngle != 0.0 )
+    {
+        snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfAngle);
+        pszComma = strchr(szBuffer, ',');
+        if (pszComma)
+            *pszComma = '.';
+        osStyle += CPLString().Printf(",a:%s", szBuffer);
+    }
+
+    if( dfHeight != 0.0 )
+    {
+        snprintf(szBuffer, sizeof(szBuffer), "%.3g", dfHeight);
+        pszComma = strchr(szBuffer, ',');
+        if (pszComma)
+            *pszComma = '.';
+        osStyle += CPLString().Printf(",s:%sg", szBuffer);
+    }
+
+    const unsigned char *pabyDWGColors = ACGetColorTable();
+
+    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x", 
+              pabyDWGColors[nColor*3+0],
+              pabyDWGColors[nColor*3+1],
+              pabyDWGColors[nColor*3+2] );
+    osStyle += szBuffer;
+
+    if( bHidden )
+        osStyle += "00"; 
+
+    osStyle += ")";
+
+    poFeature->SetStyleString( osStyle );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           TranslatePOINT()                           */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslatePOINT( OdDbEntityPtr poEntity )
+
+{
+    OdDbPointPtr poPE = OdDbPoint::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+    OdGePoint3d oPoint = poPE->position();
+
+    poFeature->SetGeometryDirectly( new OGRPoint( oPoint.x, oPoint.y, oPoint.z ) );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                        TranslateLWPOLYLINE()                         */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateLWPOLYLINE( OdDbEntityPtr poEntity )
+
+{
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    OdDbPolylinePtr poPL = OdDbPolyline::cast( poEntity );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Collect polyline details.                                       */
+/* -------------------------------------------------------------------- */
+    DXFSmoothPolyline   oSmoothPolyline;
+
+    for (unsigned int i = 0; i < poPL->numVerts(); i++)
+    {
+        OdGePoint3d oPoint;
+        poPL->getPointAt( i, oPoint );
+
+        oSmoothPolyline.AddPoint( oPoint.x, oPoint.y, 0.0, 
+                                 poPL->getBulgeAt( i ) );
+    }
+
+    if(oSmoothPolyline.IsEmpty())
+    {
+        delete poFeature;
+        return NULL;
+    }
+
+    if( poPL->isClosed() )
+        oSmoothPolyline.Close();
+
+    poFeature->SetGeometryDirectly( 
+        oSmoothPolyline.Tesselate() );
+
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                        Translate2DPOLYLINE()                         */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::Translate2DPOLYLINE( OdDbEntityPtr poEntity )
+
+{
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    OdDb2dPolylinePtr poPL = OdDb2dPolyline::cast( poEntity );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Create a polyline geometry from the vertices.                   */
+/* -------------------------------------------------------------------- */
+    OGRLineString *poLS = new OGRLineString();
+    OdDbObjectIteratorPtr poIter = poPL->vertexIterator();
+
+    while( !poIter->done() )
+    {
+        OdDb2dVertexPtr poVertex = poIter->entity();
+        OdGePoint3d oPoint = poPL->vertexPosition( *poVertex );
+        poLS->addPoint( oPoint.x, oPoint.y, oPoint.z );
+        poIter->step();
+    }
+
+    poFeature->SetGeometryDirectly( poLS );
+
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           TranslateLINE()                            */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateLINE( OdDbEntityPtr poEntity )
+
+{
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    OdDbLinePtr poPL = OdDbLine::cast( poEntity );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Create a polyline geometry from the vertices.                   */
+/* -------------------------------------------------------------------- */
+    OGRLineString *poLS = new OGRLineString();
+    OdGePoint3d oPoint;
+
+    poPL->getStartPoint( oPoint );
+    poLS->addPoint( oPoint.x, oPoint.y, oPoint.z );
+
+    poPL->getEndPoint( oPoint );
+    poLS->addPoint( oPoint.x, oPoint.y, oPoint.z );
+
+    poFeature->SetGeometryDirectly( poLS );
+
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          TranslateCIRCLE()                           */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateCIRCLE( OdDbEntityPtr poEntity )
+
+{
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    OdDbCirclePtr poC = OdDbCircle::cast( poEntity );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Get geometry information.                                       */
+/* -------------------------------------------------------------------- */
+    OdGePoint3d oCenter = poC->center();
+    double dfRadius = poC->radius();
+
+/* -------------------------------------------------------------------- */
+/*      Create geometry                                                 */
+/* -------------------------------------------------------------------- */
+    OGRGeometry *poCircle = 
+        OGRGeometryFactory::approximateArcAngles( 
+            oCenter.x, oCenter.y, oCenter.z,
+            dfRadius, dfRadius, 0.0, 0.0, 360.0, 0.0 );
+
+    poFeature->SetGeometryDirectly( poCircle );
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                            AngleCorrect()                            */
+/*                                                                      */
+/*      Convert from a "true" angle on the ellipse as returned by       */
+/*      the DWG API to an angle of rotation on the ellipse as if the    */
+/*      ellipse were actually circular.                                 */
+/************************************************************************/
+
+double OGRDWGLayer::AngleCorrect( double dfTrueAngle, double dfRatio )
+
+{
+    double dfRotAngle;
+    double dfDeltaX, dfDeltaY;
+
+    dfTrueAngle *= (PI / 180); // convert to radians.
+
+    dfDeltaX = cos(dfTrueAngle);
+    dfDeltaY = sin(dfTrueAngle);
+
+    dfRotAngle = atan2( dfDeltaY, dfDeltaX * dfRatio);
+
+    dfRotAngle *= (180 / PI); // convert to degrees.
+
+    if( dfTrueAngle < 0 && dfRotAngle > 0 )
+        dfRotAngle -= 360.0;
+    
+    if( dfTrueAngle > 360 && dfRotAngle < 360 )
+        dfRotAngle += 360.0;
+
+    return dfRotAngle;
+}
+
+/************************************************************************/
+/*                          TranslateELLIPSE()                          */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateELLIPSE( OdDbEntityPtr poEntity )
+
+{
+    OdDbEllipsePtr poEE = OdDbEllipse::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Get some details.                                               */
+/* -------------------------------------------------------------------- */
+    double dfStartAngle, dfEndAngle, dfRatio;
+    OdGePoint3d oCenter;
+    OdGeVector3d oMajorAxis, oUnitNormal;
+
+    // note we reverse start and end angles to account for ogr orientation.
+    poEE->get( oCenter, oUnitNormal, oMajorAxis, 
+               dfRatio, dfEndAngle, dfStartAngle ); 
+
+    dfStartAngle = -1 * dfStartAngle * 180 / PI;
+    dfEndAngle   = -1 * dfEndAngle * 180 / PI;
+
+/* -------------------------------------------------------------------- */
+/*      The DWG SDK expresses the angles as the angle to a real         */
+/*      point on the ellipse while DXF and the OGR "arc angles" API     */
+/*      work in terms of an angle of rotation on the ellipse as if      */
+/*      the ellipse were actually circular.  So we need to "correct"    */
+/*      for the ratio.                                                  */
+/* -------------------------------------------------------------------- */
+    dfStartAngle = AngleCorrect( dfStartAngle, dfRatio );
+    dfEndAngle = AngleCorrect( dfEndAngle, dfRatio );
+    
+    if( dfStartAngle > dfEndAngle )
+        dfEndAngle += 360.0;
+
+/* -------------------------------------------------------------------- */
+/*      Compute primary and secondary axis lengths, and the angle of    */
+/*      rotation for the ellipse.                                       */
+/* -------------------------------------------------------------------- */
+    double dfPrimaryRadius, dfSecondaryRadius;
+    double dfRotation;
+
+    dfPrimaryRadius = sqrt( oMajorAxis.x * oMajorAxis.x
+                            + oMajorAxis.y * oMajorAxis.y
+                            + oMajorAxis.z * oMajorAxis.z );
+
+    dfSecondaryRadius = dfRatio * dfPrimaryRadius;
+
+    dfRotation = -1 * atan2( oMajorAxis.y, oMajorAxis.x ) * 180 / PI;
+
+/* -------------------------------------------------------------------- */
+/*      Create geometry                                                 */
+/* -------------------------------------------------------------------- */
+    OGRGeometry *poEllipse = 
+        OGRGeometryFactory::approximateArcAngles( 
+            oCenter.x, oCenter.y, oCenter.z,
+            dfPrimaryRadius, dfSecondaryRadius, dfRotation, 
+            dfStartAngle, dfEndAngle, 0.0 );
+
+    poFeature->SetGeometryDirectly( poEllipse );
+
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                            TranslateARC()                            */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateARC( OdDbEntityPtr poEntity )
+
+{
+    OdDbArcPtr poAE = OdDbArc::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    double dfRadius = 0.0;
+    double dfStartAngle = 0.0, dfEndAngle = 360.0;
+    OdGePoint3d oCenter;
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Collect parameters.                                             */
+/* -------------------------------------------------------------------- */
+    dfEndAngle = -1 * poAE->startAngle() * 180 / PI;
+    dfStartAngle = -1 * poAE->endAngle() * 180 / PI;
+    dfRadius = poAE->radius();
+    oCenter = poAE->center();
+    
+/* -------------------------------------------------------------------- */
+/*      Create geometry                                                 */
+/* -------------------------------------------------------------------- */
+    if( dfStartAngle > dfEndAngle )
+        dfEndAngle += 360.0;
+
+    OGRGeometry *poArc = 
+        OGRGeometryFactory::approximateArcAngles( 
+            oCenter.x, oCenter.y, oCenter.z,
+            dfRadius, dfRadius, 0.0, dfStartAngle, dfEndAngle, 0.0 );
+
+    poFeature->SetGeometryDirectly( poArc );
+
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          TranslateSPLINE()                           */
+/************************************************************************/
+
+void rbspline(int npts,int k,int p1,double b[],double h[], double p[]);
+void rbsplinu(int npts,int k,int p1,double b[],double h[], double p[]);
+
+OGRFeature *OGRDWGLayer::TranslateSPLINE( OdDbEntityPtr poEntity )
+
+{
+    OdDbSplinePtr poSpline = OdDbSpline::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    std::vector<double> adfControlPoints;
+    int nDegree, i;
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+    nDegree = poSpline->degree();
+
+/* -------------------------------------------------------------------- */
+/*      Collect the control points in our vector.                       */
+/* -------------------------------------------------------------------- */
+    int nControlPoints = poSpline->numControlPoints();
+
+    adfControlPoints.push_back( 0.0 ); // some sort of control info.
+    
+    for( i = 0; i < nControlPoints; i++ )
+    {
+        OdGePoint3d oCP;
+
+        poSpline->getControlPointAt( i, oCP );
+
+        adfControlPoints.push_back( oCP.x );
+        adfControlPoints.push_back( oCP.y );
+        adfControlPoints.push_back( 0.0 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process values.                                                 */
+/* -------------------------------------------------------------------- */
+    if( poSpline->isClosed() )
+    {
+        for( i = 0; i < nDegree; i++ )
+        {
+            adfControlPoints.push_back( adfControlPoints[i*3+1] );
+            adfControlPoints.push_back( adfControlPoints[i*3+2] );
+            adfControlPoints.push_back( adfControlPoints[i*3+3] );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Interpolate spline                                              */
+/* -------------------------------------------------------------------- */
+    std::vector<double> h, p;
+
+    h.push_back(1.0);
+    for( i = 0; i < nControlPoints; i++ )
+        h.push_back( 1.0 );
+    
+    // resolution:
+    //int p1 = getGraphicVariableInt("$SPLINESEGS", 8) * npts;
+    int p1 = nControlPoints * 8;
+
+    p.push_back( 0.0 );
+    for( i = 0; i < 3*p1; i++ )
+        p.push_back( 0.0 );
+
+    if( poSpline->isClosed() )
+        rbsplinu( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]), 
+                  &(h[0]), &(p[0]) );
+    else
+        rbspline( nControlPoints, nDegree+1, p1, &(adfControlPoints[0]), 
+                  &(h[0]), &(p[0]) );
+    
+/* -------------------------------------------------------------------- */
+/*      Turn into OGR geometry.                                         */
+/* -------------------------------------------------------------------- */
+    OGRLineString *poLS = new OGRLineString();
+
+    poLS->setNumPoints( p1 );
+    for( i = 0; i < p1; i++ )
+        poLS->setPoint( i, p[i*3+1], p[i*3+2] );
+
+    poFeature->SetGeometryDirectly( poLS );
+
+    PrepareLineStyle( poFeature );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                      GeometryInsertTransformer                       */
+/************************************************************************/
+
+
+class GeometryInsertTransformer : public OGRCoordinateTransformation
+{
+public:
+    GeometryInsertTransformer() : 
+            dfXOffset(0),dfYOffset(0),dfZOffset(0),
+            dfXScale(1.0),dfYScale(1.0),dfZScale(1.0),
+            dfAngle(0.0) {}
+
+    double dfXOffset;
+    double dfYOffset;
+    double dfZOffset;
+    double dfXScale;
+    double dfYScale;
+    double dfZScale;
+    double dfAngle;
+
+    OGRSpatialReference *GetSourceCS() { return NULL; }
+    OGRSpatialReference *GetTargetCS() { return NULL; }
+    int Transform( int nCount, 
+                   double *x, double *y, double *z )
+        { return TransformEx( nCount, x, y, z, NULL ); }
+    
+    int TransformEx( int nCount, 
+                     double *x, double *y, double *z = NULL,
+                     int *pabSuccess = NULL )
+        {
+            int i;
+            for( i = 0; i < nCount; i++ )
+            {
+                double dfXNew, dfYNew;
+
+                x[i] *= dfXScale;
+                y[i] *= dfYScale;
+                z[i] *= dfZScale;
+
+                dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
+                dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
+
+                x[i] = dfXNew;
+                y[i] = dfYNew;
+
+                x[i] += dfXOffset;
+                y[i] += dfYOffset;
+                z[i] += dfZOffset;
+
+                if( pabSuccess )
+                    pabSuccess[i] = TRUE;
+            }
+            return TRUE;
+        }
+};
+
+/************************************************************************/
+/*                          TranslateINSERT()                           */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::TranslateINSERT( OdDbEntityPtr poEntity )
+
+{
+    OdDbBlockReferencePtr poRef = OdDbBlockReference::cast( poEntity );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    TranslateGenericProperties( poFeature, poEntity );
+
+/* -------------------------------------------------------------------- */
+/*      Collect parameters from the object.                             */
+/* -------------------------------------------------------------------- */
+    GeometryInsertTransformer oTransformer;
+    CPLString osBlockName;
+    double dfAngle = poRef->rotation() * 180 / PI;
+    OdGePoint3d oPosition = poRef->position();
+    OdGeScale3d oScale = poRef->scaleFactors();
+    
+    oTransformer.dfXOffset = oPosition.x;
+    oTransformer.dfYOffset = oPosition.y;
+    oTransformer.dfZOffset = oPosition.z;
+
+    oTransformer.dfXScale = oScale.sx;    
+    oTransformer.dfYScale = oScale.sy;    
+    oTransformer.dfZScale = oScale.sz;
+
+    oTransformer.dfAngle = poRef->rotation();
+
+    OdDbBlockTableRecordPtr poBlockRec = poRef->blockTableRecord().openObject();
+    if (poBlockRec.get())
+        osBlockName = (const char *) poBlockRec->getName();
+
+/* -------------------------------------------------------------------- */
+/*      In the case where we do not inlined blocks we just capture      */
+/*      info on a point feature.                                        */
+/* -------------------------------------------------------------------- */
+    if( !poDS->InlineBlocks() )
+    {
+        poFeature->SetGeometryDirectly(
+            new OGRPoint( oTransformer.dfXOffset, 
+                          oTransformer.dfYOffset,
+                          oTransformer.dfZOffset ) );
+
+        poFeature->SetField( "BlockName", osBlockName );
+
+        poFeature->SetField( "BlockAngle", dfAngle );
+        poFeature->SetField( "BlockScale", 3, &(oTransformer.dfXScale) );
+
+        return poFeature;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Lookup the block.                                               */
+/* -------------------------------------------------------------------- */
+    DWGBlockDefinition *poBlock = poDS->LookupBlock( osBlockName );
+    
+    if( poBlock == NULL )
+    {
+        delete poFeature;
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Transform the geometry.                                         */
+/* -------------------------------------------------------------------- */
+    if( poBlock->poGeometry != NULL )
+    {
+        OGRGeometry *poGeometry = poBlock->poGeometry->clone();
+
+        poGeometry->transform( &oTransformer );
+
+        poFeature->SetGeometryDirectly( poGeometry );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If we have complete features associated with the block, push    */
+/*      them on the pending feature stack copying over key override     */
+/*      information.                                                    */
+/*                                                                      */
+/*      Note that while we transform the geometry of the features we    */
+/*      don't adjust subtle things like text angle.                     */
+/* -------------------------------------------------------------------- */
+    unsigned int iSubFeat;
+
+    for( iSubFeat = 0; iSubFeat < poBlock->apoFeatures.size(); iSubFeat++ )
+    {
+        OGRFeature *poSubFeature = poBlock->apoFeatures[iSubFeat]->Clone();
+        CPLString osCompEntityId;
+
+        if( poSubFeature->GetGeometryRef() != NULL )
+            poSubFeature->GetGeometryRef()->transform( &oTransformer );
+
+        ACAdjustText( dfAngle, oScale.sx, poSubFeature );
+
+#ifdef notdef
+        osCompEntityId = poSubFeature->GetFieldAsString( "EntityHandle" );
+        osCompEntityId += ":";
+#endif
+        osCompEntityId += poFeature->GetFieldAsString( "EntityHandle" );
+
+        poSubFeature->SetField( "EntityHandle", osCompEntityId );
+
+        apoPendingFeatures.push( poSubFeature );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If we have attributes, insert them on the stack at this         */
+/*      point too.                                                      */
+/* -------------------------------------------------------------------- */
+    OdDbObjectIteratorPtr pIter = poRef->attributeIterator();
+    for (; !pIter->done(); pIter->step())
+    {
+        OdDbAttributePtr pAttr = pIter->entity();
+        if (!pAttr.isNull())
+        {
+            oStyleProperties.clear();
+
+            OGRFeature *poAttrFeat = TranslateTEXT( pAttr );
+
+            if( poAttrFeat )
+                apoPendingFeatures.push( poAttrFeat );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Return the working feature if we had geometry, otherwise        */
+/*      return NULL and let the machinery find the rest of the          */
+/*      features in the pending feature stack.                          */
+/* -------------------------------------------------------------------- */
+    if( poBlock->poGeometry == NULL )
+    {
+        delete poFeature;
+        return NULL;
+    }
+    else
+    {
+        return poFeature;
+    }
+}
+
+/************************************************************************/
+/*                      GetNextUnfilteredFeature()                      */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
+
+{
+    OGRFeature *poFeature = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      If we have pending features, return one of them.                */
+/* -------------------------------------------------------------------- */
+    if( !apoPendingFeatures.empty() )
+    {
+        poFeature = apoPendingFeatures.front();
+        apoPendingFeatures.pop();
+
+        poFeature->SetFID( iNextFID++ );
+        return poFeature;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Fetch the next entity.                                          */
+/* -------------------------------------------------------------------- */
+    while( poFeature == NULL && !poEntIter->done() )
+    {
+
+        OdDbObjectId oId = poEntIter->objectId();
+        OdDbEntityPtr poEntity = OdDbEntity::cast( oId.openObject() );
+        
+        if (poEntity.isNull())
+            return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      What is the class name for this entity?                         */
+/* -------------------------------------------------------------------- */
+        OdRxClass *poClass = poEntity->isA();
+        const OdString osName = poClass->name();
+        const char *pszEntityClassName = (const char *) osName;
+        
+/* -------------------------------------------------------------------- */
+/*      Handle the entity.                                              */
+/* -------------------------------------------------------------------- */
+        oStyleProperties.clear();
+
+        if( EQUAL(pszEntityClassName,"AcDbPoint") )
+        {
+            poFeature = TranslatePOINT( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbLine") )
+        {
+            poFeature = TranslateLINE( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbPolyline") )
+        {
+            poFeature = TranslateLWPOLYLINE( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDb2dPolyline") )
+        {
+            poFeature = Translate2DPOLYLINE( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbEllipse") )
+        {
+            poFeature = TranslateELLIPSE( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbArc") )
+        {
+            poFeature = TranslateARC( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbMText") )
+        {
+            poFeature = TranslateMTEXT( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbText") 
+                 || EQUAL(pszEntityClassName,"AcDbAttributeDefinition") )
+        {
+            poFeature = TranslateTEXT( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbAlignedDimension") 
+                 || EQUAL(pszEntityClassName,"AcDbRotatedDimension") )
+        {
+            poFeature = TranslateDIMENSION( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbCircle") )
+        {
+            poFeature = TranslateCIRCLE( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbSpline") )
+        {
+            poFeature = TranslateSPLINE( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbHatch") )
+        {
+            poFeature = TranslateHATCH( poEntity );
+        }
+        else if( EQUAL(pszEntityClassName,"AcDbBlockReference") )
+        {
+            poFeature = TranslateINSERT( poEntity );
+            if( poFeature == NULL && !apoPendingFeatures.empty() )
+            {
+                poFeature = apoPendingFeatures.front();
+                apoPendingFeatures.pop();
+            }
+               
+        }
+        else
+        {
+            if( oIgnoredEntities.count(pszEntityClassName) == 0 )
+            {
+                oIgnoredEntities.insert( pszEntityClassName );
+                CPLDebug( "DWG", "Ignoring one or more of entity '%s'.", 
+                          pszEntityClassName );
+            }
+        }
+
+        poEntIter->step();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set FID.                                                        */
+/* -------------------------------------------------------------------- */
+    if( poFeature != NULL )
+    {
+        poFeature->SetFID( iNextFID++ );
+        m_nFeaturesRead++;
+    }
+    
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRDWGLayer::GetNextFeature()
+
+{
+    while( TRUE )
+    {
+        OGRFeature *poFeature = GetNextUnfilteredFeature();
+
+        if( poFeature == NULL )
+            return NULL;
+
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature ) ) )
+        {
+            return poFeature;
+        }
+
+        delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDWGLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
diff --git a/ogr/ogrsf_frmts/dxf/GNUmakefile b/ogr/ogrsf_frmts/dxf/GNUmakefile
index 7f65f11..31e8ea1 100644
--- a/ogr/ogrsf_frmts/dxf/GNUmakefile
+++ b/ogr/ogrsf_frmts/dxf/GNUmakefile
@@ -5,7 +5,8 @@ OBJ	=	ogrdxfdriver.o ogrdxfdatasource.o ogrdxflayer.o \
 		ogrdxfreader.o ogrdxf_blockmap.o ogrdxf_dimension.o \
 		ogrdxfwriterds.o ogrdxfwriterlayer.o intronurbs.o \
 		ogrdxf_polyline_smooth.o ogrdxfblockslayer.o \
-		ogrdxfblockswriterlayer.o ogrdxf_hatch.o
+		ogrdxfblockswriterlayer.o ogrdxf_hatch.o \
+		ogr_autocad_services.o
 
 CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
 
diff --git a/ogr/ogrsf_frmts/dxf/drv_dxf.html b/ogr/ogrsf_frmts/dxf/drv_dxf.html
index 76058e2..699fba3 100644
--- a/ogr/ogrsf_frmts/dxf/drv_dxf.html
+++ b/ogr/ogrsf_frmts/dxf/drv_dxf.html
@@ -41,7 +41,8 @@ arc into line segments.
 <li> INSERT: An attempt is made to insert the block definition as defined
 in the insert.  Linework blocks are aggregated into a single feature with
 a geometry collection for the geometry.  Text blocks are returned as one or
-more text features. 
+more text features.  To avoid merging blocks into a geometry collection the 
+DXF_MERGE_BLOCK_GEOMETRIES config option may be set to FALSE.
 <li> DIMENSION: This element is exploded into a feature with arrows and
 leaders, and a feature with the dimension label.
 <li> HATCH: Line and arc boundaries are collected as a polygon geometry, but 
@@ -82,7 +83,27 @@ have a point geometry for the insertion point.
 
 The intention is that with DXF_INLINE_BLOCKS disabled, the block references
 will remain as references and the original block definitions will be
-available via the blocks layer.  On export this configuration 
+available via the blocks layer.  On export this configuration will result in the
+creation of similar blocks. <p>
+
+<h2>Character Encodings</h2>
+
+Normally DXF files are in the ANSI_1252 / Win1252 encoding.  GDAL/OGR attempts 
+to translate this to UTF-8 when reading and back into ANSI_1252 when writing.
+DXF files can also have a header field ($DWGCODEPAGE) indicating the 
+encoding of the file.  In GDAL 1.8.x and earlier this was ignored but from
+GDAL 1.9.0 and later an attempt is made to use this to recode other 
+code pages to UTF-8.  Whether this works will depend on the code page naming
+and whether GDAL/OGR is built against the iconv library for character recoding.
+<p>
+
+In some cases the $DWGCODEPAGE setting in a DXF file will be wrong, or
+unrecognised by OGR.  It could be edited manually, or the DXF_ENCODING 
+configuration variable can be used to override what id will be used by 
+OGR in transcoding.  The value of DXF_ENCODING should be an encoding name
+supported by CPLRecode() (ie. an iconv name), not a DXF $DWGCODEPAGE name.
+Using a DXF_ENCODING name of "UTF-8" will avoid any attempt to recode the 
+text as it is read.<p>
 
 <hr>
 <h2>Creation Issues</h2>
diff --git a/ogr/ogrsf_frmts/dxf/makefile.vc b/ogr/ogrsf_frmts/dxf/makefile.vc
index cc6afca..4ea75c6 100644
--- a/ogr/ogrsf_frmts/dxf/makefile.vc
+++ b/ogr/ogrsf_frmts/dxf/makefile.vc
@@ -2,7 +2,8 @@ OBJ     =       ogrdxfdriver.obj ogrdxfdatasource.obj ogrdxflayer.obj \
 		ogrdxfreader.obj ogrdxf_blockmap.obj ogrdxf_dimension.obj \
 		ogrdxfwriterds.obj ogrdxfwriterlayer.obj intronurbs.obj \
 		ogrdxf_polyline_smooth.obj ogrdxfblockslayer.obj \
-		ogrdxfblockswriterlayer.obj ogrdxf_hatch.obj
+		ogrdxfblockswriterlayer.obj ogrdxf_hatch.obj \
+		ogr_autocad_services.obj
         
 EXTRAFLAGS =	-I.. -I..\..
 
diff --git a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
new file mode 100644
index 0000000..ec1e013
--- /dev/null
+++ b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
@@ -0,0 +1,519 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  DXF and DWG Translators
+ * Purpose:  Implements various generic services shared between autocad related
+ *           drivers.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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_autocad_services.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $");
+
+#ifndef PI
+#define PI  3.14159265358979323846
+#endif 
+
+/************************************************************************/
+/*                           ACTextUnescape()                           */
+/*                                                                      */
+/*      Unexcape DXF/DWG style escape sequences such as \P for newline  */
+/*      and \~ for space, and do the recoding to UTF8.                  */
+/************************************************************************/
+
+CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
+
+{
+    CPLString osResult;
+    CPLString osInput = pszRawInput;
+    
+/* -------------------------------------------------------------------- */
+/*      Translate text from Win-1252 to UTF8.  We approximate this      */
+/*      by treating Win-1252 as Latin-1.  Note that we likely ought     */
+/*      to be consulting the $DWGCODEPAGE header variable which         */
+/*      defaults to ANSI_1252 if not set.                               */
+/* -------------------------------------------------------------------- */
+    osInput.Recode( pszEncoding, CPL_ENC_UTF8 );
+
+    const char *pszInput = osInput.c_str();
+
+/* -------------------------------------------------------------------- */
+/*      Now translate escape sequences.  They are all plain ascii       */
+/*      characters and won't have been affected by the UTF8             */
+/*      recoding.                                                       */
+/* -------------------------------------------------------------------- */
+    while( *pszInput != '\0' )
+    {
+        if( pszInput[0] == '\\' && pszInput[1] == 'P' )
+        {
+            osResult += '\n';
+            pszInput++;
+        }
+        else if( pszInput[0] == '\\' && pszInput[1] == '~' )
+        {
+            osResult += ' ';
+            pszInput++;
+        }
+        else if( pszInput[0] == '\\' && pszInput[1] == 'U' 
+                 && pszInput[2] == '+' )
+        {
+            CPLString osHex;
+            int iChar;
+
+            osHex.assign( pszInput+3, 4 );
+            sscanf( osHex.c_str(), "%x", &iChar );
+
+            wchar_t anWCharString[2];
+            anWCharString[0] = (wchar_t) iChar;
+            anWCharString[1] = 0;
+            
+            char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
+                                                    CPL_ENC_UCS2, 
+                                                    CPL_ENC_UTF8 );
+
+            osResult += pszUTF8Char;
+            CPLFree( pszUTF8Char );
+            
+            pszInput += 6;
+        }
+        else if( pszInput[0] == '\\'
+                 && (pszInput[1] == 'W' 
+                     || pszInput[1] == 'T'
+                     || pszInput[1] == 'A' ) )
+        {
+            // eg. \W1.073172x;\T1.099;Bonneuil de Verrines
+            // See data/dwg/EP/42002.dwg
+            // Not sure what \W and \T do, but we skip them. 
+            // According to qcad rs_text.cpp, \A values are vertical
+            // alignment, 0=bottom, 1=mid, 2=top but we ignore for now.
+            
+            while( *pszInput != ';' && *pszInput != '\0' )
+                pszInput++;
+        }
+        else if( pszInput[0] == '\\' && pszInput[1] == '\\' )
+        {
+            osResult += '\\';
+            pszInput++;
+        }
+        else if( EQUALN(pszInput,"%%c",3) 
+                 || EQUALN(pszInput,"%%d",3)
+                 || EQUALN(pszInput,"%%p",3) )
+        {
+            wchar_t anWCharString[2];
+
+            anWCharString[1] = 0;
+
+            // These are especial symbol representations for autocad.
+            if( EQUALN(pszInput,"%%c",3) )
+                anWCharString[0] = 0x2300; // diameter (0x00F8 is a good approx)
+            else if( EQUALN(pszInput,"%%d",3) )
+                anWCharString[0] = 0x00B0; // degree
+            else if( EQUALN(pszInput,"%%p",3) )
+                anWCharString[0] = 0x00B1; // plus/minus
+
+            char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
+                                                    CPL_ENC_UCS2, 
+                                                    CPL_ENC_UTF8 );
+
+            osResult += pszUTF8Char;
+            CPLFree( pszUTF8Char );
+            
+            pszInput += 2;
+        }
+        else 
+            osResult += *pszInput;
+
+        pszInput++;
+    }
+    
+    return osResult;
+}
+
+/************************************************************************/
+/*                          ACGetColorTable()                           */
+/************************************************************************/
+
+const unsigned char *ACGetColorTable()
+
+{
+    static const unsigned char abyDXFColors[768] = {
+          0,  0,  0, // 0 
+        255,  0,  0, // 1 
+        255,255,  0, // 2 
+          0,255,  0, // 3 
+          0,255,255, // 4 
+          0,  0,255, // 5 
+        255,  0,255, // 6 
+          0,  0,  0, // 7 - it should be white, but that plots poorly
+        127,127,127, // 8 
+        191,191,191, // 9 
+        255,  0,  0, // 10 
+        255,127,127, // 11 
+        165,  0,  0, // 12 
+        165, 82, 82, // 13 
+        127,  0,  0, // 14 
+        127, 63, 63, // 15 
+         76,  0,  0, // 16 
+         76, 38, 38, // 17 
+         38,  0,  0, // 18 
+         38, 19, 19, // 19 
+        255, 63,  0, // 20 
+        255,159,127, // 21 
+        165, 41,  0, // 22 
+        165,103, 82, // 23 
+        127, 31,  0, // 24 
+        127, 79, 63, // 25 
+         76, 19,  0, // 26 
+         76, 47, 38, // 27 
+         38,  9,  0, // 28 
+         38, 23, 19, // 29 
+        255,127,  0, // 30 
+        255,191,127, // 31 
+        165, 82,  0, // 32 
+        165,124, 82, // 33 
+        127, 63,  0, // 34 
+        127, 95, 63, // 35 
+         76, 38,  0, // 36 
+         76, 57, 38, // 37 
+         38, 19,  0, // 38 
+         38, 28, 19, // 39 
+        255,191,  0, // 40 
+        255,223,127, // 41 
+        165,124,  0, // 42 
+        165,145, 82, // 43 
+        127, 95,  0, // 44 
+        127,111, 63, // 45 
+         76, 57,  0, // 46 
+         76, 66, 38, // 47 
+         38, 28,  0, // 48 
+         38, 33, 19, // 49 
+        255,255,  0, // 50 
+        255,255,127, // 51 
+        165,165,  0, // 52 
+        165,165, 82, // 53 
+        127,127,  0, // 54 
+        127,127, 63, // 55 
+         76, 76,  0, // 56 
+         76, 76, 38, // 57 
+         38, 38,  0, // 58 
+         38, 38, 19, // 59 
+        191,255,  0, // 60 
+        223,255,127, // 61 
+        124,165,  0, // 62 
+        145,165, 82, // 63 
+         95,127,  0, // 64 
+        111,127, 63, // 65 
+         57, 76,  0, // 66 
+         66, 76, 38, // 67 
+         28, 38,  0, // 68 
+         33, 38, 19, // 69 
+        127,255,  0, // 70 
+        191,255,127, // 71 
+         82,165,  0, // 72 
+        124,165, 82, // 73 
+         63,127,  0, // 74 
+         95,127, 63, // 75 
+         38, 76,  0, // 76 
+         57, 76, 38, // 77 
+         19, 38,  0, // 78 
+         28, 38, 19, // 79 
+         63,255,  0, // 80 
+        159,255,127, // 81 
+         41,165,  0, // 82 
+        103,165, 82, // 83 
+         31,127,  0, // 84 
+         79,127, 63, // 85 
+         19, 76,  0, // 86 
+         47, 76, 38, // 87 
+          9, 38,  0, // 88 
+         23, 38, 19, // 89 
+          0,255,  0, // 90 
+        127,255,127, // 91 
+          0,165,  0, // 92 
+         82,165, 82, // 93 
+          0,127,  0, // 94 
+         63,127, 63, // 95 
+          0, 76,  0, // 96 
+         38, 76, 38, // 97 
+          0, 38,  0, // 98 
+         19, 38, 19, // 99 
+          0,255, 63, // 100 
+        127,255,159, // 101 
+          0,165, 41, // 102 
+         82,165,103, // 103 
+          0,127, 31, // 104 
+        63,127, 79, // 105 
+        0, 76, 19, // 106 
+        38, 76, 47, // 107 
+        0, 38,  9, // 108 
+        19, 38, 23, // 109 
+        0,255,127, // 110 
+        127,255,191, // 111 
+        0,165, 82, // 112 
+        82,165,124, // 113 
+        0,127, 63, // 114 
+        63,127, 95, // 115 
+        0, 76, 38, // 116 
+        38, 76, 57, // 117 
+        0, 38, 19, // 118 
+        19, 38, 28, // 119 
+        0,255,191, // 120 
+        127,255,223, // 121 
+        0,165,124, // 122 
+        82,165,145, // 123 
+        0,127, 95, // 124 
+        63,127,111, // 125 
+        0, 76, 57, // 126 
+        38, 76, 66, // 127 
+        0, 38, 28, // 128 
+        19, 38, 33, // 129 
+        0,255,255, // 130 
+        127,255,255, // 131 
+        0,165,165, // 132 
+        82,165,165, // 133 
+        0,127,127, // 134 
+        63,127,127, // 135 
+        0, 76, 76, // 136 
+        38, 76, 76, // 137 
+        0, 38, 38, // 138 
+        19, 38, 38, // 139 
+        0,191,255, // 140 
+        127,223,255, // 141 
+        0,124,165, // 142 
+        82,145,165, // 143 
+        0, 95,127, // 144 
+        63,111,127, // 145 
+        0, 57, 76, // 146 
+        38, 66, 76, // 147 
+        0, 28, 38, // 148 
+        19, 33, 38, // 149 
+        0,127,255, // 150 
+        127,191,255, // 151 
+        0, 82,165, // 152 
+        82,124,165, // 153 
+        0, 63,127, // 154 
+        63, 95,127, // 155 
+        0, 38, 76, // 156 
+        38, 57, 76, // 157 
+        0, 19, 38, // 158 
+        19, 28, 38, // 159 
+        0, 63,255, // 160 
+        127,159,255, // 161 
+        0, 41,165, // 162 
+        82,103,165, // 163 
+        0, 31,127, // 164 
+        63, 79,127, // 165 
+        0, 19, 76, // 166 
+        38, 47, 76, // 167 
+        0,  9, 38, // 168 
+        19, 23, 38, // 169 
+        0,  0,255, // 170 
+        127,127,255, // 171 
+        0,  0,165, // 172 
+        82, 82,165, // 173 
+        0,  0,127, // 174 
+        63, 63,127, // 175 
+        0,  0, 76, // 176 
+        38, 38, 76, // 177 
+        0,  0, 38, // 178 
+        19, 19, 38, // 179 
+        63,  0,255, // 180 
+        159,127,255, // 181 
+        41,  0,165, // 182 
+        103, 82,165, // 183 
+        31,  0,127, // 184 
+        79, 63,127, // 185 
+        19,  0, 76, // 186 
+        47, 38, 76, // 187 
+        9,  0, 38, // 188 
+        23, 19, 38, // 189 
+        127,  0,255, // 190 
+        191,127,255, // 191 
+        82,  0,165, // 192 
+        124, 82,165, // 193 
+        63,  0,127, // 194 
+        95, 63,127, // 195 
+        38,  0, 76, // 196 
+        57, 38, 76, // 197 
+        19,  0, 38, // 198 
+        28, 19, 38, // 199 
+        191,  0,255, // 200 
+        223,127,255, // 201 
+        124,  0,165, // 202 
+        145, 82,165, // 203 
+        95,  0,127, // 204 
+        111, 63,127, // 205 
+        57,  0, 76, // 206 
+        66, 38, 76, // 207 
+        28,  0, 38, // 208 
+        33, 19, 38, // 209 
+        255,  0,255, // 210 
+        255,127,255, // 211 
+        165,  0,165, // 212 
+        165, 82,165, // 213 
+        127,  0,127, // 214 
+        127, 63,127, // 215 
+        76,  0, 76, // 216 
+        76, 38, 76, // 217 
+        38,  0, 38, // 218 
+        38, 19, 38, // 219 
+        255,  0,191, // 220 
+        255,127,223, // 221 
+        165,  0,124, // 222 
+        165, 82,145, // 223 
+        127,  0, 95, // 224 
+        127, 63,111, // 225 
+        76,  0, 57, // 226 
+        76, 38, 66, // 227 
+        38,  0, 28, // 228 
+        38, 19, 33, // 229 
+        255,  0,127, // 230 
+        255,127,191, // 231 
+        165,  0, 82, // 232 
+        165, 82,124, // 233 
+        127,  0, 63, // 234 
+        127, 63, 95, // 235 
+        76,  0, 38, // 236 
+        76, 38, 57, // 237 
+        38,  0, 19, // 238 
+        38, 19, 28, // 239 
+        255,  0, 63, // 240 
+        255,127,159, // 241 
+        165,  0, 41, // 242 
+        165, 82,103, // 243 
+        127,  0, 31, // 244 
+        127, 63, 79, // 245 
+        76,  0, 19, // 246 
+        76, 38, 47, // 247 
+        38,  0,  9, // 248 
+        38, 19, 23, // 249 
+        84, 84, 84, // 250 
+        118,118,118, // 251 
+        152,152,152, // 252 
+        186,186,186, // 253 
+        220,220,220, // 254 
+        255,255,255  // 255 
+    };
+
+    return abyDXFColors;
+}
+
+/************************************************************************/
+/*                            ACAdjustText()                            */
+/*                                                                      */
+/*      Rotate and scale text features by the designated amount by      */
+/*      adjusting the style string.                                     */
+/************************************************************************/
+
+void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
+
+{
+/* -------------------------------------------------------------------- */
+/*      We only try to alter text elements (LABEL styles).              */
+/* -------------------------------------------------------------------- */
+    if( poFeature->GetStyleString() == NULL )
+        return;
+
+    CPLString osOldStyle = poFeature->GetStyleString();
+
+    if( strstr(osOldStyle,"LABEL") == NULL )
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Is there existing angle text?                                   */
+/* -------------------------------------------------------------------- */
+    double dfOldAngle = 0.0;
+    CPLString osPreAngle, osPostAngle;
+    size_t nAngleOff = osOldStyle.find( ",a:" );
+
+    if( nAngleOff != std::string::npos )
+    {
+        size_t nEndOfAngleOff = osOldStyle.find( ",", nAngleOff + 1 );
+
+        if( nEndOfAngleOff == std::string::npos )
+            nEndOfAngleOff = osOldStyle.find( ")", nAngleOff + 1 );
+
+        osPreAngle.assign( osOldStyle, nAngleOff );
+        osPostAngle.assign( osOldStyle.c_str() + nEndOfAngleOff );
+        
+        dfOldAngle = CPLAtof( osOldStyle.c_str() + nAngleOff + 3 );
+    }
+    else
+    {
+        CPLAssert( osOldStyle[osOldStyle.size()-1] == ')' );
+        osPreAngle.assign( osOldStyle, osOldStyle.size() - 1 );
+        osPostAngle = ")";
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Format with the new angle.                                      */
+/* -------------------------------------------------------------------- */
+    CPLString osNewStyle;
+
+    osNewStyle.Printf( "%s,a:%g%s", 
+                       osPreAngle.c_str(), 
+                       dfOldAngle + dfAngle,
+                       osPostAngle.c_str() );
+
+    osOldStyle = osNewStyle;
+
+/* -------------------------------------------------------------------- */
+/*      Is there existing scale text?                                   */
+/* -------------------------------------------------------------------- */
+    double dfOldScale = 1.0;
+    CPLString osPreScale, osPostScale;
+    size_t nScaleOff = osOldStyle.find( ",s:" );
+    
+    if( nScaleOff != std::string::npos )
+    {
+        size_t nEndOfScaleOff = osOldStyle.find( ",", nScaleOff + 1 );
+
+        if( nEndOfScaleOff == std::string::npos )
+            nEndOfScaleOff = osOldStyle.find( ")", nScaleOff + 1 );
+
+        osPreScale.assign( osOldStyle, nScaleOff );
+        osPostScale.assign( osOldStyle.c_str() + nEndOfScaleOff );
+        
+        dfOldScale = CPLAtof( osOldStyle.c_str() + nScaleOff + 3 );
+    }
+    else
+    {
+        CPLAssert( osOldStyle[osOldStyle.size()-1] == ')' );
+        osPreScale.assign( osOldStyle, osOldStyle.size() - 1 );
+        osPostScale = ")";
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Format with the new scale.                                      */
+/* -------------------------------------------------------------------- */
+    osNewStyle.Printf( "%s,s:%gg%s", 
+                       osPreScale.c_str(), 
+                       dfOldScale * dfScale,
+                       osPostScale.c_str() );
+
+    poFeature->SetStyleString( osNewStyle );
+}
+
diff --git a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
new file mode 100644
index 0000000..a557a65
--- /dev/null
+++ b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  DXF and DWG Translators
+ * Purpose:  Declarations for shared AutoCAD format services.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011,  Frank Warmerdam
+ *
+ * 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_AUTOCAD_SERVICES_H_INCLUDED
+#define _OGR_AUTOCAD_SERVICES_H_INCLUDED
+
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_geometry.h"
+#include "ogr_feature.h"
+
+/* -------------------------------------------------------------------- */
+/*      Various Functions.                                              */
+/* -------------------------------------------------------------------- */
+CPLString ACTextUnescape( const char *pszInput, const char *pszEncoding );
+
+const unsigned char *ACGetColorTable( void );
+
+void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature );
+
+#endif /* ndef _OGR_AUTOCAD_SERVICES_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dxf/ogr_dxf.h b/ogr/ogrsf_frmts/dxf/ogr_dxf.h
index b7c162b..6fddcb5 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 21245 2010-12-13 18:32:46Z warmerdam $
+ * $Id: ogr_dxf.h 22527 2011-06-13 03:58:34Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Definition of classes for OGR .dxf driver.
@@ -31,6 +31,7 @@
 #define _OGR_DXF_H_INCLUDED
 
 #include "ogrsf_frmts.h"
+#include "ogr_autocad_services.h"
 #include "cpl_conv.h"
 #include <vector>
 #include <map>
@@ -94,6 +95,8 @@ class OGRDXFLayer : public OGRLayer
     OGRFeatureDefn     *poFeatureDefn;
     int                 iNextFID;
 
+    std::set<CPLString> oIgnoredEntities;
+
     std::queue<OGRFeature*> apoPendingFeatures;
     void                ClearPendingFeatures();
 
@@ -120,8 +123,9 @@ class OGRDXFLayer : public OGRLayer
 
     void                FormatDimension( CPLString &osText, double dfValue );
     OGRErr              CollectBoundaryPath( OGRGeometryCollection * );
+    OGRErr              CollectPolylinePath( OGRGeometryCollection * );
 
-    static CPLString    TextUnescape( const char * );
+    CPLString           TextUnescape( const char * );
 
   public:
     OGRDXFLayer( OGRDXFDataSource *poDS );
@@ -184,6 +188,8 @@ class OGRDXFDataSource : public OGRDataSource
     std::map<CPLString,DXFBlockDefinition> oBlockMap;
     std::map<CPLString,CPLString> oHeaderVariables;
 
+    CPLString           osEncoding;
+
     // indexed by layer name, then by property name.
     std::map< CPLString, std::map<CPLString,CPLString> > 
                         oLayerTable;
@@ -231,6 +237,8 @@ class OGRDXFDataSource : public OGRDataSource
     const char         *GetVariable(const char *pszName, 
                                     const char *pszDefault=NULL );
 
+    const char         *GetEncoding() { return osEncoding; }
+
     // reader related.
     int  ReadValue( char *pszValueBuffer, int nValueBufferSize = 81 )
         { return oReader.ReadValue( pszValueBuffer, nValueBufferSize ); }
@@ -263,6 +271,7 @@ class OGRDXFWriterLayer : public OGRLayer
     OGRErr              WritePOINT( OGRFeature* );
     OGRErr              WriteTEXT( OGRFeature* );
     OGRErr              WritePOLYLINE( OGRFeature*, OGRGeometry* = NULL );
+    OGRErr              WriteHATCH( OGRFeature*, OGRGeometry* = NULL );
     OGRErr              WriteINSERT( OGRFeature* );
 
     static CPLString    TextEscape( const char * );
@@ -390,8 +399,6 @@ class OGRDXFDriver : public OGRSFDriver
   public:
                 ~OGRDXFDriver();
 
-    static const unsigned char *GetDXFColorTable();
-
     const char *GetName();
     OGRDataSource *Open( const char *, int );
     int         TestCapability( const char * );
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
index c0e4c61..7c017b3 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxf_blockmap.cpp 20675 2010-09-23 03:09:20Z warmerdam $
+ * $Id: ogrdxf_blockmap.cpp 22011 2011-03-22 20:13:38Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Implements BlockMap reading and management portion of 
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrdxf_blockmap.cpp 20675 2010-09-23 03:09:20Z warmerdam $");
+CPL_CVSID("$Id: ogrdxf_blockmap.cpp 22011 2011-03-22 20:13:38Z warmerdam $");
 
 /************************************************************************/
 /*                          ReadBlockSection()                          */
@@ -45,6 +45,8 @@ void OGRDXFDataSource::ReadBlocksSection()
     char szLineBuf[257];
     int  nCode;
     OGRDXFLayer *poReaderLayer = (OGRDXFLayer *) GetLayerByName( "Entities" );
+    int bMergeBlockGeometries = CSLTestBoolean(
+        CPLGetConfigOption( "DXF_MERGE_BLOCK_GEOMETRIES", "TRUE" ) );
 
     iEntitiesSectionOffset = oReader.iSrcBufferFileOffset + oReader.iSrcBufferOffset;
 
@@ -82,8 +84,9 @@ void OGRDXFDataSource::ReadBlocksSection()
 
         while( (poFeature = poReaderLayer->GetNextUnfilteredFeature()) != NULL )
         {
-            if( poFeature->GetStyleString() != NULL
-                && strstr(poFeature->GetStyleString(),"LABEL") != NULL )
+            if( (poFeature->GetStyleString() != NULL
+                 && strstr(poFeature->GetStyleString(),"LABEL") != NULL)
+                || !bMergeBlockGeometries )
             {
                 apoFeatures.push_back( poFeature );
             }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
index 078d2a6..67d58a0 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
@@ -32,8 +32,14 @@
 #include "cpl_conv.h"
 #include "ogr_api.h"
 
+#include "ogrdxf_polyline_smooth.h"
+
 CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
 
+#ifndef PI
+#define PI  3.14159265358979323846
+#endif 
+
 /************************************************************************/
 /*                           TranslateHATCH()                           */
 /*                                                                      */
@@ -99,9 +105,40 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
     poFeature->SetGeometryDirectly( (OGRGeometry *) hFinalGeom );
 
 /* -------------------------------------------------------------------- */
-/*      We ought to try and make some useful translation of the fill    */
-/*      style but I'll leave that for another time.                     */
+/*      Work out the color for this feature.  For now we just assume    */
+/*      solid fill.  We cannot trivially translate the various sorts    */
+/*      of hatching.                                                    */
 /* -------------------------------------------------------------------- */
+    CPLString osLayer = poFeature->GetFieldAsString("Layer");
+
+    int nColor = 256;
+
+    if( oStyleProperties.count("Color") > 0 )
+        nColor = atoi(oStyleProperties["Color"]);
+
+    // Use layer color? 
+    if( nColor < 1 || nColor > 255 )
+    {
+        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
+        if( pszValue != NULL )
+            nColor = atoi(pszValue);
+    }
+        
+/* -------------------------------------------------------------------- */
+/*      Setup the style string.                                         */
+/* -------------------------------------------------------------------- */
+    if( nColor >= 1 && nColor <= 255 )
+    {
+        CPLString osStyle;
+        const unsigned char *pabyDXFColors = ACGetColorTable();
+        
+        osStyle.Printf( "BRUSH(fc:#%02x%02x%02x)",
+                        pabyDXFColors[nColor*3+0],
+                        pabyDXFColors[nColor*3+1],
+                        pabyDXFColors[nColor*3+2] );
+        
+        poFeature->SetStyleString( osStyle );
+    }
 
     return poFeature;
 }
@@ -119,25 +156,21 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 /* -------------------------------------------------------------------- */
 /*      Read the boundary path type.                                    */
 /* -------------------------------------------------------------------- */
-#define BPT_DEFAULT    0
-#define BPT_EXTERNAL   1
-#define BPT_POLYLINE   2
-#define BPT_DERIVED    3
-#define BPT_TEXTBOX    4
-#define BPT_OUTERMOST  5
-
     nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
     if( nCode != 92 )
         return NULL;
 
     int  nBoundaryPathType = atoi(szLineBuf);
-    
-    // for now we don't implement polyline support.
-    if( nBoundaryPathType == BPT_POLYLINE )
-    {
-        CPLDebug( "DXF", "HATCH polyline boundaries not yet supported." );
-        return OGRERR_UNSUPPORTED_OPERATION;
-    }
+
+/* ==================================================================== */
+/*      Handle polyline loops.                                          */
+/* ==================================================================== */
+    if( nBoundaryPathType & 0x02 )
+        return CollectPolylinePath( poGC );
+
+/* ==================================================================== */
+/*      Handle non-polyline loops.                                      */
+/* ==================================================================== */
 
 /* -------------------------------------------------------------------- */
 /*      Read number of edges.                                           */
@@ -267,6 +300,86 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 
             poGC->addGeometryDirectly( poArc );
         }
+
+/* -------------------------------------------------------------------- */
+/*      Process an elliptical arc.                                      */
+/* -------------------------------------------------------------------- */
+        else if( nEdgeType == ET_ELLIPTIC_ARC )
+        {
+            double dfCenterX;
+            double dfCenterY;
+            double dfMajorRadius, dfMinorRadius;
+            double dfMajorX, dfMajorY;
+            double dfStartAngle;
+            double dfEndAngle;
+            double dfRotation;
+            double dfRatio;
+            int    bCounterClockwise = FALSE;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 10 )
+                dfCenterX = atof(szLineBuf);
+            else
+                break;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 20 )
+                dfCenterY = atof(szLineBuf);
+            else
+                break;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 11 )
+                dfMajorX = atof(szLineBuf);
+            else
+                break;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 21 )
+                dfMajorY = atof(szLineBuf);
+            else
+                break;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 40 )
+                dfRatio = atof(szLineBuf) / 100.0;
+            else
+                break;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 50 )
+                dfStartAngle = -1 * atof(szLineBuf);
+            else
+                break;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 51 )
+                dfEndAngle = -1 * atof(szLineBuf);
+            else
+                break;
+
+            if( poDS->ReadValue(szLineBuf,sizeof(szLineBuf)) == 73 )
+                bCounterClockwise = atoi(szLineBuf);
+            else
+                poDS->UnreadValue();
+
+            if( bCounterClockwise )
+            {
+                double dfTemp = dfStartAngle;
+                dfStartAngle = dfEndAngle;
+                dfEndAngle = dfTemp;
+            }
+
+            if( dfStartAngle > dfEndAngle )
+                dfEndAngle += 360.0;
+
+            dfMajorRadius = sqrt( dfMajorX * dfMajorX + dfMajorY * dfMajorY );
+            dfMinorRadius = dfMajorRadius * dfRatio;
+
+            dfRotation = -1 * atan2( dfMajorY, dfMajorX ) * 180 / PI;
+
+            OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles( 
+                dfCenterX, dfCenterY, 0.0,
+                dfMajorRadius, dfMinorRadius, dfRotation,
+                dfStartAngle, dfEndAngle, 0.0 );
+
+            poArc->flattenTo2D();
+
+            poGC->addGeometryDirectly( poArc );
+        }
         else
         {
             CPLDebug( "DXF", "Unsupported HATCH boundary line type:%d",
@@ -276,19 +389,130 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Number of source boundary objects.                              */
+/*      Skip through source boundary objects if present.                */
 /* -------------------------------------------------------------------- */
     nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
     if( nCode != 97 )
         poDS->UnreadValue();
     else
     {
-        if( atoi(szLineBuf) != 0 )
+        int iObj, nObjCount = atoi(szLineBuf);
+
+        for( iObj = 0; iObj < nObjCount; iObj++ )
+            poDS->ReadValue( szLineBuf, sizeof(szLineBuf) );
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        CollectPolylinePath()                         */
+/************************************************************************/
+
+OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
+
+{
+    int  nCode;
+    char szLineBuf[257];
+    DXFSmoothPolyline oSmoothPolyline;
+    double dfBulge = 0.0;
+    double dfX = 0.0, dfY = 0.0;
+    int bHaveX = FALSE, bHaveY = FALSE;
+    int bIsClosed = FALSE;
+    int nVertexCount = -1;
+    int bHaveBulges = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Read the boundary path type.                                    */
+/* -------------------------------------------------------------------- */
+    while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
+    {
+        if( nVertexCount > 0 && (int) oSmoothPolyline.size() == nVertexCount )
+            break;
+
+        switch( nCode )
         {
-            CPLDebug( "DXF", "got unsupported HATCH boundary object references." );
-            return OGRERR_UNSUPPORTED_OPERATION;
+          case 93:
+            nVertexCount = atoi(szLineBuf);
+            break;
+
+          case 72:
+            bHaveBulges = atoi(szLineBuf);
+            break;
+
+          case 73:
+            bIsClosed = atoi(szLineBuf);
+            break;
+
+          case 10:
+            if( bHaveX && bHaveY )
+            {
+                oSmoothPolyline.AddPoint(dfX, dfY, 0.0, dfBulge);
+                dfBulge = 0.0;
+                bHaveY = FALSE;
+            }
+            dfX = CPLAtof(szLineBuf);
+            bHaveX = TRUE;
+            break;
+
+          case 20:
+            if( bHaveX && bHaveY )
+            {
+                oSmoothPolyline.AddPoint( dfX, dfY, 0.0, dfBulge );
+                dfBulge = 0.0;
+                bHaveX = bHaveY = FALSE;
+            }
+            dfY = CPLAtof(szLineBuf);
+            bHaveY = TRUE;
+            if( bHaveX && bHaveY && !bHaveBulges )
+            {
+                oSmoothPolyline.AddPoint( dfX, dfY, 0.0, dfBulge );
+                dfBulge = 0.0;
+                bHaveX = bHaveY = FALSE;
+            }
+            break;
+
+          case 42:
+            dfBulge = CPLAtof(szLineBuf);
+            if( bHaveX && bHaveY )
+            {
+                oSmoothPolyline.AddPoint( dfX, dfY, 0.0, dfBulge );
+                dfBulge = 0.0;
+                bHaveX = bHaveY = FALSE;
+            }
+            break;
+
+          default:
+            break;
         }
     }
 
+    if( nCode != 10 && nCode != 20 && nCode != 42 )
+        poDS->UnreadValue();
+
+    if( bHaveX && bHaveY )
+        oSmoothPolyline.AddPoint(dfX, dfY, 0.0, dfBulge);
+
+    if( bIsClosed )
+        oSmoothPolyline.Close();
+
+    poGC->addGeometryDirectly( oSmoothPolyline.Tesselate() );
+
+/* -------------------------------------------------------------------- */
+/*      Skip through source boundary objects if present.                */
+/* -------------------------------------------------------------------- */
+    nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
+    if( nCode != 97 )
+        poDS->UnreadValue();
+    else
+    {
+        int iObj, nObjCount = atoi(szLineBuf);
+
+        for( iObj = 0; iObj < nObjCount; iObj++ )
+            poDS->ReadValue( szLineBuf, sizeof(szLineBuf) );
+    }
+
     return OGRERR_NONE;
 }
+
+    
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
index d205309..74a054b 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
@@ -144,8 +144,13 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
 
 /* -------------------------------------------------------------------- */
 /*      If polyline is closed, convert linestring to a linear ring      */
+/*                                                                      */
+/*      Actually, on review I'm not convinced this is a good idea.      */
+/*      Note that most (all) "filled polygons" are expressed with       */
+/*      hatches which are now handled fairly well and they tend to      */
+/*      echo linear polylines.                                          */
 /* -------------------------------------------------------------------- */
-
+#ifdef notdef
     if(m_bClosed)
     {
         OGRLinearRing *poLR = new OGRLinearRing();
@@ -158,6 +163,8 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
 
         return poPoly;
     }
+#endif
+
     return poLS;
 }
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
index 04407b2..a785d83 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
@@ -44,23 +44,23 @@
 
 class DXFSmoothPolylineVertex
 {
-    public:
-        double  x, y, z, bulge;
+public:
+    double  x, y, z, bulge;
 
 
-        DXFSmoothPolylineVertex()
+    DXFSmoothPolylineVertex()
         {
             x = y = z = bulge = 0.0;
         }
 
 
-        DXFSmoothPolylineVertex(double dfX, double dfY, double dfZ, double dfBulge)
+    DXFSmoothPolylineVertex(double dfX, double dfY, double dfZ, double dfBulge)
         {
             this->set(dfX, dfY, dfZ, dfBulge);
         }
 
 
-        void set(double dfX, double dfY, double dfZ, double dfBulge)
+    void set(double dfX, double dfY, double dfZ, double dfBulge)
         {
             x = dfX;
             y = dfY;
@@ -69,20 +69,20 @@ class DXFSmoothPolylineVertex
         }
 
 
-        void scale(double s)
+    void scale(double s)
         {
             x *= s;
             y *= s;
         }
 
           
-        double length() const
+    double length() const
         {
             return (sqrt(x*x + y*y));
         }
 
 
-        void normalize()
+    void normalize()
         {
             const double len = this->length();
             assert(len != 0.0);
@@ -92,7 +92,7 @@ class DXFSmoothPolylineVertex
         }
 
 
-        bool shares_2D_pos(const DXFSmoothPolylineVertex& v) const
+    bool shares_2D_pos(const DXFSmoothPolylineVertex& v) const
         {
             return (x == v.x && y == v.y);
         }
@@ -107,47 +107,49 @@ class DXFSmoothPolyline
     // We treat Z as constant over the entire string; this may
     // change in the future.
 
-    private:
+private:
 
-        std::vector<DXFSmoothPolylineVertex>    m_vertices;
-        mutable bool                            m_blinestringstarted;
-        bool                                    m_bClosed;
-		int										m_dim;
+    std::vector<DXFSmoothPolylineVertex>    m_vertices;
+    mutable bool                            m_blinestringstarted;
+    bool                                    m_bClosed;
+    int										m_dim;
 
        
-    public:
-        DXFSmoothPolyline()
+public:
+    DXFSmoothPolyline()
         {
             m_bClosed = false;
-			m_dim = 2;
+            m_dim = 2;
         }
 
-        OGRGeometry* Tesselate() const;
+    OGRGeometry* Tesselate() const;
 
-        void SetSize(int n) { m_vertices.reserve(n); }
+    size_t size() { return m_vertices.size(); }
 
-        void AddPoint(double dfX, double dfY, double dfZ, double dfBulge)
+    void SetSize(int n) { m_vertices.reserve(n); }
+
+    void AddPoint(double dfX, double dfY, double dfZ, double dfBulge)
         {
             m_vertices.push_back(DXFSmoothPolylineVertex(dfX, dfY, dfZ, dfBulge));
         }
 
-        void Close();
+    void Close();
 
-        bool IsEmpty() const { return m_vertices.empty(); }
+    bool IsEmpty() const { return m_vertices.empty(); }
 
-        bool HasConstantZ(double&) const;
+    bool HasConstantZ(double&) const;
 
-	    void setCoordinateDimension(int n) { m_dim = n; }
+    void setCoordinateDimension(int n) { m_dim = n; }
 
 
 
-    private:
-        void EmitArc(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&,
-                double radius, double len, double saggita, 
-                OGRLineString*, double dfZ = 0.0) const;
+private:
+    void EmitArc(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&,
+                 double radius, double len, double saggita, 
+                 OGRLineString*, double dfZ = 0.0) const;
 
-        void EmitLine(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&, 
-            OGRLineString*, bool bConstantZ, double dfZ) const;
+    void EmitLine(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&, 
+                  OGRLineString*, bool bConstantZ, double dfZ) const;
 };
 
 #endif  /* __OGRDXF_SMOOTH_POLYLINE_H__ */
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
index 2a6c3ec..2b49535 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
@@ -181,6 +181,9 @@ OGRFeature *OGRDXFBlocksLayer::GetNextFeature()
 int OGRDXFBlocksLayer::TestCapability( const char * pszCap )
 
 {
-    return FALSE;
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+    else
+        return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
index a8f06d4..d06d63a 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfdatasource.cpp 20676 2010-09-23 09:56:24Z rouault $
+ * $Id: ogrdxfdatasource.cpp 22527 2011-06-13 03:58:34Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFDataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdxfdatasource.cpp 20676 2010-09-23 09:56:24Z rouault $");
+CPL_CVSID("$Id: ogrdxfdatasource.cpp 22527 2011-06-13 03:58:34Z warmerdam $");
 
 /************************************************************************/
 /*                          OGRDXFDataSource()                          */
@@ -103,6 +103,8 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
     if( !EQUAL(CPLGetExtension(pszFilename),"dxf") )
         return FALSE;
 
+    osEncoding = CPL_ENC_ISO8859_1;
+
     osName = pszFilename;
 
     bInlineBlocks = CSLTestBoolean(
@@ -279,25 +281,33 @@ void OGRDXFDataSource::ReadLayerDefinition()
     std::map<CPLString,CPLString> oLayerProperties;
     CPLString osLayerName = "";
 
+    oLayerProperties["Hidden"] = "0";
+
     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > 0 )
     {
         switch( nCode )
         {
           case 2:
-            osLayerName = szLineBuf;
+            osLayerName = ACTextUnescape(szLineBuf,GetEncoding());
             oLayerProperties["Exists"] = "1";
             break;
 
           case 6:
-            oLayerProperties["Linetype"] = szLineBuf;
+            oLayerProperties["Linetype"] = ACTextUnescape(szLineBuf,
+                                                          GetEncoding());
             break;
             
           case 62:
             oLayerProperties["Color"] = szLineBuf;
+
+            if( atoi(szLineBuf) < 0 ) // Is layer off?
+                oLayerProperties["Hidden"] = "1";
             break;
             
           case 70:
             oLayerProperties["Flags"] = szLineBuf;
+            if( atoi(szLineBuf) & 0x01 ) // Is layer frozen?
+                oLayerProperties["Hidden"] = "1";
             break;
 
           case 370:
@@ -351,7 +361,7 @@ void OGRDXFDataSource::ReadLineTypeDefinition()
         switch( nCode )
         {
           case 2:
-            osLineTypeName = szLineBuf;
+            osLineTypeName = ACTextUnescape(szLineBuf,GetEncoding());
             break;
 
           case 49:
@@ -419,6 +429,33 @@ void OGRDXFDataSource::ReadHeaderSection()
 
     CPLDebug( "DXF", "Read %d header variables.", 
               (int) oHeaderVariables.size() );
+
+/* -------------------------------------------------------------------- */
+/*      Decide on what CPLRecode() name to use for the files            */
+/*      encoding or allow the encoding to be overridden.                */
+/* -------------------------------------------------------------------- */
+    CPLString osCodepage = GetVariable( "$DWGCODEPAGE", "ANSI_1252" );
+
+    // not strictly accurate but works even without iconv.
+    if( osCodepage == "ANSI_1252" )
+        osEncoding = CPL_ENC_ISO8859_1; 
+    else if( EQUALN(osCodepage,"ANSI_",5) )
+    {
+        osEncoding = "CP";
+        osEncoding += osCodepage + 5;
+    }
+    else
+    {
+        // fallback to the default 
+        osEncoding = CPL_ENC_ISO8859_1;
+    }
+                                       
+    if( CPLGetConfigOption( "DXF_ENCODING", NULL ) != NULL )
+        osEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
+
+    if( osEncoding != CPL_ENC_ISO8859_1 )
+        CPLDebug( "DXF", "Treating DXF as encoding '%s', $DWGCODEPAGE='%s'", 
+                  osEncoding.c_str(), osCodepage.c_str() );
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
index 1a52b94..8e1969b 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfdriver.cpp 18535 2010-01-12 01:40:32Z warmerdam $
+ * $Id: ogrdxfdriver.cpp 22527 2011-06-13 03:58:34Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFDriver.
@@ -30,7 +30,7 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdxfdriver.cpp 18535 2010-01-12 01:40:32Z warmerdam $");
+CPL_CVSID("$Id: ogrdxfdriver.cpp 22527 2011-06-13 03:58:34Z warmerdam $");
 
 /************************************************************************/
 /*                          ~OGRDXFDriver()                          */
@@ -102,275 +102,6 @@ int OGRDXFDriver::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                          GetDXFColorTable()                          */
-/************************************************************************/
-
-const unsigned char *OGRDXFDriver::GetDXFColorTable()
-
-{
-    static const unsigned char abyDXFColors[768] = {
-          0,  0,  0, // 0 
-        255,  0,  0, // 1 
-        255,255,  0, // 2 
-          0,255,  0, // 3 
-          0,255,255, // 4 
-          0,  0,255, // 5 
-        255,  0,255, // 6 
-          0,  0,  0, // 7 - it should be white, but that plots poorly
-        127,127,127, // 8 
-        191,191,191, // 9 
-        255,  0,  0, // 10 
-        255,127,127, // 11 
-        165,  0,  0, // 12 
-        165, 82, 82, // 13 
-        127,  0,  0, // 14 
-        127, 63, 63, // 15 
-         76,  0,  0, // 16 
-         76, 38, 38, // 17 
-         38,  0,  0, // 18 
-         38, 19, 19, // 19 
-        255, 63,  0, // 20 
-        255,159,127, // 21 
-        165, 41,  0, // 22 
-        165,103, 82, // 23 
-        127, 31,  0, // 24 
-        127, 79, 63, // 25 
-         76, 19,  0, // 26 
-         76, 47, 38, // 27 
-         38,  9,  0, // 28 
-         38, 23, 19, // 29 
-        255,127,  0, // 30 
-        255,191,127, // 31 
-        165, 82,  0, // 32 
-        165,124, 82, // 33 
-        127, 63,  0, // 34 
-        127, 95, 63, // 35 
-         76, 38,  0, // 36 
-         76, 57, 38, // 37 
-         38, 19,  0, // 38 
-         38, 28, 19, // 39 
-        255,191,  0, // 40 
-        255,223,127, // 41 
-        165,124,  0, // 42 
-        165,145, 82, // 43 
-        127, 95,  0, // 44 
-        127,111, 63, // 45 
-         76, 57,  0, // 46 
-         76, 66, 38, // 47 
-         38, 28,  0, // 48 
-         38, 33, 19, // 49 
-        255,255,  0, // 50 
-        255,255,127, // 51 
-        165,165,  0, // 52 
-        165,165, 82, // 53 
-        127,127,  0, // 54 
-        127,127, 63, // 55 
-         76, 76,  0, // 56 
-         76, 76, 38, // 57 
-         38, 38,  0, // 58 
-         38, 38, 19, // 59 
-        191,255,  0, // 60 
-        223,255,127, // 61 
-        124,165,  0, // 62 
-        145,165, 82, // 63 
-         95,127,  0, // 64 
-        111,127, 63, // 65 
-         57, 76,  0, // 66 
-         66, 76, 38, // 67 
-         28, 38,  0, // 68 
-         33, 38, 19, // 69 
-        127,255,  0, // 70 
-        191,255,127, // 71 
-         82,165,  0, // 72 
-        124,165, 82, // 73 
-         63,127,  0, // 74 
-         95,127, 63, // 75 
-         38, 76,  0, // 76 
-         57, 76, 38, // 77 
-         19, 38,  0, // 78 
-         28, 38, 19, // 79 
-         63,255,  0, // 80 
-        159,255,127, // 81 
-         41,165,  0, // 82 
-        103,165, 82, // 83 
-         31,127,  0, // 84 
-         79,127, 63, // 85 
-         19, 76,  0, // 86 
-         47, 76, 38, // 87 
-          9, 38,  0, // 88 
-         23, 38, 19, // 89 
-          0,255,  0, // 90 
-        127,255,127, // 91 
-          0,165,  0, // 92 
-         82,165, 82, // 93 
-          0,127,  0, // 94 
-         63,127, 63, // 95 
-          0, 76,  0, // 96 
-         38, 76, 38, // 97 
-          0, 38,  0, // 98 
-         19, 38, 19, // 99 
-          0,255, 63, // 100 
-        127,255,159, // 101 
-          0,165, 41, // 102 
-         82,165,103, // 103 
-          0,127, 31, // 104 
-        63,127, 79, // 105 
-        0, 76, 19, // 106 
-        38, 76, 47, // 107 
-        0, 38,  9, // 108 
-        19, 38, 23, // 109 
-        0,255,127, // 110 
-        127,255,191, // 111 
-        0,165, 82, // 112 
-        82,165,124, // 113 
-        0,127, 63, // 114 
-        63,127, 95, // 115 
-        0, 76, 38, // 116 
-        38, 76, 57, // 117 
-        0, 38, 19, // 118 
-        19, 38, 28, // 119 
-        0,255,191, // 120 
-        127,255,223, // 121 
-        0,165,124, // 122 
-        82,165,145, // 123 
-        0,127, 95, // 124 
-        63,127,111, // 125 
-        0, 76, 57, // 126 
-        38, 76, 66, // 127 
-        0, 38, 28, // 128 
-        19, 38, 33, // 129 
-        0,255,255, // 130 
-        127,255,255, // 131 
-        0,165,165, // 132 
-        82,165,165, // 133 
-        0,127,127, // 134 
-        63,127,127, // 135 
-        0, 76, 76, // 136 
-        38, 76, 76, // 137 
-        0, 38, 38, // 138 
-        19, 38, 38, // 139 
-        0,191,255, // 140 
-        127,223,255, // 141 
-        0,124,165, // 142 
-        82,145,165, // 143 
-        0, 95,127, // 144 
-        63,111,127, // 145 
-        0, 57, 76, // 146 
-        38, 66, 76, // 147 
-        0, 28, 38, // 148 
-        19, 33, 38, // 149 
-        0,127,255, // 150 
-        127,191,255, // 151 
-        0, 82,165, // 152 
-        82,124,165, // 153 
-        0, 63,127, // 154 
-        63, 95,127, // 155 
-        0, 38, 76, // 156 
-        38, 57, 76, // 157 
-        0, 19, 38, // 158 
-        19, 28, 38, // 159 
-        0, 63,255, // 160 
-        127,159,255, // 161 
-        0, 41,165, // 162 
-        82,103,165, // 163 
-        0, 31,127, // 164 
-        63, 79,127, // 165 
-        0, 19, 76, // 166 
-        38, 47, 76, // 167 
-        0,  9, 38, // 168 
-        19, 23, 38, // 169 
-        0,  0,255, // 170 
-        127,127,255, // 171 
-        0,  0,165, // 172 
-        82, 82,165, // 173 
-        0,  0,127, // 174 
-        63, 63,127, // 175 
-        0,  0, 76, // 176 
-        38, 38, 76, // 177 
-        0,  0, 38, // 178 
-        19, 19, 38, // 179 
-        63,  0,255, // 180 
-        159,127,255, // 181 
-        41,  0,165, // 182 
-        103, 82,165, // 183 
-        31,  0,127, // 184 
-        79, 63,127, // 185 
-        19,  0, 76, // 186 
-        47, 38, 76, // 187 
-        9,  0, 38, // 188 
-        23, 19, 38, // 189 
-        127,  0,255, // 190 
-        191,127,255, // 191 
-        82,  0,165, // 192 
-        124, 82,165, // 193 
-        63,  0,127, // 194 
-        95, 63,127, // 195 
-        38,  0, 76, // 196 
-        57, 38, 76, // 197 
-        19,  0, 38, // 198 
-        28, 19, 38, // 199 
-        191,  0,255, // 200 
-        223,127,255, // 201 
-        124,  0,165, // 202 
-        145, 82,165, // 203 
-        95,  0,127, // 204 
-        111, 63,127, // 205 
-        57,  0, 76, // 206 
-        66, 38, 76, // 207 
-        28,  0, 38, // 208 
-        33, 19, 38, // 209 
-        255,  0,255, // 210 
-        255,127,255, // 211 
-        165,  0,165, // 212 
-        165, 82,165, // 213 
-        127,  0,127, // 214 
-        127, 63,127, // 215 
-        76,  0, 76, // 216 
-        76, 38, 76, // 217 
-        38,  0, 38, // 218 
-        38, 19, 38, // 219 
-        255,  0,191, // 220 
-        255,127,223, // 221 
-        165,  0,124, // 222 
-        165, 82,145, // 223 
-        127,  0, 95, // 224 
-        127, 63,111, // 225 
-        76,  0, 57, // 226 
-        76, 38, 66, // 227 
-        38,  0, 28, // 228 
-        38, 19, 33, // 229 
-        255,  0,127, // 230 
-        255,127,191, // 231 
-        165,  0, 82, // 232 
-        165, 82,124, // 233 
-        127,  0, 63, // 234 
-        127, 63, 95, // 235 
-        76,  0, 38, // 236 
-        76, 38, 57, // 237 
-        38,  0, 19, // 238 
-        38, 19, 28, // 239 
-        255,  0, 63, // 240 
-        255,127,159, // 241 
-        165,  0, 41, // 242 
-        165, 82,103, // 243 
-        127,  0, 31, // 244 
-        127, 63, 79, // 245 
-        76,  0, 19, // 246 
-        76, 38, 47, // 247 
-        38,  0,  9, // 248 
-        38, 19, 23, // 249 
-        84, 84, 84, // 250 
-        118,118,118, // 251 
-        152,152,152, // 252 
-        186,186,186, // 253 
-        220,220,220, // 254 
-        255,255,255  // 255 
-    };
-
-    return abyDXFColors;
-}
-
-/************************************************************************/
 /*                           RegisterOGRDXF()                           */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
index 208f97e..40d2ccb 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxflayer.cpp 21252 2010-12-14 02:45:50Z warmerdam $
+ * $Id: ogrdxflayer.cpp 22527 2011-06-13 03:58:34Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFLayer class.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogrdxf_polyline_smooth.h"
 
-CPL_CVSID("$Id: ogrdxflayer.cpp 21252 2010-12-14 02:45:50Z warmerdam $");
+CPL_CVSID("$Id: ogrdxflayer.cpp 22527 2011-06-13 03:58:34Z warmerdam $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -122,7 +122,7 @@ void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
     switch( nCode )
     {
       case 8: 
-        poFeature->SetField( "Layer", pszValue );
+        poFeature->SetField( "Layer", TextUnescape(pszValue) );
         break;
             
       case 100: 
@@ -140,7 +140,7 @@ void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
         break;
 
       case 6:
-        poFeature->SetField( "Linetype", pszValue );
+        poFeature->SetField( "Linetype", TextUnescape(pszValue) );
         break;
 
       case 370:
@@ -201,6 +201,12 @@ void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
     CPLString osLayer = poFeature->GetFieldAsString("Layer");
 
 /* -------------------------------------------------------------------- */
+/*      Is the layer disabled/hidden/frozen/off?                        */
+/* -------------------------------------------------------------------- */
+    int bHidden = 
+        EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
+
+/* -------------------------------------------------------------------- */
 /*      Work out the color for this feature.                            */
 /* -------------------------------------------------------------------- */
     int nColor = 256;
@@ -244,13 +250,16 @@ void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
 /*      Format the style string.                                        */
 /* -------------------------------------------------------------------- */
     CPLString osStyle;
-    const unsigned char *pabyDXFColors = OGRDXFDriver::GetDXFColorTable();
+    const unsigned char *pabyDXFColors = ACGetColorTable();
 
     osStyle.Printf( "PEN(c:#%02x%02x%02x", 
                     pabyDXFColors[nColor*3+0],
                     pabyDXFColors[nColor*3+1],
                     pabyDXFColors[nColor*3+2] );
 
+    if( bHidden )
+        osStyle += "00"; 
+
     if( dfWeight > 0.0 )
     {
         char szBuffer[64];
@@ -258,7 +267,7 @@ void OGRDXFLayer::PrepareLineStyle( OGRFeature *poFeature )
         char* pszComma = strchr(szBuffer, ',');
         if (pszComma)
             *pszComma = '.';
-        osStyle += CPLString().Printf( ",w:%smm", szBuffer );
+        osStyle += CPLString().Printf( ",w:%sg", szBuffer );
     }
 
     if( pszPattern )
@@ -382,69 +391,7 @@ void OGRDXFLayer::ApplyOCSTransformer( OGRGeometry *poGeometry )
 CPLString OGRDXFLayer::TextUnescape( const char *pszInput )
 
 {
-    CPLString osResult;
-    CPLString osInput = pszInput;
-    
-/* -------------------------------------------------------------------- */
-/*      Translate text from Win-1252 to UTF8.  We approximate this      */
-/*      by treating Win-1252 as Latin-1.  Note that we likely ought     */
-/*      to be consulting the $DWGCODEPAGE header variable which         */
-/*      defaults to ANSI_1252 if not set.                               */
-/* -------------------------------------------------------------------- */
-    osInput.Recode( CPL_ENC_ISO8859_1, CPL_ENC_UTF8 );
-    pszInput = osInput.c_str();
-
-/* -------------------------------------------------------------------- */
-/*      Now translate escape sequences.  They are all plain ascii       */
-/*      characters and won't have been affected by the UTF8             */
-/*      recoding.                                                       */
-/* -------------------------------------------------------------------- */
-    while( *pszInput != '\0' )
-    {
-        if( pszInput[0] == '\\' && pszInput[1] == 'P' )
-        {
-            osResult += '\n';
-            pszInput++;
-        }
-        else if( pszInput[0] == '\\' && pszInput[1] == '~' )
-        {
-            osResult += ' ';
-            pszInput++;
-        }
-        else if( pszInput[0] == '\\' && pszInput[1] == 'U' 
-                 && pszInput[2] == '+' )
-        {
-            CPLString osHex;
-            int iChar;
-
-            osHex.assign( pszInput+3, 4 );
-            sscanf( osHex.c_str(), "%x", &iChar );
-
-            wchar_t anWCharString[2];
-            anWCharString[0] = iChar;
-            anWCharString[1] = 0;
-            
-            char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
-                                                    CPL_ENC_UCS2, 
-                                                    CPL_ENC_UTF8 );
-
-            osResult += pszUTF8Char;
-            CPLFree( pszUTF8Char );
-            
-            pszInput += 6;
-        }
-        else if( pszInput[0] == '\\' && pszInput[1] == '\\' )
-        {
-            osResult += '\\';
-            pszInput++;
-        }
-        else 
-            osResult += *pszInput;
-
-        pszInput++;
-    }
-    
-    return osResult;
+    return ACTextUnescape( pszInput, poDS->GetEncoding() );
 }
 
 /************************************************************************/
@@ -607,7 +554,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
 
     if( nColor > 0 && nColor < 256 )
     {
-        const unsigned char *pabyDXFColors = OGRDXFDriver::GetDXFColorTable();
+        const unsigned char *pabyDXFColors = ACGetColorTable();
         osStyle += 
             CPLString().Printf( ",c:#%02x%02x%02x", 
                                 pabyDXFColors[nColor*3+0],
@@ -660,7 +607,7 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
             break;
 
           case 1:
-          case 3:
+          // case 3:  // we used to capture prompt, but it should not be displayed as text.
             osText += szLineBuf;
             break;
 
@@ -686,11 +633,57 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
 /*      Translate text from Win-1252 to UTF8.  We approximate this      */
 /*      by treating Win-1252 as Latin-1.                                */
 /* -------------------------------------------------------------------- */
-    osText.Recode( CPL_ENC_ISO8859_1, CPL_ENC_UTF8 );
+    osText.Recode( poDS->GetEncoding(), CPL_ENC_UTF8 );
 
     poFeature->SetField( "Text", osText );
 
 /* -------------------------------------------------------------------- */
+/*      We need to escape double quotes with backslashes before they    */
+/*      can be inserted in the style string.                            */
+/* -------------------------------------------------------------------- */
+    if( strchr( osText, '"') != NULL )
+    {
+        CPLString osEscaped;
+        size_t iC;
+
+        for( iC = 0; iC < osText.size(); iC++ )
+        {
+            if( osText[iC] == '"' )
+                osEscaped += "\\\"";
+            else
+                osEscaped += osText[iC];
+        }
+        osText = osEscaped;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Is the layer disabled/hidden/frozen/off?                        */
+/* -------------------------------------------------------------------- */
+    CPLString osLayer = poFeature->GetFieldAsString("Layer");
+
+    int bHidden = 
+        EQUAL(poDS->LookupLayerProperty( osLayer, "Hidden" ), "1");
+
+/* -------------------------------------------------------------------- */
+/*      Work out the color for this feature.                            */
+/* -------------------------------------------------------------------- */
+    int nColor = 256;
+
+    if( oStyleProperties.count("Color") > 0 )
+        nColor = atoi(oStyleProperties["Color"]);
+
+    // Use layer color? 
+    if( nColor < 1 || nColor > 255 )
+    {
+        const char *pszValue = poDS->LookupLayerProperty( osLayer, "Color" );
+        if( pszValue != NULL )
+            nColor = atoi(pszValue);
+    }
+        
+    if( nColor < 1 || nColor > 255 )
+        nColor = 8;
+
+/* -------------------------------------------------------------------- */
 /*      Prepare style string.                                           */
 /* -------------------------------------------------------------------- */
     CPLString osStyle;
@@ -717,7 +710,16 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
         osStyle += CPLString().Printf(",s:%sg", szBuffer);
     }
 
-    // add color!
+    const unsigned char *pabyDWGColors = ACGetColorTable();
+
+    snprintf( szBuffer, sizeof(szBuffer), ",c:#%02x%02x%02x", 
+              pabyDWGColors[nColor*3+0],
+              pabyDWGColors[nColor*3+1],
+              pabyDWGColors[nColor*3+2] );
+    osStyle += szBuffer;
+
+    if( bHidden )
+        osStyle += "00"; 
 
     osStyle += ")";
 
@@ -1596,12 +1598,20 @@ OGRFeature *OGRDXFLayer::TranslateINSERT()
     for( iSubFeat = 0; iSubFeat < poBlock->apoFeatures.size(); iSubFeat++ )
     {
         OGRFeature *poSubFeature = poBlock->apoFeatures[iSubFeat]->Clone();
+        CPLString osCompEntityId;
 
         if( poSubFeature->GetGeometryRef() != NULL )
             poSubFeature->GetGeometryRef()->transform( &oTransformer );
 
-        poSubFeature->SetField( "EntityHandle",
-                                poFeature->GetFieldAsString("EntityHandle") );
+        ACAdjustText( dfAngle, oTransformer.dfXScale, poSubFeature );
+
+#ifdef notdef
+        osCompEntityId = poSubFeature->GetFieldAsString( "EntityHandle" );
+        osCompEntityId += ":";
+#endif
+        osCompEntityId += poFeature->GetFieldAsString( "EntityHandle" );
+
+        poSubFeature->SetField( "EntityHandle", osCompEntityId );
 
         apoPendingFeatures.push( poSubFeature );
     }
@@ -1687,7 +1697,8 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
         {
             poFeature = TranslateMTEXT();
         }
-        else if( EQUAL(szLineBuf,"TEXT") )
+        else if( EQUAL(szLineBuf,"TEXT") 
+                 || EQUAL(szLineBuf,"ATTDEF") )
         {
             poFeature = TranslateTEXT();
         }
@@ -1733,7 +1744,12 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
         }
         else
         {
-            CPLDebug( "DXF", "Ignoring entity '%s'.", szLineBuf );
+            if( oIgnoredEntities.count(szLineBuf) == 0 )
+            {
+                oIgnoredEntities.insert( szLineBuf );
+                CPLDebug( "DWG", "Ignoring one or more of entity '%s'.", 
+                          szLineBuf );
+            }
         }
     }
 
@@ -1779,6 +1795,9 @@ OGRFeature *OGRDXFLayer::GetNextFeature()
 int OGRDXFLayer::TestCapability( const char * pszCap )
 
 {
-    return FALSE;
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+    else
+        return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
index a3bc637..0041730 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdxfwriterlayer.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: ogrdxfwriterlayer.cpp 22779 2011-07-23 18:53:29Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFWriterLayer - the OGRLayer class used for
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_featurestyle.h"
 
-CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 22779 2011-07-23 18:53:29Z warmerdam $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -112,7 +112,9 @@ void OGRDXFWriterLayer::ResetFP( VSILFILE *fpNew )
 int OGRDXFWriterLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCSequentialWrite) )
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+    else if( EQUAL(pszCap,OLCSequentialWrite) )
         return TRUE;
     else 
         return FALSE;
@@ -646,11 +648,13 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 
         if( poPen->Color(bDefault) != NULL && !bDefault )
             WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
-        
-        double dfWidthInMM = poPen->Width(bDefault);
+
+        // we want to fetch the width in ground units. 
+        poPen->SetUnit( OGRSTUGround, 1.0 );
+        double dfWidth = poPen->Width(bDefault);
 
         if( !bDefault )
-            WriteValue( 370, (int) floor(dfWidthInMM * 100 + 0.5) );
+            WriteValue( 370, (int) floor(dfWidth * 100 + 0.5) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -766,6 +770,214 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 }
 
 /************************************************************************/
+/*                             WriteHATCH()                             */
+/************************************************************************/
+
+OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
+                                      OGRGeometry *poGeom )
+
+{
+/* -------------------------------------------------------------------- */
+/*      For now we handle multipolygons by writing a series of          */
+/*      entities.                                                       */
+/* -------------------------------------------------------------------- */
+    if( poGeom == NULL )
+        poGeom = poFeature->GetGeometryRef();
+
+    if ( poGeom->IsEmpty() )
+    {
+        return OGRERR_NONE;
+    }
+            
+    if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
+    {
+        OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
+        int iGeom;
+        OGRErr eErr = OGRERR_NONE;
+
+        for( iGeom = 0; 
+             eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries(); 
+             iGeom++ )
+        {
+            eErr = WriteHATCH( poFeature, poGC->getGeometryRef( iGeom ) );
+        }
+
+        return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we now have a geometry we can work with?                     */
+/* -------------------------------------------------------------------- */
+    if( wkbFlatten(poGeom->getGeometryType()) != wkbPolygon )
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+
+/* -------------------------------------------------------------------- */
+/*      Write as a hatch.                                               */
+/* -------------------------------------------------------------------- */
+    WriteValue( 0, "HATCH" );
+    WriteCore( poFeature );
+    WriteValue( 100, "AcDbEntity" );
+    WriteValue( 100, "AcDbHatch" );
+    WriteValue( 2, "SOLID" ); // fill pattern
+    WriteValue( 70, 1 ); // solid fill
+    WriteValue( 71, 0 ); // associativity 
+
+/* -------------------------------------------------------------------- */
+/*      Do we have styling information?                                 */
+/* -------------------------------------------------------------------- */
+    OGRStyleTool *poTool = NULL;
+    OGRStyleMgr oSM;
+
+    if( poFeature->GetStyleString() != NULL )
+    {
+        oSM.InitFromFeature( poFeature );
+
+        if( oSM.GetPartCount() > 0 )
+            poTool = oSM.GetPart(0);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle a PEN tool to control drawing color and width.           */
+/*      Perhaps one day also dottedness, etc.                           */
+/* -------------------------------------------------------------------- */
+#ifdef notdef
+    if( poTool && poTool->GetType() == OGRSTCPen )
+    {
+        OGRStylePen *poPen = (OGRStylePen *) poTool;
+        GBool  bDefault;
+
+        if( poPen->Color(bDefault) != NULL && !bDefault )
+            WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
+        
+        double dfWidthInMM = poPen->Width(bDefault);
+
+        if( !bDefault )
+            WriteValue( 370, (int) floor(dfWidthInMM * 100 + 0.5) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a Linetype for the feature?                          */
+/* -------------------------------------------------------------------- */
+    CPLString osLineType = poFeature->GetFieldAsString( "Linetype" );
+
+    if( osLineType.size() > 0 
+        && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL 
+            || oNewLineTypes.count(osLineType) > 0 ) )
+    {
+        // Already define -> just reference it.
+        WriteValue( 6, osLineType );
+    }
+    else if( poTool != NULL && poTool->GetType() == OGRSTCPen )
+    {
+        CPLString osDefinition = PrepareLineTypeDefinition( poFeature, 
+                                                            poTool );
+
+        if( osDefinition != "" && osLineType == "" )
+        {
+            // Is this definition already created and named?
+            std::map<CPLString,CPLString>::iterator it;
+
+            for( it = oNewLineTypes.begin();
+                 it != oNewLineTypes.end();
+                 it++ )
+            {
+                if( (*it).second == osDefinition )
+                {
+                    osLineType = (*it).first;
+                    break;
+                }
+            }
+
+            // create an automatic name for it.
+            if( osLineType == "" )
+            {
+                do 
+                { 
+                    osLineType.Printf( "AutoLineType-%d", nNextAutoID++ );
+                }
+                while( poDS->oHeaderDS.LookupLineType(osLineType) != NULL );
+            }
+        }
+
+        // If it isn't already defined, add it now.
+        if( osDefinition != "" && oNewLineTypes.count(osLineType) == 0 )
+        {
+            oNewLineTypes[osLineType] = osDefinition;
+            WriteValue( 6, osLineType );
+        }
+    }
+    delete poTool;
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Process the loops (rings).                                      */
+/* -------------------------------------------------------------------- */
+    OGRPolygon *poPoly = (OGRPolygon *) poGeom;
+
+    WriteValue( 91, poPoly->getNumInteriorRings() + 1 );
+
+    for( int iRing = -1; iRing < poPoly->getNumInteriorRings(); iRing++ )
+    {
+        OGRLinearRing *poLR;
+
+        if( iRing == -1 )
+            poLR = poPoly->getExteriorRing();
+        else
+            poLR = poPoly->getInteriorRing( iRing );
+
+        WriteValue( 92, 2 ); // Polyline
+        WriteValue( 72, 0 ); // has bulge
+        WriteValue( 73, 1 ); // is closed
+        WriteValue( 93, poLR->getNumPoints() );
+        
+        for( int iVert = 0; iVert < poLR->getNumPoints(); iVert++ )
+        {
+            WriteValue( 10, poLR->getX(iVert) );
+            WriteValue( 20, poLR->getY(iVert) );
+        }
+    }
+    
+    return OGRERR_NONE;
+
+#ifdef notdef
+/* -------------------------------------------------------------------- */
+/*      Alternate unmaintained implementation as a polyline entity.     */
+/* -------------------------------------------------------------------- */
+    WriteValue( 0, "POLYLINE" );
+    WriteCore( poFeature );
+    WriteValue( 100, "AcDbEntity" );
+    WriteValue( 100, "AcDbPolyline" );
+    if( EQUAL( poGeom->getGeometryName(), "LINEARRING" ) )
+        WriteValue( 70, 1 );
+    else
+        WriteValue( 70, 0 );
+    WriteValue( 66, "1" );
+
+    int iVert;
+
+    for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
+    {
+        WriteValue( 0, "VERTEX" );
+        WriteValue( 8, "0" );
+        WriteValue( 10, poLS->getX(iVert) );
+        if( !WriteValue( 20, poLS->getY(iVert) ) ) 
+            return OGRERR_FAILURE;
+
+        if( poLS->getGeometryType() == wkbLineString25D )
+        {
+            if( !WriteValue( 30, poLS->getZ(iVert) ) )
+                return OGRERR_FAILURE;
+        }
+    }
+
+    WriteValue( 0, "SEQEND" );
+    WriteValue( 8, "0" );
+    
+    return OGRERR_NONE;
+#endif
+}
+
+/************************************************************************/
 /*                           CreateFeature()                            */
 /************************************************************************/
 
@@ -807,11 +1019,13 @@ OGRErr OGRDXFWriterLayer::CreateFeature( OGRFeature *poFeature )
             return WritePOINT( poFeature );
     }
     else if( eGType == wkbLineString 
-             || eGType == wkbMultiLineString 
-             || eGType == wkbPolygon 
-             || eGType == wkbMultiPolygon )
+             || eGType == wkbMultiLineString )
         return WritePOLYLINE( poFeature );
 
+    else if( eGType == wkbPolygon 
+             || eGType == wkbMultiPolygon )
+        return WriteHATCH( poFeature );
+
     // Explode geometry collections into multiple entities.
     else if( eGType == wkbGeometryCollection )
     {
@@ -866,7 +1080,7 @@ int OGRDXFWriterLayer::ColorStringToDXFColor( const char *pszRGB )
 /* -------------------------------------------------------------------- */
 /*      Find near color in DXF palette.                                 */
 /* -------------------------------------------------------------------- */
-    const unsigned char *pabyDXFColors = OGRDXFDriver::GetDXFColorTable();
+    const unsigned char *pabyDXFColors = ACGetColorTable();
     int i;
     int nMinDist = 768;
     int nBestColor = -1;
diff --git a/ogr/ogrsf_frmts/edigeo/GNUmakefile b/ogr/ogrsf_frmts/edigeo/GNUmakefile
new file mode 100644
index 0000000..6f2cc94
--- /dev/null
+++ b/ogr/ogrsf_frmts/edigeo/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogredigeodriver.o ogredigeodatasource.o ogredigeolayer.o
+
+CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_edigeo.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/edigeo/drv_edigeo.html b/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
new file mode 100644
index 0000000..c6addb1
--- /dev/null
+++ b/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
@@ -0,0 +1,66 @@
+<html>
+<head>
+<title>EDIGEO</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>EDIGEO</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver reads files encoded in the French EDIGEO exchange format,
+a text based file format aimed at exchanging geographical information between GIS, with
+powerful description capabilities, topology modelling, etc.<p>
+
+The driver has been developed to read files of the French PCI
+(Plan Cadastral Informatisé - Digital Cadastral Plan) as produced by the
+DGI (Direction Générale des Impots - General Tax Office). The driver
+should also be able to open other EDIGEO based products.<p>
+
+The driver must be provided with the .THF file describing the EDIGEO exchange and it will
+read the associated .DIC, .GEO, .SCD, .QAL and .VEC files.<p>
+
+In order the SRS of the layers to be correctly built, the IGNF file that contains
+the defintion of IGN SRS must be placed in the directory of PROJ.4 ressource files.<p>
+
+The whole set of files will be parsed into memory. This may be a limitation if dealing with
+big EDIGEO exchanges.<p>
+
+<!-- Default to YES.
+If you define the configuration option / environment variable OGR_EDIGEO_SORT_FOR_QGIS to YES,
+the layers of the French PCI will be ordered such as they overlay nicely when opened from QGIS.<p>
+-->
+
+<h3>Labels</h3>
+
+For EDIGEO PCI files, the labels are contained in the ID_S_OBJ_Z_1_2_2 layer. OGR will export
+styling following the <a href="http://gdal.org/ogr/ogr_feature_style.html">OGR Feature Style specification</a>.<p>
+
+It will also add the following fields :
+<ul>
+<li>OGR_OBJ_LNK: the id of the object that is linked to this label
+<li>OBJ_OBJ_LNK_LAYER: the name of the layer of the linked object
+<li>OGR_ATR_VAL: the value of the attribute to display (found in the ATR attribute of the OGR_OBJ_LNK object)
+<li>OGR_ANGLE: the rotation angle in degrees (0 = horizontal, counter-clock-wise oriented)
+<li>OGR_FONT_SIZE: the value of the HEI attribute multiplied by the value of the configuration option OGR_EDIGEO_FONT_SIZE_FACTOR that defaults to 2.
+</ul>
+
+Combined with the FON (font family) attributes, they can be used to define the styling in QGIS for example.<p>
+
+By default, OGR will create specific layers (xxx_LABEL) to dispatch into the various labels of the ID_S_OBJ_Z_1_2_2 layer
+according to the value of xxx=OBJ_OBJ_LNK_LAYER. This can be disabled by setting OGR_EDIGEO_CREATE_LABEL_LAYERS to NO.<p>
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="http://georezo.net/wiki/main/donnees/edigeo">Introduction to the EDIGEO standard</a> (in French)
+<li> <a href="http://georezo.net/wiki/_media/main/geomatique/norme_edigeo.zip">EDIGEO standard - AFNOR NF Z 52000</a> (in French)
+<li> <a href="http://www.craig.fr/contenu/ressources/dossiers/pci/pdf/EDIGeO_PCI.pdf">Standard d'échange des objets du PCI selon la norme EDIGEO</a> (in French)
+<li> <a href="http://www.cadastre.gouv.fr">Homepage of the French Digital Cadastral Plan</a> (in French)
+<li> <a href="http://docs.codehaus.org/pages/viewpage.action?pageId=77692976">Geotools EDIGEO module description</a> (in English)
+<li> <a href="http://svn.geotools.org/trunk/modules/unsupported/edigeo/src/test/resources/org/geotools/data/edigeo/test-data/">Sample of EDIGEO data</a>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/edigeo/makefile.vc b/ogr/ogrsf_frmts/edigeo/makefile.vc
new file mode 100644
index 0000000..9921bb7
--- /dev/null
+++ b/ogr/ogrsf_frmts/edigeo/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogredigeodriver.obj ogredigeodatasource.obj ogredigeolayer.obj
+EXTRAFLAGS =	-I.. -I..\..
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
new file mode 100644
index 0000000..a7254c4
--- /dev/null
+++ b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
@@ -0,0 +1,261 @@
+/******************************************************************************
+ * $Id: ogr_edigeo.h 23423 2011-11-26 18:40:30Z 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>
+ *
+ * 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_EDIGEO_H_INCLUDED
+#define _OGR_EDIGEO_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include <vector>
+#include <map>
+#include <set>
+
+/************************************************************************/
+/*                           OGREDIGEOLayer                             */
+/************************************************************************/
+
+class OGREDIGEODataSource;
+
+class OGREDIGEOLayer : public OGRLayer
+{
+    OGREDIGEODataSource* poDS;
+
+    OGRFeatureDefn*    poFeatureDefn;
+    OGRSpatialReference *poSRS;
+
+    int                nNextFID;
+
+    OGRFeature *       GetNextRawFeature();
+
+    std::vector<OGRFeature*> aosFeatures;
+
+    /* Map attribute RID ('TEX2_id') to its index in the OGRFeatureDefn */
+    std::map<CPLString, int> mapAttributeToIndex;
+
+  public:
+                        OGREDIGEOLayer(OGREDIGEODataSource* poDS,
+                                       const char* pszName, OGRwkbGeometryType eType,
+                                       OGRSpatialReference* poSRS);
+                        ~OGREDIGEOLayer();
+
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeature *        GetFeature(long nFID);
+    virtual int                 GetFeatureCount( int bForce );
+
+    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    virtual int                 TestCapability( const char * );
+
+    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
+
+    virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
+
+
+    void                        AddFeature(OGRFeature* poFeature);
+
+    int                         GetAttributeIndex(const CPLString& osRID);
+    void                        AddFieldDefn(const CPLString& osName, OGRFieldType eType,
+                                             const CPLString& osRID);
+};
+
+/************************************************************************/
+/*                         OGREDIGEODataSource                          */
+/************************************************************************/
+
+typedef std::pair<int, int> intintType;
+typedef std::pair<double, double> xyPairType;
+typedef std::vector< xyPairType > xyPairListType;
+typedef std::pair<CPLString, CPLString> strstrType;
+typedef std::vector<CPLString> strListType;
+
+/* From the .DIC file */
+class OGREDIGEOAttributeDef
+{
+    public:
+        OGREDIGEOAttributeDef() {}
+
+        CPLString osLAB; /* e.g. TEX2 */
+        CPLString osTYP; /* e.g. T */
+};
+
+/* From the .SCD file */
+class OGREDIGEOObjectDescriptor
+{
+    public:
+        OGREDIGEOObjectDescriptor() {}
+
+        CPLString osRID;        /* e.g. BATIMENT_id */
+        CPLString osNameRID;    /* e.g. ID_N_OBJ_E_2_1_0 */
+        CPLString osKND;        /* e.g. ARE */
+        strListType aosAttrRID; /* e.g. DUR_id, TEX_id */
+};
+
+/* From the .SCD file */
+class OGREDIGEOAttributeDescriptor
+{
+    public:
+        OGREDIGEOAttributeDescriptor() {}
+
+        CPLString osRID;        /* e.g. TEX2_id */
+        CPLString osNameRID;    /* e.g. ID_N_ATT_TEX2 */
+        int nWidth;             /* e.g. 80 */
+};
+
+/* From the .VEC files */
+class OGREDIGEOFEADesc
+{
+    public:
+        OGREDIGEOFEADesc() {}
+
+        std::vector< strstrType > aosAttIdVal; /* e.g. (TEX2_id,BECHEREL),(IDU_id,022) */
+        CPLString osSCP;                       /* e.g. COMMUNE_id */
+        CPLString osQUP_RID;                   /* e.g. Actualite_Objet_X */
+};
+
+class OGREDIGEODataSource : public OGRDataSource
+{
+    friend class OGREDIGEOLayer;
+
+    char*               pszName;
+    VSILFILE*           fpTHF;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+    VSILFILE*           OpenFile(const char *pszType,
+                                 const CPLString& osExt);
+
+    CPLString osLON; /* Nom du lot */
+    CPLString osGNN; /* Nom du sous-ensemble de données générales */
+    CPLString osGON; /* Nom du sous-ensemble de la référence de coordonnées */
+    CPLString osQAN; /* Nom du sous-ensemble de qualité */
+    CPLString osDIN; /* Nom du sous-ensemble de définition de la nomenclature */
+    CPLString osSCN; /* Nom du sous-ensemble de définition du SCD */
+    strListType aosGDN; /* Nom du sous-ensemble de données géographiques */
+    int                 ReadTHF(VSILFILE* fp);
+
+    CPLString           osREL;
+    OGRSpatialReference* poSRS;
+    int                 ReadGEO();
+
+    /* Map from ID_N_OBJ_E_2_1_0 to OBJ_E_2_1_0 */
+    std::map<CPLString,CPLString> mapObjects;
+
+    /* Map from ID_N_ATT_TEX2 to (osLAB=TEX2, osTYP=T) */
+    std::map<CPLString,OGREDIGEOAttributeDef> mapAttributes;
+    int                 ReadDIC();
+
+    std::vector<OGREDIGEOObjectDescriptor> aoObjList;
+    /* Map from TEX2_id to (osNameRID=ID_N_ATT_TEX2, nWidth=80) */
+    std::map<CPLString,OGREDIGEOAttributeDescriptor> mapAttributesSCD;
+    int                 ReadSCD();
+
+    int                 bExtentValid;
+    double              dfMinX;
+    double              dfMinY;
+    double              dfMaxX;
+    double              dfMaxY;
+    int                 ReadGEN();
+
+    /* Map from Actualite_Objet_X to (creationData, updateData) */
+    std::map<CPLString,intintType> mapQAL;
+    int                 ReadQAL();
+
+    std::map<CPLString, OGREDIGEOLayer*> mapLayer;
+
+    int                 CreateLayerFromObjectDesc(const OGREDIGEOObjectDescriptor& objDesc);
+
+    std::map< CPLString, xyPairType >                 mapPNO; /* Map Noeud_X to (x,y) */
+    std::map< CPLString, xyPairListType >             mapPAR; /* Map Arc_X to ((x1,y1),...(xn,yn)) */
+    std::map< CPLString, OGREDIGEOFEADesc >           mapFEA; /* Map Object_X to FEADesc */
+    std::map< CPLString, strListType >                mapPFE_PAR; /* Map Face_X to (Arc_X1,..Arc_Xn) */
+    std::vector< strstrType >                         listFEA_PFE; /* List of (Object_X,Face_Y) */
+    std::vector< std::pair<CPLString, strListType > > listFEA_PAR; /* List of (Object_X,(Arc_Y1,..Arc_Yn))) */
+    std::vector< strstrType >                         listFEA_PNO; /* List of (Object_X,Noeud_Y) */
+    std::map< CPLString, CPLString>                   mapFEA_FEA; /* Map Attribut_TEX{X}_id_Objet_{Y} to Objet_Y */
+
+    int                 bRecodeToUTF8;
+    int                 bHasUTF8ContentOnly;
+
+    int                 ReadVEC(const char* pszVECName);
+
+    OGRFeature*         CreateFeature(const CPLString& osFEA);
+    int                 BuildPoints();
+    int                 BuildLineStrings();
+    int                 BuildPolygon(const CPLString& osFEA,
+                                     const CPLString& osPFE);
+    int                 BuildPolygons();
+
+    int                 iATR, iDI3, iDI4, iHEI, iFON;
+    int                 iATR_VAL, iANGLE, iSIZE, iOBJ_LNK, iOBJ_LNK_LAYER;
+    double              dfSizeFactor;
+    int                 bIncludeFontFamily;
+    int                 SetStyle(const CPLString& osFEA,
+                                 OGRFeature* poFeature);
+
+    std::set< CPLString >  setLayersWithLabels;
+    void                CreateLabelLayers();
+
+    int                 bHasReadEDIGEO;
+    void                ReadEDIGEO();
+
+  public:
+                        OGREDIGEODataSource();
+                        ~OGREDIGEODataSource();
+
+    int                 Open( const char * pszFilename,
+                              int bUpdate );
+
+    virtual const char*         GetName() { return pszName; }
+
+    virtual int                 GetLayerCount();
+    virtual OGRLayer*           GetLayer( int );
+
+    virtual int                 TestCapability( const char * );
+
+    int                         HasUTF8ContentOnly() { return bHasUTF8ContentOnly; }
+};
+
+/************************************************************************/
+/*                           OGREDIGEODriver                            */
+/************************************************************************/
+
+class OGREDIGEODriver : public OGRSFDriver
+{
+  public:
+                ~OGREDIGEODriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual int                 TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_EDIGEO_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
new file mode 100644
index 0000000..037cbd3
--- /dev/null
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
@@ -0,0 +1,1572 @@
+/******************************************************************************
+ * $Id: ogredigeodatasource.cpp 23423 2011-11-26 18:40:30Z 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>
+ *
+ * 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_edigeo.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogredigeodatasource.cpp 23423 2011-11-26 18:40:30Z rouault $");
+
+#ifndef M_PI
+# define M_PI  3.1415926535897932384626433832795
+#endif
+
+/************************************************************************/
+/*                        OGREDIGEODataSource()                         */
+/************************************************************************/
+
+OGREDIGEODataSource::OGREDIGEODataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+    poSRS = NULL;
+
+    bExtentValid = FALSE;
+    dfMinX = dfMinY = dfMaxX = dfMaxY = 0;
+
+    fpTHF = NULL;
+    bHasReadEDIGEO = FALSE;
+
+    bIncludeFontFamily = CSLTestBoolean(CPLGetConfigOption(
+                                 "OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES"));
+
+    iATR = iDI3 = iDI4 = iHEI = iFON = -1;
+    iATR_VAL = iANGLE = iSIZE = iOBJ_LNK = iOBJ_LNK_LAYER = -1;
+    dfSizeFactor = atof(CPLGetConfigOption("OGR_EDIGEO_FONT_SIZE_FACTOR", "2"));
+    if (dfSizeFactor <= 0 || dfSizeFactor >= 100)
+        dfSizeFactor = 2;
+
+    bRecodeToUTF8 = CSLTestBoolean(CPLGetConfigOption(
+                                        "OGR_EDIGEO_RECODE_TO_UTF8", "YES"));
+    bHasUTF8ContentOnly = TRUE;
+}
+
+/************************************************************************/
+/*                      ~OGREDIGEODataSource()                          */
+/************************************************************************/
+
+OGREDIGEODataSource::~OGREDIGEODataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    CPLFree( pszName );
+
+    if (fpTHF)
+        VSIFCloseL(fpTHF);
+
+    if (poSRS)
+        poSRS->Release();
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGREDIGEODataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGREDIGEODataSource::GetLayer( int iLayer )
+
+{
+    ReadEDIGEO();
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                         GetLayerCount()                              */
+/************************************************************************/
+
+int OGREDIGEODataSource::GetLayerCount()
+{
+    ReadEDIGEO();
+    return nLayers;
+}
+
+/************************************************************************/
+/*                              ReadTHF()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
+{
+    const char* pszLine;
+    while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
+    {
+        if (strlen(pszLine) < 8 || pszLine[7] != ':')
+            continue;
+
+        /* Cf Z 52000 tableau 56 for field list*/
+
+        if (strncmp(pszLine, "LONSA", 5) == 0)
+        {
+            if (osLON.size() != 0)
+            {
+                CPLDebug("EDIGEO", "We only handle one lot per THF file");
+                break;
+            }
+            osLON = pszLine + 8;
+        }
+        else if (strncmp(pszLine, "GNNSA", 5) == 0)
+            osGNN = pszLine + 8;
+        else if (strncmp(pszLine, "GONSA", 5) == 0)
+            osGON = pszLine + 8;
+        else if (strncmp(pszLine, "QANSA", 5) == 0)
+            osQAN = pszLine + 8;
+        else if (strncmp(pszLine, "DINSA", 5) == 0)
+            osDIN = pszLine + 8;
+        else if (strncmp(pszLine, "SCNSA", 5) == 0)
+            osSCN = pszLine + 8;
+        else if (strncmp(pszLine, "GDNSA", 5) == 0)
+            aosGDN.push_back(pszLine + 8);
+    }
+    if (osLON.size() == 0)
+    {
+        CPLDebug("EDIGEO", "LON field missing");
+        return 0;
+    }
+    if (osGON.size() == 0)
+    {
+        CPLDebug("EDIGEO", "GON field missing");
+        return 0;
+    }
+    if (osDIN.size() == 0)
+    {
+        CPLDebug("EDIGEO", "DIN field missing");
+        return 0;
+    }
+    if (osSCN.size() == 0)
+    {
+        CPLDebug("EDIGEO", "SCN field missing");
+        return FALSE;
+    }
+
+    CPLDebug("EDIGEO", "LON = %s", osLON.c_str());
+    CPLDebug("EDIGEO", "GNN = %s", osGNN.c_str());
+    CPLDebug("EDIGEO", "GON = %s", osGON.c_str());
+    CPLDebug("EDIGEO", "QAN = %s", osQAN.c_str());
+    CPLDebug("EDIGEO", "DIN = %s", osDIN.c_str());
+    CPLDebug("EDIGEO", "SCN = %s", osSCN.c_str());
+    for(int i=0;i<(int)aosGDN.size();i++)
+        CPLDebug("EDIGEO", "GDN[%d] = %s", i, aosGDN[i].c_str());
+    
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                             OpenFile()                               */
+/************************************************************************/
+
+VSILFILE* OGREDIGEODataSource::OpenFile(const char *pszType,
+                                        const CPLString& osExt)
+{
+    CPLString osTmp = osLON + pszType;
+    CPLString osFilename = CPLFormCIFilename(CPLGetPath(pszName),
+                                             osTmp.c_str(), osExt.c_str());
+    VSILFILE* fp = VSIFOpenL(osFilename, "rb");
+    if (fp == NULL)
+    {
+        CPLString osExtLower = osExt;
+        for(int i=0;i<(int)osExt.size();i++)
+            osExtLower[i] = (char)tolower(osExt[i]);
+        CPLString osFilename2 = CPLFormCIFilename(CPLGetPath(pszName),
+                                             osTmp.c_str(), osExtLower.c_str());
+        fp = VSIFOpenL(osFilename2, "rb");
+        if (fp == NULL)
+        {
+            CPLDebug("EDIGEO", "Cannot open %s", osFilename.c_str());
+        }
+    }
+    return fp;
+}
+
+/************************************************************************/
+/*                              ReadGEO()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::ReadGEO()
+{
+    VSILFILE* fp = OpenFile(osGON, "GEO");
+    if (fp == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
+    {
+        if (strlen(pszLine) < 8 || pszLine[7] != ':')
+            continue;
+
+        if (strncmp(pszLine, "RELSA", 5) == 0)
+        {
+            osREL = pszLine + 8;
+            CPLDebug("EDIGEO", "REL = %s", osREL.c_str());
+            break;
+        }
+    }
+
+    VSIFCloseL(fp);
+
+    if (osREL.size() == 0)
+    {
+        CPLDebug("EDIGEO", "REL field missing");
+        return FALSE;
+    }
+
+    /* All the SRS names mentionned in B.8.2.3 and B.8.3.1 are in the IGN file */
+    poSRS = new OGRSpatialReference();
+    CPLString osProj4Str = "+init=IGNF:" + osREL;
+    if (poSRS->SetFromUserInput(osProj4Str.c_str()) != OGRERR_NONE)
+    {
+        /* Hard code a few common cases */
+        if (osREL == "LAMB1")
+            poSRS->importFromProj4("+proj=lcc +lat_1=49.5 +lat_0=49.5 +lon_0=0 +k_0=0.99987734 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
+        else if (osREL == "LAMB2")
+            poSRS->importFromProj4("+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
+        else if (osREL == "LAMB3")
+            poSRS->importFromProj4("+proj=lcc +lat_1=44.1 +lat_0=44.1 +lon_0=0 +k_0=0.9998775 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
+        else if (osREL == "LAMB4")
+            poSRS->importFromProj4("+proj=lcc +lat_1=42.165 +lat_0=42.165 +lon_0=0 +k_0=0.99994471 +x_0=234.358 +y_0=185861.369 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs");
+        else if (osREL == "LAMB93")
+            poSRS->importFromProj4("+proj=lcc +lat_1=44 +lat_2=49 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS81 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
+        else
+        {
+            CPLDebug("EDIGEO", "Cannot resolve %s SRS. Check that the IGNF file is in the directory of PROJ.4 ressource files", osREL.c_str());
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+    
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              ReadGEN()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::ReadGEN()
+{
+    VSILFILE* fp = OpenFile(osGNN, "GEN");
+    if (fp == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    CPLString osCM1, osCM2;
+    while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
+    {
+        if (strlen(pszLine) < 8 || pszLine[7] != ':')
+            continue;
+
+        if (strncmp(pszLine, "CM1CC", 5) == 0)
+        {
+            osCM1 = pszLine + 8;
+        }
+        else if (strncmp(pszLine, "CM2CC", 5) == 0)
+        {
+            osCM2 = pszLine + 8;
+        }
+    }
+
+    VSIFCloseL(fp);
+
+    if (osCM1.size() == 0 || osCM2.size() == 0)
+        return FALSE;
+
+    char** papszTokens1 = CSLTokenizeString2(osCM1.c_str(), ";", 0);
+    char** papszTokens2 = CSLTokenizeString2(osCM2.c_str(), ";", 0);
+    if (CSLCount(papszTokens1) == 2 && CSLCount(papszTokens2) == 2)
+    {
+        bExtentValid = TRUE;
+        dfMinX = atof(papszTokens1[0]);
+        dfMinY = atof(papszTokens1[1]);
+        dfMaxX = atof(papszTokens2[0]);
+        dfMaxY = atof(papszTokens2[1]);
+    }
+    CSLDestroy(papszTokens1);
+    CSLDestroy(papszTokens2);
+
+    return bExtentValid;
+}
+
+/************************************************************************/
+/*                              ReadDIC()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::ReadDIC()
+{
+    VSILFILE* fp = OpenFile(osDIN, "DIC");
+    if (fp == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    CPLString osRTY, osRID, osLAB, osTYP;
+    while(TRUE)
+    {
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+        if (pszLine != NULL)
+        {
+            if (strlen(pszLine) < 8 || pszLine[7] != ':')
+                continue;
+        }
+
+        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        {
+            if (osRTY == "DID")
+            {
+                //CPLDebug("EDIGEO", "Object %s = %s",
+                //         osRID.c_str(), osLAB.c_str());
+                mapObjects[osRID] = osLAB;
+            }
+            else if (osRTY == "DIA")
+            {
+                //CPLDebug("EDIGEO", "Attribute %s = %s, %s",
+                //         osRID.c_str(), osLAB.c_str(), osTYP.c_str());
+                OGREDIGEOAttributeDef sAttributeDef;
+                sAttributeDef.osLAB = osLAB;
+                sAttributeDef.osTYP = osTYP;
+                mapAttributes[osRID] = sAttributeDef;
+            }
+            if (pszLine == NULL)
+                break;
+            osRTY = pszLine + 8;
+            osRID = "";
+            osLAB = "";
+            osTYP = "";
+        }
+        if (strncmp(pszLine, "RIDSA", 5) == 0)
+            osRID = pszLine + 8;
+        else if (strncmp(pszLine, "LABSA", 5) == 0)
+            osLAB = pszLine + 8;
+        else if (strncmp(pszLine, "TYPSA", 5) == 0)
+            osTYP = pszLine + 8;
+    }
+
+    VSIFCloseL(fp);
+
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              ReadSCD()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::ReadSCD()
+{
+    VSILFILE* fp = OpenFile(osSCN, "SCD");
+    if (fp == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    CPLString osRTY, osRID, osNameRID, osKND;
+    strListType aosAttrRID;
+    int nWidth = 0;
+    while(TRUE)
+    {
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+        if (pszLine != NULL)
+        {
+            if (strlen(pszLine) < 8 || pszLine[7] != ':')
+                continue;
+        }
+
+        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        {
+            if (osRTY == "OBJ")
+            {
+                if (mapObjects.find(osNameRID) == mapObjects.end())
+                {
+                    CPLDebug("EDIGEO", "Cannot find object %s",
+                             osNameRID.c_str());
+                }
+                else
+                {
+                    OGREDIGEOObjectDescriptor objDesc;
+                    objDesc.osRID = osRID;
+                    objDesc.osNameRID = osNameRID;
+                    objDesc.osKND = osKND;
+                    objDesc.aosAttrRID = aosAttrRID;
+                    /*CPLDebug("EDIGEO", "Object %s = %s, %s, %d attributes",
+                            osRID.c_str(), osNameRID.c_str(), osKND.c_str(),
+                            (int)aosAttrRID.size());*/
+
+                    aoObjList.push_back(objDesc);
+                }
+            }
+            else if (osRTY == "ATT")
+            {
+                if (mapAttributes.find(osNameRID) == mapAttributes.end())
+                {
+                    CPLDebug("EDIGEO", "Cannot find attribute %s",
+                             osNameRID.c_str());
+                }
+                else
+                {
+                    OGREDIGEOAttributeDescriptor attDesc;
+                    attDesc.osRID = osRID;
+                    attDesc.osNameRID = osNameRID;
+                    attDesc.nWidth = nWidth;
+                    /*CPLDebug("EDIGEO", "Attribute %s = %s, %d",
+                            osRID.c_str(), osNameRID.c_str(), nWidth);*/
+
+                    mapAttributesSCD[osRID] = attDesc;
+                }
+            }
+            if (pszLine == NULL)
+                break;
+            osRTY = pszLine + 8;
+            osRID = "";
+            osNameRID = "";
+            osKND = "";
+            aosAttrRID.resize(0);
+            nWidth = 0;
+        }
+        if (strncmp(pszLine, "RIDSA", 5) == 0)
+            osRID = pszLine + 8;
+        else if (strncmp(pszLine, "DIPCP", 5) == 0)
+        {
+            const char* pszDIP = pszLine + 8;
+            char** papszTokens = CSLTokenizeString2(pszDIP, ";", 0);
+            if (CSLCount(papszTokens) == 4)
+            {
+                osNameRID = papszTokens[3];
+            }
+            CSLDestroy(papszTokens);
+        }
+        else if (strncmp(pszLine, "KNDSA", 5) == 0)
+            osKND = pszLine + 8;
+        else if (strncmp(pszLine, "AAPCP", 5) == 0)
+        {
+            const char* pszAAP = pszLine + 8;
+            char** papszTokens = CSLTokenizeString2(pszAAP, ";", 0);
+            if (CSLCount(papszTokens) == 4)
+            {
+                const char* pszAttRID = papszTokens[3];
+                aosAttrRID.push_back(pszAttRID);
+            }
+            CSLDestroy(papszTokens);
+        }
+        else if (strncmp(pszLine, "CANSN", 5) == 0)
+            nWidth = atoi(pszLine + 8);
+    }
+
+    VSIFCloseL(fp);
+
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              ReadQAL()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::ReadQAL()
+{
+    VSILFILE* fp = OpenFile(osQAN, "QAL");
+    if (fp == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    CPLString osRTY, osRID;
+    int nODA = 0, nUDA = 0;
+    while(TRUE)
+    {
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+        if (pszLine != NULL)
+        {
+            if (strlen(pszLine) < 8 || pszLine[7] != ':')
+                continue;
+        }
+
+        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        {
+            if (osRTY == "QUP")
+            {
+                mapQAL[osRID] = intintType(nODA, nUDA);
+            }
+            if (pszLine == NULL)
+                break;
+            osRTY = pszLine + 8;
+            osRID = "";
+            nODA = 0;
+            nUDA = 0;
+        }
+        else if (strncmp(pszLine, "RIDSA", 5) == 0)
+            osRID = pszLine + 8;
+        else if (strncmp(pszLine, "ODASD", 5) == 0)
+            nODA = atoi(pszLine + 8);
+        else if (strncmp(pszLine, "UDASD", 5) == 0)
+            nUDA = atoi(pszLine + 8);
+    }
+
+    VSIFCloseL(fp);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                       CreateLayerFromObjectDesc()                    */
+/************************************************************************/
+
+int OGREDIGEODataSource::CreateLayerFromObjectDesc(const OGREDIGEOObjectDescriptor& objDesc)
+{
+    OGRwkbGeometryType eType = wkbUnknown;
+    if (objDesc.osKND == "ARE")
+        eType = wkbPolygon;
+    else if (objDesc.osKND == "LIN")
+        eType = wkbLineString;
+    else if (objDesc.osKND == "PCT")
+        eType = wkbPoint;
+    else
+    {
+        CPLDebug("EDIGEO", "Unknown KND : %s", objDesc.osKND.c_str());
+        return FALSE;
+    }
+
+    const char* pszLayerName = objDesc.osRID.c_str();
+        //mapObjects.find(objDesc.osNameRID)->second.c_str();
+    OGREDIGEOLayer* poLayer = new OGREDIGEOLayer(this, pszLayerName,
+                                                    eType, poSRS);
+
+    poLayer->AddFieldDefn("OBJECT_RID", OFTString, "");
+
+    for(int j=0;j<(int)objDesc.aosAttrRID.size();j++)
+    {
+        std::map<CPLString,OGREDIGEOAttributeDescriptor>::iterator it =
+            mapAttributesSCD.find(objDesc.aosAttrRID[j]);
+        if (it != mapAttributesSCD.end())
+        {
+            const OGREDIGEOAttributeDescriptor& attrDesc = it->second;
+            const OGREDIGEOAttributeDef& attrDef =
+                                    mapAttributes[attrDesc.osNameRID];
+            OGRFieldType eType = OFTString;
+            if (attrDef.osTYP == "R" || attrDef.osTYP == "E")
+                eType = OFTReal;
+            else if (attrDef.osTYP == "I" || attrDef.osTYP == "N")
+                eType = OFTInteger;
+
+            poLayer->AddFieldDefn(attrDef.osLAB, eType, objDesc.aosAttrRID[j]);
+        }
+    }
+
+
+    if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") == 0)
+    {
+        OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
+
+        iATR = poFDefn->GetFieldIndex("ATR");
+        iDI3 = poFDefn->GetFieldIndex("DI3");
+        iDI4 = poFDefn->GetFieldIndex("DI4");
+        iHEI = poFDefn->GetFieldIndex("HEI");
+        iFON = poFDefn->GetFieldIndex("FON");
+
+        poLayer->AddFieldDefn("OGR_OBJ_LNK", OFTString, "");
+        iOBJ_LNK = poFDefn->GetFieldIndex("OGR_OBJ_LNK");
+
+        poLayer->AddFieldDefn("OGR_OBJ_LNK_LAYER", OFTString, "");
+        iOBJ_LNK_LAYER = poFDefn->GetFieldIndex("OGR_OBJ_LNK_LAYER");
+
+        poLayer->AddFieldDefn("OGR_ATR_VAL", OFTString, "");
+        iATR_VAL = poFDefn->GetFieldIndex("OGR_ATR_VAL");
+
+        poLayer->AddFieldDefn("OGR_ANGLE", OFTReal, "");
+        iANGLE = poFDefn->GetFieldIndex("OGR_ANGLE");
+
+        poLayer->AddFieldDefn("OGR_FONT_SIZE", OFTReal, "");
+        iSIZE = poFDefn->GetFieldIndex("OGR_FONT_SIZE");
+    }
+    else if (mapQAL.size() != 0)
+    {
+        poLayer->AddFieldDefn("CREAT_DATE", OFTInteger, "");
+        poLayer->AddFieldDefn("UPDATE_DATE", OFTInteger, "");
+    }
+
+    mapLayer[objDesc.osRID] = poLayer;
+
+    papoLayers = (OGRLayer**)
+        CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers] = poLayer;
+    nLayers ++;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              ReadVEC()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::ReadVEC(const char* pszVECName)
+{
+    VSILFILE* fp = OpenFile(pszVECName, "VEC");
+    if (fp == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    CPLString osRTY, osRID;
+    xyPairListType aXY;
+    CPLString osLnkStartType, osLnkStartName, osLnkEndType, osLnkEndName;
+    strListType osLnkEndNameList;
+    CPLString osAttId;
+    std::vector< strstrType > aosAttIdVal;
+    CPLString osSCP;
+    CPLString osQUP_RID;
+    int bIso8859_1 = FALSE;
+
+    while(TRUE)
+    {
+        pszLine = CPLReadLine2L(fp, 81, NULL);
+skip_read_next_line:
+        if (pszLine != NULL)
+        {
+            if (strlen(pszLine) < 8 || pszLine[7] != ':')
+                continue;
+        }
+
+        if (pszLine == NULL || strncmp(pszLine, "RTYSA", 5) == 0)
+        {
+            if (osRTY == "PAR")
+            {
+                if (aXY.size() < 2)
+                    CPLDebug("EDIGEO", "Error: ARC %s has not enough points",
+                                    osRID.c_str());
+                else
+                    mapPAR[osRID] = aXY;
+            }
+            else if (osRTY == "LNK")
+            {
+                if (osLnkStartType == "PAR" && osLnkEndType == "PFE")
+                {
+                    /*CPLDebug("EDIGEO", "PFE[%s] -> PAR[%s]",
+                             osLnkEndName.c_str(), osLnkStartName.c_str());*/
+                    if (mapPFE_PAR.find(osLnkEndName) == mapPFE_PAR.end())
+                        mapPFE_PAR[osLnkEndName].push_back(osLnkStartName);
+                    else
+                    {
+                        int bAlreadyExists = FALSE;
+                        strListType& osPARList = mapPFE_PAR[osLnkEndName];
+                        for(int j=0;j<(int)osPARList.size();j++)
+                        {
+                            if (osPARList[j] == osLnkStartName)
+                                bAlreadyExists = TRUE;
+                        }
+                        if (!bAlreadyExists)
+                            osPARList.push_back(osLnkStartName);
+                    }
+                }
+                else if (osLnkStartType == "FEA" && osLnkEndType == "PFE")
+                {
+                    /*CPLDebug("EDIGEO", "FEA[%s] -> PFE[%s]",
+                             osLnkStartName.c_str(), osLnkEndName.c_str());*/
+                    listFEA_PFE.push_back(strstrType
+                                               (osLnkStartName, osLnkEndName));
+                }
+                else if (osLnkStartType == "FEA" && osLnkEndType == "PAR")
+                {
+                    /*CPLDebug("EDIGEO", "FEA[%s] -> PAR[%s]",
+                             osLnkStartName.c_str(), osLnkEndName.c_str());*/
+                    listFEA_PAR.push_back(std::pair<CPLString, strListType >
+                                                (osLnkStartName, osLnkEndNameList));
+                }
+                else if (osLnkStartType == "FEA" && osLnkEndType == "PNO")
+                {
+                    /*CPLDebug("EDIGEO", "FEA[%s] -> PNO[%s]",
+                             osLnkStartName.c_str(), osLnkEndName.c_str());*/
+                    listFEA_PNO.push_back(strstrType
+                                                (osLnkStartName, osLnkEndName));
+                }
+                else if (osLnkStartType == "FEA" && osLnkEndType == "FEA")
+                {
+                    /*CPLDebug("EDIGEO", "FEA[%s] -> FEA[%s]",
+                             osLnkStartName.c_str(), osLnkEndName.c_str());*/
+                    if (osSCP == "IS_S_REL_IWW")
+                        mapFEA_FEA[osLnkStartName] = osLnkEndName;
+                }
+                else if (osLnkStartType == "PAR" && osLnkEndType == "PNO")
+                {
+                }
+                else
+                {
+                    CPLDebug("EDIGEO", "Unhandled LNK(%s) %s=%s --> %s=%s",
+                             osRID.c_str(),
+                             osLnkStartType.c_str(), osLnkStartName.c_str(),
+                             osLnkEndType.c_str(), osLnkEndName.c_str());
+                }
+            }
+            else if (osRTY == "FEA")
+            {
+                OGREDIGEOFEADesc feaDesc;
+                feaDesc.aosAttIdVal = aosAttIdVal;
+                feaDesc.osSCP = osSCP;
+                feaDesc.osQUP_RID = osQUP_RID;
+                mapFEA[osRID] = feaDesc;
+            }
+            else if (osRTY == "PNO")
+            {
+                if (aXY.size() == 1)
+                {
+                    /*CPLDebug("EDIGEO", "PNO[%s] = %f, %f",
+                             osRID.c_str(), aXY[0].first, aXY[0].second);*/
+                    mapPNO[osRID] = aXY[0];
+                }
+            }
+            if (pszLine == NULL)
+                break;
+            osRTY = pszLine + 8;
+            osRID = "";
+            aXY.resize(0);
+            osLnkStartType = "";
+            osLnkStartName = "";
+            osLnkEndType = "";
+            osLnkEndName = "";
+            osAttId = "";
+            aosAttIdVal.resize(0);
+            osLnkEndNameList.resize(0);
+            osSCP = "";
+            osQUP_RID = "";
+            bIso8859_1 = FALSE;
+        }
+        else if (strncmp(pszLine, "RIDSA", 5) == 0)
+            osRID = pszLine + 8;
+        else if (strncmp(pszLine, "CORCC", 5) == 0)
+        {
+            const char* pszY = strchr(pszLine+8, ';');
+            if (pszY)
+            {
+                double dfX = atof(pszLine + 8);
+                double dfY = atof(pszY + 1);
+                aXY.push_back(xyPairType (dfX, dfY));
+            }
+        }
+        else if (strncmp(pszLine, "FTPCP", 5) == 0)
+        {
+            char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
+            if (CSLCount(papszTokens) == 4)
+            {
+                if (osLnkStartType.size() == 0)
+                {
+                    osLnkStartType = papszTokens[2];
+                    osLnkStartName = papszTokens[3];
+                }
+                else
+                {
+                    osLnkEndType = papszTokens[2];
+                    osLnkEndName = papszTokens[3];
+                    osLnkEndNameList.push_back(osLnkEndName);
+                }
+            }
+            CSLDestroy(papszTokens);
+        }
+        else if (strncmp(pszLine, "SCPCP", 5) == 0)
+        {
+            char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
+            if (CSLCount(papszTokens) == 4)
+            {
+                if (osRTY == "LNK")
+                {
+                    if (strcmp(papszTokens[2], "ASS") == 0)
+                        osSCP = papszTokens[3];
+                }
+                else if (strcmp(papszTokens[2], "OBJ") == 0)
+                    osSCP = papszTokens[3];
+            }
+            CSLDestroy(papszTokens);
+        }
+        else if (strncmp(pszLine, "ATPCP", 5) == 0)
+        {
+            char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
+            if (CSLCount(papszTokens) == 4)
+            {
+                if (strcmp(papszTokens[2], "ATT") == 0)
+                    osAttId = papszTokens[3];
+            }
+            CSLDestroy(papszTokens);
+        }
+        else if (strcmp(pszLine, "TEXT 06:8859-1") == 0)
+        {
+            bIso8859_1 = TRUE;
+        }
+        else if (strncmp(pszLine, "ATVS", 4) == 0)
+        {
+            CPLString osAttVal = pszLine + 8;
+            int bSkipReadNextLine = FALSE;
+            while(TRUE)
+            {
+                pszLine = CPLReadLine2L(fp, 81, NULL);
+                if (pszLine != NULL &&
+                    strlen(pszLine) >= 8 &&
+                    pszLine[7] == ':' &&
+                    strncmp(pszLine, "NEXT ", 5) == 0)
+                {
+                    osAttVal += pszLine + 8;
+                }
+                else
+                {
+                    bSkipReadNextLine = TRUE;
+                    break;
+                }
+            }
+            if (bIso8859_1 && bRecodeToUTF8)
+            {
+                char* pszNewVal = CPLRecode(osAttVal.c_str(),
+                                            CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
+                osAttVal = pszNewVal;
+                CPLFree(pszNewVal);
+            }
+            else if (bHasUTF8ContentOnly)
+            {
+                bHasUTF8ContentOnly = CPLIsUTF8(osAttVal.c_str(), -1);
+            }
+            if (osAttId.size() != 0)
+                aosAttIdVal.push_back( strstrType (osAttId, osAttVal) );
+            osAttId = "";
+            bIso8859_1 = FALSE;
+            if (bSkipReadNextLine)
+                goto skip_read_next_line;
+        }
+        else if (strncmp(pszLine, "ATVCP", 5) == 0)
+        {
+            char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
+            if (CSLCount(papszTokens) == 4)
+            {
+                if (strcmp(papszTokens[2], "ATT") == 0)
+                {
+                    CPLString osAttVal = papszTokens[3];
+                    if (osAttId.size() != 0)
+                        aosAttIdVal.push_back( strstrType (osAttId, osAttVal) );
+                    osAttId = "";
+                }
+            }
+            CSLDestroy(papszTokens);
+        }
+        else if (strncmp(pszLine, "QAPCP", 5) == 0)
+        {
+            char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
+            if (CSLCount(papszTokens) == 4)
+            {
+                if (strcmp(papszTokens[2], "QUP") == 0)
+                {
+                    osQUP_RID = papszTokens[3];
+                }
+            }
+            CSLDestroy(papszTokens);
+        }
+    }
+
+    VSIFCloseL(fp);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        CreateFeature()                               */
+/************************************************************************/
+
+OGRFeature* OGREDIGEODataSource::CreateFeature(const CPLString& osFEA)
+{
+    const std::map< CPLString, OGREDIGEOFEADesc >::iterator itFEA =
+                                                        mapFEA.find(osFEA);
+    if (itFEA == mapFEA.end())
+    {
+        CPLDebug("EDIGEO", "ERROR: Cannot find FEA %s", osFEA.c_str());
+        return NULL;
+    }
+
+    const OGREDIGEOFEADesc& fea = itFEA->second;
+    const std::map<CPLString,OGREDIGEOLayer*>::iterator itLyr =
+                                                    mapLayer.find(fea.osSCP);
+    if (itLyr != mapLayer.end())
+    {
+        OGREDIGEOLayer* poLayer = itLyr->second;
+
+        OGRFeature* poFeature = new OGRFeature(poLayer->GetLayerDefn());
+        poFeature->SetField(0, itFEA->first.c_str());
+        for(int i=0;i<(int)fea.aosAttIdVal.size();i++)
+        {
+            const CPLString& id = fea.aosAttIdVal[i].first;
+            const CPLString& val = fea.aosAttIdVal[i].second;
+            int iIndex = poLayer->GetAttributeIndex(id);
+            if (iIndex != -1)
+                poFeature->SetField(iIndex, val.c_str());
+            else
+                CPLDebug("EDIGEO",
+                         "ERROR: Cannot find attribute %s", id.c_str());
+        }
+
+        if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") != 0 &&
+            mapQAL.size() != 0 && fea.osQUP_RID.size() != 0)
+        {
+            const std::map<CPLString, intintType>::iterator itQAL =
+                                                        mapQAL.find(fea.osQUP_RID);
+            if (itQAL != mapQAL.end())
+            {
+                const intintType& creationUpdateDate = itQAL->second;
+                if (creationUpdateDate.first != 0)
+                    poFeature->SetField("CREAT_DATE", creationUpdateDate.first);
+                if (creationUpdateDate.second != 0)
+                    poFeature->SetField("UPDATE_DATE", creationUpdateDate.second);
+            }
+        }
+
+        poLayer->AddFeature(poFeature);
+
+        return poFeature;
+    }
+    else
+    {
+        CPLDebug("EDIGEO", "ERROR: Cannot find layer %s", fea.osSCP.c_str());
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                             SetStyle()                               */
+/************************************************************************/
+
+int OGREDIGEODataSource::SetStyle(const CPLString& osFEA,
+                                  OGRFeature* poFeature)
+{
+    /* EDIGEO PCI specific */
+    /* See EDIGeO_PCI.pdf, chapter 3 "Principes généraux de */
+    /* positionnement de la toponymie. */
+    const char* pszATR = NULL;
+    if (strcmp(poFeature->GetDefnRef()->GetName(), "ID_S_OBJ_Z_1_2_2") == 0 &&
+        iATR != -1 && (pszATR = poFeature->GetFieldAsString(iATR)) != NULL)
+    {
+        const CPLString osATR = pszATR;
+        std::map< CPLString, CPLString>::iterator itFEA_FEA =
+                                                mapFEA_FEA.find(osFEA);
+        if (itFEA_FEA != mapFEA_FEA.end())
+        {
+            const CPLString& osOBJ_LNK = itFEA_FEA->second;
+            std::map< CPLString, OGREDIGEOFEADesc >::iterator itFEA_LNK =
+                                                        mapFEA.find(osOBJ_LNK);
+            if (itFEA_LNK != mapFEA.end())
+            {
+                const OGREDIGEOFEADesc& fea_lnk = itFEA_LNK->second;
+                for(int j=0;j<(int)fea_lnk.aosAttIdVal.size();j++)
+                {
+                    if (fea_lnk.aosAttIdVal[j].first == osATR)
+                    {
+                        double dfAngle = 0;
+                        if (iDI3 != -1 && iDI4 != -1)
+                        {
+                            double dfBaseVectorX =
+                                poFeature->GetFieldAsDouble(iDI3);
+                            double dfBaseVectorY =
+                                poFeature->GetFieldAsDouble(iDI4);
+                            dfAngle = atan2(dfBaseVectorY, dfBaseVectorX)
+                                                                / M_PI * 180;
+                            if (dfAngle < 0)
+                                dfAngle += 360;
+                        }
+                        double dfSize = 1;
+                        if (iHEI != -1)
+                            dfSize = poFeature->GetFieldAsDouble(iHEI);
+                        if (dfSize <= 0 || dfSize >= 100)
+                            dfSize = 1;
+                        const char* pszFontFamily = NULL;
+                        if (iFON != -1)
+                            pszFontFamily = poFeature->GetFieldAsString(iFON);
+
+                        CPLString osStyle("LABEL(t:\"");
+                        osStyle += fea_lnk.aosAttIdVal[j].second;
+                        osStyle += "\"";
+                        if (dfAngle != 0)
+                        {
+                            osStyle += ",a:";
+                            osStyle += CPLString().Printf("%.1f", dfAngle);
+                        }
+                        if (pszFontFamily != NULL && bIncludeFontFamily)
+                        {
+                            osStyle += ",f:\"";
+                            osStyle += pszFontFamily;
+                            osStyle += "\"";
+                        }
+                        osStyle += ",s:";
+                        osStyle += CPLString().Printf("%.1f", dfSize);
+                        osStyle += ",c:#000000)";
+                        poFeature->SetStyleString(osStyle);
+
+                        poFeature->SetField(iATR_VAL,
+                                            fea_lnk.aosAttIdVal[j].second);
+                        poFeature->SetField(iANGLE, dfAngle);
+                        poFeature->SetField(iSIZE, dfSize * dfSizeFactor);
+                        poFeature->SetField(iOBJ_LNK, osOBJ_LNK);
+                        poFeature->SetField(iOBJ_LNK_LAYER, fea_lnk.osSCP);
+
+                        setLayersWithLabels.insert(fea_lnk.osSCP);
+
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           BuildPoints()                              */
+/************************************************************************/
+
+int OGREDIGEODataSource::BuildPoints()
+{
+    for(int i=0;i<(int)listFEA_PNO.size();i++)
+    {
+        const CPLString& osFEA = listFEA_PNO[i].first;
+        const CPLString& osPNO = listFEA_PNO[i].second;
+        const std::map< CPLString, xyPairType >::iterator itPNO =
+                                                        mapPNO.find(osPNO);
+        if (itPNO == mapPNO.end())
+        {
+            CPLDebug("EDIGEO", "Cannot find PNO %s", osPNO.c_str());
+        }
+        else
+        {
+            OGRFeature* poFeature = CreateFeature(osFEA);
+            if (poFeature)
+            {
+                const xyPairType& pno = itPNO->second;
+                OGRPoint* poPoint = new OGRPoint(pno.first, pno.second);
+                if (poSRS)
+                    poPoint->assignSpatialReference(poSRS);
+                poFeature->SetGeometryDirectly(poPoint);
+
+                SetStyle(osFEA, poFeature);
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        BuildLineStrings()                            */
+/************************************************************************/
+
+int OGREDIGEODataSource::BuildLineStrings()
+{
+    int i, iter;
+
+    for(iter=0;iter<(int)listFEA_PAR.size();iter++)
+    {
+        const CPLString& osFEA = listFEA_PAR[iter].first;
+        const strListType & aosPAR = listFEA_PAR[iter].second;
+        OGRFeature* poFeature = CreateFeature(osFEA);
+        if (poFeature)
+        {
+            OGRMultiLineString* poMulti = NULL;
+            for(int k=0;k<(int)aosPAR.size();k++)
+            {
+                const std::map< CPLString, xyPairListType >::iterator itPAR =
+                                                    mapPAR.find(aosPAR[k]);
+                if (itPAR != mapPAR.end())
+                {
+                    const xyPairListType& arc = itPAR->second;
+
+                    OGRLineString* poLS = new OGRLineString();
+                    poLS->setNumPoints((int)arc.size());
+                    for(i=0;i<(int)arc.size();i++)
+                    {
+                        poLS->setPoint(i, arc[i].first, arc[i].second);
+                    }
+
+                    if (poFeature->GetGeometryRef() != NULL)
+                    {
+                        if (poMulti == NULL)
+                        {
+                            OGRLineString* poPrevLS =
+                                (OGRLineString*) poFeature->StealGeometry();
+                            poMulti = new OGRMultiLineString();
+                            poMulti->addGeometryDirectly(poPrevLS);
+                            poFeature->SetGeometryDirectly(poMulti);
+                        }
+                        poMulti->addGeometryDirectly(poLS);
+                    }
+                    else
+                        poFeature->SetGeometryDirectly(poLS);
+                }
+                else
+                    CPLDebug("EDIGEO",
+                             "ERROR: Cannot find ARC %s", aosPAR[k].c_str());
+            }
+            if (poFeature->GetGeometryRef())
+                poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           BuildPolygon()                             */
+/************************************************************************/
+
+int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
+                                      const CPLString& osPFE)
+{
+    int i;
+
+    const std::map< CPLString, strListType >::iterator itPFE_PAR =
+                                                    mapPFE_PAR.find(osPFE);
+    if (itPFE_PAR == mapPFE_PAR.end())
+    {
+        CPLDebug("EDIGEO", "ERROR: Cannot find PFE %s", osPFE.c_str());
+        return FALSE;
+    }
+
+    const strListType & aosPARList = itPFE_PAR->second;
+
+/* -------------------------------------------------------------------- */
+/*      Resolve arc ids to arc coordinate lists.                        */
+/* -------------------------------------------------------------------- */
+    std::vector< const xyPairListType *> aoPARPtrList;
+    for(i=0;i<(int)aosPARList.size();i++)
+    {
+        const std::map< CPLString, xyPairListType >::iterator itPAR =
+                                            mapPAR.find(aosPARList[i]);
+        if (itPAR != mapPAR.end())
+            aoPARPtrList.push_back(&(itPAR->second));
+        else
+            CPLDebug("EDIGEO",
+                     "ERROR: Cannot find ARC %s", aosPARList[i].c_str());
+    }
+
+    if (aoPARPtrList.size() == 0)
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Now try to chain all arcs together.                             */
+/* -------------------------------------------------------------------- */
+    std::vector<xyPairListType> aoXYList;
+
+    int j;
+    for(j=0;j<(int)aoPARPtrList.size();j++)
+    {
+        if (aoPARPtrList[j] == NULL)
+            continue;
+        const xyPairListType& sFirstRing = *(aoPARPtrList[j]);
+        const xyPairType* psNext = &(sFirstRing[sFirstRing.size()-1]);
+
+        xyPairListType aoXY;
+        for(i=0;i<(int)sFirstRing.size();i++)
+            aoXY.push_back(sFirstRing[i]);
+        aoPARPtrList[j] = NULL;
+
+        int nIter = 1;
+        while(aoXY[aoXY.size()-1] != aoXY[0] && nIter < (int)aoPARPtrList.size())
+        {
+            int bFound = FALSE;
+            int bReverseSecond = FALSE;
+            for(i=0;i<(int)aoPARPtrList.size();i++)
+            {
+                if (aoPARPtrList[i] != NULL)
+                {
+                    const xyPairListType& sSecondRing = *(aoPARPtrList[i]);
+                    if (*psNext == sSecondRing[0])
+                    {
+                        bFound = TRUE;
+                        bReverseSecond = FALSE;
+                        break;
+                    }
+                    else if (*psNext == sSecondRing[sSecondRing.size()-1])
+                    {
+                        bFound = TRUE;
+                        bReverseSecond = TRUE;
+                        break;
+                    }
+                }
+            }
+
+            if (!bFound)
+            {
+                CPLDebug("EDIGEO", "Cannot find ring for FEA %s / PFE %s",
+                        osFEA.c_str(), osPFE.c_str());
+                break;
+            }
+            else
+            {
+                const xyPairListType& secondRing = *(aoPARPtrList[i]);
+                aoPARPtrList[i] = NULL;
+                if (!bReverseSecond)
+                {
+                    for(i=1;i<(int)secondRing.size();i++)
+                        aoXY.push_back(secondRing[i]);
+                    psNext = &secondRing[secondRing.size()-1];
+                }
+                else
+                {
+                    for(i=1;i<(int)secondRing.size();i++)
+                        aoXY.push_back(secondRing[secondRing.size()-1-i]);
+                    psNext = &secondRing[0];
+                }
+            }
+
+            nIter ++;
+        }
+
+        aoXYList.push_back(aoXY);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create feature.                                                 */
+/* -------------------------------------------------------------------- */
+    OGRFeature* poFeature = CreateFeature(osFEA);
+    if (poFeature)
+    {
+        std::vector<OGRGeometry*> aosPolygons;
+        for(j=0;j<(int)aoXYList.size();j++)
+        {
+            const xyPairListType& aoXY = aoXYList[j];
+            OGRLinearRing* poLS = new OGRLinearRing();
+            poLS->setNumPoints((int)aoXY.size());
+            for(i=0;i<(int)aoXY.size();i++)
+                poLS->setPoint(i, aoXY[i].first, aoXY[i].second);
+            poLS->closeRings();
+            OGRPolygon* poPolygon = new OGRPolygon();
+            poPolygon->addRingDirectly(poLS);
+            aosPolygons.push_back(poPolygon);
+        }
+
+        int bIsValidGeometry;
+        OGRGeometry* poGeom = OGRGeometryFactory::organizePolygons(
+            &aosPolygons[0], (int)aosPolygons.size(),
+            &bIsValidGeometry, NULL);
+        if (poGeom)
+        {
+            if (poSRS)
+                poGeom->assignSpatialReference(poSRS);
+            poFeature->SetGeometryDirectly(poGeom);
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          BuildPolygons()                             */
+/************************************************************************/
+
+int OGREDIGEODataSource::BuildPolygons()
+{
+    int iter;
+    for(iter=0;iter<(int)listFEA_PFE.size();iter++)
+    {
+        const CPLString& osFEA = listFEA_PFE[iter].first;
+        const CPLString& osPFE = listFEA_PFE[iter].second;
+        BuildPolygon(osFEA, osPFE);
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                  OGREDIGEOSortForQGIS()                              */
+/************************************************************************/
+
+static int OGREDIGEOSortForQGIS(const void* a, const void* b)
+{
+    OGREDIGEOLayer* poLayerA = *((OGREDIGEOLayer**) a);
+    OGREDIGEOLayer* poLayerB = *((OGREDIGEOLayer**) b);
+    int nTypeA, nTypeB;
+    switch (poLayerA->GetLayerDefn()->GetGeomType())
+    {
+        case wkbPoint: nTypeA = 1; break;
+        case wkbLineString: nTypeA = 2; break;
+        case wkbPolygon: nTypeA = 3; break;
+        default: nTypeA = 4; break;
+    }
+    switch (poLayerB->GetLayerDefn()->GetGeomType())
+    {
+        case wkbPoint: nTypeB = 1; break;
+        case wkbLineString: nTypeB = 2; break;
+        case wkbPolygon: nTypeB = 3; break;
+        default: nTypeB = 4; break;
+    }
+    if (nTypeA == nTypeB)
+    {
+        int nCmp = strcmp(poLayerA->GetName(), poLayerB->GetName());
+        if (nCmp == 0)
+            return 0;
+
+        static const char* apszPolyOrder[] =
+            { "COMMUNE_id", "LIEUDIT_id", "SECTION_id", "SUBDSECT_id",
+              "SUBDFISC_id", "PARCELLE_id", "BATIMENT_id" };
+        for(int i=0;i<(int)(sizeof(apszPolyOrder)/sizeof(char*));i++)
+        {
+            if (strcmp(poLayerA->GetName(), apszPolyOrder[i]) == 0)
+                return -1;
+            if (strcmp(poLayerB->GetName(), apszPolyOrder[i]) == 0)
+                return 1;
+        }
+        return nCmp;
+    }
+    else
+        return nTypeB - nTypeA;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGREDIGEODataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (bUpdateIn)
+    {
+        return FALSE;
+    }
+
+    pszName = CPLStrdup( pszFilename );
+
+/* -------------------------------------------------------------------- */
+/*      Does this appear to be a .THF file?                             */
+/* -------------------------------------------------------------------- */
+    if( !EQUAL(CPLGetExtension(pszFilename), "thf") )
+        return FALSE;
+
+    fpTHF = VSIFOpenL(pszFilename, "rb");
+    if (fpTHF == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    int i = 0;
+    int bIsEDIGEO = FALSE;
+    while(i < 100 && (pszLine = CPLReadLine2L(fpTHF, 81, NULL)) != NULL)
+    {
+        if (strcmp(pszLine, "RTYSA03:GTS") == 0)
+        {
+            bIsEDIGEO = TRUE;
+            break;
+        }
+        i++;
+    }
+
+    if (!bIsEDIGEO)
+    {
+        VSIFCloseL(fpTHF);
+        fpTHF = NULL;
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           ReadEDIGEO()                               */
+/************************************************************************/
+
+void OGREDIGEODataSource::ReadEDIGEO()
+{
+    if (bHasReadEDIGEO)
+        return;
+
+    bHasReadEDIGEO = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Read .THF file                                                  */
+/* -------------------------------------------------------------------- */
+    VSIFSeekL(fpTHF, 0, SEEK_SET);
+    if (!ReadTHF(fpTHF))
+    {
+        VSIFCloseL(fpTHF);
+        fpTHF = NULL;
+        return;
+    }
+    VSIFCloseL(fpTHF);
+    fpTHF = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Read .GEO file                                                  */
+/* -------------------------------------------------------------------- */
+    if (!ReadGEO())
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Read .GEN file                                                  */
+/* -------------------------------------------------------------------- */
+    if (osGNN.size() != 0)
+        ReadGEN();
+
+/* -------------------------------------------------------------------- */
+/*      Read .DIC file                                                  */
+/* -------------------------------------------------------------------- */
+    if (!ReadDIC())
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Read .SCD file                                                  */
+/* -------------------------------------------------------------------- */
+    if (!ReadSCD())
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Read .QAL file                                                  */
+/* -------------------------------------------------------------------- */
+    if (osQAN.size() != 0)
+        ReadQAL();
+
+/* -------------------------------------------------------------------- */
+/*      Create layers from SCD definitions                              */
+/* -------------------------------------------------------------------- */
+    int i;
+    for(i=0;i<(int)aoObjList.size();i++)
+    {
+        CreateLayerFromObjectDesc(aoObjList[i]);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read .VEC files and create features                             */
+/* -------------------------------------------------------------------- */
+    for(i=0;i<(int)aosGDN.size();i++)
+    {
+        ReadVEC(aosGDN[i]);
+
+        BuildPoints();
+        BuildLineStrings();
+        BuildPolygons();
+
+        mapPNO.clear();
+        mapPAR.clear();
+        mapFEA.clear();
+        mapPFE_PAR.clear();
+        listFEA_PFE.clear();
+        listFEA_PAR.clear();
+        listFEA_PNO.clear();
+        mapFEA_FEA.clear();
+    }
+
+    mapObjects.clear();
+    mapAttributes.clear();
+    mapAttributesSCD.clear();
+    mapQAL.clear();
+
+/* -------------------------------------------------------------------- */
+/*      Delete empty layers                                             */
+/* -------------------------------------------------------------------- */
+    for(i=0;i<nLayers;/*nothing*/)
+    {
+        if (papoLayers[i]->GetFeatureCount(TRUE) == 0)
+        {
+            delete papoLayers[i];
+            if (i < nLayers - 1)
+                memmove(papoLayers + i, papoLayers + i + 1,
+                        (nLayers - i - 1) * sizeof(OGREDIGEOLayer*));
+            nLayers --;
+        }
+        else
+            i++;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      When added from QGIS, the layers must be ordered from           */
+/*      bottom (Polygon) to top (Point) to get nice visual effect       */
+/* -------------------------------------------------------------------- */
+    if (CSLTestBoolean(CPLGetConfigOption("OGR_EDIGEO_SORT_FOR_QGIS", "YES")))
+        qsort(papoLayers, nLayers, sizeof(OGREDIGEOLayer*), OGREDIGEOSortForQGIS);
+
+/* -------------------------------------------------------------------- */
+/*      Create a label layer for each feature layer                     */
+/* -------------------------------------------------------------------- */
+    if (CSLTestBoolean(CPLGetConfigOption("OGR_EDIGEO_CREATE_LABEL_LAYERS", "YES")))
+        CreateLabelLayers();
+
+    return;
+}
+
+/************************************************************************/
+/*                         CreateLabelLayers()                          */
+/************************************************************************/
+
+void OGREDIGEODataSource::CreateLabelLayers()
+{
+    OGRLayer* poLayer = GetLayerByName("ID_S_OBJ_Z_1_2_2");
+    if (poLayer == NULL)
+        return;
+
+    std::map<CPLString, OGREDIGEOLayer*> mapLayerNameToLayer;
+
+    OGRFeature* poFeature;
+    OGRFeatureDefn* poFeatureDefn = poLayer->GetLayerDefn();
+    while((poFeature = poLayer->GetNextFeature()) != NULL)
+    {
+        const char* pszBelongingLayerName =
+            poFeature->GetFieldAsString(iOBJ_LNK_LAYER);
+        if (pszBelongingLayerName)
+        {
+            CPLString osBelongingLayerName = pszBelongingLayerName;
+            std::map<CPLString, OGREDIGEOLayer*>::iterator it =
+                        mapLayerNameToLayer.find(osBelongingLayerName);
+            OGREDIGEOLayer* poLabelLayer;
+
+            if (it == mapLayerNameToLayer.end())
+            {
+                /* Create label layer if it does not already exist */
+                CPLString osLayerLabelName = osBelongingLayerName + "_LABEL";
+                poLabelLayer = new OGREDIGEOLayer(this, osLayerLabelName.c_str(),
+                                             wkbPoint, poSRS);
+                int i;
+                OGRFeatureDefn* poLabelFeatureDefn = poLabelLayer->GetLayerDefn();
+                for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+                    poLabelFeatureDefn->AddFieldDefn(poFeatureDefn->GetFieldDefn(i));
+                mapLayerNameToLayer[osBelongingLayerName] = poLabelLayer;
+
+                papoLayers = (OGRLayer**)
+                    CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+                papoLayers[nLayers] = poLabelLayer;
+                nLayers ++;
+            }
+            else
+                poLabelLayer = mapLayerNameToLayer[osBelongingLayerName];
+
+            OGRFeature* poNewFeature = new OGRFeature(poLabelLayer->GetLayerDefn());
+            poNewFeature->SetFrom(poFeature);
+            poLabelLayer->AddFeature(poNewFeature);
+        }
+        delete poFeature;
+    }
+
+    poLayer->ResetReading();
+}
+
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
new file mode 100644
index 0000000..a056b11
--- /dev/null
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
@@ -0,0 +1,95 @@
+/******************************************************************************
+ * $Id: ogredigeodriver.cpp 21630 2011-02-06 13:08:20Z 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>
+ *
+ * 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_edigeo.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogredigeodriver.cpp 21630 2011-02-06 13:08:20Z rouault $");
+
+extern "C" void RegisterOGREDIGEO();
+
+// g++ -fPIC -g -Wall ogr/ogrsf_frmts/edigeo/*.cpp -shared -o ogr_EDIGEO.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/generic -Iogr/ogrsf_frmts/edigeo -L. -lgdal
+
+/************************************************************************/
+/*                         ~OGREDIGEODriver()                           */
+/************************************************************************/
+
+OGREDIGEODriver::~OGREDIGEODriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGREDIGEODriver::GetName()
+
+{
+    return "EDIGEO";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGREDIGEODriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGREDIGEODataSource   *poDS = new OGREDIGEODataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGREDIGEODriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGREDIGEO()                        */
+/************************************************************************/
+
+void RegisterOGREDIGEO()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGREDIGEODriver );
+}
+
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
new file mode 100644
index 0000000..ae511ab
--- /dev/null
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
@@ -0,0 +1,227 @@
+/******************************************************************************
+ * $Id: ogredigeolayer.cpp 22195 2011-04-17 18:21:14Z 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>
+ *
+ * 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_edigeo.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_p.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: ogredigeolayer.cpp 22195 2011-04-17 18:21:14Z rouault $");
+
+/************************************************************************/
+/*                          OGREDIGEOLayer()                            */
+/************************************************************************/
+
+OGREDIGEOLayer::OGREDIGEOLayer( OGREDIGEODataSource* poDS,
+                                const char* pszName, OGRwkbGeometryType eType,
+                                OGRSpatialReference* poSRS )
+
+{
+    this->poDS = poDS;
+    nNextFID = 0;
+
+    this->poSRS = poSRS;
+    if (poSRS)
+        poSRS->Reference();
+
+    poFeatureDefn = new OGRFeatureDefn( pszName );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( eType );
+}
+
+/************************************************************************/
+/*                          ~OGREDIGEOLayer()                           */
+/************************************************************************/
+
+OGREDIGEOLayer::~OGREDIGEOLayer()
+
+{
+    for(int i=0;i<(int)aosFeatures.size();i++)
+        delete aosFeatures[i];
+
+    poFeatureDefn->Release();
+
+    if (poSRS)
+        poSRS->Release();
+}
+
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGREDIGEOLayer::ResetReading()
+
+{
+    nNextFID = 0;
+}
+
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGREDIGEOLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    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 *OGREDIGEOLayer::GetNextRawFeature()
+{
+    if (nNextFID < (int)aosFeatures.size())
+    {
+        OGRFeature* poFeature = aosFeatures[nNextFID]->Clone();
+        nNextFID++;
+        return poFeature;
+    }
+    else
+        return NULL;
+}
+
+/************************************************************************/
+/*                            GetFeature()                              */
+/************************************************************************/
+
+OGRFeature * OGREDIGEOLayer::GetFeature(long nFID)
+{
+    if (nFID >= 0 && nFID < (int)aosFeatures.size())
+        return aosFeatures[nFID]->Clone();
+    else
+        return NULL;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGREDIGEOLayer::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap, OLCFastFeatureCount))
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
+
+    else if (EQUAL(pszCap, OLCRandomRead))
+        return TRUE;
+
+    else if (EQUAL(pszCap, OLCStringsAsUTF8))
+        return poDS->HasUTF8ContentOnly();
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetExtent()                             */
+/************************************************************************/
+
+OGRErr OGREDIGEOLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    /*if (poDS->bExtentValid)
+    {
+        psExtent->MinX = poDS->dfMinX;
+        psExtent->MinY = poDS->dfMinY;
+        psExtent->MaxX = poDS->dfMaxX;
+        psExtent->MaxY = poDS->dfMaxY;
+        return OGRERR_NONE;
+    }*/
+
+    return OGRLayer::GetExtent(psExtent, bForce);
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGREDIGEOLayer::GetFeatureCount( int bForce )
+{
+    if (m_poFilterGeom != NULL || m_poAttrQuery != NULL)
+        return OGRLayer::GetFeatureCount(bForce);
+
+    return (int)aosFeatures.size();
+}
+
+/************************************************************************/
+/*                             AddFeature()                             */
+/************************************************************************/
+
+void OGREDIGEOLayer::AddFeature(OGRFeature* poFeature)
+{
+    poFeature->SetFID(aosFeatures.size());
+    aosFeatures.push_back(poFeature);
+}
+
+/************************************************************************/
+/*                         GetAttributeIndex()                          */
+/************************************************************************/
+
+int OGREDIGEOLayer::GetAttributeIndex(const CPLString& osRID)
+{
+    std::map<CPLString,int>::iterator itAttrIndex =
+                                            mapAttributeToIndex.find(osRID);
+    if (itAttrIndex != mapAttributeToIndex.end())
+        return itAttrIndex->second;
+    else
+        return -1;
+}
+
+/************************************************************************/
+/*                           AddFieldDefn()                             */
+/************************************************************************/
+
+void OGREDIGEOLayer::AddFieldDefn(const CPLString& osName,
+                                  OGRFieldType eType,
+                                  const CPLString& osRID)
+{
+    if (osRID.size() != 0)
+        mapAttributeToIndex[osRID] = poFeatureDefn->GetFieldCount();
+
+    OGRFieldDefn oFieldDefn(osName, eType);
+    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
new file mode 100644
index 0000000..1139fe2
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
@@ -0,0 +1,339 @@
+/******************************************************************************
+ * $Id: FGdbDatasource.cpp 23394 2011-11-19 19:20:12Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements FileGDB OGR Datasource.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *           Paul Ramsey, pramsey at cleverelephant.ca
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Ragi Yaser Burhum
+ * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ *
+ * 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_fgdb.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "FGdbUtils.h"
+
+CPL_CVSID("$Id: FGdbDatasource.cpp 23394 2011-11-19 19:20:12Z rouault $");
+
+using std::vector;
+using std::wstring;
+
+/************************************************************************/
+/*                          FGdbDataSource()                           */
+/************************************************************************/
+
+FGdbDataSource::FGdbDataSource():
+OGRDataSource(),
+m_pszName(0), m_pGeodatabase(NULL)
+{
+}
+
+/************************************************************************/
+/*                          ~FGdbDataSource()                          */
+/************************************************************************/
+
+FGdbDataSource::~FGdbDataSource()
+{   
+    CPLFree( m_pszName );
+
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+        delete m_layers[i];
+
+    if (m_pGeodatabase)
+    {
+        ::CloseGeodatabase(*m_pGeodatabase);
+        delete m_pGeodatabase;
+    }
+}
+
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int FGdbDataSource::Open(Geodatabase* pGeodatabase, const char * pszNewName, int bUpdate )
+{
+    m_pszName = CPLStrdup( pszNewName );
+    m_pGeodatabase = pGeodatabase;
+
+    std::vector<std::wstring> typesRequested;
+
+	// We're only interested in Tables, Feature Datasets and Feature Classes
+	typesRequested.push_back(L"Feature Class");
+	typesRequested.push_back(L"Table");
+	typesRequested.push_back(L"Feature Dataset");
+	
+    bool rv = LoadLayers(L"\\");
+
+    return rv;
+}
+
+/************************************************************************/
+/*                          OpenFGDBTables()                            */
+/************************************************************************/
+
+bool FGdbDataSource::OpenFGDBTables(const std::wstring &type,
+                                    const std::vector<std::wstring> &layers)
+{
+    fgdbError hr;
+    for ( unsigned int i = 0; i < layers.size(); i++ )
+    {
+        Table* pTable = new Table;
+        //CPLDebug("FGDB", "Opening %s", WStringToString(layers[i]).c_str());
+        if (FAILED(hr = m_pGeodatabase->OpenTable(layers[i], *pTable)))
+        {
+            delete pTable;
+            GDBDebug(hr, "Error opening " + WStringToString(layers[i]) + ". Skipping it");
+            continue;
+        }
+        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);
+    }
+    return true;
+}
+
+/************************************************************************/
+/*                            LoadLayers()                             */
+/************************************************************************/
+
+bool FGdbDataSource::LoadLayers(const std::wstring &root) 
+{
+    std::vector<wstring> tables;
+    std::vector<wstring> featureclasses;
+    std::vector<wstring> featuredatasets;
+    fgdbError hr;
+
+    /* Find all the Tables in the root */
+    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Table", tables)) )
+    {
+        return GDBErr(hr, "Error reading Tables in " + WStringToString(root));
+    }
+    /* Open the tables we found */
+    if ( tables.size() > 0 && ! OpenFGDBTables(L"Table", tables) )
+        return false;
+
+    /* Find all the Feature Classes in the root */
+    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Class", featureclasses)) )
+    {
+        return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(root));
+    }
+    /* Open the tables we found */
+    if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
+        return false;
+
+    /* Find all the Feature Datasets in the root */
+    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Dataset", featuredatasets)) )
+    {
+        return GDBErr(hr, "Error reading Feature Datasets in " + WStringToString(root));
+    }
+    /* Look for Feature Classes inside the Feature Dataset */
+    for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
+    {
+        if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(featuredatasets[i], L"Feature Class", featureclasses)) )
+        {
+            return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(featuredatasets[i]));
+        }
+        if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
+            return false;
+    }
+    return true;
+}
+
+
+#if 0
+/************************************************************************/
+/*                            LoadLayersOld()                              */
+/************************************************************************/
+
+/* Old recursive LoadLayers. Removed in favor of simple one that only
+   looks at FeatureClasses and Tables. */
+
+// Flattens out hierarchichal GDB structure
+bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
+                                const wstring & parent)
+{
+    long hr = S_OK;
+
+    // I didn't find an API to give me the type of the dataset based on name - I am *not*
+    // parsing XML for something like this - in the meantime I can use this hack to see
+    // if the dataset had any children whatsoever - if so, then I won't attempt to open it
+    // otherwise, do attempt to do that
+
+    bool childrenFound = false;
+    bool errorsEncountered = false;
+
+    for (size_t dsTypeIndex = 0; dsTypeIndex < datasetTypes.size(); dsTypeIndex++)
+    {
+        std::vector<wstring> childDatasets;
+        m_pGeodatabase->GetChildDatasets( parent, datasetTypes[dsTypeIndex], childDatasets);
+
+        if (childDatasets.size() > 0)
+        {
+            //it is a container of other datasets
+
+            for (size_t childDatasetIndex = 0;
+                 childDatasetIndex < childDatasets.size();
+                 childDatasetIndex++)
+            {
+                childrenFound = true;
+
+                // do something with it
+                // For now, we just ignore dataset containers and only open the children
+                //std::wcout << datasetTypes[dsTypeIndex] << L" " << childDatasets[childDatasetIndex] << std::endl;
+
+                if (!LoadLayersOld(datasetTypes, childDatasets[childDatasetIndex]))
+                    errorsEncountered = true;
+            }
+        }
+    }
+
+    //it is a full fledged dataset itself without children - open it (except the root)
+
+    if ((!childrenFound) && parent != L"\\")
+    {
+        //wcout << "Opening " << parent << "...";
+        Table* pTable = new Table;
+        if (FAILED(hr = m_pGeodatabase->OpenTable(parent,*pTable)))
+        {
+            delete pTable;
+            return GDBErr(hr, "Error opening " + WStringToString(parent));
+        }
+
+        FGdbLayer* pLayer = new FGdbLayer;
+
+        //pLayer has ownership of the table pointer as soon Initialize is called
+        if (!pLayer->Initialize(this, pTable, parent))
+        {
+            delete pLayer;
+
+            return GDBErr(hr, "Error initializing OGRLayer for " +
+                          WStringToString(parent));
+        }
+
+        m_layers.push_back(pLayer);
+    }
+
+    return !errorsEncountered;
+}
+#endif
+
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr FGdbDataSource::DeleteLayer( int iLayer )
+{
+    if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
+        return OGRERR_FAILURE;
+
+    // Fetch FGDBAPI Table before deleting OGR layer object
+
+    Table* pTable = m_layers[iLayer]->GetTable();
+
+    std::string name = m_layers[iLayer]->GetLayerDefn()->GetName();
+    std::wstring strPath = m_layers[iLayer]->GetTablePath();
+    std::wstring strType = m_layers[iLayer]->GetType();
+
+    // delete OGR layer
+    delete m_layers[iLayer];
+
+    pTable = NULL; // OGR Layer had ownership of FGDB Table
+
+    m_layers.erase(m_layers.begin() + iLayer);
+
+    long hr;
+  
+    if (FAILED(hr = m_pGeodatabase->Delete(strPath, strType)))
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                 "%s was not deleted however it has been closed", name.c_str());
+        GDBErr(hr, "Failed deleting dataset");
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int FGdbDataSource::TestCapability( const char * pszCap )
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+
+    else if( EQUAL(pszCap,ODsCDeleteLayer) )
+        return TRUE;
+
+    return FALSE;
+}
+
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *FGdbDataSource::GetLayer( int iLayer )
+{ 
+    int count = static_cast<int>(m_layers.size());
+
+    if( iLayer < 0 || iLayer >= count )
+        return NULL;
+    else
+        return m_layers[iLayer];
+}
+
+/************************************************************************/
+/*                              CreateLayer()                           */
+/*                                                                      */
+/* See FGdbLayer::Create for creation options                           */
+/************************************************************************/
+
+OGRLayer *
+FGdbDataSource::CreateLayer( const char * pszLayerName,
+                              OGRSpatialReference *poSRS,
+                              OGRwkbGeometryType eType,
+                              char ** papszOptions )
+{
+    FGdbLayer* pLayer = new FGdbLayer;
+    if (!pLayer->Create(this, pszLayerName, poSRS, eType, papszOptions))
+    {
+        delete pLayer;
+        return NULL;
+    }
+
+    m_layers.push_back(pLayer);
+
+    return pLayer;  
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
new file mode 100644
index 0000000..a2a2c47
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
@@ -0,0 +1,249 @@
+/******************************************************************************
+ * $Id: FGdbDriver.cpp 23478 2011-12-05 23:15:46Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements FileGDB OGR driver.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *           Paul Ramsey, pramsey at cleverelephant.ca
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Ragi Yaser Burhum
+ * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ *
+ * 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_fgdb.h"
+#include "cpl_conv.h"
+#include "FGdbUtils.h"
+
+CPL_CVSID("$Id: FGdbDriver.cpp 23478 2011-12-05 23:15:46Z rouault $");
+
+extern "C" void RegisterOGRFileGDB();
+
+/************************************************************************/
+/*                            FGdbDriver()                              */
+/************************************************************************/
+FGdbDriver::FGdbDriver():
+OGRSFDriver()
+{
+}
+
+/************************************************************************/
+/*                            ~FGdbDriver()                             */
+/************************************************************************/
+FGdbDriver::~FGdbDriver()
+
+{
+}
+
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *FGdbDriver::GetName()
+
+{
+    return "FileGDB";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
+
+{
+    // First check if we have to do any work.
+    int nLen = strlen(pszFilename);
+    if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) ||
+          (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) )
+        return NULL;
+
+    long hr;
+
+    /* Check that the filename is really a directory, to avoid confusion with */
+    /* Garmin MapSource - gdb format which can be a problem when the FileGDB */
+    /* driver is loaded as a plugin, and loaded before the GPSBabel driver */
+    /* (http://trac.osgeo.org/osgeo4w/ticket/245) */
+    VSIStatBuf stat;
+    if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
+    {
+        return NULL;
+    }
+
+    Geodatabase* pGeoDatabase = new Geodatabase;
+
+    hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase);
+
+    if (FAILED(hr) || pGeoDatabase == NULL)
+    {
+        delete pGeoDatabase;
+
+        GDBErr(hr, "Failed to open Geodatabase");
+        return NULL;
+    }
+
+    FGdbDataSource* pDS;
+
+    pDS = new FGdbDataSource();
+
+    if(!pDS->Open( pGeoDatabase, pszFilename, bUpdate ) )
+    {
+        delete pDS;
+        return NULL;
+    }
+    else
+        return pDS;
+}
+
+/***********************************************************************/
+/*                     CreateDataSource()                              */
+/***********************************************************************/
+
+OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
+                                           char **papszOptions)
+{
+    long hr;
+    Geodatabase *pGeodatabase;
+    std::wstring wconn = StringToWString(conn);
+    int bUpdate = TRUE; // If we're creating, we must be writing.
+    VSIStatBuf stat;
+
+    /* We don't support options yet, so warn if they send us some */
+    if ( papszOptions )
+    {
+        /* TODO: warning, ignoring options */
+    }
+
+    /* Only accept names of form "filename.gdb" and */
+    /* also .gdb.zip to be able to return FGDB with MapServer OGR output (#4199) */
+    const char* pszExt = CPLGetExtension(conn);
+    if ( !(EQUAL(pszExt,"gdb") || EQUAL(pszExt, "zip")) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FGDB data source name must use 'gdb' extension.\n" );
+        return NULL;
+    }
+
+    /* Don't try to create on top of something already there */
+    if( CPLStat( conn, &stat ) == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s already exists.\n", conn );
+        return NULL;
+    }
+
+    /* Try to create the geodatabase */
+    pGeodatabase = new Geodatabase; // Create on heap so we can store it in the Datasource
+    hr = CreateGeodatabase(wconn, *pGeodatabase);
+
+    /* Handle creation errors */
+    if ( S_OK != hr )
+    {
+        const char *errstr = "Error creating geodatabase (%s).\n";
+        if ( hr == -2147220653 )
+            errstr = "File already exists (%s).\n";
+        delete pGeodatabase;
+        CPLError( CE_Failure, CPLE_AppDefined, errstr, conn );
+        return NULL;
+    }
+
+    /* Ready to embed the Geodatabase in an OGR Datasource */
+    FGdbDataSource* pDS = new FGdbDataSource();
+    if ( ! pDS->Open(pGeodatabase, conn, bUpdate) )
+    {
+        delete pDS;
+        return NULL;
+    }
+    else
+        return pDS;
+}
+
+/***********************************************************************/
+/*                        OpenGeodatabase()                            */
+/***********************************************************************/
+
+void FGdbDriver::OpenGeodatabase(std::string conn, Geodatabase** ppGeodatabase)
+{
+    *ppGeodatabase = NULL;
+
+    std::wstring wconn = StringToWString(conn);
+
+    long hr;
+
+    Geodatabase* pGeoDatabase = new Geodatabase;
+
+    if (S_OK != (hr = ::OpenGeodatabase(wconn, *pGeoDatabase)))
+    {
+        delete pGeoDatabase;
+
+        return;
+    }
+
+    *ppGeodatabase = pGeoDatabase;
+}
+
+/***********************************************************************/
+/*                         TestCapability()                            */
+/***********************************************************************/
+
+int FGdbDriver::TestCapability( const char * pszCap )
+{
+    if (EQUAL(pszCap, ODrCCreateDataSource) )
+        return TRUE;
+
+    else if (EQUAL(pszCap, ODrCDeleteDataSource) )
+        return TRUE;
+
+    return FALSE;
+}
+/************************************************************************/
+/*                          DeleteDataSource()                          */
+/************************************************************************/
+
+OGRErr FGdbDriver::DeleteDataSource( const char *pszDataSource )
+{
+
+    std::wstring wstr = StringToWString(pszDataSource);
+
+    long hr;
+
+    if (S_OK != (hr = ::DeleteGeodatabase(wstr)))
+    {
+        GDBErr(hr, "Failed to delete Geodatabase");
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/***********************************************************************/
+/*                       RegisterOGRFileGDB()                          */
+/***********************************************************************/
+
+void RegisterOGRFileGDB()
+
+{
+    if (! GDAL_CHECK_VERSION("OGR FGDB"))
+        return;
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new FGdbDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
new file mode 100644
index 0000000..6a4151a
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
@@ -0,0 +1,1676 @@
+/******************************************************************************
+* $Id: FGdbLayer.cpp 23394 2011-11-19 19:20:12Z rouault $
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Implements FileGDB OGR layer.
+* Author:   Ragi Yaser Burhum, ragi at burhum.com
+*           Paul Ramsey, pramsey at cleverelephant.ca
+*
+******************************************************************************
+* Copyright (c) 2010, Ragi Yaser Burhum
+* Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+*
+* 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_fgdb.h"
+#include "ogrpgeogeometry.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "FGdbUtils.h"
+#include "cpl_minixml.h" // the only way right now to extract schema information
+
+CPL_CVSID("$Id: FGdbLayer.cpp 23394 2011-11-19 19:20:12Z rouault $");
+
+using std::string;
+using std::wstring;
+
+/************************************************************************/
+/*                              FGdbLayer()                               */
+/************************************************************************/
+FGdbLayer::FGdbLayer():
+    OGRLayer(), m_pDS(NULL), m_pTable(NULL), m_pFeatureDefn(NULL), 
+    m_pSRS(NULL), m_wstrSubfields(L"*"), m_pOGRFilterGeometry(NULL), 
+    m_pEnumRows(NULL), m_bFilterDirty(true), 
+    m_supressColumnMappingError(false), m_forceMulti(false)
+{
+    m_pEnumRows = new EnumRows;
+}
+
+/************************************************************************/
+/*                            ~FGdbLayer()                              */
+/************************************************************************/
+
+FGdbLayer::~FGdbLayer()
+{
+    if (m_pFeatureDefn)
+    {
+        m_pFeatureDefn->Release();
+        m_pFeatureDefn = NULL;
+    }
+
+    if (m_pSRS)
+    {
+        m_pSRS->Release();
+        m_pSRS = NULL;
+    }
+
+    if (m_pEnumRows)
+    {
+        delete m_pEnumRows;
+        m_pEnumRows = NULL;
+    }
+
+    // NOTE: never delete m_pDS - the memory doesn't belong to us
+    // TODO: check if we need to close the table or if the destructor 
+    // takes care of closing as it should
+    if (m_pTable)
+    {
+        delete m_pTable;
+        m_pTable = NULL;
+    }
+
+    if (m_pOGRFilterGeometry)
+    {
+        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
+        m_pOGRFilterGeometry = NULL;
+    }
+    
+}
+
+
+/************************************************************************/
+/*                            CreateFeature()                           */
+/* Create an FGDB Row and populate it from an OGRFeature.               */
+/*                                                                      */
+/************************************************************************/
+
+OGRErr FGdbLayer::CreateFeature( OGRFeature *poFeature )
+{
+    Table *fgdb_table = m_pTable;
+    Row fgdb_row;
+    fgdbError hr;
+    ShapeBuffer shape;
+
+    hr = fgdb_table->CreateRowObject(fgdb_row);
+
+    /* Check the status of the Row create */
+    if (FAILED(hr))
+        return GDBErr(hr, "Failed at creating Row in CreateFeature.");
+
+    OGRFeatureDefn* poFeatureDefn = m_pFeatureDefn;
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+
+    /* Copy the OGR visible fields (everything except geometry and FID) */
+    for( int i = 0; i < nFieldCount; i++ )
+    {
+        std::string field_name = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        std::wstring wfield_name = StringToWString(field_name);
+
+        /* Set empty fields to NULL */
+        if( !poFeature->IsFieldSet( i ) )
+        {
+            if (FAILED(hr = fgdb_row.SetNull(wfield_name)))
+                return GDBErr(hr, "Failed setting field to NULL.");
+            continue;
+        }
+
+        /* Set the information using the appropriate FGDB function */
+        int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
+
+        if ( nOGRFieldType == OFTInteger )
+        {
+            /* Integers (we don't do FGDB Shorts) */
+            int fldvalue = poFeature->GetFieldAsInteger(i);
+            hr = fgdb_row.SetInteger(wfield_name, fldvalue);
+        }
+        else if ( nOGRFieldType == OFTReal )
+        {
+            /* Doubles (we don't handle FGDB Floats) */
+            double fldvalue = poFeature->GetFieldAsDouble(i);
+            hr = fgdb_row.SetDouble(wfield_name, fldvalue);
+        }
+        else if ( nOGRFieldType == OFTString )
+        {
+            /* Strings we convert to wstring */
+            std::string fldvalue = poFeature->GetFieldAsString(i);
+            std::wstring wfldvalue = StringToWString(fldvalue);
+            hr = fgdb_row.SetString(wfield_name, wfldvalue);
+        }
+        else if ( nOGRFieldType == OFTDateTime || nOGRFieldType == OFTDate )
+        {
+            /* Dates we need to coerce a little */
+            struct tm val;
+            poFeature->GetFieldAsDateTime(i, &(val.tm_year), &(val.tm_mon), &(val.tm_mday),
+                                          &(val.tm_hour), &(val.tm_min), &(val.tm_sec), NULL);
+            val.tm_year -= 1900;
+            val.tm_mon = val.tm_mon - 1; /* OGR months go 1-12, FGDB go 0-11 */
+            hr = fgdb_row.SetDate(wfield_name, val);
+        }
+        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);
+            }
+            else
+            {
+                hr = fgdb_row.SetNull(wfield_name);
+            }
+        }
+        else
+        {
+            /* We can't handle this type */
+            CPLError( CE_Failure, CPLE_AppDefined,
+                "FGDB driver does not support OGR type." );
+            return OGRERR_FAILURE;
+        }
+    }
+
+    /* Done with attribute fields, now do geometry */
+    OGRGeometry *poGeom = poFeature->GetGeometryRef();
+
+    /* Write geometry to a buffer */
+    GByte *pabyShape = NULL;
+    int nShapeSize = 0;
+    OGRErr err = OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize );
+    if ( err != OGRERR_NONE )
+        return err;
+
+    /* Copy it into a ShapeBuffer */
+    if ( nShapeSize > 0 )
+    {
+        shape.Allocate(nShapeSize);
+        memcpy(shape.shapeBuffer, pabyShape, nShapeSize);
+        shape.inUseLength = nShapeSize;
+    }
+
+    /* Free the shape buffer */
+    CPLFree(pabyShape);
+
+    /* Write ShapeBuffer into the Row */
+    hr = fgdb_row.SetGeometry(shape);
+    if (FAILED(hr))
+        return GDBErr(hr, "Failed at writing Geometry to Row in CreateFeature.");
+
+    /* Cannot write to FID field - it is managed by GDB*/
+    //std::wstring wfield_name = StringToWString(m_strOIDFieldName);
+    //hr = fgdb_row.SetInteger(wfield_name, poFeature->GetFID());
+
+    /* Write the row to the table */
+    hr = fgdb_table->Insert(fgdb_row);
+    if (FAILED(hr))
+        return GDBErr(hr, "Failed at writing Row to Table in CreateFeature.");
+
+    return OGRERR_NONE;
+
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/*  Build up an FGDB XML field definition and use it to create a Field  */
+/*  Update the OGRFeatureDefn to reflect the new field.                 */
+/*                                                                      */
+/************************************************************************/
+
+OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
+{
+    OGRFieldDefn oField(poField);
+    std::string fieldname = oField.GetNameRef();
+    std::wstring wfieldname = StringToWString(fieldname);
+    std::string fidname = std::string(GetFIDColumn());
+    std::string nullable = "true";
+    Table *fgdb_table = m_pTable;
+
+    /* Try to map the OGR type to an ESRI type */
+    OGRFieldType fldtype = oField.GetType();
+    std::string gdbFieldType;
+    if ( ! OGRToGDBFieldType(fldtype, &gdbFieldType) )
+    {
+        GDBErr(-1, "Failed converting field type.");
+        return OGRERR_FAILURE;
+    }
+
+    /* If we don't have our FGDB Table pointer intialized, we can quit now. */
+    if ( ! m_pTable )
+    {
+        GDBErr(-1, "FGDB Table has not been initialized.");
+        return OGRERR_FAILURE;
+    }
+
+    /* Then the Field definition */
+    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:Field");
+
+    /* Add the XML attributes to the Field node */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", "esri:Field");
+
+    /* Basic field information */
+    CPLCreateXMLElementAndValue(defn_xml, "Name", fieldname.c_str());
+    CPLCreateXMLElementAndValue(defn_xml, "Type", gdbFieldType.c_str());
+    CPLCreateXMLElementAndValue(defn_xml, "IsNullable", nullable.c_str());
+
+    /* Get the Width and Precision if we know them */
+    int width = oField.GetWidth();
+    int precision = oField.GetPrecision();
+    if ( width <= 0 )
+        GDBFieldTypeToWidthPrecision(gdbFieldType, &width, &precision);
+
+    /* Write out the Width and Precision */
+    char buf[100];
+    snprintf(buf, 100, "%d", width);
+    CPLCreateXMLElementAndValue(defn_xml,"Length", buf);
+    snprintf(buf, 100, "%d", precision);
+    CPLCreateXMLElementAndValue(defn_xml,"Precision", buf);
+
+    /* We know nothing about Scale, so zero it out */
+    CPLCreateXMLElementAndValue(defn_xml,"Scale", "0");
+
+    /* Default values are discouraged in OGR API docs */
+    /* <DefaultValue xsi:type="xs:string">afternoon</DefaultValue> */
+
+    /* Convert our XML tree into a string for FGDB */
+    char *defn_str = CPLSerializeXMLTree(defn_xml);
+    CPLDebug("FGDB", "CreateField() generated XML for FGDB\n%s", defn_str);
+
+    /* Add the FGDB Field to the FGDB Table. */
+    fgdbError hr = fgdb_table->AddField(defn_str);
+
+    /* Free the XML */
+    CPLFree(defn_str);
+    CPLDestroyXMLNode(defn_xml);
+
+    /* Check the status of the Field add */
+    if (FAILED(hr))
+        return GDBErr(hr, "Failed at creating Field for " + fieldname);
+
+    /* Now add the OGRFieldDefn to the OGRFeatureDefn */
+    m_pFeatureDefn->AddFieldDefn(&oField);
+
+    m_vOGRFieldToESRIField.push_back(StringToWString(fieldname));
+    m_vOGRFieldToESRIFieldType.push_back( gdbFieldType );
+
+    /* All done and happy */
+    return OGRERR_NONE;
+
+}
+
+/************************************************************************/
+/*                      XMLSpatialReference()                           */
+/*  Build up an XML representation of an OGRSpatialReference.           */
+/*  Used in layer creation.                                             */
+/*                                                                      */
+/************************************************************************/
+
+CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
+{
+    /* We always need a SpatialReference */
+    CPLXMLNode *srs_xml = CPLCreateXMLNode(NULL, CXT_Element, "SpatialReference");
+
+    /* Extract the WKID before morphing */
+    char *wkid = NULL;
+    if ( poSRS && poSRS->GetAuthorityCode(NULL) )
+    {
+        wkid = CPLStrdup(poSRS->GetAuthorityCode(NULL));
+    }
+
+    /* NULL poSRS => UnknownCoordinateSystem */
+    if ( ! poSRS )
+    {
+        FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:UnknownCoordinateSystem");
+    }
+    else
+    {
+        /* Make a clone so we can morph it without morphing the original */
+        OGRSpatialReference* poSRSClone = poSRS->Clone();
+
+        /* Flip the WKT to ESRI form, return UnknownCoordinateSystem if we can't */
+        if ( poSRSClone->morphToESRI() != OGRERR_NONE )
+        {
+            delete poSRSClone;
+            FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:UnknownCoordinateSystem");
+            return srs_xml;
+        }
+
+        /* Set the SpatialReference type attribute correctly for GEOGCS/PROJCS */
+        if ( poSRSClone->IsProjected() )
+            FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:ProjectedCoordinateSystem");
+        else
+            FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:GeographicCoordinateSystem");
+
+        /* Add the WKT to the XML */
+        char *wkt = NULL;
+        poSRSClone->exportToWkt(&wkt);
+        if (wkt)
+        {
+            CPLCreateXMLElementAndValue(srs_xml,"WKT", wkt);
+            OGRFree(wkt);
+        }
+
+        /* Dispose of our close */
+        delete poSRSClone;
+    }
+    
+    /* Handle Origin/Scale/Tolerance */
+    const char* grid[7] = {
+      "XOrigin", "YOrigin", "XYScale",
+      "ZOrigin", "ZScale",
+      "XYTolerance", "ZTolerance" };
+    const char* gridvalues[7] = {
+      "-2147483647", "-2147483647", "1000000000",
+      "-2147483647", "1000000000",
+      "0.0001", "0.0001" };
+
+    /* Convert any layer creation options available, use defaults otherwise */
+    for( int i = 0; i < 7; i++ )
+    {
+        if ( CSLFetchNameValue( papszOptions, grid[i] ) != NULL )
+            gridvalues[i] = CSLFetchNameValue( papszOptions, grid[i] );
+
+        CPLCreateXMLElementAndValue(srs_xml, grid[i], gridvalues[i]);
+    }
+
+    /* FGDB is always High Precision */
+    CPLCreateXMLElementAndValue(srs_xml, "HighPrecision", "true");     
+
+    /* Add the WKID to the XML */
+    if ( wkid ) 
+    {
+        CPLCreateXMLElementAndValue(srs_xml, "WKID", wkid);
+        CPLFree(wkid);
+    }
+
+    return srs_xml;
+}
+
+/************************************************************************/
+/*                    CreateFeatureDataset()                            */
+/************************************************************************/
+
+bool FGdbLayer::CreateFeatureDataset(FGdbDataSource* pParentDataSource, 
+                                     std::string feature_dataset_name,
+                                     OGRSpatialReference* poSRS,
+                                     char** papszOptions )
+{
+    /* XML node */
+    CPLXMLNode *xml_xml = CPLCreateXMLNode(NULL, CXT_Element, "?xml");
+    FGDB_CPLAddXMLAttribute(xml_xml, "version", "1.0");
+    FGDB_CPLAddXMLAttribute(xml_xml, "encoding", "UTF-8");
+
+    /* First build up a bare-bones feature definition */
+    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:DataElement");
+    CPLAddXMLSibling(xml_xml, defn_xml);
+
+    /* Add the attributes to the DataElement */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
+
+    /* Need to set this to esri:DEFeatureDataset or esri:DETable */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", "esri:DEFeatureDataset");
+
+    /* Add in more children */
+    std::string catalog_page = "\\" + feature_dataset_name;
+    CPLCreateXMLElementAndValue(defn_xml,"CatalogPath", catalog_page.c_str());
+    CPLCreateXMLElementAndValue(defn_xml,"Name", feature_dataset_name.c_str());
+    CPLCreateXMLElementAndValue(defn_xml,"ChildrenExpanded", "false");
+    CPLCreateXMLElementAndValue(defn_xml,"DatasetType", "esriDTFeatureDataset");
+    CPLCreateXMLElementAndValue(defn_xml,"Versioned", "false");
+    CPLCreateXMLElementAndValue(defn_xml,"CanVersion", "false");
+
+    /* Add in empty extent */
+    CPLXMLNode *extent_xml = CPLCreateXMLNode(NULL, CXT_Element, "Extent");
+    FGDB_CPLAddXMLAttribute(extent_xml, "xsi:nil", "true");
+    CPLAddXMLChild(defn_xml, extent_xml);
+
+    /* Add the SRS */
+    if( TRUE ) // TODO: conditional on existence of SRS
+    {
+        CPLXMLNode *srs_xml = XMLSpatialReference(poSRS, papszOptions);
+        if ( srs_xml )
+            CPLAddXMLChild(defn_xml, srs_xml);
+    }
+
+    /* Convert our XML tree into a string for FGDB */
+    char *defn_str = CPLSerializeXMLTree(xml_xml);
+    CPLDestroyXMLNode(xml_xml);
+
+    /* TODO, tie this to debugging levels */
+    CPLDebug("FGDB", "%s", defn_str);
+
+    /* Create the FeatureDataset. */
+    Geodatabase *gdb = pParentDataSource->GetGDB();
+    fgdbError hr = gdb->CreateFeatureDataset(defn_str);
+
+    /* Free the XML */
+    CPLFree(defn_str);
+
+    /* Check table create status */
+    if (FAILED(hr))
+    {
+        return GDBErr(hr, "Failed at creating FeatureDataset " + feature_dataset_name);
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                            Create()                                  */
+/* Build up an FGDB XML layer definition and use it to create a Table   */
+/* or Feature Class to work from.                                       */
+/*                                                                      */
+/* Layer creation options:                                              */
+/*   FEATURE_DATASET, nest layer inside a FeatureDataset folder         */
+/*   GEOMETRY_NAME, user-selected name for the geometry column          */
+/*   OID_NAME, user-selected name for the FID column                    */
+/*   XORIGIN, YORIGIN, ZORIGIN, origin of the snapping grid             */
+/*   XYSCALE, ZSCALE, inverse resolution of the snapping grid           */
+/*   XYTOLERANCE, ZTOLERANCE, snapping tolerance for topology/networks  */
+/*                                                                      */
+/************************************************************************/
+
+bool FGdbLayer::Create(FGdbDataSource* pParentDataSource, 
+                       const char* pszLayerName, 
+                       OGRSpatialReference* poSRS, 
+                       OGRwkbGeometryType eType, 
+                       char** papszOptions)
+{
+    std::string table_path = "\\" + std::string(pszLayerName);
+    std::string parent_path = "";
+    std::wstring wtable_path, wparent_path;
+    std::string geometry_name = FGDB_GEOMETRY_NAME;
+    std::string fid_name = FGDB_OID_NAME;
+    std::string esri_type;
+    bool has_z = false;
+
+    /* Handle the FEATURE_DATASET case */
+    if (  CSLFetchNameValue( papszOptions, "FEATURE_DATASET") != NULL )
+    {
+        std::string feature_dataset = CSLFetchNameValue( papszOptions, "FEATURE_DATASET");
+
+        /* Check if FEATURE_DATASET exists. Otherwise create it */
+        std::vector<wstring> featuredatasets;
+        Geodatabase *gdb = pParentDataSource->GetGDB();
+        int bFeatureDataSetExists = FALSE;
+        fgdbError hr;
+        if ( !FAILED(hr = gdb->GetChildDatasets(L"\\", L"Feature Dataset", featuredatasets)) )
+        {
+            std::wstring feature_dataset_with_slash = L"\\" + StringToWString(feature_dataset);
+            for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
+            {
+                if (featuredatasets[i] == feature_dataset_with_slash)
+                    bFeatureDataSetExists = TRUE;
+            }
+        }
+
+        if (!bFeatureDataSetExists)
+        {
+            bool rv = CreateFeatureDataset(pParentDataSource, feature_dataset, poSRS, papszOptions);
+            if ( ! rv )
+                return rv;
+        }
+
+        table_path = "\\" + feature_dataset + table_path;
+        parent_path = "\\" + feature_dataset;
+    }
+
+    /* Convert table_path into wstring */
+    wtable_path = StringToWString(table_path);
+    wparent_path = StringToWString(parent_path);
+
+    /* Over-ride the geometry name if necessary */
+    if ( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
+        geometry_name = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
+
+    /* Over-ride the OID name if necessary */
+    if ( CSLFetchNameValue( papszOptions, "OID_NAME") != NULL )
+        fid_name = CSLFetchNameValue( papszOptions, "OID_NAME");
+
+    /* Figure out our geometry type */
+    if ( eType != wkbNone )
+    {
+        if ( wkbFlatten(eType) == wkbUnknown )
+        {
+            return GDBErr(-1, "FGDB layers cannot be created with a wkbUnknown layer geometry type.");
+        }
+        if ( ! OGRGeometryToGDB(eType, &esri_type, &has_z) )
+            return GDBErr(-1, "Unable to map OGR type to ESRI type");
+    }
+
+    /* XML node */
+    CPLXMLNode *xml_xml = CPLCreateXMLNode(NULL, CXT_Element, "?xml");
+    FGDB_CPLAddXMLAttribute(xml_xml, "version", "1.0");
+    FGDB_CPLAddXMLAttribute(xml_xml, "encoding", "UTF-8");
+
+    /* First build up a bare-bones feature definition */
+    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:DataElement");
+    CPLAddXMLSibling(xml_xml, defn_xml);
+
+    /* Add the attributes to the DataElement */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
+
+    /* Need to set this to esri:DEFeatureDataset or esri:DETable */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", (eType == wkbNone ? "esri:DETable" : "esri:DEFeatureClass"));
+
+    /* Add in more children */
+    CPLCreateXMLElementAndValue(defn_xml,"CatalogPath",table_path.c_str());
+    CPLCreateXMLElementAndValue(defn_xml,"Name", pszLayerName);
+    CPLCreateXMLElementAndValue(defn_xml,"ChildrenExpanded", "false");
+
+    /* WKB type of none implies this is a 'Table' otherwise it's a 'Feature Class' */
+    std::string datasettype = (eType == wkbNone ? "esriDTTable" : "esriDTFeatureClass");
+    CPLCreateXMLElementAndValue(defn_xml,"DatasetType", datasettype.c_str() );
+    CPLCreateXMLElementAndValue(defn_xml,"Versioned", "false");
+    CPLCreateXMLElementAndValue(defn_xml,"CanVersion", "false");
+
+    /* We might need to make OID optional later, but OGR likes to have a FID */
+    CPLCreateXMLElementAndValue(defn_xml,"HasOID", "true");
+    CPLCreateXMLElementAndValue(defn_xml,"OIDFieldName", fid_name.c_str());
+
+    /* Add in empty Fields */
+    CPLXMLNode *fields_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Fields");
+    FGDB_CPLAddXMLAttribute(fields_xml, "xsi:type", "esri:Fields");
+    CPLXMLNode *fieldarray_xml = CPLCreateXMLNode(fields_xml, CXT_Element, "FieldArray");
+    FGDB_CPLAddXMLAttribute(fieldarray_xml, "xsi:type", "esri:ArrayOfField");
+
+    /* Feature Classes have an implicit geometry column, so we'll add it at creation time */
+    if ( eType != wkbNone )
+    {
+        CPLXMLNode *shape_xml = CPLCreateXMLNode(fieldarray_xml, CXT_Element, "Field");
+        FGDB_CPLAddXMLAttribute(shape_xml, "xsi:type", "esri:Field");
+        CPLCreateXMLElementAndValue(shape_xml, "Name", geometry_name.c_str());
+        CPLCreateXMLElementAndValue(shape_xml, "Type", "esriFieldTypeGeometry");
+        CPLCreateXMLElementAndValue(shape_xml, "IsNullable", "false");
+        CPLCreateXMLElementAndValue(shape_xml, "Length", "0");
+        CPLCreateXMLElementAndValue(shape_xml, "Precision", "0");
+        CPLCreateXMLElementAndValue(shape_xml, "Scale", "0");
+        CPLCreateXMLElementAndValue(shape_xml, "Required", "true");
+        CPLXMLNode *geom_xml = CPLCreateXMLNode(shape_xml, CXT_Element, "GeometryDef");
+        FGDB_CPLAddXMLAttribute(geom_xml, "xsi:type", "esri:GeometryDef");
+        CPLCreateXMLElementAndValue(geom_xml, "AvgNumPoints", "0");
+        CPLCreateXMLElementAndValue(geom_xml, "GeometryType", esri_type.c_str());
+        CPLCreateXMLElementAndValue(geom_xml,"HasM", "false");
+        CPLCreateXMLElementAndValue(geom_xml,"HasZ", (has_z ? "true" : "false"));
+
+        /* Add the SRS if we have one */
+        CPLXMLNode *srs_xml = XMLSpatialReference(poSRS, papszOptions);
+        if ( srs_xml )
+            CPLAddXMLChild(geom_xml, srs_xml);
+    }
+
+    /* All (?) Tables and Feature Classes will have an ObjectID */
+    CPLXMLNode *oid_xml = CPLCreateXMLNode(fieldarray_xml, CXT_Element, "Field");
+    FGDB_CPLAddXMLAttribute(oid_xml, "xsi:type", "esri:Field");
+    CPLCreateXMLElementAndValue(oid_xml, "Name", fid_name.c_str());
+    CPLCreateXMLElementAndValue(oid_xml, "Type", "esriFieldTypeOID");
+    CPLCreateXMLElementAndValue(oid_xml, "IsNullable", "false");
+    CPLCreateXMLElementAndValue(oid_xml, "Length", "12");
+    CPLCreateXMLElementAndValue(oid_xml, "Precision", "0");
+    CPLCreateXMLElementAndValue(oid_xml, "Scale", "0");
+    CPLCreateXMLElementAndValue(oid_xml, "Required", "true");
+
+    /* Add in empty Indexes */
+    CPLXMLNode *indexes_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Indexes");
+    FGDB_CPLAddXMLAttribute(indexes_xml, "xsi:type", "esri:Indexes");
+    CPLXMLNode *indexarray_xml = CPLCreateXMLNode(indexes_xml, CXT_Element, "IndexArray");
+    FGDB_CPLAddXMLAttribute(indexarray_xml, "xsi:type", "esri:ArrayOfIndex");
+
+    /* Map from OGR WKB type to ESRI type */
+    if ( eType != wkbNone )
+    {
+        /* Declare our feature type */
+        CPLCreateXMLElementAndValue(defn_xml,"FeatureType", "esriFTSimple");
+        CPLCreateXMLElementAndValue(defn_xml,"ShapeType", esri_type.c_str());
+        CPLCreateXMLElementAndValue(defn_xml,"ShapeFieldName", geometry_name.c_str());
+
+        /* Dimensionality */
+        CPLCreateXMLElementAndValue(defn_xml,"HasM", "false");
+        CPLCreateXMLElementAndValue(defn_xml,"HasZ", (has_z ? "true" : "false"));
+
+        /* TODO: Handle spatial indexes (layer creation option?) */
+        CPLCreateXMLElementAndValue(defn_xml,"HasSpatialIndex", "false");
+
+        /* We can't know the extent at this point <Extent xsi:nil='true'/> */
+        CPLXMLNode *extn_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Extent");
+        FGDB_CPLAddXMLAttribute(extn_xml, "xsi:nil", "true");
+    }
+
+    /* Feature Class with known SRS gets an SRS entry */
+    if( eType != wkbNone )
+    {
+        CPLXMLNode *srs_xml = XMLSpatialReference(poSRS, papszOptions);
+        if ( srs_xml )
+            CPLAddXMLChild(defn_xml, srs_xml);
+    }
+
+    /* Convert our XML tree into a string for FGDB */
+    char *defn_str = CPLSerializeXMLTree(xml_xml);
+    CPLDestroyXMLNode(xml_xml);
+
+    /* TODO, tie this to debugging levels */
+    CPLDebug("FGDB", "%s", defn_str);
+    //std::cout << defn_str << std::endl;
+
+    /* Create the table. */
+    Table *table = new Table;
+    Geodatabase *gdb = pParentDataSource->GetGDB();
+    fgdbError hr = gdb->CreateTable(defn_str, wparent_path, *table);
+
+    /* Free the XML */
+    CPLFree(defn_str);
+
+    /* Check table create status */
+    if (FAILED(hr))
+    {
+        delete table;
+        return GDBErr(hr, "Failed at creating table for " + table_path);
+    }
+
+    /* Store the new FGDB Table pointer and set up the OGRFeatureDefn */
+    return FGdbLayer::Initialize(pParentDataSource, table, wtable_path, L"Table");
+}
+
+/*************************************************************************/
+/*                            Initialize()                               */
+/* Has ownership of the table as soon as it is called.                   */
+/************************************************************************/
+
+bool FGdbLayer::Initialize(FGdbDataSource* pParentDataSource, Table* pTable,
+                           std::wstring wstrTablePath, std::wstring wstrType)
+{
+    long hr;
+
+    m_pDS = pParentDataSource; // we never assume ownership of the parent - so our destructor should not delete
+
+    m_pTable = pTable;
+
+    m_wstrTablePath = wstrTablePath;
+    m_wstrType = wstrType;
+
+    wstring wstrQueryName;
+    if (FAILED(hr = pParentDataSource->GetGDB()->GetQueryName(wstrTablePath, wstrQueryName)))
+        return GDBErr(hr, "Failed at getting underlying table name for " +
+                      WStringToString(wstrTablePath));
+
+    m_strName = WStringToString(wstrQueryName);
+
+    m_pFeatureDefn = new OGRFeatureDefn(m_strName.c_str()); //TODO: Should I "new" an OGR smart pointer - sample says so, but it doesn't seem right
+    //as long as we use the same compiler & settings in both the ogr build and this
+    //driver, we should be OK
+    m_pFeatureDefn->Reference();
+
+    string tableDef;
+    if (FAILED(hr = m_pTable->GetDefinition(tableDef)))
+        return GDBErr(hr, "Failed at getting table definition for " +
+                      WStringToString(wstrTablePath));
+
+    //xxx  printf("Table definition = %s", tableDef.c_str() );
+
+    bool abort = false;
+
+    // extract schema information from table
+    CPLXMLNode *psRoot = CPLParseXMLString( tableDef.c_str() );
+
+    if (psRoot == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                  ("Failed parsing GDB Table Schema XML for " + m_strName).c_str());
+        return false;
+    }
+
+    CPLXMLNode *pDataElementNode = psRoot->psNext; // Move to next field which should be DataElement
+
+    if( pDataElementNode != NULL
+        && pDataElementNode->psChild != NULL
+        && pDataElementNode->eType == CXT_Element
+        && EQUAL(pDataElementNode->pszValue,"esri:DataElement") )
+    {
+        CPLXMLNode *psNode;
+
+        for( psNode = pDataElementNode->psChild;
+        psNode != NULL;
+        psNode = psNode->psNext )
+        {
+            if( psNode->eType == CXT_Element && psNode->psChild != NULL )
+            {
+                if (EQUAL(psNode->pszValue,"OIDFieldName") )
+                {
+                    char* pszUnescaped = CPLUnescapeString(
+                    psNode->psChild->pszValue, NULL, CPLES_XML);
+                    m_strOIDFieldName = pszUnescaped;
+                    CPLFree(pszUnescaped);
+                }
+                else if (EQUAL(psNode->pszValue,"ShapeFieldName") )
+                {
+                    char* pszUnescaped = CPLUnescapeString(
+                    psNode->psChild->pszValue, NULL, CPLES_XML);
+                    m_strShapeFieldName = pszUnescaped;
+                    CPLFree(pszUnescaped);
+                }
+                else if (EQUAL(psNode->pszValue,"Fields") )
+                {
+                    if (!GDBToOGRFields(psNode))
+                    {
+                        abort = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (m_strShapeFieldName.size() == 0)
+            m_pFeatureDefn->SetGeomType(wkbNone);
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                ("Failed parsing GDB Table Schema XML (DataElement) for " + m_strName).c_str());
+        return false;
+    }
+    CPLDestroyXMLNode( psRoot );
+
+    if (abort)
+        return false;
+
+    return true; //AOToOGRFields(ipFields, m_pFeatureDefn, m_vOGRFieldToESRIField);
+}
+
+/************************************************************************/
+/*                          ParseGeometryDef()                          */
+/************************************************************************/
+
+bool FGdbLayer::ParseGeometryDef(CPLXMLNode* psRoot)
+{
+    CPLXMLNode *psGeometryDefItem;
+
+    string geometryType;
+    bool hasZ = false;
+    string wkt, wkid;
+
+    for (psGeometryDefItem = psRoot->psChild;
+        psGeometryDefItem != NULL;
+        psGeometryDefItem = psGeometryDefItem->psNext )
+    {
+        //loop through all "GeometryDef" elements
+        //
+
+        if (psGeometryDefItem->eType == CXT_Element &&
+            psGeometryDefItem->psChild != NULL)
+        {
+            if (EQUAL(psGeometryDefItem->pszValue,"GeometryType"))
+            {
+                char* pszUnescaped = CPLUnescapeString(
+                    psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
+
+                geometryType = pszUnescaped;
+
+                CPLFree(pszUnescaped);
+            }
+            else if (EQUAL(psGeometryDefItem->pszValue,"SpatialReference"))
+            {
+                ParseSpatialReference(psGeometryDefItem, &wkt, &wkid); // we don't check for success because it
+                                                                // may not be there
+            }
+            /* No M support in OGR yet
+            else if (EQUAL(psFieldNode->pszValue,"HasM")
+            {
+                char* pszUnescaped = CPLUnescapeString(psNode->psChild->pszValue, NULL, CPLES_XML);
+
+                if (!strcmp(szUnescaped, "true"))
+                hasM = true;
+
+                CPLFree(pszUnescaped);
+            }
+            */
+            else if (EQUAL(psGeometryDefItem->pszValue,"HasZ"))
+            {
+                char* pszUnescaped = CPLUnescapeString(
+                    psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
+
+                if (!strcmp(pszUnescaped, "true"))
+                hasZ = true;
+
+                CPLFree(pszUnescaped);
+            }
+        }
+
+    }
+
+    OGRwkbGeometryType ogrGeoType;
+    if (!GDBToOGRGeometry(geometryType, hasZ, &ogrGeoType))
+        return false;
+
+    m_pFeatureDefn->SetGeomType(ogrGeoType);
+
+    if (wkbFlatten(ogrGeoType) == wkbMultiLineString ||
+        wkbFlatten(ogrGeoType) == wkbMultiPoint)
+        m_forceMulti = true;
+
+    if (wkid.length() > 0)
+    {
+        m_pSRS = new OGRSpatialReference();
+        if (m_pSRS->importFromEPSG(atoi(wkid.c_str())) != OGRERR_NONE)
+        {
+            delete m_pSRS;
+            m_pSRS = NULL;
+        }
+        else
+            return true;
+    }
+
+    if (wkt.length() > 0)
+    {
+        if (!GDBToOGRSpatialReference(wkt, &m_pSRS))
+        {
+            //report error, but be passive about it
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Failed Mapping ESRI Spatial Reference");
+        }
+    }
+    else
+    {
+        //report error, but be passive about it
+        CPLError( CE_Warning, CPLE_AppDefined, "Empty Spatial Reference");
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                        ParseSpatialReference()                       */
+/************************************************************************/
+
+bool FGdbLayer::ParseSpatialReference(CPLXMLNode* psSpatialRefNode,
+                                      string* pOutWkt, string* pOutWKID)
+{
+    *pOutWkt = "";
+    *pOutWKID = "";
+
+    CPLXMLNode* psSRItemNode;
+
+    /* Loop through all the SRS elements we want to store */
+    for( psSRItemNode = psSpatialRefNode->psChild;
+         psSRItemNode != NULL;
+         psSRItemNode = psSRItemNode->psNext )
+    {
+        /* The WKID maps (mostly) to an EPSG code */
+        if( psSRItemNode->eType == CXT_Element &&
+            psSRItemNode->psChild != NULL &&
+            EQUAL(psSRItemNode->pszValue,"WKID") )
+        {
+            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
+            *pOutWKID = pszUnescaped;
+            CPLFree(pszUnescaped);
+        }
+        /* The WKT well-known text can be converted by OGR */
+        else if( psSRItemNode->eType == CXT_Element &&
+                psSRItemNode->psChild != NULL &&
+                EQUAL(psSRItemNode->pszValue,"WKT") )
+        {
+            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
+            *pOutWkt = pszUnescaped;
+            CPLFree(pszUnescaped);
+        }
+
+    }
+    return (*pOutWkt != "" || *pOutWKID != "");
+}
+
+/************************************************************************/
+/*                          GDBToOGRFields()                           */
+/************************************************************************/
+
+bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
+{
+    m_vOGRFieldToESRIField.clear();
+
+    if (psRoot->psChild == NULL || psRoot->psChild->psNext == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Unrecognized GDB XML Schema");
+
+        return false;
+    }
+
+    psRoot = psRoot->psChild->psNext; //change root to "FieldArray"
+
+    //CPLAssert(ogrToESRIFieldMapping.size() == pOGRFeatureDef->GetFieldCount());
+
+    CPLXMLNode* psFieldNode;
+
+    for( psFieldNode = psRoot->psChild;
+        psFieldNode != NULL;
+        psFieldNode = psFieldNode->psNext )
+    {
+        //loop through all "Field" elements
+        //
+
+        if( psFieldNode->eType == CXT_Element && psFieldNode->psChild != NULL &&
+            EQUAL(psFieldNode->pszValue,"Field"))
+        {
+
+            CPLXMLNode* psFieldItemNode;
+            std::string fieldName;
+            std::string fieldType;
+            int nLength = 0;
+            int nPrecision = 0;
+
+            // loop through all items in Field element
+            //
+
+            for( psFieldItemNode = psFieldNode->psChild;
+                psFieldItemNode != NULL;
+                psFieldItemNode = psFieldItemNode->psNext )
+            {
+                if (psFieldItemNode->eType == CXT_Element)
+                {
+
+                if (EQUAL(psFieldItemNode->pszValue,"Name"))
+                {
+                    char* pszUnescaped = CPLUnescapeString(
+                        psFieldItemNode->psChild->pszValue, NULL, CPLES_XML);
+                    fieldName = pszUnescaped;
+                    CPLFree(pszUnescaped);
+                }
+                else if (EQUAL(psFieldItemNode->pszValue,"Type") )
+                {
+                    char* pszUnescaped = CPLUnescapeString(
+                        psFieldItemNode->psChild->pszValue, NULL, CPLES_XML);
+                    fieldType = pszUnescaped;
+                    CPLFree(pszUnescaped);
+                }
+                else if (EQUAL(psFieldItemNode->pszValue,"GeometryDef") )
+                {
+                    if (!ParseGeometryDef(psFieldItemNode))
+                        return false; // if we failed parsing the GeometryDef, we are done!
+                }
+                else if (EQUAL(psFieldItemNode->pszValue,"Length") )
+                {
+                    nLength = atoi(psFieldItemNode->psChild->pszValue);
+                }
+                else if (EQUAL(psFieldItemNode->pszValue,"Precision") )
+                {
+                    nPrecision = atoi(psFieldItemNode->psChild->pszValue);
+                }
+                }
+            }
+
+
+            ///////////////////////////////////////////////////////////////////
+            // At this point we have parsed everything about the current field
+
+
+            if (fieldType == "esriFieldTypeGeometry")
+            {
+                m_strShapeFieldName = fieldName;
+
+                continue; // finish here for special field - don't add as OGR fielddef
+            }
+            else if (fieldType == "esriFieldTypeOID")
+            {
+                //m_strOIDFieldName = fieldName; // already set by this point
+
+                continue; // finish here for special field - don't add as OGR fielddef
+            }
+
+            OGRFieldType ogrType;
+            //CPLDebug("FGDB", "name = %s, type = %s", fieldName.c_str(), fieldType.c_str() );
+            if (!GDBToOGRFieldType(fieldType, &ogrType))
+            {
+                // field cannot be mapped, skipping further processing
+                CPLError( CE_Warning, CPLE_AppDefined, "Skipping field: [%s] type: [%s] ",
+                fieldName.c_str(), fieldType.c_str() );
+                continue;
+            }
+
+
+            //TODO: Optimization - modify m_wstrSubFields so it only fetches fields that are mapped
+
+            OGRFieldDefn fieldTemplate( fieldName.c_str(), ogrType);
+            //fieldTemplate.SetWidth(nLength);
+            //fieldTemplate.SetPrecision(nPrecision);
+            m_pFeatureDefn->AddFieldDefn( &fieldTemplate );
+
+            m_vOGRFieldToESRIField.push_back(StringToWString(fieldName));
+            m_vOGRFieldToESRIFieldType.push_back( fieldType );
+
+        }
+    }
+
+    return true;
+}
+
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void FGdbLayer::ResetReading()
+{
+    long hr;
+
+    if (m_pOGRFilterGeometry && !m_pOGRFilterGeometry->IsEmpty())
+    {
+        // Search spatial
+        // As of beta1, FileGDB only supports bbox searched, if we have GEOS installed,
+        // we can do the rest ourselves.
+
+        OGREnvelope ogrEnv;
+
+        m_pOGRFilterGeometry->getEnvelope(&ogrEnv);
+
+        //spatial query
+        FileGDBAPI::Envelope env(ogrEnv.MinX, ogrEnv.MaxX, ogrEnv.MinY, ogrEnv.MaxY);
+
+        if FAILED(hr = m_pTable->Search(m_wstrSubfields, m_wstrWhereClause, env, true, *m_pEnumRows))
+        GDBErr(hr, "Failed Searching");
+
+        m_bFilterDirty = false;
+
+        return;
+    }
+
+    // Search non-spatial
+
+    if FAILED(hr = m_pTable->Search(m_wstrSubfields, m_wstrWhereClause, true, *m_pEnumRows))
+        GDBErr(hr, "Failed Searching");
+
+    m_bFilterDirty = false;
+  
+}
+
+/************************************************************************/
+/*                         SetSpatialFilter()                           */
+/************************************************************************/
+
+void FGdbLayer::SetSpatialFilter( OGRGeometry* pOGRGeom )
+{
+    if (m_pOGRFilterGeometry)
+    {
+        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
+        m_pOGRFilterGeometry = NULL;
+    }
+
+    if (pOGRGeom == NULL || pOGRGeom->IsEmpty())
+    {
+        m_bFilterDirty = true;
+
+        return;
+    }
+
+    m_pOGRFilterGeometry = pOGRGeom->clone();
+
+    m_pOGRFilterGeometry->transformTo(m_pSRS);
+
+    m_bFilterDirty = true;
+}
+
+/************************************************************************/
+/*                         SetSpatialFilterRect()                       */
+/************************************************************************/
+
+void FGdbLayer::SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+{
+
+    //TODO: can optimize this by changing how the filter gets generated -
+    //this will work for now
+
+    OGRGeometry* pTemp = OGRGeometryFactory::createGeometry(wkbPolygon);
+
+    pTemp->assignSpatialReference(m_pSRS);
+
+    OGRLinearRing ring;
+
+    ring.addPoint( dfMinX, dfMinY );
+    ring.addPoint( dfMinX, dfMaxY );
+    ring.addPoint( dfMaxX, dfMaxY );
+    ring.addPoint( dfMaxX, dfMinY );
+    ring.addPoint( dfMinX, dfMinY );
+    ((OGRPolygon *) pTemp)->addRing( &ring );
+
+    SetSpatialFilter(pTemp);
+
+    OGRGeometryFactory::destroyGeometry(pTemp);
+}
+
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr FGdbLayer::SetAttributeFilter( const char* pszQuery )
+{
+    m_wstrWhereClause = StringToWString( (pszQuery != NULL) ? pszQuery : "" );
+
+    m_bFilterDirty = true;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           OGRFeatureFromGdbRow()                      */
+/************************************************************************/
+
+bool FGdbLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
+{
+    long hr;
+
+    OGRFeature* pOutFeature = new OGRFeature(m_pFeatureDefn);
+
+    /////////////////////////////////////////////////////////
+    // Translate OID
+    //
+
+    int32 oid = -1;
+    if (FAILED(hr = pRow->GetOID(oid)))
+    {
+        //this should never happen
+        delete pOutFeature;
+        return false;
+    }
+    pOutFeature->SetFID(oid);
+
+
+    /////////////////////////////////////////////////////////
+    // Translate Geometry
+    //
+
+    ShapeBuffer gdbGeometry;
+    if (!FAILED(hr = pRow->GetGeometry(gdbGeometry)))
+    {
+        OGRGeometry* pOGRGeo = NULL;
+
+        if ((!GDBGeometryToOGRGeometry(m_forceMulti, &gdbGeometry, m_pSRS, &pOGRGeo)) || pOGRGeo == NULL)
+        {
+            delete pOutFeature;
+            return GDBErr(hr, "Failed to translate FileGDB Geometry to OGR Geometry for row " + string(CPLSPrintf("%d", (int)oid)));
+        }
+
+        pOutFeature->SetGeometryDirectly(pOGRGeo);
+    }
+
+
+    //////////////////////////////////////////////////////////
+    // Map fields
+    //
+
+
+    size_t mappedFieldCount = m_vOGRFieldToESRIField.size();
+
+    bool foundBadColumn = false;
+
+    for (size_t i = 0; i < mappedFieldCount; ++i)
+    {
+        const wstring & wstrFieldName = m_vOGRFieldToESRIField[i];
+        const std::string & strFieldType = m_vOGRFieldToESRIFieldType[i];
+
+        bool isNull = false;
+
+        if (FAILED(hr = pRow->IsNull(wstrFieldName, isNull)))
+        {
+            GDBErr(hr, "Failed to determine NULL status from column " +
+                   WStringToString(wstrFieldName));
+            foundBadColumn = true;
+            continue;
+        }
+
+        if (isNull)
+        {
+            continue; //leave as unset
+        }
+
+        //
+        // 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())
+        {
+
+            case OFTInteger:
+            {
+                int32 val;
+
+                if (FAILED(hr = pRow->GetInteger(wstrFieldName, val)))
+                {
+                    int16 shortval;
+                    if (FAILED(hr = pRow->GetShort(wstrFieldName, shortval)))
+                    {
+                        GDBErr(hr, "Failed to determine integer value for column " +
+                               WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+                    val = shortval;
+                }
+
+                pOutFeature->SetField(i, (int)val);
+            }
+            break;
+
+            case OFTReal:
+            {
+                if (strFieldType == "esriFieldTypeSingle")
+                {
+                    float val;
+
+                    if (FAILED(hr = pRow->GetFloat(wstrFieldName, val)))
+                    {
+                        GDBErr(hr, "Failed to determine float value for column " +
+                               WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+
+                    pOutFeature->SetField(i, val);
+                }
+                else
+                {
+                    double val;
+
+                    if (FAILED(hr = pRow->GetDouble(wstrFieldName, val)))
+                    {
+                        GDBErr(hr, "Failed to determine real value for column " +
+                               WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+
+                    pOutFeature->SetField(i, val);
+                }
+            }
+            break;
+            case OFTString:
+            {
+                wstring val;
+
+                if (FAILED(hr = pRow->GetString(wstrFieldName, val)))
+                {
+                    GDBErr(hr, "Failed to determine string value for column " +
+                        WStringToString(wstrFieldName));
+                    foundBadColumn = true;
+                    continue;
+                }
+
+                pOutFeature->SetField(i, WStringToString(val).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;
+                }
+
+                pOutFeature->SetField(i, (int)binaryBuf.inUseLength, (GByte*)binaryBuf.byteArray);
+            }
+            break;
+            */
+
+            case OFTDateTime:
+            {
+                struct tm val;
+
+                if (FAILED(hr = pRow->GetDate(wstrFieldName, val)))
+                {
+                    GDBErr(hr, "Failed to determine date value for column " +
+                           WStringToString(wstrFieldName));
+                    foundBadColumn = true;
+                    continue;
+                }
+
+                pOutFeature->SetField(i, val.tm_year + 1900, val.tm_mon + 1,
+                                      val.tm_mday, val.tm_hour, val.tm_min, val.tm_sec);
+            // Examine test data to figure out how to extract that
+            }
+            break;
+
+            default:
+            {
+                if (!m_supressColumnMappingError)
+                {
+                    foundBadColumn = true;
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Row id: %d col:%d has unhandled col type (%d). Setting to NULL.",
+                            (int)oid, (int)i, m_pFeatureDefn->GetFieldDefn(i)->GetType());
+                }
+            }
+        }
+    }
+
+    if (foundBadColumn)
+        m_supressColumnMappingError = true;
+
+
+    *ppFeature = pOutFeature;
+
+    return true;
+}
+
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature* FGdbLayer::GetNextFeature()
+{
+    if (m_bFilterDirty)
+        ResetReading();
+
+
+    while (1) //want to skip errors
+    {
+        if (m_pEnumRows == NULL)
+            return NULL;
+
+        long hr;
+
+        Row row;
+
+        if (FAILED(hr = m_pEnumRows->Next(row)))
+        {
+            GDBErr(hr, "Failed fetching features");
+            return NULL;
+        }
+
+        if (hr != S_OK)
+        {
+        // It's OK, we are done fetching - failure is catched by FAILED macro
+            return NULL;
+        }
+
+        OGRFeature* pOGRFeature = NULL;
+
+        if (!OGRFeatureFromGdbRow(&row,  &pOGRFeature))
+        {
+            int32 oid = -1;
+            row.GetOID(oid);
+
+            GDBErr(hr, CPLSPrintf("Failed translating FGDB row [%d] to OGR Feature", oid));
+
+            //return NULL;
+            continue; //skip feature
+        }
+
+        return pOGRFeature;
+    }
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *FGdbLayer::GetFeature( long oid )
+{
+    // do query to fetch individual row
+
+    long           hr;
+    Row            row;
+    EnumRows       enumRows;
+    CPLString      osQuery;
+
+    osQuery.Printf("%s = %ld", m_strOIDFieldName.c_str(), oid);
+
+    if (FAILED(hr = m_pTable->Search(m_wstrSubfields, StringToWString(osQuery.c_str()), true, enumRows)))
+    {
+        GDBErr(hr, "Failed fetching row ");
+        return NULL;
+    }
+
+    if (FAILED(hr = enumRows.Next(row)))
+    {
+        GDBErr(hr, "Failed fetching row ");
+        return NULL;
+    }
+
+    if (hr != S_OK)
+        return NULL; //none found - but no failure
+
+
+    OGRFeature* pOGRFeature = NULL;
+
+    if (!OGRFeatureFromGdbRow(&row,  &pOGRFeature))
+    {
+        GDBErr(hr, "Failed translating ArcObjects row to OGR Feature");
+        return NULL;
+    }
+
+    return pOGRFeature;
+}
+
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int FGdbLayer::GetFeatureCount( int bForce )
+{
+    long           hr;
+    int32          rowCount = 0;
+
+    if (m_pOGRFilterGeometry != NULL || m_wstrWhereClause.size() != 0)
+        return OGRLayer::GetFeatureCount(bForce);
+
+    if (FAILED(hr = m_pTable->GetRowCount(rowCount)))
+    {
+        GDBErr(hr, "Failed counting rows");
+        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);
+}
+
+
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr FGdbLayer::GetExtent (OGREnvelope* psExtent, int bForce)
+{
+    if (m_pOGRFilterGeometry != NULL || m_wstrWhereClause.size() != 0 ||
+        m_strShapeFieldName.size() == 0)
+        return OGRLayer::GetExtent(psExtent, bForce);
+
+    long hr;
+    Envelope envelope;
+    if (FAILED(hr = m_pTable->GetExtent(envelope)))
+    {
+        GDBErr(hr, "Failed fetching extent");
+        return OGRERR_FAILURE;
+    }
+
+    psExtent->MinX = envelope.xMin;
+    psExtent->MinY = envelope.yMin;
+    psExtent->MaxX = envelope.xMax;
+    psExtent->MaxY = envelope.yMax;
+
+    if (CPLIsNan(psExtent->MinX) ||
+        CPLIsNan(psExtent->MinY) ||
+        CPLIsNan(psExtent->MaxX) ||
+        CPLIsNan(psExtent->MaxY))
+        return OGRERR_FAILURE;
+
+    return OGRERR_NONE;
+}
+
+/* OGRErr FGdbLayer::StartTransaction ()
+{
+    if ( ! m_pTable ) 
+        return OGRERR_FAILURE;
+        
+    m_pTable->LoadOnlyMode(true);
+    m_pTable->SetWriteLock();
+    return OGRERR_NONE;
+    
+} */
+
+
+/* OGRErr FGdbLayer::CommitTransaction ()
+{
+    if ( ! m_pTable ) 
+        return OGRERR_FAILURE;
+    
+    m_pTable->LoadOnlyMode(false);
+    m_pTable->FreeWriteLock();
+    return OGRERR_NONE;
+} */
+
+/* OGRErr FGdbLayer::RollbackTransaction ()
+{
+    if ( ! m_pTable ) 
+        return OGRERR_FAILURE;
+    
+    m_pTable->LoadOnlyMode(false);
+    m_pTable->FreeWriteLock();
+    return OGRERR_NONE;
+} */
+
+
+/************************************************************************/
+/*                           GetLayerXML()                              */
+/* Return XML definition of the Layer as provided by FGDB. Caller must  */
+/* free result.                                                         */
+/* Not currently used by the driver, but can be used by external code   */
+/* for specific purposes.                                               */
+/************************************************************************/
+
+OGRErr FGdbLayer::GetLayerXML (char **ppXml)
+{
+    long hr;
+    std::string xml;
+
+    if ( FAILED(hr = m_pTable->GetDefinition(xml)) )
+    {
+        GDBErr(hr, "Failed fetching XML table definition");
+        return OGRERR_FAILURE;
+    }
+
+    *ppXml = CPLStrdup(xml.c_str());
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           GetLayerMetadataXML()                      */
+/* Return XML metadata for the Layer as provided by FGDB. Caller must  */
+/* free result.                                                         */
+/* Not currently used by the driver, but can be used by external code   */
+/* for specific purposes.                                               */
+/************************************************************************/
+
+OGRErr FGdbLayer::GetLayerMetadataXML (char **ppXml)
+{
+    long hr;
+    std::string xml;
+
+    if ( FAILED(hr = m_pTable->GetDocumentation(xml)) )
+    {
+        GDBErr(hr, "Failed fetching XML table metadata");
+        return OGRERR_FAILURE;
+    }
+
+    *ppXml = CPLStrdup(xml.c_str());
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int FGdbLayer::TestCapability( const char* pszCap )
+{
+
+    if (EQUAL(pszCap,OLCRandomRead))
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCFastFeatureCount)) 
+        return m_pOGRFilterGeometry == NULL && m_wstrWhereClause.size() == 0;
+
+    else if (EQUAL(pszCap,OLCFastSpatialFilter))
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCFastGetExtent))
+        return m_pOGRFilterGeometry == NULL && m_wstrWhereClause.size() == 0;
+
+    else if (EQUAL(pszCap,OLCCreateField)) /* CreateField() */
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCSequentialWrite)) /* CreateFeature() */
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCStringsAsUTF8)) /* Native UTF16, converted to UTF8 */
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCReorderFields)) /* TBD ReorderFields() */
+        return FALSE;
+
+    else if (EQUAL(pszCap,OLCDeleteFeature)) /* TBD DeleteFeature() */
+        return FALSE;
+
+    else if (EQUAL(pszCap,OLCRandomWrite)) /* TBD SetFeature() */
+        return FALSE;
+
+    else if (EQUAL(pszCap,OLCDeleteField)) /* TBD DeleteField() */
+        return FALSE;
+        
+    else if (EQUAL(pszCap,OLCFastSetNextByIndex)) /* TBD FastSetNextByIndex() */
+        return FALSE;
+
+    else if (EQUAL(pszCap,OLCTransactions)) /* TBD Start/End Transactions() */
+        return FALSE;
+        
+    else 
+        return FALSE;
+}
+
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
new file mode 100644
index 0000000..4a8c589
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
@@ -0,0 +1,507 @@
+/******************************************************************************
+* $Id: FGdbUtils.cpp 23328 2011-11-05 20:27:40Z rouault $
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Different utility functions used in FileGDB OGR driver.
+* Author:   Ragi Yaser Burhum, ragi at burhum.com
+*           Paul Ramsey, pramsey at cleverelephant.ca
+*
+******************************************************************************
+* Copyright (c) 2010, Ragi Yaser Burhum
+* Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+*
+* 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 "FGdbUtils.h"
+#include <algorithm>
+
+#include "ogr_api.h"
+#include "ogrpgeogeometry.h"
+
+CPL_CVSID("$Id: FGdbUtils.cpp 23328 2011-11-05 20:27:40Z rouault $");
+
+using std::string;
+
+/*************************************************************************/
+/*                          StringToWString()                            */
+/*************************************************************************/
+
+std::wstring StringToWString(const std::string& utf8string)
+{
+    wchar_t* pszUTF16 = CPLRecodeToWChar( utf8string.c_str(), CPL_ENC_UTF8, CPL_ENC_UCS2);
+    std::wstring utf16string = pszUTF16;
+    CPLFree(pszUTF16);
+    return utf16string;
+}
+
+/*************************************************************************/
+/*                          WStringToString()                            */
+/*************************************************************************/
+
+std::string WStringToString(const std::wstring& utf16string)
+{
+    char* pszUTF8 = CPLRecodeFromWChar( utf16string.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8 );
+    std::string utf8string = pszUTF8;
+    CPLFree(pszUTF8);
+    return utf8string; 
+}
+
+/*************************************************************************/
+/*                                GDBErr()                               */
+/*************************************************************************/
+
+bool GDBErr(long int hr, std::string desc)
+{
+    std::wstring fgdb_error_desc_w;
+    fgdbError er;
+    er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
+    if ( er == S_OK )
+    {
+        std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error: %s (%s)", desc.c_str(), fgdb_error_desc.c_str());
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error (%ld): %s", hr, desc.c_str());
+    }
+    // FIXME? EvenR: not sure if ClearErrors() is really necessary, but as it, it causes crashes in case of
+    // repeated errors
+    //FileGDBAPI::ErrorInfo::ClearErrors();
+
+    return false;
+}
+
+/*************************************************************************/
+/*                            GDBDebug()                                 */
+/*************************************************************************/
+
+bool GDBDebug(long int hr, std::string desc)
+{
+    std::wstring fgdb_error_desc_w;
+    fgdbError er;
+    er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
+    if ( er == S_OK )
+    {
+        std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
+        CPLDebug("FGDB", "%s (%s)", desc.c_str(), fgdb_error_desc.c_str());
+    }
+    else
+    {
+        CPLDebug("FGDB", "%s", desc.c_str());
+    }
+    // FIXME? EvenR: not sure if ClearErrors() is really necessary, but as it, it causes crashes in case of
+    // repeated errors
+    //FileGDBAPI::ErrorInfo::ClearErrors();
+
+    return false;
+}
+
+/*************************************************************************/
+/*                            GDBToOGRGeometry()                         */
+/*************************************************************************/
+
+bool GDBToOGRGeometry(string geoType, bool hasZ, OGRwkbGeometryType* pOut)
+{
+    if (geoType == "esriGeometryPoint")
+    {
+        *pOut = hasZ? wkbPoint25D : wkbPoint;
+    }
+    else if (geoType == "esriGeometryMultipoint")
+    {
+        *pOut = hasZ? wkbMultiPoint25D : wkbMultiPoint;
+    }
+    else if (geoType == "esriGeometryLine")
+    {
+        *pOut = hasZ? wkbLineString25D : wkbLineString;
+    }
+    else if (geoType == "esriGeometryPolyline")
+    {
+        *pOut = hasZ? wkbMultiLineString25D : wkbMultiLineString;
+    }
+    else if (geoType == "esriGeometryPolygon" ||
+            geoType == "esriGeometryMultiPatch")
+    {
+        *pOut = hasZ? wkbMultiPolygon25D : wkbMultiPolygon; // no mapping to single polygon
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "Cannot map esriGeometryType(%s) to OGRwkbGeometryType", geoType.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+/*************************************************************************/
+/*                            OGRGeometryToGDB()                         */
+/*************************************************************************/
+
+bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ)
+{
+    switch (ogrType)
+    {
+        /* 3D forms */
+        case wkbPoint25D:
+        {
+            *gdbType = "esriGeometryPoint";
+            *hasZ = true;
+            break;
+        }
+
+        case wkbMultiPoint25D:
+        {
+            *gdbType = "esriGeometryMultipoint";
+            *hasZ = true;
+            break;
+        }
+
+        case wkbLineString25D:
+        case wkbMultiLineString25D:
+        {
+            *gdbType = "esriGeometryPolyline";
+            *hasZ = true;
+            break;
+        }
+
+        case wkbPolygon25D:
+        case wkbMultiPolygon25D:
+        {
+            *gdbType = "esriGeometryPolygon";
+            *hasZ = true;
+            break;
+        }
+
+        /* 2D forms */
+        case wkbPoint:
+        {
+            *gdbType = "esriGeometryPoint";
+            *hasZ = false;
+            break;
+        }
+
+        case wkbMultiPoint:
+        {
+            *gdbType = "esriGeometryMultipoint";
+            *hasZ = false;
+            break;
+        }
+
+        case wkbLineString:
+        case wkbMultiLineString:
+        {
+            *gdbType = "esriGeometryPolyline";
+            *hasZ = false;
+            break;
+        }
+
+        case wkbPolygon:
+        case wkbMultiPolygon:
+        {
+            *gdbType = "esriGeometryPolygon";
+            *hasZ = false;
+            break;
+        }
+        
+        default:
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cannot map OGRwkbGeometryType (%s) to ESRI type",
+                      OGRGeometryTypeToName(ogrType));
+            return false;
+        }
+    }
+    return true;
+}
+
+/*************************************************************************/
+/*                            GDBToOGRFieldType()                        */
+/*************************************************************************/
+
+// We could make this function far more robust by doing automatic coertion of types,
+// and/or skipping fields we do not know. But our purposes this works fine
+bool GDBToOGRFieldType(std::string gdbType, OGRFieldType* pOut)
+{
+    /*
+    ESRI types
+    esriFieldTypeSmallInteger = 0,
+    esriFieldTypeInteger = 1,
+    esriFieldTypeSingle = 2,
+    esriFieldTypeDouble = 3,
+    esriFieldTypeString = 4,
+    esriFieldTypeDate = 5,
+    esriFieldTypeOID = 6,
+    esriFieldTypeGeometry = 7,
+    esriFieldTypeBlob = 8,
+    esriFieldTypeRaster = 9,
+    esriFieldTypeGUID = 10,
+    esriFieldTypeGlobalID = 11,
+    esriFieldTypeXML = 12
+    */
+
+    //OGR Types
+
+    //            Desc                                 Name                GDB->OGR Mapped By Us?
+    /** Simple 32bit integer *///                   OFTInteger = 0,             YES
+    /** List of 32bit integers *///                 OFTIntegerList = 1,         NO
+    /** Double Precision floating point *///        OFTReal = 2,                YES
+    /** List of doubles *///                        OFTRealList = 3,            NO
+    /** String of ASCII chars *///                  OFTString = 4,              YES
+    /** Array of strings *///                       OFTStringList = 5,          NO
+    /** deprecated *///                             OFTWideString = 6,          NO
+    /** deprecated *///                             OFTWideStringList = 7,      NO
+    /** Raw Binary data *///                        OFTBinary = 8,              YES
+    /** Date *///                                   OFTDate = 9,                NO
+    /** Time *///                                   OFTTime = 10,               NO
+    /** Date and Time *///                          OFTDateTime = 11            YES
+
+    if (gdbType == "esriFieldTypeSmallInteger" ||
+        gdbType == "esriFieldTypeInteger")
+    {
+        *pOut = OFTInteger;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeSingle" ||
+        gdbType == "esriFieldTypeDouble")
+    {
+        *pOut = OFTReal;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeGUID" ||
+        gdbType == "esriFieldTypeGlobalID" ||
+        gdbType == "esriFieldTypeXML" ||
+        gdbType == "esriFieldTypeString")
+    {
+        *pOut = OFTString;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeDate")
+    {
+        *pOut = OFTDateTime;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeBlob")
+    {
+        *pOut = OFTBinary;
+        return true;
+    }
+    else
+    {
+        /* Intentionally fail at these
+        esriFieldTypeOID
+        esriFieldTypeGeometry
+        esriFieldTypeRaster
+        */
+        CPLError( CE_Warning, CPLE_AppDefined, "%s", ("Cannot map field " + gdbType).c_str());
+
+        return false;
+    }
+}
+
+/*************************************************************************/
+/*                            OGRToGDBFieldType()                        */
+/*************************************************************************/
+
+bool OGRToGDBFieldType(OGRFieldType ogrType, std::string* gdbType)
+{
+    switch(ogrType)
+    {
+        case OFTInteger:
+        {
+            *gdbType = "esriFieldTypeInteger";
+            break;
+        }
+        case OFTReal:
+        {
+            *gdbType = "esriFieldTypeDouble";
+            break;
+        }
+        case OFTString:
+        {
+            *gdbType = "esriFieldTypeString";
+            break;
+        }
+        case OFTBinary:
+        {
+            *gdbType = "esriFieldTypeBlob";
+            break;
+        }
+        case OFTDate:
+        case OFTDateTime:
+        {
+            *gdbType = "esriFieldTypeDate";
+            break;
+        }
+        default:
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Cannot map OGR field type (%s)",
+                      OGR_GetFieldTypeName(ogrType) );
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/*************************************************************************/
+/*                       GDBFieldTypeToWidthPrecision()                  */
+/*************************************************************************/
+
+bool GDBFieldTypeToWidthPrecision(std::string &gdbType, int *width, int *precision)
+{
+    *precision = 0;
+
+    if(gdbType == "esriFieldTypeSmallInteger" )
+    {
+        *width = 2;
+    }
+    else if(gdbType == "esriFieldTypeInteger" )
+    {
+        *width = 12;
+    }
+    else if(gdbType == "esriFieldTypeSingle" )
+    {
+        *width = 12;
+        *precision = 5;
+    }
+    else if(gdbType == "esriFieldTypeDouble" )
+    {
+        *width = 24;
+        *precision = 15;
+    }
+    else if(gdbType == "esriFieldTypeString" )
+    {
+        *width = 2147483647;
+    }
+    else if(gdbType == "esriFieldTypeDate" )
+    {
+        *width = 32;
+    }
+    else if(gdbType == "esriFieldTypeOID" )
+    {
+        *width = 15;
+    }
+    else
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Cannot map ESRI field type (%s)", gdbType.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+/*************************************************************************/
+/*                       GDBFieldTypeToWidthPrecision()                  */
+/*************************************************************************/
+
+bool GDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry,
+                              OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry)
+{
+
+    OGRGeometry* pOGRGeometry = NULL;
+
+    OGRErr eErr = OGRCreateFromShapeBin( pGdbGeometry->shapeBuffer,
+                                &pOGRGeometry,
+                                pGdbGeometry->inUseLength);
+
+    //OGRErr eErr = OGRGeometryFactory::createFromWkb(pGdbGeometry->shapeBuffer, pOGRSR, &pOGRGeometry, pGdbGeometry->inUseLength );
+
+    if (eErr != OGRERR_NONE)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed attempting to import GDB WKB Geometry. OGRGeometryFactory err:%d", eErr);
+        return false;
+    }
+
+    if( pOGRGeometry != NULL )
+    {
+        // force geometries to multi if requested
+
+        // If it is a polygon, force to MultiPolygon since we always produce multipolygons
+        if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPolygon)
+        {
+            pOGRGeometry = OGRGeometryFactory::forceToMultiPolygon(pOGRGeometry);
+        }
+        else if (forceMulti)
+        {
+            if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbLineString)
+            {
+                pOGRGeometry = OGRGeometryFactory::forceToMultiLineString(pOGRGeometry);
+            }
+            else if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPoint)
+            {
+                pOGRGeometry = OGRGeometryFactory::forceToMultiPoint(pOGRGeometry);
+            }
+        }
+
+        if (pOGRGeometry)
+            pOGRGeometry->assignSpatialReference( pOGRSR );
+    }
+
+
+    *ppOutGeometry = pOGRGeometry;
+
+    return true;
+}
+
+/*************************************************************************/
+/*                         GDBToOGRSpatialReference()                    */
+/*************************************************************************/
+
+bool GDBToOGRSpatialReference(const string & wkt, OGRSpatialReference** ppSR)
+{
+    if (wkt.size() <= 0)
+    {
+        CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is NULL");
+        return false;
+    }
+
+    *ppSR = new OGRSpatialReference(wkt.c_str());
+
+    OGRErr result = (*ppSR)->morphFromESRI();
+
+    if (result == OGRERR_NONE)
+    {
+        return true;
+    }
+    else
+    {
+        delete *ppSR;
+        *ppSR = NULL;
+
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed morhping from ESRI Geometry: %s", wkt.c_str());
+
+        return false;
+    }
+}
+
+/*************************************************************************/
+/*                           FGDB_CPLAddXMLAttribute()                   */
+/*************************************************************************/
+
+/* Utility method for attributing nodes */
+void FGDB_CPLAddXMLAttribute(CPLXMLNode* node, const char* attrname, const char* attrvalue)
+{
+    if ( !node ) return;
+    CPLCreateXMLNode( CPLCreateXMLNode( node, CXT_Attribute, attrname ), CXT_Text, attrvalue );
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbUtils.h b/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
new file mode 100644
index 0000000..9c0fa4a
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ * $Id: FGdbUtils.h 23025 2011-09-02 19:57:13Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Various FileGDB OGR Datasource utility functions
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Ragi Yaser Burhum
+ *
+ * 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 _FGDB_UTILS_H_INCLUDED
+#define _FGDB_UTILS_H_INCLUDED
+
+#include "ogr_fgdb.h"
+#include <iostream>
+#include <string>
+#include "cpl_minixml.h"
+
+std::wstring StringToWString(const std::string& s);
+std::string WStringToString(const std::wstring& s);
+
+//
+// GDB API to OGR Geometry Mapping
+//
+
+// Type mapping
+bool GDBToOGRGeometry(std::string geoType, bool hasZ, OGRwkbGeometryType* pOut);
+bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ);
+
+
+bool GDBToOGRSpatialReference(const std::string & wkt, OGRSpatialReference** ppSR);
+
+// Feature mapping 
+bool GDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry, 
+                              OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry);
+
+//temporary version - until we can parse the full binary format
+bool GhettoGDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry, 
+                                    OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry);
+//
+// GDB API to OGR Field Mapping
+//
+bool GDBToOGRFieldType(std::string gdbType, OGRFieldType* ogrType);
+bool OGRToGDBFieldType(OGRFieldType ogrType, std::string* gdbType);
+
+//
+// GDB Field Width defaults
+//
+bool GDBFieldTypeToWidthPrecision(std::string &gdbType, int *width, int *precision);
+
+//
+// GDBAPI error to OGR
+//
+bool GDBErr(long hr, std::string desc);
+bool GDBDebug(long hr, std::string desc);
+
+//
+// Utility for adding attributes to CPL nodes
+//
+void FGDB_CPLAddXMLAttribute(CPLXMLNode* node, const char* attrname, const char* attrvalue);
+
+#endif
diff --git a/ogr/ogrsf_frmts/filegdb/GNUmakefile b/ogr/ogrsf_frmts/filegdb/GNUmakefile
new file mode 100644
index 0000000..93a23e3
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	FGdbDatasource.o FGdbDriver.o FGdbLayer.o FGdbUtils.o
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(FGDB_INC) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_fgdb.h
diff --git a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
new file mode 100644
index 0000000..bc78212
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
@@ -0,0 +1,73 @@
+<html>
+<head>
+<title>ESRI File Geodatabase (FileGDB)</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>ESRI File Geodatabase (FileGDB)</h1>
+
+<p>The FileGDB driver provides read and write access to File Geodatabases (.gdb directories) created by ArcGIS 10 and above.</p>
+
+
+<h2>Requirements</h2>
+
+<p>
+	<ul>
+		<li><a href="http://resources.arcgis.com/fr/content/geodatabases/10.0/file-gdb-api">FileGDB API SDK</a></li>
+        <li>OGR >= 1.9.0</li>
+	</ul>
+</p>
+
+<h2>Dataset Creation Options</h2>
+
+<p>None.</p>
+
+<h2>Layer Creation Options</h2>
+
+<ul>
+	<li><b>FEATURE_DATASET</b>: When this option is set, the new layer will be created inside the named FeatureDataset folder. If the folder does not already exist, it will be created.<p>
+	<li><b>GEOMETRY_NAME</b>: Set name of geometry column in new layer. Defaults to "SHAPE".<p>
+	<li><b>OID_NAME</b>: Name of the OID column to create. Defaults to "OBJECTID".<p>
+	<li><b>XORIGIN, YORIGIN, ZORIGIN, XYSCALE, ZSCALE</b>: These parameters control the <a href="http://help.arcgis.com/en/sdk/10.0/java_ao_adf/conceptualhelp/engine/index.html#//00010000037m000000">coordinate precision grid</a>  inside the file geodatabase. The dimensions of the grid are determined by the origin, and the scale. The origin defines the location of a reference grid point in space. The scale is the reciprocal of the resolution. So, to get a grid with an origin at 0 and a resolution of 0.001 on all axes, you would set all the origins to 0 and all the scales to 1000.<p>
+	<li><b>XYTOLERANCE, ZTOLERANCE</b>: These parameters control the snapping tolerance used for advanced ArcGIS features like network and topology rules. They won't effect any OGR operations, but they will by used by ArcGIS. The units of the parameters are the units of the coordinate reference system.<p>
+</ul>
+
+<h2>Examples</h2>
+
+<ul>
+	<li>Read layer from FileGDB and load into PostGIS:<p>
+	<code>ogr2ogr -overwrite -skipfailures -f "PostgreSQL" PG:"host=myhost user=myuser dbname=mydb password=mypass" "C:\somefolder\BigFileGDB.gdb" "MyFeatureClass"</code>
+
+	<li>Get detailed info for FileGDB:<p>
+	<code>ogrinfo -al "C:\somefolder\MyGDB.gdb"</code>
+
+</ul>
+
+<h2>Building Notes</h2>
+
+<p> Read the <a href="http://trac.osgeo.org/gdal/wiki/BuildingOnWindows">GDAL Windows Building example for Plugins</a>. You will find a similar section in nmake.opt for FileGDB. After you are done, go to the <i>$gdal_source_root\ogr\ogrsf_frmts\filegdb</i> folder and execute:</p>
+
+<p>
+	<code>
+		nmake /f makefile.vc plugin
+		nmake /f makefile.vc plugin-install
+	</code>
+</p>
+
+
+<h2>Known Issues</h2>
+
+<ul>
+	<li>Blob fields have not been implemented.</li>
+	<li>FGDB coordinate snapping will cause geometries to be altered during writing. Use the origin and scale layer creation options to control the snapping behavior.</li>
+</ul>
+
+<h2>Links</h2>
+
+<ul>
+<li><a href="http://resources.arcgis.com/fr/content/geodatabases/10.0/file-gdb-api">ESRI File Geodatabase API Page</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/filegdb/makefile.vc b/ogr/ogrsf_frmts/filegdb/makefile.vc
new file mode 100644
index 0000000..bd64190
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/makefile.vc
@@ -0,0 +1,33 @@
+OBJ     =       FGdbDriver.obj FGdbDatasource.obj FGdbLayer.obj FGdbUtils.obj
+EXTRAFLAGS =	-I.. -I..\.. -I$(FGDB_INC)
+
+GDAL_ROOT	=	..\..\..
+
+PLUGIN_DLL 	=	ogr_FileGDB.dll
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	$(INSTALL) *.obj ..\o
+
+all:	default
+
+clean:
+	-del *.obj
+	-del *.dll
+	-del *.exp
+	-del *.lib
+	-del *.manifest
+	-del *.pdb
+	-del *.tlh
+
+plugin: $(PLUGIN_DLL)
+
+$(PLUGIN_DLL):	$(OBJ)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDAL_ROOT)/gdal_i.lib $(FGDB_LIB) ..\ogrsf_frmts.lib 
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
diff --git a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
new file mode 100644
index 0000000..8103c30
--- /dev/null
+++ b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
@@ -0,0 +1,224 @@
+/******************************************************************************
+* $Id: ogr_fgdb.h 23027 2011-09-02 22:19:29Z rouault $
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Standard includes and class definitions ArcObjects OGR driver.
+* Author:   Ragi Yaser Burhum, ragi at burhum.com
+*
+******************************************************************************
+* Copyright (c) 2009, Ragi Yaser Burhum
+*
+* 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_FGDB_H_INCLUDED
+#define _OGR_FGDB_H_INCLUDED
+
+#include <vector>
+#include "ogrsf_frmts.h"
+
+/* GDAL string utilities */
+#include "cpl_string.h"
+
+/* GDAL XML handler */
+#include "cpl_minixml.h"
+
+/* FGDB API headers */
+#include "FileGDBAPI.h"
+
+/************************************************************************
+* Default layer creation options
+*/
+
+#define FGDB_FEATURE_DATASET "";
+#define FGDB_GEOMETRY_NAME "SHAPE"
+#define FGDB_OID_NAME "OBJECTID"
+
+
+/* The ESRI FGDB API namespace */
+using namespace FileGDBAPI;
+
+
+/************************************************************************/
+/*                            FGdbLayer                                 */
+/************************************************************************/
+
+class FGdbDataSource;
+
+class FGdbLayer : public OGRLayer
+{
+public:
+
+  FGdbLayer();
+  virtual ~FGdbLayer();
+
+  // Internal used by FGDB driver */
+  bool Initialize(FGdbDataSource* pParentDataSource, Table* pTable, std::wstring wstrTablePath, std::wstring wstrType);
+  bool Create(FGdbDataSource* pParentDataSource, const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions);
+  bool CreateFeatureDataset(FGdbDataSource* pParentDataSource, std::string feature_dataset_name, OGRSpatialReference* poSRS, char** papszOptions );
+
+  // 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();
+  virtual OGRFeature* GetFeature( long nFeatureId );
+
+  Table* GetTable() { return m_pTable; }
+
+  std::wstring GetTablePath() const { return m_wstrTablePath; }
+  std::wstring GetType() const { return m_wstrType; }
+
+  virtual OGRErr      CreateField( OGRFieldDefn *poField, int bApproxOK );
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+  virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+  virtual int         GetFeatureCount( int bForce );
+  virtual OGRErr      SetAttributeFilter( const char *pszQuery );
+  virtual void 	      SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
+  virtual void        SetSpatialFilter( OGRGeometry * );
+
+//  virtual OGRErr        StartTransaction( );
+//  virtual OGRErr        CommitTransaction( );
+//  virtual OGRErr        RollbackTransaction( );
+
+  OGRFeatureDefn *    GetLayerDefn() { return m_pFeatureDefn; }
+	
+  virtual OGRSpatialReference *GetSpatialRef() { return m_pSRS; }
+
+  virtual int         TestCapability( const char * );
+
+  // Access the XML directly. The 2 following methods are not currently used by the driver, but
+  // can be used by external code for specific purposes.
+  OGRErr              GetLayerXML ( char **poXml );
+  OGRErr              GetLayerMetadataXML ( char **poXmlMeta );
+  
+protected:
+
+  bool GDBToOGRFields(CPLXMLNode* psFields);  
+  bool ParseGeometryDef(CPLXMLNode* psGeometryDef);
+  bool ParseSpatialReference(CPLXMLNode* psSpatialRefNode, std::string* pOutWkt, std::string* pOutWKID);
+
+  bool OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature);
+  
+  FGdbDataSource* m_pDS;
+  Table* m_pTable;
+  OGRFeatureDefn* m_pFeatureDefn;
+  OGRSpatialReference* m_pSRS;
+
+  std::string m_strName; //contains underlying FGDB table name (not catalog name)
+
+  std::string m_strOIDFieldName;
+  std::string m_strShapeFieldName;
+
+  std::wstring m_wstrTablePath;
+  std::wstring m_wstrType; // the type: "Table" or "Feature Class"
+
+  std::wstring m_wstrSubfields;
+  std::wstring m_wstrWhereClause;
+  OGRGeometry* m_pOGRFilterGeometry;
+  EnumRows*    m_pEnumRows;
+
+  bool        m_bFilterDirty; //optimization to avoid multiple calls to search until necessary
+
+
+  std::vector<std::wstring> m_vOGRFieldToESRIField; //OGR Field Index to ESRI Field Name Mapping
+  std::vector<std::string> m_vOGRFieldToESRIFieldType; //OGR Field Index to ESRI Field Type Mapping
+
+  //buffers are used for avoiding constant reallocation of temp memory
+  //unsigned char* m_pBuffer;
+  //long  m_bufferSize; //in bytes
+  
+  bool  m_supressColumnMappingError;
+  bool  m_forceMulti;
+
+};
+
+/************************************************************************/
+/*                           FGdbDataSource                            */
+/************************************************************************/
+class FGdbDataSource : public OGRDataSource
+{
+
+public:
+  FGdbDataSource();
+  virtual ~FGdbDataSource();
+
+  int         Open(Geodatabase* pGeodatabase, const char *, int );
+
+  const char* GetName() { return m_pszName; }
+  int         GetLayerCount() { return static_cast<int>(m_layers.size()); }
+
+  OGRLayer*   GetLayer( int );
+
+  virtual OGRLayer* CreateLayer( const char *, OGRSpatialReference* = NULL, OGRwkbGeometryType = wkbUnknown, char** = NULL );
+
+  virtual OGRErr DeleteLayer( int );
+
+  int TestCapability( const char * );
+
+  Geodatabase* GetGDB() { return m_pGeodatabase; }
+
+  /*
+  protected:
+
+  void EnumerateSpatialTables();
+  void OpenSpatialTable( const char* pszTableName );
+  */
+protected:
+  bool LoadLayers(const std::wstring & parent);
+  bool OpenFGDBTables(const std::wstring &type,
+                      const std::vector<std::wstring> &layers);
+
+  char* m_pszName;
+  std::vector <FGdbLayer*> m_layers;
+  Geodatabase* m_pGeodatabase;
+
+};
+
+/************************************************************************/
+/*                              FGdbDriver                                */
+/************************************************************************/
+
+class FGdbDriver : public OGRSFDriver
+{
+
+public:
+  FGdbDriver();
+  virtual ~FGdbDriver();
+
+  virtual const char *GetName();
+  virtual OGRDataSource *Open( const char *, int );
+  virtual int TestCapability( const char * );
+  virtual OGRDataSource *CreateDataSource( const char *pszName, char ** = NULL);
+  virtual OGRErr DeleteDataSource( const char *pszDataSource );
+
+  void OpenGeodatabase(std::string, Geodatabase** ppGeodatabase);
+
+private:
+
+};
+
+CPL_C_START
+void CPL_DLL RegisterOGRFileGDB();
+CPL_C_END
+
+#endif /* ndef _OGR_PG_H_INCLUDED */
+
+
diff --git a/ogr/ogrsf_frmts/generic/GNUmakefile b/ogr/ogrsf_frmts/generic/GNUmakefile
index 57219cb..519d9b6 100644
--- a/ogr/ogrsf_frmts/generic/GNUmakefile
+++ b/ogr/ogrsf_frmts/generic/GNUmakefile
@@ -36,7 +36,13 @@ BASEFORMATS = \
 	-DOPENAIR_ENABLED \
 	-DPDS_ENABLED \
 	-DHTF_ENABLED \
-	-DAERONAVFAA_ENABLED
+	-DAERONAVFAA_ENABLED \
+	-DEDIGEO_ENABLED \
+	-DSVG_ENABLED \
+	-DIDRISI_ENABLED \
+	-DARCGEN_ENABLED \
+	-DSEGUKOOA_ENABLED \
+	-DSEGY_ENABLED
 
 CXXFLAGS :=     $(CXXFLAGS) -DINST_DATA=\"$(INST_DATA)\" $(BASEFORMATS)
 
@@ -52,6 +58,10 @@ ifeq ($(HAVE_SDE),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DSDE_ENABLED
 endif
 
+ifeq ($(HAVE_FGDB),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DFGDB_ENABLED
+endif
+
 ifeq ($(HAVE_OGR_PG),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DPG_ENABLED
 endif
@@ -133,6 +143,26 @@ ifeq ($(CURL_SETTING),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DWFS_ENABLED
 endif
 
+ifeq ($(GEOMEDIA_SETTING),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DGEOMEDIA_ENABLED
+endif
+
+ifeq ($(MDB_ENABLED),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DMDB_ENABLED
+endif
+
+ifeq ($(CURL_SETTING),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DGFT_ENABLED
+endif
+
+ifeq ($(CURL_SETTING),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DCOUCHDB_ENABLED
+endif
+
+ifeq ($(HAVE_FREEXL),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DFREEXL_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 882a1ef..98d943d 100644
--- a/ogr/ogrsf_frmts/generic/makefile.vc
+++ b/ogr/ogrsf_frmts/generic/makefile.vc
@@ -6,12 +6,13 @@ OBJ	=	ogrsfdriverregistrar.obj ogrlayer.obj ogr_gensql.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 -DVFK_ENABLED -DPGDUMP_ENABLED -DGPSBABEL_ENABLED -DSUA_ENABLED -DOPENAIR_ENABLED -DPDS_ENABLED -DHTF_ENABLED -DAERONAVFAA_ENABLED
+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 -DVFK_ENABLED -DPGDUMP_ENABLED -DGPSBABEL_ENABLED -DSUA_ENABLED -DOPENAIR_ENABLED -DPDS_ENABLED -DHTF_ENABLED -DAERONAVFAA_ENABLED -DEDIGEO_ENABLED -DSVG_ENABLED -DIDRISI_ENABLED -DARCGEN_ENABLED -DSEGUKOOA_ENABLED -DSEGY_ENABLED
 
 EXTRAFLAGS =	-I.. -I..\.. $(OGDIDEF) $(FMEDEF) $(OCIDEF) $(PGDEF) \
 		$(ODBCDEF) $(SQLITEDEF) $(MYSQLDEF) $(ILIDEF) $(DWGDEF) \
 		$(SDEDEF) $(BASEFORMATS) $(IDBDEF) $(NASDEF) $(DODSDEF) \
-		$(PCIDSKDEF) $(LIBKMLDEF) $(WFSDEF) $(SOSIDEF)
+		$(PCIDSKDEF) $(LIBKMLDEF) $(WFSDEF) $(SOSIDEF) $(GFTDEF) \
+		$(COUCHDBDEF) $(FGDBDEF) $(XLSDEF)
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
@@ -28,7 +29,7 @@ OGDIDEF	=	-DOGDI_ENABLED
 !ENDIF
 
 !IFDEF ODBC_SUPPORTED
-ODBCDEF	=	-DODBC_ENABLED -DPGEO_ENABLED -DMSSQLSPATIAL_ENABLED
+ODBCDEF	=	-DODBC_ENABLED -DPGEO_ENABLED -DMSSQLSPATIAL_ENABLED -DGEOMEDIA_ENABLED
 !ENDIF
 
 !IFDEF PG_LIB
@@ -90,6 +91,24 @@ WFSDEF = -DWFS_ENABLED
 SOSIDEF	= -DSOSI_ENABLED
 !ENDIF
 
+!IFDEF CURL_LIB
+GFTDEF = -DGFT_ENABLED
+!ENDIF
+
+!IFDEF CURL_LIB
+COUCHDBDEF = -DCOUCHDB_ENABLED
+!ENDIF
+
+!IFDEF FGDB_LIB
+!IF "$(FGDB_PLUGIN)" != "YES"
+FGDBDEF = -DFGDB_ENABLED
+!ENDIF
+!ENDIF
+
+!IFDEF FREEXL_LIBS
+XLSDEF = -DFREEXL_ENABLED
+!ENDIF
+
 default:	$(OBJ)
 
 clean:
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.cpp b/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
index 343ca5b..19eab79 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 22519 2011-06-08 19:36:29Z warmerdam $
+ * $Id: ogr_gensql.cpp 23683 2012-01-01 23:53:00Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGenSQLResultsLayer.
@@ -33,7 +33,35 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogr_gensql.cpp 22519 2011-06-08 19:36:29Z warmerdam $");
+CPL_CVSID("$Id: ogr_gensql.cpp 23683 2012-01-01 23:53:00Z rouault $");
+
+
+/************************************************************************/
+/*               OGRGenSQLResultsLayerHasSpecialField()                 */
+/************************************************************************/
+
+static
+int OGRGenSQLResultsLayerHasSpecialField(swq_expr_node* expr,
+                                         int nMinIndexForSpecialField)
+{
+    if (expr->eNodeType == SNT_COLUMN)
+    {
+        if (expr->table_index == 0)
+        {
+            return expr->field_index >= nMinIndexForSpecialField;
+        }
+    }
+    else if (expr->eNodeType == SNT_OPERATION)
+    {
+        for( int i = 0; i < expr->nSubExprCount; i++ )
+        {
+            if (OGRGenSQLResultsLayerHasSpecialField(expr->papoSubExpr[i],
+                                                     nMinIndexForSpecialField))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
 
 /************************************************************************/
 /*                       OGRGenSQLResultsLayer()                        */
@@ -42,7 +70,8 @@ CPL_CVSID("$Id: ogr_gensql.cpp 22519 2011-06-08 19:36:29Z warmerdam $");
 OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
                                               void *pSelectInfo, 
                                               OGRGeometry *poSpatFilter,
-                                              const char *pszWHERE )
+                                              const char *pszWHERE,
+                                              const char *pszDialect )
 
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
@@ -57,11 +86,6 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
     nExtraDSCount = 0;
     papoExtraDS = NULL;
 
-    if( pszWHERE )
-        this->pszWHERE = CPLStrdup(pszWHERE);
-    else
-        this->pszWHERE = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Identify all the layers involved in the SELECT.                 */
 /* -------------------------------------------------------------------- */
@@ -109,6 +133,29 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
     poSrcLayer = papoTableLayers[0];
 
 /* -------------------------------------------------------------------- */
+/*      If the user has explicitely requested a OGRSQL dialect, then    */
+/*      we should avoid to forward the where clause to the source layer */
+/*      when there is a risk it cannot understand it (#4022)            */
+/* -------------------------------------------------------------------- */
+    int bForwardWhereToSourceLayer = TRUE;
+    if( pszWHERE )
+    {
+        if( psSelectInfo->where_expr && pszDialect != NULL &&
+            EQUAL(pszDialect, "OGRSQL") )
+        {
+            int nMinIndexForSpecialField = poSrcLayer->GetLayerDefn()->GetFieldCount();
+            bForwardWhereToSourceLayer = !OGRGenSQLResultsLayerHasSpecialField
+                            (psSelectInfo->where_expr, nMinIndexForSpecialField);
+        }
+        if (bForwardWhereToSourceLayer)
+            this->pszWHERE = CPLStrdup(pszWHERE);
+        else
+            this->pszWHERE = NULL;
+    }
+    else
+        this->pszWHERE = NULL;
+
+/* -------------------------------------------------------------------- */
 /*      Now that we have poSrcLayer, we can install a spatial filter    */
 /*      if there is one.                                                */
 /* -------------------------------------------------------------------- */
@@ -169,8 +216,11 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
         else if( poSrcFDefn != NULL )
         {
             oFDefn.SetType( poSrcFDefn->GetType() );
-            oFDefn.SetWidth( poSrcFDefn->GetWidth() );
-            oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
+            if( psColDef->col_func != SWQCF_AVG )
+            {
+                oFDefn.SetWidth( poSrcFDefn->GetWidth() );
+                oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
+            }
         }
         else if ( psColDef->field_index >= iFIDFieldIndex )
         {
@@ -261,7 +311,10 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
 
     ResetReading();
 
-    SetIgnoredFields();
+    FindAndSetIgnoredFields();
+
+    if( !bForwardWhereToSourceLayer )
+        SetAttributeFilter( pszWHERE );
 }
 
 /************************************************************************/
@@ -498,6 +551,35 @@ int OGRGenSQLResultsLayer::TestCapability( const char *pszCap )
 }
 
 /************************************************************************/
+/*                        ContainGeomSpecialField()                     */
+/************************************************************************/
+
+int OGRGenSQLResultsLayer::ContainGeomSpecialField(swq_expr_node* expr)
+{
+    if (expr->eNodeType == SNT_COLUMN)
+    {
+        if( expr->table_index != -1 && 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;
+        }
+    }
+    else if (expr->eNodeType == SNT_OPERATION)
+    {
+        for( int i = 0; i < expr->nSubExprCount; i++ )
+        {
+            if (ContainGeomSpecialField(expr->papoSubExpr[i]))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/************************************************************************/
 /*                           PrepareSummary()                           */
 /************************************************************************/
 
@@ -522,15 +604,28 @@ int OGRGenSQLResultsLayer::PrepareSummary()
     poSrcLayer->ResetReading();
 
 /* -------------------------------------------------------------------- */
-/*      We treat COUNT(*) (or COUNT of anything without distinct) as    */
-/*      a special case, and fill with GetFeatureCount().                */
+/*      Ignore geometry reading if no spatial filter in place and that  */
+/*      the where clause doesn't include OGR_GEOMETRY, OGR_GEOM_WKT or  */
+/*      OGR_GEOM_AREA special fields.                                   */
+/* -------------------------------------------------------------------- */
+    int bSaveIsGeomIgnored = poSrcLayer->GetLayerDefn()->IsGeometryIgnored();
+    if ( m_poFilterGeom == NULL && ( psSelectInfo->where_expr == NULL ||
+                !ContainGeomSpecialField(psSelectInfo->where_expr) ) )
+    {
+        poSrcLayer->GetLayerDefn()->SetGeometryIgnored(TRUE);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      We treat COUNT(*) as a special case, and fill with              */
+/*      GetFeatureCount().                                              */
 /* -------------------------------------------------------------------- */
 
     if( psSelectInfo->result_columns == 1 
         && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
-        && !psSelectInfo->column_defs[0].distinct_flag )
+        && psSelectInfo->column_defs[0].field_index < 0 )
     {
         poSummaryFeature->SetField( 0, poSrcLayer->GetFeatureCount( TRUE ) );
+        poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
         return TRUE;
     }
 
@@ -540,22 +635,42 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 /* -------------------------------------------------------------------- */
     const char *pszError;
     OGRFeature *poSrcFeature;
+    int iField;
 
     while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
     {
-        for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
+        for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
 
-            pszError = swq_select_summarize( psSelectInfo, iField, 
-                                          poSrcFeature->GetFieldAsString( 
-                                              psColDef->field_index ) );
+            if (psColDef->col_func == SWQCF_COUNT)
+            {
+                /* 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 (poSrcFeature->IsFieldSet(psColDef->field_index))
+                    pszError = swq_select_summarize( psSelectInfo, iField, poSrcFeature->GetFieldAsString(
+                                                psColDef->field_index ) );
+                else
+                    pszError = NULL;
+            }
+            else
+            {
+                const char* pszVal = NULL;
+                if (poSrcFeature->IsFieldSet(psColDef->field_index))
+                    pszVal = poSrcFeature->GetFieldAsString(
+                                                psColDef->field_index );
+                pszError = swq_select_summarize( psSelectInfo, iField, pszVal );
+            }
             
             if( pszError != NULL )
             {
+                delete poSrcFeature;
                 delete poSummaryFeature;
                 poSummaryFeature = NULL;
 
+                poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
+
                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
                 return FALSE;
             }
@@ -564,6 +679,8 @@ int OGRGenSQLResultsLayer::PrepareSummary()
         delete poSrcFeature;
     }
 
+    poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
+
     pszError = swq_select_finish_summarize( psSelectInfo );
     if( pszError != NULL )
     {
@@ -586,25 +703,29 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 /*      Now apply the values to the summary feature.  If we are in      */
 /*      DISTINCT_LIST mode we don't do this step.                       */
 /* -------------------------------------------------------------------- */
-    if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD 
-        && psSelectInfo->column_summary != NULL )
+    if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
     {
-        for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
+        for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
-            swq_summary *psSummary = psSelectInfo->column_summary + iField;
-
-            if( psColDef->col_func == SWQCF_AVG )
-                poSummaryFeature->SetField( iField, 
-                                        psSummary->sum / psSummary->count );
-            else if( psColDef->col_func == SWQCF_MIN )
-                poSummaryFeature->SetField( iField, psSummary->min );
-            else if( psColDef->col_func == SWQCF_MAX )
-                poSummaryFeature->SetField( iField, psSummary->max );
-            else if( psColDef->col_func == SWQCF_COUNT )
-                poSummaryFeature->SetField( iField, psSummary->count );
-            else if( psColDef->col_func == SWQCF_SUM )
-                poSummaryFeature->SetField( iField, psSummary->sum );
+            if (psSelectInfo->column_summary != NULL)
+            {
+                swq_summary *psSummary = psSelectInfo->column_summary + iField;
+
+                if( psColDef->col_func == SWQCF_AVG )
+                    poSummaryFeature->SetField( iField,
+                                            psSummary->sum / psSummary->count );
+                else if( psColDef->col_func == SWQCF_MIN )
+                    poSummaryFeature->SetField( iField, psSummary->min );
+                else if( psColDef->col_func == SWQCF_MAX )
+                    poSummaryFeature->SetField( iField, psSummary->max );
+                else if( psColDef->col_func == SWQCF_COUNT )
+                    poSummaryFeature->SetField( iField, psSummary->count );
+                else if( psColDef->col_func == SWQCF_SUM )
+                    poSummaryFeature->SetField( iField, psSummary->sum );
+            }
+            else if ( psColDef->col_func == SWQCF_COUNT )
+                poSummaryFeature->SetField( iField, 0 );
         }
     }
 
@@ -721,17 +842,31 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
             apoFeatures.push_back( NULL );
             continue;
         }
+        
+        OGRFieldDefn* poSecondaryFieldDefn =
+            poJoinLayer->GetLayerDefn()->GetFieldDefn( 
+                     psJoinInfo->secondary_field );
+        OGRFieldType ePrimaryFieldType = poSrcLayer->GetLayerDefn()->
+                    GetFieldDefn(psJoinInfo->primary_field )->GetType();
+        OGRFieldType eSecondaryFieldType = poSecondaryFieldDefn->GetType();
 
         // Prepare attribute query to express fetching on the joined variable
-        osFilter.Printf("%s = ", 
-                 poJoinLayer->GetLayerDefn()->GetFieldDefn( 
-                     psJoinInfo->secondary_field )->GetNameRef() );
+        
+        // If joining a (primary) numeric column with a (secondary) string column
+        // then add implicit casting of the secondary column to numeric. This behaviour
+        // worked in GDAL < 1.8, and it is consistant with how sqlite behaves too. See #4321
+        // For the reverse case, joining a string column with a numeric column, the
+        // string constant will be cast to float by SWQAutoConvertStringToNumeric (#4259)
+        if( eSecondaryFieldType == OFTString &&
+            (ePrimaryFieldType == OFTInteger || ePrimaryFieldType == OFTReal) )
+            osFilter.Printf("CAST(%s AS FLOAT) = ", poSecondaryFieldDefn->GetNameRef() );
+        else
+            osFilter.Printf("%s = ", poSecondaryFieldDefn->GetNameRef() );
 
         OGRField *psSrcField = 
             poSrcFeat->GetRawFieldRef(psJoinInfo->primary_field);
 
-        switch( poSrcLayer->GetLayerDefn()->GetFieldDefn( 
-                    psJoinInfo->primary_field )->GetType() )
+        switch( ePrimaryFieldType )
         {
           case OFTInteger:
             osFilter += CPLString().Printf("%d", psSrcField->Integer );
@@ -988,7 +1123,10 @@ OGRFeature *OGRGenSQLResultsLayer::GetFeature( long nFID )
         if( nFID < 0 || nFID >= psSummary->count )
             return NULL;
 
-        poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
+        if( psSummary->distinct_list[nFID] != NULL )
+            poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
+        else
+            poSummaryFeature->UnsetField( 0 );
         poSummaryFeature->SetFID( nFID );
 
         return poSummaryFeature->Clone();
@@ -1096,6 +1234,16 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
     {
         int iKey;
 
+        if (iFeature == nIndexSize)
+        {
+            /* Should not happen theoretically. GetFeatureCount() may sometimes */
+            /* overestimate the number of features, but should *never* under-estimate it */
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "GetFeatureCount() reported less features than there are when iterating over the layer. "
+                     "Not all features will be listed.");
+            break;
+        }
+
         for( iKey = 0; iKey < nOrderItems; iKey++ )
         {
             swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
@@ -1152,7 +1300,10 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
         iFeature++;
     }
 
-    CPLAssert( nIndexSize == iFeature );
+    /* Adjust the number of features in case GetFeatureCount() has */
+    /* overestimated the number of features, which may be the case */
+    /* for a shapefile with deleted records */
+    nIndexSize = iFeature;
 
 /* -------------------------------------------------------------------- */
 /*      Quick sort the records.                                         */
@@ -1394,10 +1545,10 @@ void OGRGenSQLResultsLayer::ExploreExprForIgnoredFields(swq_expr_node* expr,
 }
 
 /************************************************************************/
-/*                       SetIgnoredFields()                             */
+/*                     FindAndSetIgnoredFields()                        */
 /************************************************************************/
 
-void OGRGenSQLResultsLayer::SetIgnoredFields()
+void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
     CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashPointer,
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.h b/ogr/ogrsf_frmts/generic/ogr_gensql.h
index d4d3651..0a82a15 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 20897 2010-10-19 19:15:58Z rouault $
+ * $Id: ogr_gensql.h 23531 2011-12-11 19:11:56Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to generic implementation of ExecuteSQL().
@@ -74,15 +74,17 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
 
     void        ClearFilters();
 
-    void        SetIgnoredFields();
+    void        FindAndSetIgnoredFields();
     void        ExploreExprForIgnoredFields(swq_expr_node* expr, CPLHashSet* hSet);
     void        AddFieldDefnToSet(int iTable, int iColumn, CPLHashSet* hSet);
-    
+
+    int         ContainGeomSpecialField(swq_expr_node* expr);
   public:
                 OGRGenSQLResultsLayer( OGRDataSource *poSrcDS, 
                                        void *pSelectInfo, 
                                        OGRGeometry *poSpatFilter,
-                                       const char *pszWHERE );
+                                       const char *pszWHERE,
+                                       const char *pszDialect );
     virtual     ~OGRGenSQLResultsLayer();
 
     virtual OGRGeometry *GetSpatialFilter();
diff --git a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
index 6f72a35..dc9889a 100644
--- a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrdatasource.cpp 20616 2010-09-15 01:20:36Z warmerdam $
+ * $Id: ogrdatasource.cpp 23403 2011-11-20 21:01:21Z ajolma $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRDataSource class.
@@ -35,7 +35,7 @@
 #include "ogr_attrind.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrdatasource.cpp 20616 2010-09-15 01:20:36Z warmerdam $");
+CPL_CVSID("$Id: ogrdatasource.cpp 23403 2011-11-20 21:01:21Z ajolma $");
 
 /************************************************************************/
 /*                           ~OGRDataSource()                           */
@@ -308,10 +308,10 @@ OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
 
         if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
         {
-            delete poFeature;
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to translate feature %ld from layer %s.\n",
                       poFeature->GetFID(), poSrcDefn->GetName() );
+            OGRFeature::DestroyFeature( poFeature );
             return poDstLayer;
         }
 
@@ -411,6 +411,7 @@ OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS,
 {
     VALIDATE_POINTER1( hDS, "OGR_DS_CopyLayer", NULL );
     VALIDATE_POINTER1( hSrcLayer, "OGR_DS_CopyLayer", NULL );
+    VALIDATE_POINTER1( pszNewName, "OGR_DS_CopyLayer", NULL );
 
     return (OGRLayerH) 
         ((OGRDataSource *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer, 
@@ -721,6 +722,524 @@ OGRErr OGRDataSource::ProcessSQLDropIndex( const char *pszSQLCommand )
 }
 
 /************************************************************************/
+/*                        ProcessSQLDropTable()                         */
+/*                                                                      */
+/*      The correct syntax for dropping a table (layer) in the OGR SQL  */
+/*      dialect is:                                                     */
+/*                                                                      */
+/*          DROP TABLE <layername>                                      */
+/************************************************************************/
+
+OGRErr OGRDataSource::ProcessSQLDropTable( const char *pszSQLCommand )
+
+{
+    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+
+/* -------------------------------------------------------------------- */
+/*      Do some general syntax checking.                                */
+/* -------------------------------------------------------------------- */
+    if( CSLCount(papszTokens) != 3
+        || !EQUAL(papszTokens[0],"DROP")
+        || !EQUAL(papszTokens[1],"TABLE") )
+    {
+        CSLDestroy( papszTokens );
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Syntax error in DROP TABLE command.\n"
+                  "Was '%s'\n"
+                  "Should be of form 'DROP TABLE <table>'",
+                  pszSQLCommand );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the named layer.                                           */
+/* -------------------------------------------------------------------- */
+    int  i;
+    OGRLayer *poLayer=NULL;
+
+    for( i = 0; i < GetLayerCount(); i++ )
+    {
+        poLayer = GetLayer(i);
+        
+        if( EQUAL(poLayer->GetName(),papszTokens[2]) )
+            break;
+    }
+    
+    if( i >= GetLayerCount() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "DROP TABLE failed, no such layer as `%s'.",
+                  papszTokens[2] );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+    CSLDestroy( papszTokens );
+
+/* -------------------------------------------------------------------- */
+/*      Delete it.                                                      */
+/* -------------------------------------------------------------------- */
+
+    return DeleteLayer( i );
+}
+
+/************************************************************************/
+/*                    OGRDataSourceParseSQLType()                       */
+/************************************************************************/
+
+/* All arguments will be altered */
+static OGRFieldType OGRDataSourceParseSQLType(char* pszType, int& nWidth, int &nPrecision)
+{
+    char* pszParenthesis = strchr(pszType, '(');
+    if (pszParenthesis)
+    {
+        nWidth = atoi(pszParenthesis + 1);
+        *pszParenthesis = '\0';
+        char* pszComma = strchr(pszParenthesis + 1, ',');
+        if (pszComma)
+            nPrecision = atoi(pszComma + 1);
+    }
+
+    OGRFieldType eType = OFTString;
+    if (EQUAL(pszType, "INTEGER"))
+        eType = OFTInteger;
+    else if (EQUAL(pszType, "INTEGER[]"))
+        eType = OFTIntegerList;
+    else if (EQUAL(pszType, "FLOAT") ||
+             EQUAL(pszType, "NUMERIC") ||
+             EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
+             EQUAL(pszType, "REAL") /* unofficial alias */)
+        eType = OFTReal;
+    else if (EQUAL(pszType, "FLOAT[]") ||
+             EQUAL(pszType, "NUMERIC[]") ||
+             EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
+             EQUAL(pszType, "REAL[]") /* unofficial alias */)
+        eType = OFTRealList;
+    else if (EQUAL(pszType, "CHARACTER") ||
+             EQUAL(pszType, "TEXT") /* unofficial alias */ ||
+             EQUAL(pszType, "STRING") /* unofficial alias */ ||
+             EQUAL(pszType, "VARCHAR") /* unofficial alias */)
+        eType = OFTString;
+    else if (EQUAL(pszType, "TEXT[]") ||
+             EQUAL(pszType, "STRING[]") /* unofficial alias */||
+             EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
+        eType = OFTStringList;
+    else if (EQUAL(pszType, "DATE"))
+        eType = OFTDate;
+    else if (EQUAL(pszType, "TIME"))
+        eType = OFTTime;
+    else if (EQUAL(pszType, "TIMESTAMP") ||
+             EQUAL(pszType, "DATETIME") /* unofficial alias */ )
+        eType = OFTDateTime;
+    else
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                 "Unsupported column type '%s'. Defaulting to VARCHAR",
+                 pszType);
+    }
+    return eType;
+}
+
+/************************************************************************/
+/*                    ProcessSQLAlterTableAddColumn()                   */
+/*                                                                      */
+/*      The correct syntax for adding a column in the OGR SQL           */
+/*      dialect is:                                                     */
+/*                                                                      */
+/*          ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype>*/
+/************************************************************************/
+
+OGRErr OGRDataSource::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
+
+{
+    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+
+/* -------------------------------------------------------------------- */
+/*      Do some general syntax checking.                                */
+/* -------------------------------------------------------------------- */
+    const char* pszLayerName = NULL;
+    const char* pszColumnName = NULL;
+    char* pszType = NULL;
+    int iTypeIndex = 0;
+    int nTokens = CSLCount(papszTokens);
+
+    if( nTokens >= 7
+        && EQUAL(papszTokens[0],"ALTER")
+        && EQUAL(papszTokens[1],"TABLE")
+        && EQUAL(papszTokens[3],"ADD")
+        && EQUAL(papszTokens[4],"COLUMN"))
+    {
+        pszLayerName = papszTokens[2];
+        pszColumnName = papszTokens[5];
+        iTypeIndex = 6;
+    }
+    else if( nTokens >= 6
+             && EQUAL(papszTokens[0],"ALTER")
+             && EQUAL(papszTokens[1],"TABLE")
+             && EQUAL(papszTokens[3],"ADD"))
+    {
+        pszLayerName = papszTokens[2];
+        pszColumnName = papszTokens[4];
+        iTypeIndex = 5;
+    }
+    else
+    {
+        CSLDestroy( papszTokens );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Syntax error in ALTER TABLE ADD COLUMN command.\n"
+                  "Was '%s'\n"
+                  "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype>'",
+                  pszSQLCommand );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Merge type components into a single string if there were split  */
+/*      with spaces                                                     */
+/* -------------------------------------------------------------------- */
+    CPLString osType;
+    for(int i=iTypeIndex;i<nTokens;i++)
+    {
+        osType += papszTokens[i];
+        CPLFree(papszTokens[i]);
+    }
+    pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
+    papszTokens[iTypeIndex + 1] = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Find the named layer.                                           */
+/* -------------------------------------------------------------------- */
+    OGRLayer *poLayer = GetLayerByName(pszLayerName);
+    if( poLayer == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s failed, no such layer as `%s'.",
+                  pszSQLCommand,
+                  pszLayerName );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add column.                                                     */
+/* -------------------------------------------------------------------- */
+
+    int nWidth = 0, nPrecision = 0;
+    OGRFieldType eType = OGRDataSourceParseSQLType(pszType, nWidth, nPrecision);
+    OGRFieldDefn oFieldDefn(pszColumnName, eType);
+    oFieldDefn.SetWidth(nWidth);
+    oFieldDefn.SetPrecision(nPrecision);
+
+    CSLDestroy( papszTokens );
+
+    return poLayer->CreateField( &oFieldDefn );
+}
+
+/************************************************************************/
+/*                    ProcessSQLAlterTableDropColumn()                  */
+/*                                                                      */
+/*      The correct syntax for droping a column in the OGR SQL          */
+/*      dialect is:                                                     */
+/*                                                                      */
+/*          ALTER TABLE <layername> DROP [COLUMN] <columnname>          */
+/************************************************************************/
+
+OGRErr OGRDataSource::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
+
+{
+    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+
+/* -------------------------------------------------------------------- */
+/*      Do some general syntax checking.                                */
+/* -------------------------------------------------------------------- */
+    const char* pszLayerName = NULL;
+    const char* pszColumnName = NULL;
+    if( CSLCount(papszTokens) == 6
+        && EQUAL(papszTokens[0],"ALTER")
+        && EQUAL(papszTokens[1],"TABLE")
+        && EQUAL(papszTokens[3],"DROP")
+        && EQUAL(papszTokens[4],"COLUMN"))
+    {
+        pszLayerName = papszTokens[2];
+        pszColumnName = papszTokens[5];
+    }
+    else if( CSLCount(papszTokens) == 5
+             && EQUAL(papszTokens[0],"ALTER")
+             && EQUAL(papszTokens[1],"TABLE")
+             && EQUAL(papszTokens[3],"DROP"))
+    {
+        pszLayerName = papszTokens[2];
+        pszColumnName = papszTokens[4];
+    }
+    else
+    {
+        CSLDestroy( papszTokens );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Syntax error in ALTER TABLE DROP COLUMN command.\n"
+                  "Was '%s'\n"
+                  "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] <columnname>'",
+                  pszSQLCommand );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the named layer.                                           */
+/* -------------------------------------------------------------------- */
+    OGRLayer *poLayer = GetLayerByName(pszLayerName);
+    if( poLayer == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s failed, no such layer as `%s'.",
+                  pszSQLCommand,
+                  pszLayerName );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the field.                                                 */
+/* -------------------------------------------------------------------- */
+
+    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
+    if( nFieldIndex < 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s failed, no such field as `%s'.",
+                  pszSQLCommand,
+                  pszColumnName );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+
+/* -------------------------------------------------------------------- */
+/*      Remove it.                                                      */
+/* -------------------------------------------------------------------- */
+
+    CSLDestroy( papszTokens );
+
+    return poLayer->DeleteField( nFieldIndex );
+}
+
+/************************************************************************/
+/*                 ProcessSQLAlterTableRenameColumn()                   */
+/*                                                                      */
+/*      The correct syntax for renaming a column in the OGR SQL         */
+/*      dialect is:                                                     */
+/*                                                                      */
+/*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
+/************************************************************************/
+
+OGRErr OGRDataSource::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand )
+
+{
+    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+
+/* -------------------------------------------------------------------- */
+/*      Do some general syntax checking.                                */
+/* -------------------------------------------------------------------- */
+    const char* pszLayerName = NULL;
+    const char* pszOldColName = NULL;
+    const char* pszNewColName = NULL;
+    if( CSLCount(papszTokens) == 8
+        && EQUAL(papszTokens[0],"ALTER")
+        && EQUAL(papszTokens[1],"TABLE")
+        && EQUAL(papszTokens[3],"RENAME")
+        && EQUAL(papszTokens[4],"COLUMN")
+        && EQUAL(papszTokens[6],"TO"))
+    {
+        pszLayerName = papszTokens[2];
+        pszOldColName = papszTokens[5];
+        pszNewColName = papszTokens[7];
+    }
+    else if( CSLCount(papszTokens) == 7
+             && EQUAL(papszTokens[0],"ALTER")
+             && EQUAL(papszTokens[1],"TABLE")
+             && EQUAL(papszTokens[3],"RENAME")
+             && EQUAL(papszTokens[5],"TO"))
+    {
+        pszLayerName = papszTokens[2];
+        pszOldColName = papszTokens[4];
+        pszNewColName = papszTokens[6];
+    }
+    else
+    {
+        CSLDestroy( papszTokens );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
+                  "Was '%s'\n"
+                  "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] <columnname> <columntype>'",
+                  pszSQLCommand );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the named layer.                                           */
+/* -------------------------------------------------------------------- */
+    OGRLayer *poLayer = GetLayerByName(pszLayerName);
+    if( poLayer == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s failed, no such layer as `%s'.",
+                  pszSQLCommand,
+                  pszLayerName );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the field.                                                 */
+/* -------------------------------------------------------------------- */
+
+    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
+    if( nFieldIndex < 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s failed, no such field as `%s'.",
+                  pszSQLCommand,
+                  pszOldColName );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Rename column.                                                  */
+/* -------------------------------------------------------------------- */
+    OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
+    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
+    oNewFieldDefn.SetName(pszNewColName);
+
+    CSLDestroy( papszTokens );
+
+    return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, ALTER_NAME_FLAG );
+}
+
+/************************************************************************/
+/*                 ProcessSQLAlterTableAlterColumn()                    */
+/*                                                                      */
+/*      The correct syntax for altering the type of a column in the     */
+/*      OGR SQL dialect is:                                             */
+/*                                                                      */
+/*   ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
+/************************************************************************/
+
+OGRErr OGRDataSource::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
+
+{
+    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+
+/* -------------------------------------------------------------------- */
+/*      Do some general syntax checking.                                */
+/* -------------------------------------------------------------------- */
+    const char* pszLayerName = NULL;
+    const char* pszColumnName = NULL;
+    char* pszType = NULL;
+    int iTypeIndex = 0;
+    int nTokens = CSLCount(papszTokens);
+
+    if( nTokens >= 8
+        && EQUAL(papszTokens[0],"ALTER")
+        && EQUAL(papszTokens[1],"TABLE")
+        && EQUAL(papszTokens[3],"ALTER")
+        && EQUAL(papszTokens[4],"COLUMN")
+        && EQUAL(papszTokens[6],"TYPE"))
+    {
+        pszLayerName = papszTokens[2];
+        pszColumnName = papszTokens[5];
+        iTypeIndex = 7;
+    }
+    else if( nTokens >= 7
+             && EQUAL(papszTokens[0],"ALTER")
+             && EQUAL(papszTokens[1],"TABLE")
+             && EQUAL(papszTokens[3],"ALTER")
+             && EQUAL(papszTokens[5],"TYPE"))
+    {
+        pszLayerName = papszTokens[2];
+        pszColumnName = papszTokens[4];
+        iTypeIndex = 6;
+    }
+    else
+    {
+        CSLDestroy( papszTokens );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
+                  "Was '%s'\n"
+                  "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <columntype>'",
+                  pszSQLCommand );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Merge type components into a single string if there were split  */
+/*      with spaces                                                     */
+/* -------------------------------------------------------------------- */
+    CPLString osType;
+    for(int i=iTypeIndex;i<nTokens;i++)
+    {
+        osType += papszTokens[i];
+        CPLFree(papszTokens[i]);
+    }
+    pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
+    papszTokens[iTypeIndex + 1] = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Find the named layer.                                           */
+/* -------------------------------------------------------------------- */
+    OGRLayer *poLayer = GetLayerByName(pszLayerName);
+    if( poLayer == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s failed, no such layer as `%s'.",
+                  pszSQLCommand,
+                  pszLayerName );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the field.                                                 */
+/* -------------------------------------------------------------------- */
+
+    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
+    if( nFieldIndex < 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s failed, no such field as `%s'.",
+                  pszSQLCommand,
+                  pszColumnName );
+        CSLDestroy( papszTokens );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Alter column.                                                   */
+/* -------------------------------------------------------------------- */
+
+    OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
+    OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
+
+    int nWidth = 0, nPrecision = 0;
+    OGRFieldType eType = OGRDataSourceParseSQLType(pszType, nWidth, nPrecision);
+    oNewFieldDefn.SetType(eType);
+    oNewFieldDefn.SetWidth(nWidth);
+    oNewFieldDefn.SetPrecision(nPrecision);
+
+    int nFlags = 0;
+    if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
+        nFlags |= ALTER_TYPE_FLAG;
+    if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
+        poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
+        nFlags |= ALTER_WIDTH_PRECISION_FLAG;
+
+    CSLDestroy( papszTokens );
+
+    if (nFlags == 0)
+        return OGRERR_NONE;
+    else
+        return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, nFlags );
+}
+
+/************************************************************************/
 /*                             ExecuteSQL()                             */
 /************************************************************************/
 
@@ -759,6 +1278,59 @@ OGRLayer * OGRDataSource::ExecuteSQL( const char *pszStatement,
     }
     
 /* -------------------------------------------------------------------- */
+/*      Handle DROP TABLE statements specially.                         */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszStatement,"DROP TABLE",10) )
+    {
+        ProcessSQLDropTable( pszStatement );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle ALTER TABLE statements specially.                        */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszStatement,"ALTER TABLE",11) )
+    {
+        char **papszTokens = CSLTokenizeString( pszStatement );
+        if( CSLCount(papszTokens) >= 4 &&
+            EQUAL(papszTokens[3],"ADD") )
+        {
+            ProcessSQLAlterTableAddColumn( pszStatement );
+            CSLDestroy(papszTokens);
+            return NULL;
+        }
+        else if( CSLCount(papszTokens) >= 4 &&
+                 EQUAL(papszTokens[3],"DROP") )
+        {
+            ProcessSQLAlterTableDropColumn( pszStatement );
+            CSLDestroy(papszTokens);
+            return NULL;
+        }
+        else if( CSLCount(papszTokens) >= 4 &&
+                 EQUAL(papszTokens[3],"RENAME") )
+        {
+            ProcessSQLAlterTableRenameColumn( pszStatement );
+            CSLDestroy(papszTokens);
+            return NULL;
+        }
+        else if( CSLCount(papszTokens) >= 4 &&
+                 EQUAL(papszTokens[3],"ALTER") )
+        {
+            ProcessSQLAlterTableAlterColumn( pszStatement );
+            CSLDestroy(papszTokens);
+            return NULL;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unsupported ALTER TABLE command : %s",
+                      pszStatement );
+            CSLDestroy(papszTokens);
+            return NULL;
+        }
+    }
+    
+/* -------------------------------------------------------------------- */
 /*      Preparse the SQL statement.                                     */
 /* -------------------------------------------------------------------- */
     psSelectInfo = new swq_select();
@@ -908,7 +1480,12 @@ OGRLayer * OGRDataSource::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
     if( psSelectInfo->where_expr != NULL )
     {
-        pszWHERE = psSelectInfo->where_expr->Unparse( &sFieldList );
+        if (m_poDriver && (
+                EQUAL(m_poDriver->GetName(), "PostgreSQL") ||
+                EQUAL(m_poDriver->GetName(), "FileGDB" )) )
+            pszWHERE = psSelectInfo->where_expr->Unparse( &sFieldList, '"' );
+        else
+            pszWHERE = psSelectInfo->where_expr->Unparse( &sFieldList, '\'' );
         //CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
     }
 
@@ -918,7 +1495,8 @@ OGRLayer * OGRDataSource::ExecuteSQL( const char *pszStatement,
 
     poResults = new OGRGenSQLResultsLayer( this, psSelectInfo, 
                                            poSpatialFilter,
-                                           pszWHERE );
+                                           pszWHERE,
+                                           pszDialect );
 
     CPLFree( pszWHERE );
 
diff --git a/ogr/ogrsf_frmts/generic/ogrlayer.cpp b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
index f137ca6..4a19ff8 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayer.cpp 20885 2010-10-19 00:16:08Z warmerdam $
+ * $Id: ogrlayer.cpp 23554 2011-12-12 18:10:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFLayer class.
@@ -31,8 +31,9 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 #include "ogr_attrind.h"
+#include "swq.h"
 
-CPL_CVSID("$Id: ogrlayer.cpp 20885 2010-10-19 00:16:08Z warmerdam $");
+CPL_CVSID("$Id: ogrlayer.cpp 23554 2011-12-12 18:10:25Z rouault $");
 
 /************************************************************************/
 /*                              OGRLayer()                              */
@@ -306,6 +307,51 @@ OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
 }
 
 /************************************************************************/
+/*                        ContainGeomSpecialField()                     */
+/************************************************************************/
+
+static int ContainGeomSpecialField(swq_expr_node* expr,
+                                   int nLayerFieldCount)
+{
+    if (expr->eNodeType == SNT_COLUMN)
+    {
+        if( expr->table_index == 0 && expr->field_index != -1 )
+        {
+            int nSpecialFieldIdx = expr->field_index -
+                                    nLayerFieldCount;
+            return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
+                   nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
+                   nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
+        }
+    }
+    else if (expr->eNodeType == SNT_OPERATION)
+    {
+        for( int i = 0; i < expr->nSubExprCount; i++ )
+        {
+            if (ContainGeomSpecialField(expr->papoSubExpr[i],
+                                        nLayerFieldCount))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                AttributeFilterEvaluationNeedsGeometry()              */
+/************************************************************************/
+
+int OGRLayer::AttributeFilterEvaluationNeedsGeometry()
+{
+    if( !m_poAttrQuery )
+        return FALSE;
+
+    swq_expr_node* expr = (swq_expr_node *) m_poAttrQuery->GetSWGExpr();
+    int nLayerFieldCount = GetLayerDefn()->GetFieldCount();
+
+    return ContainGeomSpecialField(expr, nLayerFieldCount);
+}
+
+/************************************************************************/
 /*                      OGR_L_SetAttributeFilter()                      */
 /************************************************************************/
 
@@ -485,6 +531,162 @@ OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
 }
 
 /************************************************************************/
+/*                            DeleteField()                             */
+/************************************************************************/
+
+OGRErr OGRLayer::DeleteField( int iField )
+
+{
+    (void) iField;
+
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "DeleteField() not supported by this layer.\n" );
+
+    return OGRERR_UNSUPPORTED_OPERATION;
+}
+
+/************************************************************************/
+/*                         OGR_L_DeleteField()                          */
+/************************************************************************/
+
+OGRErr OGR_L_DeleteField( OGRLayerH hLayer, int iField )
+
+{
+    VALIDATE_POINTER1( hLayer, "OGR_L_DeleteField", OGRERR_INVALID_HANDLE );
+
+    return ((OGRLayer *) hLayer)->DeleteField( iField );
+}
+
+/************************************************************************/
+/*                           ReorderFields()                            */
+/************************************************************************/
+
+OGRErr OGRLayer::ReorderFields( int* panMap )
+
+{
+    (void) panMap;
+
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "ReorderFields() not supported by this layer.\n" );
+
+    return OGRERR_UNSUPPORTED_OPERATION;
+}
+
+/************************************************************************/
+/*                       OGR_L_ReorderFields()                          */
+/************************************************************************/
+
+OGRErr OGR_L_ReorderFields( OGRLayerH hLayer, int* panMap )
+
+{
+    VALIDATE_POINTER1( hLayer, "OGR_L_ReorderFields", OGRERR_INVALID_HANDLE );
+
+    return ((OGRLayer *) hLayer)->ReorderFields( panMap );
+}
+
+/************************************************************************/
+/*                            ReorderField()                            */
+/************************************************************************/
+
+OGRErr OGRLayer::ReorderField( int iOldFieldPos, int iNewFieldPos )
+
+{
+    OGRErr eErr;
+
+    int nFieldCount = GetLayerDefn()->GetFieldCount();
+
+    if (iOldFieldPos < 0 || iOldFieldPos >= nFieldCount)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+    if (iNewFieldPos < 0 || iNewFieldPos >= nFieldCount)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+    if (iNewFieldPos == iOldFieldPos)
+        return OGRERR_NONE;
+
+    int* panMap = (int*) CPLMalloc(sizeof(int) * nFieldCount);
+    int i;
+    if (iOldFieldPos < iNewFieldPos)
+    {
+        /* "0","1","2","3","4" (1,3) -> "0","2","3","1","4" */
+        for(i=0;i<iOldFieldPos;i++)
+            panMap[i] = i;
+        for(;i<iNewFieldPos;i++)
+            panMap[i] = i + 1;
+        panMap[iNewFieldPos] = iOldFieldPos;
+        for(i=iNewFieldPos+1;i<nFieldCount;i++)
+            panMap[i] = i;
+    }
+    else
+    {
+        /* "0","1","2","3","4" (3,1) -> "0","3","1","2","4" */
+        for(i=0;i<iNewFieldPos;i++)
+            panMap[i] = i;
+        panMap[iNewFieldPos] = iOldFieldPos;
+        for(i=iNewFieldPos+1;i<=iOldFieldPos;i++)
+            panMap[i] = i - 1;
+        for(;i<nFieldCount;i++)
+            panMap[i] = i;
+    }
+
+    eErr = ReorderFields(panMap);
+
+    CPLFree(panMap);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                        OGR_L_ReorderField()                          */
+/************************************************************************/
+
+OGRErr OGR_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos, int iNewFieldPos )
+
+{
+    VALIDATE_POINTER1( hLayer, "OGR_L_ReorderField", OGRERR_INVALID_HANDLE );
+
+    return ((OGRLayer *) hLayer)->ReorderField( iOldFieldPos, iNewFieldPos );
+}
+
+/************************************************************************/
+/*                           AlterFieldDefn()                           */
+/************************************************************************/
+
+OGRErr OGRLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
+                                 int nFlags )
+
+{
+    (void) iField;
+    (void) poNewFieldDefn;
+    (void) nFlags;
+
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "AlterFieldDefn() not supported by this layer.\n" );
+
+    return OGRERR_UNSUPPORTED_OPERATION;
+}
+
+/************************************************************************/
+/*                        OGR_L_AlterFieldDefn()                        */
+/************************************************************************/
+
+OGRErr OGR_L_AlterFieldDefn( OGRLayerH hLayer, int iField, OGRFieldDefnH hNewFieldDefn,
+                             int nFlags )
+
+{
+    VALIDATE_POINTER1( hLayer, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
+    VALIDATE_POINTER1( hNewFieldDefn, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
+
+    return ((OGRLayer *) hLayer)->AlterFieldDefn( iField, (OGRFieldDefn*) hNewFieldDefn, nFlags );
+}
+
+/************************************************************************/
 /*                          StartTransaction()                          */
 /************************************************************************/
 
@@ -839,6 +1041,9 @@ OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
 {
     OGRErr eErr;
 
+    if (m_poAttrIndex != NULL)
+        return OGRERR_NONE;
+
     m_poAttrIndex = OGRCreateDefaultLayerIndex();
 
     eErr = m_poAttrIndex->Initialize( pszFilename, this );
@@ -1124,7 +1329,7 @@ OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
 OGRErr OGR_L_SetIgnoredFields( OGRLayerH hLayer, const char **papszFields )
 
 {
-    VALIDATE_POINTER1( hLayer, "OGR_L_SetIgnoredFields", NULL );
+    VALIDATE_POINTER1( hLayer, "OGR_L_SetIgnoredFields", OGRERR_INVALID_HANDLE );
 
     return ((OGRLayer *) hLayer)->SetIgnoredFields( papszFields );
 }
diff --git a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
index 57d90ac..ba56e60 100644
--- a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrregisterall.cpp 21372 2011-01-01 23:53:54Z rouault $
+ * $Id: ogrregisterall.cpp 23381 2011-11-17 21:55:45Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Function to register all known OGR drivers.
@@ -29,7 +29,7 @@
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrregisterall.cpp 21372 2011-01-01 23:53:54Z rouault $");
+CPL_CVSID("$Id: ogrregisterall.cpp 23381 2011-11-17 21:55:45Z rouault $");
 
 /************************************************************************/
 /*                           OGRRegisterAll()                           */
@@ -108,7 +108,14 @@ void OGRRegisterAll()
 #endif
 #ifdef ODBC_ENABLED
     RegisterOGRODBC();
-#endif    
+#endif
+
+/* Register before PGeo and Geomedia drivers */
+/* that don't work well on Linux */
+#ifdef MDB_ENABLED
+    RegisterOGRMDB();
+#endif
+
 #ifdef PGEO_ENABLED
     RegisterOGRPGeo();
 #endif
@@ -136,6 +143,9 @@ void OGRRegisterAll()
 #ifdef SDE_ENABLED
     RegisterOGRSDE();
 #endif
+#ifdef FGDB_ENABLED
+    RegisterOGRFileGDB();
+#endif
 #ifdef XPLANE_ENABLED
     RegisterOGRXPlane();
 #endif
@@ -197,4 +207,34 @@ void OGRRegisterAll()
 #ifdef AERONAVFAA_ENABLED
     RegisterOGRAeronavFAA();
 #endif
+#ifdef GEOMEDIA_ENABLED
+    RegisterOGRGeomedia();
+#endif
+#ifdef EDIGEO_ENABLED
+    RegisterOGREDIGEO();
+#endif
+#ifdef GFT_ENABLED
+    RegisterOGRGFT();
+#endif
+#ifdef SVG_ENABLED
+    RegisterOGRSVG();
+#endif
+#ifdef COUCHDB_ENABLED
+    RegisterOGRCouchDB();
+#endif
+#ifdef IDRISI_ENABLED
+    RegisterOGRIdrisi();
+#endif
+#ifdef ARCGEN_ENABLED
+    RegisterOGRARCGEN();
+#endif
+#ifdef SEGUKOOA_ENABLED
+    RegisterOGRSEGUKOOA();
+#endif
+#ifdef SEGY_ENABLED
+    RegisterOGRSEGY();
+#endif
+#ifdef FREEXL_ENABLED
+    RegisterOGRXLS();
+#endif
 } /* OGRRegisterAll */
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
index e5feb3f..ebb43f8 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsfdriver.cpp 16319 2009-02-13 23:17:58Z rouault $
+ * $Id: ogrsfdriver.cpp 23413 2011-11-22 21:53:32Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFDriver class.
@@ -31,7 +31,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrsfdriver.cpp 16319 2009-02-13 23:17:58Z rouault $");
+CPL_CVSID("$Id: ogrsfdriver.cpp 23413 2011-11-22 21:53:32Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRSFDriver()                            */
@@ -193,7 +193,14 @@ OGRDataSource *OGRSFDriver::CopyDataSource( OGRDataSource *poSrcDS,
         poODS->CopyLayer( poLayer, poLayer->GetLayerDefn()->GetName(), 
                           papszOptions );
     }
-    
+
+    /* Make sure that the driver is attached to the created datasource */
+    /* It is also done in OGR_Dr_CopyDataSource() C method, in case */
+    /* another C++ implementation forgets to do it. Currently (Nov 2011), */
+    /* this implementation is the only one in the OGR source tree */
+    if( poODS != NULL && poODS->GetDriver() == NULL )
+        poODS->SetDriver( this );
+
     return poODS;
 }
 
@@ -209,9 +216,18 @@ OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver,
 {
     VALIDATE_POINTER1( hDriver, "OGR_Dr_CopyDataSource", NULL );
     VALIDATE_POINTER1( hSrcDS, "OGR_Dr_CopyDataSource", NULL );
+    VALIDATE_POINTER1( pszNewName, "OGR_Dr_CopyDataSource", NULL );
 
-    return (OGRDataSourceH)
+    OGRDataSource* poDS =
         ((OGRSFDriver *) hDriver)->CopyDataSource( 
             (OGRDataSource *) hSrcDS, pszNewName, papszOptions );
+
+    /* Make sure that the driver is attached to the created datasource */
+    /* if not already done by the implementation of the CopyDataSource() */
+    /* method */
+    if( poDS != NULL && poDS->GetDriver() == NULL )
+        poDS->SetDriver( (OGRSFDriver *)hDriver );
+
+    return (OGRDataSourceH)poDS;
 }
 
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
index 361d68a..5d581ca 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsfdriverregistrar.cpp 21447 2011-01-09 16:02:28Z rouault $
+ * $Id: ogrsfdriverregistrar.cpp 22812 2011-07-25 04:50:23Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSFDriverRegistrar class implementation.
@@ -37,7 +37,7 @@
 #include <unistd.h>
 #endif
 
-CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 21447 2011-01-09 16:02:28Z rouault $");
+CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 22812 2011-07-25 04:50:23Z warmerdam $");
 
 static void *hDRMutex = NULL;
 static OGRSFDriverRegistrar * volatile poRegistrar = NULL;
@@ -150,6 +150,9 @@ void OGRCleanupAll()
         swq_op_registrar::DeInitialize();
     }
 
+    CPLDestroyMutex( hDRMutex );
+    hDRMutex = NULL;
+
     CPLFinderClean();
     VSICleanupFileManager();
     CPLFreeConfig();
@@ -835,11 +838,26 @@ void OGRSFDriverRegistrar::AutoLoadDrivers()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Scan each directory looking for files starting with gdal_       */
+/*      Format the ABI version specific subdirectory to look in.        */
+/* -------------------------------------------------------------------- */
+    CPLString osABIVersion;
+
+    osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
+
+/* -------------------------------------------------------------------- */
+/*      Scan each directory looking for files starting with ogr_        */
 /* -------------------------------------------------------------------- */
     for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
     {
-        char  **papszFiles = CPLReadDir( papszSearchPath[iDir] );
+        char **papszFiles = NULL;
+        VSIStatBufL sStatBuf;
+        CPLString osABISpecificDir =
+            CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
+        
+        if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
+            osABISpecificDir = papszSearchPath[iDir];
+
+        papszFiles = CPLReadDir( osABISpecificDir );
 
         for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
         {
@@ -861,7 +879,7 @@ void OGRSFDriverRegistrar::AutoLoadDrivers()
                      CPLGetBasename(papszFiles[iFile]) + 4 );
             
             pszFilename = 
-                CPLFormFilename( papszSearchPath[iDir], 
+                CPLFormFilename( osABISpecificDir,
                                  papszFiles[iFile], NULL );
 
             pRegister = CPLGetSymbol( pszFilename, pszFuncName );
diff --git a/ogr/ogrsf_frmts/geoconcept/makefile.vc b/ogr/ogrsf_frmts/geoconcept/makefile.vc
index 493fee7..9e7fa65 100644
--- a/ogr/ogrsf_frmts/geoconcept/makefile.vc
+++ b/ogr/ogrsf_frmts/geoconcept/makefile.vc
@@ -1,7 +1,7 @@
 OBJ     =       geoconcept.obj geoconcept_syscoord.obj \
 		ogrgeoconceptdriver.obj \
 		ogrgeoconceptdatasource.obj ogrgeoconceptlayer.obj
-EXTRAFLAGS =	-I.. -I..\.. -DUSE_CPL
+EXTRAFLAGS =	-I.. -I..\.. -DUSE_CPL /wd4706
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
index 9cb3892..657a312 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
@@ -110,11 +110,20 @@ OGRGeoconceptDataSource::~OGRGeoconceptDataSource()
 int OGRGeoconceptDataSource::Open( const char* pszName, int bTestOpen, int bUpdate )
 
 {
-    VSIStatBuf  stat;
+/* -------------------------------------------------------------------- */
+/*      We will only consider .gxt and .txt files.                      */
+/* -------------------------------------------------------------------- */
+    const char* pszExtension = CPLGetExtension(pszName);
+    if( !EQUAL(pszExtension,"gxt") && !EQUAL(pszExtension,"txt") )
+    {
+        return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Is the given path a directory or a regular file?                */
 /* -------------------------------------------------------------------- */
+    VSIStatBuf  stat;
+
     if( CPLStat( pszName, &stat ) != 0
         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     {
@@ -170,10 +179,6 @@ int OGRGeoconceptDataSource::LoadFile( const char *pszMode )
     if( _pszExt == NULL)
     {
       const char* pszExtension = CPLGetExtension(_pszName);
-      if( !EQUAL(pszExtension,"gxt") && !EQUAL(pszExtension,"txt") )
-      {
-        return FALSE;
-      }
       _pszExt = CPLStrdup(pszExtension);
     }
     CPLStrlwr( _pszExt );
diff --git a/ogr/ogrsf_frmts/geojson/GNUmakefile b/ogr/ogrsf_frmts/geojson/GNUmakefile
index ef8a83f..4260e81 100644
--- a/ogr/ogrsf_frmts/geojson/GNUmakefile
+++ b/ogr/ogrsf_frmts/geojson/GNUmakefile
@@ -22,3 +22,5 @@ default:        $(foreach d,$(SUBDIRS-yes),$(d)-target) $(O_OBJ:.o=.$(OBJ_EXT))
 clean: $(foreach d,$(SUBDIRS-yes),$(d)-clean)
 	rm -f *.o $(O_OBJ)
 	rm -f *~
+
+$(O_OBJ):       ogr_geojson.h
diff --git a/ogr/ogrsf_frmts/geojson/drv_geojson.html b/ogr/ogrsf_frmts/geojson/drv_geojson.html
index e5b3c61..0607c38 100644
--- a/ogr/ogrsf_frmts/geojson/drv_geojson.html
+++ b/ogr/ogrsf_frmts/geojson/drv_geojson.html
@@ -85,6 +85,24 @@ This behavior may be controlled by setting environment variable <strong>GEOMETRY
 <li><b>ATTRIBUTES_SKIP</b> - controls translation of attributes: YES - skip all attributes</li>
 </ul>
 
+<h2>Layer creation option</h2>
+
+<ul>
+<li><b>WRITE_BBOX</b> = YES/NO : (OGR >= 1.9.0) Set to YES to write a bbox property with the bounding box of the geometries at the feature and feature
+collection level. Defaults to NO.</li>
+<li><b>COORDINATE_PRECISION</b> = int_number : (OGR >= 1.9.0) Maximum number of figures after decimal separator to write in coordinates.
+Default to 15. "Smart" truncation will occur to remove trailing zeros.</li>
+</ul>
+
+<h2>VSI Virtual File System API support</h2>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
+
 <h2>Example</h2>
 
 <p>How to dump content of .geojson file:
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/ChangeLog b/ogr/ogrsf_frmts/geojson/jsonc/ChangeLog
index dddd995..4cd28d3 100644
--- a/ogr/ogrsf_frmts/geojson/jsonc/ChangeLog
+++ b/ogr/ogrsf_frmts/geojson/jsonc/ChangeLog
@@ -1,3 +1,7 @@
+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>
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_object.c b/ogr/ogrsf_frmts/geojson/jsonc/json_object.c
index 1022cf3..1c2a12e 100644
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_object.c
+++ b/ogr/ogrsf_frmts/geojson/jsonc/json_object.c
@@ -356,10 +356,134 @@ int json_object_get_int(struct json_object *jso)
 
 /* 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)
 {
-  return sprintbuf(pb, "%f", jso->o.c_double);
+   /* 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)
@@ -368,8 +492,21 @@ struct json_object* json_object_new_double(double d)
   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)
 {
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_object.h b/ogr/ogrsf_frmts/geojson/jsonc/json_object.h
index 80d2313..a2bdcce 100644
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_object.h
+++ b/ogr/ogrsf_frmts/geojson/jsonc/json_object.h
@@ -274,6 +274,15 @@ extern int json_object_get_int(struct json_object *obj);
  */
 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.
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/json_object_private.h b/ogr/ogrsf_frmts/geojson/jsonc/json_object_private.h
index 9fb4011..9265239 100644
--- a/ogr/ogrsf_frmts/geojson/jsonc/json_object_private.h
+++ b/ogr/ogrsf_frmts/geojson/jsonc/json_object_private.h
@@ -35,6 +35,7 @@ struct json_object
     struct array_list *c_array;
     char *c_string;
   } o;
+  int _precision; /* GDAL addition */
 };
 
 /* CAW: added for ANSI C iteration correctness */
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/makefile.vc b/ogr/ogrsf_frmts/geojson/jsonc/makefile.vc
index 5256a83..6cbe3ff 100644
--- a/ogr/ogrsf_frmts/geojson/jsonc/makefile.vc
+++ b/ogr/ogrsf_frmts/geojson/jsonc/makefile.vc
@@ -16,7 +16,7 @@ GDAL_ROOT	=	..\..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS =	-I.. -I..\.. -I..\..\..
+EXTRAFLAGS =	-I.. -I..\.. -I..\..\.. $(SOFTWARNFLAGS)
 
 default:	$(OBJ)
 
diff --git a/ogr/ogrsf_frmts/geojson/jsonc/printbuf.c b/ogr/ogrsf_frmts/geojson/jsonc/printbuf.c
index 44f3391..d5760f2 100644
--- a/ogr/ogrsf_frmts/geojson/jsonc/printbuf.c
+++ b/ogr/ogrsf_frmts/geojson/jsonc/printbuf.c
@@ -89,9 +89,9 @@ int sprintbuf(struct printbuf *p, const char *msg, ...)
           *pszComma = '.';
   }
   
-  ret = printbuf_memappend(p, t, size); 
-  free(t); 
-  return ret; 
+  ret = printbuf_memappend(p, t, size);
+  CPLFree(t);
+  return ret;
 }
 
 void printbuf_reset(struct printbuf *p)
diff --git a/ogr/ogrsf_frmts/geojson/ogr_geojson.h b/ogr/ogrsf_frmts/geojson/ogr_geojson.h
index fcae89e..048bc4c 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 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_geojson.h 23367 2011-11-12 22:46:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definitions of OGR OGRGeoJSON driver types.
@@ -33,6 +33,8 @@
 #include <cstdio>
 #include <vector> // used by OGRGeoJSONLayer
 
+#define SPACE_FOR_BBOX  80
+
 class OGRGeoJSONDataSource;
 
 /************************************************************************/
@@ -88,6 +90,12 @@ private:
     OGRSpatialReference* poSRS_;
     CPLString sFIDColumn_;
     int nOutCounter_;
+
+    int bWriteBBOX;
+    int bBBOX3D;
+    OGREnvelope3D sEnvelopeLayer;
+
+    int nCoordPrecision;
 };
 
 /************************************************************************/
@@ -136,6 +144,9 @@ public:
 
     void SetAttributesTranslation( AttributesTranslation type );
 
+    int  GetFpOutputIsSeekable() const { return bFpOutputIsSeekable_; }
+    int  GetBBOXInsertLocation() const { return nBBOXInsertLocation_; }
+
 private:
 
     //
@@ -153,6 +164,9 @@ private:
     GeometryTranslation flTransGeom_;
     AttributesTranslation flTransAttrs_;
 
+    int bFpOutputIsSeekable_;
+    int nBBOXInsertLocation_;
+
     //
     // Priavte utility functions
     //
@@ -186,7 +200,7 @@ public:
     //
     // OGRGeoJSONDriver Interface
     //
-    // NOTE: New version of Open() based on Andrey's RCF 10.
+    // NOTE: New version of Open() based on Andrey's RFC 10.
     OGRDataSource* Open( const char* pszName, int bUpdate,
                          char** papszOptions );
 
diff --git a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
index 730f15e..9f08a3b 100644
--- a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogresrijsonreader.cpp 22282 2011-05-01 17:58:03Z rouault $
+ * $Id: ogresrijsonreader.cpp 22281 2011-05-01 17:57:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRESRIJSONReader class (OGR ESRIJSON Driver)
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
index 170e192..b7a034c 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsondatasource.cpp 21345 2010-12-30 11:37:54Z rouault $
+ * $Id: ogrgeojsondatasource.cpp 23367 2011-11-12 22:46:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONDataSource class (OGR GeoJSON Driver).
@@ -43,7 +43,9 @@ OGRGeoJSONDataSource::OGRGeoJSONDataSource()
     : pszName_(NULL), pszGeoData_(NULL),
         papoLayers_(NULL), nLayers_(0), fpOut_(NULL),
         flTransGeom_( OGRGeoJSONDataSource::eGeometryPreserve ),
-        flTransAttrs_( OGRGeoJSONDataSource::eAtributesPreserve )
+        flTransAttrs_( OGRGeoJSONDataSource::eAtributesPreserve ),
+        bFpOutputIsSeekable_( FALSE ),
+        nBBOXInsertLocation_(0)
 {
     // I've got constructed. Lunch time!
 }
@@ -115,7 +117,11 @@ int OGRGeoJSONDataSource::Open( const char* pszName )
 /*      Construct OGR layer and feature objects from                    */
 /*      GeoJSON text tree.                                              */
 /* -------------------------------------------------------------------- */
-    if( NULL == pszGeoData_ )
+    if( NULL == pszGeoData_ ||
+        strncmp(pszGeoData_, "{\"couchdb\":\"Welcome\"", strlen("{\"couchdb\":\"Welcome\"")) == 0 ||
+        strncmp(pszGeoData_, "{\"db_name\":\"", strlen("{\"db_name\":\"")) == 0 ||
+        strncmp(pszGeoData_, "{\"total_rows\":", strlen("{\"total_rows\":")) == 0 ||
+        strncmp(pszGeoData_, "{\"rows\":[", strlen("{\"rows\":[")) == 0)
     {
         Clear();
         return FALSE;
@@ -218,7 +224,19 @@ OGRLayer* OGRGeoJSONDataSource::CreateLayer( const char* pszName_,
 
     if( NULL != fpOut_ )
     {
-        VSIFPrintfL( fpOut_, "{\n\"type\": \"FeatureCollection\",\n\"features\": [\n" );
+        VSIFPrintfL( fpOut_, "{\n\"type\": \"FeatureCollection\",\n" );
+
+        if (bFpOutputIsSeekable_)
+        {
+            nBBOXInsertLocation_ = (int) VSIFTellL( fpOut_ );
+
+            char szSpaceForBBOX[SPACE_FOR_BBOX+1];
+            memset(szSpaceForBBOX, ' ', SPACE_FOR_BBOX);
+            szSpaceForBBOX[SPACE_FOR_BBOX] = '\0';
+            VSIFPrintfL( fpOut_, "%s\n", szSpaceForBBOX);
+        }
+
+        VSIFPrintfL( fpOut_, "\"features\": [\n" );
     }
 
     return poLayer;
@@ -244,6 +262,13 @@ int OGRGeoJSONDataSource::Create( const char* pszName, char** papszOptions )
 
     CPLAssert( NULL == fpOut_ );
 
+    if (strcmp(pszName, "/dev/stdout") == 0)
+        pszName = "/vsistdout/";
+
+    bFpOutputIsSeekable_ =  !(strcmp(pszName,"/vsistdout/") == 0 ||
+                              strncmp(pszName,"/vsigzip/", 9) == 0 ||
+                              strncmp(pszName,"/vsizip/", 8) == 0);
+
 /* -------------------------------------------------------------------- */
 /*     File overwrite not supported.                                    */
 /* -------------------------------------------------------------------- */
@@ -258,11 +283,7 @@ int OGRGeoJSONDataSource::Create( const char* pszName, char** papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    if( EQUAL( pszName, "stdout" ) )
-        fpOut_ = VSIFOpenL( "/vsistdout/", "w" );
-    else
-        fpOut_ = VSIFOpenL( pszName, "w" );
-
+    fpOut_ = VSIFOpenL( pszName, "w" );
     if( NULL == fpOut_)
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
@@ -362,7 +383,7 @@ int OGRGeoJSONDataSource::ReadFromFile( const char* pszSource )
 
     VSIFSeekL( fp, 0, SEEK_SET );
 
-    pszGeoData_ = (char*)VSIMalloc(nDataLen + 1);
+    pszGeoData_ = (char*)VSIMalloc((size_t)(nDataLen + 1));
     if( NULL == pszGeoData_ )
     {
         VSIFCloseL(fp);
@@ -370,7 +391,7 @@ int OGRGeoJSONDataSource::ReadFromFile( const char* pszSource )
     }
 
     pszGeoData_[nDataLen] = '\0';
-    if( ( nDataLen != VSIFReadL( pszGeoData_, 1, nDataLen, fp ) ) )
+    if( ( nDataLen != VSIFReadL( pszGeoData_, 1, (size_t)nDataLen, fp ) ) )
     {
         Clear();
         VSIFCloseL( fp );
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
index 0727d0f..a085d0d 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonlayer.cpp 21338 2010-12-29 22:45:03Z rouault $
+ * $Id: ogrgeojsonlayer.cpp 23367 2011-11-12 22:46:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
@@ -55,7 +55,8 @@ OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
                                   OGRGeoJSONDataSource* poDS )
     : iterCurrent_( seqFeatures_.end() ), poDS_( poDS ), poFeatureDefn_(new OGRFeatureDefn( pszName ) ), poSRS_( NULL ), nOutCounter_( 0 )
 {
-    UNREFERENCED_PARAM(papszOptions);
+    bWriteBBOX = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WRITE_BBOX", "FALSE"));
+    bBBOX3D = FALSE;
 
     CPLAssert( NULL != poDS_ );
     CPLAssert( NULL != poFeatureDefn_ );
@@ -67,6 +68,8 @@ OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
     {
         SetSpatialRef( poSRSIn );
     }
+
+    nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
 }
 
 /************************************************************************/
@@ -78,7 +81,43 @@ OGRGeoJSONLayer::~OGRGeoJSONLayer()
     VSILFILE* fp = poDS_->GetOutputFile();
     if( NULL != fp )
     {
-        VSIFPrintfL( fp, "\n]\n}\n" );
+        VSIFPrintfL( fp, "\n]" );
+
+        if( bWriteBBOX && sEnvelopeLayer.IsInit() )
+        {
+            json_object* poObjBBOX = json_object_new_array();
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelopeLayer.MinX, nCoordPrecision));
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelopeLayer.MinY, nCoordPrecision));
+            if( bBBOX3D )
+                json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelopeLayer.MinZ, nCoordPrecision));
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelopeLayer.MaxX, nCoordPrecision));
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelopeLayer.MaxY, nCoordPrecision));
+            if( bBBOX3D )
+                json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelopeLayer.MaxZ, nCoordPrecision));
+
+            const char* pszBBOX = json_object_to_json_string( poObjBBOX );
+            if( poDS_->GetFpOutputIsSeekable() )
+            {
+                VSIFSeekL(fp, poDS_->GetBBOXInsertLocation(), SEEK_SET);
+                if (strlen(pszBBOX) + 9 < SPACE_FOR_BBOX)
+                    VSIFPrintfL( fp, "\"bbox\": %s,", pszBBOX );
+                VSIFSeekL(fp, 0, SEEK_END);
+            }
+            else
+            {
+                VSIFPrintfL( fp, ",\n\"bbox\": %s", pszBBOX );
+            }
+
+            json_object_put( poObjBBOX );
+        }
+
+        VSIFPrintfL( fp, "\n}\n" );
     }
 
     std::for_each(seqFeatures_.begin(), seqFeatures_.end(),
@@ -215,7 +254,7 @@ OGRErr OGRGeoJSONLayer::CreateFeature( OGRFeature* poFeature )
         return OGRERR_INVALID_HANDLE;
     }
 
-    json_object* poObj = OGRGeoJSONWriteFeature( poFeature );
+    json_object* poObj = OGRGeoJSONWriteFeature( poFeature, bWriteBBOX, nCoordPrecision );
     CPLAssert( NULL != poObj );
 
     if( nOutCounter_ > 0 )
@@ -229,6 +268,18 @@ OGRErr OGRGeoJSONLayer::CreateFeature( OGRFeature* poFeature )
 
     ++nOutCounter_;
 
+    OGRGeometry* poGeometry = poFeature->GetGeometryRef();
+    if ( bWriteBBOX && !poGeometry->IsEmpty() )
+    {
+        OGREnvelope3D sEnvelope;
+        poGeometry->getEnvelope(&sEnvelope);
+
+        if( poGeometry->getCoordinateDimension() == 3 )
+            bBBOX3D = TRUE;
+
+        sEnvelopeLayer.Merge(sEnvelope);
+    }
+
     return OGRERR_NONE;
 }
 
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
index bb4385d..7f1a1b6 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.cpp 22358 2011-05-11 18:11:29Z rouault $
+ * $Id: ogrgeojsonreader.cpp 23654 2011-12-29 16:19:38Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONReader class (OGR GeoJSON Driver).
@@ -40,7 +40,8 @@
 OGRGeoJSONReader::OGRGeoJSONReader()
     : poGJObject_( NULL ), poLayer_( NULL ),
         bGeometryPreserve_( true ),
-        bAttributesSkip_( false )
+        bAttributesSkip_( false ),
+        bFlattenGeocouchSpatiallistFormat (-1), bFoundId (false), bFoundRev(false), bFoundTypeFeature(false), bIsGeocouchSpatiallistFormat(false)
 {
     // Take a deep breath and get to work.
 }
@@ -425,6 +426,16 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
     if( NULL != poObjProps &&
         json_object_get_type(poObjProps) == json_type_object )
     {
+        if (bIsGeocouchSpatiallistFormat)
+        {
+            poObjProps = json_object_object_get(poObjProps, "properties");
+            if( NULL == poObjProps ||
+                json_object_get_type(poObjProps) != json_type_object )
+            {
+                return true;
+            }
+        }
+
         json_object_iter it;
         it.key = NULL;
         it.val = NULL;
@@ -434,6 +445,30 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
             int nFldIndex = poDefn->GetFieldIndex( it.key );
             if( -1 == nFldIndex )
             {
+                /* Detect the special kind of GeoJSON output by a spatiallist of GeoCouch */
+                /* such as http://gd.iriscouch.com/cphosm/_design/geo/_rewrite/data?bbox=12.53%2C55.73%2C12.54%2C55.73 */
+                if (strcmp(it.key, "_id") == 0)
+                    bFoundId = true;
+                else if (bFoundId && strcmp(it.key, "_rev") == 0)
+                    bFoundRev = true;
+                else if (bFoundRev && strcmp(it.key, "type") == 0 &&
+                         it.val != NULL && json_object_get_type(it.val) == json_type_string &&
+                         strcmp(json_object_get_string(it.val), "Feature") == 0)
+                    bFoundTypeFeature = true;
+                else if (bFoundTypeFeature && strcmp(it.key, "properties") == 0 &&
+                         it.val != NULL && json_object_get_type(it.val) == json_type_object)
+                {
+                    if (bFlattenGeocouchSpatiallistFormat < 0)
+                        bFlattenGeocouchSpatiallistFormat = CSLTestBoolean(
+                            CPLGetConfigOption("GEOJSON_FLATTEN_GEOCOUCH", "TRUE"));
+                    if (bFlattenGeocouchSpatiallistFormat)
+                    {
+                        poDefn->DeleteFieldDefn(poDefn->GetFieldIndex("type"));
+                        bIsGeocouchSpatiallistFormat = true;
+                        return GenerateFeatureDefn(poObj);
+                    }
+                }
+
                 OGRFieldDefn fldDefn( it.key,
                     GeoJSONPropertyToFieldType( it.val ) );
                 poDefn->AddFieldDefn( &fldDefn );
@@ -446,7 +481,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
                 {
                     OGRFieldType eNewType = GeoJSONPropertyToFieldType( it.val );
                     if( eNewType == OFTReal )
-                        poFDefn->SetType(OFTReal);
+                        poFDefn->SetType(eNewType);
                 }
             }
         }
@@ -558,6 +593,24 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
     if( !bAttributesSkip_ && NULL != poObjProps &&
         json_object_get_type(poObjProps) == json_type_object )
     {
+        if (bIsGeocouchSpatiallistFormat)
+        {
+            json_object* poId = json_object_object_get(poObjProps, "_id");
+            if (poId != NULL && json_object_get_type(poId) == json_type_string)
+                poFeature->SetField( "_id", json_object_get_string(poId) );
+
+            json_object* poRev = json_object_object_get(poObjProps, "_rev");
+            if (poRev != NULL && json_object_get_type(poRev) == json_type_string)
+                poFeature->SetField( "_rev", json_object_get_string(poRev) );
+
+            poObjProps = json_object_object_get(poObjProps, "properties");
+            if( NULL == poObjProps ||
+                json_object_get_type(poObjProps) != json_type_object )
+            {
+                return poFeature;
+            }
+        }
+
         int nField = -1;
         OGRFieldDefn* poFieldDefn = NULL;
         json_object_iter it;
@@ -569,11 +622,13 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
             nField = poFeature->GetFieldIndex(it.key);
             poFieldDefn = poFeature->GetFieldDefnRef(nField);
             CPLAssert( NULL != poFieldDefn );
+            OGRFieldType eType = poFieldDefn->GetType();
 
-			/* Unset FID. */
-			poFeature->SetFID( -1 );
-
-            if( OFTInteger == poFieldDefn->GetType() )
+            if( it.val == NULL)
+            {
+                /* nothing to do */
+            }
+            else if( OFTInteger == eType )
 			{
                 poFeature->SetField( nField, json_object_get_int(it.val) );
 				
@@ -581,10 +636,60 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
 				if( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
 					poFeature->SetFID( json_object_get_int(it.val) );
 			}
-            else if( OFTReal == poFieldDefn->GetType() )
+            else if( OFTReal == eType )
 			{
                 poFeature->SetField( nField, json_object_get_double(it.val) );
 			}
+            else if( OFTIntegerList == eType )
+            {
+                if ( json_object_get_type(it.val) == json_type_array )
+                {
+                    int nLength = json_object_array_length(it.val);
+                    int* panVal = (int*)CPLMalloc(sizeof(int) * nLength);
+                    for(int i=0;i<nLength;i++)
+                    {
+                        json_object* poRow = json_object_array_get_idx(it.val, i);
+                        panVal[i] = json_object_get_int(poRow);
+                    }
+                    poFeature->SetField( nField, nLength, panVal );
+                    CPLFree(panVal);
+                }
+            }
+            else if( OFTRealList == eType )
+            {
+                if ( json_object_get_type(it.val) == json_type_array )
+                {
+                    int nLength = json_object_array_length(it.val);
+                    double* padfVal = (double*)CPLMalloc(sizeof(double) * nLength);
+                    for(int i=0;i<nLength;i++)
+                    {
+                        json_object* poRow = json_object_array_get_idx(it.val, i);
+                        padfVal[i] = json_object_get_double(poRow);
+                    }
+                    poFeature->SetField( nField, nLength, padfVal );
+                    CPLFree(padfVal);
+                }
+            }
+            else if( OFTStringList == eType )
+            {
+                if ( json_object_get_type(it.val) == json_type_array )
+                {
+                    int nLength = json_object_array_length(it.val);
+                    char** papszVal = (char**)CPLMalloc(sizeof(char*) * (nLength+1));
+                    int i;
+                    for(i=0;i<nLength;i++)
+                    {
+                        json_object* poRow = json_object_array_get_idx(it.val, i);
+                        const char* pszVal = json_object_get_string(poRow);
+                        if (pszVal == NULL)
+                            break;
+                        papszVal[i] = CPLStrdup(pszVal);
+                    }
+                    papszVal[i] = NULL;
+                    poFeature->SetField( nField, papszVal );
+                    CSLDestroy(papszVal);
+                }
+            }
             else
 			{
                 poFeature->SetField( nField, json_object_get_string(it.val) );
@@ -722,10 +827,9 @@ json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
     it.key = NULL;
     it.val = NULL;
     it.entry = NULL;
-    if( NULL != json_object_get_object(poTmp) )
+    if( NULL != json_object_get_object(poTmp) &&
+        NULL != json_object_get_object(poTmp)->head )
     {
-        CPLAssert( NULL != json_object_get_object(poTmp)->head );
-
         for( it.entry = json_object_get_object(poTmp)->head;
              ( it.entry ?
                ( it.key = (char*)it.entry->k,
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
index 85a2be4..7ea8af2 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.h 21346 2010-12-30 11:59:00Z rouault $
+ * $Id: ogrgeojsonreader.h 23325 2011-11-05 17:19:38Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -103,6 +103,9 @@ private:
     bool bGeometryPreserve_;
     bool bAttributesSkip_;
 
+    int bFlattenGeocouchSpatiallistFormat;
+    bool bFoundId, bFoundRev, bFoundTypeFeature, bIsGeocouchSpatiallistFormat;
+
     //
     // Copy operations not supported.
     //
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
index 957baed..2520eea 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonutils.cpp 19489 2010-04-21 21:39:05Z rouault $
+ * $Id: ogrgeojsonutils.cpp 23293 2011-10-30 11:11:39Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of private utilities used within OGR GeoJSON Driver.
@@ -54,6 +54,65 @@ int GeoJSONIsObject( const char* pszText )
 }
 
 /************************************************************************/
+/*                           GeoJSONFileIsObject()                      */
+/************************************************************************/
+
+int GeoJSONFileIsObject( const char* pszSource ) 
+{ 
+    CPLAssert( NULL != pszSource ); 
+ 
+    VSILFILE* fp = NULL; 
+    fp = VSIFOpenL( pszSource, "rb" ); 
+    if( NULL == fp ) 
+    { 
+        return FALSE; 
+    } 
+    
+    // by default read first 6000 bytes 
+    // 6000 was chosen as enough bytes to  
+    // enable all current tests to pass 
+    vsi_l_offset nToReadLen = 6000; 
+    vsi_l_offset nDataLen = 0; 
+
+    char* pszGeoData = (char*)VSIMalloc((size_t)(nToReadLen + 1)); 
+    if( NULL == pszGeoData ) 
+    { 
+        VSIFCloseL(fp); 
+        return FALSE; 
+    } 
+
+    nDataLen = VSIFReadL( pszGeoData, 1, (size_t)nToReadLen, fp );
+    pszGeoData[nDataLen] = '\0'; 
+    if( nDataLen == 0 ) 
+    { 
+        VSIFCloseL( fp ); 
+        CPLFree( pszGeoData ); 
+        return FALSE; 
+    } 
+    VSIFCloseL( fp ); 
+    
+    char* pszIter = pszGeoData;
+    while( *pszIter != '\0' && isspace( (unsigned char)*pszIter ) )
+        pszIter++;
+
+    if( *pszIter != '{' )
+    {
+        CPLFree( pszGeoData ); 
+        return FALSE;
+    }
+
+    int bRet = FALSE; 
+
+    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; 
+} 
+
+/************************************************************************/
 /*                           GeoJSONGetSourceType()                     */
 /************************************************************************/
 
@@ -76,10 +135,13 @@ GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource )
     {
         srcType = eGeoJSONSourceFile;
     }
-    else
+    else if( GeoJSONIsObject( pszSource ) )
     {
-        if( GeoJSONIsObject( pszSource ) )
-            srcType = eGeoJSONSourceText;
+        srcType = eGeoJSONSourceText;
+    }
+    else if( GeoJSONFileIsObject( pszSource ) )
+    {
+        srcType = eGeoJSONSourceFile;
     }
 
     return srcType;
@@ -122,7 +184,28 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject )
     else if( json_type_string == type )
         return OFTString;
     else if( json_type_array == type )
-        return OFTStringList; /* string or JSON-string */
+    {
+        int nSize = json_object_array_length(poObject);
+        if (nSize == 0)
+            return OFTStringList; /* we don't know, so let's assume it's a string list */
+        OGRFieldType eType = OFTIntegerList;
+        for(int i=0;i<nSize;i++)
+        {
+            json_object* poRow = json_object_array_get_idx(poObject, i);
+            if (poRow != NULL)
+            {
+                type = json_object_get_type( poRow );
+                if (type == json_type_string)
+                    return OFTStringList;
+                else if (type == json_type_double)
+                    eType = OFTRealList;
+                else if (type != json_type_int &&
+                         type != json_type_boolean)
+                    return OFTString;
+            }
+        }
+        return eType;
+    }
     else
         return OFTString; /* null, object */
 }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
index d6a1fd9..4b1525d 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.cpp 21350 2010-12-30 18:35:09Z rouault $
+ * $Id: ogrgeojsonwriter.cpp 22490 2011-06-03 10:26:47Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of GeoJSON writer utilities (OGR GeoJSON Driver).
@@ -36,7 +36,7 @@
 /*                           OGRGeoJSONWriteFeature                     */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature )
+json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision )
 {
     CPLAssert( NULL != poFeature );
 
@@ -72,8 +72,31 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature )
     OGRGeometry* poGeometry = poFeature->GetGeometryRef();
     if ( NULL != poGeometry )
     {
-        poObjGeom = OGRGeoJSONWriteGeometry( poGeometry );
-        CPLAssert( NULL != poObjGeom );
+        poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision );
+
+        if ( bWriteBBOX && !poGeometry->IsEmpty() )
+        {
+            OGREnvelope3D sEnvelope;
+            poGeometry->getEnvelope(&sEnvelope);
+
+            json_object* poObjBBOX = json_object_new_array();
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelope.MinX, nCoordPrecision));
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelope.MinY, nCoordPrecision));
+            if (poGeometry->getCoordinateDimension() == 3)
+                json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelope.MinZ, nCoordPrecision));
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelope.MaxX, nCoordPrecision));
+            json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelope.MaxY, nCoordPrecision));
+            if (poGeometry->getCoordinateDimension() == 3)
+                json_object_array_add(poObjBBOX,
+                            json_object_new_double_with_precision(sEnvelope.MaxZ, nCoordPrecision));
+
+            json_object_object_add( poObj, "bbox", poObjBBOX );
+        }
     }
     
     json_object_object_add( poObj, "geometry", poObjGeom );
@@ -95,25 +118,62 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
     OGRFeatureDefn* poDefn = poFeature->GetDefnRef();
     for( int nField = 0; nField < poDefn->GetFieldCount(); ++nField )
     {
-        json_object* poObjProp = NULL;
+        json_object* poObjProp;
         OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn( nField );
         CPLAssert( NULL != poFieldDefn );
+        OGRFieldType eType = poFieldDefn->GetType();
 
-        if( OFTInteger == poFieldDefn->GetType() )
+        if( !poFeature->IsFieldSet(nField) )
+        {
+            poObjProp = NULL;
+        }
+        else if( OFTInteger == eType )
         {
             poObjProp = json_object_new_int( 
                 poFeature->GetFieldAsInteger( nField ) );
         }
-        else if( OFTReal == poFieldDefn->GetType() )
+        else if( OFTReal == eType )
         {
             poObjProp = json_object_new_double( 
                 poFeature->GetFieldAsDouble(nField) );
         }
-        else if( OFTString == poFieldDefn->GetType() )
+        else if( OFTString == eType )
         {
             poObjProp = json_object_new_string( 
                 poFeature->GetFieldAsString(nField) );
         }
+        else if( OFTIntegerList == eType )
+        {
+            int nSize = 0;
+            const int* panList = poFeature->GetFieldAsIntegerList(nField, &nSize);
+            poObjProp = json_object_new_array();
+            for(int i=0;i<nSize;i++)
+            {
+                json_object_array_add(poObjProp,
+                            json_object_new_int(panList[i]));
+            }
+        }
+        else if( OFTRealList == eType )
+        {
+            int nSize = 0;
+            const double* padfList = poFeature->GetFieldAsDoubleList(nField, &nSize);
+            poObjProp = json_object_new_array();
+            for(int i=0;i<nSize;i++)
+            {
+                json_object_array_add(poObjProp,
+                            json_object_new_double(padfList[i]));
+            }
+        }
+        else if( OFTStringList == eType )
+        {
+            char** papszStringList = poFeature->GetFieldAsStringList(nField);
+            poObjProp = json_object_new_array();
+            for(int i=0; papszStringList && papszStringList[i]; i++)
+            {
+                json_object_array_add(poObjProp,
+                            json_object_new_string(papszStringList[i]));
+            }
+        }
         else
         {
             poObjProp = json_object_new_string( 
@@ -132,7 +192,7 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature )
 /*                           OGRGeoJSONWriteGeometry                    */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry )
+json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecision )
 {
     CPLAssert( NULL != poGeometry );
 
@@ -155,23 +215,23 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry )
     OGRwkbGeometryType eType = poGeometry->getGeometryType();
     if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
     {
-        poObjGeom = OGRGeoJSONWriteGeometryCollection( static_cast<OGRGeometryCollection*>(poGeometry) );
+        poObjGeom = OGRGeoJSONWriteGeometryCollection( static_cast<OGRGeometryCollection*>(poGeometry), nCoordPrecision );
         json_object_object_add( poObj, "geometries", poObjGeom);
     }
     else
     {
         if( wkbPoint == eType || wkbPoint25D == eType )
-            poObjGeom = OGRGeoJSONWritePoint( static_cast<OGRPoint*>(poGeometry) );
+            poObjGeom = OGRGeoJSONWritePoint( static_cast<OGRPoint*>(poGeometry), nCoordPrecision );
         else if( wkbLineString == eType || wkbLineString25D == eType )
-            poObjGeom = OGRGeoJSONWriteLineString( static_cast<OGRLineString*>(poGeometry) );
+            poObjGeom = OGRGeoJSONWriteLineString( static_cast<OGRLineString*>(poGeometry), nCoordPrecision );
         else if( wkbPolygon == eType || wkbPolygon25D == eType )
-            poObjGeom = OGRGeoJSONWritePolygon( static_cast<OGRPolygon*>(poGeometry) );
+            poObjGeom = OGRGeoJSONWritePolygon( static_cast<OGRPolygon*>(poGeometry), nCoordPrecision );
         else if( wkbMultiPoint == eType || wkbMultiPoint25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiPoint( static_cast<OGRMultiPoint*>(poGeometry) );
+            poObjGeom = OGRGeoJSONWriteMultiPoint( static_cast<OGRMultiPoint*>(poGeometry), nCoordPrecision );
         else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiLineString( static_cast<OGRMultiLineString*>(poGeometry) );
+            poObjGeom = OGRGeoJSONWriteMultiLineString( static_cast<OGRMultiLineString*>(poGeometry), nCoordPrecision );
         else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiPolygon( static_cast<OGRMultiPolygon*>(poGeometry) );
+            poObjGeom = OGRGeoJSONWriteMultiPolygon( static_cast<OGRMultiPolygon*>(poGeometry), nCoordPrecision );
         else
         {
             CPLDebug( "GeoJSON",
@@ -189,7 +249,7 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry )
 /*                           OGRGeoJSONWritePoint                       */
 /************************************************************************/
 
-json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint )
+json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision )
 {
     CPLAssert( NULL != poPoint );
 
@@ -200,12 +260,14 @@ json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint )
     {
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
                                        poPoint->getY(),
-                                       poPoint->getZ() );
+                                       poPoint->getZ(),
+                                       nCoordPrecision );
     }
     else if( 2 == poPoint->getCoordinateDimension() )
     {
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
-                                       poPoint->getY() );
+                                       poPoint->getY(),
+                                       nCoordPrecision );
     }
     else
     {
@@ -219,13 +281,13 @@ json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint )
 /*                           OGRGeoJSONWriteLineString                  */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine )
+json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, int nCoordPrecision )
 {
     CPLAssert( NULL != poLine );
 
     /* Generate "coordinates" object for 2D or 3D dimension. */
     json_object* poObj = NULL;
-    poObj = OGRGeoJSONWriteLineCoords( poLine );
+    poObj = OGRGeoJSONWriteLineCoords( poLine, nCoordPrecision );
 
     return poObj;
 }
@@ -234,7 +296,7 @@ json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine )
 /*                           OGRGeoJSONWritePolygon                     */
 /************************************************************************/
 
-json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon )
+json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision )
 {
     CPLAssert( NULL != poPolygon );
 
@@ -248,7 +310,7 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon )
         return poObj;
     
     json_object* poObjRing = NULL;
-    poObjRing = OGRGeoJSONWriteLineCoords( poRing );
+    poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision );
     json_object_array_add( poObj, poObjRing );
 
     /* Interior rings. */
@@ -259,7 +321,7 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon )
         if (poRing == NULL)
             continue;
 
-        poObjRing = OGRGeoJSONWriteLineCoords( poRing );
+        poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision );
 
         json_object_array_add( poObj, poObjRing );
     }
@@ -271,7 +333,7 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon )
 /*                           OGRGeoJSONWriteMultiPoint                  */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry )
+json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPrecision )
 {
     CPLAssert( NULL != poGeometry );
 
@@ -286,7 +348,7 @@ json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry )
         OGRPoint* poPoint = static_cast<OGRPoint*>(poGeom);
 
         json_object* poObjPoint = NULL;
-        poObjPoint = OGRGeoJSONWritePoint( poPoint );
+        poObjPoint = OGRGeoJSONWritePoint( poPoint, nCoordPrecision );
 
         json_object_array_add( poObj, poObjPoint );
     }
@@ -298,7 +360,7 @@ json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry )
 /*                           OGRGeoJSONWriteMultiLineString             */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry )
+json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int nCoordPrecision )
 {
     CPLAssert( NULL != poGeometry );
 
@@ -313,7 +375,7 @@ json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry )
         OGRLineString* poLine = static_cast<OGRLineString*>(poGeom);
 
         json_object* poObjLine = NULL;
-        poObjLine = OGRGeoJSONWriteLineString( poLine );
+        poObjLine = OGRGeoJSONWriteLineString( poLine, nCoordPrecision );
         
         json_object_array_add( poObj, poObjLine );
     }
@@ -325,7 +387,7 @@ json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry )
 /*                           OGRGeoJSONWriteMultiPolygon                */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry )
+json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoordPrecision )
 {
     CPLAssert( NULL != poGeometry );
 
@@ -340,7 +402,7 @@ json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry )
         OGRPolygon* poPoly = static_cast<OGRPolygon*>(poGeom);
 
         json_object* poObjPoly = NULL;
-        poObjPoly = OGRGeoJSONWritePolygon( poPoly );
+        poObjPoly = OGRGeoJSONWritePolygon( poPoly, nCoordPrecision );
         
         json_object_array_add( poObj, poObjPoly );
     }
@@ -352,7 +414,7 @@ json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry )
 /*                           OGRGeoJSONWriteGeometryCollection          */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry )
+json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry, int nCoordPrecision )
 {
     CPLAssert( NULL != poGeometry );
 
@@ -366,7 +428,7 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
         CPLAssert( NULL != poGeom );
         
         json_object* poObjGeom = NULL;
-        poObjGeom = OGRGeoJSONWriteGeometry( poGeom );
+        poObjGeom = OGRGeoJSONWriteGeometry( poGeom, nCoordPrecision );
         
         json_object_array_add( poObj, poObjGeom );
     }
@@ -377,23 +439,23 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
 /*                           OGRGeoJSONWriteCoords                      */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY )
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision )
 {
     json_object* poObjCoords = NULL;
     poObjCoords = json_object_new_array();
-    json_object_array_add( poObjCoords, json_object_new_double( fX ) );
-    json_object_array_add( poObjCoords, json_object_new_double( fY ) );
+    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 ) );
 
     return poObjCoords;
 }
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ )
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision )
 {
     json_object* poObjCoords = NULL;
     poObjCoords = json_object_new_array();
-    json_object_array_add( poObjCoords, json_object_new_double( fX ) );
-    json_object_array_add( poObjCoords, json_object_new_double( fY ) );
-    json_object_array_add( poObjCoords, json_object_new_double( fZ ) );
+    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 ) );
+    json_object_array_add( poObjCoords, json_object_new_double_with_precision( fZ, nCoordPrecision ) );
 
     return poObjCoords;
 }
@@ -402,7 +464,7 @@ json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double c
 /*                           OGRGeoJSONWriteLineCoords                  */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine )
+json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecision )
 {
     json_object* poObjPoint = NULL;
     json_object* poObjCoords = json_object_new_array();
@@ -410,7 +472,10 @@ json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine )
     const int nCount = poLine->getNumPoints();
     for( int i = 0; i < nCount; ++i )
     {
-        poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i) );
+        if( poLine->getCoordinateDimension() == 2 )
+            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), nCoordPrecision );
+        else
+            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), poLine->getZ(i), nCoordPrecision );
         json_object_array_add( poObjCoords, poObjPoint );
     }
     
@@ -434,17 +499,43 @@ json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine )
 
 char* OGR_G_ExportToJson( OGRGeometryH hGeometry )
 {
+    return OGR_G_ExportToJsonEx(hGeometry, NULL);
+}
+
+/************************************************************************/
+/*                           OGR_G_ExportToJsonEx                       */
+/************************************************************************/
+
+/**
+ * \brief Convert a geometry into GeoJSON format.
+ *
+ * The returned string should be freed with CPLFree() when no longer required.
+ *
+ * This method is the same as the C++ method OGRGeometry::exportToJson().
+ *
+ * @param hGeometry handle to the geometry.
+ * @param papszOptions a null terminated list of options. For now, only COORDINATE_PRECISION=int_number
+ *                     where int_number is the maximum number of figures after decimal separator to write in coordinates.
+ * @return A GeoJSON fragment or NULL in case of error.
+ *
+ * @since OGR 1.9.0
+ */
+
+char* OGR_G_ExportToJsonEx( OGRGeometryH hGeometry, char** papszOptions )
+{
     VALIDATE_POINTER1( hGeometry, "OGR_G_ExportToJson", NULL );
 
     OGRGeometry* poGeometry = (OGRGeometry*) (hGeometry);
 
+    int nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
+
     json_object* poObj = NULL;
-    poObj = OGRGeoJSONWriteGeometry( poGeometry );
-    
+    poObj = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision );
+
     if( NULL != poObj )
     {
         char* pszJson = CPLStrdup( json_object_to_json_string( poObj ) );
-        
+
         /* Release JSON tree. */
         json_object_put( poObj );
 
@@ -454,4 +545,3 @@ char* OGR_G_ExportToJson( OGRGeometryH hGeometry )
     /* Translation failed */
     return NULL;
 }
-
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
index 3e158a7..e6f39b6 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.h 19489 2010-04-21 21:39:05Z rouault $
+ * $Id: ogrgeojsonwriter.h 22490 2011-06-03 10:26:47Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -51,19 +51,19 @@ class OGRGeometryCollection;
 /*                 GeoJSON Geometry Translators                         */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature );
+json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision );
 json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature );
-json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry );
-json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint );
-json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine );
-json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon );
-json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry );
-json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry );
-json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry );
-json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry );
+json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecision );
+json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision );
+json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, int nCoordPrecision );
+json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision );
+json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPrecision );
+json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int nCoordPrecision );
+json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoordPrecision );
+json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry, int nCoordPrecision );
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY );
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ );
-json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine );
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision );
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision );
+json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecision );
 
 #endif /* OGR_GEOJSONWRITER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geomedia/GNUmakefile b/ogr/ogrsf_frmts/geomedia/GNUmakefile
new file mode 100644
index 0000000..1b12e2a
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/GNUmakefile
@@ -0,0 +1,15 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrgeomediadatasource.o ogrgeomedialayer.o ogrgeomediadriver.o \
+		ogrgeomediatablelayer.o ogrgeomediaselectlayer.o
+
+CPPFLAGS	:=	$(GDAL_INCLUDE) -I.. -I../.. $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_geomedia.h
diff --git a/ogr/ogrsf_frmts/geomedia/drv_geomedia.html b/ogr/ogrsf_frmts/geomedia/drv_geomedia.html
new file mode 100644
index 0000000..557237b
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/drv_geomedia.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
+
+<html>
+<head>
+
+  <title>Geomedia MDB database</title>
+</head>
+
+<body bgcolor="#FFFFFF">
+  <h1>Geomedia MDB database</h1>
+
+  <p>GDAL/OGR >= 1.9.0</p>
+
+  <p>OGR optionally supports reading Geomedia .mdb
+  files via ODBC. Geomedia is a Microsoft Access
+  database with a set of tables defined by Intergraph for holding
+  geodatabase metadata, and with geometry for features held in a
+  BLOB column in a custom format. This drivers accesses the database via
+  ODBC but does not depend on any Intergraph middle-ware.</p>
+
+  <p>Geomedia .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/">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>In order to facilitate compatibility with different configurations, 
+  the GEOMEDIA_DRIVER_TEMPLATE Config Option was added to provide a way to
+  programmatically set the DSN programmatically with the filename as 
+  an argument.   In cases where the driver name is known, this allows for
+  the construction of the DSN based on that information in a manner similar
+  to the default (used for Windows access to the Microsoft Access Driver).</p>
+  
+  <p>OGR treats all feature tables as layers. Most geometry types
+  should be supported (arcs are not yet). Coordinate system information
+  is not currently supported.</p>
+
+  <p>Currently the OGR Personal Geodatabase driver does not take
+  advantage of spatial indexes for fast spatial queries.</p>
+
+<p>By default, SQL statements are passed directly to the MDB 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>
+
+  <h2>How to use Geomedia driver with unixODBC and MDB Tools (on Unix and Linux)</h2>
+
+  <p>Starting with GDAL/OGR 1.9.0, the <a href="drv_mdb.html">MDB</a> driver is an alternate
+     way of reading Geomedia .mdb files without requiring unixODBC and MDB Tools</p>
+
+  <p>Refer to the similar section of the <a href="drv_pgeo.html">PGeo</a> driver. The prefix to use
+     for this driver is Geomedia:<p>
+
+  <h2>See also</h2>
+
+  <ul>
+  <li><a href="drv_mdb.html">MDB</a> driver page</li>
+  </ul>
+
+</body>
+</html>
+
diff --git a/ogr/ogrsf_frmts/geomedia/makefile.vc b/ogr/ogrsf_frmts/geomedia/makefile.vc
new file mode 100755
index 0000000..01d79d4
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/makefile.vc
@@ -0,0 +1,14 @@
+
+OBJ	=	ogrgeomediadriver.obj ogrgeomediadatasource.obj ogrgeomedialayer.obj \
+		ogrgeomediatablelayer.obj  ogrgeomediaselectlayer.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS = -I.. -I..\..
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
diff --git a/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
new file mode 100644
index 0000000..8996df0
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
@@ -0,0 +1,217 @@
+/******************************************************************************
+ * $Id: ogr_geomedia.h 21561 2011-01-23 12:22:58Z 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) 2005, 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_GEOMEDIA_H_INCLUDED
+#define _OGR_GEOMEDIA_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_odbc.h"
+#include "cpl_error.h"
+
+/************************************************************************/
+/*                          OGRGeomediaLayer                            */
+/************************************************************************/
+
+class OGRGeomediaDataSource;
+    
+class OGRGeomediaLayer : public OGRLayer
+{
+  protected:
+    OGRFeatureDefn     *poFeatureDefn;
+
+    CPLODBCStatement   *poStmt;
+
+    // Layer spatial reference system, and srid.
+    OGRSpatialReference *poSRS;
+    int                 nSRSId;
+
+    int                 iNextShapeId;
+
+    OGRGeomediaDataSource    *poDS;
+
+    char                *pszGeomColumn;
+    char                *pszFIDColumn;
+
+    int                *panFieldOrdinals;
+
+    CPLErr              BuildFeatureDefn( const char *pszLayerName,
+                                          CPLODBCStatement *poStmt );
+
+    virtual CPLODBCStatement *  GetStatement() { return poStmt; }
+
+    void                LookupSRID( int );
+
+  public:
+                        OGRGeomediaLayer();
+    virtual             ~OGRGeomediaLayer();
+
+    virtual void        ResetReading();
+    virtual OGRFeature *GetNextRawFeature();
+    virtual OGRFeature *GetNextFeature();
+
+    virtual OGRFeature *GetFeature( long nFeatureId );
+    
+    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    virtual OGRSpatialReference *GetSpatialRef();
+
+    virtual int         TestCapability( const char * );
+
+    virtual const char *GetFIDColumn();
+    virtual const char *GetGeometryColumn();
+};
+
+/************************************************************************/
+/*                       OGRGeomediaTableLayer                          */
+/************************************************************************/
+
+class OGRGeomediaTableLayer : public OGRGeomediaLayer
+{
+    int                 bUpdateAccess;
+
+    char                *pszQuery;
+
+    void		ClearStatement();
+    OGRErr              ResetStatement();
+
+    virtual CPLODBCStatement *  GetStatement();
+
+  public:
+                        OGRGeomediaTableLayer( OGRGeomediaDataSource * );
+                        ~OGRGeomediaTableLayer();
+
+    CPLErr              Initialize( const char *pszTableName, 
+                                    const char *pszGeomCol,
+                                    OGRSpatialReference* poSRS );
+
+    virtual void        ResetReading();
+    virtual int         GetFeatureCount( int );
+
+    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRFeature *GetFeature( long nFeatureId );
+    
+    virtual int         TestCapability( const char * );
+};
+
+/************************************************************************/
+/*                        OGRGeomediaSelectLayer                        */
+/************************************************************************/
+
+class OGRGeomediaSelectLayer : public OGRGeomediaLayer
+{
+    char                *pszBaseStatement;
+
+    void		ClearStatement();
+    OGRErr              ResetStatement();
+
+    virtual CPLODBCStatement *  GetStatement();
+
+  public:
+                        OGRGeomediaSelectLayer( OGRGeomediaDataSource *,
+                                           CPLODBCStatement * );
+                        ~OGRGeomediaSelectLayer();
+
+    virtual void        ResetReading();
+    virtual int         GetFeatureCount( int );
+
+    virtual OGRFeature *GetFeature( long nFeatureId );
+    
+    virtual int         TestCapability( const char * );
+};
+
+/************************************************************************/
+/*                        OGRGeomediaDataSource                         */
+/************************************************************************/
+
+class OGRGeomediaDataSource : public OGRDataSource
+{
+    OGRGeomediaLayer  **papoLayers;
+    int                 nLayers;
+
+    OGRGeomediaLayer  **papoLayersInvisible;
+    int                 nLayersWithInvisible;
+
+    char               *pszName;
+
+    int                 bDSUpdate;
+    CPLODBCSession      oSession;
+
+    CPLString          GetTableNameFromType(const char* pszTableType);
+    OGRSpatialReference* GetGeomediaSRS(const char* pszGCoordSystemTable,
+                                        const char* pszGCoordSystemGUID);
+
+  public:
+                        OGRGeomediaDataSource();
+                        ~OGRGeomediaDataSource();
+
+    int                 Open( const char *, int bUpdate, int bTestOpen );
+    int                 OpenTable( const char *pszTableName, 
+                                   const char *pszGeomCol,
+                                   int bUpdate );
+
+    const char          *GetName() { return pszName; }
+    int                 GetLayerCount() { return nLayers; }
+    OGRLayer            *GetLayer( int );
+    OGRLayer            *GetLayerByName( const char* pszLayerName );
+
+    int                 TestCapability( const char * );
+
+    virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                    OGRGeometry *poSpatialFilter,
+                                    const char *pszDialect );
+    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+
+    // Internal use
+    CPLODBCSession     *GetSession() { return &oSession; }
+};
+
+/************************************************************************/
+/*                          OGRGeomediaDriver                           */
+/************************************************************************/
+
+class OGRGeomediaDriver : public OGRSFDriver
+{
+    CPLString   osDriverFile;
+
+    bool        InstallMdbDriver();
+    bool        LibraryExists( const char* pszLibPath );
+    bool        FindDriverLib();
+    CPLString   FindDefaultLib(const char* pszLibName);
+
+  public:
+                ~OGRGeomediaDriver();
+                
+    const char  *GetName();
+    OGRDataSource *Open( const char *, int );
+
+    int          TestCapability( const char * );
+};
+
+#endif /* ndef _OGR_Geomedia_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
new file mode 100644
index 0000000..7d713e3
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
@@ -0,0 +1,446 @@
+/******************************************************************************
+ * $Id: ogrgeomediadatasource.cpp 21561 2011-01-23 12:22:58Z 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) 2005, 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_geomedia.h"
+#include "ogrgeomediageometry.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include <vector>
+
+CPL_CVSID("$Id: ogrgeomediadatasource.cpp 21561 2011-01-23 12:22:58Z rouault $");
+
+/************************************************************************/
+/*                       OGRGeomediaDataSource()                        */
+/************************************************************************/
+
+OGRGeomediaDataSource::OGRGeomediaDataSource()
+
+{
+    pszName = NULL;
+    papoLayers = NULL;
+    papoLayersInvisible = NULL;
+    nLayers = 0;
+    nLayersWithInvisible = 0;
+}
+
+/************************************************************************/
+/*                       ~OGRGeomediaDataSource()                       */
+/************************************************************************/
+
+OGRGeomediaDataSource::~OGRGeomediaDataSource()
+
+{
+    int         i;
+
+    CPLFree( pszName );
+
+    for( i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    for( i = 0; i < nLayersWithInvisible; i++ )
+        delete papoLayersInvisible[i];
+    CPLFree( papoLayersInvisible );
+}
+
+/************************************************************************/
+/*                  CheckDSNStringTemplate()                            */
+/* The string will be used as the formatting argument of sprintf with   */
+/* a string in vararg. So let's check there's only one '%s', and nothing*/
+/* else                                                                 */
+/************************************************************************/
+
+static int CheckDSNStringTemplate(const char* pszStr)
+{
+    int nPercentSFound = FALSE;
+    while(*pszStr)
+    {
+        if (*pszStr == '%')
+        {
+            if (pszStr[1] != 's')
+            {
+                return FALSE;
+            }
+            else
+            {
+                if (nPercentSFound)
+                    return FALSE;
+                nPercentSFound = TRUE;
+            }
+        }
+        pszStr ++;
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
+                              int bTestOpen )
+
+{
+    CPLAssert( nLayers == 0 );
+
+/* -------------------------------------------------------------------- */
+/*      If this is the name of an MDB file, then construct the          */
+/*      appropriate connection string.  Otherwise clip of GEOMEDIA: to  */
+/*      get the DSN.                                                    */
+/*                                                                      */
+/* -------------------------------------------------------------------- */
+    char *pszDSN;
+    if( EQUALN(pszNewName,"GEOMEDIA:",9) )
+        pszDSN = CPLStrdup( pszNewName + 9 );
+    else
+    {
+        const char *pszDSNStringTemplate = NULL;
+        pszDSNStringTemplate = CPLGetConfigOption( "GEOMEDIA_DRIVER_TEMPLATE", "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s");
+        if (!CheckDSNStringTemplate(pszDSNStringTemplate))
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Illegal value for GEOMEDIA_DRIVER_TEMPLATE option");
+            return FALSE;
+        }
+        pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
+        sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize based on the DSN.                                    */
+/* -------------------------------------------------------------------- */
+    CPLDebug( "Geomedia", "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 tables and their supporting info from           */
+/*      GAliasTable.                                                    */
+/* -------------------------------------------------------------------- */
+    CPLString osGFeaturesTable = GetTableNameFromType("INGRFeatures");
+    if (osGFeaturesTable.size() == 0)
+        return FALSE;
+
+    CPLString osGeometryProperties = GetTableNameFromType("INGRGeometryProperties");
+    CPLString osGCoordSystemTable = GetTableNameFromType("GCoordSystemTable");
+
+    std::vector<char **> apapszGeomColumns;
+    {
+        CPLODBCStatement oStmt( &oSession );
+        oStmt.Appendf( "SELECT FeatureName, PrimaryGeometryFieldName FROM %s", osGFeaturesTable.c_str() );
+
+        if( !oStmt.ExecuteSQL() )
+        {
+            CPLDebug( "GEOMEDIA",
+                    "SELECT on %s fails, perhaps not a geomedia geodatabase?\n%s",
+                    osGFeaturesTable.c_str(),
+                    oSession.GetLastError() );
+            return FALSE;
+        }
+
+        while( oStmt.Fetch() )
+        {
+            int i, iNew = apapszGeomColumns.size();
+            char **papszRecord = NULL;
+            for( i = 0; i < 2; i++ )
+                papszRecord = CSLAddString( papszRecord,
+                                            oStmt.GetColData(i) );
+            apapszGeomColumns.resize(iNew+1);
+            apapszGeomColumns[iNew] = papszRecord;
+        }
+    }
+
+    std::vector<OGRSpatialReference*> apoSRS;
+    if (osGeometryProperties.size() != 0 && osGCoordSystemTable.size() != 0)
+    {
+        std::vector<CPLString> aosGUID;
+        {
+            CPLODBCStatement oStmt( &oSession );
+            oStmt.Appendf( "SELECT GCoordSystemGUID FROM %s", osGeometryProperties.c_str() );
+
+            if( !oStmt.ExecuteSQL() )
+            {
+                CPLDebug( "GEOMEDIA",
+                        "SELECT on %s fails, perhaps not a geomedia geodatabase?\n%s",
+                        osGeometryProperties.c_str(),
+                        oSession.GetLastError() );
+                return FALSE;
+            }
+
+            while( oStmt.Fetch() )
+            {
+                aosGUID.push_back(oStmt.GetColData(0));
+            }
+
+            if (apapszGeomColumns.size() != aosGUID.size())
+            {
+                CPLDebug( "GEOMEDIA", "%s and %s don't have the same size",
+                        osGFeaturesTable.c_str(), osGeometryProperties.c_str() );
+                return FALSE;
+            }
+        }
+
+        int i;
+        for(i=0; i<(int)aosGUID.size();i++)
+        {
+            apoSRS.push_back(GetGeomediaSRS(osGCoordSystemTable, aosGUID[i]));
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a layer for each spatial table.                          */
+/* -------------------------------------------------------------------- */
+    unsigned int iTable;
+
+    papoLayers = (OGRGeomediaLayer **) CPLCalloc(apapszGeomColumns.size(),
+                                             sizeof(void*));
+
+    for( iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
+    {
+        char **papszRecord = apapszGeomColumns[iTable];
+        OGRGeomediaTableLayer  *poLayer;
+
+        poLayer = new OGRGeomediaTableLayer( this );
+
+        if( poLayer->Initialize( papszRecord[0], papszRecord[1], (apoSRS.size()) ? apoSRS[iTable] : NULL )
+            != CE_None )
+        {
+            delete poLayer;
+        }
+        else
+        {
+            papoLayers[nLayers++] = poLayer;
+        }
+        CSLDestroy(papszRecord);
+    }
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                     GetTableNameFromType()                           */
+/************************************************************************/
+
+CPLString OGRGeomediaDataSource::GetTableNameFromType(const char* pszTableType)
+{
+    CPLODBCStatement oStmt( &oSession );
+
+    oStmt.Appendf( "SELECT TableName FROM GAliasTable WHERE TableType = '%s'", pszTableType );
+
+    if( !oStmt.ExecuteSQL() )
+    {
+        CPLDebug( "GEOMEDIA",
+                  "SELECT for %s on GAliasTable fails, perhaps not a geomedia geodatabase?\n%s",
+                  pszTableType,
+                  oSession.GetLastError() );
+        return "";
+    }
+
+    while( oStmt.Fetch() )
+    {
+        return oStmt.GetColData(0);
+    }
+
+    return "";
+}
+
+
+/************************************************************************/
+/*                          GetGeomediaSRS()                            */
+/************************************************************************/
+
+OGRSpatialReference* OGRGeomediaDataSource::GetGeomediaSRS(const char* pszGCoordSystemTable,
+                                                      const char* pszGCoordSystemGUID)
+{
+    if (pszGCoordSystemTable == NULL || pszGCoordSystemGUID == NULL)
+        return NULL;
+
+    OGRLayer* poGCoordSystemTable = GetLayerByName(pszGCoordSystemTable);
+    if (poGCoordSystemTable == NULL)
+        return NULL;
+
+    poGCoordSystemTable->ResetReading();
+
+    OGRFeature* poFeature;
+    while((poFeature = poGCoordSystemTable->GetNextFeature()) != NULL)
+    {
+        const char* pszCSGUID = poFeature->GetFieldAsString("CSGUID");
+        if (pszCSGUID && strcmp(pszCSGUID, pszGCoordSystemGUID) == 0)
+        {
+            OGRSpatialReference* poSRS = OGRGetGeomediaSRS(poFeature);
+            delete poFeature;
+            return poSRS;
+        }
+
+        delete poFeature;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGeomediaDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRGeomediaDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRGeomediaDataSource::GetLayerByName( const char* pszName )
+
+{
+    if (pszName == NULL)
+        return NULL;
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszName);
+    if (poLayer)
+        return poLayer;
+
+    for( int i = 0; i < nLayersWithInvisible; i++ )
+    {
+        poLayer = papoLayersInvisible[i];
+
+        if( strcmp( pszName, poLayer->GetName() ) == 0 )
+            return poLayer;
+    }
+
+    OGRGeomediaTableLayer  *poGeomediaLayer;
+
+    poGeomediaLayer = new OGRGeomediaTableLayer( this );
+
+    if( poGeomediaLayer->Initialize(pszName, NULL, NULL) != CE_None )
+    {
+        delete poGeomediaLayer;
+        return NULL;
+    }
+
+    papoLayersInvisible = (OGRGeomediaLayer**)CPLRealloc(papoLayersInvisible,
+                            (nLayersWithInvisible+1) * sizeof(OGRGeomediaLayer*));
+    papoLayersInvisible[nLayersWithInvisible++] = poGeomediaLayer;
+
+    return poGeomediaLayer;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRGeomediaDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                          OGRGeometry *poSpatialFilter,
+                                          const char *pszDialect )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Use generic imlplementation for OGRSQL dialect.                 */
+/* -------------------------------------------------------------------- */
+    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+        return OGRDataSource::ExecuteSQL( pszSQLCommand, 
+                                          poSpatialFilter, 
+                                          pszDialect );
+
+/* -------------------------------------------------------------------- */
+/*      Execute statement.                                              */
+/* -------------------------------------------------------------------- */
+    CPLODBCStatement *poStmt = new CPLODBCStatement( &oSession );
+
+    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.                                                      */
+/* -------------------------------------------------------------------- */
+    OGRGeomediaSelectLayer *poLayer = NULL;
+        
+    poLayer = new OGRGeomediaSelectLayer( this, poStmt );
+
+    if( poSpatialFilter != NULL )
+        poLayer->SetSpatialFilter( poSpatialFilter );
+    
+    return poLayer;
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRGeomediaDataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
new file mode 100644
index 0000000..73d5d3f
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
@@ -0,0 +1,287 @@
+/******************************************************************************
+ * $Id: ogrgeomediadriver.cpp 21545 2011-01-22 14:26:31Z 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) 2005, 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_geomedia.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrgeomediadriver.cpp 21545 2011-01-22 14:26:31Z rouault $");
+
+/************************************************************************/
+/*                          ~OGRODBCDriver()                            */
+/************************************************************************/
+
+OGRGeomediaDriver::~OGRGeomediaDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRGeomediaDriver::GetName()
+
+{
+    return "Geomedia";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRGeomediaDriver::Open( const char * pszFilename,
+                                    int bUpdate )
+
+{
+    OGRGeomediaDataSource     *poDS;
+
+    if( !EQUALN(pszFilename,"GEOMEDIA:",9) 
+        && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
+        return NULL;
+
+    if( !EQUALN(pszFilename,"GEOMEDIA:",9) &&
+        EQUAL(CPLGetExtension(pszFilename),"mdb") )
+    {
+        VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+        if (!fp)
+            return NULL;
+        GByte* pabyHeader = (GByte*) CPLMalloc(100000);
+        VSIFReadL(pabyHeader, 100000, 1, fp);
+        VSIFCloseL(fp);
+
+        /* Look for GAliasTable table */
+        const GByte pabyNeedle[] = { 'G', 0, 'A', 0, 'l', 0, 'i', 0, 'a', 0, 's', 0, 'T', 0, 'a', 0, 'b', 0, 'l', 0, 'e'};
+        int bFound = FALSE;
+        for(int i=0;i<100000 - (int)sizeof(pabyNeedle);i++)
+        {
+            if (memcmp(pabyHeader + i, pabyNeedle, sizeof(pabyNeedle)) == 0)
+            {
+                bFound = TRUE;
+                break;
+            }
+        }
+        CPLFree(pabyHeader);
+        if (!bFound)
+            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( "Geomedia", "MDB Tools driver installed successfully!");
+
+#endif /* ndef WIN32 */
+
+    // Open data source
+    poDS = new OGRGeomediaDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
+    {
+        delete poDS;
+        return NULL;
+    }
+    else
+        return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+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()                          */
+/************************************************************************/
+
+void RegisterOGRGeomedia()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRGeomediaDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
new file mode 100644
index 0000000..2db02f2
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
@@ -0,0 +1,360 @@
+/******************************************************************************
+ * $Id: ogrgeomedialayer.cpp 21547 2011-01-22 14:47:01Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRGeomediaLayer class, code shared between
+ *           the direct table access, and the generic SQL results.
+ * 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) 2005, 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 "cpl_conv.h"
+#include "ogr_geomedia.h"
+#include "cpl_string.h"
+#include "ogrgeomediageometry.h"
+
+CPL_CVSID("$Id: ogrgeomedialayer.cpp 21547 2011-01-22 14:47:01Z rouault $");
+
+/************************************************************************/
+/*                          OGRGeomediaLayer()                          */
+/************************************************************************/
+
+OGRGeomediaLayer::OGRGeomediaLayer()
+
+{
+    poDS = NULL;
+
+    pszGeomColumn = NULL;
+    pszFIDColumn = NULL;
+
+    poStmt = NULL;
+
+    iNextShapeId = 0;
+
+    poSRS = NULL;
+    nSRSId = -2; // we haven't even queried the database for it yet. 
+}
+
+/************************************************************************/
+/*                         ~OGRGeomediaLayer()                          */
+/************************************************************************/
+
+OGRGeomediaLayer::~OGRGeomediaLayer()
+
+{
+    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    {
+        CPLDebug( "Geomedia", "%d features read on layer '%s'.",
+                  (int) m_nFeaturesRead, 
+                  poFeatureDefn->GetName() );
+    }
+
+    if( poStmt != NULL )
+    {
+        delete poStmt;
+        poStmt = NULL;
+    }
+
+    if( poFeatureDefn != NULL )
+    {
+        poFeatureDefn->Release();
+        poFeatureDefn = NULL;
+    }
+
+    CPLFree( pszGeomColumn );
+    CPLFree( panFieldOrdinals ); 
+    CPLFree( pszFIDColumn );
+
+    if( poSRS != NULL )
+    {
+        poSRS->Release();
+        poSRS = NULL;
+    }
+}
+
+/************************************************************************/
+/*                          BuildFeatureDefn()                          */
+/*                                                                      */
+/*      Build feature definition from a set of column definitions       */
+/*      set on a statement.  Sift out geometry and FID fields.          */
+/************************************************************************/
+
+CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
+                                       CPLODBCStatement *poStmt )
+
+{
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    int    nRawColumns = poStmt->GetColCount();
+
+    poFeatureDefn->Reference();
+
+    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) )
+            continue;
+
+        if( pszGeomColumn == NULL 
+            && EQUAL(poStmt->GetColName(iCol),"Geometry")
+			&& (poStmt->GetColType(iCol) == SQL_BINARY ||
+			    poStmt->GetColType(iCol) == SQL_VARBINARY ||
+				poStmt->GetColType(iCol) == SQL_LONGVARBINARY) )
+        {
+            pszGeomColumn = CPLStrdup(poStmt->GetColName(iCol));
+            continue;
+        }
+        
+        switch( poStmt->GetColType(iCol) )
+        {
+          case SQL_INTEGER:
+          case SQL_SMALLINT:
+            oField.SetType( OFTInteger );
+            break;
+
+          case SQL_BINARY:
+          case SQL_VARBINARY:
+          case SQL_LONGVARBINARY:
+            oField.SetType( OFTBinary );
+            break;
+
+          case SQL_DECIMAL:
+            oField.SetType( OFTReal );
+            oField.SetPrecision( poStmt->GetColPrecision(iCol) );
+            break;
+
+          case SQL_FLOAT:
+          case SQL_REAL:
+          case SQL_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;
+    }
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRGeomediaLayer::ResetReading()
+
+{
+    iNextShapeId = 0;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRGeomediaLayer::GetNextFeature()
+
+{
+    for( ; 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;
+    }
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRGeomediaLayer::GetNextRawFeature()
+
+{
+    OGRErr err = OGRERR_NONE;
+
+    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 );
+        GByte *pabyShape = (GByte *) poStmt->GetColData( iField );
+        int nBytes = poStmt->GetColDataLength(iField);
+        OGRGeometry *poGeom = NULL;
+
+        if( pabyShape != NULL )
+        {
+            err = OGRCreateFromGeomedia( pabyShape, &poGeom, nBytes );
+            if( OGRERR_NONE != err )
+            {
+                CPLDebug( "Geomedia",
+                          "Translation geomedia binary to OGR geometry failed (FID=%ld)",
+                           (long)poFeature->GetFID() );
+            }
+        }
+
+        if( poGeom != NULL && OGRERR_NONE == err )
+        {
+            poGeom->assignSpatialReference( poSRS );
+            poFeature->SetGeometryDirectly( poGeom );
+        }
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRGeomediaLayer::GetFeature( long nFeatureId )
+
+{
+    /* This should be implemented directly! */
+
+    return OGRLayer::GetFeature( nFeatureId );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGeomediaLayer::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+
+OGRSpatialReference *OGRGeomediaLayer::GetSpatialRef()
+
+{
+    return poSRS;
+}
+
+/************************************************************************/
+/*                            GetFIDColumn()                            */
+/************************************************************************/
+
+const char *OGRGeomediaLayer::GetFIDColumn()
+
+{
+    if( pszFIDColumn != NULL )
+        return pszFIDColumn;
+    else
+        return "";
+}
+
+/************************************************************************/
+/*                         GetGeometryColumn()                          */
+/************************************************************************/
+
+const char *OGRGeomediaLayer::GetGeometryColumn()
+
+{
+    if( pszGeomColumn != NULL )
+        return pszGeomColumn;
+    else
+        return "";
+}
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
new file mode 100644
index 0000000..bc994d8
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
@@ -0,0 +1,165 @@
+/******************************************************************************
+ * $Id: ogrgeomediaselectlayer.cpp 21545 2011-01-22 14:26:31Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRGeomediaSelectLayer class, layer access to the results
+ *           of a SELECT statement executed via ExecuteSQL().
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2005, Frank Warmerdam
+ *
+ * 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_geomedia.h"
+
+CPL_CVSID("$Id: ogrgeomediaselectlayer.cpp 21545 2011-01-22 14:26:31Z rouault $");
+
+/************************************************************************/
+/*                        OGRGeomediaSelectLayer()                      */
+/************************************************************************/
+
+OGRGeomediaSelectLayer::OGRGeomediaSelectLayer( OGRGeomediaDataSource *poDSIn,
+                                        CPLODBCStatement * poStmtIn )
+
+{
+    poDS = poDSIn;
+
+    iNextShapeId = 0;
+    nSRSId = -1;
+    poFeatureDefn = NULL;
+
+    poStmt = poStmtIn;
+    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
+
+    BuildFeatureDefn( "SELECT", poStmt );
+}
+
+/************************************************************************/
+/*                        ~OGRGeomediaSelectLayer()                     */
+/************************************************************************/
+
+OGRGeomediaSelectLayer::~OGRGeomediaSelectLayer()
+
+{
+    ClearStatement();
+    CPLFree(pszBaseStatement);
+}
+
+/************************************************************************/
+/*                           ClearStatement()                           */
+/************************************************************************/
+
+void OGRGeomediaSelectLayer::ClearStatement()
+
+{
+    if( poStmt != NULL )
+    {
+        delete poStmt;
+        poStmt = NULL;
+    }
+}
+
+/************************************************************************/
+/*                            GetStatement()                            */
+/************************************************************************/
+
+CPLODBCStatement *OGRGeomediaSelectLayer::GetStatement()
+
+{
+    if( poStmt == NULL )
+        ResetStatement();
+
+    return poStmt;
+}
+
+/************************************************************************/
+/*                           ResetStatement()                           */
+/************************************************************************/
+
+OGRErr OGRGeomediaSelectLayer::ResetStatement()
+
+{
+    ClearStatement();
+
+    iNextShapeId = 0;
+
+    CPLDebug( "ODBC", "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 OGRGeomediaSelectLayer::ResetReading()
+
+{
+    if( iNextShapeId != 0 )
+        ClearStatement();
+
+    OGRGeomediaLayer::ResetReading();
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRGeomediaSelectLayer::GetFeature( long nFeatureId )
+
+{
+    return OGRGeomediaLayer::GetFeature( nFeatureId );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGeomediaSelectLayer::TestCapability( const char * pszCap )
+
+{
+    return OGRGeomediaLayer::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 OGRGeomediaSelectLayer::GetFeatureCount( int bForce )
+
+{
+    return OGRGeomediaLayer::GetFeatureCount( bForce );
+}
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
new file mode 100644
index 0000000..af604d7
--- /dev/null
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
@@ -0,0 +1,305 @@
+/******************************************************************************
+ * $Id: ogrgeomediatablelayer.cpp 21561 2011-01-23 12:22:58Z 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) 2005, 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 "cpl_conv.h"
+#include "ogr_geomedia.h"
+
+CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 21561 2011-01-23 12:22:58Z rouault $");
+
+/************************************************************************/
+/*                          OGRGeomediaTableLayer()                     */
+/************************************************************************/
+
+OGRGeomediaTableLayer::OGRGeomediaTableLayer( OGRGeomediaDataSource *poDSIn )
+
+{
+    poDS = poDSIn;
+    pszQuery = NULL;
+    bUpdateAccess = TRUE;
+    iNextShapeId = 0;
+    nSRSId = -1;
+    poFeatureDefn = NULL;
+}
+
+/************************************************************************/
+/*                       ~OGRGeomediaTableLayer()                       */
+/************************************************************************/
+
+OGRGeomediaTableLayer::~OGRGeomediaTableLayer()
+
+{
+    CPLFree( pszQuery );
+    ClearStatement();
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
+                                          const char *pszGeomCol,
+                                          OGRSpatialReference* poSRS )
+
+
+{
+    CPLODBCSession *poSession = poDS->GetSession();
+
+    CPLFree( pszGeomColumn );
+    if( pszGeomCol == NULL )
+        pszGeomColumn = NULL;
+    else
+        pszGeomColumn = CPLStrdup( pszGeomCol );
+
+    CPLFree( pszFIDColumn );
+    pszFIDColumn = NULL;
+
+    this->poSRS = poSRS;
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a simple primary key?                                */
+/* -------------------------------------------------------------------- */
+    {
+    CPLODBCStatement oGetKey( poSession );
+    
+    if( oGetKey.GetPrimaryKeys( pszTableName ) && oGetKey.Fetch() )
+    {
+        pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
+        
+        if( oGetKey.Fetch() ) // more than one field in key! 
+        {
+            CPLFree( pszFIDColumn );
+            pszFIDColumn = NULL;
+            CPLDebug( "Geomedia", "%s: Compound primary key, ignoring.",
+                      pszTableName );
+        }
+        else
+            CPLDebug( "Geomedia",
+                      "%s: Got primary key %s.",
+                      pszTableName, pszFIDColumn );
+    }
+    else
+        CPLDebug( "Geomedia", "%s: no primary key", pszTableName );
+    }
+/* -------------------------------------------------------------------- */
+/*      Get the column definitions for this table.                      */
+/* -------------------------------------------------------------------- */
+    CPLODBCStatement oGetCol( poSession );
+    CPLErr eErr;
+
+    if( !oGetCol.GetColumns( pszTableName ) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "GetColumns() failed on %s.\n%s",
+                  pszTableName, poSession->GetLastError() );
+        return CE_Failure;
+    }
+
+    eErr = BuildFeatureDefn( pszTableName, &oGetCol );
+    if( eErr != CE_None )
+        return eErr;
+
+    if( poFeatureDefn->GetFieldCount() == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "No column definitions found for table '%s', layer not usable.", 
+                  pszTableName );
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           ClearStatement()                           */
+/************************************************************************/
+
+void OGRGeomediaTableLayer::ClearStatement()
+
+{
+    if( poStmt != NULL )
+    {
+        delete poStmt;
+        poStmt = NULL;
+    }
+}
+
+/************************************************************************/
+/*                            GetStatement()                            */
+/************************************************************************/
+
+CPLODBCStatement *OGRGeomediaTableLayer::GetStatement()
+
+{
+    if( poStmt == NULL )
+        ResetStatement();
+
+    return poStmt;
+}
+
+/************************************************************************/
+/*                           ResetStatement()                           */
+/************************************************************************/
+
+OGRErr OGRGeomediaTableLayer::ResetStatement()
+
+{
+    ClearStatement();
+
+    iNextShapeId = 0;
+
+    poStmt = new CPLODBCStatement( poDS->GetSession() );
+    poStmt->Append( "SELECT * FROM " );
+    poStmt->Append( poFeatureDefn->GetName() );
+    if( pszQuery != NULL )
+        poStmt->Appendf( " WHERE %s", pszQuery );
+
+    if( poStmt->ExecuteSQL() )
+        return OGRERR_NONE;
+    else
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRGeomediaTableLayer::ResetReading()
+
+{
+    ClearStatement();
+    OGRGeomediaLayer::ResetReading();
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRGeomediaTableLayer::GetFeature( long nFeatureId )
+
+{
+    if( pszFIDColumn == NULL )
+        return OGRGeomediaLayer::GetFeature( nFeatureId );
+
+    ClearStatement();
+
+    iNextShapeId = nFeatureId;
+
+    poStmt = new CPLODBCStatement( poDS->GetSession() );
+    poStmt->Append( "SELECT * FROM " );
+    poStmt->Append( poFeatureDefn->GetName() );
+    poStmt->Appendf( " WHERE %s = %ld", pszFIDColumn, nFeatureId );
+
+    if( !poStmt->ExecuteSQL() )
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return NULL;
+    }
+
+    return GetNextRawFeature();
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRGeomediaTableLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    if( (pszQuery == NULL && this->pszQuery == NULL)
+        || (pszQuery != NULL && this->pszQuery != NULL 
+            && EQUAL(pszQuery,this->pszQuery)) )
+        return OGRERR_NONE;
+
+    CPLFree( this->pszQuery );
+    this->pszQuery = pszQuery ? CPLStrdup( pszQuery ) : NULL; 
+
+    ClearStatement();
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGeomediaTableLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCRandomRead) )
+        return TRUE;
+
+    else if( EQUAL(pszCap,OLCFastFeatureCount) )
+        return m_poFilterGeom == NULL;
+
+    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
+        return FALSE;
+
+    else 
+        return OGRGeomediaLayer::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 OGRGeomediaTableLayer::GetFeatureCount( int bForce )
+
+{
+    if( m_poFilterGeom != NULL )
+        return OGRGeomediaLayer::GetFeatureCount( bForce );
+
+    CPLODBCStatement oStmt( poDS->GetSession() );
+    oStmt.Append( "SELECT COUNT(*) FROM " );
+    oStmt.Append( poFeatureDefn->GetName() );
+
+    if( pszQuery != NULL )
+        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 OGRGeomediaLayer::GetFeatureCount(bForce);
+    }
+
+    return atoi(oStmt.GetColData(0));
+}
diff --git a/ogr/ogrsf_frmts/georss/drv_georss.html b/ogr/ogrsf_frmts/georss/drv_georss.html
index f46c7f5..cd9a56e 100644
--- a/ogr/ogrsf_frmts/georss/drv_georss.html
+++ b/ogr/ogrsf_frmts/georss/drv_georss.html
@@ -139,6 +139,14 @@ This can be done with a <a href="drv_vrt.html">OGR VRT</a> dataset, or by using
 
 </li>
 
+<h2>VSI Virtual File System API support</h2>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
 
 <h2>Example</h2>
 
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
index 5e93956..df7e9d3 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeorssdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrgeorssdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSDataSource class
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrgeorssdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrgeorssdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $");
 
 /************************************************************************/
 /*                          OGRGeoRSSDataSource()                          */
@@ -229,16 +229,8 @@ int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
     pszName = CPLStrdup( pszFilename );
 
 /* -------------------------------------------------------------------- */
-/*      Determine what sort of object this is.                          */
+/*      Try to open the file.                                           */
 /* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
-
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
-        return FALSE;
-    
-    if( VSI_ISDIR(sStatBuf.st_mode) )
-        return FALSE;
-
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
     if (fp == NULL)
         return FALSE;
@@ -346,6 +338,9 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
         return FALSE;
     }
 
+    if (strcmp(pszFilename, "/dev/stdout") == 0)
+        pszFilename = "/vsistdout/";
+
 /* -------------------------------------------------------------------- */
 /*     Do not override exiting file.                                    */
 /* -------------------------------------------------------------------- */
@@ -364,10 +359,7 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
     pszName = CPLStrdup( pszFilename );
 
-    if( EQUAL(pszFilename,"stdout") )
-        fpOutput = VSIFOpenL( "/vsistdout/", "w" );
-    else
-        fpOutput = VSIFOpenL( pszFilename, "w" );
+    fpOutput = VSIFOpenL( pszFilename, "w" );
     if( fpOutput == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed, 
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
index 9a53505..c64ae09 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeorsslayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrgeorsslayer.cpp 23001 2011-08-28 17:33:04Z rouault $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSLayer class.
@@ -33,7 +33,7 @@
 #include "ogr_api.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeorsslayer.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrgeorsslayer.cpp 23001 2011-08-28 17:33:04Z rouault $");
 
 static const char* apszAllowedATOMFieldNamesWithSubElements[] = { "author", "contributor", NULL };
 
@@ -341,8 +341,7 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
     if (bStopParsing) return;
 
     if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
-        (eFormat == GEORSS_RSS && currentDepth == 2 && strcmp(pszName, "item") == 0) ||
-        (eFormat == GEORSS_RSS_RDF && currentDepth == 1 && strcmp(pszName, "item") == 0))
+        ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && !bInFeature && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
     {
         featureDepth = currentDepth;
 
@@ -620,8 +619,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
     currentDepth--;
 
     if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
-        (eFormat == GEORSS_RSS && currentDepth == 2 && strcmp(pszName, "item") == 0) ||
-        (eFormat == GEORSS_RSS_RDF && currentDepth == 1 && strcmp(pszName, "item") == 0))
+        ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
     {
         bInFeature = FALSE;
         bInTagWithSubTag = FALSE;
@@ -1890,8 +1888,7 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
     nWithoutEventCounter = 0;
 
     if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
-        (eFormat == GEORSS_RSS && currentDepth == 2 && strcmp(pszName, "item") == 0) ||
-        (eFormat == GEORSS_RSS_RDF && currentDepth == 1 && strcmp(pszName, "item") == 0))
+        ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && !bInFeature && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
     {
         bInFeature = TRUE;
         featureDepth = currentDepth;
@@ -1932,6 +1929,12 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
             count ++;
             CPLFree(pszTagWithSubTag);
             pszTagWithSubTag = CPLStrdup(CPLSPrintf("%s%d", pszName, count));
+            if (pszTagWithSubTag[0] == 0)
+            {
+                XML_StopParser(oSchemaParser, XML_FALSE);
+                bStopParsing = TRUE;
+                break;
+            }
         }
         CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszTagWithSubTag));
 
@@ -2159,8 +2162,7 @@ void OGRGeoRSSLayer::endElementLoadSchemaCbk(const char *pszName)
         return;
 
     if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszName, "entry") == 0) ||
-        (eFormat == GEORSS_RSS && currentDepth == 2 && strcmp(pszName, "item") == 0)  ||
-        (eFormat == GEORSS_RSS_RDF && currentDepth == 1 && strcmp(pszName, "item") == 0))
+        ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && (currentDepth == 1 || currentDepth == 2) && strcmp(pszName, "item") == 0))
     {
         bInFeature = FALSE;
     }
diff --git a/ogr/ogrsf_frmts/gft/GNUmakefile b/ogr/ogrsf_frmts/gft/GNUmakefile
new file mode 100644
index 0000000..b50b429
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrgftdriver.o ogrgftdatasource.o ogrgftlayer.o ogrgfttablelayer.o ogrgftresultlayer.o
+
+CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_gft.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/gft/drv_gft.html b/ogr/ogrsf_frmts/gft/drv_gft.html
new file mode 100644
index 0000000..6ef9af3
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/drv_gft.html
@@ -0,0 +1,165 @@
+<html>
+<head>
+<title>GFT - Google Fusion Tables</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>GFT - Google Fusion Tables</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver can connect to the Google Fusion Tables service. GDAL/OGR must be built with Curl support in order to the
+GFT driver to be compiled.<p>
+
+The driver supports read and write operations.<p>
+
+<h2>Dataset name syntax</h2>
+
+The minimal syntax to open a GFT datasource is : <pre>GFT:</pre><p>
+
+Additionnal optional parameters can be specified after the ':' sign such as :<p>
+
+<ul>
+<li> <b>tables=table_id1[,table_id2]*</b>: A list of table IDs. This is necessary when you need to access to public tables for example.
+If you want the table ID of a public table, or any other table that is not owned by the authenticated user, you have to visit the table
+in the Google Fusion Tables website and note the number at the end of the URL.
+<li> <b>protocol=https</b>: To use HTTPS protocol for all operations. By default, HTTP is used, except for the authentication operation
+where HTTPS is always used.
+<li> <b>email=john.doe at example.com</b>: The email of the Google account used for authentication.
+<li> <b>password=your_secret_password</b>: The password of the Google account used for authentication.
+<li> <b>auth=auth_key</b>: An authentication key as described below.
+</ul>
+
+If several parameters are specified, they must be separated by a space.
+
+<h2>Authentication</h2>
+
+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>
+
+The authentication information can be provided by different means :
+<ul>
+<li>specifying the <i>email</i> and <i>password</i> parameters in the dataset name, as described above.</li>
+<li>specifying them through the <i>GFT_EMAIL</i> and <i>GFT_PASSWORD</i> configuration options/environment variables.</li>
+<li>specifying the authentication key through the <i>GFT_AUTH</i> configuration option/environment variable.
+This value is a key returned by the server when using the email + password method,
+and that can re-used for later authentication. You can fetch this key by running a first time ogrinfo with CPL_DEBUG set to ON
+and authenticating with another method. The value will be displayed after the "Auth key : " string.
+This method has the advantage of not exposing your plain password.</li>
+<li>specifying the authentication key through the <i>auth</i> connection parameter.</li>
+</ul>
+
+<h2>Geometry</h2>
+
+Geometries in GFT tables must be expressed in the geodetic WGS84 SRS. GFT allows them to be encoded in different forms :
+<ul>
+<li>A single column with a "lat lon" or "lat,lon" string, where lat et lon are expressed in decimal degrees.</li>
+<li>A single column with a KML string that is the representation of a Point, a LineString or a Polygon.</li>
+<li>Two columns, one with the latitude and the other one with the longitude, both values expressed in decimal degrees.</li>
+<li>A single column with an address known by the geocoding service of Google Maps.</li>
+</ul>
+
+Only the first 3 types are supported by OGR, not the last one.<p>
+
+Fusion tables can have multiple geometry columns per table. By default, OGR
+will use the first geometry column it finds. It is possible to select another
+column as the geometry column by specifying <i>table_name(geometry_column_name)</i>
+as the layer name passed to GetLayerByName().<p>
+
+<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 GFT_PAGE_SIZE
+configuration option.<p>
+
+<h2>Write support</h2>
+
+Table creation and deletion is possible. Note that fields can only be added to a table in which there are no features created yet.<p>
+
+Write support is only enabled when the datasource is opened in update mode.<p>
+
+The mapping between the operations of the GFT 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. OGR will also automatically reproject its geometry into the
+geodetic WGS84 SRS if needed (provided that the original SRS is attached to the geometry).<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() oepration between OGRLayer::StartTransaction() and OGRLayer::CommitTransaction().
+The operations will be stored into memory and only executed at the time CommitTransaction() is called. Note that
+the GFT service only supports up to 500 INSERTs and up to 1MB of content per transaction.<p>
+
+Note : only CreateFeature() makes use of OGR transaction mechanism. SetFeature() and DeleteFeature()
+will still be issued immediately.<p>
+
+<h2>SQL</h2>
+
+SQL commands provided to the OGRDataSource::ExecuteSQL() call are executed on the server side, unless the OGRSQL
+dialect is specified. The subset of SQL supported by the GFT service is described in the links at the end of this page.<p>
+
+The SQL supported by the server understands only natively table id, and not the table names returned by OGR.
+For conveniency, OGR will "patch" your SQL command to replace the table name by the table id however.<p>
+
+<h2>Examples</h2>
+
+<li>
+Listing the tables and views owned by the authenticated user:
+<pre>
+ogrinfo -ro "GFT:email=john.doe at example.com password=secret_password"
+</pre>
+<p>
+
+<li>
+Creating and populating a table from a shapefile:
+<pre>
+ogr2ogr -f GFT "GFT:email=john.doe at example.com password=secret_password" shapefile.shp
+</pre>
+<p>
+
+<li>
+Displaying the content of a public table with a spatial and attribue filters:
+<pre>
+ogrinfo -ro "GFT:tables=224453" -al -spat 67 31.5 67.5 32 -where "'Attack on' = 'ENEMY'"
+</pre>
+<p>
+
+<li>
+Getting the auth key:
+<pre>
+ogrinfo --config CPL_DEBUG ON "GFT:email=john.doe at example.com password=secret_password"
+</pre>
+
+returns:
+<pre>
+HTTP: Fetch(https://www.google.com/accounts/ClientLogin)
+HTTP: These HTTP headers were set: Content-Type: application/x-www-form-urlencoded
+GFT: Auth key : A_HUGE_STRING_WITH_ALPHANUMERIC_AND_SPECIAL_CHARACTERS
+</pre>
+
+Now, you can set the GFT_AUTH environment variable to that value and simply use "GFT:" as the DSN.
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="http://code.google.com/intl/fr/apis/fusiontables/docs/developers_guide.html">Google Fusion Tables Developer's Guide</a><p>
+<li> <a href="http://code.google.com/intl/fr/apis/fusiontables/docs/developers_reference.html">Google Fusion Tables Developer's Reference</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/gft/makefile.vc b/ogr/ogrsf_frmts/gft/makefile.vc
new file mode 100644
index 0000000..1a64429
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrgftdriver.obj ogrgftdatasource.obj ogrgftlayer.obj ogrgfttablelayer.obj ogrgftresultlayer.obj
+EXTRAFLAGS =	-I.. -I..\..
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/gft/ogr_gft.h b/ogr/ogrsf_frmts/gft/ogr_gft.h
new file mode 100644
index 0000000..3343b84
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/ogr_gft.h
@@ -0,0 +1,260 @@
+/******************************************************************************
+ * $Id: ogr_gft.h 22268 2011-04-30 13:10:40Z 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>
+ *
+ * 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_GFT_H_INCLUDED
+#define _OGR_GFT_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_http.h"
+
+#include <vector>
+
+/************************************************************************/
+/*                             OGRGFTLayer                              */
+/************************************************************************/
+class OGRGFTDataSource;
+
+class OGRGFTLayer : public OGRLayer
+{
+protected:
+    OGRGFTDataSource* poDS;
+
+    OGRFeatureDefn*    poFeatureDefn;
+    OGRSpatialReference *poSRS;
+
+    int                nNextInSeq;
+
+    int                iGeometryField;
+    int                iLatitudeField;
+    int                iLongitudeField;
+    int                bHiddenGeometryField;
+
+    OGRFeature *       GetNextRawFeature();
+
+    int                nOffset;
+    int                bEOF;
+    virtual int                FetchNextRows() = 0;
+
+    std::vector<CPLString> aosRows;
+
+    int                 bFirstTokenIsFID;
+    OGRFeature*         BuildFeatureFromSQL(const char* pszLine);
+
+    static CPLString    LaunderColName(const char* pszColName);
+
+  public:
+                         OGRGFTLayer(OGRGFTDataSource* poDS);
+                        ~OGRGFTLayer();
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+
+    virtual int                 TestCapability( const char * );
+
+    virtual OGRSpatialReference*GetSpatialRef();
+
+    virtual const char *        GetGeometryColumn();
+
+    virtual OGRErr              SetNextByIndex( long nIndex );
+
+    const char *        GetDefaultGeometryColumnName() { return "geometry"; }
+
+    static int                  ParseCSVResponse(char* pszLine,
+                                                 std::vector<CPLString>& aosRes);
+    static CPLString            PatchSQL(const char* pszSQL);
+
+    int                         GetGeometryFieldIndex() { return iGeometryField; }
+    int                         GetLatitudeFieldIndex() { return iLatitudeField; }
+    int                         GetLongitudeFieldIndex() { return iLongitudeField; }
+
+    int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("GFT_PAGE_SIZE", "500")); }
+};
+
+/************************************************************************/
+/*                         OGRGFTTableLayer                             */
+/************************************************************************/
+
+class OGRGFTTableLayer : public OGRGFTLayer
+{
+    CPLString         osTableName;
+    CPLString         osTableId;
+    CPLString         osGeomColumnName;
+
+    int                bHasTriedCreateTable;
+    void               CreateTableIfNecessary();
+
+    CPLString           osWHERE;
+    CPLString           osQuery;
+
+    void                BuildWhere(void);
+
+    CPLString          osTransaction;
+    int                bInTransaction;
+    int                nFeaturesInTransaction;
+
+    int                FetchDescribe();
+    virtual int                FetchNextRows();
+
+    OGRwkbGeometryType eGTypeForCreation;
+
+    std::vector<CPLString>  aosColumnInternalName;
+
+    public:
+            OGRGFTTableLayer(OGRGFTDataSource* poDS,
+                             const char* pszTableName,
+                             const char* pszTableId = "",
+                             const char* pszGeomColumnName = "");
+            ~OGRGFTTableLayer();
+
+    virtual void                ResetReading();
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+
+    virtual const char *        GetName() { return osTableName.c_str(); }
+    virtual int         GetFeatureCount( int bForce = TRUE );
+
+    virtual OGRFeature *        GetFeature( long nFID );
+
+    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual OGRErr      SetAttributeFilter( 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 OGRErr      StartTransaction();
+    virtual OGRErr      CommitTransaction();
+    virtual OGRErr      RollbackTransaction();
+
+    const CPLString&            GetTableId() const { return osTableId; }
+
+    virtual int                 TestCapability( const char * );
+
+    void                SetGeometryType(OGRwkbGeometryType eGType);
+};
+
+/************************************************************************/
+/*                        OGRGFTResultLayer                             */
+/************************************************************************/
+
+class OGRGFTResultLayer : public OGRGFTLayer
+{
+    CPLString   osSQL;
+    int         bGotAllRows;
+
+    virtual int                FetchNextRows();
+
+    public:
+            OGRGFTResultLayer(OGRGFTDataSource* poDS,
+                              const char* pszSQL);
+            ~OGRGFTResultLayer();
+
+    virtual void                ResetReading();
+
+    int     RunSQL();
+};
+
+/************************************************************************/
+/*                           OGRGFTDataSource                           */
+/************************************************************************/
+
+class OGRGFTDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+    int                 bReadWrite;
+
+    int                 bUseHTTPS;
+    CPLString           osAuth;
+    int                 FetchAuth(const char* pszEmail, const char* pszPassword);
+
+    void                DeleteLayer( const char *pszLayerName );
+
+    int                 bMustCleanPersistant;
+
+  public:
+                        OGRGFTDataSource();
+                        ~OGRGFTDataSource();
+
+    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 CPLString&            GetAuth() const { return osAuth; }
+    const char*                 GetAPIURL() const;
+    int                         IsReadWrite() const { return bReadWrite; }
+    char**                      AddHTTPOptions(char** papszOptions = NULL);
+    CPLHTTPResult*              RunSQL(const char* pszUnescapedSQL);
+};
+
+/************************************************************************/
+/*                             OGRGFTDriver                             */
+/************************************************************************/
+
+class OGRGFTDriver : public OGRSFDriver
+{
+  public:
+                ~OGRGFTDriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual OGRDataSource*      CreateDataSource( const char * pszName,
+                                                  char **papszOptions );
+    virtual int                 TestCapability( const char * );
+};
+
+char **OGRGFTCSVSplitLine( const char *pszString, char chDelimiter );
+char* OGRGFTGotoNextLine(char* pszData);
+
+#endif /* ndef _OGR_GFT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
new file mode 100644
index 0000000..d948c49
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
@@ -0,0 +1,602 @@
+/******************************************************************************
+ * $Id: ogrgftdatasource.cpp 22871 2011-08-06 20:29:35Z rouault $
+ *
+ * Project:  GFT 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>
+ *
+ * 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_gft.h"
+
+CPL_CVSID("$Id: ogrgftdatasource.cpp 22871 2011-08-06 20:29:35Z rouault $");
+
+/************************************************************************/
+/*                          OGRGFTDataSource()                          */
+/************************************************************************/
+
+OGRGFTDataSource::OGRGFTDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+
+    bReadWrite = FALSE;
+    bUseHTTPS = FALSE;
+
+    bMustCleanPersistant = FALSE;
+}
+
+/************************************************************************/
+/*                         ~OGRGFTDataSource()                          */
+/************************************************************************/
+
+OGRGFTDataSource::~OGRGFTDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    if (bMustCleanPersistant)
+    {
+        char** papszOptions = CSLAddString(NULL, CPLSPrintf("CLOSE_PERSISTENT=GFT:%p", this));
+        CPLHTTPFetch( GetAPIURL(), papszOptions);
+        CSLDestroy(papszOptions);
+    }
+
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGFTDataSource::TestCapability( const char * pszCap )
+
+{
+    if( bReadWrite && EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+    else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRGFTDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRGFTDataSource::GetLayerByName(const char * pszLayerName)
+{
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszLayerName);
+    if (poLayer)
+        return poLayer;
+        
+    char* pszGeomColumnName = NULL;
+    char* pszName = CPLStrdup(pszLayerName);
+    char *pszLeftParenthesis = strchr(pszName, '(');
+    if( pszLeftParenthesis != NULL )
+    {
+        *pszLeftParenthesis = '\0';
+        pszGeomColumnName = CPLStrdup(pszLeftParenthesis+1);
+        int len = strlen(pszGeomColumnName);
+        if (len > 0 && pszGeomColumnName[len - 1] == ')')
+            pszGeomColumnName[len - 1] = '\0';
+    }
+    
+    CPLString osTableId(pszName);
+    for(int i=0;i<nLayers;i++)
+    {
+        if( strcmp(papoLayers[i]->GetName(), pszName) == 0)
+        {
+            osTableId = ((OGRGFTTableLayer*)papoLayers[i])->GetTableId();
+            break;
+        }
+    }
+
+    poLayer = new OGRGFTTableLayer(this, pszLayerName, osTableId,
+                                   pszGeomColumnName);
+    CPLFree(pszName);
+    CPLFree(pszGeomColumnName);
+    if (poLayer->GetLayerDefn()->GetFieldCount() == 0)
+    {
+        delete poLayer;
+        return NULL;
+    }
+    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+    return poLayer;
+}
+
+/************************************************************************/
+/*                             FetchAuth()                              */
+/************************************************************************/
+
+int OGRGFTDataSource::FetchAuth(const char* pszEmail, const char* pszPassword)
+{
+
+    char** papszOptions = NULL;
+
+    const char* pszAuthURL = CPLGetConfigOption("GFT_AUTH_URL", NULL);
+    if (pszAuthURL == NULL)
+        pszAuthURL = "https://www.google.com/accounts/ClientLogin";
+
+    papszOptions = CSLAddString(papszOptions, "HEADERS=Content-Type: application/x-www-form-urlencoded");
+    papszOptions = CSLAddString(papszOptions, CPLSPrintf("POSTFIELDS=Email=%s&Passwd=%s&service=fusiontables", pszEmail, pszPassword));
+    CPLHTTPResult * psResult = CPLHTTPFetch( pszAuthURL, papszOptions);
+    CSLDestroy(papszOptions);
+    papszOptions = NULL;
+
+    if (psResult == NULL)
+        return FALSE;
+
+    const char* pszAuth = NULL;
+    if (psResult->pabyData == NULL ||
+        psResult->pszErrBuf != NULL ||
+        (pszAuth = strstr((const char*)psResult->pabyData, "Auth=")) == NULL)
+    {
+        CPLHTTPDestroyResult(psResult);
+        return FALSE;
+    }
+    osAuth = pszAuth + 5;
+    pszAuth = NULL;
+
+    while(osAuth.size() &&
+          (osAuth[osAuth.size()-1] == 13 || osAuth[osAuth.size()-1] == 10))
+        osAuth.resize(osAuth.size()-1);
+
+    CPLDebug("GFT", "Auth key : %s", osAuth.c_str());
+
+    CPLHTTPDestroyResult(psResult);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                      OGRGFTGetOptionValue()                          */
+/************************************************************************/
+
+CPLString OGRGFTGetOptionValue(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 OGRGFTDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (!EQUALN(pszFilename, "GFT:", 4))
+        return FALSE;
+
+    bReadWrite = bUpdateIn;
+
+    pszName = CPLStrdup( pszFilename );
+
+    const char* pszEmail = CPLGetConfigOption("GFT_EMAIL", NULL);
+    CPLString osEmail = OGRGFTGetOptionValue(pszFilename, "email");
+    if (osEmail.size() != 0)
+        pszEmail = osEmail.c_str();
+
+    const char* pszPassword = CPLGetConfigOption("GFT_PASSWORD", NULL);
+    CPLString osPassword = OGRGFTGetOptionValue(pszFilename, "password");
+    if (osPassword.size() != 0)
+        pszPassword = osPassword.c_str();
+
+    const char* pszAuth = CPLGetConfigOption("GFT_AUTH", NULL);
+    osAuth = OGRGFTGetOptionValue(pszFilename, "auth");
+    if (osAuth.size() == 0 && pszAuth != NULL)
+        osAuth = pszAuth;
+
+    CPLString osTables = OGRGFTGetOptionValue(pszFilename, "tables");
+
+    bUseHTTPS = strstr(pszFilename, "protocol=https") != NULL;
+
+    if (osAuth.size() == 0 && (pszEmail == NULL || pszPassword == NULL))
+    {
+        if (osTables.size() == 0)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Unauthenticated access requires explicit tables= parameter");
+            return FALSE;
+        }
+    }
+    else if (osAuth.size() == 0 && !FetchAuth(pszEmail, pszPassword))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Authentication failed");
+        return FALSE;
+    }
+
+    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 OGRGFTTableLayer(this, papszTables[i], papszTables[i]);
+        }
+        CSLDestroy(papszTables);
+        return TRUE;
+    }
+
+    /* Get list of tables */
+    CPLHTTPResult * psResult = RunSQL("SHOW TABLES");
+
+    if (psResult == NULL)
+        return FALSE;
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        psResult->pszErrBuf != NULL ||
+        strncmp(pszLine, "table id,name", strlen("table id,name")) != 0)
+    {
+        CPLHTTPDestroyResult(psResult);
+        return FALSE;
+    }
+
+    pszLine = OGRGFTGotoNextLine(pszLine);
+    while(pszLine != NULL && *pszLine != 0)
+    {
+        char* pszNextLine = OGRGFTGotoNextLine(pszLine);
+        if (pszNextLine)
+            pszNextLine[-1] = 0;
+
+        char** papszTokens = CSLTokenizeString2(pszLine, ",", 0);
+        if (CSLCount(papszTokens) == 2)
+        {
+            CPLString osTableId(papszTokens[0]);
+            CPLString osLayerName(papszTokens[1]);
+            for(int i=0;i<nLayers;i++)
+            {
+                if (strcmp(papoLayers[i]->GetName(), osLayerName) == 0)
+                {
+                    osLayerName += " (";
+                    osLayerName += osTableId;
+                    osLayerName += ")";
+                    break;
+                }
+            }
+            papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+            papoLayers[nLayers ++] = new OGRGFTTableLayer(this, osLayerName, osTableId);
+        }
+        CSLDestroy(papszTokens);
+
+        pszLine = pszNextLine;
+    }
+
+    CPLHTTPDestroyResult(psResult);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            GetAPIURL()                               */
+/************************************************************************/
+
+const char*  OGRGFTDataSource::GetAPIURL() const
+{
+    const char* pszAPIURL = CPLGetConfigOption("GFT_API_URL", NULL);
+    if (pszAPIURL)
+        return pszAPIURL;
+    else if (bUseHTTPS)
+        return "https://www.google.com/fusiontables/api/query";
+    else
+        return "http://www.google.com/fusiontables/api/query";
+}
+
+/************************************************************************/
+/*                           CreateLayer()                              */
+/************************************************************************/
+
+OGRLayer   *OGRGFTDataSource::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 (osAuth.size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in unauthenticated 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( pszName );
+                break;
+            }
+            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;
+            }
+        }
+    }
+
+    OGRGFTTableLayer* poLayer = new OGRGFTTableLayer(this, pszName);
+    poLayer->SetGeometryType(eGType);
+    papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+    return poLayer;
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+void OGRGFTDataSource::DeleteLayer( const char *pszLayerName )
+
+{
+    int iLayer;
+
+/* -------------------------------------------------------------------- */
+/*      Try to find layer.                                              */
+/* -------------------------------------------------------------------- */
+    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    {
+        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
+            break;
+    }
+
+    if( iLayer == nLayers )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to delete layer '%s', but this layer is not known to OGR.",
+                  pszLayerName );
+        return;
+    }
+
+    DeleteLayer(iLayer);
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr OGRGFTDataSource::DeleteLayer(int iLayer)
+{
+    if (!bReadWrite)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (osAuth.size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in unauthenticated 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;
+    }
+
+    CPLString osTableId = ((OGRGFTTableLayer*)papoLayers[iLayer])->GetTableId();
+    CPLString osLayerName = GetLayer(iLayer)->GetName();
+
+/* -------------------------------------------------------------------- */
+/*      Blow away our OGR structures related to the layer.  This is     */
+/*      pretty dangerous if anything has a reference to this layer!     */
+/* -------------------------------------------------------------------- */
+    CPLDebug( "GFT", "DeleteLayer(%s)", osLayerName.c_str() );
+
+    delete papoLayers[iLayer];
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
+             sizeof(void *) * (nLayers - iLayer - 1) );
+    nLayers--;
+
+/* -------------------------------------------------------------------- */
+/*      Remove from the database.                                       */
+/* -------------------------------------------------------------------- */
+
+    CPLString osSQL("DROP TABLE ");
+    osSQL += osTableId;
+
+    CPLHTTPResult* psResult = RunSQL( osSQL );
+
+    if (psResult == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Table deletion failed");
+        return OGRERR_FAILURE;
+    }
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        !EQUALN(pszLine, "OK", 2) ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Table deletion failed");
+        CPLHTTPDestroyResult(psResult);
+        return OGRERR_FAILURE;
+    }
+
+    CPLHTTPDestroyResult(psResult);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          AddHTTPOptions()                            */
+/************************************************************************/
+
+char** OGRGFTDataSource::AddHTTPOptions(char** papszOptions)
+{
+    bMustCleanPersistant = TRUE;
+    papszOptions = CSLAddString(papszOptions,
+        CPLSPrintf("HEADERS=Authorization: GoogleLogin auth=%s", osAuth.c_str()));
+    return CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=GFT:%p", this));
+}
+
+/************************************************************************/
+/*                               RunSQL()                               */
+/************************************************************************/
+
+CPLHTTPResult * OGRGFTDataSource::RunSQL(const char* pszUnescapedSQL)
+{
+    CPLString osSQL("POSTFIELDS=sql=");
+    /* 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);
+    }
+    char** papszOptions = CSLAddString(AddHTTPOptions(), osSQL);
+    CPLDebug("GFT", "Run %s", pszUnescapedSQL);
+    CPLHTTPResult * psResult = CPLHTTPFetch( GetAPIURL(), papszOptions);
+    CSLDestroy(papszOptions);
+    if (psResult && psResult->pszContentType &&
+        strncmp(psResult->pszContentType, "text/html", 9) == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "HTML error page returned by server");
+        CPLHTTPDestroyResult(psResult);
+        psResult = NULL;
+    }
+    return psResult;
+}
+
+/************************************************************************/
+/*                             ExecuteSQL()                             */
+/************************************************************************/
+
+OGRLayer * OGRGFTDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                          OGRGeometry *poSpatialFilter,
+                                          const char *pszDialect )
+
+{
+    if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
+                                          pszDialect );
+
+/* -------------------------------------------------------------------- */
+/*      Special case DELLAYER: command.                                 */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
+    {
+        const char *pszLayerName = pszSQLCommand + 9;
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        DeleteLayer( pszLayerName );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create layer.                                                   */
+/* -------------------------------------------------------------------- */
+    OGRGFTResultLayer *poLayer = NULL;
+
+    CPLString osSQL = pszSQLCommand;
+    poLayer = new OGRGFTResultLayer( this, osSQL );
+    if (!poLayer->RunSQL())
+    {
+        delete poLayer;
+        return NULL;
+    }
+
+    if( poSpatialFilter != NULL )
+        poLayer->SetSpatialFilter( poSpatialFilter );
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                          ReleaseResultSet()                          */
+/************************************************************************/
+
+void OGRGFTDataSource::ReleaseResultSet( OGRLayer * poLayer )
+
+{
+    delete poLayer;
+}
+
+/************************************************************************/
+/*                      OGRGFTGotoNextLine()                            */
+/************************************************************************/
+
+char* OGRGFTGotoNextLine(char* pszData)
+{
+    char* pszNextLine = strchr(pszData, '\n');
+    if (pszNextLine)
+        return pszNextLine + 1;
+    return NULL;
+}
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
new file mode 100644
index 0000000..10b7d33
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
@@ -0,0 +1,119 @@
+/******************************************************************************
+ * $Id: ogrgftdriver.cpp 22070 2011-03-29 21:56:51Z 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>
+ *
+ * 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_gft.h"
+
+// g++ -g -Wall -fPIC -shared -o ogr_GFT.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gft ogr/ogrsf_frmts/gft/*.c* -L. -lgdal
+
+/* 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 $");
+
+extern "C" void RegisterOGRGFT();
+
+/************************************************************************/
+/*                           ~OGRGFTDriver()                            */
+/************************************************************************/
+
+OGRGFTDriver::~OGRGFTDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRGFTDriver::GetName()
+
+{
+    return "GFT";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRGFTDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRGFTDataSource   *poDS = new OGRGFTDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+
+/************************************************************************/
+/*                          CreateDataSource()                          */
+/************************************************************************/
+
+OGRDataSource *OGRGFTDriver::CreateDataSource( const char * pszName,
+                                               char **papszOptions )
+
+{
+    OGRGFTDataSource   *poDS = new OGRGFTDataSource();
+
+    if( !poDS->Open( pszName, TRUE ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGFTDriver::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap, ODrCCreateDataSource))
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRGFT()                           */
+/************************************************************************/
+
+void RegisterOGRGFT()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRGFTDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
new file mode 100644
index 0000000..73d4026
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
@@ -0,0 +1,680 @@
+/******************************************************************************
+ * $Id: ogrgftlayer.cpp 22268 2011-04-30 13:10:40Z 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>
+ *
+ * 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_gft.h"
+#include "cpl_minixml.h"
+
+CPL_CVSID("$Id: ogrgftlayer.cpp 22268 2011-04-30 13:10:40Z rouault $");
+
+/************************************************************************/
+/*                            OGRGFTLayer()                             */
+/************************************************************************/
+
+OGRGFTLayer::OGRGFTLayer(OGRGFTDataSource* poDS)
+
+{
+    this->poDS = poDS;
+
+    nNextInSeq = 0;
+
+    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+
+    poFeatureDefn = NULL;
+
+    nOffset = 0;
+    bEOF = FALSE;
+
+    iLatitudeField = iLongitudeField = -1;
+    iGeometryField = -1;
+    bHiddenGeometryField = FALSE;
+
+    bFirstTokenIsFID = FALSE;
+}
+
+/************************************************************************/
+/*                            ~OGRGFTLayer()                            */
+/************************************************************************/
+
+OGRGFTLayer::~OGRGFTLayer()
+
+{
+    if( poSRS != NULL )
+        poSRS->Release();
+
+    if( poFeatureDefn != NULL )
+        poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRGFTLayer::ResetReading()
+
+{
+    nNextInSeq = 0;
+    nOffset = 0;
+    bEOF = FALSE;
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRGFTLayer::GetLayerDefn()
+{
+    CPLAssert(poFeatureDefn);
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRGFTLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    GetLayerDefn();
+
+    while(TRUE)
+    {
+        if (nNextInSeq < nOffset ||
+            nNextInSeq >= nOffset + (int)aosRows.size())
+        {
+            if (bEOF)
+                return NULL;
+
+            nOffset += aosRows.size();
+            if (!FetchNextRows())
+                return NULL;
+        }
+
+        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;
+    }
+}
+
+/************************************************************************/
+/*                            CSVSplitLine()                            */
+/*                                                                      */
+/*      Tokenize a CSV line into fields in the form of a string         */
+/*      list.  This is used instead of the CPLTokenizeString()          */
+/*      because it provides correct CSV escaping and quoting            */
+/*      semantics.                                                      */
+/************************************************************************/
+
+char **OGRGFTCSVSplitLine( const char *pszString, char chDelimiter )
+
+{
+    char        **papszRetList = NULL;
+    char        *pszToken;
+    int         nTokenMax, nTokenLen;
+
+    pszToken = (char *) CPLCalloc(10,1);
+    nTokenMax = 10;
+
+    while( pszString != NULL && *pszString != '\0' )
+    {
+        int     bInString = FALSE;
+
+        nTokenLen = 0;
+
+        /* Try to find the next delimeter, marking end of token */
+        for( ; *pszString != '\0'; pszString++ )
+        {
+
+            /* End if this is a delimeter skip it and break. */
+            if( !bInString && *pszString == chDelimiter )
+            {
+                pszString++;
+                break;
+            }
+
+            if( *pszString == '"' )
+            {
+                if( !bInString || pszString[1] != '"' )
+                {
+                    bInString = !bInString;
+                    continue;
+                }
+                else  /* doubled quotes in string resolve to one quote */
+                {
+                    pszString++;
+                }
+            }
+
+            if( nTokenLen >= nTokenMax-2 )
+            {
+                nTokenMax = nTokenMax * 2 + 10;
+                pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
+            }
+
+            pszToken[nTokenLen] = *pszString;
+            nTokenLen++;
+        }
+
+        pszToken[nTokenLen] = '\0';
+        papszRetList = CSLAddString( papszRetList, pszToken );
+
+        /* If the last token is an empty token, then we have to catch
+         * it now, otherwise we won't reenter the loop and it will be lost.
+         */
+        if ( *pszString == '\0' && *(pszString-1) == chDelimiter )
+        {
+            papszRetList = CSLAddString( papszRetList, "" );
+        }
+    }
+
+    if( papszRetList == NULL )
+        papszRetList = (char **) CPLCalloc(sizeof(char *),1);
+
+    CPLFree( pszToken );
+
+    return papszRetList;
+}
+/************************************************************************/
+/*                           ParseKMLGeometry()                         */
+/************************************************************************/
+
+static void ParseLineString(OGRLineString* poLS,
+                            const char* pszCoordinates)
+{
+    char** papszTuples = CSLTokenizeString2(pszCoordinates, " ", 0);
+    for(int iTuple = 0; papszTuples && papszTuples[iTuple]; iTuple++)
+    {
+        char** papszTokens = CSLTokenizeString2(papszTuples[iTuple], ",", 0);
+        if (CSLCount(papszTokens) == 2)
+            poLS->addPoint(atof(papszTokens[0]), atof(papszTokens[1]));
+        else if (CSLCount(papszTokens) == 3)
+            poLS->addPoint(atof(papszTokens[0]), atof(papszTokens[1]),
+                            atof(papszTokens[2]));
+        CSLDestroy(papszTokens);
+    }
+    CSLDestroy(papszTuples);
+}
+
+/* Could be moved somewhere else */
+
+static OGRGeometry* ParseKMLGeometry(/* const */ CPLXMLNode* psXML)
+{
+    OGRGeometry* poGeom = NULL;
+    const char* pszGeomType = psXML->pszValue;
+    if (strcmp(pszGeomType, "Point") == 0)
+    {
+        const char* pszCoordinates = CPLGetXMLValue(psXML, "coordinates", NULL);
+        if (pszCoordinates)
+        {
+            char** papszTokens = CSLTokenizeString2(pszCoordinates, ",", 0);
+            if (CSLCount(papszTokens) == 2)
+                poGeom = new OGRPoint(atof(papszTokens[0]), atof(papszTokens[1]));
+            else if (CSLCount(papszTokens) == 3)
+                poGeom = new OGRPoint(atof(papszTokens[0]), atof(papszTokens[1]),
+                                      atof(papszTokens[2]));
+            CSLDestroy(papszTokens);
+        }
+    }
+    else if (strcmp(pszGeomType, "LineString") == 0)
+    {
+        const char* pszCoordinates = CPLGetXMLValue(psXML, "coordinates", NULL);
+        if (pszCoordinates)
+        {
+            OGRLineString* poLS = new OGRLineString();
+            ParseLineString(poLS, pszCoordinates);
+            poGeom = poLS;
+        }
+    }
+    else if (strcmp(pszGeomType, "Polygon") == 0)
+    {
+        OGRPolygon* poPoly = NULL;
+        CPLXMLNode* psOuterBoundary = CPLGetXMLNode(psXML, "outerBoundaryIs");
+        if (psOuterBoundary)
+        {
+            CPLXMLNode* psLinearRing = CPLGetXMLNode(psOuterBoundary, "LinearRing");
+            const char* pszCoordinates = CPLGetXMLValue(
+                psLinearRing ? psLinearRing : psOuterBoundary, "coordinates", NULL);
+            if (pszCoordinates)
+            {
+                OGRLinearRing* poLS = new OGRLinearRing();
+                ParseLineString(poLS, pszCoordinates);
+                poPoly = new OGRPolygon();
+                poPoly->addRingDirectly(poLS);
+                poGeom = poPoly;
+            }
+
+            if (poPoly)
+            {
+                CPLXMLNode* psIter = psXML->psChild;
+                while(psIter)
+                {
+                    if (psIter->eType == CXT_Element &&
+                        strcmp(psIter->pszValue, "innerBoundaryIs") == 0)
+                    {
+                        CPLXMLNode* psLinearRing = CPLGetXMLNode(psIter, "LinearRing");
+                        const char* pszCoordinates = CPLGetXMLValue(
+                            psLinearRing ? psLinearRing : psIter, "coordinates", NULL);
+                        if (pszCoordinates)
+                        {
+                            OGRLinearRing* poLS = new OGRLinearRing();
+                            ParseLineString(poLS, pszCoordinates);
+                            poPoly->addRingDirectly(poLS);
+                        }
+                    }
+                    psIter = psIter->psNext;
+                }
+            }
+        }
+    }
+    else if (strcmp(pszGeomType, "MultiGeometry") == 0)
+    {
+        CPLXMLNode* psIter;
+        OGRwkbGeometryType eType = wkbUnknown;
+        for(psIter = psXML->psChild; psIter; psIter = psIter->psNext)
+        {
+            if (psIter->eType == CXT_Element)
+            {
+                OGRwkbGeometryType eNewType = wkbUnknown;
+                if (strcmp(psIter->pszValue, "Point") == 0)
+                {
+                    eNewType = wkbPoint;
+                }
+                else if (strcmp(psIter->pszValue, "LineString") == 0)
+                {
+                    eNewType = wkbLineString;
+                }
+                else if (strcmp(psIter->pszValue, "Polygon") == 0)
+                {
+                    eNewType = wkbPolygon;
+                }
+                else
+                    break;
+                if (eType == wkbUnknown)
+                    eType = eNewType;
+                else if (eType != eNewType)
+                    break;
+            }
+        }
+        OGRGeometryCollection* poColl = NULL;
+        if (psIter != NULL)
+            poColl = new OGRGeometryCollection();
+        else if (eType == wkbPoint)
+            poColl = new OGRMultiPoint();
+        else if (eType == wkbLineString)
+            poColl = new OGRMultiLineString();
+        else if (eType == wkbPolygon)
+            poColl = new OGRMultiPolygon();
+        else
+            CPLAssert(0);
+
+        psIter = psXML->psChild;
+        for(psIter = psXML->psChild; psIter; psIter = psIter->psNext)
+        {
+            if (psIter->eType == CXT_Element)
+            {
+                OGRGeometry* poSubGeom = ParseKMLGeometry(psIter);
+                if (poSubGeom)
+                    poColl->addGeometryDirectly(poSubGeom);
+            }
+        }
+
+        poGeom = poColl;
+    }
+
+    return poGeom;
+}
+
+static OGRGeometry* ParseKMLGeometry(const char* pszKML)
+{
+    CPLXMLNode* psXML = CPLParseXMLString(pszKML);
+    if (psXML == NULL)
+        return NULL;
+
+    if (psXML->eType != CXT_Element)
+    {
+        CPLDestroyXMLNode(psXML);
+        return NULL;
+    }
+
+    OGRGeometry* poGeom = ParseKMLGeometry(psXML);
+
+    CPLDestroyXMLNode(psXML);
+    return poGeom;
+}
+
+
+/************************************************************************/
+/*                         BuildFeatureFromSQL()                        */
+/************************************************************************/
+
+OGRFeature *OGRGFTLayer::BuildFeatureFromSQL(const char* pszLine)
+{
+    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+
+    char** papszTokens = OGRGFTCSVSplitLine(pszLine, ',');
+    int nTokens = CSLCount(papszTokens);
+    CPLString osFID;
+
+    int nAttrOffset = 0;
+    int iROWID = -1;
+    if (bFirstTokenIsFID)
+    {
+        osFID = papszTokens[0];
+        nAttrOffset = 1;
+    }
+    else
+    {
+        iROWID = poFeatureDefn->GetFieldIndex("rowid");
+        if (iROWID < 0)
+            iROWID = poFeatureDefn->GetFieldIndex("ROWID");
+    }
+
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+    if (nTokens == nFieldCount + bHiddenGeometryField + nAttrOffset)
+    {
+        for(int i=0;i<nFieldCount+bHiddenGeometryField;i++)
+        {
+            const char* pszVal = papszTokens[i+nAttrOffset];
+            if (pszVal[0])
+            {
+                if (i<nFieldCount)
+                    poFeature->SetField(i, pszVal);
+
+                if (i == iGeometryField && i != iLatitudeField)
+                {
+                    if (pszVal[0] == '-' || (pszVal[0] >= '0' && pszVal[0] <= '9'))
+                    {
+                        char** papszLatLon = CSLTokenizeString2(pszVal, " ,", 0);
+                        if (CSLCount(papszLatLon) == 2 &&
+                            CPLGetValueType(papszLatLon[0]) != CPL_VALUE_STRING &&
+                            CPLGetValueType(papszLatLon[1]) != CPL_VALUE_STRING)
+                        {
+                            OGRPoint* poPoint = new OGRPoint(atof( papszLatLon[1]),
+                                                            atof( papszLatLon[0]));
+                            poPoint->assignSpatialReference(poSRS);
+                            poFeature->SetGeometryDirectly(poPoint);
+                        }
+                        CSLDestroy(papszLatLon);
+                    }
+                    else if (strstr(pszVal, "<Point>") ||
+                             strstr(pszVal, "<LineString>") ||
+                             strstr(pszVal, "<Polygon>"))
+                    {
+                        OGRGeometry* poGeom = ParseKMLGeometry(pszVal);
+                        if (poGeom)
+                        {
+                            poGeom->assignSpatialReference(poSRS);
+                            poFeature->SetGeometryDirectly(poGeom);
+                        }
+                    }
+                }
+                else if (i == iROWID)
+                {
+                    osFID = pszVal;
+                }
+            }
+        }
+
+        if (iLatitudeField >= 0 && iLongitudeField >= 0)
+        {
+            const char* pszLat = papszTokens[iLatitudeField+nAttrOffset];
+            const char* pszLong = papszTokens[iLongitudeField+nAttrOffset];
+            if (pszLat[0] != 0 && pszLong[0] != 0 &&
+                CPLGetValueType(pszLat) != CPL_VALUE_STRING &&
+                CPLGetValueType(pszLong) != CPL_VALUE_STRING)
+            {
+                OGRPoint* poPoint = new OGRPoint(atof(pszLong), atof(pszLat));
+                poPoint->assignSpatialReference(poSRS);
+                poFeature->SetGeometryDirectly(poPoint);
+            }
+        }
+    }
+    else
+    {
+        CPLDebug("GFT", "Only %d columns for feature %s", nTokens, osFID.c_str());
+    }
+    CSLDestroy(papszTokens);
+
+    int nFID = atoi(osFID);
+    if (strcmp(CPLSPrintf("%d", nFID), osFID.c_str()) == 0)
+        poFeature->SetFID(nFID);
+    else
+        poFeature->SetFID(nNextInSeq);
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRGFTLayer::GetNextRawFeature()
+{
+    if (nNextInSeq < nOffset ||
+        nNextInSeq - nOffset >= (int)aosRows.size())
+        return NULL;
+
+    OGRFeature* poFeature = BuildFeatureFromSQL(aosRows[nNextInSeq - nOffset]);
+
+    nNextInSeq ++;
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                          SetNextByIndex()                            */
+/************************************************************************/
+
+OGRErr OGRGFTLayer::SetNextByIndex( long nIndex )
+{
+    if (nIndex < 0)
+        return OGRERR_FAILURE;
+    bEOF = FALSE;
+    nNextInSeq = nIndex;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGFTLayer::TestCapability( const char * pszCap )
+
+{
+    if ( EQUAL(pszCap, OLCStringsAsUTF8) )
+        return TRUE;
+    else if ( EQUAL(pszCap, OLCFastSetNextByIndex) )
+        return TRUE;
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         GetGeometryColumn()                          */
+/************************************************************************/
+
+const char *OGRGFTLayer::GetGeometryColumn()
+{
+    GetLayerDefn();
+    if (iGeometryField < 0)
+        return "";
+
+    if (iGeometryField == poFeatureDefn->GetFieldCount())
+    {
+        CPLAssert(bHiddenGeometryField);
+        return GetDefaultGeometryColumnName();
+    }
+
+    return poFeatureDefn->GetFieldDefn(iGeometryField)->GetNameRef();
+}
+
+/************************************************************************/
+/*                         ParseCSVResponse()                           */
+/************************************************************************/
+
+int OGRGFTLayer::ParseCSVResponse(char* pszLine,
+                                  std::vector<CPLString>& aosRes)
+{
+    while(pszLine != NULL && *pszLine != 0)
+    {
+        char* pszNextLine = OGRGFTGotoNextLine(pszLine);
+        if (pszNextLine)
+            pszNextLine[-1] = 0;
+
+        int nDoubleQuotes = 0;
+        char* pszIter = pszLine;
+        while(*pszIter)
+        {
+            if (*pszIter == '"')
+            {
+                if (pszIter[1] != '"')
+                    nDoubleQuotes ++;
+                else
+                    pszIter ++;
+            }
+            pszIter ++;
+        }
+
+        if ((nDoubleQuotes % 2) == 0)
+            aosRes.push_back(pszLine);
+        else
+        {
+            CPLString osLine(pszLine);
+
+            pszLine = pszNextLine;
+            while(pszLine != NULL && *pszLine != 0)
+            {
+                pszNextLine = OGRGFTGotoNextLine(pszLine);
+                if (pszNextLine)
+                    pszNextLine[-1] = 0;
+
+                osLine += "\n";
+                osLine += pszLine;
+
+                pszIter = pszLine;
+                while(*pszIter)
+                {
+                    if (*pszIter == '"')
+                    {
+                        if (pszIter[1] != '"')
+                            nDoubleQuotes ++;
+                        else
+                            pszIter ++;
+                    }
+                    pszIter ++;
+                }
+
+                if ((nDoubleQuotes % 2) == 0)
+                {
+                    break;
+                }
+
+                pszLine = pszNextLine;
+            }
+
+            aosRes.push_back(osLine);
+        }
+
+        pszLine = pszNextLine;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              PatchSQL()                              */
+/************************************************************************/
+
+CPLString OGRGFTLayer::PatchSQL(const char* pszSQL)
+{
+    CPLString osSQL;
+
+    while(*pszSQL)
+    {
+        if (EQUALN(pszSQL, "COUNT(", 5) && strchr(pszSQL, ')'))
+        {
+            const char* pszNext = strchr(pszSQL, ')');
+            osSQL += "COUNT()";
+            pszSQL = pszNext + 1;
+        }
+        else if ((*pszSQL == '<' && pszSQL[1] == '>') ||
+                 (*pszSQL == '!' && pszSQL[1] == '='))
+        {
+            osSQL += " NOT EQUAL TO ";
+            pszSQL += 2;
+        }
+        else
+        {
+            osSQL += *pszSQL;
+            pszSQL ++;
+        }
+    }
+    return osSQL;
+}
+
+/************************************************************************/
+/*                          GetSpatialRef()                             */
+/************************************************************************/
+
+OGRSpatialReference* OGRGFTLayer::GetSpatialRef()
+{
+    GetLayerDefn();
+
+    if (iGeometryField < 0)
+        return NULL;
+
+    return poSRS;
+}
+
+/************************************************************************/
+/*                         LaunderColName()                             */
+/************************************************************************/
+
+CPLString OGRGFTLayer::LaunderColName(const char* pszColName)
+{
+    CPLString osLaunderedColName;
+
+    for(int i=0;pszColName[i];i++)
+    {
+        if (pszColName[i] == '\n')
+            osLaunderedColName += "\\n";
+        else
+            osLaunderedColName += pszColName[i];
+    }
+    return osLaunderedColName;
+}
diff --git a/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
new file mode 100644
index 0000000..da9ef48
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
@@ -0,0 +1,298 @@
+/******************************************************************************
+ * $Id: ogrgftresultlayer.cpp 22115 2011-04-03 22:27:42Z 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>
+ *
+ * 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_gft.h"
+
+CPL_CVSID("$Id: ogrgftresultlayer.cpp 22115 2011-04-03 22:27:42Z rouault $");
+
+/************************************************************************/
+/*                        OGRGFTResultLayer()                           */
+/************************************************************************/
+
+OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDS,
+                                     const char* pszSQL) : OGRGFTLayer(poDS)
+
+{
+    osSQL = PatchSQL(pszSQL);
+
+    bGotAllRows = FALSE;
+
+    poFeatureDefn = new OGRFeatureDefn( "result" );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbUnknown );
+}
+
+/************************************************************************/
+/*                       ~OGRGFTResultLayer()                           */
+/************************************************************************/
+
+OGRGFTResultLayer::~OGRGFTResultLayer()
+
+{
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRGFTResultLayer::ResetReading()
+
+{
+    nNextInSeq = 0;
+    nOffset = 0;
+    if (!bGotAllRows)
+    {
+        aosRows.resize(0);
+        bEOF = FALSE;
+    }
+}
+
+/************************************************************************/
+/*                           FetchNextRows()                            */
+/************************************************************************/
+
+int OGRGFTResultLayer::FetchNextRows()
+{
+    if (!((EQUALN(osSQL.c_str(), "SELECT", 6) ||
+           EQUALN(osSQL.c_str(), "select", 6))))
+        return FALSE;
+
+    aosRows.resize(0);
+
+    CPLString osChangedSQL(osSQL);
+    if (strstr(osSQL.c_str(), " OFFSET ") == NULL &&
+        strstr(osSQL.c_str(), " offset ") == NULL &&
+        strstr(osSQL.c_str(), " LIMIT ") == NULL &&
+        strstr(osSQL.c_str(), " limit ") == NULL )
+    {
+        osChangedSQL += CPLSPrintf(" OFFSET %d LIMIT %d",
+                                   nOffset, GetFeaturesToFetch());
+    }
+
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);
+    CPLPopErrorHandler();
+
+    if (psResult == NULL)
+    {
+        bEOF = TRUE;
+        return FALSE;
+    }
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
+        CPLHTTPDestroyResult(psResult);
+        bEOF = TRUE;
+        return FALSE;
+    }
+
+    pszLine = OGRGFTGotoNextLine(pszLine);
+    if (pszLine == NULL)
+    {
+        CPLHTTPDestroyResult(psResult);
+        bEOF = TRUE;
+        return FALSE;
+    }
+
+    ParseCSVResponse(pszLine, aosRows);
+
+    CPLHTTPDestroyResult(psResult);
+
+    bEOF = (int)aosRows.size() < GetFeaturesToFetch();
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         OGRGFTExtractTableID()                        */
+/************************************************************************/
+
+static CPLString OGRGFTExtractTableID(const char* pszTableID,
+                                      CPLString& osReminder)
+{
+    CPLString osTableId(pszTableID);
+    if (osTableId.size() > 1 &&
+        (osTableId[0] == '"' || osTableId[0] == '\''))
+    {
+        char chFirstChar = osTableId[0];
+        osTableId.erase(0, 1);
+        for(int i=0;i<(int)osTableId.size();i++)
+        {
+            if (osTableId[i] == chFirstChar)
+            {
+                osReminder = osTableId.substr(i+1);
+                osTableId.resize(i);
+                break;
+            }
+        }
+    }
+    else
+    {
+        for(int i=0;i<(int)osTableId.size();i++)
+        {
+            if (osTableId[i] == ' ')
+            {
+                osReminder = osTableId.substr(i);
+                osTableId.resize(i);
+                break;
+            }
+        }
+    }
+    return osTableId;
+}
+
+/************************************************************************/
+/*                               RunSQL()                               */
+/************************************************************************/
+
+int OGRGFTResultLayer::RunSQL()
+{
+    CPLString osChangedSQL(osSQL);
+    int bHasSetLimit = FALSE;
+    OGRGFTTableLayer* poTableLayer = NULL;
+    OGRFeatureDefn* poTableDefn = NULL;
+    CPLString osTableId;
+    if (EQUALN(osSQL.c_str(), "SELECT", 6))
+    {
+        const char* pszFROM = strstr(osSQL.c_str(), " FROM ");
+        if (pszFROM == NULL)
+            pszFROM = strstr(osSQL.c_str(), " from ");
+        if (pszFROM == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed. Missing FROM in SELECT");
+            return FALSE;
+        }
+        CPLString osReminder;
+        int nPosFROM = pszFROM - osSQL.c_str() + 6;
+        osTableId = OGRGFTExtractTableID(pszFROM + 6, osReminder);
+        pszFROM = NULL;
+
+        poTableLayer = (OGRGFTTableLayer*) poDS->GetLayerByName(osTableId);
+        if (poTableLayer != NULL)
+            poTableDefn = poTableLayer->GetLayerDefn();
+
+        if (poTableLayer != NULL &&
+            poTableLayer->GetTableId().size() &&
+            !EQUAL(osTableId, poTableLayer->GetTableId()))
+        {
+            osChangedSQL = osSQL;
+            osChangedSQL.resize(nPosFROM);
+            osChangedSQL += poTableLayer->GetTableId();
+            osChangedSQL += osReminder;
+            osSQL = osChangedSQL;
+            CPLDebug("GFT", "Patching table name (%s) to table id (%s)",
+                     osTableId.c_str(), poTableLayer->GetTableId().c_str());
+        }
+
+        int nFeaturesToFetch = GetFeaturesToFetch();
+        if (strstr(osSQL.c_str(), " OFFSET ") == NULL &&
+            strstr(osSQL.c_str(), " offset ") == NULL &&
+            strstr(osSQL.c_str(), " LIMIT ") == NULL &&
+            strstr(osSQL.c_str(), " limit ") == NULL &&
+            nFeaturesToFetch > 0)
+        {
+            osChangedSQL += CPLSPrintf(" LIMIT %d", nFeaturesToFetch);
+            bHasSetLimit = TRUE;
+        }
+    }
+    else
+    {
+        bGotAllRows = bEOF = TRUE;
+        poFeatureDefn->SetGeomType( wkbNone );
+    }
+
+    CPLHTTPResult * psResult = poDS->RunSQL(osChangedSQL);
+
+    if (psResult == NULL)
+        return FALSE;
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "RunSQL() failed");
+        CPLHTTPDestroyResult(psResult);
+        return FALSE;
+    }
+
+    if (EQUALN(osSQL.c_str(), "SELECT", 6) ||
+        EQUAL(osSQL.c_str(), "SHOW TABLES") ||
+        EQUALN(osSQL.c_str(), "DESCRIBE", 8))
+    {
+        ParseCSVResponse(pszLine, aosRows);
+        if (aosRows.size() > 0)
+        {
+            char** papszTokens = OGRGFTCSVSplitLine(aosRows[0], ',');
+            for(int i=0;papszTokens && papszTokens[i];i++)
+            {
+                CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
+                int iIndex = (poTableDefn) ? poTableDefn->GetFieldIndex(osLaunderedColName) : -1;
+                if (iIndex >= 0)
+                {
+                    poFeatureDefn->AddFieldDefn(poTableDefn->GetFieldDefn(iIndex));
+                    if (iIndex == poTableLayer->GetGeometryFieldIndex())
+                        iGeometryField = i;
+                    if (iIndex == poTableLayer->GetLatitudeFieldIndex())
+                        iLatitudeField = i;
+                    if (iIndex == poTableLayer->GetLongitudeFieldIndex())
+                        iLongitudeField = i;
+                }
+                else
+                {
+                    OGRFieldType eType = OFTString;
+                    if (EQUAL(osLaunderedColName, "COUNT()"))
+                        eType = OFTInteger;
+                    OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
+                    poFeatureDefn->AddFieldDefn(&oFieldDefn);
+                }
+            }
+            CSLDestroy(papszTokens);
+
+            aosRows.erase(aosRows.begin());
+        }
+
+        if (iLatitudeField >= 0 && iLongitudeField >= 0)
+        {
+            iGeometryField = iLatitudeField;
+            poFeatureDefn->SetGeomType( wkbPoint );
+        }
+
+        if (bHasSetLimit)
+            bGotAllRows = bEOF = (int)aosRows.size() < GetFeaturesToFetch();
+        else
+            bGotAllRows = bEOF = TRUE;
+    }
+
+    CPLHTTPDestroyResult(psResult);
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
new file mode 100644
index 0000000..b2af07f
--- /dev/null
+++ b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
@@ -0,0 +1,1307 @@
+/******************************************************************************
+ * $Id: ogrgfttablelayer.cpp 22407 2011-05-20 19:31:11Z 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>
+ *
+ * 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_gft.h"
+
+CPL_CVSID("$Id: ogrgfttablelayer.cpp 22407 2011-05-20 19:31:11Z rouault $");
+
+/************************************************************************/
+/*                         OGRGFTTableLayer()                           */
+/************************************************************************/
+
+OGRGFTTableLayer::OGRGFTTableLayer(OGRGFTDataSource* poDS,
+                         const char* pszTableName,
+                         const char* pszTableId,
+                         const char* pszGeomColumnName) : OGRGFTLayer(poDS)
+
+{
+    osTableName = pszTableName;
+    osTableId = pszTableId;
+    osGeomColumnName = pszGeomColumnName ? pszGeomColumnName : "";
+
+    bHasTriedCreateTable = FALSE;
+    bInTransaction = FALSE;
+    nFeaturesInTransaction = 0;
+
+    bFirstTokenIsFID = TRUE;
+    eGTypeForCreation = wkbUnknown;
+}
+
+/************************************************************************/
+/*                        ~OGRGFTTableLayer()                           */
+/************************************************************************/
+
+OGRGFTTableLayer::~OGRGFTTableLayer()
+
+{
+    CreateTableIfNecessary();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRGFTTableLayer::ResetReading()
+
+{
+    OGRGFTLayer::ResetReading();
+    aosRows.resize(0);
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGFTTableLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCRandomRead) )
+        return TRUE;
+
+    else if( EQUAL(pszCap,OLCSequentialWrite)
+             || EQUAL(pszCap,OLCRandomWrite)
+             || EQUAL(pszCap,OLCDeleteFeature) )
+        return poDS->IsReadWrite();
+
+    else if( EQUAL(pszCap,OLCCreateField) )
+        return poDS->IsReadWrite();
+
+    else if( EQUAL(pszCap, OLCTransactions) )
+        return poDS->IsReadWrite();
+
+    return OGRGFTLayer::TestCapability(pszCap);
+}
+
+/************************************************************************/
+/*                           FetchDescribe()                            */
+/************************************************************************/
+
+int OGRGFTTableLayer::FetchDescribe()
+{
+    poFeatureDefn = new OGRFeatureDefn( osTableName );
+    poFeatureDefn->Reference();
+
+    const CPLString& osAuth = poDS->GetAuth();
+    std::vector<CPLString> aosHeaderAndFirstDataLine;
+    if (osAuth.size())
+    {
+        CPLString osSQL("DESCRIBE ");
+        osSQL += osTableId;
+        CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
+
+        if (psResult == NULL)
+            return FALSE;
+
+        char* pszLine = (char*) psResult->pabyData;
+        if (pszLine == NULL ||
+            psResult->pszErrBuf != NULL ||
+            strncmp(pszLine, "column id,name,type",
+                    strlen("column id,name,type")) != 0)
+        {
+            CPLHTTPDestroyResult(psResult);
+            return FALSE;
+        }
+
+        pszLine = OGRGFTGotoNextLine(pszLine);
+
+        std::vector<CPLString> aosLines;
+        ParseCSVResponse(pszLine, aosLines);
+        for(int i=0;i<(int)aosLines.size();i++)
+        {
+            char** papszTokens = OGRGFTCSVSplitLine(aosLines[i], ',');
+            if (CSLCount(papszTokens) == 3)
+            {
+                aosColumnInternalName.push_back(papszTokens[0]);
+
+                //CPLDebug("GFT", "%s %s %s", papszTokens[0], papszTokens[1], papszTokens[2]);
+                OGRFieldType eType = OFTString;
+                if (EQUAL(papszTokens[2], "number"))
+                    eType = OFTReal;
+                else if (EQUAL(papszTokens[2], "datetime"))
+                    eType = OFTDateTime;
+
+                if (EQUAL(papszTokens[2], "location") && osGeomColumnName.size() == 0)
+                {
+                    if (iGeometryField < 0)
+                        iGeometryField = poFeatureDefn->GetFieldCount();
+                    else
+                        CPLDebug("GFT", "Multiple geometry fields detected. "
+                                         "Only first encountered one is handled");
+                }
+
+                CPLString osLaunderedColName(LaunderColName(papszTokens[1]));
+                OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
+                poFeatureDefn->AddFieldDefn(&oFieldDefn);
+            }
+            CSLDestroy(papszTokens);
+        }
+
+        CPLHTTPDestroyResult(psResult);
+    }
+    else
+    {
+        /* http://code.google.com/intl/fr/apis/fusiontables/docs/developers_guide.html#Exploring states */
+        /* that DESCRIBE should work on public tables without authentication, but it is not true... */
+        CPLString osSQL("SELECT * FROM ");
+        osSQL += osTableId;
+        osSQL += " OFFSET 0 LIMIT 1";
+
+        CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
+
+        if (psResult == NULL)
+            return FALSE;
+
+        char* pszLine = (char*) psResult->pabyData;
+        if (pszLine == NULL || psResult->pszErrBuf != NULL)
+        {
+            CPLHTTPDestroyResult(psResult);
+            return FALSE;
+        }
+
+        ParseCSVResponse(pszLine, aosHeaderAndFirstDataLine);
+        if (aosHeaderAndFirstDataLine.size() > 0)
+        {
+            char** papszTokens = OGRGFTCSVSplitLine(aosHeaderAndFirstDataLine[0], ',');
+            for(int i=0;papszTokens && papszTokens[i];i++)
+            {
+                CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
+                OGRFieldDefn oFieldDefn(osLaunderedColName, OFTString);
+                poFeatureDefn->AddFieldDefn(&oFieldDefn);
+            }
+            CSLDestroy(papszTokens);
+        }
+
+        CPLHTTPDestroyResult(psResult);
+    }
+    
+    if (osGeomColumnName.size() > 0)
+    {
+        iGeometryField = poFeatureDefn->GetFieldIndex(osGeomColumnName);
+        if (iGeometryField < 0)
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Cannot find column called %s", osGeomColumnName.c_str());
+        }
+    }
+
+    for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
+    {
+        const char* pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        if (EQUAL(pszName, "latitude") || EQUAL(pszName, "lat") ||
+            EQUAL(pszName, "latdec"))
+            iLatitudeField = i;
+        else if (EQUAL(pszName, "longitude") || EQUAL(pszName, "lon") ||
+                 EQUAL(pszName, "londec") || EQUAL(pszName, "long"))
+            iLongitudeField = i;
+    }
+
+    if (iLatitudeField >= 0 && iLongitudeField >= 0)
+    {
+        if (iGeometryField < 0)
+            iGeometryField = iLatitudeField;
+        poFeatureDefn->GetFieldDefn(iLatitudeField)->SetType(OFTReal);
+        poFeatureDefn->GetFieldDefn(iLongitudeField)->SetType(OFTReal);
+        poFeatureDefn->SetGeomType( wkbPoint );
+    }
+    else if (iGeometryField < 0 && osGeomColumnName.size() == 0)
+    {
+        iLatitudeField = iLongitudeField = -1;
+
+        /* In the unauthentified case, we try to parse the first record to */
+        /* autodetect the geometry field */
+        OGRwkbGeometryType eType = wkbUnknown;
+        if (aosHeaderAndFirstDataLine.size() == 2)
+        {
+            char** papszTokens = OGRGFTCSVSplitLine(aosHeaderAndFirstDataLine[1], ',');
+            if (CSLCount(papszTokens) == poFeatureDefn->GetFieldCount())
+            {
+                for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
+                {
+                    const char* pszVal = papszTokens[i];
+                    if (pszVal != NULL &&
+                        (strncmp(pszVal, "<Point>", 7) == 0 ||
+                         strncmp(pszVal, "<LineString>", 12) == 0 ||
+                         strncmp(pszVal, "<Polygon>", 9) == 0 ||
+                         strncmp(pszVal, "<MultiGeometry>", 15) == 0))
+                    {
+                        if (iGeometryField < 0)
+                        {
+                            iGeometryField = i;
+                        }
+                        else
+                        {
+                            CPLDebug("GFT", "Multiple geometry fields detected. "
+                                     "Only first encountered one is handled");
+                        }
+                    }
+                    else if (pszVal)
+                    {
+                        /* http://www.google.com/fusiontables/DataSource?dsrcid=423292 */
+                        char** papszTokens2 = CSLTokenizeString2(pszVal, " ,", 0);
+                        if (CSLCount(papszTokens2) == 2 &&
+                            CPLGetValueType(papszTokens2[0]) == CPL_VALUE_REAL &&
+                            CPLGetValueType(papszTokens2[1]) == CPL_VALUE_REAL &&
+                            fabs(CPLAtof(papszTokens2[0])) <= 90 &&
+                            fabs(CPLAtof(papszTokens2[1])) <= 180 )
+                        {
+                            if (iGeometryField < 0)
+                            {
+                                iGeometryField = i;
+                                eType = wkbPoint;
+                            }
+                            else
+                            {
+                                CPLDebug("GFT", "Multiple geometry fields detected. "
+                                         "Only first encountered one is handled");
+                            }
+                        }
+                        CSLDestroy(papszTokens2);
+                    }
+                }
+            }
+            CSLDestroy(papszTokens);
+        }
+        
+        if (iGeometryField < 0)
+            poFeatureDefn->SetGeomType( wkbNone );
+        else
+            poFeatureDefn->SetGeomType( eType );
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         EscapeAndQuote()                             */
+/************************************************************************/
+
+static CPLString EscapeAndQuote(const char* pszStr)
+{
+    char ch;
+    CPLString osRes("'");
+    while((ch = *pszStr) != 0)
+    {
+        if (ch == '\'')
+            osRes += "\\\'";
+        else
+            osRes += ch;
+        pszStr ++;
+    }
+    osRes += "'";
+    return osRes;
+}
+
+/************************************************************************/
+/*                           FetchNextRows()                            */
+/************************************************************************/
+
+int OGRGFTTableLayer::FetchNextRows()
+{
+    aosRows.resize(0);
+
+    CPLString osSQL("SELECT ROWID");
+    for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
+    {
+        osSQL += ",";
+
+        if (i < (int)aosColumnInternalName.size())
+            osSQL += aosColumnInternalName[i];
+        else
+        {
+            const char* pszFieldName =
+                poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+            osSQL += EscapeAndQuote(pszFieldName);
+        }
+    }
+    if (bHiddenGeometryField)
+    {
+        osSQL += ",";
+        osSQL += EscapeAndQuote(GetGeometryColumn());
+    }
+    osSQL += " FROM ";
+    osSQL += osTableId;
+    if (osWHERE.size())
+    {
+        osSQL += " ";
+        osSQL += osWHERE;
+    }
+
+    int nFeaturesToFetch = GetFeaturesToFetch();
+    if (nFeaturesToFetch > 0)
+        osSQL += CPLSPrintf(" OFFSET %d LIMIT %d", nOffset, nFeaturesToFetch);
+
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
+    CPLPopErrorHandler();
+
+    if (psResult == NULL)
+    {
+        bEOF = TRUE;
+        return FALSE;
+    }
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL || psResult->pszErrBuf != NULL)
+    {
+        CPLDebug("GFT", "Error : %s", pszLine ? pszLine : psResult->pszErrBuf);
+        CPLHTTPDestroyResult(psResult);
+        bEOF = TRUE;
+        return FALSE;
+    }
+
+    ParseCSVResponse(pszLine, aosRows);
+
+    if (aosRows.size() > 0)
+        aosRows.erase(aosRows.begin());
+
+    if (nFeaturesToFetch > 0)
+        bEOF = (int)aosRows.size() < GetFeaturesToFetch();
+    else
+        bEOF = TRUE;
+
+    CPLHTTPDestroyResult(psResult);
+
+    return TRUE;
+}
+/************************************************************************/
+/*                            GetFeature()                              */
+/************************************************************************/
+
+OGRFeature * OGRGFTTableLayer::GetFeature( long nFID )
+{
+    GetLayerDefn();
+
+    CPLString osSQL("SELECT ROWID");
+    for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
+    {
+        osSQL += ",";
+
+        const char* pszFieldName =
+            poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        osSQL += EscapeAndQuote(pszFieldName);
+    }
+    if (bHiddenGeometryField)
+    {
+        osSQL += ",";
+        osSQL += EscapeAndQuote(GetGeometryColumn());
+    }
+    osSQL += " FROM ";
+    osSQL += osTableId;
+    osSQL += CPLSPrintf(" WHERE ROWID='%ld'", nFID);
+
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
+    CPLPopErrorHandler();
+
+    if (psResult == NULL)
+        return NULL;
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL || psResult->pszErrBuf != NULL)
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    /* skip header line */
+    pszLine = OGRGFTGotoNextLine(pszLine);
+    if (pszLine == NULL || pszLine[0] == 0)
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    int nLen = (int)strlen(pszLine);
+    if (nLen > 0 && pszLine[nLen-1] == '\n')
+        pszLine[nLen-1] = '\0';
+
+    OGRFeature* poFeature = BuildFeatureFromSQL(pszLine);
+
+    CPLHTTPDestroyResult(psResult);
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           GetLayerDefn()                             */
+/************************************************************************/
+
+OGRFeatureDefn * OGRGFTTableLayer::GetLayerDefn()
+{
+    if (poFeatureDefn == NULL)
+    {
+        if (osTableId.size() == 0)
+            return NULL;
+        FetchDescribe();
+    }
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRGFTTableLayer::GetFeatureCount(int bForce)
+{
+    GetLayerDefn();
+
+    CPLString osSQL("SELECT COUNT() FROM ");
+    osSQL += osTableId;
+    if (osWHERE.size())
+    {
+        osSQL += " ";
+        osSQL += osWHERE;
+    }
+
+    CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
+
+    if (psResult == NULL)
+        return 0;
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        strncmp(pszLine, "count()", 7) != 0 ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GetFeatureCount() failed");
+        CPLHTTPDestroyResult(psResult);
+        return 0;
+    }
+
+    pszLine = OGRGFTGotoNextLine(pszLine);
+    if (pszLine == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GetFeatureCount() failed");
+        CPLHTTPDestroyResult(psResult);
+        return 0;
+    }
+
+    char* pszNextLine = OGRGFTGotoNextLine(pszLine);
+    if (pszNextLine)
+        pszNextLine[-1] = 0;
+
+    int nFeatureCount = atoi(pszLine);
+
+    CPLHTTPDestroyResult(psResult);
+
+    return nFeatureCount;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRGFTTableLayer::CreateField( OGRFieldDefn *poField,
+                                 int bApproxOK )
+{
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (osTableId.size() != 0)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Cannot add field to already created table");
+        return OGRERR_FAILURE;
+    }
+
+    if (poDS->GetAuth().size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in unauthenticated mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeatureDefn == NULL)
+    {
+        poFeatureDefn = new OGRFeatureDefn( osTableName );
+        poFeatureDefn->Reference();
+    }
+
+    poFeatureDefn->AddFieldDefn(poField);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                       CreateTableIfNecessary()                       */
+/************************************************************************/
+
+void OGRGFTTableLayer::CreateTableIfNecessary()
+{
+    if (bHasTriedCreateTable || osTableId.size() != 0)
+        return;
+
+    bHasTriedCreateTable = TRUE;
+
+    CPLString osSQL("CREATE TABLE '");
+    osSQL += osTableName;
+    osSQL += "' (";
+
+    int i;
+
+    if (poFeatureDefn == NULL)
+    {
+        /* In case CreateField() hasn't yet been called */
+        poFeatureDefn = new OGRFeatureDefn( osTableName );
+        poFeatureDefn->Reference();
+    }
+
+    /* If there are longitude and latitude fields, use the latitude */
+    /* field as the LOCATION field */
+    for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+    {
+        const char* pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        if (EQUAL(pszName, "latitude") || EQUAL(pszName, "lat") ||
+            EQUAL(pszName, "latdec"))
+            iLatitudeField = i;
+        else if (EQUAL(pszName, "longitude") || EQUAL(pszName, "lon") ||
+                 EQUAL(pszName, "londec") || EQUAL(pszName, "long"))
+            iLongitudeField = i;
+    }
+
+    if (iLatitudeField >= 0 && iLongitudeField >= 0)
+    {
+        iGeometryField = iLatitudeField;
+        poFeatureDefn->SetGeomType( wkbPoint );
+    }
+    /* If no longitude/latitude field exist, let's look at a column */
+    /* named 'geometry' and use it as the LOCATION column if the layer */
+    /* hasn't been created with a none geometry type */
+    else if (iGeometryField < 0 && eGTypeForCreation != wkbNone)
+    {
+        iGeometryField = poFeatureDefn->GetFieldIndex(GetDefaultGeometryColumnName());
+        poFeatureDefn->SetGeomType( eGTypeForCreation );
+    }
+    /* The user doesn't want geometries, so don't create one */
+    else if (eGTypeForCreation == wkbNone)
+    {
+        poFeatureDefn->SetGeomType( eGTypeForCreation );
+    }
+
+    for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+    {
+        if (i > 0)
+            osSQL += ", ";
+
+        const char* pszFieldName =
+            poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        osSQL += EscapeAndQuote(pszFieldName);
+        osSQL += ": ";
+
+        if (iGeometryField == i)
+        {
+            osSQL += "LOCATION";
+        }
+        else
+        {
+            switch(poFeatureDefn->GetFieldDefn(i)->GetType())
+            {
+                case OFTInteger:
+                case OFTReal:
+                    osSQL += "NUMBER";
+                    break;
+                default:
+                    osSQL += "STRING";
+            }
+        }
+    }
+
+    /* If there's not yet a geometry field and the user didn't forbid */
+    /* the creation of one, then let's add it to the CREATE TABLE, but */
+    /* DO NOT add it to the feature defn as a feature might already have */
+    /* been created with it, so it is not safe to alter it at that point. */
+    /* So we set the bHiddenGeometryField flag to be able to fetch/set this */
+    /* column but not try to get/set a related feature field */
+    if (iGeometryField < 0 && eGTypeForCreation != wkbNone)
+    {
+        if (i > 0)
+            osSQL += ", ";
+        osSQL += EscapeAndQuote(GetDefaultGeometryColumnName());
+        osSQL += ": LOCATION";
+
+        iGeometryField = poFeatureDefn->GetFieldCount();
+        bHiddenGeometryField = TRUE;
+    }
+    osSQL += ")";
+
+    CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
+    if (psResult == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Table creation failed");
+        return;
+    }
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        strncmp(pszLine, "tableid", 7) != 0 ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Table creation failed");
+        CPLHTTPDestroyResult(psResult);
+        return;
+    }
+
+    pszLine = OGRGFTGotoNextLine(pszLine);
+    if (pszLine == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Table creation failed");
+        CPLHTTPDestroyResult(psResult);
+        return;
+    }
+
+    char* pszNextLine = OGRGFTGotoNextLine(pszLine);
+    if (pszNextLine)
+        pszNextLine[-1] = 0;
+
+    osTableId = pszLine;
+    CPLDebug("GFT", "Table %s --> id = %s", osTableName.c_str(), osTableId.c_str());
+
+    CPLHTTPDestroyResult(psResult);
+}
+
+/************************************************************************/
+/*                           CreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRGFTTableLayer::CreateFeature( OGRFeature *poFeature )
+
+{
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (osTableId.size() == 0)
+    {
+        CreateTableIfNecessary();
+        if (osTableId.size() == 0)
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                    "Cannot add feature to non-created table");
+            return OGRERR_FAILURE;
+        }
+    }
+
+    if (poDS->GetAuth().size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in unauthenticated mode");
+        return OGRERR_FAILURE;
+    }
+
+    CPLString      osCommand;
+
+    osCommand += "INSERT INTO ";
+    osCommand += osTableId;
+    osCommand += " (";
+
+    int iField;
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+    for(iField = 0; iField < nFieldCount; iField++)
+    {
+        if (iField > 0)
+            osCommand += ", ";
+
+        const char* pszFieldName =
+            poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
+        osCommand += EscapeAndQuote(pszFieldName);
+    }
+    if (bHiddenGeometryField)
+    {
+        if (iField > 0)
+            osCommand += ", ";
+        osCommand += EscapeAndQuote(GetGeometryColumn());
+    }
+    osCommand += ") VALUES (";
+    for(iField = 0; iField < nFieldCount + bHiddenGeometryField; iField++)
+    {
+        if (iField > 0)
+            osCommand += ", ";
+
+        OGRGeometry* poGeom = poFeature->GetGeometryRef();
+        /* If there's a geometry, let's use it in priority over the textual */
+        /* content of the field. */
+        if (iGeometryField != iLatitudeField && iField == iGeometryField &&
+            (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSet( iField )))
+        {
+            if (poGeom == NULL)
+                osCommand += "''";
+            else
+            {
+                char* pszKML;
+                if (poGeom->getSpatialReference() != NULL &&
+                    !poGeom->getSpatialReference()->IsSame(poSRS))
+                {
+                    OGRGeometry* poGeom4326 = poGeom->clone();
+                    poGeom4326->transformTo(poSRS);
+                    pszKML = poGeom4326->exportToKML();
+                    delete poGeom4326;
+                }
+                else
+                {
+                    pszKML = poGeom->exportToKML();
+                }
+                osCommand += "'";
+                osCommand += pszKML;
+                osCommand += "'";
+                CPLFree(pszKML);
+            }
+            continue;
+        }
+
+        if( !poFeature->IsFieldSet( iField ) )
+        {
+            osCommand += "''";
+        }
+        else
+        {
+            OGRFieldType eType = poFeatureDefn->GetFieldDefn(iField)->GetType();
+            if (eType != OFTInteger && eType != OFTReal)
+            {
+                CPLString osTmp;
+                const char* pszVal = poFeature->GetFieldAsString(iField);
+
+                if (!CPLIsUTF8(pszVal, -1))
+                {
+                    static int bFirstTime = TRUE;
+                    if (bFirstTime)
+                    {
+                        bFirstTime = FALSE;
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
+                                "This warning won't be issued anymore", pszVal);
+                    }
+                    else
+                    {
+                        CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
+                                pszVal);
+                    }
+                    char* pszEscaped = CPLForceToASCII(pszVal, -1, '?');
+                    osTmp = pszEscaped;
+                    CPLFree(pszEscaped);
+                    pszVal = osTmp.c_str();
+                }
+
+                osCommand += EscapeAndQuote(pszVal);
+            }
+            else
+                osCommand += poFeature->GetFieldAsString(iField);
+        }
+    }
+
+    osCommand += ")";
+
+    //CPLDebug("GFT", "%s",  osCommand.c_str());
+
+    if (bInTransaction)
+    {
+        nFeaturesInTransaction ++;
+        if (nFeaturesInTransaction > 1)
+            osTransaction += "; ";
+        osTransaction += osCommand;
+        return OGRERR_NONE;
+    }
+
+    CPLHTTPResult * psResult = poDS->RunSQL(osCommand);
+    if (psResult == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Feature creation failed");
+        return OGRERR_FAILURE;
+    }
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        strncmp(pszLine, "rowid", 5) != 0 ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Feature creation failed");
+        CPLHTTPDestroyResult(psResult);
+        return OGRERR_FAILURE;
+    }
+
+    pszLine = OGRGFTGotoNextLine(pszLine);
+    if (pszLine == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Feature creation failed");
+        CPLHTTPDestroyResult(psResult);
+        return OGRERR_FAILURE;
+    }
+
+    char* pszNextLine = OGRGFTGotoNextLine(pszLine);
+    if (pszNextLine)
+        pszNextLine[-1] = 0;
+
+    CPLDebug("GFT", "Feature id = %s",  pszLine);
+
+    int nFID = atoi(pszLine);
+    if (strcmp(CPLSPrintf("%d", nFID), pszLine) == 0)
+        poFeature->SetFID(nFID);
+
+    CPLHTTPDestroyResult(psResult);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           SetFeature()                               */
+/************************************************************************/
+
+OGRErr      OGRGFTTableLayer::SetFeature( OGRFeature *poFeature )
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (osTableId.size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "Cannot set feature to non-created table");
+        return OGRERR_FAILURE;
+    }
+
+    if (poDS->GetAuth().size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in unauthenticated mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeature->GetFID() == OGRNullFID)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FID required on features given to SetFeature()." );
+        return OGRERR_FAILURE;
+    }
+
+    CPLString      osCommand;
+
+    osCommand += "UPDATE ";
+    osCommand += osTableId;
+    osCommand += " SET ";
+
+    int iField;
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+    for(iField = 0; iField < nFieldCount + bHiddenGeometryField; iField++)
+    {
+        if (iField > 0)
+            osCommand += ", ";
+
+        if (iField == nFieldCount)
+        {
+            osCommand += EscapeAndQuote(GetGeometryColumn());
+        }
+        else
+        {
+            const char* pszFieldName =
+                poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
+            osCommand += EscapeAndQuote(pszFieldName);
+        }
+
+        osCommand += " = ";
+
+        OGRGeometry* poGeom = poFeature->GetGeometryRef();
+        if (iGeometryField != iLatitudeField && iField == iGeometryField &&
+            (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSet( iField )))
+        {
+            if (poGeom == NULL)
+                osCommand += "''";
+            else
+            {
+                char* pszKML;
+                if (poGeom->getSpatialReference() != NULL &&
+                    !poGeom->getSpatialReference()->IsSame(poSRS))
+                {
+                    OGRGeometry* poGeom4326 = poGeom->clone();
+                    poGeom4326->transformTo(poSRS);
+                    pszKML = poGeom4326->exportToKML();
+                    delete poGeom4326;
+                }
+                else
+                {
+                    pszKML = poGeom->exportToKML();
+                }
+                osCommand += "'";
+                osCommand += pszKML;
+                osCommand += "'";
+                CPLFree(pszKML);
+            }
+            continue;
+        }
+
+        if( !poFeature->IsFieldSet( iField ) )
+        {
+            osCommand += "''";
+        }
+        else
+        {
+            OGRFieldType eType = poFeatureDefn->GetFieldDefn(iField)->GetType();
+            if (eType != OFTInteger && eType != OFTReal)
+            {
+                CPLString osTmp;
+                const char* pszVal = poFeature->GetFieldAsString(iField);
+
+                if (!CPLIsUTF8(pszVal, -1))
+                {
+                    static int bFirstTime = TRUE;
+                    if (bFirstTime)
+                    {
+                        bFirstTime = FALSE;
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
+                                "This warning won't be issued anymore", pszVal);
+                    }
+                    else
+                    {
+                        CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
+                                pszVal);
+                    }
+                    char* pszEscaped = CPLForceToASCII(pszVal, -1, '?');
+                    osTmp = pszEscaped;
+                    CPLFree(pszEscaped);
+                    pszVal = osTmp.c_str();
+                }
+
+                osCommand += EscapeAndQuote(pszVal);
+            }
+            else
+                osCommand += poFeature->GetFieldAsString(iField);
+        }
+    }
+
+    osCommand += " WHERE ROWID = '";
+    osCommand += CPLSPrintf("%ld", poFeature->GetFID());
+    osCommand += "'";
+
+    //CPLDebug("GFT", "%s",  osCommand.c_str());
+
+    CPLHTTPResult * psResult = poDS->RunSQL(osCommand);
+    if (psResult == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Feature update failed");
+        return OGRERR_FAILURE;
+    }
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        strncmp(pszLine, "OK", 2) != 0 ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Feature update failed");
+        CPLHTTPDestroyResult(psResult);
+        return OGRERR_FAILURE;
+    }
+
+    CPLHTTPDestroyResult(psResult);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRGFTTableLayer::DeleteFeature( long nFID )
+{
+    GetLayerDefn();
+
+    if (!poDS->IsReadWrite())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
+    if (osTableId.size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "Cannot delete feature in non-created table");
+        return OGRERR_FAILURE;
+    }
+
+    if (poDS->GetAuth().size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in unauthenticated mode");
+        return OGRERR_FAILURE;
+    }
+
+    CPLString      osCommand;
+
+    osCommand += "DELETE FROM ";
+    osCommand += osTableId;
+    osCommand += " WHERE ROWID = '";
+    osCommand += CPLSPrintf("%ld", nFID);
+    osCommand += "'";
+
+    //CPLDebug("GFT", "%s",  osCommand.c_str());
+
+    CPLHTTPResult * psResult = poDS->RunSQL(osCommand);
+    if (psResult == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Feature deletion failed");
+        return OGRERR_FAILURE;
+    }
+
+    char* pszLine = (char*) psResult->pabyData;
+    if (pszLine == NULL ||
+        strncmp(pszLine, "OK", 2) != 0 ||
+        psResult->pszErrBuf != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Feature deletion failed");
+        CPLHTTPDestroyResult(psResult);
+        return OGRERR_FAILURE;
+    }
+
+    CPLHTTPDestroyResult(psResult);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         StartTransaction()                           */
+/************************************************************************/
+
+OGRErr OGRGFTTableLayer::StartTransaction()
+{
+    GetLayerDefn();
+
+    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;
+    }
+
+    if (osTableId.size() == 0)
+    {
+        CreateTableIfNecessary();
+        if (osTableId.size() == 0)
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                    "Cannot add feature to non-created table");
+            return OGRERR_FAILURE;
+        }
+    }
+
+    if (poDS->GetAuth().size() == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Operation not available in unauthenticated mode");
+        return OGRERR_FAILURE;
+    }
+
+    bInTransaction = TRUE;
+    osTransaction.resize(0);
+    nFeaturesInTransaction = 0;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRGFTTableLayer::CommitTransaction()
+{
+    GetLayerDefn();
+
+    if (!bInTransaction)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
+        return OGRERR_FAILURE;
+    }
+
+    bInTransaction = FALSE;
+
+    if (nFeaturesInTransaction > 0)
+    {
+        if (nFeaturesInTransaction > 1)
+            osTransaction += ";";
+
+        CPLHTTPResult * psResult = poDS->RunSQL(osTransaction);
+        osTransaction.resize(0);
+        nFeaturesInTransaction = 0;
+
+        if (psResult == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "CommitTransaction failed");
+            return OGRERR_FAILURE;
+        }
+
+        char* pszLine = (char*) psResult->pabyData;
+        if (pszLine == NULL ||
+            strncmp(pszLine, "rowid", 5) != 0 ||
+            psResult->pszErrBuf != NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "CommitTransaction failed : %s",
+                     pszLine ? pszLine : psResult->pszErrBuf);
+            CPLHTTPDestroyResult(psResult);
+            return OGRERR_FAILURE;
+        }
+
+        pszLine = OGRGFTGotoNextLine(pszLine);
+        while(pszLine && *pszLine != 0)
+        {
+            char* pszNextLine = OGRGFTGotoNextLine(pszLine);
+            if (pszNextLine)
+                pszNextLine[-1] = 0;
+            //CPLDebug("GFT", "Feature id = %s",  pszLine);
+
+            pszLine = pszNextLine;
+        }
+
+        CPLHTTPDestroyResult(psResult);
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGRGFTTableLayer::RollbackTransaction()
+{
+    GetLayerDefn();
+
+    if (!bInTransaction)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
+        return OGRERR_FAILURE;
+    }
+    bInTransaction = FALSE;
+    nFeaturesInTransaction = 0;
+    osTransaction.resize(0);
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRGFTTableLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    GetLayerDefn();
+
+    if( pszQuery == NULL )
+        osQuery = "";
+    else
+    {
+        osQuery = PatchSQL(pszQuery);
+    }
+
+    BuildWhere();
+
+    ResetReading();
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRGFTTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
+
+{
+    GetLayerDefn();
+
+    if( InstallFilter( poGeomIn ) )
+    {
+        BuildWhere();
+
+        ResetReading();
+    }
+}
+
+/************************************************************************/
+/*                             BuildWhere()                             */
+/*                                                                      */
+/*      Build the WHERE statement appropriate to the current set of     */
+/*      criteria (spatial and attribute queries).                       */
+/************************************************************************/
+
+void OGRGFTTableLayer::BuildWhere()
+
+{
+    osWHERE = "";
+
+    if( m_poFilterGeom != NULL && iGeometryField >= 0)
+    {
+        OGREnvelope  sEnvelope;
+
+        m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        CPLString osQuotedGeomColumn(EscapeAndQuote(GetGeometryColumn()));
+
+        osWHERE.Printf("WHERE ST_INTERSECTS(%s, RECTANGLE(LATLNG(%.12f, %.12f), LATLNG(%.12f, %.12f)))",
+                       osQuotedGeomColumn.c_str(),
+                       MAX(-90.,sEnvelope.MinY - 1e-11), MAX(-180., sEnvelope.MinX - 1e-11),
+                       MIN(90.,sEnvelope.MaxY + 1e-11), MIN(180.,sEnvelope.MaxX + 1e-11));
+    }
+
+    if( strlen(osQuery) > 0 )
+    {
+        if( strlen(osWHERE) == 0 )
+            osWHERE = "WHERE ";
+        else
+            osWHERE += " AND ";
+        osWHERE += osQuery;
+    }
+}
+
+/************************************************************************/
+/*                          SetGeometryType()                           */
+/************************************************************************/
+
+void OGRGFTTableLayer::SetGeometryType(OGRwkbGeometryType eGType)
+{
+    eGTypeForCreation = eGType;
+}
diff --git a/ogr/ogrsf_frmts/gml/GNUmakefile b/ogr/ogrsf_frmts/gml/GNUmakefile
index ce09050..824336f 100644
--- a/ogr/ogrsf_frmts/gml/GNUmakefile
+++ b/ogr/ogrsf_frmts/gml/GNUmakefile
@@ -3,25 +3,26 @@
 include ../../../GDALmake.opt
 
 CORE_OBJ =	gmlpropertydefn.o gmlfeatureclass.o gmlfeature.o gmlreader.o \
-		parsexsd.o resolvexlinks.o gmlutils.o
+		parsexsd.o resolvexlinks.o hugefileresolver.o gmlutils.o \
+		gmlreadstate.o gmlhandler.o trstring.o gfstemplate.o
 
 OGR_OBJ =	ogrgmldriver.o ogrgmldatasource.o ogrgmllayer.o
 
 OBJ =	$(CORE_OBJ) $(OGR_OBJ)
 
-CPPFLAGS :=	-I.. -I../.. $(GDAL_INCLUDE) $(XERCES_INCLUDE) $(EXPAT_INCLUDE) $(CPPFLAGS)
+CPPFLAGS :=	-I.. -I../.. $(GDAL_INCLUDE) $(XERCES_INCLUDE) $(EXPAT_INCLUDE) $(SQLITE_INC) $(CPPFLAGS)
 #CFLAGS	:=	$(filter-out -Wall,$(CFLAGS))
 
 ifeq ($(HAVE_XERCES),yes)
-CORE_OBJ :=	$(CORE_OBJ) gmlreadstate.o gmlhandler.o trstring.o
-CPPFLAGS +=  -DHAVE_XERCES=1
-else
+CPPFLAGS +=  -DHAVE_XERCES
+endif
+
 ifeq ($(HAVE_EXPAT),yes)
-CORE_OBJ :=	$(CORE_OBJ) gmlreadstate.o gmlhandler.o
-CPPFLAGS +=  -DHAVE_XERCES=0 -DHAVE_EXPAT
-else
-CPPFLAGS +=  -DHAVE_XERCES=0
+CPPFLAGS +=  -DHAVE_EXPAT
 endif
+
+ifeq ($(HAVE_SQLITE),yes)
+CPPFLAGS +=  -DHAVE_SQLITE
 endif
 
 # By default, XML validation is disabled.  Uncomment the following line to
diff --git a/ogr/ogrsf_frmts/gml/drv_gml.html b/ogr/ogrsf_frmts/gml/drv_gml.html
index 6563738..51bc3c3 100644
--- a/ogr/ogrsf_frmts/gml/drv_gml.html
+++ b/ogr/ogrsf_frmts/gml/drv_gml.html
@@ -8,7 +8,7 @@
 <h1>GML - Geography Markup Language</h1>
 
 OGR has limited support for GML reading and writing. Update of existing
-files is not currently supported.<p>
+files is not supported.<p>
 
 Supported GML flavors :
 <table border>
@@ -21,12 +21,22 @@ Supported GML flavors :
 </table>
 <p>
 
+<h2>Parsers</h2>
+
 The reading part of the driver only
-works if OGR is built with Xerces linked in. Starting with GDAL 1.7.0, when
+works if OGR is built with Xerces linked in. Starting with OGR 1.7.0, when
 Xerces is unavailable, read support also works if OGR is built with Expat linked in.
 XML validation is disabled by default.
 GML writing is always supported, even without Xerces or Expat.<p>
 
+Note: starting with OGR 1.9.0, if both Xerces and Expat are available at build time,
+the GML driver will preferentially select at runtime the Expat parser for cases where it is possible
+(GML file in a compatible encoding), and default back to Xerces parser in other cases.
+However, the choice of the parser can be overriden by specifying the <b>GML_PARSER</b>
+configuration option to <b>EXPAT</b> or <b>XERCES</b>.<p>
+
+<h2>CRS support</h2>
+
 Since OGR 1.8.0, the GML driver has coordinate system support. This is
 only reported when all the geometries of a layer have a srsName attribute,
 whose value is the same for all geometries. For srsName such as "urn:ogc:def:crs:EPSG:",
@@ -45,6 +55,8 @@ not consider the EPSG axis order and will report the coordinates in (latitude,lo
 order. However, if you set the configuration option <b>GML_CONSIDER_EPSG_AS_URN</b> to
 <b>YES</b>, the rules explained in the previous paragraph will be applied.<p>
 
+<h2>Schema</h2>
+
 In contrast to most GML readers, the OGR GML reader does not require
 the presence of an XML Schema definition of the feature classes (file with .xsd
 extension) to be able to read the GML file. If the .xsd file is absent or
@@ -138,6 +150,77 @@ the configuration option <b>GML_SKIP_RESOLVE_ELEMS</b>.  Set it to <b>ALL</b>
 to skip resolving altogether (default action).  Set it to <b>NONE</b> to
 resolve all the xlinks.<p>
 
+Starting since OGR 1.9.0 an alternative resolution method is available.
+This alternative method will be activated using the configuration option
+<b>GML_SKIP_RESOLVE_ELEMS HUGE</b>. In this case any gml:xlink will be 
+resolved using a temporary SQLite DB so to identify any corresponding
+gml:id relation. At the end of this SQL-based process, a resolved file
+will be generated exactly as in the <b>NONE</b> case but without their limits. 
+The main advantages in using an external (temporary) DBMS so to resolve 
+gml:xlink and gml:id relations are the followings:<ul>
+	<li>no memory size constraints. The <b>NONE</b> method stores the whole
+	   GML node-tree in-memory; and this practically means that no GML
+	   file bigger than 1 GB can be processed at all using a 32-bit
+	   platform, due to memory allocation limits. Using a file-system
+	   based DBMS avoids at all this issue.</li>
+	<li>by far better efficiency, most notably when huge GML files containing
+	   many thousands (or even millions) of xlink:href / gml:id relational 
+	   pairs.</li>
+	<li>using the <b>GML_SKIP_RESOLVE_ELEMS HUGE</b> method realistically allows 
+	   to succesfully resolve some really huge GML file (3GB+) containing many 
+	   millions xlink:href / gml:id in a reasonable time (about an hour or so on).</li>
+	<li>The <b>GML_SKIP_RESOLVE_ELEMS HUGE</b> method supports the followind further
+	   configuration option:<ul>
+		<li>you can use <b>GML_GFS_TEMPLATE</b> <b><i>path_to_template.gfs</i></b>
+		   in order to unconditionally use a predefined GFS file. This option is really useful
+		   when you are planning to import many distinct GML files in subsequent steps [<b>-append</b>] 
+		   and you absolutely want to preserve a fully consistent data layout for the whole GML set.
+		   Please, pay attention not to use the <b>-lco LAUNDER=yes</b> setting when using <b>GML_GFS_TEMPLATE</b>; 
+		   this should break the correct recognition of attribute names between subsequent GML import runs.
+</li>
+	</ul></li>
+</ul>
+
+<h2>TopoSurface interpretation rules [polygons and internal holes]</h2>
+
+<p>
+Starting since OGR 1.9.0 the GML driver is able to recognize two different interpretation
+rules for TopoSurface when a polygon contains any internal hole:
+<ul>
+	<li>the previously supported interpretation rule assumed that:<ul>
+		<li>each TopoSurface may be represented as a collection of many Faces</li>
+		<li><i>positive</i> Faces [i.e. declaring <b>orientation="+"</b>] are assumed to
+		    represent the Exterior Ring of some Polygon.</li>
+		<li><i>negative</i> Faces [i.e. declaring <b>orientation="-"</b>] are assumed to
+		    represent an Interior Ring (aka <i>hole</i>) belonging to the latest declared 
+			Exterior Ring.</li>
+		<li>ordering any Edge used to represent each Ring is important: each Edge is expected
+			to be exactly adjacent to the next one.</li>
+	</li></ul>
+	<li>the new interpretation rule now assumes that:<ul>
+		<li>each TopoSurface may be represented as a collection of many Faces</li>
+		<li>the declared <b>orientation</b> for any Face has nothing to deal with Exterior/Interior Rings</li>
+		<li>each Face is now intended to represent a complete Polygon, eventually including any possible Interior 
+			Ring (<i>holes</i>)</li>
+		<li>the relative ordering of any Edge composing the same Face is completely not relevant</li> 
+	</li></ul>
+</ul>
+		
+The newest interpretation seems to fully match GML 3 standard recommendations; so this latest
+is now assumed to be the default interpretation supported by OGR.</p>
+
+<p><b>NOTE</b> : Using the newest interpretation requires GDAL/OGR to be built against the GEOS library.</p>
+
+<p>Using the <b>GML_FACE_HOLE_NEGATIVE</b> configuration option you can anyway select the
+actual interpretation to be applied when parsing GML 3 Topologies:
+<ul>
+	<li>setting <b>GML_FACE_HOLE_NEGATIVE NO</b> (<i>default</i> option) will activate
+	    the newest interpretation rule</li>
+	<li>but explicitly setting <b>GML_FACE_HOLE_NEGATIVE YES</b> still enables to activate
+	    the old interpretation rule</li>
+</ul>
+</p>
+
 <h2>Encoding issues</h2>
 
 Expat library supports reading the following built-in encodings :
@@ -155,13 +238,73 @@ ISO-8859-1 might work in some cases).<p>
 The content returned by OGR will be encoded in UTF-8, after the conversion from the
 encoding mentionned in the file header is.<p>
 
-If your GML file is not encoded in one of the previous encodings, it will not be parsed by the
-GML driver. You may convert it into one of the supported encoding with the <i>iconv</i> utility
-for example and change accordingly the <i>encoding</i> parameter value in the XML header.<br>
+If the GML file is not encoded in one of the previous encodings and the only parser available
+is Expat, it will not be parsed by the GML driver. You may convert it into one of the supported
+encodings with the <i>iconv</i> utility for example and change accordingly the <i>encoding</i>
+parameter value in the XML header.<br>
 <p>
 
 When writing a GML file, the driver expects UTF-8 content to be passed in.<p>
 
+<h2>Feature id (fid / gml:id)</h2>
+
+Starting with OGR 1.8.0, the driver exposes the content of the gml:id attribute
+as a string field called <i>gml_id</i>, when reading GML WFS documents. When creating
+a GML3 document, if a field is called <i>gml_id</i>, its content will also be used to
+write the content of the gml:id attribute of the created feature.<p>
+
+Starting with OGR 1.9.0, the driver autodetects the presence of a fid (GML2)
+(resp. gml:id (GML3)) attribute at the beginning of the file, and, if found,
+exposes it by default as a <i>fid</i> (resp. <i>gml_id</i>) field. The autodetection
+can be overriden by specifying the <b>GML_EXPOSE_FID</b> or <b>GML_EXPOSE_GML_ID</b> configuration
+option to <b>YES</b> or <b>NO</b>.<p>
+
+Starting with OGR 1.9.0, when creating a GML2 document, if a field is called
+<i>fid</i>, its content will also be used to write the content of the fid attribute of the
+created feature.<p>
+
+<h2>Performance issues with large multi-layer GML files.</h2>
+
+There is only one GML parser per GML datasource shared among the various layers.
+By default, the GML driver will restart reading from the beginning of the file, each time a layer
+is accessed for the first time, which can lead to poor performance with large GML files.<p>
+
+Starting with OGR 1.9.0, the <b>GML_READ_MODE</b> configuration option can be set to <b>SEQUENTIAL_LAYERS</b>
+if all features belonging to the same layer are written sequentially in the file. The reader will then avoid
+unnecessary resets when layers are read completely one after the other. To get the best performance,
+the layers must be read in the order they appear in the file.<p>
+
+If no .xsd and .gfs files are found, the parser will detect the layout of layers when
+building the .gfs file. If the layers are found to be sequential, a <i><SequentialLayers>true</SequentialLayers></i>
+element will be written in the .gfs file, so that the GML_READ_MODE will be automatically
+initialized to MONOBLOCK_LAYERS if not explicitely set by the user.<p>
+
+Starting with OGR 1.9.0, the GML_READ_MODE configuration option can be set to INTERLEAVED_LAYERS to be able
+to read a GML file whose features from different layers are interleaved. In the case, the semantics of the
+GetNextFeature() will be slightly altered, in a way where a NULL return does not necessarily mean that
+all features from the current layer have been read, but it could also mean that there is still a feature to read, but that
+belongs to another layer. In that case, the file should be read with code similar to the following one :
+
+<pre>
+    int nLayerCount = poDS->GetLayerCount();
+    int bFoundFeature;
+    do
+    {
+        bFoundFeature = FALSE;
+        for( int iLayer = 0; iLayer < nLayerCount; iLayer++ )
+        {
+            OGRLayer   *poLayer = poDS->GetLayer(iLayer);
+            OGRFeature *poFeature;
+            while((poFeature = poLayer->GetNextFeature()) != NULL)
+            {
+                bFoundFeature = TRUE;
+                poFeature->DumpReadable(stdout, NULL);
+                OGRFeature::DestroyFeature(poFeature);
+            }
+        }
+    } while (bInterleaved && bFoundFeature);
+</pre>
+
 <h2>Creation Issues</h2>
 
 On export all layers are written to a single GML file all in a single
@@ -169,7 +312,7 @@ feature collection.  Each layer's name is used as the element name for
 objects from that layer.  Geometries are always written as the 
 ogr:geometryProperty element on the feature.<p>
 
-The GML writer supports the following creation options:
+The GML writer supports the following dataset creation options:
 
 <ul>
 <li> <B>XSISCHEMAURI</B>: If provided, this URI will be inserted as the
@@ -183,20 +326,38 @@ EXTERNAL.  This writes a GML application schema file to a corresponding .xsd fil
 file, but this is experimental and almost certainly not valid XML.
 OFF disables schema generation (and is implicit if XSISCHEMAURI is used).<p>
 
-<li> <b>FORMAT</b>: (OGR >= 1.8.0) This can be set to GML3 in order
-to write GML files that follow GML3 SF-0 profile. Otherwise GML2 will be used.<p>
-
-<li> <b>GML3_LONGSRS</b>=YES/NO. (OGR >= 1.8.0, only valid when FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
+<li> <b>FORMAT</b>: (OGR >= 1.8.0) This can be set to :
+<ul>
+<li><i>GML3</i> in order to write GML files that follow GML 3.1.1 SF-0 profile.</li>
+<li><i>GML3Deegree</i> (OGR >= 1.9.0) in order to produce a GML 3.1.1 .XSD schema,
+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>
+
+<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.
 In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
 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>SPACE_INDENTATION</b>=YES/NO. (OGR >= 1.8.0) Default to YES. If YES, the output will be indented with spaces
+<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>
 
 </ul>
 
+<h2>VSI Virtual File System API support</h2>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported. Note that in that case, only the content of the GML file
+will be written to the standard output (and not the .xsd). The <boundedBy> element will not be written. This is also
+the case if writing in /vsigzip/<p>
+
 <h2>Syntax of .gfs file by example</h2>
 
 Let's consider the following test.gml file :
@@ -292,10 +453,15 @@ 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</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="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>
 
+<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>
+</ul>
+
 </body>
 </html>
diff --git a/ogr/ogrsf_frmts/gml/gfstemplate.cpp b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
new file mode 100644
index 0000000..80218f3
--- /dev/null
+++ b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
@@ -0,0 +1,348 @@
+/******************************************************************************
+ * $Id: gfstemplate.cpp 23547 2011-12-12 16:29:27Z rouault $
+ *
+ * Project:  GML Reader
+ * Purpose:  Implementation of GML GFS template management
+ * Author:   Alessandro Furieri, a.furitier at lqt.it
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Alessandro Furieri
+ *
+ * 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.
+ *
+ ******************************************************************************
+ * Contributor: Alessandro Furieri, a.furieri at lqt.it
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from
+ * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
+ *
+ ****************************************************************************/
+
+#include "gmlreaderp.h"
+#include "ogr_gml.h"
+
+CPL_CVSID("$Id: gfstemplate.cpp 23547 2011-12-12 16:29:27Z rouault $");
+
+/************************************************************************/
+/*                        GFSTemplateItem                               */
+/************************************************************************/
+
+class GFSTemplateItem
+{
+private:
+    char            *m_pszName;
+    int             n_nItemCount;
+    int             n_nGeomCount;
+    GFSTemplateItem *pNext;
+public:
+                    GFSTemplateItem( const char *pszName );
+                    ~GFSTemplateItem();
+    const char      *GetName() { return m_pszName; }
+    void            Update( int b_has_geom );
+    int             GetCount() { return n_nItemCount; }
+    int             GetGeomCount() { return n_nGeomCount; }
+    void            SetNext( GFSTemplateItem *pN ) { pNext = pN; }
+    GFSTemplateItem *GetNext() { return pNext; }
+};
+
+/***************************************************/
+/*               gmlUpdateFeatureClasses()         */
+/***************************************************/
+
+ void gmlUpdateFeatureClasses ( GFSTemplateList *pCC,
+                                GMLReader *pReader,
+                                int *pbSequentialLayers )
+{
+/* updating the FeatureClass list */
+    int clIdx;
+    for (clIdx = 0; clIdx < pReader->GetClassCount(); clIdx++)
+    {
+        GMLFeatureClass* poClass = pReader->GetClass( clIdx );
+        if (poClass != NULL)
+            poClass->SetFeatureCount( 0 );
+    }
+    int m_bValid = FALSE;
+    GFSTemplateItem *pItem = pCC->GetFirst();
+    while ( pItem != NULL )
+    {
+    /* updating Classes */
+        GMLFeatureClass* poClass = pReader->GetClass( pItem->GetName() );
+        if (poClass != NULL)
+        {
+            poClass->SetFeatureCount( pItem->GetCount() );
+            if ( pItem->GetGeomCount() == 0)
+                poClass->SetGeometryType( wkbNone );
+            m_bValid = TRUE;
+        }
+        pItem = pItem->GetNext();
+    }
+    if ( m_bValid == TRUE && pCC->HaveSequentialLayers() == TRUE )
+        *pbSequentialLayers = TRUE;
+}
+
+/***************************************************/
+/*       GMLReader::ReArrangeTemplateClasses()     */
+/***************************************************/
+
+int GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
+{
+/* rearranging the final FeatureClass list [SEQUENTIAL] */
+    int m_nSavedClassCount = GetClassCount();
+
+/* saving the previous FeatureClass list */
+    GMLFeatureClass **m_papoSavedClass = (GMLFeatureClass **)
+                    CPLMalloc( sizeof(void*) * m_nSavedClassCount );
+    int clIdx;
+    for (clIdx = 0; clIdx < GetClassCount(); clIdx++)
+    {
+    /* tranferring any previous FeatureClass */
+        m_papoSavedClass[clIdx] = m_papoClass[clIdx];
+    }
+
+/* cleaning the previous FeatureClass list */
+    SetClassListLocked( FALSE );
+    CPLFree( m_papoClass );
+    m_nClassCount = 0;
+    m_papoClass = NULL;
+
+    GFSTemplateItem *pItem = pCC->GetFirst();
+    while ( pItem != NULL )
+    {
+    /*
+    * re-inserting any required FeatureClassup
+    * accordingly to actual SEQUENTIAL layout
+    */
+        GMLFeatureClass* poClass = NULL;
+        for( int iClass = 0; iClass < m_nSavedClassCount; iClass++ )
+        {
+            GMLFeatureClass* poItem = m_papoSavedClass[iClass];
+            if( EQUAL(poItem->GetName(), pItem->GetName() ))
+            {
+                poClass = poItem;
+                break;
+            }
+        }
+        if (poClass != NULL)
+        {
+            if (poClass->GetFeatureCount() > 0)
+                AddClass( poClass );
+        }
+        pItem = pItem->GetNext();
+    }
+    SetClassListLocked( TRUE );
+
+/* destroying the saved List and any unused FeatureClass */
+    for( int iClass = 0; iClass < m_nSavedClassCount; iClass++ )
+    {
+        int bUnused = TRUE;
+        GMLFeatureClass* poClass = m_papoSavedClass[iClass];
+        for( int iClass2 = 0; iClass2 < m_nClassCount; iClass2++ )
+        {
+            if (m_papoClass[iClass2] == poClass)
+            {
+                bUnused = FALSE;
+                break;
+            }
+        }
+        if ( bUnused == TRUE )
+            delete poClass;
+    }
+    CPLFree( m_papoSavedClass );
+    return 1;
+}
+
+/***************************************************/
+/*       GMLReader::PrescanForTemplate()           */
+/***************************************************/
+
+int GMLReader::PrescanForTemplate ()
+{
+    int iCount = 0;
+    GMLFeature      *poFeature;
+    //int bSequentialLayers = TRUE;
+    GFSTemplateList *pCC = new GFSTemplateList();
+
+    /* processing GML features */
+    while( (poFeature = NextFeature()) != NULL )
+    {
+        GMLFeatureClass *poClass = poFeature->GetClass();
+        const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
+        int b_has_geom = FALSE;
+
+        if( papsGeomList != NULL )
+        {
+            int i = 0;
+            const CPLXMLNode *psNode = papsGeomList[i];
+            while( psNode != NULL )
+            {
+                b_has_geom = TRUE;
+                i++;
+                psNode = papsGeomList[i];
+            }
+        }
+        pCC->Update( poClass->GetElementName(), b_has_geom );
+
+        delete poFeature;
+    }
+
+    gmlUpdateFeatureClasses( pCC, this, &m_bSequentialLayers );
+    if ( m_bSequentialLayers == TRUE )
+        ReArrangeTemplateClasses( pCC );
+    iCount = pCC->GetClassCount();
+    delete pCC;
+    CleanupParser();
+    return iCount > 0;
+}
+
+
+/***************************************************/
+/*                 GFSTemplateList()               */
+/***************************************************/
+
+GFSTemplateList::GFSTemplateList( void )
+{
+    m_bSequentialLayers = TRUE;
+    pFirst = NULL;
+    pLast = NULL;
+}
+
+/***************************************************/
+/*                 GFSTemplateList()               */
+/***************************************************/
+
+GFSTemplateList::~GFSTemplateList()
+{
+    GFSTemplateItem *pNext;
+    GFSTemplateItem *pItem = pFirst;
+    while ( pItem != NULL )
+    {
+        pNext = pItem->GetNext();
+        delete pItem;
+        pItem = pNext;
+    }
+}
+
+/***************************************************/
+/*             GFSTemplateList::Insert()           */
+/***************************************************/
+
+GFSTemplateItem *GFSTemplateList::Insert( const char *pszName )
+{
+    GFSTemplateItem *pItem;
+    pItem = new GFSTemplateItem( pszName );
+
+    /* inserting into the linked list */
+    if( pFirst == NULL )
+        pFirst = pItem;
+    if( pLast != NULL )
+        pLast->SetNext( pItem );
+    pLast = pItem;
+    return pItem;
+}
+
+/***************************************************/
+/*             GFSTemplateList::Update()           */
+/***************************************************/
+
+void GFSTemplateList::Update( const char *pszName, int bHasGeom )
+{
+    GFSTemplateItem *pItem;
+
+    if( pFirst == NULL )
+    {
+    /* empty List: first item */
+        pItem = Insert( pszName );
+        pItem->Update( bHasGeom );
+        return;
+    }
+    if( EQUAL(pszName, pLast->GetName() ) )
+    {
+    /* continuing with the current Class Item */
+        pLast->Update( bHasGeom );
+        return;
+    }
+
+    pItem = pFirst;
+    while( pItem != NULL )
+    {
+        if( EQUAL(pszName, pItem->GetName() ))
+        {
+        /* Class Item previously declared: NOT SEQUENTIAL */
+            m_bSequentialLayers = FALSE;
+            pItem->Update( bHasGeom );
+            return;
+        }
+        pItem = pItem->GetNext();
+    }
+
+    /* inserting a new Class Item */
+    pItem = Insert( pszName );
+    pItem->Update( bHasGeom );
+}
+
+
+/***************************************************/
+/*          GFSTemplateList::GetClassCount()       */
+/***************************************************/
+
+int GFSTemplateList::GetClassCount( )
+{
+    int iCount = 0;
+    GFSTemplateItem *pItem;
+
+    pItem = pFirst;
+    while( pItem != NULL )
+    {
+        iCount++;
+        pItem = pItem->GetNext();
+    }
+
+    return iCount;
+}
+
+/***************************************************/
+/*                 GFSTemplateItem()               */
+/***************************************************/
+
+GFSTemplateItem::GFSTemplateItem( const char *pszName )
+{
+    m_pszName = CPLStrdup( pszName );
+    n_nItemCount = 0;
+    n_nGeomCount = 0;
+    pNext = NULL;
+}
+
+/***************************************************/
+/*                ~GFSTemplateItem()               */
+/***************************************************/
+
+GFSTemplateItem::~GFSTemplateItem()
+{
+    CPLFree(m_pszName);
+}
+
+/***************************************************/
+/*             GFSTemplateItem::Update()           */
+/***************************************************/
+
+void GFSTemplateItem::Update( int bHasGeom )
+{
+    n_nItemCount++;
+    if( bHasGeom == TRUE )
+        n_nGeomCount++;
+}
diff --git a/ogr/ogrsf_frmts/gml/gmlfeature.cpp b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
index f4565ad..7b11221 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeature.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlfeature.cpp 20247 2010-08-10 18:48:46Z rouault $
+ * $Id: gmlfeature.cpp 22954 2011-08-19 21:47:19Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeature.
@@ -40,10 +40,14 @@ GMLFeature::GMLFeature( GMLFeatureClass *poClass )
 {
     m_poClass = poClass;
     m_pszFID = NULL;
-    m_papszGeometryList = NULL;
     
     m_nPropertyCount = 0;
     m_pasProperties = NULL;
+
+    m_nGeometryCount = 0;
+    m_papsGeometry = m_apsGeometry;
+    m_apsGeometry[0] = NULL;
+    m_apsGeometry[1] = NULL;
     
     m_papszOBProperties = NULL;
 }
@@ -56,16 +60,33 @@ GMLFeature::~GMLFeature()
 
 {
     CPLFree( m_pszFID );
-    
-    for( int i = 0; i < m_nPropertyCount; i++ )
+
+    int i;
+    for( i = 0; i < m_nPropertyCount; i++ )
     {
-        for( int j = 0; j < m_pasProperties[i].nSubProperties; j++)
-            CPLFree( m_pasProperties[i].papszSubProperties[j] );
-        CPLFree( m_pasProperties[i].papszSubProperties );
+        int nSubProperties = m_pasProperties[i].nSubProperties;
+        if (nSubProperties == 1)
+            CPLFree( m_pasProperties[i].aszSubProperties[0] );
+        else if (nSubProperties > 1)
+        {
+            for( int j = 0; j < nSubProperties; j++)
+                CPLFree( m_pasProperties[i].papszSubProperties[j] );
+            CPLFree( m_pasProperties[i].papszSubProperties );
+        }
+    }
+
+    if (m_nGeometryCount == 1)
+    {
+        CPLDestroyXMLNode(m_apsGeometry[0]);
+    }
+    else if (m_nGeometryCount > 1)
+    {
+        for(i=0;i<m_nGeometryCount;i++)
+            CPLDestroyXMLNode(m_papsGeometry[i]);
+        CPLFree(m_papsGeometry);
     }
 
     CPLFree( m_pasProperties );
-    CSLDestroy( m_papszGeometryList );
     CSLDestroy( m_papszOBProperties );
 }
 
@@ -84,51 +105,58 @@ void GMLFeature::SetFID( const char *pszFID )
 }
 
 /************************************************************************/
-/*                            GetProperty()                             */
-/************************************************************************/
-
-const GMLProperty *GMLFeature::GetProperty( int iIndex ) const
-
-{
-    if( iIndex < 0 || iIndex >= m_nPropertyCount )
-        return NULL;
-    else
-        return &m_pasProperties[iIndex];
-}
-
-/************************************************************************/
-/*                            SetProperty()                             */
+/*                        SetPropertyDirectly()                         */
 /************************************************************************/
 
-void GMLFeature::SetProperty( int iIndex, const char *pszValue )
+void GMLFeature::SetPropertyDirectly( int iIndex, char *pszValue )
 
 {
-    if( iIndex < 0 || iIndex >= m_poClass->GetPropertyCount() )
-    {
-        CPLAssert( FALSE );
-        return;
-    }
-
     if( iIndex >= m_nPropertyCount )
     {
-        m_pasProperties = (GMLProperty*) 
-            CPLRealloc( m_pasProperties, 
-                        sizeof(GMLProperty) * m_poClass->GetPropertyCount() );
-        for( int i = m_nPropertyCount; i < m_poClass->GetPropertyCount(); i++ )
+        int nClassPropertyCount = m_poClass->GetPropertyCount();
+        m_pasProperties = (GMLProperty*)
+            CPLRealloc( m_pasProperties,
+                        sizeof(GMLProperty) * nClassPropertyCount );
+        int i;
+        for( i = 0; i < m_nPropertyCount; i ++ )
+        {
+            /* Make sure papszSubProperties point to the right address in case */
+            /* m_pasProperties has been relocated */
+            if (m_pasProperties[i].nSubProperties <= 1)
+                m_pasProperties[i].papszSubProperties = m_pasProperties[i].aszSubProperties;
+        }
+        for( i = m_nPropertyCount; i < nClassPropertyCount; i++ )
         {
             m_pasProperties[i].nSubProperties = 0;
-            m_pasProperties[i].papszSubProperties = NULL;
+            m_pasProperties[i].papszSubProperties = m_pasProperties[i].aszSubProperties;
+            m_pasProperties[i].aszSubProperties[0] = NULL;
+            m_pasProperties[i].aszSubProperties[1] = NULL;
         }
-        m_nPropertyCount = m_poClass->GetPropertyCount();
+        m_nPropertyCount = nClassPropertyCount;
     }
 
-    int nSubProperties = m_pasProperties[iIndex].nSubProperties;
-    m_pasProperties[iIndex].papszSubProperties = (char**) CPLRealloc(
-                        m_pasProperties[iIndex].papszSubProperties,
-                        sizeof(char*) * (nSubProperties + 2) );
-    m_pasProperties[iIndex].papszSubProperties[nSubProperties] = CPLStrdup( pszValue );
-    m_pasProperties[iIndex].papszSubProperties[nSubProperties + 1] = NULL;
-    m_pasProperties[iIndex].nSubProperties ++;
+    GMLProperty* psProperty = &m_pasProperties[iIndex];
+    int nSubProperties = psProperty->nSubProperties;
+    if (nSubProperties == 0)
+        psProperty->aszSubProperties[0] = pszValue;
+    else if (nSubProperties == 1)
+    {
+        psProperty->papszSubProperties = (char**) CPLMalloc(
+                            sizeof(char*) * (nSubProperties + 2) );
+        psProperty->papszSubProperties[0] = psProperty->aszSubProperties[0];
+        psProperty->aszSubProperties[0] = NULL;
+        psProperty->papszSubProperties[nSubProperties] = pszValue;
+        psProperty->papszSubProperties[nSubProperties + 1] = NULL;
+    }
+    else
+    {
+        psProperty->papszSubProperties = (char**) CPLRealloc(
+                            psProperty->papszSubProperties,
+                            sizeof(char*) * (nSubProperties + 2) );
+        psProperty->papszSubProperties[nSubProperties] = pszValue;
+        psProperty->papszSubProperties[nSubProperties + 1] = NULL;
+    }
+    psProperty->nSubProperties ++;
 }
 
 /************************************************************************/
@@ -142,8 +170,9 @@ void GMLFeature::Dump( FILE * fp )
     
     if( m_pszFID != NULL )
         printf( "  FID = %s\n", m_pszFID );
-    
-    for( int i = 0; i < m_nPropertyCount; i++ )
+
+    int i;
+    for( i = 0; i < m_nPropertyCount; i++ )
     {
         const GMLProperty * psGMLProperty = GetProperty( i );
         printf( "  %s = ", m_poClass->GetProperty( i )->GetName());
@@ -155,14 +184,11 @@ void GMLFeature::Dump( FILE * fp )
         printf("\n");
     }
 
-    if( m_papszGeometryList )
+    for(i=0;i<m_nGeometryCount;i++)
     {
-        char** papszIter = m_papszGeometryList;
-        while(*papszIter)
-        {
-            printf( "  %s\n", *papszIter );
-            papszIter ++;
-        }
+        char* pszXML = CPLSerializeXMLTree(m_papsGeometry[i]);
+        printf( "  %s\n", pszXML );
+        CPLFree(pszXML);
     }
 }
 
@@ -170,32 +196,43 @@ void GMLFeature::Dump( FILE * fp )
 /*                        SetGeometryDirectly()                         */
 /************************************************************************/
 
-void GMLFeature::SetGeometryDirectly( char *pszGeometry )
+void GMLFeature::SetGeometryDirectly( CPLXMLNode* psGeom )
 
 {
-    if (m_papszGeometryList != NULL && m_papszGeometryList[0] != NULL &&
-        m_papszGeometryList[1] == NULL)
-    {
-        CPLFree(m_papszGeometryList[0]);
-    }
-    else
-    {
-        CSLDestroy(m_papszGeometryList);
-        m_papszGeometryList = (char**)CPLMalloc(sizeof(char*) * 2);
-        m_papszGeometryList[1] = NULL;
-    }
-    m_papszGeometryList[0] = pszGeometry;
+    if (m_apsGeometry[0] != NULL)
+        CPLDestroyXMLNode(m_apsGeometry[0]);
+    m_nGeometryCount = 1;
+    m_apsGeometry[0] = psGeom;
 }
 
 /************************************************************************/
 /*                             AddGeometry()                            */
 /************************************************************************/
 
-void GMLFeature::AddGeometry( char *pszGeometry )
+void GMLFeature::AddGeometry( CPLXMLNode* psGeom )
 
 {
-    m_papszGeometryList = CSLAddString(m_papszGeometryList, pszGeometry);
-    CPLFree(pszGeometry);
+    if (m_nGeometryCount == 0)
+    {
+        m_apsGeometry[0] = psGeom;
+    }
+    else if (m_nGeometryCount == 1)
+    {
+        m_papsGeometry = (CPLXMLNode **) CPLMalloc(
+            (m_nGeometryCount + 2) * sizeof(CPLXMLNode *));
+        m_papsGeometry[0] = m_apsGeometry[0];
+        m_apsGeometry[0] = NULL;
+        m_papsGeometry[m_nGeometryCount] = psGeom;
+        m_papsGeometry[m_nGeometryCount + 1] = NULL;
+    }
+    else
+    {
+        m_papsGeometry = (CPLXMLNode **) CPLRealloc(m_papsGeometry,
+            (m_nGeometryCount + 2) * sizeof(CPLXMLNode *));
+        m_papsGeometry[m_nGeometryCount] = psGeom;
+        m_papsGeometry[m_nGeometryCount + 1] = NULL;
+    }
+    m_nGeometryCount ++;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
index 3b9e14a..3e5c310 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlfeatureclass.cpp 20422 2010-08-23 20:55:20Z rouault $
+ * $Id: gmlfeatureclass.cpp 22954 2011-08-19 21:47:19Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeatureClass.
@@ -39,7 +39,9 @@ GMLFeatureClass::GMLFeatureClass( const char *pszName )
 
 {
     m_pszName = CPLStrdup( pszName );
+    n_nNameLen = strlen( m_pszName );
     m_pszElementName = NULL;
+    n_nElementNameLen = 0;
     m_pszGeometryElement = NULL;
     m_nPropertyCount = 0;
     m_papoProperty = NULL;
@@ -101,6 +103,23 @@ int GMLFeatureClass::GetPropertyIndex( const char *pszName ) const
 }
 
 /************************************************************************/
+/*                        GetPropertyIndexBySrcElement()                */
+/************************************************************************/
+
+int GMLFeatureClass::GetPropertyIndexBySrcElement( const char *pszElement, int nLen ) const
+
+{
+    for( int i = 0; i < m_nPropertyCount; i++ )
+        if( nLen == (int)m_papoProperty[i]->GetSrcElementLen() &&
+            memcmp(pszElement,m_papoProperty[i]->GetSrcElement(), nLen) == 0)
+            return i;
+
+    return -1;
+}
+
+
+
+/************************************************************************/
 /*                            AddProperty()                             */
 /************************************************************************/
 
@@ -133,6 +152,7 @@ void GMLFeatureClass::SetElementName( const char *pszElementName )
 {
     CPLFree( m_pszElementName );
     m_pszElementName = CPLStrdup( pszElementName );
+    n_nElementNameLen = strlen(pszElementName);
 }
 
 /************************************************************************/
@@ -149,6 +169,19 @@ const char *GMLFeatureClass::GetElementName() const
 }
 
 /************************************************************************/
+/*                           GetElementName()                           */
+/************************************************************************/
+
+size_t GMLFeatureClass::GetElementNameLen() const
+
+{
+    if( m_pszElementName == NULL )
+        return n_nNameLen;
+    else
+        return n_nElementNameLen;
+}
+
+/************************************************************************/
 /*                         SetGeometryElement()                         */
 /************************************************************************/
 
@@ -156,7 +189,10 @@ void GMLFeatureClass::SetGeometryElement( const char *pszElement )
 
 {
     CPLFree( m_pszGeometryElement );
-    m_pszGeometryElement = CPLStrdup( pszElement );
+    if (pszElement)
+        m_pszGeometryElement = CPLStrdup( pszElement );
+    else
+        m_pszGeometryElement = NULL;
 }
 
 /************************************************************************/
@@ -310,6 +346,7 @@ 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 ) );
 
diff --git a/ogr/ogrsf_frmts/gml/gmlhandler.cpp b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
index 5bb88d6..08edb42 100644
--- a/ogr/ogrsf_frmts/gml/gmlhandler.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlhandler.cpp 21390 2011-01-03 22:43:07Z rouault $
+ * $Id: gmlhandler.cpp 23566 2011-12-13 20:51:04Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLHandler class.
@@ -31,8 +31,9 @@
 #include "gmlreaderp.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "cpl_hash_set.h"
 
-#if HAVE_XERCES == 1
+#ifdef HAVE_XERCES
 
 /* Must be a multiple of 4 */
 #define MAX_TOKEN_SIZE  1000
@@ -78,7 +79,7 @@ void GMLXercesHandler::startElement(const XMLCh* const    uri,
     else
         tr_strcpy( szElementName, localname );
 
-    if (GMLHandler::startElement(szElementName, (void*) &attrs) == CE_Failure)
+    if (GMLHandler::startElement(szElementName, strlen(szElementName), (void*) &attrs) == OGRERR_NOT_ENOUGH_MEMORY)
     {
         throw SAXNotSupportedException("Out of memory");
     }
@@ -92,65 +93,36 @@ void GMLXercesHandler::endElement(const   XMLCh* const    uri,
                                   const   XMLCh* const    qname )
 
 {
-    char        szElementName[MAX_TOKEN_SIZE];
-
     m_nEntityCounter = 0;
 
-    /* A XMLCh character can expand to 4 bytes in UTF-8 */
-    if (4 * tr_strlen( localname ) >= MAX_TOKEN_SIZE)
-    {
-        XMLCh* tempBuffer = (XMLCh*) CPLMalloc(sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4 + 1));
-        memcpy(tempBuffer, localname, sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4));
-        tempBuffer[MAX_TOKEN_SIZE / 4] = 0;
-        tr_strcpy( szElementName, tempBuffer );
-        CPLFree(tempBuffer);
-    }
-    else
-        tr_strcpy( szElementName, localname );
-
-    if (GMLHandler::endElement(szElementName) == CE_Failure)
+    if (GMLHandler::endElement() == OGRERR_NOT_ENOUGH_MEMORY)
     {
         throw SAXNotSupportedException("Out of memory");
     }
 }
 
-#if XERCES_VERSION_MAJOR >= 3
 /************************************************************************/
-/*                             characters() (xerces 3 version)          */
+/*                             characters()                             */
 /************************************************************************/
 
 void GMLXercesHandler::characters(const XMLCh* const chars_in,
-                                  const XMLSize_t length )
-{
-    char* utf8String = tr_strdup(chars_in);
-    int nLen = strlen(utf8String);
-    OGRErr eErr = GMLHandler::dataHandler(utf8String, nLen);
-    CPLFree(utf8String);
-    if (eErr == CE_Failure)
-    {
-        throw SAXNotSupportedException("Out of memory");
-    }
-}
-
+#if XERCES_VERSION_MAJOR >= 3
+                                  const XMLSize_t length
 #else
-/************************************************************************/
-/*                             characters() (xerces 2 version)          */
-/************************************************************************/
-
-void GMLXercesHandler::characters(const XMLCh* const chars_in,
-                                  const unsigned int length )
+                                  const unsigned int length
+#endif
+                                  )
 
 {
     char* utf8String = tr_strdup(chars_in);
     int nLen = strlen(utf8String);
     OGRErr eErr = GMLHandler::dataHandler(utf8String, nLen);
     CPLFree(utf8String);
-    if (eErr == CE_Failure)
+    if (eErr == OGRERR_NOT_ENOUGH_MEMORY)
     {
         throw SAXNotSupportedException("Out of memory");
     }
 }
-#endif
 
 /************************************************************************/
 /*                             fatalError()                             */
@@ -186,7 +158,7 @@ void GMLXercesHandler::startEntity (const XMLCh *const name)
 /*                               GetFID()                               */
 /************************************************************************/
 
-char* GMLXercesHandler::GetFID(void* attr)
+const char* GMLXercesHandler::GetFID(void* attr)
 {
     const Attributes* attrs = (const Attributes*) attr;
     int nFIDIndex;
@@ -195,41 +167,58 @@ char* GMLXercesHandler::GetFID(void* attr)
     tr_strcpy( anFID, "fid" );
     nFIDIndex = attrs->getIndex( anFID );
     if( nFIDIndex != -1 )
-        return tr_strdup( attrs->getValue( nFIDIndex ) );
+    {
+        char* pszValue = tr_strdup( attrs->getValue( nFIDIndex ) );
+        osFID.assign(pszValue);
+        CPLFree(pszValue);
+        return osFID.c_str();
+    }
     else
     {
         tr_strcpy( anFID, "gml:id" );
         nFIDIndex = attrs->getIndex( anFID );
         if( nFIDIndex != -1 )
-            return tr_strdup( attrs->getValue( nFIDIndex ) );
+        {
+            char* pszValue = tr_strdup( attrs->getValue( nFIDIndex ) );
+            osFID.assign(pszValue);
+            CPLFree(pszValue);
+            return osFID.c_str();
+        }
     }
 
+    osFID.resize(0);
     return NULL;
 }
 
 /************************************************************************/
-/*                        GetAttributes()                               */
+/*                        AddAttributes()                               */
 /************************************************************************/
 
-char* GMLXercesHandler::GetAttributes(void* attr)
+CPLXMLNode* GMLXercesHandler::AddAttributes(CPLXMLNode* psNode, void* attr)
 {
     const Attributes* attrs = (const Attributes*) attr;
-    CPLString osRes;
-    char *pszString;
+
+    CPLXMLNode* psLastChild = NULL;
 
     for(unsigned int i=0; i < attrs->getLength(); i++)
     {
-        osRes += " ";
-        pszString = tr_strdup(attrs->getQName(i));
-        osRes += pszString;
-        CPLFree( pszString );
-        osRes += "=\"";
-        pszString = tr_strdup(attrs->getValue(i));
-        osRes += pszString;
-        CPLFree( pszString );
-        osRes += "\"";
+        char* pszName = tr_strdup(attrs->getQName(i));
+        char* pszValue = tr_strdup(attrs->getValue(i));
+
+        CPLXMLNode* psChild = CPLCreateXMLNode(NULL, CXT_Attribute, pszName);
+        CPLCreateXMLNode(psChild, CXT_Text, pszValue);
+
+        CPLFree(pszName);
+        CPLFree(pszValue);
+
+        if (psLastChild == NULL)
+            psNode->psChild = psChild;
+        else
+            psLastChild->psNext = psChild;
+        psLastChild = psChild;
     }
-    return CPLStrdup(osRes);
+
+    return psLastChild;
 }
 
 /************************************************************************/
@@ -252,8 +241,9 @@ char* GMLXercesHandler::GetAttributeValue(void* attr, const char* pszAttributeNa
     return NULL;
 }
 
-#else
+#endif
 
+#ifdef HAVE_EXPAT
 
 /************************************************************************/
 /*                            GMLExpatHandler()                         */
@@ -268,105 +258,102 @@ GMLExpatHandler::GMLExpatHandler( GMLReader *poReader, XML_Parser oParser ) : GM
 }
 
 /************************************************************************/
-/*                            startElement()                            */
+/*                           startElementCbk()                          */
 /************************************************************************/
 
-OGRErr GMLExpatHandler::startElement(const char *pszName, void* attr )
+void XMLCALL GMLExpatHandler::startElementCbk(void *pUserData, const char *pszName,
+                                              const char **ppszAttr)
 
 {
-    if (m_bStopParsing)
-        return CE_Failure;
+    GMLExpatHandler* pThis = ((GMLExpatHandler*)pUserData);
+    if (pThis->m_bStopParsing)
+        return;
 
-    const char* pszColon = strchr(pszName, ':');
-    if (pszColon)
-        pszName = pszColon + 1;
+    const char* pszIter = pszName;
+    char ch;
+    while((ch = *pszIter) != '\0')
+    {
+        if (ch == ':')
+            pszName = pszIter + 1;
+        pszIter ++;
+    }
 
-    if (GMLHandler::startElement(pszName, attr) == CE_Failure)
+    if (pThis->GMLHandler::startElement(pszName, (int)(pszIter - pszName), ppszAttr) == OGRERR_NOT_ENOUGH_MEMORY)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
-        m_bStopParsing = TRUE;
-        XML_StopParser(m_oParser, XML_FALSE);
-        return CE_Failure;
+        pThis->m_bStopParsing = TRUE;
+        XML_StopParser(pThis->m_oParser, XML_FALSE);
     }
 
-    return CE_None;
 }
 
 /************************************************************************/
-/*                             endElement()                             */
+/*                            endElementCbk()                           */
 /************************************************************************/
-OGRErr GMLExpatHandler::endElement(const char* pszName )
+void XMLCALL GMLExpatHandler::endElementCbk(void *pUserData, const char* pszName )
 
 {
-    if (m_bStopParsing)
-        return CE_Failure;
-
-    const char* pszColon = strchr(pszName, ':');
-    if (pszColon)
-        pszName = pszColon + 1;
+    GMLExpatHandler* pThis = ((GMLExpatHandler*)pUserData);
+    if (pThis->m_bStopParsing)
+        return;
 
-    if (GMLHandler::endElement(pszName) == CE_Failure)
+    if (pThis->GMLHandler::endElement() == OGRERR_NOT_ENOUGH_MEMORY)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
-        m_bStopParsing = TRUE;
-        XML_StopParser(m_oParser, XML_FALSE);
-        return CE_Failure;
+        pThis->m_bStopParsing = TRUE;
+        XML_StopParser(pThis->m_oParser, XML_FALSE);
     }
-
-    return CE_None;
 }
 
 /************************************************************************/
-/*                             characters()                             */
+/*                            dataHandlerCbk()                          */
 /************************************************************************/
 
-OGRErr GMLExpatHandler::dataHandler(const char *data, int nLen)
+void XMLCALL GMLExpatHandler::dataHandlerCbk(void *pUserData, const char *data, int nLen)
 
 {
-    if (m_bStopParsing)
-        return CE_Failure;
-
-    m_nDataHandlerCounter ++;
-    if (m_nDataHandlerCounter >= BUFSIZ)
+    GMLExpatHandler* pThis = ((GMLExpatHandler*)pUserData);
+    if (pThis->m_bStopParsing)
+        return;
+
+    pThis->m_nDataHandlerCounter ++;
+    /* The size of the buffer that is fetched and that Expat parses is */
+    /* PARSER_BUF_SIZE bytes. If the dataHandlerCbk() callback is called */
+    /* more than PARSER_BUF_SIZE times, this means that one byte in the */
+    /* file expands to more XML text fragments, which is the sign of a */
+    /* likely abuse of <!ENTITY> */
+    /* Note: the counter is zeroed by ResetDataHandlerCounter() before each */
+    /* new XML parsing. */
+    if (pThis->m_nDataHandlerCounter >= PARSER_BUF_SIZE)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
-        m_bStopParsing = TRUE;
-        XML_StopParser(m_oParser, XML_FALSE);
-        return CE_Failure;
+        pThis->m_bStopParsing = TRUE;
+        XML_StopParser(pThis->m_oParser, XML_FALSE);
+        return;
     }
 
-    if (GMLHandler::dataHandler(data, nLen) == CE_Failure)
+    if (pThis->GMLHandler::dataHandler(data, nLen) == OGRERR_NOT_ENOUGH_MEMORY)
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
-        m_bStopParsing = TRUE;
-        XML_StopParser(m_oParser, XML_FALSE);
-        return CE_Failure;
+        pThis->m_bStopParsing = TRUE;
+        XML_StopParser(pThis->m_oParser, XML_FALSE);
+        return;
     }
-
-    return CE_None;
 }
 
 /************************************************************************/
 /*                               GetFID()                               */
 /************************************************************************/
 
-char* GMLExpatHandler::GetFID(void* attr)
+const char* GMLExpatHandler::GetFID(void* attr)
 {
     const char** papszIter = (const char** )attr;
     while(*papszIter)
     {
-        if (strcmp(*papszIter, "fid") == 0)
+        if (strcmp(*papszIter, "fid") == 0 ||
+            strcmp(*papszIter, "gml:id") == 0)
         {
-            return CPLStrdup(papszIter[1]);
-        }
-        papszIter += 2;
-    }
-    papszIter = (const char** )attr;
-    while(*papszIter)
-    {
-        if (strcmp(*papszIter, "gml:id") == 0)
-        {
-            return CPLStrdup(papszIter[1]);
+            return papszIter[1];
         }
         papszIter += 2;
     }
@@ -374,24 +361,30 @@ char* GMLExpatHandler::GetFID(void* attr)
 }
 
 /************************************************************************/
-/*                        GetAttributes()                               */
+/*                        AddAttributes()                               */
 /************************************************************************/
 
-char* GMLExpatHandler::GetAttributes(void* attr)
+CPLXMLNode* GMLExpatHandler::AddAttributes(CPLXMLNode* psNode, void* attr)
 {
     const char** papszIter = (const char** )attr;
-    CPLString osRes;
+
+    CPLXMLNode* psLastChild = NULL;
+
     while(*papszIter)
     {
-        osRes += " ";
-        osRes += *papszIter;
-        osRes += "=\"";
-        osRes += papszIter[1];
-        osRes += "\"";
+        CPLXMLNode* psChild = CPLCreateXMLNode(NULL, CXT_Attribute, papszIter[0]);
+        CPLCreateXMLNode(psChild, CXT_Text, papszIter[1]);
+
+        if (psLastChild == NULL)
+            psNode->psChild = psChild;
+        else
+            psLastChild->psNext = psChild;
+        psLastChild = psChild;
 
         papszIter += 2;
     }
-    return CPLStrdup( osRes );
+
+    return psLastChild;
 }
 
 /************************************************************************/
@@ -415,6 +408,49 @@ char* GMLExpatHandler::GetAttributeValue(void* attr, const char* pszAttributeNam
 #endif
 
 
+static const char* const apszGMLGeometryElements[] =
+{
+    "CompositeSurface",
+    "Curve",
+    "GeometryCollection", /* OGR < 1.8.0 bug... */
+    "LineString",
+    "MultiCurve",
+    "MultiGeometry",
+    "MultiLineString",
+    "MultiPoint",
+    "MultiPolygon",
+    "MultiSurface",
+    "Point",
+    "Polygon",
+    "PolygonPatch",
+    "Solid",
+    "Surface",
+    "TopoCurve",
+    "TopoSurface"
+};
+
+#define GML_GEOMETRY_TYPE_COUNT  \
+    (int)(sizeof(apszGMLGeometryElements) / sizeof(apszGMLGeometryElements[0]))
+
+struct _GeometryNamesStruct {
+    unsigned long nHash;
+    const char   *pszName;
+} ;
+
+/************************************************************************/
+/*                    GMLHandlerSortGeometryElements()                  */
+/************************************************************************/
+
+static int GMLHandlerSortGeometryElements(const void *_pA, const void *_pB)
+{
+    GeometryNamesStruct* pA = (GeometryNamesStruct*)_pA;
+    GeometryNamesStruct* pB = (GeometryNamesStruct*)_pB;
+    CPLAssert(pA->nHash != pB->nHash);
+    if (pA->nHash < pB->nHash)
+        return -1;
+    else
+        return 1;
+}
 
 /************************************************************************/
 /*                            GMLHandler()                              */
@@ -424,15 +460,20 @@ GMLHandler::GMLHandler( GMLReader *poReader )
 
 {
     m_poReader = poReader;
+    m_bInCurField = FALSE;
+    m_nCurFieldAlloc = 0;
+    m_nCurFieldLen = 0;
     m_pszCurField = NULL;
+    m_nAttributeIndex = -1;
+    m_nAttributeDepth = 0;
+
     m_pszGeometry = NULL;
-    m_nGeomAlloc = m_nGeomLen = 0;
-    m_nDepthFeature = m_nDepth = 0;
-    m_bIgnoreFeature = FALSE;
+    m_nGeomAlloc = 0;
+    m_nGeomLen = 0;
     m_nGeometryDepth = 0;
-    m_bInBoundedBy = FALSE;
+
+    m_nDepthFeature = m_nDepth = 0;
     m_inBoundedByDepth = 0;
-    m_bInCityGMLGenericAttr = FALSE;
     m_pszCityGMLGenericAttrName = NULL;
     m_inCityGMLGenericAttrDepth = 0;
     m_bIsCityGML = FALSE;
@@ -441,6 +482,21 @@ GMLHandler::GMLHandler( GMLReader *poReader )
     m_pszHref = NULL;
     m_pszUom = NULL;
     m_pszValue = NULL;
+
+    pasGeometryNames = (GeometryNamesStruct*)CPLMalloc(
+        GML_GEOMETRY_TYPE_COUNT * sizeof(GeometryNamesStruct));
+    for(int i=0; i<GML_GEOMETRY_TYPE_COUNT; i++)
+    {
+        pasGeometryNames[i].pszName = apszGMLGeometryElements[i];
+        pasGeometryNames[i].nHash =
+                    CPLHashSetHashStr(pasGeometryNames[i].pszName);
+    }
+    qsort(pasGeometryNames, GML_GEOMETRY_TYPE_COUNT,
+          sizeof(GeometryNamesStruct),
+          GMLHandlerSortGeometryElements);
+
+    nStackDepth = 0;
+    stateStack[0] = STATE_TOP;
 }
 
 /************************************************************************/
@@ -450,222 +506,285 @@ GMLHandler::GMLHandler( GMLReader *poReader )
 GMLHandler::~GMLHandler()
 
 {
+    if (apsXMLNode.size() >= 2 && apsXMLNode[1].psNode != NULL)
+        CPLDestroyXMLNode(apsXMLNode[1].psNode);
+
     CPLFree( m_pszCurField );
     CPLFree( m_pszGeometry );
     CPLFree( m_pszCityGMLGenericAttrName );
     CPLFree( m_pszHref );
     CPLFree( m_pszUom );
     CPLFree( m_pszValue );
+    CPLFree( pasGeometryNames );
 }
 
 
 /************************************************************************/
-/*                            startElement()                            */
+/*                             startElement()                           */
 /************************************************************************/
 
-OGRErr GMLHandler::startElement(const char *pszName, void* attr )
-
+OGRErr GMLHandler::startElement(const char *pszName, int nLenName, void* attr)
 {
-    GMLReadState *poState = m_poReader->GetState();
-
-    if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
+    OGRErr eRet;
+    switch(stateStack[nStackDepth])
     {
-        m_nDepth ++;
-        return CE_None;
+        case STATE_TOP:                 eRet = startElementTop(pszName, nLenName, attr); break;
+        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_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;
+        case STATE_CITYGML_ATTRIBUTE:   eRet = startElementCityGMLGenericAttr(pszName, nLenName, attr); break;
+        default:                        eRet = OGRERR_NONE; break;
     }
+    m_nDepth++;
+    return eRet;
+}
+
+/************************************************************************/
+/*                              endElement()                            */
+/************************************************************************/
 
-    if ( m_nDepth == 0 )
+OGRErr GMLHandler::endElement()
+{
+    m_nDepth--;
+    switch(stateStack[nStackDepth])
     {
-        if (strcmp(pszName, "CityModel") == 0 )
-        {
-            m_bIsCityGML = TRUE;
-        }
-        else if (strcmp(pszName, "AIXMBasicMessage") == 0)
-        {
-            m_bIsAIXM = m_bReportHref = TRUE;
-        }
+        case STATE_TOP:                 return OGRERR_NONE; break;
+        case STATE_DEFAULT:             return endElementDefault(); break;
+        case STATE_FEATURE:             return endElementFeature(); break;
+        case STATE_PROPERTY:            return endElementAttribute(); break;
+        case STATE_GEOMETRY:            return endElementGeometry(); break;
+        case STATE_IGNORED_FEATURE:     return endElementIgnoredFeature(); break;
+        case STATE_BOUNDED_BY:          return endElementBoundedBy(); break;
+        case STATE_CITYGML_ATTRIBUTE:   return endElementCityGMLGenericAttr(); break;
+        default:                        return OGRERR_NONE; break;
     }
-    else if ( m_nDepth == 2 && m_bInBoundedBy )
+}
+
+/************************************************************************/
+/*                              dataHandler()                           */
+/************************************************************************/
+
+OGRErr GMLHandler::dataHandler(const char *data, int nLen)
+{
+    switch(stateStack[nStackDepth])
     {
-        if ( strcmp(pszName, "Envelope") == 0 )
-        {
-            char* pszGlobalSRSName = GetAttributeValue(attr, "srsName");
-            if (pszGlobalSRSName != NULL &&
-                strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
-                CSLTestBoolean(CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "NO")))
-            {
-                char* pszNew = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s", pszGlobalSRSName+5));
-                CPLFree(pszGlobalSRSName);
-                pszGlobalSRSName = pszNew;
-            }
-            m_poReader->SetGlobalSRSName(pszGlobalSRSName);
-            CPLFree(pszGlobalSRSName);
-        }
+        case STATE_TOP:                 return OGRERR_NONE; break;
+        case STATE_DEFAULT:             return OGRERR_NONE; break;
+        case STATE_FEATURE:             return OGRERR_NONE; break;
+        case STATE_PROPERTY:            return dataHandlerAttribute(data, nLen); 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;
+        case STATE_CITYGML_ATTRIBUTE:   return dataHandlerAttribute(data, nLen); break;
+        default:                        return OGRERR_NONE; break;
     }
+}
 
-/* -------------------------------------------------------------------- */
-/*      If we are in the midst of collecting a feature attribute        */
-/*      value, then this must be a complex attribute which we don't     */
-/*      try to collect for now, so just terminate the field             */
-/*      collection.                                                     */
-/* -------------------------------------------------------------------- */
-    if( m_pszCurField != NULL )
+#define PUSH_STATE(val) do { nStackDepth ++; CPLAssert(nStackDepth < STACK_SIZE); stateStack[nStackDepth] = val; } while(0)
+#define POP_STATE()     nStackDepth --
+
+/************************************************************************/
+/*                       startElementBoundedBy()                        */
+/************************************************************************/
+
+OGRErr GMLHandler::startElementBoundedBy(const char *pszName, int nLenName, void* attr )
+{
+    if ( m_nDepth == 2 && strcmp(pszName, "Envelope") == 0 )
     {
-        CPLFree( m_pszCurField );
-        m_pszCurField = NULL;
+        char* pszGlobalSRSName = GetAttributeValue(attr, "srsName");
+        m_poReader->SetGlobalSRSName(pszGlobalSRSName);
+        CPLFree(pszGlobalSRSName);
     }
 
-    if ( m_bInCityGMLGenericAttr )
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                       startElementGeometry()                         */
+/************************************************************************/
+
+OGRErr GMLHandler::startElementGeometry(const char *pszName, int nLenName, void* attr )
+{
+    if( nLenName == 9 && strcmp(pszName, "boundedBy") == 0 )
     {
-        if( strcmp(pszName, "value") == 0 )
-        {
-            CPLFree( m_pszCurField );
-            m_pszCurField = CPLStrdup("");
-        }
+        m_inBoundedByDepth = m_nDepth;
+
+        PUSH_STATE(STATE_BOUNDED_BY);
+
+        return OGRERR_NONE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we are collecting geometry, or if we determine this is a     */
-/*      geometry element then append to the geometry info.              */
-/* -------------------------------------------------------------------- */
-    else if( poState->m_poFeature != NULL &&
-             (m_pszGeometry != NULL
-              || IsGeometryElement( pszName )
-              || (m_bIsAIXM && strcmp( pszName, "ElevatedPoint") == 0)) )
-    {
-        int bReadGeometry;
+    /* Create new XML Element */
+    CPLXMLNode* psCurNode = (CPLXMLNode *) CPLCalloc(sizeof(CPLXMLNode),1);
+    psCurNode->eType = CXT_Element;
+    psCurNode->pszValue = (char*) CPLMalloc( nLenName+1 );
+    memcpy(psCurNode->pszValue, pszName, nLenName+1);
 
-        if( m_pszGeometry == NULL )
-        {
-            /* If the <GeometryElementPath> is defined in the .gfs, use it */
-            /* to read the appropriate geometry element */
-            const char* pszGeometryElement = (poState->m_poFeature) ?
-                    poState->m_poFeature->GetClass()->GetGeometryElement() : NULL;
-            if (pszGeometryElement != NULL)
-                bReadGeometry = strcmp(poState->m_pszPath, pszGeometryElement) == 0;
-            else
-            {
-                /* AIXM special case: for RouteSegment, we only want to read Curve geometries */
-                /* not 'start' and 'end' geometries */
-                if (m_bIsAIXM &&
-                    strcmp(poState->m_poFeature->GetClass()->GetName(), "RouteSegment") == 0)
-                    bReadGeometry = strcmp( pszName, "Curve") == 0;
-                else
-                    bReadGeometry = TRUE;
-            }
-            CPLAssert(m_nGeometryDepth == 0);
-            m_nGeometryDepth = m_nDepth;
-        }
-        else
-            bReadGeometry = TRUE;
+    /* Attach element as the last child of its parent */
+    NodeLastChild& sNodeLastChild = apsXMLNode[apsXMLNode.size()-1];
+    CPLXMLNode* psLastChildParent = sNodeLastChild.psLastChild;
 
-        if (bReadGeometry)
-        {
-            char* pszAttributes = GetAttributes(attr);
-            size_t nLNLenBytes = strlen(pszName);
-
-            /* 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 && strcmp(pszName, "posList") == 0 &&
-                strstr(pszAttributes, "srsDimension") == NULL)
-            {
-                CPLFree(pszAttributes);
-                pszAttributes = CPLStrdup(" srsDimension=\"3\"");
-            }
+    if (psLastChildParent == NULL)
+    {
+        CPLXMLNode* psParent = sNodeLastChild.psNode;
+        if (psParent)
+            psParent->psChild = psCurNode;
+    }
+    else
+    {
+        psLastChildParent->psNext = psCurNode;
+    }
+    sNodeLastChild.psLastChild = psCurNode;
 
-            if( m_nGeomLen + nLNLenBytes + 4 + strlen( pszAttributes ) >
-                m_nGeomAlloc )
-            {
-                m_nGeomAlloc = (size_t) (m_nGeomAlloc * 1.3 + nLNLenBytes + 1000 +
-                                    strlen( pszAttributes ));
-                char* pszNewGeometry = (char *)
-                    VSIRealloc( m_pszGeometry, m_nGeomAlloc);
-                if (pszNewGeometry == NULL)
-                {
-                    CPLFree(pszAttributes);
-                    return CE_Failure;
-                }
-                m_pszGeometry = pszNewGeometry;
-            }
+    /* Add attributes to the element */
+    CPLXMLNode* psLastChildCurNode = AddAttributes(psCurNode, attr);
 
-            strcpy( m_pszGeometry+m_nGeomLen++, "<" );
-            strcpy( m_pszGeometry+m_nGeomLen, pszName );
-            m_nGeomLen += nLNLenBytes;
-            /* saving attributes */
-            strcat( m_pszGeometry + m_nGeomLen, pszAttributes );
-            m_nGeomLen += strlen( pszAttributes );
-            CPLFree(pszAttributes);
-            strcat( m_pszGeometry + (m_nGeomLen++), ">" );
-        }
+    /* 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 &&
+        strcmp(pszName, "posList") == 0 &&
+        CPLGetXMLValue(psCurNode, "srsDimension", NULL) == NULL)
+    {
+        CPLXMLNode* psChild = CPLCreateXMLNode(NULL, CXT_Attribute, "srsDimension");
+        CPLCreateXMLNode(psChild, CXT_Text, "3");
+
+        if (psLastChildCurNode == NULL)
+            psCurNode->psChild = psChild;
+        else
+            psLastChildCurNode->psNext = psChild;
+        psLastChildCurNode = psChild;
     }
 
-    else if (m_nGeometryDepth != 0 && m_nDepth > m_nGeometryDepth)
+    /* Push the element on the stack */
+    NodeLastChild sNewNodeLastChild;
+    sNewNodeLastChild.psNode = psCurNode;
+    sNewNodeLastChild.psLastChild = psLastChildCurNode;
+    apsXMLNode.push_back(sNewNodeLastChild);
+
+    if (m_pszGeometry)
     {
-        ;
+        CPLFree(m_pszGeometry);
+        m_pszGeometry = NULL;
+        m_nGeomAlloc = 0;
+        m_nGeomLen = 0;
     }
 
-    else if( m_bInBoundedBy)
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                    startElementCityGMLGenericAttr()                  */
+/************************************************************************/
+
+OGRErr GMLHandler::startElementCityGMLGenericAttr(const char *pszName, int nLenName, void* attr )
+{
+    if( strcmp(pszName, "value") == 0 )
     {
-        ;
+        if(m_pszCurField)
+        {
+            CPLFree(m_pszCurField);
+            m_pszCurField = NULL;
+            m_nCurFieldLen = m_nCurFieldAlloc = 0;
+        }
+        m_bInCurField = TRUE;
     }
 
+    return OGRERR_NONE;
+}
+/************************************************************************/
+/*                      startElementFeatureAttribute()                  */
+/************************************************************************/
+
+OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenName, void* attr )
+{
+    /* Reset flag */
+    m_bInCurField = FALSE;
+
+    GMLReadState *poState = m_poReader->GetState();
+
 /* -------------------------------------------------------------------- */
-/*      Is it a feature?  If so push a whole new state, and return.     */
+/*      If we are collecting geometry, or if we determine this is a     */
+/*      geometry element then append to the geometry info.              */
 /* -------------------------------------------------------------------- */
-    else if( m_nDepthFeature == 0 &&
-             m_poReader->IsFeatureElement( pszName ) )
+    if( IsGeometryElement( pszName ) )
     {
-        const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
-        if ( pszFilteredClassName != NULL &&
-             strcmp(pszName, pszFilteredClassName) != 0 )
-        {
-            m_bIgnoreFeature = TRUE;
-            m_nDepthFeature = m_nDepth;
-            m_nDepth ++;
+        int bReadGeometry;
 
-            return CE_None;
+        /* 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;
+        else
+        {
+            /* AIXM special case: for RouteSegment, we only want to read Curve geometries */
+            /* not 'start' and 'end' geometries */
+            if (m_bIsAIXM &&
+                strcmp(poState->m_poFeature->GetClass()->GetName(), "RouteSegment") == 0)
+                bReadGeometry = strcmp( pszName, "Curve") == 0;
+            else
+                bReadGeometry = TRUE;
         }
+        if (bReadGeometry)
+        {
+            m_nGeometryDepth = m_nDepth;
 
-        m_bIgnoreFeature = FALSE;
-
-        char* pszFID = GetFID(attr);
-
-        m_poReader->PushFeature( pszName, pszFID);
+            CPLAssert(apsXMLNode.size() == 0);
 
-        CPLFree(pszFID);
+            NodeLastChild sNodeLastChild;
+            sNodeLastChild.psNode = NULL;
+            sNodeLastChild.psLastChild = NULL;
+            apsXMLNode.push_back(sNodeLastChild);
 
-        m_nDepthFeature = m_nDepth;
-        m_nDepth ++;
+            PUSH_STATE(STATE_GEOMETRY);
 
-        return CE_None;
+            return startElementGeometry(pszName, nLenName, attr);
+        }
     }
 
-    else if( strcmp(pszName, "boundedBy") == 0 )
+
+    else if( nLenName == 9 && strcmp(pszName, "boundedBy") == 0 )
     {
-        m_bInBoundedBy = TRUE;
         m_inBoundedByDepth = m_nDepth;
+
+        PUSH_STATE(STATE_BOUNDED_BY);
+
+        return OGRERR_NONE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is it a CityGML generic attribute ?                             */
 /* -------------------------------------------------------------------- */
-    else if( m_poReader->IsCityGMLGenericAttributeElement( pszName, attr ) )
+    else if( m_bIsCityGML &&
+             m_poReader->IsCityGMLGenericAttributeElement( pszName, attr ) )
     {
-        m_bInCityGMLGenericAttr = TRUE;
         CPLFree(m_pszCityGMLGenericAttrName);
         m_pszCityGMLGenericAttrName = GetAttributeValue(attr, "name");
         m_inCityGMLGenericAttrDepth = m_nDepth;
+
+        PUSH_STATE(STATE_CITYGML_ATTRIBUTE);
+
+        return OGRERR_NONE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      If it is (or at least potentially is) a simple attribute,       */
 /*      then start collecting it.                                       */
 /* -------------------------------------------------------------------- */
-    else if( m_poReader->IsAttributeElement( pszName ) )
+    else if( (m_nAttributeIndex =
+                m_poReader->GetAttributeElementIndex( pszName, nLenName )) != -1 )
     {
-        CPLFree( m_pszCurField );
-        m_pszCurField = CPLStrdup("");
+        if(m_pszCurField)
+        {
+            CPLFree(m_pszCurField);
+            m_pszCurField = NULL;
+            m_nCurFieldLen = m_nCurFieldAlloc = 0;
+        }
+        m_bInCurField = TRUE;
         if (m_bReportHref)
         {
             CPLFree(m_pszHref);
@@ -675,247 +794,370 @@ OGRErr GMLHandler::startElement(const char *pszName, void* attr )
         m_pszUom = GetAttributeValue(attr, "uom");
         CPLFree(m_pszValue);
         m_pszValue = GetAttributeValue(attr, "value");
+
+        if (stateStack[nStackDepth] != STATE_PROPERTY)
+        {
+            m_nAttributeDepth = m_nDepth;
+            PUSH_STATE(STATE_PROPERTY);
+        }
+
     }
-    else if( m_bReportHref && m_poReader->IsAttributeElement( CPLSPrintf("%s_href", pszName ) ) )
+    else if( m_bReportHref && (m_nAttributeIndex =
+                m_poReader->GetAttributeElementIndex( CPLSPrintf("%s_href", pszName ),
+                                                      nLenName + 5 )) != -1 )
     {
-        CPLFree( m_pszCurField );
-        m_pszCurField = CPLStrdup("");
+        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");
-    }
 
-/* -------------------------------------------------------------------- */
-/*      Push the element onto the current state's path.                 */
-/* -------------------------------------------------------------------- */
-    poState->PushPath( pszName );
+        if (stateStack[nStackDepth] != STATE_PROPERTY)
+        {
+            m_nAttributeDepth = m_nDepth;
+            PUSH_STATE(STATE_PROPERTY);
+        }
+    }
 
-    m_nDepth ++;
+    poState->PushPath( pszName, nLenName );
 
-    return CE_None;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
-/*                             endElement()                             */
+/*                         startElementTop()                            */
 /************************************************************************/
-OGRErr GMLHandler::endElement(const char* pszName )
+
+OGRErr GMLHandler::startElementTop(const char *pszName, int nLenName, void* attr )
 
 {
-    m_nDepth --;
+    if (strcmp(pszName, "CityModel") == 0 )
+    {
+        m_bIsCityGML = TRUE;
+    }
+    else if (strcmp(pszName, "AIXMBasicMessage") == 0)
+    {
+        m_bIsAIXM = m_bReportHref = TRUE;
+    }
+
+    stateStack[0] = STATE_DEFAULT;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        startElementDefault()                         */
+/************************************************************************/
+
+OGRErr GMLHandler::startElementDefault(const char *pszName, int nLenName, void* attr )
 
-    if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
+{
+/* -------------------------------------------------------------------- */
+/*      Is it a feature?  If so push a whole new state, and return.     */
+/* -------------------------------------------------------------------- */
+    int nClassIndex;
+    if( (nClassIndex = m_poReader->GetFeatureElementIndex( pszName, nLenName )) != -1 )
     {
-        if (m_nDepth == m_nDepthFeature)
+        const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
+        if ( pszFilteredClassName != NULL &&
+             strcmp(pszName, pszFilteredClassName) != 0 )
         {
-             m_bIgnoreFeature = FALSE;
-             m_nDepthFeature = 0;
+            m_nDepthFeature = m_nDepth;
+
+            PUSH_STATE(STATE_IGNORED_FEATURE);
+
+            return OGRERR_NONE;
+        }
+        else
+        {
+            m_poReader->PushFeature( pszName, GetFID(attr), nClassIndex );
+
+            m_nDepthFeature = m_nDepth;
+
+            PUSH_STATE(STATE_FEATURE);
+
+            return OGRERR_NONE;
         }
-        return CE_None;
     }
 
-    GMLReadState *poState = m_poReader->GetState();
+    else if( nLenName == 9 && strcmp(pszName, "boundedBy") == 0 )
+    {
+        m_inBoundedByDepth = m_nDepth;
+
+        PUSH_STATE(STATE_BOUNDED_BY);
+
+        return OGRERR_NONE;
+    }
 
-    if( m_bInBoundedBy && strcmp(pszName, "boundedBy") == 0 &&
-        m_inBoundedByDepth == m_nDepth)
+/* -------------------------------------------------------------------- */
+/*      Push the element onto the current state's path.                 */
+/* -------------------------------------------------------------------- */
+    m_poReader->GetState()->PushPath( pszName, nLenName );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                      endElementIgnoredFeature()                      */
+/************************************************************************/
+
+OGRErr GMLHandler::endElementIgnoredFeature()
+
+{
+    if (m_nDepth == m_nDepthFeature)
     {
-        m_bInBoundedBy = FALSE;
+        POP_STATE();
     }
+    return OGRERR_NONE;
+}
 
-    else if( m_bInCityGMLGenericAttr )
+/************************************************************************/
+/*                         endElementBoundedBy()                        */
+/************************************************************************/
+OGRErr GMLHandler::endElementBoundedBy()
+
+{
+    if( m_inBoundedByDepth == m_nDepth)
     {
-        if( m_pszCityGMLGenericAttrName != NULL && m_pszCurField != NULL )
-        {
-            CPLAssert( poState->m_poFeature != NULL );
+        POP_STATE();
+    }
 
-            m_poReader->SetFeatureProperty( m_pszCityGMLGenericAttrName, m_pszCurField );
-            CPLFree( m_pszCurField );
-            m_pszCurField = NULL;
-            CPLFree(m_pszCityGMLGenericAttrName);
-            m_pszCityGMLGenericAttrName = NULL;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                       ParseAIXMElevationPoint()                      */
+/************************************************************************/
+
+CPLXMLNode* GMLHandler::ParseAIXMElevationPoint(CPLXMLNode *psGML)
+{
+    const char* pszElevation =
+        CPLGetXMLValue( psGML, "elevation", NULL );
+    if (pszElevation)
+    {
+        m_poReader->SetFeaturePropertyDirectly( "elevation",
+                                        CPLStrdup(pszElevation), -1 );
+        const char* pszElevationUnit =
+            CPLGetXMLValue( psGML, "elevation.uom", NULL );
+        if (pszElevationUnit)
+        {
+            m_poReader->SetFeaturePropertyDirectly( "elevation_uom",
+                                            CPLStrdup(pszElevationUnit), -1 );
         }
+    }
 
-        if( m_inCityGMLGenericAttrDepth == m_nDepth )
+    const char* pszGeoidUndulation =
+        CPLGetXMLValue( psGML, "geoidUndulation", NULL );
+    if (pszGeoidUndulation)
+    {
+        m_poReader->SetFeaturePropertyDirectly( "geoidUndulation",
+                                        CPLStrdup(pszGeoidUndulation), -1 );
+        const char* pszGeoidUndulationUnit =
+            CPLGetXMLValue( psGML, "geoidUndulation.uom", NULL );
+        if (pszGeoidUndulationUnit)
         {
-            m_bInCityGMLGenericAttr = FALSE;
+            m_poReader->SetFeaturePropertyDirectly( "geoidUndulation_uom",
+                                            CPLStrdup(pszGeoidUndulationUnit), -1 );
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Is this closing off an attribute value?  We assume so if        */
-/*      we are collecting an attribute value and got to this point.     */
-/*      We don't bother validating that the closing tag matches the     */
-/*      opening tag.                                                    */
-/* -------------------------------------------------------------------- */
-    else if( m_pszCurField != NULL )
+    const char* pszPos =
+                    CPLGetXMLValue( psGML, "pos", NULL );
+    const char* pszCoordinates =
+                CPLGetXMLValue( psGML, "coordinates", NULL );
+    if (pszPos != NULL)
     {
-        CPLAssert( poState->m_poFeature != NULL );
+        char* pszGeometry = CPLStrdup(CPLSPrintf(
+            "<gml:Point><gml:pos>%s</gml:pos></gml:Point>",
+                                                    pszPos));
+        CPLDestroyXMLNode(psGML);
+        psGML = CPLParseXMLString(pszGeometry);
+        CPLFree(pszGeometry);
+    }
+    else if (pszCoordinates != NULL)
+    {
+        char* pszGeometry = CPLStrdup(CPLSPrintf(
+            "<gml:Point><gml:coordinates>%s</gml:coordinates></gml:Point>",
+                                            pszCoordinates));
+        CPLDestroyXMLNode(psGML);
+        psGML = CPLParseXMLString(pszGeometry);
+        CPLFree(pszGeometry);
+    }
+    else
+    {
+        CPLDestroyXMLNode(psGML);
+        psGML = NULL;
+    }
 
-        if ( m_pszHref != NULL && (m_pszCurField == NULL || EQUAL(m_pszCurField, "")))
+    return psGML;
+}
+
+/************************************************************************/
+/*                         endElementGeometry()                         */
+/************************************************************************/
+OGRErr GMLHandler::endElementGeometry()
+
+{
+    if (m_nGeomLen)
+    {
+        CPLXMLNode* psNode = (CPLXMLNode *) CPLCalloc(sizeof(CPLXMLNode),1);
+        psNode->eType = CXT_Text;
+        psNode->pszValue = m_pszGeometry;
+
+        NodeLastChild& sNodeLastChild = apsXMLNode[apsXMLNode.size()-1];
+        CPLXMLNode* psLastChildParent = sNodeLastChild.psLastChild;
+        if (psLastChildParent == NULL)
         {
-            CPLString osPropNameHref = CPLSPrintf("%s_href", poState->m_pszPath);
-            m_poReader->SetFeatureProperty( osPropNameHref, m_pszHref );
+            CPLXMLNode* psParent = sNodeLastChild.psNode;
+            if (psParent)
+                psParent->psChild = psNode;
         }
         else
-        {
-            if (EQUAL(m_pszCurField, "") && m_pszValue != NULL)
-                m_poReader->SetFeatureProperty( poState->m_pszPath, m_pszValue );
-            else
-                m_poReader->SetFeatureProperty( poState->m_pszPath, m_pszCurField );
+            psLastChildParent->psNext = psNode;
+        sNodeLastChild.psLastChild = psNode;
 
-            if (m_pszHref != NULL)
-            {
-                CPLString osPropNameHref = CPLSPrintf("%s_href", poState->m_pszPath);
-                m_poReader->SetFeatureProperty( osPropNameHref, m_pszHref );
-            }
-        }
-        if (m_pszUom != NULL)
+        m_pszGeometry = NULL;
+        m_nGeomAlloc = 0;
+        m_nGeomLen = 0;
+    }
+
+    if( m_nDepth == m_nGeometryDepth )
+    {
+        CPLXMLNode* psInterestNode = apsXMLNode[apsXMLNode.size()-1].psNode;
+
+        /*char* pszXML = CPLSerializeXMLTree(psInterestNode);
+        CPLDebug("GML", "geometry = %s", pszXML);
+        CPLFree(pszXML);*/
+
+        apsXMLNode.pop_back();
+
+        /* AIXM ElevatedPoint. We want to parse this */
+        /* 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 &&
+            strcmp(psInterestNode->pszValue, "ElevatedPoint") == 0 )
         {
-            CPLString osPropNameUom = CPLSPrintf("%s_uom", poState->m_pszPath);
-            m_poReader->SetFeatureProperty( osPropNameUom, m_pszUom );
+            psInterestNode = ParseAIXMElevationPoint(psInterestNode);
         }
 
-        CPLFree( m_pszCurField );
+        if (m_poReader->FetchAllGeometries())
+            m_poReader->GetState()->m_poFeature->AddGeometry(psInterestNode);
+        else
+            m_poReader->GetState()->m_poFeature->SetGeometryDirectly(psInterestNode);
+
+        POP_STATE();
+    }
+
+    apsXMLNode.pop_back();
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                    endElementCityGMLGenericAttr()                    */
+/************************************************************************/
+OGRErr GMLHandler::endElementCityGMLGenericAttr()
+
+{
+    if( m_pszCityGMLGenericAttrName != NULL && m_bInCurField )
+    {
+        m_poReader->SetFeaturePropertyDirectly( m_pszCityGMLGenericAttrName,
+                                        m_pszCurField, -1 );
         m_pszCurField = NULL;
-        CPLFree( m_pszHref );
-        m_pszHref = NULL;
-        CPLFree( m_pszUom );
-        m_pszUom = NULL;
-        CPLFree( m_pszValue );
-        m_pszValue = NULL;
+        m_nCurFieldLen = m_nCurFieldAlloc = 0;
+        m_bInCurField = FALSE;
+        CPLFree(m_pszCityGMLGenericAttrName);
+        m_pszCityGMLGenericAttrName = NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we are collecting Geometry than store it, and consider if    */
-/*      this is the end of the geometry.                                */
-/* -------------------------------------------------------------------- */
-    if( m_pszGeometry != NULL )
+    if( m_inCityGMLGenericAttrDepth == m_nDepth )
     {
-        /* should save attributes too! */
+        POP_STATE();
+    }
 
-        size_t nLNLenBytes = strlen(pszName);
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        endElementAttribute()                         */
+/************************************************************************/
+OGRErr GMLHandler::endElementAttribute()
+
+{
+    GMLReadState *poState = m_poReader->GetState();
 
-        if( m_nGeomLen + nLNLenBytes + 4 > m_nGeomAlloc )
+    if (m_bInCurField)
+    {
+        if (m_pszCurField == NULL)
         {
-            m_nGeomAlloc = (size_t) (m_nGeomAlloc * 1.3 + nLNLenBytes + 1000);
-            char* pszNewGeometry = (char *)
-                VSIRealloc( m_pszGeometry, m_nGeomAlloc);
-            if (pszNewGeometry == NULL)
+            if (m_pszValue != NULL)
             {
-                return CE_Failure;
+                m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(),
+                                                m_pszValue, -1 );
+                m_pszValue = NULL;
             }
-            m_pszGeometry = pszNewGeometry;
+        }
+        else
+        {
+            m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(),
+                                            m_pszCurField,
+                                            m_nAttributeIndex );
+            m_pszCurField = NULL;
         }
 
-        strcat( m_pszGeometry+m_nGeomLen, "</" );
-        strcpy( m_pszGeometry+m_nGeomLen+2, pszName );
-        strcat( m_pszGeometry+m_nGeomLen+nLNLenBytes+2, ">" );
-        m_nGeomLen += nLNLenBytes + 3;
-
-        if( m_nDepth == m_nGeometryDepth )
+        if (m_pszHref != NULL)
         {
-            if( poState->m_poFeature != NULL )
-            {
-                /* AIXM ElevatedPoint. We want to parse this */
-                /* 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 && strcmp(pszName, "ElevatedPoint") == 0 )
-                {
-                    CPLXMLNode *psGML = CPLParseXMLString( m_pszGeometry );
-                    if (psGML)
-                    {
-                        const char* pszElevation =
-                            CPLGetXMLValue( psGML, "elevation", NULL );
-                        if (pszElevation)
-                        {
-                            m_poReader->SetFeatureProperty( "elevation",
-                                                            pszElevation );
-                            const char* pszElevationUnit =
-                                CPLGetXMLValue( psGML, "elevation.uom", NULL );
-                            if (pszElevationUnit)
-                            {
-                                m_poReader->SetFeatureProperty( "elevation_uom",
-                                                             pszElevationUnit );
-                            }
-                        }
-
-                        const char* pszGeoidUndulation =
-                            CPLGetXMLValue( psGML, "geoidUndulation", NULL );
-                        if (pszGeoidUndulation)
-                        {
-                            m_poReader->SetFeatureProperty( "geoidUndulation",
-                                                            pszGeoidUndulation );
-                            const char* pszGeoidUndulationUnit =
-                                CPLGetXMLValue( psGML, "geoidUndulation.uom", NULL );
-                            if (pszGeoidUndulationUnit)
-                            {
-                                m_poReader->SetFeatureProperty( "geoidUndulation_uom",
-                                                             pszGeoidUndulationUnit );
-                            }
-                        }
-
-                        const char* pszPos =
-                                        CPLGetXMLValue( psGML, "pos", NULL );
-                        const char* pszCoordinates =
-                                  CPLGetXMLValue( psGML, "coordinates", NULL );
-                        if (pszPos != NULL)
-                        {
-                            char* pszNewGeometry = CPLStrdup(CPLSPrintf(
-                                "<gml:Point><gml:pos>%s</gml:pos></gml:Point>",
-                                                                      pszPos));
-                            CPLFree(m_pszGeometry);
-                            m_pszGeometry = pszNewGeometry;
-                        }
-                        else if (pszCoordinates != NULL)
-                        {
-                            char* pszNewGeometry = CPLStrdup(CPLSPrintf(
-                                "<gml:Point><gml:coordinates>%s</gml:coordinates></gml:Point>",
-                                                              pszCoordinates));
-                            CPLFree(m_pszGeometry);
-                            m_pszGeometry = pszNewGeometry;
-                        }
-                        else
-                        {
-                            CPLFree(m_pszGeometry);
-                            m_pszGeometry = NULL;
-                        }
-                        CPLDestroyXMLNode( psGML );
-                    }
-                    else
-                    {
-                        CPLFree(m_pszGeometry);
-                        m_pszGeometry = NULL;
-                    }
-                }
-                if (m_pszGeometry)
-                {
-                    if (m_poReader->FetchAllGeometries())
-                        poState->m_poFeature->AddGeometry( m_pszGeometry );
-                    else
-                        poState->m_poFeature->SetGeometryDirectly( m_pszGeometry );
-                }
-            }
-            else
-                CPLFree( m_pszGeometry );
+            CPLString osPropNameHref = poState->osPath + "_href";
+            m_poReader->SetFeaturePropertyDirectly( osPropNameHref, m_pszHref, -1 );
+            m_pszHref = NULL;
+        }
 
-            m_pszGeometry = NULL;
-            m_nGeomAlloc = m_nGeomLen = 0;
+        if (m_pszUom != NULL)
+        {
+            CPLString osPropNameUom = poState->osPath + "_uom";
+            m_poReader->SetFeaturePropertyDirectly( osPropNameUom, m_pszUom, -1 );
+            m_pszUom = NULL;
         }
+
+        m_nCurFieldLen = m_nCurFieldAlloc = 0;
+        m_bInCurField = FALSE;
+        m_nAttributeIndex = -1;
+
+        CPLFree( m_pszValue );
+        m_pszValue = NULL;
     }
 
-    if ( m_nGeometryDepth != 0 && m_nDepth == m_nGeometryDepth )
-        m_nGeometryDepth = 0;
+    poState->PopPath();
+
+    if( m_nAttributeDepth == m_nDepth )
+    {
+        POP_STATE();
+    }
+
+    return OGRERR_NONE;
+}
 
+/************************************************************************/
+/*                          endElementFeature()                         */
+/************************************************************************/
+OGRErr GMLHandler::endElementFeature()
+
+{
 /* -------------------------------------------------------------------- */
 /*      If we are collecting a feature, and this element tag matches    */
 /*      element name for the class, then we have finished the           */
 /*      feature, and we pop the feature read state.                     */
 /* -------------------------------------------------------------------- */
-    if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
-        && strcmp(pszName,
-                 poState->m_poFeature->GetClass()->GetElementName()) == 0 )
+    if( m_nDepth == m_nDepthFeature )
     {
-        m_nDepthFeature = 0;
         m_poReader->PopState();
+
+        POP_STATE();
     }
 
 /* -------------------------------------------------------------------- */
@@ -924,83 +1166,109 @@ OGRErr GMLHandler::endElement(const char* pszName )
 /* -------------------------------------------------------------------- */
     else
     {
-        if( strcmp(pszName,poState->GetLastComponent()) == 0 )
-            poState->PopPath();
-        else
-        {
-            CPLAssert( FALSE );
-        }
+        m_poReader->GetState()->PopPath();
     }
 
-    return CE_None;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
-/*                             characters()                             */
+/*                          endElementDefault()                         */
 /************************************************************************/
+OGRErr GMLHandler::endElementDefault()
 
-OGRErr GMLHandler::dataHandler(const char *data, int nLen)
+{
+    if (m_nDepth > 0)
+        m_poReader->GetState()->PopPath();
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         dataHandlerAttribute()                       */
+/************************************************************************/
+
+OGRErr GMLHandler::dataHandlerAttribute(const char *data, int nLen)
 
 {
     int nIter = 0;
 
-    if( m_pszCurField != NULL )
+    if( m_bInCurField )
     {
-        int     nCurFieldLength = strlen(m_pszCurField);
-
         // Ignore white space
-        if (nCurFieldLength == 0)
+        if (m_nCurFieldLen == 0)
         {
-            while (nIter < nLen &&
-                   ( data[nIter] == ' ' || data[nIter] == 10 || data[nIter]== 13 || data[nIter] == '\t') )
+            while (nIter < nLen)
+            {
+                char ch = data[nIter];
+                if( !(ch == ' ' || ch == 10 || ch == 13 || ch == '\t') )
+                    break;
                 nIter ++;
+            }
         }
 
-        size_t nCharsLen = nLen - nIter;
+        int nCharsLen = nLen - nIter;
 
-        char *pszNewCurField = (char *)
-            VSIRealloc( m_pszCurField,
-                        nCurFieldLength+ nCharsLen +1 );
-        if (pszNewCurField == NULL)
+        if (m_nCurFieldLen + nCharsLen + 1 > m_nCurFieldAlloc)
         {
-            return CE_Failure;
+            m_nCurFieldAlloc = m_nCurFieldAlloc * 4 / 3 + nCharsLen + 1;
+            char *pszNewCurField = (char *)
+                VSIRealloc( m_pszCurField, m_nCurFieldAlloc );
+            if (pszNewCurField == NULL)
+            {
+                return OGRERR_NOT_ENOUGH_MEMORY;
+            }
+            m_pszCurField = pszNewCurField;
         }
-        m_pszCurField = pszNewCurField;
-        memcpy( m_pszCurField + nCurFieldLength, data + nIter, nCharsLen);
-        nCurFieldLength += nCharsLen;
-
-        m_pszCurField[nCurFieldLength] = '\0';
+        memcpy( m_pszCurField + m_nCurFieldLen, data + nIter, nCharsLen);
+        m_nCurFieldLen += nCharsLen;
+        m_pszCurField[m_nCurFieldLen] = '\0';
     }
-    else if( m_pszGeometry != NULL )
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         dataHandlerGeometry()                        */
+/************************************************************************/
+
+OGRErr GMLHandler::dataHandlerGeometry(const char *data, int nLen)
+
+{
+    int nIter = 0;
+
+    // Ignore white space
+    if (m_nGeomLen == 0)
     {
-        // Ignore white space
-        if (m_nGeomLen == 0)
+        while (nIter < nLen)
         {
-            while (nIter < nLen &&
-                   ( data[nIter] == ' ' || data[nIter] == 10 || data[nIter]== 13 || data[nIter] == '\t') )
-                nIter ++;
+            char ch = data[nIter];
+            if( !(ch == ' ' || ch == 10 || ch == 13 || ch == '\t') )
+                break;
+            nIter ++;
         }
+    }
 
-        size_t nCharsLen = nLen - nIter;
-
-        if( m_nGeomLen + nCharsLen + 4 > m_nGeomAlloc )
+    int nCharsLen = nLen - nIter;
+    if (nCharsLen)
+    {
+        if( m_nGeomLen + nCharsLen + 1 > m_nGeomAlloc )
         {
-            m_nGeomAlloc = (size_t) (m_nGeomAlloc * 1.3 + nCharsLen + 1000);
+            m_nGeomAlloc = m_nGeomAlloc * 4 / 3 + nCharsLen + 1;
             char* pszNewGeometry = (char *)
                 VSIRealloc( m_pszGeometry, m_nGeomAlloc);
             if (pszNewGeometry == NULL)
             {
-                return CE_Failure;
+                return OGRERR_NOT_ENOUGH_MEMORY;
             }
             m_pszGeometry = pszNewGeometry;
         }
-
         memcpy( m_pszGeometry+m_nGeomLen, data + nIter, nCharsLen);
         m_nGeomLen += nCharsLen;
         m_pszGeometry[m_nGeomLen] = '\0';
     }
 
-    return CE_None;
+    return OGRERR_NONE;
 }
 
 
@@ -1011,21 +1279,22 @@ OGRErr GMLHandler::dataHandler(const char *data, int nLen)
 int GMLHandler::IsGeometryElement( const char *pszElement )
 
 {
-    return strcmp(pszElement,"Polygon") == 0
-        || strcmp(pszElement,"MultiPolygon") == 0
-        || strcmp(pszElement,"MultiPoint") == 0
-        || strcmp(pszElement,"MultiLineString") == 0
-        || strcmp(pszElement,"MultiSurface") == 0
-        || strcmp(pszElement,"MultiGeometry") == 0
-        || strcmp(pszElement,"GeometryCollection") == 0 /* OGR < 1.8.0 bug... */
-        || strcmp(pszElement,"Point") == 0
-        || strcmp(pszElement,"Curve") == 0
-        || strcmp(pszElement,"MultiCurve") == 0
-        || strcmp(pszElement,"TopoCurve") == 0
-        || strcmp(pszElement,"Surface") == 0
-        || strcmp(pszElement,"TopoSurface") == 0
-        || strcmp(pszElement,"PolygonPatch") == 0
-        || strcmp(pszElement,"LineString") == 0
-        || strcmp(pszElement,"CompositeSurface") == 0
-        || strcmp(pszElement,"Solid") == 0;
+    int nFirst = 0;
+    int nLast = GML_GEOMETRY_TYPE_COUNT- 1;
+    unsigned long nHash = CPLHashSetHashStr(pszElement);
+    do
+    {
+        int nMiddle = (nFirst + nLast) / 2;
+        if (nHash == pasGeometryNames[nMiddle].nHash)
+            return strcmp(pszElement, pasGeometryNames[nMiddle].pszName) == 0;
+        if (nHash < pasGeometryNames[nMiddle].nHash)
+            nLast = nMiddle - 1;
+        else
+            nFirst = nMiddle + 1;
+    } while(nFirst <= nLast);
+
+    if (m_bIsAIXM && strcmp( pszElement, "ElevatedPoint") == 0)
+        return TRUE;
+
+    return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
index 27c06cb..5988768 100644
--- a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlpropertydefn.cpp 21202 2010-12-06 19:51:51Z rouault $
+ * $Id: gmlpropertydefn.cpp 22954 2011-08-19 21:47:19Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLPropertyDefn
@@ -41,9 +41,15 @@ GMLPropertyDefn::GMLPropertyDefn( const char *pszName,
 {
     m_pszName = CPLStrdup( pszName );
     if( pszSrcElement != NULL )
+    {
+        m_nSrcElementLen = strlen( pszSrcElement );
         m_pszSrcElement = CPLStrdup( pszSrcElement );
+    }
     else
+    {
+        m_nSrcElementLen = 0;
         m_pszSrcElement = NULL;
+    }
     m_eType = GMLPT_Untyped;
     m_nWidth = 0; 
     m_nPrecision = 0;
@@ -70,9 +76,15 @@ void GMLPropertyDefn::SetSrcElement( const char *pszSrcElement )
 {
     CPLFree( m_pszSrcElement );
     if( pszSrcElement != NULL )
+    {
+        m_nSrcElementLen = strlen( pszSrcElement );
         m_pszSrcElement = CPLStrdup( pszSrcElement );
+    }
     else
+    {
+        m_nSrcElementLen = 0;
         m_pszSrcElement = NULL;
+    }
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.cpp b/ogr/ogrsf_frmts/gml/gmlreader.cpp
index 10207c9..be4fed2 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.cpp 21390 2011-01-03 22:43:07Z rouault $
+ * $Id: gmlreader.cpp 23647 2011-12-23 22:27:20Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader class.
@@ -31,6 +31,9 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 #include "gmlutils.h"
+#include "gmlreaderp.h"
+#include "cpl_conv.h"
+#include <map>
 
 #define SUPPORT_GEOMETRY
 
@@ -52,13 +55,16 @@ IGMLReader::~IGMLReader()
 /*                  No XERCES or EXPAT Library                          */
 /* ==================================================================== */
 /************************************************************************/
-#if HAVE_XERCES == 0 && !defined(HAVE_EXPAT)
+#if !defined(HAVE_XERCES) && !defined(HAVE_EXPAT)
 
 /************************************************************************/
 /*                          CreateGMLReader()                           */
 /************************************************************************/
 
-IGMLReader *CreateGMLReader()
+IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
+                            int bInvertAxisOrderIfLatLong,
+                            int bConsiderEPSGAsURN,
+                            int bGetSecondaryGeometryOption)
 
 {
     CPLError( CE_Failure, CPLE_AppDefined,
@@ -72,21 +78,26 @@ IGMLReader *CreateGMLReader()
 /*                  With XERCES or EXPAT Library                        */
 /* ==================================================================== */
 /************************************************************************/
-#else /* HAVE_XERCES == 1 or HAVE_EXPAT */
-
-#include "gmlreaderp.h"
-#include "cpl_conv.h"
+#else /* defined(HAVE_XERCES) || defined(HAVE_EXPAT) */
 
 /************************************************************************/
 /*                          CreateGMLReader()                           */
 /************************************************************************/
 
-IGMLReader *CreateGMLReader()
+IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
+                            int bInvertAxisOrderIfLatLong,
+                            int bConsiderEPSGAsURN,
+                            int bGetSecondaryGeometryOption)
 
 {
-    return new GMLReader();
+    return new GMLReader(bUseExpatParserPreferably,
+                         bInvertAxisOrderIfLatLong,
+                         bConsiderEPSGAsURN,
+                         bGetSecondaryGeometryOption);
 }
 
+#endif
+
 int GMLReader::m_bXercesInitialized = FALSE;
 int GMLReader::m_nInstanceCount = 0;
 
@@ -94,9 +105,29 @@ int GMLReader::m_nInstanceCount = 0;
 /*                             GMLReader()                              */
 /************************************************************************/
 
-GMLReader::GMLReader()
+GMLReader::GMLReader(int bUseExpatParserPreferably,
+                     int bInvertAxisOrderIfLatLong,
+                     int bConsiderEPSGAsURN,
+                     int bGetSecondaryGeometryOption)
 
 {
+#ifndef HAVE_XERCES
+    bUseExpatReader = TRUE;
+#else
+    bUseExpatReader = FALSE;
+#ifdef HAVE_EXPAT
+    if(bUseExpatParserPreferably)
+        bUseExpatReader = TRUE;
+#endif
+#endif
+
+#if defined(HAVE_EXPAT) && defined(HAVE_XERCES)
+    if (bUseExpatReader)
+        CPLDebug("GML", "Using Expat reader");
+    else
+        CPLDebug("GML", "Using Xerces reader");
+#endif
+
     m_nInstanceCount++;
     m_nClassCount = 0;
     m_papoClass = NULL;
@@ -104,20 +135,25 @@ GMLReader::GMLReader()
     m_bClassListLocked = FALSE;
 
     m_poGMLHandler = NULL;
-#if HAVE_XERCES == 1
+#ifdef HAVE_XERCES
     m_poSAXReader = NULL;
     m_poCompleteFeature = NULL;
     m_GMLInputSource = NULL;
-#else
+    m_bEOF = FALSE;
+#endif
+#ifdef HAVE_EXPAT
     oParser = NULL;
     ppoFeatureTab = NULL;
     nFeatureTabIndex = 0;
     nFeatureTabLength = 0;
+    nFeatureTabAlloc = 0;
+    pabyBuf = NULL;
 #endif
     fpGML = NULL;
     m_bReadStarted = FALSE;
     
     m_poState = NULL;
+    m_poRecycledState = NULL;
 
     m_pszFilename = NULL;
 
@@ -126,12 +162,19 @@ GMLReader::GMLReader()
     /* A bit experimental. Not publicly advertized. See commented doc in drv_gml.html */
     m_bFetchAllGeometries = CSLTestBoolean(CPLGetConfigOption("GML_FETCH_ALL_GEOMETRIES", "NO"));
 
-    m_bInvertAxisOrderIfLatLong = CSLTestBoolean(CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES"));
+    m_bInvertAxisOrderIfLatLong = bInvertAxisOrderIfLatLong;
+    m_bConsiderEPSGAsURN = bConsiderEPSGAsURN;
+    m_bGetSecondaryGeometryOption = bGetSecondaryGeometryOption;
 
     m_pszGlobalSRSName = NULL;
     m_bCanUseGlobalSRSName = FALSE;
 
     m_pszFilteredClassName = NULL;
+
+    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"));
 }
 
 /************************************************************************/
@@ -147,14 +190,19 @@ GMLReader::~GMLReader()
 
     CleanupParser();
 
+    delete m_poRecycledState;
+
     --m_nInstanceCount;
-#if HAVE_XERCES == 1
+#ifdef HAVE_XERCES
     if( m_nInstanceCount == 0 && m_bXercesInitialized )
     {
         XMLPlatformUtils::Terminate();
         m_bXercesInitialized = FALSE;
     }
 #endif
+#ifdef HAVE_EXPAT
+    CPLFree(pabyBuf);
+#endif
 
     if (fpGML)
         VSIFCloseL(fpGML);
@@ -186,26 +234,6 @@ const char* GMLReader::GetSourceFileName()
     return m_pszFilename;
 }
 
-#ifdef HAVE_EXPAT
-
-static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
-                                    const char **ppszAttr)
-{
-    ((GMLHandler*)pUserData)->startElement(pszName, ppszAttr);
-}
-
-static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
-{
-    ((GMLHandler*)pUserData)->endElement(pszName);
-}
-
-static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
-{
-    ((GMLHandler*)pUserData)->dataHandler(data, nLen);
-}
-
-#endif
-
 /************************************************************************/
 /*                            SetupParser()                             */
 /************************************************************************/
@@ -218,8 +246,41 @@ int GMLReader::SetupParser()
     if (fpGML != NULL)
         VSIFSeekL( fpGML, 0, SEEK_SET );
 
-#if HAVE_XERCES == 1
+    int bRet = -1;
+#ifdef HAVE_EXPAT
+    if (bUseExpatReader)
+        bRet = SetupParserExpat();
+#endif
+
+#ifdef HAVE_XERCES
+    if (!bUseExpatReader)
+        bRet = SetupParserXerces();
+#endif
+    if (bRet < 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "SetupParser(): shouldn't happen");
+        return FALSE;
+    }
+
+    if (!bRet)
+        return FALSE;
+
+    m_bReadStarted = FALSE;
 
+    // Push an empty state.
+    PushState( m_poRecycledState ? m_poRecycledState : new GMLReadState() );
+    m_poRecycledState = NULL;
+
+    return TRUE;
+}
+
+#ifdef HAVE_XERCES
+/************************************************************************/
+/*                        SetupParserXerces()                           */
+/************************************************************************/
+
+int GMLReader::SetupParserXerces()
+{
     if( !m_bXercesInitialized )
     {
         try
@@ -248,13 +309,14 @@ int GMLReader::SetupParser()
     try{
         m_poSAXReader = XMLReaderFactory::createXMLReader();
     
-        m_poGMLHandler = new GMLXercesHandler( this );
+        GMLXercesHandler* poXercesHandler = new GMLXercesHandler( this );
+        m_poGMLHandler = poXercesHandler;
 
-        m_poSAXReader->setContentHandler( m_poGMLHandler );
-        m_poSAXReader->setErrorHandler( m_poGMLHandler );
-        m_poSAXReader->setLexicalHandler( m_poGMLHandler );
-        m_poSAXReader->setEntityResolver( m_poGMLHandler );
-        m_poSAXReader->setDTDHandler( m_poGMLHandler );
+        m_poSAXReader->setContentHandler( poXercesHandler );
+        m_poSAXReader->setErrorHandler( poXercesHandler );
+        m_poSAXReader->setLexicalHandler( poXercesHandler );
+        m_poSAXReader->setEntityResolver( poXercesHandler );
+        m_poSAXReader->setDTDHandler( poXercesHandler );
 
         xmlUriValid = XMLString::transcode("http://xml.org/sax/features/validation");
         xmlUriNS = XMLString::transcode("http://xml.org/sax/features/namespaces");
@@ -293,7 +355,18 @@ int GMLReader::SetupParser()
 
     if (m_GMLInputSource == NULL && fpGML != NULL)
         m_GMLInputSource = new GMLInputSource(fpGML);
-#else
+
+    return TRUE;
+}
+#endif
+
+/************************************************************************/
+/*                        SetupParserExpat()                            */
+/************************************************************************/
+
+#ifdef HAVE_EXPAT
+int GMLReader::SetupParserExpat()
+{
     // Cleanup any old parser.
     if( oParser != NULL )
         CleanupParser();
@@ -301,18 +374,18 @@ int GMLReader::SetupParser()
     oParser = OGRCreateExpatXMLParser();
     m_poGMLHandler = new GMLExpatHandler( this, oParser );
 
-    XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
-    XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
+    XML_SetElementHandler(oParser, GMLExpatHandler::startElementCbk, GMLExpatHandler::endElementCbk);
+    XML_SetCharacterDataHandler(oParser, GMLExpatHandler::dataHandlerCbk);
     XML_SetUserData(oParser, m_poGMLHandler);
-#endif
-
-    m_bReadStarted = FALSE;
 
-    // Push an empty state.
-    PushState( new GMLReadState() );
+    if (pabyBuf == NULL)
+        pabyBuf = (char*)VSIMalloc(PARSER_BUF_SIZE);
+    if (pabyBuf == NULL)
+        return FALSE;
 
     return TRUE;
 }
+#endif
 
 /************************************************************************/
 /*                           CleanupParser()                            */
@@ -321,25 +394,30 @@ int GMLReader::SetupParser()
 void GMLReader::CleanupParser()
 
 {
-#if HAVE_XERCES == 1
-    if( m_poSAXReader == NULL )
+#ifdef HAVE_XERCES
+    if( !bUseExpatReader && m_poSAXReader == NULL )
         return;
-#else
-    if (oParser == NULL )
+#endif
+
+#ifdef HAVE_EXPAT
+    if ( bUseExpatReader && oParser == NULL )
         return;
 #endif
 
     while( m_poState )
         PopState();
 
-#if HAVE_XERCES == 1
+#ifdef HAVE_XERCES
     delete m_poSAXReader;
     m_poSAXReader = NULL;
     delete m_GMLInputSource;
     m_GMLInputSource = NULL;
     delete m_poCompleteFeature;
     m_poCompleteFeature = NULL;
-#else
+    m_bEOF = FALSE;
+#endif
+
+#ifdef HAVE_EXPAT
     if (oParser)
         XML_ParserFree(oParser);
     oParser = NULL;
@@ -350,6 +428,7 @@ void GMLReader::CleanupParser()
     CPLFree(ppoFeatureTab);
     nFeatureTabIndex = 0;
     nFeatureTabLength = 0;
+    nFeatureTabAlloc = 0;
     ppoFeatureTab = NULL;
 
 #endif
@@ -360,7 +439,7 @@ void GMLReader::CleanupParser()
     m_bReadStarted = FALSE;
 }
 
-#if HAVE_XERCES == 1
+#ifdef HAVE_XERCES
 
 GMLBinInputStream::GMLBinInputStream(VSILFILE* fp)
 {
@@ -413,18 +492,21 @@ BinInputStream* GMLInputSource::makeStream() const
     return binInputStream;
 }
 
-#endif
+#endif // HAVE_XERCES
 
 /************************************************************************/
-/*                            NextFeature()                             */
+/*                        NextFeatureXerces()                           */
 /************************************************************************/
 
-#if HAVE_XERCES == 1
-GMLFeature *GMLReader::NextFeature()
+#ifdef HAVE_XERCES
+GMLFeature *GMLReader::NextFeatureXerces()
 
 {
     GMLFeature *poReturn = NULL;
 
+    if (m_bEOF)
+        return NULL;
+
     try
     {
         if( !m_bReadStarted )
@@ -445,6 +527,9 @@ GMLFeature *GMLReader::NextFeature()
                && !m_bStopParsing
                && m_poSAXReader->parseNext( m_oToFill ) ) {}
 
+        if (m_poCompleteFeature == NULL)
+            m_bEOF = TRUE;
+
         poReturn = m_poCompleteFeature;
         m_poCompleteFeature = NULL;
 
@@ -468,8 +553,10 @@ GMLFeature *GMLReader::NextFeature()
 
     return poReturn;
 }
-#else
-GMLFeature *GMLReader::NextFeature()
+#endif
+
+#ifdef HAVE_EXPAT
+GMLFeature *GMLReader::NextFeatureExpat()
 
 {
     if (!m_bReadStarted)
@@ -491,22 +578,19 @@ GMLFeature *GMLReader::NextFeature()
     if (VSIFEofL(fpGML))
         return NULL;
 
-    char aBuf[BUFSIZ];
-
-    CPLFree(ppoFeatureTab);
-    ppoFeatureTab = NULL;
     nFeatureTabLength = 0;
     nFeatureTabIndex = 0;
 
     int nDone;
     do
     {
-        m_poGMLHandler->ResetDataHandlerCounter();
+        /* Reset counter that is used to detect billion laugh attacks */
+        ((GMLExpatHandler*)m_poGMLHandler)->ResetDataHandlerCounter();
 
         unsigned int nLen =
-                (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGML );
+                (unsigned int)VSIFReadL( pabyBuf, 1, PARSER_BUF_SIZE, fpGML );
         nDone = VSIFEofL(fpGML);
-        if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
+        if (XML_Parse(oParser, pabyBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "XML parsing of GML file failed : %s "
@@ -517,7 +601,7 @@ GMLFeature *GMLReader::NextFeature()
             m_bStopParsing = TRUE;
         }
         if (!m_bStopParsing)
-            m_bStopParsing = m_poGMLHandler->HasStoppedParsing();
+            m_bStopParsing = ((GMLExpatHandler*)m_poGMLHandler)->HasStoppedParsing();
 
     } while (!nDone && !m_bStopParsing && nFeatureTabLength == 0);
 
@@ -525,6 +609,22 @@ GMLFeature *GMLReader::NextFeature()
 }
 #endif
 
+GMLFeature *GMLReader::NextFeature()
+{
+#ifdef HAVE_EXPAT
+    if (bUseExpatReader)
+        return NextFeatureExpat();
+#endif
+
+#ifdef HAVE_XERCES
+    if (!bUseExpatReader)
+        return NextFeatureXerces();
+#endif
+
+    CPLError(CE_Failure, CPLE_AppDefined, "NextFeature(): Should not happen");
+    return NULL;
+}
+
 /************************************************************************/
 /*                            PushFeature()                             */
 /*                                                                      */
@@ -536,38 +636,46 @@ GMLFeature *GMLReader::NextFeature()
 /************************************************************************/
 
 void GMLReader::PushFeature( const char *pszElement, 
-                             const char *pszFID )
+                             const char *pszFID,
+                             int nClassIndex )
 
 {
     int iClass;
 
-/* -------------------------------------------------------------------- */
-/*      Find the class of this element.                                 */
-/* -------------------------------------------------------------------- */
-    for( iClass = 0; iClass < GetClassCount(); iClass++ )
+    if( nClassIndex != INT_MAX )
     {
-        if( EQUAL(pszElement,GetClass(iClass)->GetElementName()) )
-            break;
+        iClass = nClassIndex;
     }
-
-/* -------------------------------------------------------------------- */
-/*      Create a new feature class for this element, if there is no     */
-/*      existing class for it.                                          */
-/* -------------------------------------------------------------------- */
-    if( iClass == GetClassCount() )
+    else
     {
-        CPLAssert( !IsClassListLocked() );
+    /* -------------------------------------------------------------------- */
+    /*      Find the class of this element.                                 */
+    /* -------------------------------------------------------------------- */
+        for( iClass = 0; iClass < m_nClassCount; iClass++ )
+        {
+            if( EQUAL(pszElement,m_papoClass[iClass]->GetElementName()) )
+                break;
+        }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create a new feature class for this element, if there is no     */
+    /*      existing class for it.                                          */
+    /* -------------------------------------------------------------------- */
+        if( iClass == m_nClassCount )
+        {
+            CPLAssert( !m_bClassListLocked );
 
-        GMLFeatureClass *poNewClass = new GMLFeatureClass( pszElement );
+            GMLFeatureClass *poNewClass = new GMLFeatureClass( pszElement );
 
-        AddClass( poNewClass );
+            AddClass( poNewClass );
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create a feature of this feature class.  Try to set the fid     */
 /*      if available.                                                   */
 /* -------------------------------------------------------------------- */
-    GMLFeature *poFeature = new GMLFeature( GetClass( iClass ) );
+    GMLFeature *poFeature = new GMLFeature( m_papoClass[iClass] );
     if( pszFID != NULL )
     {
         poFeature->SetFID( pszFID );
@@ -578,7 +686,8 @@ void GMLReader::PushFeature( const char *pszElement,
 /* -------------------------------------------------------------------- */
     GMLReadState *poState;
 
-    poState = new GMLReadState();
+    poState = m_poRecycledState ? m_poRecycledState : new GMLReadState();
+    m_poRecycledState = NULL;
     poState->m_poFeature = poFeature;
     PushState( poState );
 }
@@ -590,62 +699,69 @@ void GMLReader::PushFeature( const char *pszElement,
 /*      GML feature element?                                            */
 /************************************************************************/
 
-int GMLReader::IsFeatureElement( const char *pszElement )
+int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLength )
 
 {
-    CPLAssert( m_poState != NULL );
-
     const char *pszLast = m_poState->GetLastComponent();
-    int        nLen = strlen(pszLast);
-    int        nElementLength = strlen(pszElement);
-
-    if (strcmp(pszLast, "dane") == 0)
-    {
-         /* Polish TBD GML */
-    }
+    size_t      nLenLast = m_poState->GetLastComponentLen();
 
-    /* Begin of OpenLS */
-    else if (strcmp(pszLast, "GeocodeResponseList") == 0 &&
-             strcmp(pszElement, "GeocodedAddress") == 0)
+    if( (nLenLast >= 6 && EQUAL(pszLast+nLenLast-6,"member")) ||
+        (nLenLast >= 7 && EQUAL(pszLast+nLenLast-7,"members")) )
     {
+        /* Default feature name */
     }
-    else if (strcmp(pszLast, "DetermineRouteResponse") == 0)
-    {
-        /* We don't want the children of RouteInstructionsList */
-        /* to be a single feature. We want each RouteInstruction */
-        /* to be a feature */
-        if (strcmp(pszElement, "RouteInstructionsList") == 0)
-            return FALSE;
-    }
-    else if (strcmp(pszElement, "RouteInstruction") == 0 &&
-             strcmp(pszLast, "RouteInstructionsList") == 0)
+    else
     {
-    }
-    /* End of OpenLS */
+        if (nLenLast == 4 && strcmp(pszLast, "dane") == 0)
+        {
+            /* Polish TBD GML */
+        }
 
-    else if (nLen > 6 && strcmp(pszLast + nLen - 6, "_layer") == 0 &&
-             nElementLength > 8 && strcmp(pszElement + nElementLength - 8, "_feature") == 0)
-    {
-        /* GML answer of MapServer WMS GetFeatureInfo request */
-    }
+        /* Begin of OpenLS */
+        else if (nLenLast == 19 && nElementLength == 15 &&
+                 strcmp(pszLast, "GeocodeResponseList") == 0 &&
+                 strcmp(pszElement, "GeocodedAddress") == 0)
+        {
+        }
+        else if (nLenLast == 22 &&
+                 strcmp(pszLast, "DetermineRouteResponse") == 0)
+        {
+            /* We don't want the children of RouteInstructionsList */
+            /* to be a single feature. We want each RouteInstruction */
+            /* to be a feature */
+            if (strcmp(pszElement, "RouteInstructionsList") == 0)
+                return -1;
+        }
+        else if (nElementLength == 16 && nLenLast == 21 &&
+                 strcmp(pszElement, "RouteInstruction") == 0 &&
+                 strcmp(pszLast, "RouteInstructionsList") == 0)
+        {
+        }
+        /* End of OpenLS */
 
-    else if( nLen < 6 || !(EQUAL(pszLast+nLen-6,"member") ||
-                      EQUAL(pszLast+nLen-7,"members")) )
-        return FALSE;
+        else if (nLenLast > 6 && strcmp(pszLast + nLenLast - 6, "_layer") == 0 &&
+                 nElementLength > 8 && strcmp(pszElement + nElementLength - 8, "_feature") == 0)
+        {
+            /* GML answer of MapServer WMS GetFeatureInfo request */
+        }
+        else
+            return -1;
+    }
 
     // If the class list isn't locked, any element that is a featureMember
     // will do. 
-    if( !IsClassListLocked() )
-        return TRUE;
+    if( !m_bClassListLocked )
+        return INT_MAX;
 
     // otherwise, find a class with the desired element name.
-    for( int i = 0; i < GetClassCount(); i++ )
+    for( int i = 0; i < m_nClassCount; i++ )
     {
-        if( EQUAL(pszElement,GetClass(i)->GetElementName()) )
-            return TRUE;
+        if( nElementLength == (int)m_papoClass[i]->GetElementNameLen() &&
+            memcmp(pszElement,m_papoClass[i]->GetElementName(), nElementLength) == 0 )
+            return i;
     }
 
-    return FALSE;
+    return -1;
 }
 
 /************************************************************************/
@@ -660,9 +776,6 @@ int GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* a
         strcmp(pszElement, "doubleAttribute") != 0 )
         return FALSE;
 
-    if( m_poState->m_poFeature == NULL )
-        return FALSE;
-
     char* pszVal = m_poGMLHandler->GetAttributeValue(attr, "name");
     if (pszVal == NULL)
         return FALSE;
@@ -691,40 +804,32 @@ int GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* a
 }
 
 /************************************************************************/
-/*                         IsAttributeElement()                         */
+/*                       GetAttributeElementIndex()                     */
 /************************************************************************/
 
-int GMLReader::IsAttributeElement( const char *pszElement )
+int GMLReader::GetAttributeElementIndex( const char *pszElement, int nLen )
 
 {
-    if( m_poState->m_poFeature == NULL )
-        return FALSE;
-
     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
 
     // If the schema is not yet locked, then any simple element
     // is potentially an attribute.
     if( !poClass->IsSchemaLocked() )
-        return TRUE;
+        return INT_MAX;
 
     // Otherwise build the path to this element into a single string
     // and compare against known attributes.
-    CPLString osElemPath;
-
     if( m_poState->m_nPathLength == 0 )
-        osElemPath = pszElement;
+        return poClass->GetPropertyIndexBySrcElement(pszElement, nLen);
     else
     {
-        osElemPath = m_poState->m_pszPath;
-        osElemPath += "|";
-        osElemPath += pszElement;
+        int nFullLen = nLen + m_poState->osPath.size() + 1;
+        osElemPath.reserve(nFullLen);
+        osElemPath.assign(m_poState->osPath);
+        osElemPath.append(1, '|');
+        osElemPath.append(pszElement, nLen);
+        return poClass->GetPropertyIndexBySrcElement(osElemPath.c_str(), nFullLen);
     }
-
-    for( int i = 0; i < poClass->GetPropertyCount(); i++ )
-        if( strcmp(poClass->GetProperty(i)->GetSrcElement(),osElemPath) == 0 )
-            return TRUE;
-
-    return FALSE;
 }
 
 /************************************************************************/
@@ -736,18 +841,25 @@ void GMLReader::PopState()
 {
     if( m_poState != NULL )
     {
-#if HAVE_XERCES == 1
-        if( m_poState->m_poFeature != NULL && m_poCompleteFeature == NULL )
+#ifdef HAVE_XERCES
+        if( !bUseExpatReader && m_poState->m_poFeature != NULL &&
+            m_poCompleteFeature == NULL )
         {
             m_poCompleteFeature = m_poState->m_poFeature;
             m_poState->m_poFeature = NULL;
         }
-#else
-        if ( m_poState->m_poFeature != NULL )
+#endif
+
+#ifdef HAVE_EXPAT
+        if ( bUseExpatReader && m_poState->m_poFeature != NULL )
         {
-            ppoFeatureTab = (GMLFeature**)
-                    CPLRealloc(ppoFeatureTab,
-                                sizeof(GMLFeature*) * (nFeatureTabLength + 1));
+            if (nFeatureTabLength >= nFeatureTabAlloc)
+            {
+                nFeatureTabAlloc = nFeatureTabLength * 4 / 3 + 16;
+                ppoFeatureTab = (GMLFeature**)
+                        CPLRealloc(ppoFeatureTab,
+                                    sizeof(GMLFeature*) * (nFeatureTabAlloc));
+            }
             ppoFeatureTab[nFeatureTabLength] = m_poState->m_poFeature;
             nFeatureTabLength++;
 
@@ -759,7 +871,9 @@ void GMLReader::PopState()
 
         poParent = m_poState->m_poParentState;
         
-        delete m_poState;
+        delete m_poRecycledState;
+        m_poRecycledState = m_poState;
+        m_poRecycledState->Reset();
         m_poState = poParent;
     }
 }
@@ -837,16 +951,16 @@ void GMLReader::ClearClasses()
 }
 
 /************************************************************************/
-/*                         SetFeatureProperty()                         */
+/*                     SetFeaturePropertyDirectly()                     */
 /*                                                                      */
 /*      Set the property value on the current feature, adding the       */
 /*      property name to the GMLFeatureClass if required.               */
-/*      Eventually this function may also "refine" the property         */
-/*      type based on what is encountered.                              */
+/*      The pszValue ownership is passed to this function.              */
 /************************************************************************/
 
-void GMLReader::SetFeatureProperty( const char *pszElement, 
-                                    const char *pszValue )
+void GMLReader::SetFeaturePropertyDirectly( const char *pszElement, 
+                                            char *pszValue,
+                                            int iPropertyIn )
 
 {
     GMLFeature *poFeature = GetState()->m_poFeature;
@@ -860,54 +974,64 @@ void GMLReader::SetFeatureProperty( const char *pszElement,
     GMLFeatureClass *poClass = poFeature->GetClass();
     int      iProperty;
 
-    for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
+    int nPropertyCount = poClass->GetPropertyCount();
+    if (iPropertyIn >= 0 && iPropertyIn < nPropertyCount)
     {
-        if( strcmp(poClass->GetProperty( iProperty )->GetSrcElement(),
-                  pszElement ) == 0 )
-            break;
+        iProperty = iPropertyIn;
     }
-    
-    if( iProperty == poClass->GetPropertyCount() )
+    else
     {
-        if( poClass->IsSchemaLocked() )
+        for( iProperty=0; iProperty < nPropertyCount; iProperty++ )
         {
-            CPLDebug("GML","Encountered property missing from class schema.");
-            return;
+            if( strcmp(poClass->GetProperty( iProperty )->GetSrcElement(),
+                    pszElement ) == 0 )
+                break;
         }
 
-        CPLString osFieldName;
-        
-        if( strchr(pszElement,'|') == NULL )
-            osFieldName = pszElement;
-        else
+        if( iProperty == nPropertyCount )
         {
-            osFieldName = strrchr(pszElement,'|') + 1;
-            if( poClass->GetPropertyIndex(osFieldName) != -1 )
+            if( poClass->IsSchemaLocked() )
+            {
+                CPLDebug("GML","Encountered property missing from class schema.");
+                CPLFree(pszValue);
+                return;
+            }
+
+            CPLString osFieldName;
+
+            if( strchr(pszElement,'|') == NULL )
                 osFieldName = pszElement;
-        }
+            else
+            {
+                osFieldName = strrchr(pszElement,'|') + 1;
+                if( poClass->GetPropertyIndex(osFieldName) != -1 )
+                    osFieldName = pszElement;
+            }
 
-        // Does this conflict with an existing property name? 
-        while( poClass->GetProperty(osFieldName) != NULL )
-        {
-            osFieldName += "_";
-        }
+            // Does this conflict with an existing property name?
+            while( poClass->GetProperty(osFieldName) != NULL )
+            {
+                osFieldName += "_";
+            }
 
-        GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);
+            GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);
 
-        if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
-            poPDefn->SetType( GMLPT_String );
+            if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
+                poPDefn->SetType( GMLPT_String );
 
-        if (poClass->AddProperty( poPDefn ) < 0)
-        {
-            delete poPDefn;
-            return;
+            if (poClass->AddProperty( poPDefn ) < 0)
+            {
+                delete poPDefn;
+                CPLFree(pszValue);
+                return;
+            }
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set the property                                                */
 /* -------------------------------------------------------------------- */
-    poFeature->SetProperty( iProperty, pszValue );
+    poFeature->SetPropertyDirectly( iProperty, pszValue );
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to update the property type?                         */
@@ -947,7 +1071,7 @@ int GMLReader::LoadClasses( const char *pszFile )
     }
 
     VSIFSeekL( fp, 0, SEEK_END );
-    nLength = VSIFTellL( fp );
+    nLength = (int) VSIFTellL( fp );
     VSIFSeekL( fp, 0, SEEK_SET );
 
     pszWholeText = (char *) VSIMalloc(nLength+1);
@@ -1004,6 +1128,10 @@ int GMLReader::LoadClasses( const char *pszFile )
         return FALSE;
     }
 
+    const char* pszSequentialLayers = CPLGetXMLValue(psRoot, "SequentialLayers", NULL);
+    if (pszSequentialLayers)
+        m_bSequentialLayers = CSLTestBoolean(pszSequentialLayers);
+
 /* -------------------------------------------------------------------- */
 /*      Extract feature classes for all definitions found.              */
 /* -------------------------------------------------------------------- */
@@ -1056,11 +1184,15 @@ int GMLReader::SaveClasses( const char *pszFile )
 
     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
 
-    for( int iClass = 0; iClass < GetClassCount(); iClass++ )
+    if (m_bSequentialLayers != -1 && m_nClassCount > 1)
     {
-        GMLFeatureClass *poClass = GetClass( iClass );
-        
-        CPLAddXMLChild( psRoot, poClass->SerializeToXML() );
+        CPLCreateXMLElementAndValue( psRoot, "SequentialLayers",
+                                     m_bSequentialLayers ? "true" : "false" );
+    }
+
+    for( int iClass = 0; iClass < m_nClassCount; iClass++ )
+    {
+        CPLAddXMLChild( psRoot, m_papoClass[iClass]->SerializeToXML() );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1111,20 +1243,48 @@ int GMLReader::PrescanForSchema( int bGetExtents )
 
     m_bCanUseGlobalSRSName = TRUE;
 
+    std::map<GMLFeatureClass*, int> osMapCountFeatureWithoutGeometry;
+    GMLFeatureClass *poLastClass = NULL;
+
+    m_bSequentialLayers = TRUE;
+
+    void* hCacheSRS = GML_BuildOGRGeometryFromList_CreateCache();
+
+    std::string osWork;
+
     while( (poFeature = NextFeature()) != NULL )
     {
         GMLFeatureClass *poClass = poFeature->GetClass();
 
+        if (poLastClass != NULL && poClass != poLastClass &&
+            poClass->GetFeatureCount() != -1)
+            m_bSequentialLayers = FALSE;
+        poLastClass = poClass;
+
         if( poClass->GetFeatureCount() == -1 )
             poClass->SetFeatureCount( 1 );
         else
             poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
 
+        const CPLXMLNode* const * papsGeometry = poFeature->GetGeometryList();
+        if (papsGeometry[0] == NULL)
+        {
+            std::map<GMLFeatureClass*, int>::iterator oIter =
+                osMapCountFeatureWithoutGeometry.find(poClass);
+            if (oIter == osMapCountFeatureWithoutGeometry.end())
+                osMapCountFeatureWithoutGeometry[poClass] = 1;
+            else
+                oIter->second ++;
+        }
+
+
 #ifdef SUPPORT_GEOMETRY
         if( bGetExtents )
         {
             OGRGeometry *poGeometry = GML_BuildOGRGeometryFromList(
-                poFeature->GetGeometryList(), TRUE, m_bInvertAxisOrderIfLatLong, NULL);
+                papsGeometry, TRUE, m_bInvertAxisOrderIfLatLong,
+                NULL, m_bConsiderEPSGAsURN, m_bGetSecondaryGeometryOption, 
+                hCacheSRS, m_bFaceHoleNegative );
 
             if( poGeometry != NULL )
             {
@@ -1133,11 +1293,12 @@ int GMLReader::PrescanForSchema( int bGetExtents )
                 OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
                     poClass->GetGeometryType();
 
-                char* pszSRSName = GML_ExtractSrsNameFromGeometry(poFeature->GetGeometryList());
+                const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry,
+                                                                        osWork,
+                                                                        m_bConsiderEPSGAsURN);
                 if (pszSRSName != NULL)
                     m_bCanUseGlobalSRSName = FALSE;
                 poClass->MergeSRSName(pszSRSName);
-                CPLFree(pszSRSName);
 
                 // Merge geometry type into layer.
                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
@@ -1177,6 +1338,8 @@ int GMLReader::PrescanForSchema( int bGetExtents )
         delete poFeature;
     }
 
+    GML_BuildOGRGeometryFromList_DestroyCache(hCacheSRS);
+
     for( int i = 0; i < m_nClassCount; i++ )
     {
         GMLFeatureClass *poClass = m_papoClass[i];
@@ -1212,11 +1375,19 @@ int GMLReader::PrescanForSchema( int bGetExtents )
                 }
             }
         }
+
+        std::map<GMLFeatureClass*, int>::iterator oIter =
+                osMapCountFeatureWithoutGeometry.find(poClass);
+        if (oIter != osMapCountFeatureWithoutGeometry.end() &&
+            oIter->second == poClass->GetFeatureCount())
+        {
+            poClass->SetGeometryType(wkbNone);
+        }
     }
 
     CleanupParser();
 
-    return GetClassCount() > 0;
+    return m_nClassCount > 0;
 }
 
 /************************************************************************/
@@ -1237,7 +1408,18 @@ void GMLReader::ResetReading()
 void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
 {
     if (m_pszGlobalSRSName == NULL && pszGlobalSRSName != NULL)
-        m_pszGlobalSRSName = CPLStrdup(pszGlobalSRSName);
+    {
+        if (strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
+            m_bConsiderEPSGAsURN)
+        {
+            m_pszGlobalSRSName = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s",
+                                                      pszGlobalSRSName+5));
+        }
+        else
+        {
+            m_pszGlobalSRSName = CPLStrdup(pszGlobalSRSName);
+        }
+    }
 }
 
 /************************************************************************/
@@ -1250,6 +1432,3 @@ int GMLReader::SetFilteredClassName(const char* pszClassName)
     m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
     return TRUE;
 }
-
-#endif /* HAVE_XERCES == 1 or HAVE_EXPAT */
-
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.h b/ogr/ogrsf_frmts/gml/gmlreader.h
index 90505e6..c38b68f 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.h
+++ b/ogr/ogrsf_frmts/gml/gmlreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.h 21390 2011-01-03 22:43:07Z rouault $
+ * $Id: gmlreader.h 23547 2011-12-12 16:29:27Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Public Declarations for OGR free GML Reader code.
@@ -33,6 +33,8 @@
 #include "cpl_port.h"
 #include "cpl_minixml.h"
 
+#include <vector>
+
 typedef enum {
     GMLPT_Untyped = 0,
     GMLPT_String = 1,
@@ -52,6 +54,7 @@ typedef struct
 {
     int     nSubProperties;
     char**  papszSubProperties;
+    char*   aszSubProperties[2]; /* Optimization in the case of nSubProperties == 1 */
 } GMLProperty;
 
 class CPL_DLL GMLPropertyDefn
@@ -61,6 +64,7 @@ class CPL_DLL GMLPropertyDefn
     int               m_nWidth;
     int               m_nPrecision;
     char             *m_pszSrcElement;
+    size_t            m_nSrcElementLen;
     int               m_nIndex;
 
 public:
@@ -73,13 +77,14 @@ public:
     GMLPropertyType GetType() const { return m_eType; } 
     void        SetType( GMLPropertyType eType ) { m_eType = eType; }
     void        SetWidth( int nWidth) { m_nWidth = nWidth; }
-    int         GetWidth() { return m_nWidth; }
+    int         GetWidth() const { return m_nWidth; }
     void        SetPrecision( int nPrecision) { m_nPrecision = nPrecision; }
-    int         GetPrecision() { return m_nPrecision; }
+    int         GetPrecision() const { return m_nPrecision; }
     void        SetSrcElement( const char *pszSrcElement );
-    const char *GetSrcElement() { return m_pszSrcElement; }
+    const char *GetSrcElement() const { return m_pszSrcElement; }
+    size_t      GetSrcElementLen() const { return m_nSrcElementLen; }
     void        SetAttributeIndex( int nIndex ) { m_nIndex = nIndex; }
-    int         GetAttributeIndex() { return m_nIndex; }
+    int         GetAttributeIndex() const { return m_nIndex; }
 
     void        AnalysePropertyValue( const GMLProperty* psGMLProperty );
 };
@@ -91,6 +96,8 @@ class CPL_DLL GMLFeatureClass
 {
     char        *m_pszName;
     char        *m_pszElementName;
+    int          n_nNameLen;
+    int          n_nElementNameLen;
     char        *m_pszGeometryElement;
     int         m_nPropertyCount;
     GMLPropertyDefn **m_papoProperty;
@@ -118,6 +125,7 @@ public:
            ~GMLFeatureClass();
 
     const char *GetElementName() const;
+    size_t      GetElementNameLen() const;
     void        SetElementName( const char *pszElementName );
 
     const char *GetGeometryElement() const { return m_pszGeometryElement; }
@@ -129,6 +137,7 @@ public:
     int GetPropertyIndex( const char *pszName ) const;
     GMLPropertyDefn *GetProperty( const char *pszName ) const 
         { return GetProperty( GetPropertyIndex(pszName) ); }
+    int         GetPropertyIndexBySrcElement( const char *pszElement, int nLen ) const;
 
     int         AddProperty( GMLPropertyDefn * );
 
@@ -171,30 +180,26 @@ class CPL_DLL GMLFeature
     int              m_nPropertyCount;
     GMLProperty     *m_pasProperties;
 
-    char           **m_papszGeometryList;
+    int              m_nGeometryCount;
+    CPLXMLNode     **m_papsGeometry; /* NULL-terminated. Alias to m_apsGeometry if m_nGeometryCount <= 1 */
+    CPLXMLNode      *m_apsGeometry[2]; /* NULL-terminated */
 
     // string list of named non-schema properties - used by NAS driver.
-    char           **m_papszOBProperties; 
-    
+    char           **m_papszOBProperties;
+
 public:
                     GMLFeature( GMLFeatureClass * );
                    ~GMLFeature();
 
     GMLFeatureClass*GetClass() const { return m_poClass; }
 
-    void            SetGeometryDirectly( char * );
-    const char     *GetGeometry() const { return (m_papszGeometryList) ? m_papszGeometryList[0] : NULL; }
+    void            SetGeometryDirectly( CPLXMLNode* psGeom );
+    void            AddGeometry( CPLXMLNode* psGeom );
+    const CPLXMLNode* const * GetGeometryList() const { return m_papsGeometry; }
 
-    void            AddGeometry( char * );
-    char**          GetGeometryList() { return m_papszGeometryList; }
+    void            SetPropertyDirectly( int i, char *pszValue );
 
-    void            SetProperty( int i, const char *pszValue );
-    void            SetProperty( const char *pszName, const char *pszValue )
-        { SetProperty( m_poClass->GetPropertyIndex(pszName), pszValue ); }
-
-    const GMLProperty*GetProperty( int i ) const;
-    const GMLProperty*GetProperty( const char *pszName ) const
-        { return GetProperty( m_poClass->GetPropertyIndex(pszName) ); }
+    const GMLProperty*GetProperty( int i ) const { return (i < m_nPropertyCount) ? &m_pasProperties[i] : NULL; }
 
     const char      *GetFID() const { return m_pszFID; }
     void             SetFID( const char *pszFID );
@@ -239,7 +244,12 @@ public:
                                 char **papszSkip = NULL,
                                 const int bStrict = FALSE ) = 0;
 
+    virtual int  HugeFileResolver( const char *pszFile,
+                                   int pbSqlitIsTempFile,
+                                   int iSqliteCacheMB ) = 0;
+
     virtual int PrescanForSchema( int bGetExtents = TRUE ) = 0;
+    virtual int PrescanForTemplate( void ) = 0;
 
     virtual int HasStoppedParsing() = 0;
 
@@ -248,9 +258,14 @@ public:
 
     virtual int SetFilteredClassName(const char* pszClassName) = 0;
     virtual const char* GetFilteredClassName() = 0;
+
+    virtual int IsSequentialLayers() const { return FALSE; }
 };
 
-IGMLReader *CreateGMLReader();
+IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
+                            int bInvertAxisOrderIfLatLong,
+                            int bConsiderEPSGAsURN,
+                            int bGetSecondaryGeometryOption);
 
 
 #endif /* _GMLREADER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlreaderp.h b/ogr/ogrsf_frmts/gml/gmlreaderp.h
index 2aa6003..c725e39 100644
--- a/ogr/ogrsf_frmts/gml/gmlreaderp.h
+++ b/ogr/ogrsf_frmts/gml/gmlreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreaderp.h 21390 2011-01-03 22:43:07Z rouault $
+ * $Id: gmlreaderp.h 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Private Declarations for OGR free GML Reader code.
@@ -34,29 +34,85 @@
 #include "ogr_api.h"
 #include "cpl_vsi.h"
 
+#include <string>
+#include <vector>
+
+#define PARSER_BUF_SIZE (10*8192)
+
 class GMLReader;
 
+typedef struct _GeometryNamesStruct GeometryNamesStruct;
+
+/************************************************************************/
+/*                        GFSTemplateList                               */
+/************************************************************************/
+
+class GFSTemplateItem;
+
+class GFSTemplateList
+{
+private:
+    int             m_bSequentialLayers;
+    GFSTemplateItem *pFirst;
+    GFSTemplateItem *pLast;
+    GFSTemplateItem *Insert( const char *pszName );
+public:
+                    GFSTemplateList( void );
+                    ~GFSTemplateList();
+    void            Update( const char *pszName, int bHasGeom );
+    GFSTemplateItem *GetFirst() { return pFirst; }
+    int             HaveSequentialLayers() { return m_bSequentialLayers; }
+    int             GetClassCount();
+};
+
+void gmlUpdateFeatureClasses ( GFSTemplateList *pCC,
+                               GMLReader *pReader,
+                               int *pbSequentialLayers );
+
 /************************************************************************/
 /*                              GMLHandler                              */
 /************************************************************************/
+
+#define STACK_SIZE 5
+
+typedef enum
+{
+    STATE_TOP,
+    STATE_DEFAULT,
+    STATE_FEATURE,
+    STATE_PROPERTY,
+    STATE_GEOMETRY,
+    STATE_IGNORED_FEATURE,
+    STATE_BOUNDED_BY,
+    STATE_CITYGML_ATTRIBUTE
+} HandlerState;
+
+typedef struct
+{
+    CPLXMLNode* psNode;
+    CPLXMLNode* psLastChild;
+} NodeLastChild;
+
 class GMLHandler
 {
-    char       *m_pszCurField;
+    char      *m_pszCurField;
+    size_t     m_nCurFieldAlloc;
+    size_t     m_nCurFieldLen;
+    int        m_bInCurField;
+    int        m_nAttributeIndex;
+    int        m_nAttributeDepth;
 
-    char       *m_pszGeometry;
-    size_t     m_nGeomAlloc;
-    size_t     m_nGeomLen;
 
+    char      *m_pszGeometry;
+    int        m_nGeomAlloc;
+    int        m_nGeomLen;
     int        m_nGeometryDepth;
 
     int        m_nDepth;
     int        m_nDepthFeature;
-    int        m_bIgnoreFeature;
 
-    int        m_bInBoundedBy;
     int        m_inBoundedByDepth;
 
-    int        m_bInCityGMLGenericAttr;
     char      *m_pszCityGMLGenericAttrName;
     int        m_inCityGMLGenericAttrDepth;
     int        m_bIsCityGML;
@@ -67,25 +123,60 @@ class GMLHandler
     char      *m_pszUom;
     char      *m_pszValue;
 
+    GeometryNamesStruct* pasGeometryNames;
+
+    std::vector<NodeLastChild> apsXMLNode;
+
+    OGRErr     startElementTop(const char *pszName, int nLenName, void* attr);
+
+    OGRErr     endElementIgnoredFeature();
+
+    OGRErr     startElementBoundedBy(const char *pszName, int nLenName, void* attr);
+    OGRErr     endElementBoundedBy();
+
+    OGRErr     startElementFeatureAttribute(const char *pszName, int nLenName, void* attr);
+    OGRErr     endElementFeature();
+
+    OGRErr     startElementCityGMLGenericAttr(const char *pszName, int nLenName, void* attr);
+    OGRErr     endElementCityGMLGenericAttr();
+
+    OGRErr     startElementGeometry(const char *pszName, int nLenName, void* attr);
+    CPLXMLNode* ParseAIXMElevationPoint(CPLXMLNode*);
+    OGRErr     endElementGeometry();
+    OGRErr     dataHandlerGeometry(const char *data, int nLen);
+
+    OGRErr     endElementAttribute();
+    OGRErr     dataHandlerAttribute(const char *data, int nLen);
+
+    OGRErr     startElementDefault(const char *pszName, int nLenName, void* attr);
+    OGRErr     endElementDefault();
+
 protected:
     GMLReader  *m_poReader;
 
+    int              nStackDepth;
+    HandlerState     stateStack[STACK_SIZE];
+
+    std::string      osFID;
+    virtual const char* GetFID(void* attr) = 0;
+
+    virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr) = 0;
+
+    OGRErr      startElement(const char *pszName, int nLenName, void* attr);
+    OGRErr      endElement();
+    OGRErr      dataHandler(const char *data, int nLen);
+
+    int         IsGeometryElement( const char *pszElement );
+
 public:
     GMLHandler( GMLReader *poReader );
     virtual ~GMLHandler();
 
-    virtual OGRErr      startElement(const char *pszName, void* attr);
-    virtual OGRErr      endElement(const char *pszName);
-    virtual OGRErr      dataHandler(const char *data, int nLen);
-    virtual char*       GetFID(void* attr) = 0;
-    virtual char*       GetAttributes(void* attr) = 0;
     virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName) = 0;
-
-    int         IsGeometryElement( const char *pszElement );
 };
 
 
-#if HAVE_XERCES == 1
+#if defined(HAVE_XERCES)
 
 // This works around problems with math.h on some platforms #defining INFINITY
 #ifdef INFINITY
@@ -188,12 +279,15 @@ public:
 
     void startEntity (const XMLCh *const name);
 
-    virtual char*       GetFID(void* attr);
-    virtual char*       GetAttributes(void* attr);
+    virtual const char* GetFID(void* attr);
+    virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr);
     virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName);
 };
 
-#elif defined(HAVE_EXPAT)
+#endif
+
+
+#if defined(HAVE_EXPAT)
 
 #include "ogr_expat.h"
 
@@ -209,18 +303,20 @@ class GMLExpatHandler : public GMLHandler
 public:
     GMLExpatHandler( GMLReader *poReader, XML_Parser oParser );
 
-    virtual OGRErr      startElement(const char *pszName, void* attr);
-    virtual OGRErr      endElement(const char *pszName);
-    virtual OGRErr      dataHandler(const char *data, int nLen);
-
     int         HasStoppedParsing() { return m_bStopParsing; }
 
     void        ResetDataHandlerCounter() { m_nDataHandlerCounter = 0; }
-    int         GetDataHandlerCounter() { return m_nDataHandlerCounter; }
 
-    virtual char*       GetFID(void* attr);
-    virtual char*       GetAttributes(void* attr);
+    virtual const char* GetFID(void* attr);
+    virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr);
     virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName);
+
+    static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
+                                        const char **ppszAttr);
+
+    static void XMLCALL endElementCbk(void *pUserData, const char *pszName);
+
+    static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen);
 };
 
 #endif
@@ -231,26 +327,31 @@ public:
 
 class GMLReadState
 {
-    void        RebuildPath();
+    std::vector<std::string> aosPathComponents;
 
 public:
     GMLReadState();
     ~GMLReadState();
 
-    void        PushPath( const char *pszElement );
+    void        PushPath( const char *pszElement, int nLen = -1 );
     void        PopPath();
 
-    int         MatchPath( const char *pszPathInput );
-    const char  *GetPath() const { return m_pszPath; }
-    const char  *GetLastComponent() const;
+    const char  *GetLastComponent() const {
+        return ( m_nPathLength == 0 ) ? "" : aosPathComponents[m_nPathLength-1].c_str();
+    }
+
+
+    size_t GetLastComponentLen() const {
+        return ( m_nPathLength == 0 ) ? 0: aosPathComponents[m_nPathLength-1].size();
+    }
+
+    void        Reset();
 
     GMLFeature  *m_poFeature;
     GMLReadState *m_poParentState;
 
-    char        *m_pszPath; // element path ... | as separator.
-
-    int         m_nPathLength;
-    char        **m_papszPathComponents;
+    std::string  osPath; // element path ... | as separator.
+    int          m_nPathLength;
 };
 
 /************************************************************************/
@@ -269,23 +370,36 @@ private:
 
     char          *m_pszFilename;
 
-#if HAVE_XERCES == 1
-    GMLXercesHandler    *m_poGMLHandler;
+    int            bUseExpatReader;
+
+    GMLHandler    *m_poGMLHandler;
+
+#if defined(HAVE_XERCES)
     SAX2XMLReader *m_poSAXReader;
     XMLPScanToken m_oToFill;
     GMLFeature   *m_poCompleteFeature;
     GMLInputSource *m_GMLInputSource;
-#else
-    GMLExpatHandler    *m_poGMLHandler;
+    int           m_bEOF;
+    int           SetupParserXerces();
+    GMLFeature   *NextFeatureXerces();
+#endif
+
+#if defined(HAVE_EXPAT)
     XML_Parser    oParser;
     GMLFeature ** ppoFeatureTab;
     int           nFeatureTabLength;
     int           nFeatureTabIndex;
+    int           nFeatureTabAlloc;
+    int           SetupParserExpat();
+    GMLFeature   *NextFeatureExpat();
+    char         *pabyBuf;
 #endif
+
     VSILFILE*     fpGML;
     int           m_bReadStarted;
 
     GMLReadState *m_poState;
+    GMLReadState *m_poRecycledState;
 
     int           m_bStopParsing;
 
@@ -295,6 +409,8 @@ private:
     int           m_bFetchAllGeometries;
 
     int           m_bInvertAxisOrderIfLatLong;
+    int           m_bConsiderEPSGAsURN;
+    int           m_bGetSecondaryGeometryOption;
 
     int           ParseFeatureType(CPLXMLNode *psSchemaNode,
                                 const char* pszName,
@@ -305,8 +421,20 @@ private:
 
     char         *m_pszFilteredClassName;
 
+    int           m_bSequentialLayers;
+
+    std::string   osElemPath;
+
+    int           m_bFaceHoleNegative;
+
+    int           ParseXMLHugeFile( const char *pszOutputFilename, 
+                                    const int bSqliteIsTempFile,
+                                    const int iSqliteCacheMB );
+                               
+
 public:
-                GMLReader();
+                GMLReader(int bExpatReader, int bInvertAxisOrderIfLatLong,
+                          int bConsiderEPSGAsURN, int bGetSecondaryGeometryOption);
     virtual     ~GMLReader();
 
     int              IsClassListLocked() const { return m_bClassListLocked; }
@@ -332,8 +460,14 @@ public:
                                     int* pbOutIsTempFile,
                                     char **papszSkip = NULL,
                                     const int bStrict = FALSE );
+ 
+    int              HugeFileResolver( const char *pszFile,
+                                       int pbSqliteIsTempFile,
+                                       int iSqliteCacheMB );
 
     int              PrescanForSchema(int bGetExtents = TRUE );
+    int              PrescanForTemplate( void );
+    int              ReArrangeTemplateClasses( GFSTemplateList *pCC );
     void             ResetReading();
 
 // --- 
@@ -342,15 +476,17 @@ public:
     void             PopState();
     void             PushState( GMLReadState * );
 
-    int         IsFeatureElement( const char *pszElement );
-    int         IsAttributeElement( const char *pszElement );
+    int         GetFeatureElementIndex( const char *pszElement, int nLen );
+    int         GetAttributeElementIndex( const char *pszElement, int nLen );
     int         IsCityGMLGenericAttributeElement( const char *pszElement, void* attr );
 
     void        PushFeature( const char *pszElement, 
-                             const char *pszFID );
+                             const char *pszFID,
+                             int nClassIndex );
 
-    void        SetFeatureProperty( const char *pszElement,
-                                    const char *pszValue );
+    void        SetFeaturePropertyDirectly( const char *pszElement,
+                                    char *pszValue,
+                                    int iPropertyIn );
 
     int         HasStoppedParsing() { return m_bStopParsing; }
 
@@ -363,6 +499,8 @@ public:
 
     int         SetFilteredClassName(const char* pszClassName);
     const char* GetFilteredClassName() { return m_pszFilteredClassName; }
+
+    int         IsSequentialLayers() const { return m_bSequentialLayers == TRUE; }
 };
 
 #endif /* _CPL_GMLREADERP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
index 8708abb..efa4a07 100644
--- a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlreadstate.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: gmlreadstate.cpp 22954 2011-08-19 21:47:19Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReadState class.
@@ -40,10 +40,7 @@ GMLReadState::GMLReadState()
 {
     m_poFeature = NULL;
     m_poParentState = NULL;
-
-    m_pszPath = CPLStrdup("");
     m_nPathLength = 0;
-    m_papszPathComponents = NULL;
 }
 
 /************************************************************************/
@@ -53,105 +50,60 @@ GMLReadState::GMLReadState()
 GMLReadState::~GMLReadState()
 
 {
-    CPLFree( m_pszPath );
-    for( int i = 0; i < m_nPathLength; i++ )
-        CPLFree( m_papszPathComponents[i] );
-    CPLFree( m_papszPathComponents );
-}
-
-/************************************************************************/
-/*                              PushPath()                              */
-/************************************************************************/
-
-void GMLReadState::PushPath( const char *pszElement )
-
-{
-    m_nPathLength++;
-    m_papszPathComponents = CSLAddString( m_papszPathComponents, pszElement );
-
-    RebuildPath();
 }
 
 /************************************************************************/
-/*                              PopPath()                               */
+/*                              Reset()                                 */
 /************************************************************************/
 
-void GMLReadState::PopPath()
-
+void GMLReadState::Reset()
 {
-    CPLAssert( m_nPathLength > 0 );
-    if( m_nPathLength <= 0 )
-        return;
-
-    CPLFree( m_papszPathComponents[m_nPathLength-1] );
-    m_papszPathComponents[--m_nPathLength] = NULL;
+    m_poFeature = NULL;
+    m_poParentState = NULL;
 
-    RebuildPath();
+    osPath.resize(0);
+    m_nPathLength = 0;
 }
 
 /************************************************************************/
-/*                            RebuildPath()                             */
+/*                              PushPath()                              */
 /************************************************************************/
 
-void GMLReadState::RebuildPath()
+void GMLReadState::PushPath( const char *pszElement, int nLen )
 
 {
-    int   nLength=0, i;
-
-    for( i = 0; i < m_nPathLength; i++ )
-        nLength += strlen(m_papszPathComponents[i]) + 1;
-    
-    m_pszPath = (char *) CPLRealloc(m_pszPath, nLength );
-
-    nLength = 0;
-    for( i = 0; i < m_nPathLength; i++ )
+    if (m_nPathLength > 0)
+        osPath.append(1, '|');
+    if (m_nPathLength < (int)aosPathComponents.size())
     {
-        if( i > 0 )
-            m_pszPath[nLength++] = '|';
-
-        strcpy( m_pszPath + nLength, m_papszPathComponents[i] );
-        nLength += strlen(m_papszPathComponents[i]);
+        if (nLen >= 0)
+        {
+            aosPathComponents[m_nPathLength].assign(pszElement, nLen);
+            osPath.append(pszElement, nLen);
+        }
+        else
+        {
+            aosPathComponents[m_nPathLength].assign(pszElement);
+            osPath.append(pszElement);
+        }
     }
-}
-
-/************************************************************************/
-/*                          GetLastComponent()                          */
-/************************************************************************/
-
-const char *GMLReadState::GetLastComponent() const
-
-{
-    if( m_nPathLength == 0 )
-        return "";
     else
-        return m_papszPathComponents[m_nPathLength-1];
+    {
+        aosPathComponents.push_back(pszElement);
+        osPath.append(pszElement);
+    }
+    m_nPathLength ++;
 }
 
 /************************************************************************/
-/*                             MatchPath()                              */
-/*                                                                      */
-/*      Compare the passed in path to the current one and see if        */
-/*      they match.  It is assumed that the passed in path may          */
-/*      contain one or more elements and must match the tail of the     */
-/*      current path.  However, the passed in path does not need all    */
-/*      the components of the current read state path.                  */
-/*                                                                      */
-/*      Returns TRUE if the paths match.                                */
+/*                              PopPath()                               */
 /************************************************************************/
 
-int GMLReadState::MatchPath( const char *pszPathIn )
+void GMLReadState::PopPath()
 
 {
-    int iOffset;
-    int nInputLength = strlen(pszPathIn);
-    int nInternalLength = strlen(m_pszPath);
-
-    if( nInputLength > nInternalLength )
-        return FALSE;
-
-    iOffset = nInternalLength - nInputLength;
-    if( iOffset > 0 && m_pszPath[iOffset-1] != '|' )
-        return FALSE;
+    CPLAssert( m_nPathLength > 0 );
 
-    return strcmp(pszPathIn,m_pszPath + iOffset) == 0;
+    osPath.resize(osPath.size() - (aosPathComponents[m_nPathLength-1].size() + ((m_nPathLength > 1) ? 1 : 0)));
+    m_nPathLength --;
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.cpp b/ogr/ogrsf_frmts/gml/gmlutils.cpp
index a9373d6..76dd912 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlutils.cpp 21600 2011-01-29 13:40:21Z rouault $
+ * $Id: gmlutils.cpp 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -27,51 +27,52 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
-
 #include "gmlutils.h"
 
+#include "cpl_string.h"
+#include "ogr_api.h"
+#include "ogr_p.h"
+#include <string>
+
 /************************************************************************/
 /*                GML_ExtractSrsNameFromGeometry()                      */
 /************************************************************************/
 
-char* GML_ExtractSrsNameFromGeometry(char** papszGeometryList)
+const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometry,
+                                     std::string& osWork,
+                                     int bConsiderEPSGAsURN)
 {
-    if (papszGeometryList != NULL &&
-        *papszGeometryList != NULL &&
-        papszGeometryList[1] == NULL)
+    if (papsGeometry[0] != NULL && papsGeometry[1] == NULL)
     {
-        const char* pszSRSName = strstr(*papszGeometryList, "srsName=\"");
+        const char* pszSRSName = CPLGetXMLValue((CPLXMLNode*)papsGeometry[0], "srsName", NULL);
         if (pszSRSName)
         {
-            pszSRSName += strlen("srsName=\"");
+            int nLen = strlen(pszSRSName);
 
-            char* pszRet;
             if (strncmp(pszSRSName, "EPSG:", 5) == 0 &&
-                CSLTestBoolean(CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "NO")))
+                bConsiderEPSGAsURN)
             {
-                pszRet = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s", pszSRSName+5));
+                osWork.reserve(22 + nLen-5);
+                osWork.assign("urn:ogc:def:crs:EPSG::", 22);
+                osWork.append(pszSRSName+5, nLen-5);
+                return osWork.c_str();
             }
-            else if (strncmp(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#",
-                        strlen("http://www.opengis.net/gml/srs/epsg.xml#")) == 0)
+            else if (strncmp(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#", 40) == 0)
             {
-                pszRet = CPLStrdup(CPLSPrintf("EPSG:%s", pszSRSName +
-                            strlen("http://www.opengis.net/gml/srs/epsg.xml#")));
+                osWork.reserve(5 + nLen-40 );
+                osWork.assign("EPSG:", 5);
+                osWork.append(pszSRSName+40, nLen-40);
+                return osWork.c_str();
             }
             else
             {
-                pszRet = CPLStrdup(pszSRSName);
+                return pszSRSName;
             }
-            char* pszEndQuote = strchr(pszRet, '"');
-            if (pszEndQuote)
-                *pszEndQuote = 0;
-            return pszRet;
         }
     }
     return NULL;
 }
 
-
 /************************************************************************/
 /*                       GML_IsSRSLatLongOrder()                        */
 /************************************************************************/
@@ -101,99 +102,147 @@ int GML_IsSRSLatLongOrder(const char* pszSRSName)
     return FALSE;
 }
 
+
+/************************************************************************/
+/*                GML_BuildOGRGeometryFromList_CreateCache()            */
+/************************************************************************/
+
+class SRSCache
+{
+public:
+    std::string osLastSRSName;
+    int   bAxisInvertLastSRSName;
+};
+
+void* GML_BuildOGRGeometryFromList_CreateCache()
+{
+    return new SRSCache();
+}
+
+/************************************************************************/
+/*                 GML_BuildOGRGeometryFromList_DestroyCache()          */
+/************************************************************************/
+
+void GML_BuildOGRGeometryFromList_DestroyCache(void* hCacheSRS)
+{
+    delete (SRSCache*)hCacheSRS;
+}
+
 /************************************************************************/
 /*                 GML_BuildOGRGeometryFromList()                       */
 /************************************************************************/
 
-OGRGeometry* GML_BuildOGRGeometryFromList(char** papszGeometryList,
+OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry,
                                           int bTryToMakeMultipolygons,
                                           int bInvertAxisOrderIfLatLong,
-                                          const char* pszDefaultSRSName)
+                                          const char* pszDefaultSRSName,
+                                          int bConsiderEPSGAsURN,
+                                          int bGetSecondaryGeometryOption,
+                                          void* hCacheSRS,
+                                          int bFaceHoleNegative)
 {
     OGRGeometry* poGeom = NULL;
-    if( papszGeometryList != NULL )
+    int i;
+    OGRGeometryCollection* poCollection = NULL;
+    for(i=0;papsGeometry[i] != NULL;i++)
     {
-        char** papszIter = papszGeometryList;
-        OGRGeometryCollection* poCollection = NULL;
-        while(*papszIter)
+        OGRGeometry* poSubGeom = GML2OGRGeometry_XMLNode( papsGeometry[i],
+                                                          bGetSecondaryGeometryOption,
+                                                          0, FALSE, TRUE,
+                                                          bFaceHoleNegative );
+        if (poSubGeom)
         {
-            OGRGeometry* poSubGeom = OGRGeometryFactory::createFromGML( *papszIter );
-            if (poSubGeom)
+            if (poGeom == NULL)
+                poGeom = poSubGeom;
+            else
             {
-                if (poGeom == NULL)
-                    poGeom = poSubGeom;
-                else
+                if (poCollection == NULL)
                 {
-                    if (poCollection == NULL)
+                    if (bTryToMakeMultipolygons &&
+                        wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
+                        wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                     {
-                        if (bTryToMakeMultipolygons &&
-                            wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
-                            wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
-                        {
-                            OGRGeometryCollection* poGeomColl = new OGRMultiPolygon();
-                            poGeomColl->addGeometryDirectly(poGeom);
-                            poGeomColl->addGeometryDirectly(poSubGeom);
-                            poGeom = poGeomColl;
-                        }
-                        else if (bTryToMakeMultipolygons &&
-                                  wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
-                                 wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
-                        {
-                            OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
-                            poGeomColl->addGeometryDirectly(poSubGeom);
-                        }
-                        else if (bTryToMakeMultipolygons &&
-                                 wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
-                                 wkbFlatten(poSubGeom->getGeometryType()) == wkbMultiPolygon)
-                        {
-                            OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
-                            OGRGeometryCollection* poGeomColl2 = (OGRGeometryCollection* )poSubGeom;
-                            int nCount = poGeomColl2->getNumGeometries();
-                            int i;
-                            for(i=0;i<nCount;i++)
-                            {
-                                poGeomColl->addGeometry(poGeomColl2->getGeometryRef(i));
-                            }
-                            delete poSubGeom;
-                        }
-                        else if (bTryToMakeMultipolygons &&
-                                 wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon)
-                        {
-                            delete poGeom;
-                            delete poSubGeom;
-                            return GML_BuildOGRGeometryFromList(papszGeometryList, FALSE,
-                                                                bInvertAxisOrderIfLatLong,
-                                                                pszDefaultSRSName);
-                        }
-                        else
+                        OGRGeometryCollection* poGeomColl = new OGRMultiPolygon();
+                        poGeomColl->addGeometryDirectly(poGeom);
+                        poGeomColl->addGeometryDirectly(poSubGeom);
+                        poGeom = poGeomColl;
+                    }
+                    else if (bTryToMakeMultipolygons &&
+                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
+                                wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
+                    {
+                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
+                        poGeomColl->addGeometryDirectly(poSubGeom);
+                    }
+                    else if (bTryToMakeMultipolygons &&
+                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
+                                wkbFlatten(poSubGeom->getGeometryType()) == wkbMultiPolygon)
+                    {
+                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
+                        OGRGeometryCollection* poGeomColl2 = (OGRGeometryCollection* )poSubGeom;
+                        int nCount = poGeomColl2->getNumGeometries();
+                        int i;
+                        for(i=0;i<nCount;i++)
                         {
-                            poCollection = new OGRGeometryCollection();
-                            poCollection->addGeometryDirectly(poGeom);
-                            poGeom = poCollection;
+                            poGeomColl->addGeometry(poGeomColl2->getGeometryRef(i));
                         }
+                        delete poSubGeom;
+                    }
+                    else if (bTryToMakeMultipolygons &&
+                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon)
+                    {
+                        delete poGeom;
+                        delete poSubGeom;
+                        return GML_BuildOGRGeometryFromList(papsGeometry, FALSE,
+                                                            bInvertAxisOrderIfLatLong,
+                                                            pszDefaultSRSName,
+                                                            bConsiderEPSGAsURN,
+                                                            bGetSecondaryGeometryOption,
+                                                            hCacheSRS);
                     }
-                    if (poCollection != NULL)
+                    else
                     {
-                        poCollection->addGeometryDirectly(poSubGeom);
+                        poCollection = new OGRGeometryCollection();
+                        poCollection->addGeometryDirectly(poGeom);
+                        poGeom = poCollection;
                     }
                 }
+                if (poCollection != NULL)
+                {
+                    poCollection->addGeometryDirectly(poSubGeom);
+                }
             }
-            papszIter ++;
         }
     }
 
     if ( poGeom != NULL && bInvertAxisOrderIfLatLong )
     {
-        char* pszSRSName = GML_ExtractSrsNameFromGeometry(papszGeometryList);
-        if (GML_IsSRSLatLongOrder(pszSRSName ? pszSRSName : pszDefaultSRSName))
-            poGeom->swapXY();
-        CPLFree(pszSRSName);
+        std::string osWork;
+        const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork,
+                                                          bConsiderEPSGAsURN);
+        const char* pszNameLookup = pszSRSName ? pszSRSName : pszDefaultSRSName;
+        if (pszNameLookup != NULL)
+        {
+            SRSCache* poSRSCache = (SRSCache*)hCacheSRS;
+            int bSwap;
+            if (strcmp(poSRSCache->osLastSRSName.c_str(), pszNameLookup) == 0)
+            {
+                bSwap = poSRSCache->bAxisInvertLastSRSName;
+            }
+            else
+            {
+                bSwap = GML_IsSRSLatLongOrder(pszNameLookup);
+                poSRSCache->osLastSRSName = pszNameLookup;
+                poSRSCache->bAxisInvertLastSRSName= bSwap;
+            }
+            if (bSwap)
+                poGeom->swapXY();
+        }
     }
-    
+
     return poGeom;
 }
 
-
 /************************************************************************/
 /*                           GML_GetSRSName()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.h b/ogr/ogrsf_frmts/gml/gmlutils.h
index af57f1a..69125c5 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.h
+++ b/ogr/ogrsf_frmts/gml/gmlutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlutils.h 21272 2010-12-16 00:38:34Z rouault $
+ * $Id: gmlutils.h 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -30,16 +30,29 @@
 #ifndef _CPL_GMLUTILS_H_INCLUDED
 #define _CPL_GMLUTILS_H_INCLUDED
 
+#include <vector>
+#include <string>
+#include "cpl_minixml.h"
+
 #include "ogr_geometry.h"
 
-char* GML_ExtractSrsNameFromGeometry(char** papszGeometryList);
+const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometry,
+                                     std::string& osWork,
+                                     int bConsiderEPSGAsURN);
 
 int GML_IsSRSLatLongOrder(const char* pszSRSName);
 
-OGRGeometry* GML_BuildOGRGeometryFromList(char** papszGeometryList,
+void* GML_BuildOGRGeometryFromList_CreateCache();
+void GML_BuildOGRGeometryFromList_DestroyCache(void* hCacheSRS);
+
+OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry,
                                           int bTryToMakeMultipolygons,
                                           int bInvertAxisOrderIfLatLong,
-                                          const char* pszDefaultSRSName);
+                                          const char* pszDefaultSRSName,
+                                          int bConsiderEPSGAsURN,
+                                          int bGetSecondaryGeometryOption,
+                                          void* hCacheSRS,
+                                          int bFaceHoleNegative = FALSE );
 
 char* GML_GetSRSName(const OGRSpatialReference* poSRS, int bLongSRS, int *pbCoordSwap);
 
diff --git a/ogr/ogrsf_frmts/gml/hugefileresolver.cpp b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
new file mode 100644
index 0000000..d38df2e
--- /dev/null
+++ b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
@@ -0,0 +1,2071 @@
+/******************************************************************************
+ * $Id: hugefileresolver.cpp 23676 2012-01-01 16:10:36Z rouault $
+ *
+ * Project:  GML Reader
+ * Purpose:  Implementation of GMLReader::HugeFileResolver() method.
+ * Author:   Alessandro Furieri, a.furitier at lqt.it
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Alessandro Furieri
+ *
+ * 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.
+ *
+ ******************************************************************************
+ * Contributor: Alessandro Furieri, a.furieri at lqt.it
+ * This module implents GML_SKIP_RESOLVE_ELEMS HUGE
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
+ *
+ ****************************************************************************/
+
+#include "gmlreader.h"
+#include "cpl_error.h"
+
+#include "gmlreaderp.h"
+#include "gmlutils.h"
+#include "cpl_conv.h"
+#include "ogr_p.h"
+#include "cpl_string.h"
+#include "cpl_http.h"
+
+#include <stack>
+
+CPL_CVSID("$Id: hugefileresolver.cpp 23676 2012-01-01 16:10:36Z rouault $");
+
+/****************************************************/
+/*      SQLite is absolutely required in order to   */
+/*      support the HUGE xlink:href resolver        */
+/****************************************************/
+
+#ifdef HAVE_SQLITE
+#include <sqlite3.h>
+#endif
+
+/* sqlite3_clear_bindings() isn't available in old versions of */
+/* sqlite3 */
+#if defined(HAVE_SQLITE) && SQLITE_VERSION_NUMBER >= 3006000
+
+/* an internal helper struct supporting GML tags <Edge> */
+struct huge_tag
+{
+    CPLString           *gmlTagValue;
+    CPLString           *gmlId;
+    CPLString           *gmlNodeFrom;
+    CPLString           *gmlNodeTo;
+    int	                bIsNodeFromHref;
+    int                 bIsNodeToHref;
+    int                 bHasCoords;
+    int                 bHasZ;
+    double              xNodeFrom;
+    double              yNodeFrom;
+    double              zNodeFrom;
+    double              xNodeTo;
+    double              yNodeTo;
+    double              zNodeTo;
+    struct huge_tag     *pNext;
+};
+
+/* an internal helper struct supporting GML tags xlink:href */
+struct huge_href
+{
+    CPLString           *gmlId;
+    CPLString           *gmlText;
+    const CPLXMLNode    *psParent;
+    const CPLXMLNode    *psNode;
+    int                 bIsDirectedEdge;
+    char                cOrientation;
+    struct huge_href    *pNext;
+};
+
+/* an internal helper struct supporying GML rewriting */
+struct huge_child
+{
+    CPLXMLNode          *psChild;
+    struct huge_href    *pItem;
+    struct huge_child   *pNext;
+};
+
+/* an internal helper struct supporting GML rewriting */
+struct huge_parent
+{
+    CPLXMLNode          *psParent;
+    struct huge_child   *pFirst;
+    struct huge_child   *pLast;
+    struct huge_parent  *pNext;
+};
+
+/*
+/ an internal helper struct supporting GML 
+/ resolver for Huge Files (based on SQLite)
+*/
+struct huge_helper
+{
+    sqlite3             *hDB;
+    sqlite3_stmt        *hNodes;
+    sqlite3_stmt        *hEdges;
+    CPLString           *nodeSrs;
+    struct huge_tag     *pFirst;
+    struct huge_tag     *pLast;
+    struct huge_href    *pFirstHref;
+    struct huge_href    *pLastHref;
+    struct huge_parent  *pFirstParent;
+    struct huge_parent  *pLastParent;
+};
+
+static int gmlHugeFileSQLiteInit( struct huge_helper *helper )
+{
+/* attempting to create SQLite tables */
+    const char          *osCommand;
+    char                *pszErrMsg = NULL;
+    int                 rc;
+    sqlite3             *hDB = helper->hDB;
+    sqlite3_stmt        *hStmt;
+
+    /* DB table: NODES */
+    osCommand = "CREATE TABLE nodes ("
+                "     gml_id VARCHAR PRIMARY KEY, "
+                "     x DOUBLE, "
+                "     y DOUBLE, "
+                "     z DOUBLE)";
+    rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create table nodes: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return FALSE;
+    }
+
+    /* DB table: GML_EDGES */
+    osCommand = "CREATE TABLE gml_edges ("
+                "     gml_id VARCHAR PRIMARY KEY, "
+                "     gml_string BLOB, "
+                "     gml_resolved BLOB, "
+				"     node_from_id TEXT, "
+                "     node_from_x DOUBLE, "
+                "     node_from_y DOUBLE, "
+                "     node_from_z DOUBLE, "
+				"     node_to_id TEXT, "
+                "     node_to_x DOUBLE, "
+                "     node_to_y DOUBLE, "
+                "     node_to_z DOUBLE)";
+    rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create table gml_edges: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return FALSE;
+    }
+
+    /* 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 );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create INSERT stmt for: nodes" );
+        return FALSE;
+    }
+    helper->hNodes = hStmt;
+
+    /* DB table: GML_EDGES / Insert cursor */
+    osCommand = "INSERT INTO gml_edges "
+                "(gml_id, gml_string, gml_resolved, "
+                "node_from_id, node_from_x, node_from_y, "
+                "node_from_z, node_to_id, node_to_x, "
+                "node_to_y, node_to_z) "
+                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+    rc = sqlite3_prepare( hDB, osCommand, -1, &hStmt, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create INSERT stmt for: gml_edges" );
+        return FALSE;
+    }
+    helper->hEdges = hStmt;
+
+    /* starting a TRANSACTION */
+    rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to perform BEGIN TRANSACTION: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return FALSE;
+    }	
+
+    return TRUE;
+}
+
+static int gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
+                                    const char *pszFromId,
+                                    const char *pszToId )
+{
+/* resolves an Edge definition */
+    CPLXMLNode      *psDirNode_1 = NULL;
+    CPLXMLNode      *psDirNode_2 = NULL;
+    CPLXMLNode      *psOldNode_1 = NULL;
+    CPLXMLNode      *psOldNode_2 = NULL;
+    CPLXMLNode      *psNewNode_1 = NULL;
+    CPLXMLNode      *psNewNode_2 = NULL;
+    int             iToBeReplaced = 0;
+    int             iReplaced = 0;
+    if( psNode->eType == CXT_Element && EQUAL( psNode->pszValue, "Edge" ) )
+        ;
+    else
+        return FALSE;
+
+    CPLXMLNode *psChild = psNode->psChild;
+    while( psChild != NULL )
+    {
+        if( psChild->eType == CXT_Element &&
+            EQUAL( psChild->pszValue, "directedNode" ) )
+        {
+            char cOrientation = '+';
+            CPLXMLNode *psOldNode = NULL;
+            CPLXMLNode *psAttr = psChild->psChild;
+            while( psAttr != NULL )
+            {
+                if( psAttr->eType == CXT_Attribute &&
+                    EQUAL( psAttr->pszValue, "xlink:href" ) )
+                    psOldNode = psAttr;
+                if( psAttr->eType == CXT_Attribute &&
+                    EQUAL( psAttr->pszValue, "orientation" ) )
+                {
+                    const CPLXMLNode *psOrientation = psAttr->psChild;
+                    if( psOrientation != NULL )
+                    {
+                        if( psOrientation->eType == CXT_Text )
+                            cOrientation = *(psOrientation->pszValue);
+                    }
+                }
+                psAttr = psAttr->psNext;
+            }
+            if( psOldNode != NULL )
+            {
+                CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "Node");
+                CPLXMLNode *psGMLIdNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "gml:id");
+                if( cOrientation == '-' )
+                    CPLCreateXMLNode(psGMLIdNode, CXT_Text, pszFromId);
+                else
+                    CPLCreateXMLNode(psGMLIdNode, CXT_Text, pszToId);
+                if( iToBeReplaced == 0 )
+                {
+                    psDirNode_1 = psChild;
+                    psOldNode_1 = psOldNode;
+                    psNewNode_1 = psNewNode;
+                }
+                else
+                {
+                    psDirNode_2 = psChild;
+                    psOldNode_2 = psOldNode;
+                    psNewNode_2 = psNewNode;
+                }
+                iToBeReplaced++;
+            }
+        }
+        psChild = psChild->psNext;
+    }
+
+    /* rewriting the Edge GML definition */
+    if( psDirNode_1 != NULL)
+    {
+        if( psOldNode_1 != NULL )
+        {
+            CPLRemoveXMLChild( psDirNode_1, psOldNode_1 );
+            CPLDestroyXMLNode( psOldNode_1 );
+            if( psNewNode_1 != NULL )
+            {
+                CPLAddXMLChild( psDirNode_1, psNewNode_1 );
+                iReplaced++;
+            }
+        }
+    }
+    if( psDirNode_2 != NULL)
+    {
+        if( psOldNode_2 != NULL )
+        {
+            CPLRemoveXMLChild( psDirNode_2, psOldNode_2 );
+            CPLDestroyXMLNode( psOldNode_2 );
+            if( psNewNode_2 != NULL )
+            {
+                CPLAddXMLChild( psDirNode_2, psNewNode_2 );
+                iReplaced++;
+            }
+        }
+    }
+    if( iToBeReplaced != iReplaced )
+        return FALSE;
+return TRUE;
+}
+
+static int gmlHugeFileResolveEdges( struct huge_helper *helper )
+{
+/* identifying any not yet resolved <Edge> GML string */
+    const char          *osCommand;
+    char                *pszErrMsg = NULL;
+    int rc;
+    sqlite3             *hDB = helper->hDB;
+    sqlite3_stmt        *hQueryStmt;
+    sqlite3_stmt        *hUpdateStmt;
+    int                 iCount = 0;
+    int                 bError = FALSE;
+
+    /* query cursor */
+    osCommand = "SELECT e.gml_id, e.gml_string, e.node_from_id, "
+                "e.node_from_x, e.node_from_y, e.node_from_z, "
+                "n1.gml_id, n1.x, n1.y, n1.z, e.node_to_id, "
+                "e.node_to_x, e.node_to_y, e.node_to_z, "
+                "n2.gml_id, n2.x, n2.y, n2.z "
+                "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 );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create QUERY stmt for Edge resolver" );
+        return FALSE;
+    }
+
+    /* update cursor */
+    osCommand = "UPDATE gml_edges "
+                "SET gml_resolved = ?, "
+                "gml_string = NULL "
+                "WHERE gml_id = ?";
+    rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create UPDATE stmt for resolved Edges" );
+        sqlite3_finalize ( hQueryStmt );
+        return FALSE;
+    }
+
+    /* starting a TRANSACTION */
+    rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to perform BEGIN TRANSACTION: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        sqlite3_finalize ( hQueryStmt );
+        sqlite3_finalize ( hUpdateStmt );
+        return FALSE;
+    }
+    
+    /* looping on the QUERY result-set */
+    while ( TRUE )
+    {
+        const char      *pszGmlId;
+        const char      *pszGmlString = NULL;
+        int             bIsGmlStringNull;
+        const char      *pszFromId = NULL;
+        int             bIsFromIdNull;
+        double          xFrom = 0.0;
+        int             bIsXFromNull;
+        double          yFrom = 0.0;
+        int             bIsYFromNull;
+        double          zFrom = 0.0;
+        int             bIsZFromNull;
+        const char      *pszNodeFromId = NULL;
+        int             bIsNodeFromIdNull;
+        double          xNodeFrom = 0.0;
+        int             bIsXNodeFromNull;
+        double          yNodeFrom = 0.0;
+        int             bIsYNodeFromNull;
+        double          zNodeFrom = 0.0;
+        int             bIsZNodeFromNull;
+        const char      *pszToId = NULL;
+        int             bIsToIdNull;
+        double          xTo = 0.0;
+        int             bIsXToNull;
+        double          yTo = 0.0;
+        int             bIsYToNull;
+        double          zTo = 0.0;
+        int             bIsZToNull;
+        const char      *pszNodeToId = NULL;
+        int             bIsNodeToIdNull;
+        double          xNodeTo = 0.0;
+        int             bIsXNodeToNull;
+        double          yNodeTo = 0.0;
+        int             bIsYNodeToNull;
+        double          zNodeTo = 0.0;
+        int             bIsZNodeToNull;
+
+        rc = sqlite3_step( hQueryStmt );
+        if( rc == SQLITE_DONE )
+            break;
+        else if( rc == SQLITE_ROW )
+        {
+            bError = FALSE;
+            pszGmlId = (const char *) sqlite3_column_text( hQueryStmt, 0 );
+            if( sqlite3_column_type( hQueryStmt, 1 ) == SQLITE_NULL )
+                bIsGmlStringNull = TRUE;
+            else
+            {
+                pszGmlString = (const char *) sqlite3_column_blob( hQueryStmt, 1 );
+                bIsGmlStringNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 2 ) == SQLITE_NULL )
+                bIsFromIdNull = TRUE;
+            else
+            {
+                pszFromId = (const char *) sqlite3_column_text( hQueryStmt, 2 );
+                bIsFromIdNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 3 ) == SQLITE_NULL )
+                bIsXFromNull = TRUE;
+            else
+            {
+                xFrom = sqlite3_column_double( hQueryStmt, 3 );
+                bIsXFromNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 4 ) == SQLITE_NULL )
+                bIsYFromNull = TRUE;
+            else
+            {
+                yFrom = sqlite3_column_double( hQueryStmt, 4 );
+                bIsYFromNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 5 ) == SQLITE_NULL )
+                bIsZFromNull = TRUE;
+            else
+            {
+                zFrom = sqlite3_column_double( hQueryStmt, 5 );
+                bIsZFromNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 6 ) == SQLITE_NULL )
+                bIsNodeFromIdNull = TRUE;
+            else
+            {
+                pszNodeFromId = (const char *) sqlite3_column_text( hQueryStmt, 6 );
+                bIsNodeFromIdNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 7 ) == SQLITE_NULL )
+                bIsXNodeFromNull = TRUE;
+            else
+            {
+                xNodeFrom = sqlite3_column_double( hQueryStmt, 7 );
+                bIsXNodeFromNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 8 ) == SQLITE_NULL )
+                bIsYNodeFromNull = TRUE;
+            else
+            {
+                yNodeFrom = sqlite3_column_double( hQueryStmt, 8 );
+                bIsYNodeFromNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 9 ) == SQLITE_NULL )
+                bIsZNodeFromNull = TRUE;
+            else
+            {
+                zNodeFrom = sqlite3_column_double( hQueryStmt, 9 );
+                bIsZNodeFromNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 10 ) == SQLITE_NULL )
+                bIsToIdNull = TRUE;
+            else
+            {
+                pszToId = (const char *) sqlite3_column_text( hQueryStmt, 10 );
+                bIsToIdNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 11 ) == SQLITE_NULL )
+                bIsXToNull = TRUE;
+            else
+            {
+                xTo = sqlite3_column_double( hQueryStmt, 11 );
+                bIsXToNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 12 ) == SQLITE_NULL )
+                bIsYToNull = TRUE;
+            else
+            {
+                yTo = sqlite3_column_double( hQueryStmt, 12 );
+                bIsYToNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 13 ) == SQLITE_NULL )
+                bIsZToNull = TRUE;
+            else
+            {
+                zTo = sqlite3_column_double( hQueryStmt, 13 );
+                bIsZToNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 14 ) == SQLITE_NULL )
+                bIsNodeToIdNull = TRUE;
+            else
+            {
+                pszNodeToId = (const char *) sqlite3_column_text( hQueryStmt, 14 );
+                bIsNodeToIdNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 15 ) == SQLITE_NULL )
+                bIsXNodeToNull = TRUE;
+            else
+            {
+                xNodeTo = sqlite3_column_double( hQueryStmt, 15 );
+                bIsXNodeToNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 16 ) == SQLITE_NULL )
+                bIsYNodeToNull = TRUE;
+            else
+            {
+                yNodeTo = sqlite3_column_double( hQueryStmt, 16 );
+                bIsYNodeToNull = FALSE;
+            }
+            if( sqlite3_column_type( hQueryStmt, 17 ) == SQLITE_NULL )
+                bIsZNodeToNull = TRUE;
+            else
+            {
+                zNodeTo = sqlite3_column_double( hQueryStmt, 17 );
+                bIsZNodeToNull = FALSE;
+            }
+
+            /* checking for consistency */
+            if( bIsFromIdNull == TRUE || bIsXFromNull == TRUE ||
+                bIsYFromNull == TRUE )
+            {
+                bError = TRUE;
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                          "Edge gml:id=\"%s\": invalid Node-from", 
+                          pszGmlId );
+            }
+            else
+            {
+                if( bIsNodeFromIdNull == TRUE )
+                {
+                    bError = TRUE;
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"", 
+                              pszGmlId, pszFromId );
+                }
+                else if( bIsXNodeFromNull == TRUE || bIsYNodeFromNull == TRUE )
+                {
+                    bError = TRUE;
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"", 
+                              pszGmlId, pszFromId );
+                }
+                else if( xFrom != xNodeFrom || yFrom != yNodeFrom )
+                {
+                    bError = TRUE;
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"", 
+                              pszGmlId, pszFromId );
+                }
+                else
+                {
+                    if( bIsZFromNull == TRUE && bIsZNodeFromNull == TRUE )
+;
+                    else if(  bIsZFromNull == TRUE || bIsZNodeFromNull == TRUE )
+                    {
+                        bError = TRUE;
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"", 
+                                  pszGmlId, pszFromId );
+                    }
+                    else if( zFrom != zNodeFrom ) 
+                    {
+                        bError = TRUE;
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"", 
+                                  pszGmlId, pszFromId );
+                    }
+                }
+            }
+            if( bIsToIdNull == TRUE || bIsXToNull == TRUE ||
+                bIsYToNull == TRUE )
+            {
+                bError = TRUE;
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                          "Edge gml:id=\"%s\": invalid Node-to", 
+                          pszGmlId );
+            }
+            else
+            {
+                if( bIsNodeToIdNull == TRUE )
+                {
+                    bError = TRUE;
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"", 
+                              pszGmlId, pszToId );
+                }
+                else if( bIsXNodeToNull == TRUE || bIsYNodeToNull == TRUE )
+                {
+                    bError = TRUE;
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"", 
+                              pszGmlId, pszToId );
+                }
+                else if( xTo != xNodeTo || yTo != yNodeTo )
+                {
+                    bError = TRUE;
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"", 
+                              pszGmlId, pszToId );
+                }
+                else
+                {
+                    if( bIsZToNull == TRUE && bIsZNodeToNull == TRUE )
+;
+                    else if(  bIsZToNull == TRUE || bIsZNodeToNull == TRUE )
+                    {
+                        bError = TRUE;
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"", 
+                                  pszGmlId, pszToId );
+                    }
+                    else if( zTo != zNodeTo ) 
+                    {
+                        bError = TRUE;
+                        CPLError( CE_Failure, CPLE_AppDefined, 
+                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"", 
+                                  pszGmlId, pszToId );
+                    }
+                }
+            }
+
+            /* updating the resolved Node */
+            if( bError == FALSE && bIsGmlStringNull == FALSE &&
+                bIsFromIdNull == FALSE && bIsToIdNull == FALSE )
+            {
+                CPLXMLNode *psNode = CPLParseXMLString( pszGmlString );
+                if( psNode != NULL )
+                {
+                    if( gmlHugeResolveEdgeNodes( psNode, pszFromId,
+                                                 pszToId ) == TRUE )
+                    {
+                        char * gmlText = CPLSerializeXMLTree(psNode);
+                        sqlite3_reset ( hUpdateStmt );
+                        sqlite3_clear_bindings ( hUpdateStmt );
+                        sqlite3_bind_blob( hUpdateStmt, 1, gmlText,
+                                           strlen(gmlText), SQLITE_STATIC );
+                        sqlite3_bind_text( hUpdateStmt, 2, pszGmlId, -1,
+                                           SQLITE_STATIC );
+                        rc = sqlite3_step( hUpdateStmt );
+                        if( rc != SQLITE_OK && rc != SQLITE_DONE )
+                        {
+                            CPLError( CE_Failure, CPLE_AppDefined,
+                                      "UPDATE resoved Edge \"%s\" sqlite3_step() failed:\n  %s",
+                                      pszGmlId, sqlite3_errmsg(hDB) );
+                        }
+                        CPLFree( gmlText );
+                        iCount++;
+                        if( (iCount % 1024) == 1023 )
+                        {
+                            /* committing the current TRANSACTION */
+                            rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL,
+                                               &pszErrMsg );
+                            if( rc != SQLITE_OK )
+                            {
+                                CPLError( CE_Failure, CPLE_AppDefined, 
+                                          "Unable to perform COMMIT TRANSACTION: %s",
+                                          pszErrMsg );
+                                sqlite3_free( pszErrMsg );
+                                return FALSE;
+                            }
+                            /* restarting a new TRANSACTION */
+                            rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
+                            if( rc != SQLITE_OK )
+                            {
+                                CPLError( CE_Failure, CPLE_AppDefined, 
+                                          "Unable to perform BEGIN TRANSACTION: %s",
+                                          pszErrMsg );
+                                sqlite3_free( pszErrMsg );
+                                sqlite3_finalize ( hQueryStmt );
+                                sqlite3_finalize ( hUpdateStmt );
+                                return FALSE;
+                            }
+                        }
+                    }
+                    CPLDestroyXMLNode( psNode );
+                }
+            }
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "Edge resolver QUERY: sqlite3_step(%s)", 
+                      sqlite3_errmsg(hDB) );
+            sqlite3_finalize ( hQueryStmt );
+            sqlite3_finalize ( hUpdateStmt );
+            return FALSE;
+        }
+    }
+    sqlite3_finalize ( hQueryStmt );
+    sqlite3_finalize ( hUpdateStmt );
+
+    /* committing the current TRANSACTION */
+    rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to perform COMMIT TRANSACTION: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return FALSE;
+    }
+    if( bError == TRUE )
+        return FALSE;
+    return TRUE;
+}
+
+static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
+{
+/* inserting any appropriate row into the SQLite DB */
+    int rc;
+    struct huge_tag *pItem;
+
+    /* looping on GML tags */
+    pItem = helper->pFirst;
+    while ( pItem != NULL )
+    {
+        if( pItem->bHasCoords == TRUE )
+        {
+            if( pItem->gmlNodeFrom != NULL )
+            {
+                sqlite3_reset ( helper->hNodes );
+                sqlite3_clear_bindings ( helper->hNodes );
+                sqlite3_bind_text( helper->hNodes, 1,
+                                   pItem->gmlNodeFrom->c_str(), -1,
+                                   SQLITE_STATIC );
+                sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeFrom );
+                sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeFrom );
+                if( pItem->bHasZ == TRUE )
+                    sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeFrom );
+                sqlite3_bind_null ( helper->hNodes, 5 );
+                rc = sqlite3_step( helper->hNodes );
+                if( rc != SQLITE_OK && rc != SQLITE_DONE )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "sqlite3_step() failed:\n  %s", 
+                              sqlite3_errmsg(helper->hDB) );
+                              return FALSE;
+                }
+            }
+            if( pItem->gmlNodeTo != NULL )
+            {
+                sqlite3_reset ( helper->hNodes );
+                sqlite3_clear_bindings ( helper->hNodes );
+                sqlite3_bind_text( helper->hNodes, 1, pItem->gmlNodeTo->c_str(),
+                                   -1, SQLITE_STATIC );
+                sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeTo );
+                sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeTo );
+                if ( pItem->bHasZ == TRUE )
+                    sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeTo );
+                sqlite3_bind_null ( helper->hNodes, 5 );
+                rc = sqlite3_step( helper->hNodes );
+                if( rc != SQLITE_OK && rc != SQLITE_DONE )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "sqlite3_step() failed:\n  %s", 
+                              sqlite3_errmsg(helper->hDB) );
+                              return FALSE;
+                }
+            }
+        }
+
+        /* gml:id */
+        sqlite3_reset( helper->hEdges );
+        sqlite3_clear_bindings( helper->hEdges );
+        sqlite3_bind_text( helper->hEdges, 1, pItem->gmlId->c_str(), -1,
+                           SQLITE_STATIC );
+        if( pItem->bIsNodeFromHref == FALSE && pItem->bIsNodeToHref == FALSE )
+        {
+            sqlite3_bind_null( helper->hEdges, 2 );
+            sqlite3_bind_blob( helper->hEdges, 3, pItem->gmlTagValue->c_str(),
+                               strlen( pItem->gmlTagValue->c_str() ),
+                               SQLITE_STATIC );
+        }
+        else
+        {
+            sqlite3_bind_blob( helper->hEdges, 2, pItem->gmlTagValue->c_str(),
+                               strlen( pItem->gmlTagValue->c_str() ),
+                               SQLITE_STATIC );
+            sqlite3_bind_null( helper->hEdges, 3 );
+        }
+        if( pItem->gmlNodeFrom != NULL )
+            sqlite3_bind_text( helper->hEdges, 4, pItem->gmlNodeFrom->c_str(),
+                               -1, SQLITE_STATIC );
+        else
+            sqlite3_bind_null( helper->hEdges, 4 );
+        if( pItem->bHasCoords == TRUE )
+        {
+            sqlite3_bind_double( helper->hEdges, 5, pItem->xNodeFrom );
+            sqlite3_bind_double( helper->hEdges, 6, pItem->yNodeFrom );
+            if( pItem->bHasZ == TRUE )
+                sqlite3_bind_double( helper->hEdges, 7, pItem->zNodeFrom );
+            else
+                sqlite3_bind_null( helper->hEdges, 7 );
+        }
+        else
+        {
+            sqlite3_bind_null( helper->hEdges, 5 );
+            sqlite3_bind_null( helper->hEdges, 6 );
+            sqlite3_bind_null( helper->hEdges, 7 );
+        }
+        if( pItem->gmlNodeTo != NULL )
+            sqlite3_bind_text( helper->hEdges, 8, pItem->gmlNodeTo->c_str(),
+                               -1, SQLITE_STATIC );
+        else
+            sqlite3_bind_null( helper->hEdges, 8 );
+        if( pItem->bHasCoords == TRUE )
+        {
+            sqlite3_bind_double( helper->hEdges, 9, pItem->xNodeTo );
+            sqlite3_bind_double( helper->hEdges, 10, pItem->yNodeTo );
+            if( pItem->bHasZ == TRUE )
+                sqlite3_bind_double( helper->hEdges, 11, pItem->zNodeTo );
+            else
+                sqlite3_bind_null( helper->hEdges, 11 );
+        }
+        else
+        {
+            sqlite3_bind_null( helper->hEdges, 9 );
+            sqlite3_bind_null( helper->hEdges, 10 );
+            sqlite3_bind_null( helper->hEdges, 11 );
+        }
+        rc = sqlite3_step( helper->hEdges );
+        if( rc != SQLITE_OK && rc != SQLITE_DONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "sqlite3_step() failed:\n  %s", 
+                      sqlite3_errmsg(helper->hDB) );
+            return FALSE;
+        }
+        pItem = pItem->pNext;
+    }
+    return TRUE;
+}
+
+static void gmlHugeFileReset( struct huge_helper *helper )
+{
+/* resetting an empty helper struct */
+    struct huge_tag *pNext;
+    struct huge_tag *p = helper->pFirst;
+
+    /* cleaning any previous item */
+    while( p != NULL )
+    {
+        pNext = p->pNext;
+        if( p->gmlTagValue != NULL )
+            delete p->gmlTagValue;
+        if( p->gmlId != NULL )
+            delete p->gmlId;
+        if( p->gmlNodeFrom != NULL )
+            delete p->gmlNodeFrom;
+        if( p->gmlNodeTo != NULL )
+            delete p->gmlNodeTo;
+        delete p;
+        p = pNext;
+    }
+    helper->pFirst = NULL;
+    helper->pLast = NULL;
+}
+
+static void gmlHugeFileHrefReset( struct huge_helper *helper )
+{
+/* resetting an empty helper struct */
+    struct huge_href *pNext;
+    struct huge_href *p = helper->pFirstHref;
+
+    /* cleaning any previous item */
+    while( p != NULL )
+    {
+        pNext = p->pNext;
+        if( p->gmlId != NULL )
+            delete p->gmlId;
+        if( p->gmlText != NULL )
+            delete p->gmlText;
+        delete p;
+        p = pNext;
+    }
+    helper->pFirstHref = NULL;
+    helper->pLastHref = NULL;
+}
+
+static int gmlHugeFileHrefCheck( struct huge_helper *helper )
+{
+/* testing for unresolved items */
+    int bError = FALSE;
+	struct huge_href *p = helper->pFirstHref;
+	while( p != NULL )
+    {
+		if( p->gmlText == NULL)
+		{
+			bError = TRUE;
+			CPLError( CE_Failure, CPLE_AppDefined, 
+                      "Edge xlink:href\"%s\": unresolved match", 
+                      p->gmlId->c_str() );
+		}
+        p = p->pNext;
+    }
+	if( bError == TRUE )
+		return FALSE;
+	return TRUE;
+}
+
+static void gmlHugeFileRewiterReset( struct huge_helper *helper )
+{
+/* resetting an empty helper struct */
+    struct huge_parent *pNext;
+    struct huge_parent *p = helper->pFirstParent;
+
+    /* cleaning any previous item */
+    while( p != NULL )
+    {
+        pNext = p->pNext;
+        struct huge_child *pChildNext;
+        struct huge_child *pChild = p->pFirst;
+        while( pChild != NULL )
+        {
+            pChildNext = pChild->pNext;
+            delete pChild;
+            pChild = pChildNext;
+        }
+        delete p;
+        p = pNext;
+    }
+    helper->pFirstParent = NULL;
+    helper->pLastParent = NULL;
+}
+
+static struct huge_tag *gmlHugeAddToHelper( struct huge_helper *helper,
+                                            CPLString *gmlId,
+                                            CPLString *gmlFragment )
+{
+/* adding an item  into the linked list */
+    struct huge_tag *pItem;
+
+    /* checking against duplicates */
+    pItem = helper->pFirst;
+    while( pItem != NULL )
+    {
+        if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) )
+            return NULL;
+        pItem = pItem->pNext;
+    }	
+
+    pItem = new struct huge_tag;
+    pItem->gmlId = gmlId;
+    pItem->gmlTagValue = gmlFragment;
+    pItem->gmlNodeFrom = NULL;
+    pItem->gmlNodeTo = NULL;
+    pItem->bHasCoords = FALSE;
+    pItem->bHasZ = FALSE;
+    pItem->pNext = NULL;
+
+    /* appending the item to the linked list */
+    if ( helper->pFirst == NULL )
+        helper->pFirst = pItem;
+    if ( helper->pLast != NULL )
+        helper->pLast->pNext = pItem;
+    helper->pLast = pItem;
+    return pItem;
+}
+
+static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
+                                       CPLString *gmlId,
+                                       const CPLXMLNode *psParent,
+                                       const CPLXMLNode *psNode,
+                                       int bIsDirectedEdge,
+                                       char cOrientation )
+{
+/* inserting an item into the linked list */
+    struct huge_href *pItem;
+
+    /* checking against duplicates */
+    pItem = helper->pFirstHref;
+    while( pItem != NULL )
+    {
+        if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) &&
+            pItem->psParent == psParent  && 
+            pItem->psNode == psNode && 
+            pItem->cOrientation == cOrientation &&
+            pItem->bIsDirectedEdge == bIsDirectedEdge )
+            {
+                delete gmlId;
+                return;
+            }
+            pItem = pItem->pNext;
+    }	
+
+    pItem = new struct huge_href;
+    pItem->gmlId = gmlId;
+    pItem->gmlText = NULL;
+    pItem->psParent = psParent;
+    pItem->psNode = psNode;
+    pItem->bIsDirectedEdge = bIsDirectedEdge;
+    pItem->cOrientation = cOrientation;
+    pItem->pNext = NULL;
+
+    /* appending the item to the linked list */
+    if ( helper->pFirstHref == NULL )
+        helper->pFirstHref = pItem;
+    if ( helper->pLastHref != NULL )
+        helper->pLastHref->pNext = pItem;
+    helper->pLastHref = pItem;
+}
+
+static int gmlHugeFindGmlId( const CPLXMLNode *psNode, CPLString **gmlId )
+{
+/* attempting to identify a gml:id value      */
+    *gmlId = NULL;
+    const CPLXMLNode *psChild = psNode->psChild;
+    while( psChild != NULL )
+    {
+        if( psChild->eType == CXT_Attribute &&
+            EQUAL( psChild->pszValue, "gml:id" ) )
+        {
+            const CPLXMLNode *psIdValue = psChild->psChild;
+            if( psIdValue != NULL )
+            {
+                if( psIdValue->eType == CXT_Text )
+                {
+                    *gmlId = new CPLString(psIdValue->pszValue);
+                    return TRUE;
+                }
+            }
+        }
+        psChild = psChild->psNext;
+    }
+    return FALSE;
+}
+
+static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
+                                   const CPLXMLNode * psNode,
+                                   CPLString **nodeSrs )
+{
+/* 
+/ this function attempts to set coordinates for <Node> items
+/ when required (an <Edge> is expected to be processed)
+*/
+
+/* attempting to fetch Node coordinates */
+    CPLXMLNode *psTopoCurve = CPLCreateXMLNode(NULL, CXT_Element, "TopoCurve");
+    CPLXMLNode *psDirEdge = CPLCreateXMLNode(psTopoCurve, CXT_Element, "directedEdge");
+    CPLXMLNode *psEdge = CPLCloneXMLTree((CPLXMLNode *)psNode);
+    CPLAddXMLChild( psDirEdge, psEdge );
+    OGRGeometryCollection *poColl = (OGRGeometryCollection *)
+                                    GML2OGRGeometry_XMLNode( psTopoCurve, FALSE );
+    CPLDestroyXMLNode( psTopoCurve );
+    if( poColl != NULL )
+    {
+        int iCount = poColl->getNumGeometries();
+        if( iCount == 1 )
+        {
+            OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(0);
+            int type = wkbFlatten( poChild->getGeometryType());
+            if( type == wkbLineString )
+            {
+                OGRLineString *poLine = (OGRLineString *)poChild;
+                int iPoints =  poLine->getNumPoints();
+                if( iPoints >= 2 )
+                {
+                    pItem->bHasCoords = TRUE;
+                    pItem->xNodeFrom = poLine->getX( 0 );
+                    pItem->yNodeFrom = poLine->getY( 0 );
+                    pItem->xNodeTo = poLine->getX( iPoints - 1 );
+                    pItem->yNodeTo = poLine->getY( iPoints - 1 );
+                    if( poLine->getCoordinateDimension() == 3 )
+                    {
+                        pItem->zNodeFrom = poLine->getZ( 0 );
+                        pItem->zNodeTo = poLine->getZ( iPoints - 1 );
+                        pItem->bHasZ = TRUE;
+                    }
+                    else
+                        pItem->bHasZ = FALSE;
+                }
+            }
+        }
+        delete poColl;
+    }
+	
+    /* searching the <directedNode> sub-tags */
+    const CPLXMLNode *psChild = psNode->psChild;
+    while( psChild != NULL )
+    {
+        if( psChild->eType == CXT_Element &&
+            EQUAL( psChild->pszValue, "directedNode" ) )
+        {
+            char cOrientation = '+';
+            const char *pszGmlId = NULL;
+            int bIsHref = FALSE;
+            const CPLXMLNode *psAttr = psChild->psChild;
+            while( psAttr != NULL )
+            {
+                if( psAttr->eType == CXT_Attribute &&
+                    EQUAL( psAttr->pszValue, "xlink:href" ) )
+                {
+                    const CPLXMLNode *psHref = psAttr->psChild;
+                    if( psHref != NULL )
+                    {
+                        if( psHref->eType == CXT_Text )
+                        {
+                            pszGmlId = psHref->pszValue;
+                            bIsHref = TRUE;
+                        }
+                    }
+                }
+                if( psAttr->eType == CXT_Attribute &&
+                    EQUAL( psAttr->pszValue, "orientation" ) )
+                {
+                    const CPLXMLNode *psOrientation = psAttr->psChild;
+                    if( psOrientation != NULL )
+                    {
+                        if( psOrientation->eType == CXT_Text )
+                        {
+                            cOrientation = *(psOrientation->pszValue);
+                        }
+                    }
+                }
+                if( psAttr->eType == CXT_Element &&
+                    EQUAL( psAttr->pszValue, "Node" ) )
+                {
+                    const CPLXMLNode *psId = psAttr->psChild;
+                    while( psId != NULL )
+                    {		
+                        if( psId->eType == CXT_Attribute &&
+                            EQUAL( psId->pszValue, "gml:id" ) )
+                        {
+                            const CPLXMLNode *psIdGml = psId->psChild;
+                            if( psIdGml != NULL )
+                            {
+                                if( psIdGml->eType == CXT_Text )
+                                {
+                                    pszGmlId = psIdGml->pszValue;
+                                    bIsHref = FALSE;
+                                }
+                            }
+                        }
+                        psId = psId->psNext;
+                    }
+                }
+                psAttr = psAttr->psNext;
+            }
+            if( pszGmlId != NULL )
+            {
+                CPLString* posNode;
+                if( bIsHref == TRUE )
+                {
+                    if (pszGmlId[0] != '#')
+                    {
+                        CPLError(CE_Warning, CPLE_NotSupported,
+                                 "Only values of xlink:href element starting with '#' are supported, "
+                                 "so %s will not be properly recognized", pszGmlId);
+                    }
+                    posNode = new CPLString(pszGmlId+1);
+                }
+                else
+                    posNode = new CPLString(pszGmlId);
+                if( cOrientation == '-' )
+                {
+                     pItem->gmlNodeFrom = posNode;
+                    pItem->bIsNodeFromHref = bIsHref;
+                }
+                else
+                {
+                    pItem->gmlNodeTo = posNode;
+                    pItem->bIsNodeToHref = bIsHref;
+                }
+                pszGmlId = NULL;
+                bIsHref = FALSE;
+                cOrientation = '+';
+            }
+        }
+        psChild = psChild->psNext;
+    }
+}
+
+static void gmlHugeFileCheckXrefs( struct huge_helper *helper, 
+                                   const CPLXMLNode *psNode )
+{
+/* identifying <Edge> GML nodes */
+    if( psNode->eType == CXT_Element )
+    {
+        if( EQUAL(psNode->pszValue, "Edge") == TRUE )
+        {
+            CPLString *gmlId = NULL;
+            if( gmlHugeFindGmlId( psNode, &gmlId ) == TRUE )
+            {
+                char * gmlText = CPLSerializeXMLTree((CPLXMLNode *)psNode);
+                CPLString *gmlValue = new CPLString(gmlText);
+                CPLFree( gmlText );
+                struct huge_tag *pItem = gmlHugeAddToHelper( helper, gmlId,
+                                                             gmlValue );
+                if( pItem != NULL )
+                    gmlHugeFileNodeCoords( pItem, psNode, &(helper->nodeSrs) );
+                else
+                {
+                    delete gmlId;
+                    delete gmlValue;
+                }
+            }
+        }
+    }
+
+    /* recursively scanning each Child GML node */
+    const CPLXMLNode *psChild = psNode->psChild;
+    while( psChild != NULL )
+    {
+        if( psChild->eType == CXT_Element )
+        {
+            if( EQUAL(psChild->pszValue, "Edge") == TRUE ||
+                EQUAL(psChild->pszValue, "directedEdge") == TRUE )
+            {
+                gmlHugeFileCheckXrefs( helper, psChild );
+            }
+            if( EQUAL(psChild->pszValue, "directedFace") == TRUE )
+            {
+                const CPLXMLNode *psFace = psChild->psChild;
+                if( psFace != NULL )
+                {
+                    if( psFace->eType == CXT_Element &&
+                        EQUAL(psFace->pszValue, "Face") == TRUE)
+                    {
+                        const CPLXMLNode *psDirEdge = psFace->psChild;
+                        while (psDirEdge != NULL)
+                        {
+                            const CPLXMLNode *psEdge = psDirEdge->psChild;
+                            while( psEdge != NULL)
+                            {
+                                if( psEdge->eType == CXT_Element &&
+                                    EQUAL(psEdge->pszValue, "Edge") == TRUE)
+                                    gmlHugeFileCheckXrefs( helper, psEdge );
+                                psEdge = psEdge->psNext;
+                            }
+                            psDirEdge = psDirEdge->psNext;
+                        }
+                    }
+                }
+            }
+        }
+        psChild = psChild->psNext;
+    }
+
+    /* recursively scanning each GML of the same level */
+    const CPLXMLNode *psNext = psNode->psNext;
+    while( psNext != NULL )
+    {
+        if( psNext->eType == CXT_Element )
+        {
+            if( EQUAL(psNext->pszValue, "Edge") == TRUE ||
+                EQUAL(psNext->pszValue, "directedEdge") == TRUE )
+            {
+                gmlHugeFileCheckXrefs( helper, psNext );
+            }
+        }
+        psNext = psNext->psNext;
+    }
+}
+
+static void gmlHugeFileCleanUp ( struct huge_helper *helper ) 
+{
+/* cleaning up any SQLite handle */
+    if( helper->hNodes != NULL )
+        sqlite3_finalize ( helper->hNodes );
+    if( helper->hEdges != NULL )
+        sqlite3_finalize ( helper->hEdges );
+    if( helper->hDB != NULL )
+        sqlite3_close( helper->hDB );
+    if( helper->nodeSrs != NULL )
+        delete helper->nodeSrs;
+}
+
+static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
+                                          const CPLXMLNode *psParent,
+                                          const CPLXMLNode *psNode )
+{
+/* identifying any xlink:href to be replaced */
+    if( psNode->eType == CXT_Element )
+    {
+        if( EQUAL(psNode->pszValue, "directedEdge") == TRUE )
+        {
+            char cOrientation = '+';
+            CPLXMLNode *psAttr = psNode->psChild;
+            while( psAttr != NULL )
+            {
+                if( psAttr->eType == CXT_Attribute &&
+                    EQUAL( psAttr->pszValue, "orientation" ) )
+                {
+                    const CPLXMLNode *psOrientation = psAttr->psChild;
+                    if( psOrientation != NULL )
+                    {
+                        if( psOrientation->eType == CXT_Text )
+                            cOrientation = *(psOrientation->pszValue);
+                    }
+                }
+                psAttr = psAttr->psNext;
+            }
+            psAttr = psNode->psChild;
+            while( psAttr != NULL )
+            {
+                if( psAttr->eType == CXT_Attribute &&
+                    EQUAL( psAttr->pszValue, "xlink:href" ) )
+                {
+                    const CPLXMLNode *pszHref = psAttr->psChild;
+                    if( pszHref != NULL )
+                    {
+                        if( pszHref->eType == CXT_Text )
+                        {
+                            if (pszHref->pszValue[0] != '#')
+                            {
+                                CPLError(CE_Warning, CPLE_NotSupported,
+                                        "Only values of xlink:href element starting with '#' are supported, "
+                                        "so %s will not be properly recognized", pszHref->pszValue);
+                            }
+                            CPLString *gmlId = new CPLString(pszHref->pszValue+1);
+                            gmlHugeAddPendingToHelper( helper, gmlId, psParent,
+                                                       psNode, TRUE, cOrientation );
+                        }
+                    }
+                }
+                psAttr = psAttr->psNext;
+            }
+        }
+    }
+
+    /* recursively scanning each Child GML node */
+    const CPLXMLNode *psChild = psNode->psChild;
+    while( psChild != NULL )
+    {
+        if( psChild->eType == CXT_Element )
+        {
+            if( EQUAL(psChild->pszValue, "directedEdge") == TRUE ||
+                EQUAL(psChild->pszValue, "directedFace") == TRUE ||
+                EQUAL(psChild->pszValue, "Face") == TRUE)
+            {
+                gmlHugeFileCheckPendingHrefs( helper, psNode, psChild );
+            }
+        }
+        psChild = psChild->psNext;
+    }
+
+    /* recursively scanning each GML of the same level */
+    const CPLXMLNode *psNext = psNode->psNext;
+    while( psNext != NULL )
+    {
+        if( psNext->eType == CXT_Element )
+        {
+            if( EQUAL(psNext->pszValue, "Face") == TRUE )
+            {
+                gmlHugeFileCheckPendingHrefs( helper, psParent, psNext );
+            }
+        }
+        psNext = psNext->psNext;
+    }
+}
+
+static void gmlHugeSetHrefGmlText( struct huge_helper *helper,
+                                   const char *pszGmlId,
+                                   const char *pszGmlText )
+{
+/* setting the GML text for the corresponding gml:id */
+    struct huge_href *pItem = helper->pFirstHref;
+    while( pItem != NULL )
+    {
+        if( EQUAL( pItem->gmlId->c_str(), pszGmlId ) == TRUE )
+        {
+            if( pItem->gmlText != NULL)
+                delete pItem->gmlText;
+            pItem->gmlText = new CPLString( pszGmlText );
+            return;
+        }
+        pItem = pItem->pNext;
+    }
+}
+
+static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
+                                              CPLXMLNode *psParent )
+{
+/* inserting a GML Node (parent) to be rewritted */
+    struct huge_parent *pItem = helper->pFirstParent;
+
+    /* checking if already exists */
+    while( pItem != NULL )
+    {
+        if( pItem->psParent == psParent )
+            return pItem;
+        pItem = pItem->pNext;
+    }
+
+    /* creating a new Parent Node */
+    pItem = new struct huge_parent;
+    pItem->psParent = psParent;
+    pItem->pFirst = NULL;
+    pItem->pLast = NULL;
+    pItem->pNext = NULL;
+    if( helper->pFirstParent == NULL )
+        helper->pFirstParent = pItem;
+    if( helper->pLastParent != NULL )
+        helper->pLastParent->pNext = pItem;
+    helper->pLastParent = pItem;
+
+    /* inserting any Child node into the Parent */
+    CPLXMLNode *psChild = psParent->psChild;
+    while( psChild != NULL )
+    {
+        struct huge_child *pChildItem;
+        pChildItem = new struct huge_child;
+        pChildItem->psChild = psChild;
+        pChildItem->pItem = NULL;
+        pChildItem->pNext = NULL;
+        if( pItem->pFirst == NULL )
+            pItem->pFirst = pChildItem;
+        if( pItem->pLast != NULL )
+            pItem->pLast->pNext = pChildItem;
+        pItem->pLast = pChildItem;
+        psChild = psChild->psNext;
+    }
+    return pItem;
+}
+
+static int gmlHugeSetChild( struct huge_parent *pParent,
+                            struct huge_href *pItem )
+{
+/* setting a Child Node to be rewritted */
+    struct huge_child *pChild = pParent->pFirst;
+    while( pChild != NULL )
+    {
+         if( pChild->psChild == pItem->psNode )
+         {
+            pChild->pItem = pItem;
+            return TRUE;
+         }
+         pChild = pChild->pNext;
+    }
+    return FALSE;
+}
+
+static int gmlHugeResolveEdges( struct huge_helper *helper,
+                                CPLXMLNode *psNode, sqlite3 *hDB )
+{
+/* resolving GML <Edge> xlink:href */
+    CPLString      osCommand;
+    sqlite3_stmt   *hStmtEdges;
+    int            rc;
+    int            bIsComma = FALSE;
+    int            bError = FALSE;
+    struct huge_href *pItem;
+    struct huge_parent *pParent;
+
+    /* query cursor [Edges] */
+    osCommand = "SELECT gml_id, gml_resolved "
+                "FROM gml_edges "
+                "WHERE gml_id IN (";
+    pItem = helper->pFirstHref;
+    while( pItem != NULL )
+    {
+        if( bIsComma == TRUE )
+            osCommand += ", ";
+        else
+            bIsComma = TRUE;
+        osCommand += "'";
+        osCommand += pItem->gmlId->c_str();
+        osCommand += "'";
+        pItem = pItem->pNext;
+    }
+    osCommand += ")";
+    rc = sqlite3_prepare( hDB, osCommand.c_str(), -1, &hStmtEdges, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create QUERY stmt for EDGES" );
+        return FALSE;
+    }
+    while ( TRUE )
+    {
+        rc = sqlite3_step( hStmtEdges );
+        if( rc == SQLITE_DONE )
+            break;
+        if ( rc == SQLITE_ROW )
+        {
+            const char *pszGmlId;
+            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 );
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "Edge xlink:href QUERY: sqlite3_step(%s)", 
+                      sqlite3_errmsg(hDB) );
+            bError = TRUE;
+            break;
+        }
+    }
+    sqlite3_finalize ( hStmtEdges );
+    if( bError == TRUE )
+        return FALSE;
+
+    /* indentifying any GML node to be rewritten */
+    pItem = helper->pFirstHref;
+    while( pItem != NULL )
+    {
+        if( pItem->gmlText == NULL || pItem->psParent == NULL ||
+            pItem->psNode == NULL )
+        {
+            bError = TRUE;
+            break;
+        }
+        pParent = gmlHugeFindParent( helper, (CPLXMLNode *)pItem->psParent );
+        if( gmlHugeSetChild( pParent, pItem ) == FALSE )
+        {
+            bError = TRUE;
+            break;
+        }
+        pItem = pItem->pNext;
+    }
+
+    if( bError == FALSE )
+    {
+    /* rewriting GML nodes */
+        pParent = helper->pFirstParent;
+        while( pParent != NULL )
+        {
+            struct huge_child *pChild;
+
+            /* removing any Child node from the Parent */
+            pChild = pParent->pFirst;
+            while( pChild != NULL )
+            {
+                CPLRemoveXMLChild( pParent->psParent, pChild->psChild );
+
+                /* destroyng any Child Node to be rewritten */
+                if( pChild->pItem != NULL )
+                    CPLDestroyXMLNode( pChild->psChild );
+                pChild = pChild->pNext;
+            }
+
+            /* rewriting the Parent Node */
+            pChild = pParent->pFirst;
+            while( pChild != NULL )
+            {
+                if( pChild->pItem == NULL )
+                {
+                    /* reinserting any untouched Child Node */
+                    CPLAddXMLChild( pParent->psParent, pChild->psChild );
+                }
+                else
+                {
+                    /* rewriting a Child Node */
+                    CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "directedEdge");
+                    if( pChild->pItem->cOrientation == '-' )
+                    {
+                        CPLXMLNode *psOrientationNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "orientation");
+                        CPLCreateXMLNode(psOrientationNode, CXT_Text, "-");
+                    }
+                    CPLXMLNode *psEdge = CPLParseXMLString(pChild->pItem->gmlText->c_str());
+                    CPLAddXMLChild( psNewNode, psEdge );
+                    CPLAddXMLChild( pParent->psParent, psNewNode );
+                }
+                pChild = pChild->pNext;
+            }
+            pParent = pParent->pNext;
+        }
+    }
+
+    /* resetting the Rewrite Helper to an empty state */
+    gmlHugeFileRewiterReset( helper );
+    if( bError == TRUE )
+        return FALSE;
+    return TRUE;
+}
+
+static int gmlHugeFileWriteResolved ( struct huge_helper *helper, 
+                                      const char *pszOutputFilename, 
+                                      GMLReader *pReader,
+                                      int *m_bSequentialLayers ) 
+{
+/* writing the resolved GML file */
+    VSILFILE       *fp;
+    GMLFeature     *poFeature;
+    const char     *osCommand;
+    int            rc;
+    sqlite3        *hDB = helper->hDB;
+    sqlite3_stmt   *hStmtNodes;
+    int            bError = FALSE;
+    int            iOutCount = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Opening the resolved GML file                                   */
+/* -------------------------------------------------------------------- */
+    fp = VSIFOpenL( pszOutputFilename, "w" );
+    if( fp == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Failed to open %.500s to write.", pszOutputFilename );
+        return FALSE;
+    }
+
+    /* query cursor [Nodes] */
+    osCommand = "SELECT gml_id, x, y, z "
+                "FROM nodes";
+    rc = sqlite3_prepare( hDB, osCommand, -1, &hStmtNodes, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to create QUERY stmt for NODES" );
+        VSIFCloseL( fp );
+        return FALSE;
+    }
+
+    VSIFPrintfL ( fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" ); 
+    VSIFPrintfL ( fp, "<ResolvedTopoFeatureCollection  "
+                      "xmlns:gml=\"http://www.opengis.net/gml\">\n" );		
+    VSIFPrintfL ( fp, "  <ResolvedTopoFeatureMembers>\n" );
+    /* exporting Nodes */
+    GFSTemplateList *pCC = new GFSTemplateList();
+    while ( TRUE )
+    {
+        rc = sqlite3_step( hStmtNodes );
+        if( rc == SQLITE_DONE )
+            break;
+        if ( rc == SQLITE_ROW )
+        {
+            const char *pszGmlId;
+            char* pszEscaped;
+            double x;
+            double y;
+            double z = 0.0;
+            int bHasZ = FALSE;
+            pszGmlId = (const char *)sqlite3_column_text ( hStmtNodes, 0 );
+            x = sqlite3_column_double ( hStmtNodes, 1 );
+            y = sqlite3_column_double ( hStmtNodes, 2 );
+            if ( sqlite3_column_type( hStmtNodes, 3 ) == SQLITE_FLOAT )
+            {
+                z = sqlite3_column_double ( hStmtNodes, 3 );
+                bHasZ = TRUE;
+            }
+
+            /* inserting a node into the resolved GML file */
+            pCC->Update( "ResolvedNodes", TRUE );
+            VSIFPrintfL ( fp, "    <ResolvedNodes>\n" );
+            pszEscaped = CPLEscapeString( pszGmlId, -1, CPLES_XML );
+            VSIFPrintfL ( fp, "      <NodeGmlId>%s</NodeGmlId>\n", pszEscaped );
+            CPLFree(pszEscaped);
+            VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
+            if ( helper->nodeSrs == NULL )
+                VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\">",
+                              ( bHasZ == TRUE ) ? 3 : 2 );
+            else
+            {
+                pszEscaped = CPLEscapeString( helper->nodeSrs->c_str(), -1, CPLES_XML );
+                VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\""
+                                  " srsName=\"%s\">",
+                                  ( bHasZ == TRUE ) ? 3 : 2,
+                              pszEscaped );
+                CPLFree(pszEscaped);
+            }
+            if ( bHasZ == TRUE )
+                VSIFPrintfL ( fp, "<gml:pos>%1.8f %1.8f %1.8f</gml:pos>"
+                                  "</gml:Point>\n",
+                              x, y, z );
+            else
+                VSIFPrintfL ( fp, "<gml:pos>%1.8f %1.8f</gml:pos>"
+                                  "</gml:Point>\n",
+                              x, y );
+            VSIFPrintfL ( fp, "      </ResolvedGeometry> \n" );
+            VSIFPrintfL ( fp, "    </ResolvedNodes>\n" );
+            iOutCount++;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "ResolvedNodes QUERY: sqlite3_step(%s)", 
+            sqlite3_errmsg(hDB) );
+            sqlite3_finalize ( hStmtNodes );
+            return FALSE;
+        }
+    }
+    sqlite3_finalize ( hStmtNodes );
+
+    /* processing GML features */
+    while( (poFeature = pReader->NextFeature()) != NULL )
+    {
+        GMLFeatureClass *poClass = poFeature->GetClass();
+        const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
+        int iPropCount = poClass->GetPropertyCount();
+		
+        int b_has_geom = FALSE;
+        VSIFPrintfL ( fp, "    <%s>\n", poClass->GetElementName() ); 
+
+        for( int iProp = 0; iProp < iPropCount; iProp++ )
+        {
+            GMLPropertyDefn *poPropDefn = poClass->GetProperty( iProp );
+            const char *pszPropName = poPropDefn->GetName();
+            const GMLProperty *poProp = poFeature->GetProperty( iProp );
+
+            if( poProp != NULL )
+            {
+                for( int iSub = 0; iSub < poProp->nSubProperties; iSub++ )
+                {
+                    char *gmlText = CPLEscapeString( poProp->papszSubProperties[iSub],
+                                                    -1,
+                                                    CPLES_XML );
+                    VSIFPrintfL ( fp, "      <%s>%s</%s>\n", 
+                                  pszPropName, gmlText, pszPropName ); 
+                    CPLFree( gmlText );
+                }
+            }
+        }
+
+        if( papsGeomList != NULL )
+        {
+            int i = 0;
+            const CPLXMLNode *psNode = papsGeomList[i];
+            while( psNode != NULL )
+            {
+                char *pszResolved = NULL;
+                int bNotToBeResolved;
+                if( psNode->eType != CXT_Element )
+                    bNotToBeResolved = TRUE;
+                else
+                {
+                    if( EQUAL(psNode->pszValue, "TopoCurve") == TRUE ||
+                        EQUAL(psNode->pszValue, "TopoSurface") == TRUE )
+                        bNotToBeResolved = FALSE;
+                    else
+                        bNotToBeResolved = TRUE;
+                }
+                if( bNotToBeResolved == TRUE )
+                {
+                    VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
+                    pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
+                    VSIFPrintfL ( fp, "        %s\n", pszResolved );
+                    CPLFree( pszResolved );
+                    VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
+                    b_has_geom = TRUE;
+                }
+                else
+                {
+                    gmlHugeFileCheckPendingHrefs( helper, psNode, psNode );
+                    if( helper->pFirstHref == NULL )
+                    {
+                        VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
+                        pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
+                        VSIFPrintfL ( fp, "        %s\n", pszResolved );
+                        CPLFree( pszResolved );
+                        VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
+                        b_has_geom = TRUE;
+                    }
+                    else
+                    {
+                        if( gmlHugeResolveEdges( helper, (CPLXMLNode *)psNode,
+                                                         hDB ) == FALSE)
+                            bError = TRUE;
+                        if( gmlHugeFileHrefCheck( helper ) == FALSE )
+							bError = TRUE;
+                        VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
+                        pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
+                        VSIFPrintfL ( fp, "        %s\n", pszResolved );
+                        CPLFree( pszResolved );
+                        VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
+                        b_has_geom = TRUE;
+                        gmlHugeFileHrefReset( helper );
+                    }
+                }
+                i++;
+                psNode = papsGeomList[i];
+            }
+        }
+        pCC->Update( poClass->GetElementName(), b_has_geom );
+
+        VSIFPrintfL ( fp, "    </%s>\n", poClass->GetElementName() ); 
+
+        delete poFeature;
+        iOutCount++;
+    }
+
+    VSIFPrintfL ( fp, "  </ResolvedTopoFeatureMembers>\n" ); 
+    VSIFPrintfL ( fp, "</ResolvedTopoFeatureCollection>\n" ); 
+
+    VSIFCloseL( fp );
+		
+    gmlUpdateFeatureClasses( pCC, pReader, m_bSequentialLayers );
+    if ( *m_bSequentialLayers == TRUE )
+        pReader->ReArrangeTemplateClasses( pCC );
+    delete pCC;
+    if( bError == TRUE || iOutCount == 0 )
+        return FALSE;
+    return TRUE;
+}
+
+/**************************************************************/
+/*                                                            */
+/* private member(s):                                         */
+/* any other funtion is implemented as "internal" static,     */
+/* so to make all the SQLite own stuff nicely "invisible"     */
+/*                                                            */
+/**************************************************************/
+
+int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
+                                 const int bSqliteIsTempFile,
+                                 const int iSqliteCacheMB )
+
+{
+    GMLFeature  *poFeature;
+    int iFeatureUID = 0;
+    int rc;
+    sqlite3 *hDB = NULL;
+    CPLString osSQLiteFilename;
+    const char *pszSQLiteFilename = NULL;
+    struct huge_helper helper;
+    char *pszErrMsg = NULL;
+
+    /* initializing the helper struct */
+    helper.hDB = NULL;
+    helper.hNodes = NULL;
+    helper.hEdges = NULL;
+    helper.nodeSrs = NULL;
+    helper.pFirst = NULL;
+    helper.pLast = NULL;
+    helper.pFirstHref = NULL;
+    helper.pLastHref = NULL;
+    helper.pFirstParent = NULL;
+    helper.pLastParent = NULL;
+	
+/* -------------------------------------------------------------------- */
+/*      Creating/Opening the SQLite DB file                             */
+/* -------------------------------------------------------------------- */
+    osSQLiteFilename = CPLResetExtension( m_pszFilename, "sqlite" );
+    pszSQLiteFilename = osSQLiteFilename.c_str();
+
+    VSIStatBufL statBufL;
+    if ( VSIStatExL ( pszSQLiteFilename, &statBufL, VSI_STAT_EXISTS_FLAG) == 0)
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "sqlite3_open(%s) failed:\n\tDB-file already exists", 
+                  pszSQLiteFilename );
+        return FALSE;
+    }
+
+    rc = sqlite3_open( pszSQLiteFilename, &hDB );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "sqlite3_open(%s) failed: %s", 
+                  pszSQLiteFilename, sqlite3_errmsg( hDB ) );
+        return FALSE;
+    }
+    helper.hDB = hDB;
+	
+/* 
+* setting SQLite for max speed; this is intrinsically unsafe,
+* and the DB file could be potentially damaged (power failure ...]
+*
+* but after all this one simply is a TEMPORARY FILE !!
+* so there is no real risk condition
+*/
+    rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL,
+                       &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to set PRAGMA synchronous = OFF: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+    }
+    rc = sqlite3_exec( hDB, "PRAGMA journal_mode = OFF", NULL, NULL,
+                       &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to set PRAGMA journal_mode = OFF: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+    }
+    rc = sqlite3_exec( hDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL,
+                       &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unable to set PRAGMA locking_mode = EXCLUSIVE: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+    }
+    
+    /* setting the SQLite cache */
+    if( iSqliteCacheMB > 0 )
+    {
+        int cache_size = iSqliteCacheMB * 1024;
+
+        /* refusing to allocate more than 1GB */
+        if( cache_size > 1024 * 1024 )
+            cache_size = 1024 * 1024;
+        char sqlPragma[1024];
+        sprintf( sqlPragma, "PRAGMA cache_size = %d", cache_size );
+        rc = sqlite3_exec( hDB, sqlPragma, NULL, NULL, &pszErrMsg );
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to set %s: %s", sqlPragma, pszErrMsg );
+            sqlite3_free( pszErrMsg );
+        }
+    }
+	
+    if( !SetupParser() )
+    {
+        gmlHugeFileCleanUp ( &helper );
+        return FALSE;
+    }
+
+    /* creating SQLite tables and Insert cursors */
+    if( gmlHugeFileSQLiteInit( &helper ) == FALSE )
+    {
+        gmlHugeFileCleanUp ( &helper );
+        return FALSE;
+    }
+
+    /* processing GML features */
+    while( (poFeature = NextFeature()) != NULL )
+    {
+        const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
+        if (papsGeomList != NULL)
+        {
+            int i = 0;
+            const CPLXMLNode *psNode = papsGeomList[i];
+            while(psNode)
+            {
+                gmlHugeFileCheckXrefs( &helper, psNode );
+                /* inserting into the SQLite DB any appropriate row */
+                gmlHugeFileSQLiteInsert ( &helper );
+                /* resetting an empty helper struct */
+                gmlHugeFileReset ( &helper );
+                i ++;
+                psNode = papsGeomList[i];
+            }
+        }
+        iFeatureUID++;
+        delete poFeature;
+    }
+
+    /* finalizing any SQLite Insert cursor */
+    if( helper.hNodes != NULL )
+        sqlite3_finalize ( helper.hNodes );
+    helper.hNodes = NULL;
+    if( helper.hEdges != NULL )
+        sqlite3_finalize ( helper.hEdges );
+    helper.hEdges = NULL;
+
+    /* confirming the still pending TRANSACTION */
+    rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Unable to perform COMMIT TRANSACTION: %s",
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return FALSE;
+    }
+
+/* attempting to resolve GML strings */
+    if( gmlHugeFileResolveEdges( &helper ) == FALSE )
+    {
+        gmlHugeFileCleanUp ( &helper );
+        return FALSE;
+    }
+	
+    /* restarting the GML parser */
+    if( !SetupParser() )
+    {
+        gmlHugeFileCleanUp ( &helper );
+        return FALSE;
+    }
+
+    /* output: writing the revolved GML file */
+    if ( gmlHugeFileWriteResolved( &helper, pszOutputFilename, this, 
+                                   &m_bSequentialLayers ) == FALSE)
+    {
+        gmlHugeFileCleanUp ( &helper );
+        return FALSE;
+    }
+
+    gmlHugeFileCleanUp ( &helper );
+    if ( bSqliteIsTempFile == TRUE )
+        VSIUnlink( pszSQLiteFilename );
+    return TRUE;
+}
+
+/**************************************************************/
+/*                                                            */
+/* an alternative <xlink:href> resolver based on SQLite       */
+/*                                                            */
+/**************************************************************/
+int GMLReader::HugeFileResolver( const char *pszFile,
+                                 int bSqliteIsTempFile,
+                                 int iSqliteCacheMB )
+
+{
+    // Check if the original source file is set.
+    if( m_pszFilename == NULL )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+        "GML source file needs to be set first with "
+        "GMLReader::SetSourceFile()." );
+        return FALSE;
+    }
+    if ( ParseXMLHugeFile( pszFile, bSqliteIsTempFile, iSqliteCacheMB ) == FALSE )
+        return FALSE;
+
+    //set the source file to the resolved file
+    CleanupParser();
+    if (fpGML)
+        VSIFCloseL(fpGML);
+    fpGML = NULL;
+    CPLFree( m_pszFilename );
+    m_pszFilename = CPLStrdup( pszFile );
+    return TRUE;
+}
+
+#else  // HAVE_SQLITE
+
+/**************************************************/
+/*    if SQLite support isn't available we'll     */
+/*    simply output an error message              */
+/**************************************************/
+
+int GMLReader::HugeFileResolver( const char *pszFile,
+                                 int bSqliteIsTempFile,
+                                 int iSqliteCacheMB )
+
+{
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "OGR was built without SQLite3 support\n"
+              "... sorry, the HUGE GML resolver is unsupported\n" );
+    return FALSE;
+}
+
+int GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
+                                 const int bSqliteIsTempFile,
+                                 const int iSqliteCacheMB )
+{
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "OGR was built without SQLite3 support\n"
+              "... sorry, the HUGE GML resolver is unsupported\n" );
+    return FALSE;
+}
+
+#endif // HAVE_SQLITE
diff --git a/ogr/ogrsf_frmts/gml/makefile.vc b/ogr/ogrsf_frmts/gml/makefile.vc
index 149ea1c..abcc7d7 100644
--- a/ogr/ogrsf_frmts/gml/makefile.vc
+++ b/ogr/ogrsf_frmts/gml/makefile.vc
@@ -1,6 +1,7 @@
 
 LL_OBJ	=	gmlpropertydefn.obj gmlfeatureclass.obj gmlfeature.obj \
-		gmlreader.obj parsexsd.obj resolvexlinks.obj gmlutils.obj $(X_OBJ)
+		gmlreader.obj parsexsd.obj resolvexlinks.obj hugefileresolver.obj gmlutils.obj \
+		gmlreadstate.obj gmlhandler.obj trstring.obj  gfstemplate.obj
 OGR_OBJ	=	ogrgmldriver.obj ogrgmldatasource.obj ogrgmllayer.obj
 
 OBJ	=	$(LL_OBJ) $(OGR_OBJ)
@@ -9,23 +10,22 @@ GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
+EXTRAFLAGS = 	-I.. -I..\.. $(XERCES_EXTRAFLAGS) $(EXPAT_EXTRAFLAGS) $(SQLITE_EXTRAFLAGS)
+
 # By default, XML validation is disabled.  Uncomment the following line to
 # enable XML schema validation in the parser.
 #OGR_GML_VALIDATION = -DOGR_GML_VALIDATION=1
 
 !IFDEF XERCES_DIR
-X_OBJ =		gmlreadstate.obj gmlhandler.obj trstring.obj
-EXTRAFLAGS =	-I.. -I..\.. $(XERCES_INCLUDE) -DHAVE_XERCES=1 \
-                $(OGR_GML_VALIDATION)
-!ELSE
+XERCES_EXTRAFLAGS =	$(XERCES_INCLUDE) -DHAVE_XERCES $(OGR_GML_VALIDATION)
+!ENDIF
 
 !IFDEF EXPAT_DIR
-X_OBJ =		gmlreadstate.obj gmlhandler.obj
-EXTRAFLAGS =    -I.. -I..\.. -DHAVE_XERCES=0 $(EXPAT_INCLUDE) -DHAVE_EXPAT=1 
-!ELSE
-EXTRAFLAGS =    -I.. -I..\.. -DHAVE_XERCES=0
+EXPAT_EXTRAFLAGS =    $(EXPAT_INCLUDE) -DHAVE_EXPAT
 !ENDIF
 
+!IFDEF SQLITE_INC
+SQLITE_EXTRAFLAGS = $(SQLITE_INC) -DHAVE_SQLITE
 !ENDIF
 
 # By default, XML validation is disabled.  Uncomment the following line to
diff --git a/ogr/ogrsf_frmts/gml/ogr_gml.h b/ogr/ogrsf_frmts/gml/ogr_gml.h
index 31ffd60..63bca3d 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 21383 2011-01-03 18:58:41Z rouault $
+ * $Id: ogr_gml.h 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Declarations for OGR wrapper classes for GML, and GML<->OGR
@@ -36,6 +36,13 @@
 
 class OGRGMLDataSource;
 
+typedef enum
+{
+    STANDARD,
+    SEQUENTIAL_LAYERS,
+    INTERLEAVED_LAYERS
+} ReadMode;
+
 /************************************************************************/
 /*                            OGRGMLLayer                               */
 /************************************************************************/
@@ -56,7 +63,11 @@ class OGRGMLLayer : public OGRLayer
 
     GMLFeatureClass     *poFClass;
 
-    int                 m_bInvertAxisOrderIfLatLong;
+    void                *hCacheSRS;
+
+    int                 bUseOldFIDFormat;
+
+    int                 bFaceHoleNegative;
 
   public:
                         OGRGMLLayer( const char * pszName, 
@@ -106,11 +117,14 @@ class OGRGMLDataSource : public OGRDataSource
     VSILFILE           *fpOutput;
     int                 bFpOutputIsNonSeekable;
     int                 bFpOutputSingleFile;
-    OGREnvelope         sBoundingRect;
+    OGREnvelope3D       sBoundingRect;
+    int                 bBBOX3D;
     int                 nBoundedByLocation;
     
     int                 nSchemaInsertLocation;
     int                 bIsOutputGML3;
+    int                 bIsOutputGML3Deegree; /* if TRUE, then bIsOutputGML3 is also TRUE */
+    int                 bIsOutputGML32; /* if TRUE, then bIsOutputGML3 is also TRUE */
     int                 bIsLongSRSRequired;
     int                 bWriteSpaceIndentation;
 
@@ -121,10 +135,19 @@ class OGRGMLDataSource : public OGRDataSource
     void                InsertHeader();
 
     int                 bExposeGMLId;
+    int                 bExposeFid;
     int                 bIsWFS;
 
     OGRSpatialReference* poGlobalSRS;
 
+    int                 m_bInvertAxisOrderIfLatLong;
+    int                 m_bConsiderEPSGAsURN;
+    int                 m_bGetSecondaryGeometryOption;
+
+    ReadMode            eReadMode;
+    GMLFeature         *poStoredGMLFeature;
+    OGRGMLLayer        *poLastReadLayer;
+
   public:
                         OGRGMLDataSource();
                         ~OGRGMLDataSource();
@@ -143,19 +166,32 @@ class OGRGMLDataSource : public OGRDataSource
 
     int                 TestCapability( const char * );
 
-    VSILFILE            *GetOutputFP() { return fpOutput; }
-    IGMLReader          *GetReader() { return poReader; }
+    VSILFILE            *GetOutputFP() const { return fpOutput; }
+    IGMLReader          *GetReader() const { return poReader; }
 
-    void                GrowExtents( OGREnvelope *psGeomBounds );
+    void                GrowExtents( OGREnvelope3D *psGeomBounds, int nCoordDimension );
 
-    int                 ExposeGMLId() { return bExposeGMLId; }
+    int                 ExposeId() const { return bExposeGMLId || bExposeFid; }
 
     static void         PrintLine(VSILFILE* fp, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT (2, 3);
 
-    int                 IsGML3Output() { return bIsOutputGML3; }
-    int                 IsLongSRSRequired() { return bIsLongSRSRequired; }
-    int                 WriteSpaceIndentation() { return bWriteSpaceIndentation; }
+    int                 IsGML3Output() const { return bIsOutputGML3; }
+    int                 IsGML3DeegreeOutput() const { return bIsOutputGML3Deegree; }
+    int                 IsGML32Output() const { return bIsOutputGML32; }
+    int                 IsLongSRSRequired() const { return bIsLongSRSRequired; }
+    int                 WriteSpaceIndentation() const { return bWriteSpaceIndentation; }
     const char         *GetGlobalSRSName();
+
+    int                 GetInvertAxisOrderIfLatLong() const { return m_bInvertAxisOrderIfLatLong; }
+    int                 GetConsiderEPSGAsURN() const { return m_bConsiderEPSGAsURN; }
+    int                 GetSecondaryGeometryOption() const { return m_bGetSecondaryGeometryOption; }
+
+    ReadMode            GetReadMode() const { return eReadMode; }
+    void                SetStoredGMLFeature(GMLFeature* poStoredGMLFeatureIn) { poStoredGMLFeature = poStoredGMLFeatureIn; }
+    GMLFeature*         PeekStoredGMLFeature() const { return  poStoredGMLFeature; }
+
+    OGRGMLLayer*        GetLastReadLayer() const { return poLastReadLayer; }
+    void                SetLastReadLayer(OGRGMLLayer* poLayer) { poLastReadLayer = poLayer; }
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
index 9a6a411..f662804 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldatasource.cpp 21383 2011-01-03 18:58:41Z rouault $
+ * $Id: ogrgmldatasource.cpp 23573 2011-12-14 12:13:48Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLDataSource class.
@@ -25,6 +25,13 @@
  * 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.
+ *
+ ******************************************************************************
+ * Contributor: Alessandro Furieri, a.furieri at lqt.it
+ * Portions of this module implenting GML_SKIP_RESOLVE_ELEMS HUGE
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
+ *
  ****************************************************************************/
 
 #include "ogr_gml.h"
@@ -36,7 +43,7 @@
 
 #include <vector>
 
-CPL_CVSID("$Id: ogrgmldatasource.cpp 21383 2011-01-03 18:58:41Z rouault $");
+CPL_CVSID("$Id: ogrgmldatasource.cpp 23573 2011-12-14 12:13:48Z rouault $");
 
 /************************************************************************/
 /*                         OGRGMLDataSource()                         */
@@ -54,6 +61,8 @@ OGRGMLDataSource::OGRGMLDataSource()
     bFpOutputIsNonSeekable = FALSE;
     bFpOutputSingleFile = FALSE;
     bIsOutputGML3 = FALSE;
+    bIsOutputGML3Deegree = FALSE;
+    bIsOutputGML32 = FALSE;
     bIsLongSRSRequired = FALSE;
     bWriteSpaceIndentation = TRUE;
 
@@ -61,11 +70,21 @@ OGRGMLDataSource::OGRGMLDataSource()
     bOutIsTempFile = FALSE;
 
     bExposeGMLId = FALSE;
+    bExposeFid = FALSE;
     nSchemaInsertLocation = -1;
     nBoundedByLocation = -1;
+    bBBOX3D = FALSE;
 
     poGlobalSRS = NULL;
     bIsWFS = FALSE;
+
+    eReadMode = STANDARD;
+    poStoredGMLFeature = NULL;
+    poLastReadLayer = NULL;
+
+    m_bInvertAxisOrderIfLatLong = FALSE;
+    m_bConsiderEPSGAsURN = FALSE;
+    m_bGetSecondaryGeometryOption = FALSE;
 }
 
 /************************************************************************/
@@ -105,18 +124,18 @@ OGRGMLDataSource::~OGRGMLDataSource()
                 char szLowerCorner[75], szUpperCorner[75];
                 if (bCoordSwap)
                 {
-                    OGRMakeWktCoordinate(szLowerCorner, sBoundingRect.MinY, sBoundingRect.MinX, 0, 2);
-                    OGRMakeWktCoordinate(szUpperCorner, sBoundingRect.MaxY, sBoundingRect.MaxX, 0, 2);
+                    OGRMakeWktCoordinate(szLowerCorner, sBoundingRect.MinY, sBoundingRect.MinX, sBoundingRect.MinZ, (bBBOX3D) ? 3 : 2);
+                    OGRMakeWktCoordinate(szUpperCorner, sBoundingRect.MaxY, sBoundingRect.MaxX, sBoundingRect.MaxZ, (bBBOX3D) ? 3 : 2);
                 }
                 else
                 {
-                    OGRMakeWktCoordinate(szLowerCorner, sBoundingRect.MinX, sBoundingRect.MinY, 0, 2);
-                    OGRMakeWktCoordinate(szUpperCorner, sBoundingRect.MaxX, sBoundingRect.MaxY, 0, 2);
+                    OGRMakeWktCoordinate(szLowerCorner, sBoundingRect.MinX, sBoundingRect.MinY, sBoundingRect.MinZ, (bBBOX3D) ? 3 : 2);
+                    OGRMakeWktCoordinate(szUpperCorner, sBoundingRect.MaxX, sBoundingRect.MaxY, sBoundingRect.MaxZ, (bBBOX3D) ? 3 : 2);
                 }
                 if (bWriteSpaceIndentation)
                     VSIFPrintfL( fpOutput, "  ");
-                PrintLine( fpOutput, "<gml:boundedBy><gml:Envelope%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
-                                pszSRSName, szLowerCorner, szUpperCorner);
+                PrintLine( fpOutput, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
+                           (bBBOX3D) ? " srsDimension=\"3\"" : "", pszSRSName, szLowerCorner, szUpperCorner);
                 CPLFree(pszSRSName);
             }
             else
@@ -129,16 +148,24 @@ OGRGMLDataSource::~OGRGMLDataSource()
                 PrintLine( fpOutput, "<gml:Box>" );
                 if (bWriteSpaceIndentation)
                     VSIFPrintfL( fpOutput, "      ");
-                PrintLine( fpOutput,
+                VSIFPrintfL( fpOutput,
                             "<gml:coord><gml:X>%.16g</gml:X>"
-                            "<gml:Y>%.16g</gml:Y></gml:coord>",
+                            "<gml:Y>%.16g</gml:Y>",
                             sBoundingRect.MinX, sBoundingRect.MinY );
+                if (bBBOX3D)
+                    VSIFPrintfL( fpOutput, "<gml:Z>%.16g</gml:Z>",
+                               sBoundingRect.MinZ );
+                PrintLine( fpOutput, "</gml:coord>");
                 if (bWriteSpaceIndentation)
                     VSIFPrintfL( fpOutput, "      ");
-                PrintLine( fpOutput,
+                VSIFPrintfL( fpOutput,
                             "<gml:coord><gml:X>%.16g</gml:X>"
-                            "<gml:Y>%.16g</gml:Y></gml:coord>",
+                            "<gml:Y>%.16g</gml:Y>",
                             sBoundingRect.MaxX, sBoundingRect.MaxY );
+                if (bBBOX3D)
+                    VSIFPrintfL( fpOutput, "<gml:Z>%.16g</gml:Z>",
+                               sBoundingRect.MaxZ );
+                PrintLine( fpOutput, "</gml:coord>");
                 if (bWriteSpaceIndentation)
                     VSIFPrintfL( fpOutput, "    ");
                 PrintLine( fpOutput, "</gml:Box>" );
@@ -168,6 +195,8 @@ OGRGMLDataSource::~OGRGMLDataSource()
     }
 
     delete poGlobalSRS;
+
+    delete poStoredGMLFeature;
 }
 
 /************************************************************************/
@@ -180,6 +209,9 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
     VSILFILE   *fp;
     char        szHeader[2048];
     int         nNumberOfFeatures = 0;
+    CPLString   osWithVsiGzip;
+
+    pszName = CPLStrdup( pszNewName );
 
 /* -------------------------------------------------------------------- */
 /*      Open the source file.                                           */
@@ -195,6 +227,10 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
         return FALSE;
     }
 
+    int bExpatCompatibleEncoding = FALSE;
+    int bHas3D = FALSE;
+    int bHintConsiderEPSGAsURN = FALSE;
+
 /* -------------------------------------------------------------------- */
 /*      If we aren't sure it is GML, load a header chunk and check      */
 /*      for signs it is GML                                             */
@@ -209,6 +245,31 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
         }
         szHeader[MIN(nRead, sizeof(szHeader))-1] = '\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(pszNewName), "gz") &&
+             strncmp(pszNewName, "/vsigzip/", strlen("/vsigzip/")) != 0 )
+        {
+            VSIFCloseL( fp );
+            osWithVsiGzip = "/vsigzip/";
+            osWithVsiGzip += pszNewName;
+
+            pszNewName = osWithVsiGzip;
+
+            fp = VSIFOpenL( pszNewName, "r" );
+            if( fp == NULL )
+                return FALSE;
+
+            nRead = VSIFReadL( szHeader, 1, sizeof(szHeader), fp );
+            if (nRead <= 0)
+            {
+                VSIFCloseL( fp );
+                return FALSE;
+            }
+            szHeader[MIN(nRead, sizeof(szHeader))-1] = '\0';
+        }
+
 /* -------------------------------------------------------------------- */
 /*      Check for a UTF-8 BOM and skip if found                         */
 /*                                                                      */
@@ -226,6 +287,16 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
             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-1", 10));
+        else
+            bExpatCompatibleEncoding = TRUE; /* utf-8 is the default */
+
+        bHas3D = strstr(szPtr, "srsDimension=\"3\"") != NULL || strstr(szPtr, "<gml:Z>") != NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Here, we expect the opening chevrons of GML tree root element   */
 /* -------------------------------------------------------------------- */
@@ -256,10 +327,23 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
             const char* pszNumberOfFeatures = strstr(szPtr, "numberOfFeatures=");
             if (pszNumberOfFeatures)
             {
-                char ch = pszNumberOfFeatures[17];
-                if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 17 + 1, ch) != NULL)
+                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 += 15;
+                char ch = pszNumberOfFeatures[0];
+                if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 1, ch) != NULL)
                 {
-                    nNumberOfFeatures = atoi(pszNumberOfFeatures + 17 + 1);
+                    /* '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);
                 }
             }
         }
@@ -271,6 +355,23 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
             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);
+        }
+
+        bHintConsiderEPSGAsURN = strstr(szPtr, "xmlns:fme=\"http://www.safe.com/gml/fme\"") != NULL;
     }
     
 /* -------------------------------------------------------------------- */
@@ -278,8 +379,56 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
 /*      GMLReader on it.                                                */
 /* -------------------------------------------------------------------- */
     VSIFCloseL( fp );
-    
-    poReader = CreateGMLReader();
+
+    const char* pszReadMode = CPLGetConfigOption("GML_READ_MODE", NULL);
+    if (pszReadMode == NULL || EQUAL(pszReadMode, "STANDARD"))
+        eReadMode = STANDARD;
+    else if (EQUAL(pszReadMode, "SEQUENTIAL_LAYERS"))
+        eReadMode = SEQUENTIAL_LAYERS;
+    else if (EQUAL(pszReadMode, "INTERLEAVED_LAYERS"))
+        eReadMode = INTERLEAVED_LAYERS;
+    else
+    {
+        CPLDebug("GML", "Unrecognized value for GML_READ_MODE configuration option.");
+    }
+
+    m_bInvertAxisOrderIfLatLong = CSLTestBoolean(
+        CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES"));
+
+    const char* pszConsiderEPSGAsURN =
+        CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", NULL);
+    if (pszConsiderEPSGAsURN != NULL)
+        m_bConsiderEPSGAsURN = CSLTestBoolean(pszConsiderEPSGAsURN);
+    else if (bHintConsiderEPSGAsURN)
+    {
+        /* GML produced by FME (at least CanVec GML) seem to honour EPSG axis ordering */
+        CPLDebug("GML", "FME-produced GML --> consider that GML_CONSIDER_EPSG_AS_URN is set to YES");
+        m_bConsiderEPSGAsURN = TRUE;
+    }
+    else
+        m_bConsiderEPSGAsURN = FALSE;
+
+    m_bGetSecondaryGeometryOption = CSLTestBoolean(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
+
+    /* EXPAT is faster than Xerces, so when it is safe to use it, use it ! */
+    /* The only interest of Xerces is for rare encodings that Expat doesn't handle */
+    /* but UTF-8 is well handled by Expat */
+    int bUseExpatParserPreferably = bExpatCompatibleEncoding;
+
+    /* Override default choice */
+    const char* pszGMLParser = CPLGetConfigOption("GML_PARSER", NULL);
+    if (pszGMLParser)
+    {
+        if (EQUAL(pszGMLParser, "EXPAT"))
+            bUseExpatParserPreferably = TRUE;
+        else if (EQUAL(pszGMLParser, "XERCES"))
+            bUseExpatParserPreferably = FALSE;
+    }
+
+    poReader = CreateGMLReader( bUseExpatParserPreferably,
+                                m_bInvertAxisOrderIfLatLong,
+                                m_bConsiderEPSGAsURN,
+                                m_bGetSecondaryGeometryOption );
     if( poReader == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -300,6 +449,7 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
     char *pszXlinkResolvedFilename = NULL;
     const char *pszOption = CPLGetConfigOption("GML_SAVE_RESOLVED_TO", NULL);
     int bResolve = TRUE;
+    int bHugeFile = FALSE;
     if( pszOption != NULL && EQUALN( pszOption, "SAME", 4 ) )
     {
         // "SAME" will overwrite the existing gml file
@@ -344,45 +494,102 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
     char **papszSkip = NULL;
     if( EQUAL( pszSkipOption, "ALL" ) )
         bResolve = FALSE;
+    else if( EQUAL( pszSkipOption, "HUGE" ) )//exactly as NONE, but intended for HUGE files
+        bHugeFile = TRUE;
     else if( !EQUAL( pszSkipOption, "NONE" ) )//use this to resolve everything
         papszSkip = CSLTokenizeString2( pszSkipOption, ",",
                                            CSLT_STRIPLEADSPACES |
                                            CSLT_STRIPENDSPACES );
+    const char *pszGFSFilename;
+    VSIStatBufL sGFSStatBuf, sGMLStatBuf;
+    int         bHaveSchema = FALSE;
+    int         bSchemaDone = FALSE;
+ 
+/* -------------------------------------------------------------------- */
+/*      Is some GML Feature Schema (.gfs) TEMPLATE required ?           */
+/* -------------------------------------------------------------------- */
+    const char *pszGFSTemplateName = 
+                CPLGetConfigOption( "GML_GFS_TEMPLATE", NULL);
+    if( pszGFSTemplateName != NULL )
+    {
+        /* attempting to load the GFS TEMPLATE */
+        bHaveSchema = poReader->LoadClasses( pszGFSTemplateName );
+    }	
 
     if( bResolve )
     {
-        poReader->ResolveXlinks( pszXlinkResolvedFilename,
-                                 &bOutIsTempFile,
-                                 papszSkip );
+        if ( bHugeFile )
+        {
+            bSchemaDone = TRUE;
+            int bSqliteIsTempFile =
+                CSLTestBoolean(CPLGetConfigOption( "GML_HUGE_TEMPFILE", "YES"));
+            int iSqliteCacheMB = atoi(CPLGetConfigOption( "OGR_SQLITE_CACHE", "0"));
+            if( poReader->HugeFileResolver( pszXlinkResolvedFilename,
+                                            bSqliteIsTempFile, 
+                                            iSqliteCacheMB ) == FALSE )
+            {
+                // we assume an errors have been reported.
+                return FALSE;
+            }
+        }
+        else
+        {
+            poReader->ResolveXlinks( pszXlinkResolvedFilename,
+                                     &bOutIsTempFile,
+                                     papszSkip );
+        }
     }
 
     CPLFree( pszXlinkResolvedFilename );
+    pszXlinkResolvedFilename = NULL;
     CSLDestroy( papszSkip );
+    papszSkip = NULL;
 
-    pszName = CPLStrdup( pszNewName );
+    /* Is a prescan required ? */
+    if( bHaveSchema && !bSchemaDone )
+    {
+        /* We must detect which layers are actually present in the .gml */
+        /* and how many features they have */
+        if( !poReader->PrescanForTemplate() )
+        {
+            // we assume an errors have been reported.
+            return FALSE;
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Can we find a GML Feature Schema (.gfs) for the input file?     */
 /* -------------------------------------------------------------------- */
-    const char *pszGFSFilename;
-    VSIStatBufL sGFSStatBuf, sGMLStatBuf;
-    int        bHaveSchema = FALSE;
-
-    pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
-    if( VSIStatL( pszGFSFilename, &sGFSStatBuf ) == 0 )
+    if( !bHaveSchema )
     {
-        VSIStatL( pszNewName, &sGMLStatBuf );
-
-        if( sGMLStatBuf.st_mtime > sGFSStatBuf.st_mtime )
-        {
-            CPLDebug( "GML", 
-                      "Found %s but ignoring because it appears\n"
-                      "be older than the associated GML file.", 
-                      pszGFSFilename );
-        }
-        else
+        pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
+        if (strncmp(pszGFSFilename, "/vsigzip/", strlen("/vsigzip/")) == 0)
+            pszGFSFilename += strlen("/vsigzip/");
+        if( VSIStatL( pszGFSFilename, &sGFSStatBuf ) == 0 )
         {
-            bHaveSchema = poReader->LoadClasses( pszGFSFilename );
+            VSIStatL( pszNewName, &sGMLStatBuf );
+            if( sGMLStatBuf.st_mtime > sGFSStatBuf.st_mtime )
+            {
+                CPLDebug( "GML", 
+                          "Found %s but ignoring because it appears\n"
+                          "be older than the associated GML file.", 
+                          pszGFSFilename );
+            }
+            else
+            {
+                bHaveSchema = poReader->LoadClasses( pszGFSFilename );
+                if (bHaveSchema)
+                {
+                    const char *pszXSDFilename;
+                    pszXSDFilename = CPLResetExtension( pszNewName, "xsd" );
+                    if( VSIStatExL( pszXSDFilename, &sGMLStatBuf,
+                                    VSI_STAT_EXISTS_FLAG ) == 0 )
+                    {
+                        CPLDebug("GML", "Using %s file, ignoring %s",
+                                 pszGFSFilename, pszXSDFilename);
+                    }
+                }
+            }
         }
     }
 
@@ -393,12 +600,15 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
 /*      just hopes it is in the same director with the same name.       */
 /* -------------------------------------------------------------------- */
     const char *pszXSDFilename;
+    int bHasFoundXSD = FALSE;
 
     if( !bHaveSchema )
     {
         pszXSDFilename = CPLResetExtension( pszNewName, "xsd" );
         if( VSIStatL( pszXSDFilename, &sGMLStatBuf ) == 0 )
         {
+            bHasFoundXSD = TRUE;
+
             std::vector<GMLFeatureClass*> aosClasses;
             bHaveSchema = GMLParseXSD( pszXSDFilename, aosClasses );
             if (bHaveSchema)
@@ -409,22 +619,47 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
                 {
                     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)
+                    {
+                        poClass->SetGeometryType(
+                            poClass->GetGeometryType() | wkb25DBit);
+                    }
                     poReader->AddClass( poClass );
                 }
                 poReader->SetClassListLocked( TRUE );
             }
         }
     }
-    
+
 /* -------------------------------------------------------------------- */
 /*      Force a first pass to establish the schema.  Eventually we      */
 /*      will have mechanisms for remembering the schema and related     */
 /*      information.                                                    */
 /* -------------------------------------------------------------------- */
-    if( !bHaveSchema && !poReader->PrescanForSchema( TRUE ) )
+    if( !bHaveSchema )
     {
-        // we assume an errors have been reported.
-        return FALSE;
+        if( !poReader->PrescanForSchema( TRUE ) )
+        {
+            // we assume an errors have been reported.
+            return FALSE;
+        }
+
+        if( bHasFoundXSD )
+        {
+            CPLDebug("GML", "Generating %s file, ignoring %s",
+                     pszGFSFilename, pszXSDFilename);
+        }
+    }
+
+    if (poReader->GetClassCount() > 1 && poReader->IsSequentialLayers() &&
+        pszReadMode == NULL)
+    {
+        CPLDebug("GML", "Layers are monoblock. Using SEQUENTIAL_LAYERS read mode");
+        eReadMode = SEQUENTIAL_LAYERS;
     }
 
 /* -------------------------------------------------------------------- */
@@ -433,13 +668,17 @@ int OGRGMLDataSource::Open( const char * pszNewName, int bTestOpen )
 /* -------------------------------------------------------------------- */
     if( !bHaveSchema && !poReader->HasStoppedParsing() &&
         !EQUALN(pszNewName, "/vsitar/", strlen("/vsitar/")) &&
-        !EQUALN(pszNewName, "/vsigzip/", strlen("/vsigzip/")) &&
         !EQUALN(pszNewName, "/vsizip/", strlen("/vsizip/")) &&
+        !EQUALN(pszNewName, "/vsigzip/vsi", strlen("/vsigzip/vsi")) &&
+        !EQUALN(pszNewName, "/vsigzip//vsi", strlen("/vsigzip//vsi")) &&
         !EQUALN(pszNewName, "/vsicurl/", strlen("/vsicurl/")))
     {
         VSILFILE    *fp = NULL;
 
         pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
+        if (strncmp(pszGFSFilename, "/vsigzip/", strlen("/vsigzip/")) == 0)
+            pszGFSFilename += strlen("/vsigzip/");
+
         if( VSIStatL( pszGFSFilename, &sGFSStatBuf ) != 0 
             && (fp = VSIFOpenL( pszGFSFilename, "wt" )) != NULL )
         {
@@ -528,6 +767,11 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         OGRFieldDefn oField( "gml_id", OFTString );
         poLayer->GetLayerDefn()->AddFieldDefn( &oField );
     }
+    else if (bExposeFid)
+    {
+        OGRFieldDefn oField( "fid", OFTString );
+        poLayer->GetLayerDefn()->AddFieldDefn( &oField );
+    }
 
     for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
     {
@@ -591,24 +835,42 @@ int OGRGMLDataSource::Create( const char *pszFilename,
         return FALSE;
     }
 
+    if( strcmp(pszFilename,"/dev/stdout") == 0 )
+        pszFilename = "/vsistdout/";
+
+/* -------------------------------------------------------------------- */
+/*      Read options                                                    */
+/* -------------------------------------------------------------------- */
+
+    CSLDestroy(papszCreateOptions);
+    papszCreateOptions = CSLDuplicate(papszOptions);
+
+    const char* pszFormat = CSLFetchNameValue(papszCreateOptions, "FORMAT");
+    bIsOutputGML3 = pszFormat && EQUAL(pszFormat, "GML3");
+    bIsOutputGML3Deegree = pszFormat && EQUAL(pszFormat, "GML3Deegree");
+    bIsOutputGML32 = pszFormat && EQUAL(pszFormat, "GML3.2");
+    if (bIsOutputGML3Deegree || bIsOutputGML32)
+        bIsOutputGML3 = TRUE;
+
+    bIsLongSRSRequired =
+        CSLTestBoolean(CSLFetchNameValueDef(papszCreateOptions, "GML3_LONGSRS", "YES"));
+
+    bWriteSpaceIndentation =
+        CSLTestBoolean(CSLFetchNameValueDef(papszCreateOptions, "SPACE_INDENTATION", "YES"));
+
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
     pszName = CPLStrdup( pszFilename );
 
-    if( EQUAL(pszFilename,"stdout") || EQUAL(pszFilename,"/vsistdout/"))
-    {
-        fpOutput = VSIFOpenL("/vsistdout/", "wb");
-        bFpOutputIsNonSeekable = TRUE;
-        bFpOutputSingleFile = TRUE;
-    }
-    else if ( EQUALN(pszFilename,"/vsigzip/", 9) )
+    if( strcmp(pszFilename,"/vsistdout/") == 0 ||
+        strncmp(pszFilename,"/vsigzip/", 9) == 0 )
     {
         fpOutput = VSIFOpenL(pszFilename, "wb");
         bFpOutputIsNonSeekable = TRUE;
         bFpOutputSingleFile = TRUE;
     }
-    else if ( EQUALN(pszFilename,"/vsizip/", 8) )
+    else if ( strncmp(pszFilename,"/vsizip/", 8) == 0)
     {
         if (EQUAL(CPLGetExtension(pszFilename), "zip"))
         {
@@ -636,11 +898,15 @@ int OGRGMLDataSource::Create( const char *pszFilename,
                 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" );
 
     if (!bFpOutputIsNonSeekable)
-        nSchemaInsertLocation = VSIFTellL( fpOutput );
+        nSchemaInsertLocation = (int) VSIFTellL( fpOutput );
 
     PrintLine( fpOutput, "%s", 
                 "<ogr:FeatureCollection" );
 
+    if (IsGML32Output())
+        PrintLine( fpOutput, "%s",
+                "     gml:id=\"aFeatureCollection\"" );
+
 /* -------------------------------------------------------------------- */
 /*      Write out schema info if provided in creation options.          */
 /* -------------------------------------------------------------------- */
@@ -667,13 +933,14 @@ int OGRGMLDataSource::Create( const char *pszFilename,
         CPLFree( pszBasename );
     }
 
-    CSLDestroy(papszCreateOptions);
-    papszCreateOptions = CSLDuplicate(papszOptions);
-
     PrintLine( fpOutput, "%s", 
                 "     xmlns:ogr=\"http://ogr.maptools.org/\"" );
-    PrintLine( fpOutput, "%s", 
-                "     xmlns:gml=\"http://www.opengis.net/gml\">" );
+    if (IsGML32Output())
+        PrintLine( fpOutput, "%s",
+                "     xmlns:gml=\"http://www.opengis.net/gml/3.2\">" );
+    else
+        PrintLine( fpOutput, "%s",
+                    "     xmlns:gml=\"http://www.opengis.net/gml\">" );
 
 /* -------------------------------------------------------------------- */
 /*      Should we initialize an area to place the boundedBy element?    */
@@ -682,23 +949,14 @@ int OGRGMLDataSource::Create( const char *pszFilename,
     if( CSLFetchBoolean( papszOptions, "BOUNDEDBY", TRUE ) &&
         !bFpOutputIsNonSeekable )
     {
-        nBoundedByLocation = VSIFTellL( fpOutput );
+        nBoundedByLocation = (int) VSIFTellL( fpOutput );
 
         if( nBoundedByLocation != -1 )
-            PrintLine( fpOutput, "%280s", "" );
+            PrintLine( fpOutput, "%350s", "" );
     }
     else
         nBoundedByLocation = -1;
 
-    const char* pszFormat = CSLFetchNameValue(papszCreateOptions, "FORMAT");
-    bIsOutputGML3 = pszFormat && EQUAL(pszFormat, "GML3");
-
-    bIsLongSRSRequired =
-        CSLTestBoolean(CSLFetchNameValueDef(papszCreateOptions, "GML3_LONGSRS", "YES"));
-
-    bWriteSpaceIndentation =
-        CSLTestBoolean(CSLFetchNameValueDef(papszCreateOptions, "SPACE_INDENTATION", "YES"));
-
     return TRUE;
 }
 
@@ -807,10 +1065,12 @@ OGRLayer *OGRGMLDataSource::GetLayer( int iLayer )
 /*                            GrowExtents()                             */
 /************************************************************************/
 
-void OGRGMLDataSource::GrowExtents( OGREnvelope *psGeomBounds )
+void OGRGMLDataSource::GrowExtents( OGREnvelope3D *psGeomBounds, int nCoordDimension )
 
 {
     sBoundingRect.Merge( *psGeomBounds );
+    if (nCoordDimension == 3)
+        bBBOX3D = TRUE;
 }
 
 /************************************************************************/
@@ -860,7 +1120,7 @@ void OGRGMLDataSource::InsertHeader()
     {
         if (fpOutput == NULL)
             return;
-        nSchemaStart = VSIFTellL( fpOutput );
+        nSchemaStart = (int) VSIFTellL( fpOutput );
         fpSchema = fpOutput;
     }
     else                                                               
@@ -889,32 +1149,72 @@ void OGRGMLDataSource::InsertHeader()
                     pszPrefix, pszTargetNameSpace );
         PrintLine( fpSchema,
                    "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"");
-        PrintLine( fpSchema,
-                   "    xmlns:gml=\"http://www.opengis.net/gml\"");
-        PrintLine( fpSchema,
-                   "    xmlns:gmlsf=\"http://www.opengis.net/gmlsf\"");
+        if (IsGML32Output())
+        {
+            PrintLine( fpSchema,
+                   "    xmlns:gml=\"http://www.opengis.net/gml/3.2\"");
+            PrintLine( fpSchema,
+                    "    xmlns:gmlsf=\"http://www.opengis.net/gmlsf/2.0\"");
+        }
+        else
+        {
+            PrintLine( fpSchema,
+                    "    xmlns:gml=\"http://www.opengis.net/gml\"");
+            if (!IsGML3DeegreeOutput())
+            {
+                PrintLine( fpSchema,
+                        "    xmlns:gmlsf=\"http://www.opengis.net/gmlsf\"");
+            }
+        }
         PrintLine( fpSchema,
                    "    elementFormDefault=\"qualified\"");
         PrintLine( fpSchema,
                    "    version=\"1.0\">");
 
-        PrintLine( fpSchema,
-                   "<xs:annotation>");
-        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>");
-        PrintLine( fpSchema,
-                   "    <gmlsf:GMLProfileSchema>http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd</gmlsf:GMLProfileSchema>");
-        PrintLine( fpSchema,
-                   "  </xs:appinfo>");
-        PrintLine( fpSchema,
-                   "</xs:annotation>");
+        if (IsGML32Output())
+        {
+            PrintLine( fpSchema,
+                    "<xs:annotation>");
+            PrintLine( fpSchema,
+                    "  <xs:appinfo source=\"http://schemas.opengis.net/gmlsfProfile/2.0/gmlsfLevels.xsd\">");
+            PrintLine( fpSchema,
+                    "    <gmlsf:ComplianceLevel>0</gmlsf:ComplianceLevel>");
+            PrintLine( fpSchema,
+                    "  </xs:appinfo>");
+            PrintLine( fpSchema,
+                    "</xs:annotation>");
+
+            PrintLine( fpSchema,
+                        "<xs:import namespace=\"http://www.opengis.net/gml/3.2\" schemaLocation=\"http://schemas.opengis.net/gml/3.2.1/gml.xsd\"/>" );
+            PrintLine( fpSchema,
+                        "<xs:import namespace=\"http://www.opengis.net/gmlsf/2.0\" schemaLocation=\"http://schemas.opengis.net/gmlsfProfile/2.0/gmlsfLevels.xsd\"/>" );
+        }
+        else
+        {
+            if (!IsGML3DeegreeOutput())
+            {
+                PrintLine( fpSchema,
+                        "<xs:annotation>");
+                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>");
+                PrintLine( fpSchema,
+                        "    <gmlsf:GMLProfileSchema>http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd</gmlsf:GMLProfileSchema>");
+                PrintLine( fpSchema,
+                        "  </xs:appinfo>");
+                PrintLine( fpSchema,
+                        "</xs:annotation>");
+            }
 
-        PrintLine( fpSchema,
-                    "<xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\"/>" );
-        PrintLine( fpSchema,
-                    "<xs:import namespace=\"http://www.opengis.net/gmlsf\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsfLevels.xsd\"/>" );
+            PrintLine( fpSchema,
+                        "<xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\"/>" );
+            if (!IsGML3DeegreeOutput())
+            {
+                PrintLine( fpSchema,
+                            "<xs:import namespace=\"http://www.opengis.net/gmlsf\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsfLevels.xsd\"/>" );
+            }
+        }
     }
     else
     {
@@ -931,19 +1231,56 @@ void OGRGMLDataSource::InsertHeader()
 /* -------------------------------------------------------------------- */
     if (IsGML3Output())
     {
-        PrintLine( fpSchema,
-                    "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_GML\"/>",
-                    pszPrefix );
+        if (IsGML32Output())
+        {
+            PrintLine( fpSchema,
+                        "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:AbstractGML\"/>",
+                        pszPrefix );
+        }
+        else if (IsGML3DeegreeOutput())
+        {
+            PrintLine( fpSchema,
+                        "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_FeatureCollection\"/>",
+                        pszPrefix );
+        }
+        else
+        {
+            PrintLine( fpSchema,
+                        "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_GML\"/>",
+                        pszPrefix );
+        }
 
         PrintLine( fpSchema, "<xs:complexType name=\"FeatureCollectionType\">");
         PrintLine( fpSchema, "  <xs:complexContent>" );
-        PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureType\">" );
-        PrintLine( fpSchema, "      <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" );
-        PrintLine( fpSchema, "        <xs:element name=\"featureMember\">" );
+        if (IsGML3DeegreeOutput())
+        {
+            PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureCollectionType\">" );
+            PrintLine( fpSchema, "      <xs:sequence>" );
+            PrintLine( fpSchema, "        <xs:element name=\"featureMember\" minOccurs=\"0\" maxOccurs=\"unbounded\">" );
+        }
+        else
+        {
+            PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureType\">" );
+            PrintLine( fpSchema, "      <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" );
+            PrintLine( fpSchema, "        <xs:element name=\"featureMember\">" );
+        }
         PrintLine( fpSchema, "          <xs:complexType>" );
-        PrintLine( fpSchema, "            <xs:sequence>" );
-        PrintLine( fpSchema, "              <xs:element ref=\"gml:_Feature\"/>" );
-        PrintLine( fpSchema, "            </xs:sequence>" );
+        if (IsGML32Output())
+        {
+            PrintLine( fpSchema, "            <xs:complexContent>" );
+            PrintLine( fpSchema, "              <xs:extension base=\"gml:AbstractFeatureMemberType\">" );
+            PrintLine( fpSchema, "                <xs:sequence>" );
+            PrintLine( fpSchema, "                  <xs:element ref=\"gml:AbstractFeature\"/>" );
+            PrintLine( fpSchema, "                </xs:sequence>" );
+            PrintLine( fpSchema, "              </xs:extension>" );
+            PrintLine( fpSchema, "            </xs:complexContent>" );
+        }
+        else
+        {
+            PrintLine( fpSchema, "            <xs:sequence>" );
+            PrintLine( fpSchema, "              <xs:element ref=\"gml:_Feature\"/>" );
+            PrintLine( fpSchema, "            </xs:sequence>" );
+        }
         PrintLine( fpSchema, "          </xs:complexType>" );
         PrintLine( fpSchema, "        </xs:element>" );
         PrintLine( fpSchema, "      </xs:sequence>" );
@@ -979,10 +1316,20 @@ void OGRGMLDataSource::InsertHeader()
 /* -------------------------------------------------------------------- */
 /*      Emit initial stuff for a feature type.                          */
 /* -------------------------------------------------------------------- */
-        PrintLine(
-            fpSchema,
-            "<xs:element name=\"%s\" type=\"%s:%s_Type\" substitutionGroup=\"gml:_Feature\"/>",
-            poFDefn->GetName(), pszPrefix, poFDefn->GetName() );
+        if (IsGML32Output())
+        {
+            PrintLine(
+                fpSchema,
+                "<xs:element name=\"%s\" type=\"%s:%s_Type\" substitutionGroup=\"gml:AbstractFeature\"/>",
+                poFDefn->GetName(), pszPrefix, poFDefn->GetName() );
+        }
+        else
+        {
+            PrintLine(
+                fpSchema,
+                "<xs:element name=\"%s\" type=\"%s:%s_Type\" substitutionGroup=\"gml:_Feature\"/>",
+                poFDefn->GetName(), pszPrefix, poFDefn->GetName() );
+        }
 
         PrintLine( fpSchema, "<xs:complexType name=\"%s_Type\">", poFDefn->GetName());
         PrintLine( fpSchema, "  <xs:complexContent>");
@@ -1031,8 +1378,12 @@ void OGRGMLDataSource::InsertHeader()
             default:
                 break;
         }
-        PrintLine( fpSchema,
-            "        <xs:element name=\"geometryProperty\" type=\"gml:%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"1\"/>", pszGeometryTypeName );
+
+        if (poFDefn->GetGeomType() != wkbNone)
+        {
+            PrintLine( fpSchema,
+                "        <xs:element name=\"geometryProperty\" type=\"gml:%s\" nillable=\"true\" minOccurs=\"0\" maxOccurs=\"1\"/>", pszGeometryTypeName );
+        }
             
 /* -------------------------------------------------------------------- */
 /*      Emit each of the attributes.                                    */
@@ -1124,7 +1475,7 @@ void OGRGMLDataSource::InsertHeader()
 /* -------------------------------------------------------------------- */
 /*      Read the schema into memory.                                    */
 /* -------------------------------------------------------------------- */
-        int nSchemaSize = VSIFTellL( fpOutput ) - nSchemaStart;
+        int nSchemaSize = (int) VSIFTellL( fpOutput ) - nSchemaStart;
         char *pszSchema = (char *) CPLMalloc(nSchemaSize+1);
     
         VSIFSeekL( fpOutput, nSchemaStart, SEEK_SET );
diff --git a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
index 2c28ea0..8fbc416 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmllayer.cpp 21390 2011-01-03 22:43:07Z rouault $
+ * $Id: ogrgmllayer.cpp 23638 2011-12-22 21:02:56Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLLayer class.
@@ -33,8 +33,9 @@
 #include "cpl_port.h"
 #include "cpl_string.h"
 #include "ogr_p.h"
+#include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrgmllayer.cpp 21390 2011-01-03 22:43:07Z rouault $");
+CPL_CVSID("$Id: ogrgmllayer.cpp 23638 2011-12-22 21:02:56Z rouault $");
 
 /************************************************************************/
 /*                           OGRGMLLayer()                              */
@@ -55,6 +56,7 @@ OGRGMLLayer::OGRGMLLayer( const char * pszName,
     nTotalGMLCount = -1;
     bInvalidFIDFound = FALSE;
     pszFIDPrefix = NULL;
+    bFaceHoleNegative = FALSE;
         
     poDS = poDSIn;
 
@@ -76,7 +78,15 @@ OGRGMLLayer::OGRGMLLayer( const char * pszName,
     else
         poFClass = NULL;
 
-    m_bInvertAxisOrderIfLatLong = CSLTestBoolean(CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES"));
+    hCacheSRS = GML_BuildOGRGeometryFromList_CreateCache();
+
+    /* Compatibility option. Not advertized, because hopefully won't be needed */
+    /* Just put here in provision... */
+    bUseOldFIDFormat = CSLTestBoolean(CPLGetConfigOption("GML_USE_OLD_FID_FORMAT", "FALSE"));
+
+    /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
+    bFaceHoleNegative = CSLTestBoolean(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
+
 }
 
 /************************************************************************/
@@ -93,6 +103,8 @@ OGRGMLLayer::~OGRGMLLayer()
 
     if( poSRS != NULL )
         poSRS->Release();
+
+    GML_BuildOGRGeometryFromList_DestroyCache(hCacheSRS);
 }
 
 /************************************************************************/
@@ -102,9 +114,26 @@ OGRGMLLayer::~OGRGMLLayer()
 void OGRGMLLayer::ResetReading()
 
 {
+    if (bWriter)
+        return;
+
+    if (poDS->GetReadMode() == INTERLEAVED_LAYERS ||
+        poDS->GetReadMode() == SEQUENTIAL_LAYERS)
+    {
+        /* Does the last stored feature belong to our layer ? If so, no */
+        /* need to reset the reader */
+        if (iNextGMLId == 0 && poDS->PeekStoredGMLFeature() != NULL &&
+            poDS->PeekStoredGMLFeature()->GetClass() == poFClass)
+            return;
+
+        delete poDS->PeekStoredGMLFeature();
+        poDS->SetStoredGMLFeature(NULL);
+    }
+
     iNextGMLId = 0;
     poDS->GetReader()->ResetReading();
-    if (poFClass && poDS->GetLayerCount() > 1)
+    CPLDebug("GML", "ResetReading()");
+    if (poDS->GetLayerCount() > 1 && poDS->GetReadMode() == STANDARD)
         poDS->GetReader()->SetFilteredClassName(poFClass->GetName());
 }
 
@@ -125,8 +154,12 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         return NULL;
     }
 
-    if( iNextGMLId == 0 )
-        ResetReading();
+    if( poDS->GetLastReadLayer() != this )
+    {
+        if( poDS->GetReadMode() != INTERLEAVED_LAYERS )
+            ResetReading();
+        poDS->SetLastReadLayer(this);
+    }
 
 /* ==================================================================== */
 /*      Loop till we find and translate a feature meeting all our       */
@@ -146,21 +179,37 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
             poGeom = NULL;
         }
 
-        poGMLFeature = poDS->GetReader()->NextFeature();
-        if( poGMLFeature == NULL )
-            return NULL;
+        poGMLFeature = poDS->PeekStoredGMLFeature();
+        if (poGMLFeature != NULL)
+            poDS->SetStoredGMLFeature(NULL);
+        else
+        {
+            poGMLFeature = poDS->GetReader()->NextFeature();
+            if( poGMLFeature == NULL )
+                return NULL;
+
+            // We count reading low level GML features as a feature read for
+            // work checking purposes, though at least we didn't necessary
+            // have to turn it into an OGRFeature.
+            m_nFeaturesRead++;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Is it of the proper feature class?                              */
 /* -------------------------------------------------------------------- */
 
-        // We count reading low level GML features as a feature read for
-        // work checking purposes, though at least we didn't necessary
-        // have to turn it into an OGRFeature.
-        m_nFeaturesRead++;
-
         if( poGMLFeature->GetClass() != poFClass )
-            continue;
+        {
+            if( poDS->GetReadMode() == INTERLEAVED_LAYERS ||
+                (poDS->GetReadMode() == SEQUENTIAL_LAYERS && iNextGMLId != 0) )
+            {
+                CPLAssert(poDS->PeekStoredGMLFeature() == NULL);
+                poDS->SetStoredGMLFeature(poGMLFeature);
+                return NULL;
+            }
+            else
+                continue;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Extract the fid:                                                */
@@ -230,26 +279,58 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /*      Does it satisfy the spatial query, if there is one?             */
 /* -------------------------------------------------------------------- */
 
-        char** papszGeometryList = poGMLFeature->GetGeometryList();
-        if( papszGeometryList != NULL )
+        const CPLXMLNode* const * papsGeometry = poGMLFeature->GetGeometryList();
+        if (papsGeometry[0] != NULL)
         {
             const char* pszSRSName = poDS->GetGlobalSRSName();
-            poGeom = GML_BuildOGRGeometryFromList(papszGeometryList, TRUE,
-                                                  m_bInvertAxisOrderIfLatLong, pszSRSName);
+            poGeom = GML_BuildOGRGeometryFromList(papsGeometry, TRUE,
+                                                  poDS->GetInvertAxisOrderIfLatLong(),
+                                                  pszSRSName,
+                                                  poDS->GetConsiderEPSGAsURN(),
+                                                  poDS->GetSecondaryGeometryOption(),
+                                                  hCacheSRS,
+                                                  bFaceHoleNegative );
+
+            /* Force single geometry to multigeometry if needed to match layer geometry type */
+            if (poGeom != NULL)
+            {
+                OGRwkbGeometryType eType = poGeom->getGeometryType();
+                OGRwkbGeometryType eLayerType = GetGeomType();
+                if (eType == wkbPoint && eLayerType == wkbMultiPoint)
+                {
+                    OGRMultiPoint* poNewGeom = new OGRMultiPoint();
+                    poNewGeom->addGeometryDirectly(poGeom);
+                    poGeom = poNewGeom;
+                }
+                else if (eType == wkbLineString && eLayerType == wkbMultiLineString)
+                {
+                    OGRMultiLineString* poNewGeom = new OGRMultiLineString();
+                    poNewGeom->addGeometryDirectly(poGeom);
+                    poGeom = poNewGeom;
+                }
+                else if (eType == wkbPolygon && eLayerType == wkbMultiPolygon)
+                {
+                    OGRMultiPolygon* poNewGeom = new OGRMultiPolygon();
+                    poNewGeom->addGeometryDirectly(poGeom);
+                    poGeom = poNewGeom;
+                }
+            }
+
             if (poGeom != NULL && poSRS != NULL)
                 poGeom->assignSpatialReference(poSRS);
 
             // We assume the createFromGML() function would have already
-            // reported the error. 
+            // reported the error.
             if( poGeom == NULL )
             {
                 delete poGMLFeature;
                 return NULL;
             }
-            
+
             if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
                 continue;
         }
+
         
 /* -------------------------------------------------------------------- */
 /*      Convert the whole feature into an OGRFeature.                   */
@@ -259,14 +340,15 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         OGRFeature *poOGRFeature = new OGRFeature( GetLayerDefn() );
 
         poOGRFeature->SetFID( nFID );
-        if (poDS->ExposeGMLId())
+        if (poDS->ExposeId())
         {
             if (pszGML_FID)
                 poOGRFeature->SetField( iDstField, pszGML_FID );
             iDstField ++;
         }
 
-        for( iField = 0; iField < poFClass->GetPropertyCount(); iField++, iDstField ++ )
+        int nPropertyCount = poFClass->GetPropertyCount();
+        for( iField = 0; iField < nPropertyCount; iField++, iDstField ++ )
         {
             const GMLProperty *psGMLProperty = poGMLFeature->GetProperty( iField );
             if( psGMLProperty == NULL || psGMLProperty->nSubProperties == 0 )
@@ -433,9 +515,28 @@ OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
                     poFeature->GetFID() );
     }
     else
-        poDS->PrintLine( fp, "<ogr:%s fid=\"F%ld\">",
+    {
+        nGMLIdIndex = poFeatureDefn->GetFieldIndex("fid");
+        if (bUseOldFIDFormat)
+        {
+            poDS->PrintLine( fp, "<ogr:%s fid=\"F%ld\">",
+                                poFeatureDefn->GetName(),
+                                poFeature->GetFID() );
+        }
+        else if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
+        {
+            poDS->PrintLine( fp, "<ogr:%s fid=\"%s\">",
                 poFeatureDefn->GetName(),
-                poFeature->GetFID() );
+                poFeature->GetFieldAsString(nGMLIdIndex) );
+        }
+        else
+        {
+            poDS->PrintLine( fp, "<ogr:%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 */
@@ -443,10 +544,12 @@ OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
     if( poGeom != NULL && !poGeom->IsEmpty())
     {
         char    *pszGeometry;
-        OGREnvelope sGeomBounds;
+        OGREnvelope3D sGeomBounds;
+
+        int nCoordDimension = poGeom->getCoordinateDimension();
 
         poGeom->getEnvelope( &sGeomBounds );
-        poDS->GrowExtents( &sGeomBounds );
+        poDS->GrowExtents( &sGeomBounds, nCoordDimension );
 
         if (bIsGML3Output)
         {
@@ -459,24 +562,26 @@ OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
             char szLowerCorner[75], szUpperCorner[75];
             if (bCoordSwap)
             {
-                OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, 0, 2);
-                OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, 0, 2);
+                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, 0, 2);
-                OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, 0, 2);
+                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><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
-                             pszSRSName, szLowerCorner, szUpperCorner);
+            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);
         }
 
         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)
diff --git a/ogr/ogrsf_frmts/gml/parsexsd.cpp b/ogr/ogrsf_frmts/gml/parsexsd.cpp
index 5a4716d..4be2861 100644
--- a/ogr/ogrsf_frmts/gml/parsexsd.cpp
+++ b/ogr/ogrsf_frmts/gml/parsexsd.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: parsexsd.cpp 20428 2010-08-24 20:39:50Z rouault $
+ * $Id: parsexsd.cpp 23686 2012-01-02 20:59:38Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLParseXSD()
@@ -163,6 +163,23 @@ static const AssocNameType apsPropertyTypes [] =
     {NULL, wkbUnknown},
 };
 
+/* Found in FME .xsd  (e.g. <element ref="gml:curveProperty" minOccurs="0"/>) */
+static const AssocNameType apsRefTypes [] =
+{
+    {"pointProperty", wkbPoint},
+    {"curveProperty", wkbLineString},
+    {"surfaceProperty", wkbPolygon},
+    {"multiPointProperty", wkbMultiPoint},
+    {"multiCurveProperty", wkbMultiLineString},
+    {"multiSurfaceProperty", wkbMultiPolygon},
+    {NULL, wkbUnknown},
+};
+
+static
+GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
+                                     const char* pszName,
+                                     CPLXMLNode *psThis);
+
 static
 GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                                 const char* pszName,
@@ -182,11 +199,21 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
     if (psThis == NULL)
         return NULL;
 
+    return GMLParseFeatureType(psSchemaNode, pszName, psThis);
+}
+
+
+static
+GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
+                                     const char* pszName,
+                                     CPLXMLNode *psComplexType)
+{
+
 /* -------------------------------------------------------------------- */
 /*      Grab the sequence of extensions greatgrandchild.                */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psAttrSeq =
-        CPLGetXMLNode( psThis,
+        CPLGetXMLNode( psComplexType,
                         "complexContent.extension.sequence" );
 
     if( psAttrSeq == NULL )
@@ -207,16 +234,26 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
     CPLXMLNode *psAttrDef;
     int nAttributeIndex = 0;
 
+    int bGotUnrecognizedType = FALSE;
+
     for( psAttrDef = psAttrSeq->psChild;
             psAttrDef != NULL;
             psAttrDef = psAttrDef->psNext )
     {
+        if( strcmp(psAttrDef->pszValue,"group") == 0 )
+        {
+            /* Too complex schema for us. Aborts parsing */
+            delete poClass;
+            return NULL;
+        }
+
         if( !EQUAL(psAttrDef->pszValue,"element") )
             continue;
 
         /* MapServer WFS writes element type as an attribute of element */
         /* not as a simpleType definition */
         const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL );
+        const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL );
         if (pszType != NULL)
         {
             const char* pszStrippedNSType = StripNS(pszType);
@@ -249,7 +286,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                         }
                         else
                         {
-                            poClass->SetGeometryElement(CPLGetXMLValue( psAttrDef, "name", NULL ));
+                            poClass->SetGeometryElement(pszElementName);
                             poClass->SetGeometryType(psIter->eType);
                             poClass->SetGeometryAttributeIndex( nAttributeIndex );
 
@@ -261,6 +298,18 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 
                     psIter ++;
                 }
+
+                if (psIter->pszName == NULL)
+                {
+                    /* Can be a non geometry gml type */
+                    /* Too complex schema for us. Aborts parsing */
+                    delete poClass;
+                    return NULL;
+                }
+
+                if (poClass->GetGeometryAttributeIndex() == -1)
+                    bGotUnrecognizedType = TRUE;
+
                 continue;
             }
 
@@ -268,7 +317,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 ||
                      strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0)
             {
-                poClass->SetGeometryElement(CPLGetXMLValue( psAttrDef, "name", NULL ));
+                poClass->SetGeometryElement(pszElementName);
                 poClass->SetGeometryType(wkbMultiPoint);
                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
 
@@ -278,7 +327,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 ||
                      strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0)
             {
-                poClass->SetGeometryElement(CPLGetXMLValue( psAttrDef, "name", NULL ));
+                poClass->SetGeometryElement(pszElementName);
                 poClass->SetGeometryType(wkbMultiLineString);
                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
 
@@ -289,7 +338,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                      strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 ||
                      strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0)
             {
-                poClass->SetGeometryElement(CPLGetXMLValue( psAttrDef, "name", NULL ));
+                poClass->SetGeometryElement(pszElementName);
                 poClass->SetGeometryType(wkbMultiPolygon);
                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
 
@@ -300,7 +349,7 @@ 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(CPLGetXMLValue( psAttrDef, "name", NULL ));
+                poClass->SetGeometryElement(pszElementName);
                 poClass->SetGeometryType(wkbMultiPolygon);
                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
 
@@ -314,13 +363,16 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 if ( ! LookForSimpleType(psSchemaNode, pszStrippedNSType,
                                          &gmlType, &nWidth, &nPrecision) )
                 {
-                    //CPLDebug("GML", "Unknown type (%s).", pszType);
+                    /* Too complex schema for us. Aborts parsing */
+                    delete poClass;
+                    return NULL;
                 }
             }
 
+            if (pszElementName == NULL)
+                pszElementName = "unnamed";
             GMLPropertyDefn *poProp = new GMLPropertyDefn(
-                CPLGetXMLValue( psAttrDef, "name", "unnamed" ),
-                CPLGetXMLValue( psAttrDef, "name", "unnamed" ) );
+                pszElementName, pszElementName );
 
             poProp->SetType( gmlType );
             poProp->SetAttributeIndex( nAttributeIndex );
@@ -338,12 +390,72 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
         // For now we skip geometries .. fixup later.
         CPLXMLNode* psSimpleType = CPLGetXMLNode( psAttrDef, "simpleType" );
         if( psSimpleType == NULL )
-            continue;
+        {
+            const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL );
 
-        GMLPropertyDefn *poProp = new GMLPropertyDefn(
-            CPLGetXMLValue( psAttrDef, "name", "unnamed" ),
-            CPLGetXMLValue( psAttrDef, "name", "unnamed" ) );
+            /* FME .xsd */
+            if (pszRef != NULL && strncmp(pszRef, "gml:", 4) == 0)
+            {
+                const AssocNameType* psIter = apsRefTypes;
+                while(psIter->pszName)
+                {
+                    if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
+                    {
+                        if (poClass->GetGeometryAttributeIndex() != -1)
+                        {
+                            OGRwkbGeometryType eNewType = psIter->eType;
+                            OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryType();
+                            if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) ||
+                                (eNewType == wkbMultiLineString && eOldType == wkbLineString) ||
+                                (eNewType == wkbMultiPolygon && eOldType == wkbPolygon))
+                            {
+                                poClass->SetGeometryType(eNewType);
+                            }
+                            else
+                            {
+                                CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
+                            }
+                        }
+                        else
+                        {
+                            poClass->SetGeometryElement(pszElementName);
+                            poClass->SetGeometryType(psIter->eType);
+                            poClass->SetGeometryAttributeIndex( nAttributeIndex );
 
+                            nAttributeIndex ++;
+                        }
+
+                        break;
+                    }
+
+                    psIter ++;
+                }
+
+                if (psIter->pszName == NULL)
+                {
+                    /* Can be a non geometry gml type */
+                    /* Too complex schema for us. Aborts parsing */
+                    delete poClass;
+                    return NULL;
+                }
+
+                if (poClass->GetGeometryAttributeIndex() == -1)
+                    bGotUnrecognizedType = TRUE;
+
+                continue;
+            }
+            else
+            {
+                /* Too complex schema for us. Aborts parsing */
+                delete poClass;
+                return NULL;
+            }
+        }
+
+        if (pszElementName == NULL)
+            pszElementName = "unnamed";
+        GMLPropertyDefn *poProp = new GMLPropertyDefn(
+            pszElementName, pszElementName );
 
         GMLPropertyType eType = GMLPT_Untyped;
         int nWidth = 0, nPrecision = 0;
@@ -359,6 +471,15 @@ 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)
+    {
+        poClass->SetGeometryType(wkbNone);
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Class complete, add to reader class list.                       */
 /* -------------------------------------------------------------------- */
@@ -426,7 +547,8 @@ int GMLParseXSD( const char *pszFile,
         if( EQUAL(pszSubGroup, "_FeatureCollection") )
             continue;
 
-        if( !EQUAL(pszSubGroup, "_Feature") )
+        if( !EQUAL(pszSubGroup, "_Feature") &&
+            !EQUAL(pszSubGroup, "AbstractFeature") /* AbstractFeature used by GML 3.2 */ )
         {
             continue;
         }
@@ -449,7 +571,17 @@ int GMLParseXSD( const char *pszFile,
 
         pszType = CPLGetXMLValue( psThis, "type", NULL );
         if (pszType == NULL)
+        {
+            CPLXMLNode *psComplexType = CPLGetXMLNode( psThis, "complexType" );
+            if (psComplexType)
+            {
+                GMLFeatureClass* poClass =
+                        GMLParseFeatureType(psSchemaNode, pszName, psComplexType);
+                if (poClass)
+                    aosClasses.push_back(poClass);
+            }
             continue;
+        }
         if( strstr( pszType, ":" ) != NULL )
             pszType = strstr( pszType, ":" ) + 1;
         if( EQUAL(pszType, pszName) )
@@ -465,6 +597,12 @@ int GMLParseXSD( const char *pszFile,
             continue;
         }
 
+        /* CanVec .xsd contains weird types that are not used in the related GML */
+        if (strncmp(pszName, "XyZz", 4) == 0 ||
+            strncmp(pszName, "XyZ1", 4) == 0 ||
+            strncmp(pszName, "XyZ2", 4) == 0)
+            continue;
+
         GMLFeatureClass* poClass =
                 GMLParseFeatureType(psSchemaNode, pszName, pszType);
         if (poClass)
diff --git a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
index bb1883f..b30d1ab 100644
--- a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
+++ b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: resolvexlinks.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: resolvexlinks.cpp 22205 2011-04-18 21:17:30Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader::ResolveXlinks() method.
@@ -30,9 +30,7 @@
 #include "gmlreader.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: resolvexlinks.cpp 21298 2010-12-20 10:58:34Z rouault $");
-
-#if HAVE_XERCES != 0 || defined(HAVE_EXPAT)
+CPL_CVSID("$Id: resolvexlinks.cpp 22205 2011-04-18 21:17:30Z rouault $");
 
 #include "gmlreaderp.h"
 #include "cpl_conv.h"
@@ -629,5 +627,3 @@ int GMLReader::ResolveXlinks( const char *pszFile,
 
     return bReturn;
 }
-
-#endif /* HAVE_XERCES == 1  || defined(HAVE_EXPAT) */
diff --git a/ogr/ogrsf_frmts/gml/trstring.cpp b/ogr/ogrsf_frmts/gml/trstring.cpp
index 5c452d8..def831c 100644
--- a/ogr/ogrsf_frmts/gml/trstring.cpp
+++ b/ogr/ogrsf_frmts/gml/trstring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: trstring.cpp 16785 2009-04-17 10:07:28Z chaitanya $
+ * $Id: trstring.cpp 22205 2011-04-18 21:17:30Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Functions for translating back and forth between XMLCh and char.
@@ -30,6 +30,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifdef HAVE_XERCES
+
 #include "gmlreaderp.h"
 #include "cpl_vsi.h"
 #include "cpl_conv.h"
@@ -129,7 +131,7 @@ void tr_strcpy( XMLCh *panXMLString, const char *pszCString )
     int i;
     wchar_t *pwszUTF16;
 
-    pwszUTF16 = CPLRecodeToWChar( pszCString, CPL_ENC_UTF8, CPL_ENC_UTF16 );
+    pwszUTF16 = CPLRecodeToWChar( pszCString, CPL_ENC_UTF8, "WCHAR_T" );
     
     for( i = 0; pwszUTF16[i] != 0; i++ )
         panXMLString[i] = pwszUTF16[i];
@@ -178,7 +180,7 @@ void tr_strcpy( char *pszCString, const XMLCh *panXMLString )
     pwszSource[i] = 0;
     
     char *pszResult = CPLRecodeFromWChar( pwszSource, 
-                                          CPL_ENC_UTF16, CPL_ENC_UTF8 );
+                                          "WCHAR_T", CPL_ENC_UTF8 );
     
     strcpy( pszCString, pszResult );
 
@@ -230,3 +232,5 @@ char *tr_strdup( const XMLCh *panXMLString )
     tr_strcpy( pszResult, panXMLString );
     return pszResult;
 }
+
+#endif // HAVE_XERCES
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
index 23993d1..0cd5590 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
@@ -180,7 +180,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdate )
 /* -------------------------------------------------------------------- */
     if( osRegion.length() > 0 )
     {
-        char **papszTokens = CSLTokenizeStringComplex( osRegion.c_str() + 1,
+        char **papszTokens = CSLTokenizeStringComplex( osRegion.c_str(),
                                                        "/", FALSE, FALSE );
         
         if( CSLCount(papszTokens) == 4 )
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
index 194e05b..1b56ce1 100755
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpsbabeldatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrgpsbabeldatasource.cpp 23557 2011-12-12 22:08:17Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGPSBabelDataSource class.
@@ -34,7 +34,7 @@
 
 #include <string.h>
 
-CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 23557 2011-12-12 22:08:17Z rouault $");
 
 /************************************************************************/
 /*                      OGRGPSBabelDataSource()                         */
@@ -146,11 +146,6 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName, int bUpdateIn)
 
     if (!EQUALN(pszDatasourceName, "GPSBABEL:", 9))
     {
-        VSIStatBufL sStatBuf;
-        if( VSIStatL( pszDatasourceName, &sStatBuf ) != 0 
-            ||!VSI_ISREG(sStatBuf.st_mode) )
-            return FALSE;
-
         VSILFILE* fp = VSIFOpenL(pszDatasourceName, "rb");
         if (fp == NULL)
             return FALSE;
diff --git a/ogr/ogrsf_frmts/gpx/drv_gpx.html b/ogr/ogrsf_frmts/gpx/drv_gpx.html
index f5ea585..e128bba 100644
--- a/ogr/ogrsf_frmts/gpx/drv_gpx.html
+++ b/ogr/ogrsf_frmts/gpx/drv_gpx.html
@@ -205,6 +205,15 @@ Starting with GDAL 1.7.0, there is a more convenient way to select all fields an
 
 </ul>
 
+<h2>VSI Virtual File System API support</h2>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
+
 <h2>Example</h2>
 
 <li>The ogrinfo utility can be used to dump the content of a GPX datafile :
@@ -261,6 +270,15 @@ ogr2ogr -f GPX output.gpx input.shp -sql "SELECT field1 AS name, field2 AS desc
 </pre>
 </li>
 
+<h2>FAQ</h2>
+
+<li>How to solve "ERROR 6: Cannot create GPX layer XXXXXX with unknown geometry type" ?<p>
+This error happens when the layer to create does not expose a precise geometry type, but just a generic
+wkbUnknown type. This is for example the case when using ogr2ogr with a SQL request to a PostgreSQL datasource.
+You must then explicitely specify -nlt POINT (or LINESTRING or MULTILINESTRING).
+</li>
+
+
 <h2>See Also</h2>
 
 <ul>
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
index d72714b..76641db 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpxdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrgpxdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXDataSource class
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrgpxdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrgpxdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $");
 
 #define SPACE_FOR_METADATA 160
 
@@ -280,16 +280,8 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
     pszName = CPLStrdup( pszFilename );
 
 /* -------------------------------------------------------------------- */
-/*      Determine what sort of object this is.                          */
+/*      Try to open the file.                                           */
 /* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
-
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
-        return FALSE;
-    
-    if( VSI_ISDIR(sStatBuf.st_mode) )
-        return FALSE;
-
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
     if (fp == NULL)
         return FALSE;
@@ -431,6 +423,9 @@ int OGRGPXDataSource::Create( const char *pszFilename,
         return FALSE;
     }
 
+    if (strcmp(pszFilename, "/dev/stdout") == 0)
+        pszFilename = "/vsistdout/";
+
 /* -------------------------------------------------------------------- */
 /*     Do not override exiting file.                                    */
 /* -------------------------------------------------------------------- */
@@ -447,12 +442,13 @@ int OGRGPXDataSource::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
+
     pszName = CPLStrdup( pszFilename );
 
-    if( EQUAL(pszFilename,"stdout") || EQUAL(pszFilename,"/vsistdout/"))
+    if( strcmp(pszName, "/vsistdout/") == 0 )
     {
         bIsBackSeekable = FALSE;
-        fpOutput = VSIFOpenL( "/vsistdout/", "w" );
+        fpOutput = VSIFOpenL( pszFilename, "w" );
     }
     else
         fpOutput = VSIFOpenL( pszFilename, "w+" );
@@ -534,7 +530,7 @@ int OGRGPXDataSource::Create( const char *pszFilename,
       char szMetadata[SPACE_FOR_METADATA+1];
       memset(szMetadata, ' ', SPACE_FOR_METADATA);
       szMetadata[SPACE_FOR_METADATA] = '\0';
-      nOffsetBounds = VSIFTellL(fpOutput);
+      nOffsetBounds = (int) VSIFTellL(fpOutput);
       PrintLine("%s", szMetadata);
     }
 
diff --git a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
index be665c2..ad95e8f 100644
--- a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtmtracklayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gtmtracklayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of GTMTrackLayer class.
@@ -153,7 +153,7 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
     pBuffer = CPLMalloc(bufferSize);
     void* pBufferAux = pBuffer;
     /* Write track string name size to buffer */
-    appendUShort(pBufferAux, trackNameLength);
+    appendUShort(pBufferAux, (unsigned short) trackNameLength);
     pBufferAux = (char*)pBufferAux + 2;
 
     /* Write track name */
@@ -161,7 +161,7 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
     pBufferAux = (char*)pBufferAux + trackNameLength;
 
     /* Write track type */
-    appendUChar(pBufferAux, type);
+    appendUChar(pBufferAux, (unsigned char) type);
     pBufferAux = (char*)pBufferAux + 1;
   
     /* Write track color */
diff --git a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
index e74bd17..d10e65b 100644
--- a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtmwaypointlayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gtmwaypointlayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of gtmwaypoint class.
@@ -187,14 +187,14 @@ void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float alti
 
     /* Write waypoint string comment size to buffer */
     pBufferAux = (char*)pBuffer+10;
-    appendUShort(pBufferAux, commentLength);
+    appendUShort(pBufferAux, (unsigned short) commentLength);
 
     /* Write waypoint string comment to buffer */
     strncpy((char*)pBuffer+12, pszcomment, commentLength);
 
     /* Write icon to buffer */
     pBufferAux = (char*)pBuffer+12+commentLength;
-    appendUShort(pBufferAux, icon);
+    appendUShort(pBufferAux, (unsigned short) icon);
 
     /* Write dslp to buffer */
     pBufferAux = (char*)pBufferAux + 2;
diff --git a/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp b/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
index 34b53fc..bad77ee 100644
--- a/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
+++ b/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgtmdatasource.cpp 17604 2009-09-02 18:46:38Z rouault $
+ * $Id: ogrgtmdatasource.cpp 21684 2011-02-11 22:14:01Z warmerdam $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of OGRGTMDataSource class.
@@ -124,7 +124,7 @@ void OGRGTMDataSource::WriteWaypointStyles()
                 strncpy((char*)pBufferAux, "Arial", 5);
                 pBufferAux = ((char*)pBufferAux) + 5; 
                 // dspl
-                appendUChar(pBufferAux, i);
+                appendUChar(pBufferAux, (unsigned char) i);
                 pBufferAux = ((char*)pBufferAux) + 1;
                 // color
                 appendInt(pBufferAux, 0);
@@ -417,7 +417,7 @@ int OGRGTMDataSource::Create( const char* pszFilename, char** papszOptions )
         strcpy((char*)pCurrentPos, "Arial");
         pCurrentPos = ((char*)pCurrentPos) + 5;
     }
-    appendUShort(pCurrentPos, strlen(pszBaseFileName));
+    appendUShort(pCurrentPos, (unsigned short) strlen(pszBaseFileName));
     pCurrentPos = ((char*)pCurrentPos) + 2;
     strcpy((char*)pCurrentPos, pszBaseFileName);
 
diff --git a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
index 1781768..f0b883c 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrhtfdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrhtfdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFDataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrhtfdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrhtfdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
 
 /************************************************************************/
 /*                          OGRHTFDataSource()                          */
@@ -116,15 +116,6 @@ int OGRHTFDataSource::Open( const char * pszFilename, int bUpdateIn)
 
     pszName = CPLStrdup( pszFilename );
 
-/* -------------------------------------------------------------------- */
-/*      Determine what sort of object this is.                          */
-/* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
-
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 ||
-        !VSI_ISREG(sStatBuf.st_mode) )
-        return FALSE;
-    
 // -------------------------------------------------------------------- 
 //      Does this appear to be a .htf file?
 // --------------------------------------------------------------------
diff --git a/ogr/ogrsf_frmts/idrisi/GNUmakefile b/ogr/ogrsf_frmts/idrisi/GNUmakefile
new file mode 100644
index 0000000..3b68458
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogridrisidriver.o ogridrisidatasource.o ogridrisilayer.o
+
+CPPFLAGS	:=	-I.. -I../.. -I../../../frmts/idrisi $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_idrisi.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/idrisi/drv_idrisi.html b/ogr/ogrsf_frmts/idrisi/drv_idrisi.html
new file mode 100644
index 0000000..eb23714
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/drv_idrisi.html
@@ -0,0 +1,33 @@
+<html>
+<head>
+<title>Idrisi Vector (.VCT)</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>Idrisi Vector (.VCT)</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver reads Idrisi vector files with .vct extension. The driver
+recognized point, lines and polygons geometries.<p>
+
+For geographical referencing identification, the .vdc file contains information
+that points to a file that holds the geographic reference details. Those files
+uses extension REF and  resides in the same folder as the RST image or more
+likely in the Idrisi installation folders.<p>
+
+Therefore the presence or absence of the Idrisi software in the running operation
+system will determine the way that this driver will work. By setting the
+environment variable IDRISIDIR pointing to the Idrisi main installation folder
+will enable GDAL to find more detailed information about geographical reference
+and projection in the REF files.<p>
+
+Note that the driver recognizes the name convention used in Idrisi for UTM and
+State Plane geographic reference so it doesn't need to access the REF files. That
+is the case for RDC file that specify "utm-30n" or "spc87ma1" in the "ref. system"
+field. Note that exporting to RST in any other geographical reference system will
+generate a suggested REF content in the comment section of the RDC file.<p>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/idrisi/generate_test_files.c b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
new file mode 100644
index 0000000..6a5b107
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
@@ -0,0 +1,205 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  
+ * Purpose:  Generate sample .VCT files
+ * 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>
+ *
+ * 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>
+
+int main(int argc, char* argv[])
+{
+    char c;
+    int i;
+    int nfeatures;
+    int nodes;
+    int nparts;
+    FILE* f;
+    double id, x, y;
+    double minx, maxx, miny, maxy;
+
+    f = fopen("points.vct", "wb");
+    c = 0x01;
+    fwrite(&c, 1, 1, f);
+    nfeatures = 2;
+    fwrite(&nfeatures, 1, sizeof(int), f);
+    for(i=5;i<0x105;i++)
+    {
+        c = 0;
+        fwrite(&c, 1, 1, f);
+    }
+
+    id = 1;
+    x = 400000;
+    y = 5000000;
+    fwrite(&id, 1, sizeof(double), f);
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+
+    id = 2;
+    x = 600000;
+    y = 4000000;
+    fwrite(&id, 1, sizeof(double), f);
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+
+    fclose(f);
+
+
+
+    f = fopen("lines.vct", "wb");
+    c = 0x02;
+    fwrite(&c, 1, 1, f);
+    nfeatures = 2;
+    fwrite(&nfeatures, 1, sizeof(int), f);
+    for(i=5;i<0x105;i++)
+    {
+        c = 0;
+        fwrite(&c, 1, 1, f);
+    }
+
+    id = 10;
+    minx = 400000;
+    miny = 4500000;
+    maxx = 600000;
+    maxy = 5000000;
+    fwrite(&id, 1, sizeof(double), f);
+    fwrite(&minx, 1, sizeof(double), f);
+    fwrite(&miny, 1, sizeof(double), f);
+    fwrite(&maxx, 1, sizeof(double), f);
+    fwrite(&maxy, 1, sizeof(double), f);
+    nodes = 2;
+    fwrite(&nodes, 1, sizeof(int), f);
+    x = 400000;
+    y = 5000000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 600000;
+    y = 4500000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+
+    id = 20;
+    minx = 400000;
+    miny = 4000000;
+    maxx = 600000;
+    maxy = 4500000;
+    fwrite(&id, 1, sizeof(double), f);
+    fwrite(&minx, 1, sizeof(double), f);
+    fwrite(&miny, 1, sizeof(double), f);
+    fwrite(&maxx, 1, sizeof(double), f);
+    fwrite(&maxy, 1, sizeof(double), f);
+    nodes = 2;
+    fwrite(&nodes, 1, sizeof(int), f);
+    x = 450000;
+    y = 4000000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 550000;
+    y = 4500000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+
+    fclose(f);
+
+
+
+    f = fopen("polygons.vct", "wb");
+    c = 0x03;
+    fwrite(&c, 1, 1, f);
+    nfeatures = 1;
+    fwrite(&nfeatures, 1, sizeof(int), f);
+    for(i=5;i<0x105;i++)
+    {
+        c = 0;
+        fwrite(&c, 1, 1, f);
+    }
+
+    id = 1;
+    minx = 400000;
+    miny = 4000000;
+    maxx = 600000;
+    maxy = 5000000;
+    fwrite(&id, 1, sizeof(double), f);
+    fwrite(&minx, 1, sizeof(double), f);
+    fwrite(&miny, 1, sizeof(double), f);
+    fwrite(&maxx, 1, sizeof(double), f);
+    fwrite(&maxy, 1, sizeof(double), f);
+    nparts = 2;
+    fwrite(&nparts, 1, sizeof(int), f);
+    nodes = 10;
+    fwrite(&nodes, 1, sizeof(int), f);
+
+    nodes = 5;
+    fwrite(&nodes, 1, sizeof(int), f);
+    x = 400000;
+    y = 4000000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 400000;
+    y = 5000000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 600000;
+    y = 5000000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 600000;
+    y = 4000000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 400000;
+    y = 4000000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+
+
+    nodes = 5;
+    fwrite(&nodes, 1, sizeof(int), f);
+    x = 450000;
+    y = 4250000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 450000;
+    y = 4750000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 550000;
+    y = 4750000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 550000;
+    y = 4250000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+    x = 450000;
+    y = 4250000;
+    fwrite(&x, 1, sizeof(double), f);
+    fwrite(&y, 1, sizeof(double), f);
+
+    fclose(f);
+
+    return 0;
+}
diff --git a/ogr/ogrsf_frmts/idrisi/makefile.vc b/ogr/ogrsf_frmts/idrisi/makefile.vc
new file mode 100644
index 0000000..76cbead
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogridrisidriver.obj ogridrisidatasource.obj ogridrisilayer.obj
+EXTRAFLAGS =	-I.. -I..\.. -I..\..\..\frmts\idrisi
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
new file mode 100644
index 0000000..b582488
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
@@ -0,0 +1,123 @@
+/******************************************************************************
+ * $Id: ogr_idrisi.h 23040 2011-09-04 14:42:12Z 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>
+ *
+ * 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_IDRISI_H_INCLUDED
+#define _OGR_IDRISI_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+/************************************************************************/
+/*                         OGRIdrisiLayer                               */
+/************************************************************************/
+
+class OGRIdrisiLayer : public OGRLayer
+{
+protected:
+    OGRFeatureDefn*    poFeatureDefn;
+    OGRSpatialReference *poSRS;
+    OGRwkbGeometryType eGeomType;
+
+    VSILFILE*          fp;
+    int                bEOF;
+
+    int                nNextFID;
+
+    int                bExtentValid;
+    double             dfMinX;
+    double             dfMinY;
+    double             dfMaxX;
+    double             dfMaxY;
+
+    unsigned int       nTotalFeatures;
+
+    virtual OGRFeature *       GetNextRawFeature();
+
+  public:
+                        OGRIdrisiLayer(const char* pszLayerName, VSILFILE* fp,
+                                       OGRwkbGeometryType eGeomType, const char* pszWTKString);
+                        ~OGRIdrisiLayer();
+
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    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);
+
+    virtual int         GetFeatureCount( int bForce = TRUE );
+};
+
+/************************************************************************/
+/*                        OGRIdrisiDataSource                           */
+/************************************************************************/
+
+class OGRIdrisiDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+  public:
+                        OGRIdrisiDataSource();
+                        ~OGRIdrisiDataSource();
+
+    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 * );
+};
+
+/************************************************************************/
+/*                         OGRIdrisiDriver                              */
+/************************************************************************/
+
+class OGRIdrisiDriver : public OGRSFDriver
+{
+  public:
+                ~OGRIdrisiDriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual int                 TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_IDRISI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
new file mode 100644
index 0000000..d9be723
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
@@ -0,0 +1,200 @@
+/******************************************************************************
+ * $Id: ogridrisidatasource.cpp 23040 2011-09-04 14:42:12Z 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>
+ *
+ * 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_idrisi.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "idrisi.h"
+
+CPL_CVSID("$Id: ogridrisidatasource.cpp 23040 2011-09-04 14:42:12Z rouault $");
+
+/************************************************************************/
+/*                        OGRIdrisiDataSource()                         */
+/************************************************************************/
+
+OGRIdrisiDataSource::OGRIdrisiDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+}
+
+/************************************************************************/
+/*                       ~OGRIdrisiDataSource()                         */
+/************************************************************************/
+
+OGRIdrisiDataSource::~OGRIdrisiDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRIdrisiDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRIdrisiDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRIdrisiDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (bUpdateIn)
+    {
+        return FALSE;
+    }
+
+// --------------------------------------------------------------------
+//      Does this appear to be a .vct file?
+// --------------------------------------------------------------------
+    if ( !EQUAL(CPLGetExtension(pszFilename), "vct") )
+        return FALSE;
+
+    pszName = CPLStrdup( pszFilename );
+
+    VSILFILE* fpVCT = VSIFOpenL(pszFilename, "rb");
+    if (fpVCT == NULL)
+        return FALSE;
+
+    char* pszWTKString = NULL;
+
+// --------------------------------------------------------------------
+//      Look for .vdc file
+// --------------------------------------------------------------------
+    const char* pszVDCFilename = CPLResetExtension(pszFilename, "vdc");
+    VSILFILE* fpVDC = VSIFOpenL(pszVDCFilename, "rb");
+    if (fpVDC == NULL)
+    {
+        pszVDCFilename = CPLResetExtension(pszFilename, "VDC");
+        fpVDC = VSIFOpenL(pszVDCFilename, "rb");
+    }
+
+    char** papszVDC = NULL;
+    if (fpVDC != NULL)
+    {
+        VSIFCloseL(fpVDC);
+        fpVDC = NULL;
+
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        papszVDC = CSLLoad2(pszVDCFilename, 1024, 256, NULL);
+        CPLPopErrorHandler();
+        CPLErrorReset();
+    }
+
+    OGRwkbGeometryType eType = wkbUnknown;
+
+    if (papszVDC != NULL)
+    {
+        CSLSetNameValueSeparator( papszVDC, ":" );
+
+        const char *pszVersion = CSLFetchNameValue( papszVDC, "file format " );
+
+        if( pszVersion == NULL || !EQUAL( pszVersion, "IDRISI Vector A.1" ) )
+        {
+            CSLDestroy( papszVDC );
+            VSIFCloseL(fpVCT);
+            return FALSE;
+        }
+
+        const char *pszRefSystem  = CSLFetchNameValue( papszVDC, "ref. system " );
+        const char *pszRefUnits   = CSLFetchNameValue( papszVDC, "ref. units  " );
+
+        if (pszRefSystem != NULL && pszRefUnits != NULL)
+            IdrisiGeoReference2Wkt( pszFilename, pszRefSystem, pszRefUnits, &pszWTKString);
+    }
+
+    GByte chType;
+    if (VSIFReadL(&chType, 1, 1, fpVCT) != 1)
+    {
+        VSIFCloseL(fpVCT);
+        CSLDestroy( papszVDC );
+        return FALSE;
+    }
+
+    if (chType == 1)
+        eType = wkbPoint;
+    else if (chType == 2)
+        eType = wkbLineString;
+    else if (chType == 3)
+        eType = wkbPolygon;
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Unsupport geometry type : %d",
+                    (int)chType);
+        VSIFCloseL(fpVCT);
+        CSLDestroy( papszVDC );
+        return FALSE;
+    }
+
+    const char *pszMinX       = CSLFetchNameValue( papszVDC, "min. X      " );
+    const char *pszMaxX       = CSLFetchNameValue( papszVDC, "max. X      " );
+    const char *pszMinY       = CSLFetchNameValue( papszVDC, "min. Y      " );
+    const char *pszMaxY       = CSLFetchNameValue( papszVDC, "max. Y      " );
+
+    OGRIdrisiLayer* poLayer = new OGRIdrisiLayer(CPLGetBasename(pszFilename), fpVCT, eType, pszWTKString);
+    papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+    papoLayers[nLayers ++] = poLayer;
+
+    if (pszMinX != NULL && pszMaxX != NULL && pszMinY != NULL && pszMaxY != NULL)
+    {
+        poLayer->SetExtent(CPLAtof(pszMinX), CPLAtof(pszMinY), CPLAtof(pszMaxX), CPLAtof(pszMaxY));
+    }
+
+    CPLFree(pszWTKString);
+
+    CSLDestroy( papszVDC );
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
new file mode 100644
index 0000000..129df51
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
@@ -0,0 +1,95 @@
+/******************************************************************************
+ * $I$
+ *
+ * Project:  Idrisi Translator
+ * Purpose:  Implements OGRIdrisiDriver.
+ * 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>
+ *
+ * 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_idrisi.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogridrisidriver.cpp 23040 2011-09-04 14:42:12Z 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
+
+extern "C" void RegisterOGRIdrisi();
+
+/************************************************************************/
+/*                       ~OGRIdrisiDriver()                         */
+/************************************************************************/
+
+OGRIdrisiDriver::~OGRIdrisiDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRIdrisiDriver::GetName()
+
+{
+    return "Idrisi";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRIdrisiDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRIdrisiDataSource   *poDS = new OGRIdrisiDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRIdrisiDriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                        RegisterOGRIdrisi()                       */
+/************************************************************************/
+
+void RegisterOGRIdrisi()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRIdrisiDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
new file mode 100644
index 0000000..c5fcf1b
--- /dev/null
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
@@ -0,0 +1,412 @@
+/******************************************************************************
+ * $Id: ogridrisilayer.cpp 23388 2011-11-18 23:34:35Z 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>
+ *
+ * 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_idrisi.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_p.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: ogridrisilayer.cpp 23388 2011-11-18 23:34:35Z rouault $");
+
+/************************************************************************/
+/*                         OGRIdrisiLayer()                             */
+/************************************************************************/
+
+OGRIdrisiLayer::OGRIdrisiLayer( const char* pszLayerName, VSILFILE* fp,
+                                OGRwkbGeometryType eGeomType,
+                                const char* pszWTKString )
+
+{
+    this->fp = fp;
+    this->eGeomType = eGeomType;
+    nNextFID = 1;
+    bEOF = FALSE;
+
+    if (pszWTKString)
+    {
+        poSRS = new OGRSpatialReference();
+        char* pszTmp = (char*)pszWTKString;
+        poSRS->importFromWkt(&pszTmp);
+    }
+    else
+        poSRS = NULL;
+
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( eGeomType );
+
+    OGRFieldDefn oFieldDefn("id", OFTReal);
+    poFeatureDefn->AddFieldDefn( &oFieldDefn );
+
+    bExtentValid = FALSE;
+    dfMinX = dfMinY = dfMaxX = dfMaxY = 0.0;
+
+    VSIFSeekL( fp, 1, SEEK_SET );
+    if (VSIFReadL( &nTotalFeatures, sizeof(unsigned int), 1, fp ) != 1)
+        nTotalFeatures = 0;
+    CPL_LSBPTR32(&nTotalFeatures);
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                          ~OGRIdrisiLayer()                           */
+/************************************************************************/
+
+OGRIdrisiLayer::~OGRIdrisiLayer()
+
+{
+    if( poSRS != NULL )
+        poSRS->Release();
+
+    poFeatureDefn->Release();
+
+    VSIFCloseL( fp );
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRIdrisiLayer::ResetReading()
+
+{
+    nNextFID = 1;
+    bEOF = FALSE;
+    VSIFSeekL( fp, 0x105, SEEK_SET );
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRIdrisiLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    while(TRUE)
+    {
+        if (bEOF)
+            return NULL;
+
+        poFeature = GetNextRawFeature();
+        if (poFeature == NULL)
+        {
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        if((m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeometryRef() ) )
+        && (m_poAttrQuery == NULL
+            || m_poAttrQuery->Evaluate( poFeature )) )
+        {
+            return poFeature;
+        }
+        else
+            delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRIdrisiLayer::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap, OLCFastFeatureCount))
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
+
+    if (EQUAL(pszCap, OLCFastGetExtent))
+        return bExtentValid;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
+{
+    while(TRUE)
+    {
+        if (eGeomType == wkbPoint)
+        {
+            double dfId;
+            double dfX, dfY;
+            if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfX, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfY, sizeof(double), 1, fp) != 1)
+            {
+                return NULL;
+            }
+            CPL_LSBPTR64(&dfId);
+            CPL_LSBPTR64(&dfX);
+            CPL_LSBPTR64(&dfY);
+
+            if (m_poFilterGeom != NULL &&
+                (dfX < m_sFilterEnvelope.MinX ||
+                 dfX > m_sFilterEnvelope.MaxX ||
+                 dfY < m_sFilterEnvelope.MinY ||
+                 dfY > m_sFilterEnvelope.MaxY))
+            {
+                nNextFID ++;
+                continue;
+            }
+
+            OGRPoint* poGeom = new OGRPoint(dfX, dfY);
+            if (poSRS)
+                poGeom->assignSpatialReference(poSRS);
+            OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+            poFeature->SetField(0, dfId);
+            poFeature->SetFID(nNextFID ++);
+            poFeature->SetGeometryDirectly(poGeom);
+            return poFeature;
+        }
+        else if (eGeomType == wkbLineString)
+        {
+            double dfId;
+            double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape;
+            unsigned int nNodes;
+
+            if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
+            {
+                return NULL;
+            }
+            CPL_LSBPTR64(&dfId);
+            CPL_LSBPTR64(&dfMinXShape);
+            CPL_LSBPTR64(&dfMaxXShape);
+            CPL_LSBPTR64(&dfMinYShape);
+            CPL_LSBPTR64(&dfMaxYShape);
+
+            if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
+            {
+                return NULL;
+            }
+            CPL_LSBPTR32(&nNodes);
+
+            if (nNodes > 100 * 1000 * 1000)
+                return NULL;
+
+            if (m_poFilterGeom != NULL &&
+                (dfMaxXShape < m_sFilterEnvelope.MinX ||
+                 dfMinXShape > m_sFilterEnvelope.MaxX ||
+                 dfMaxYShape < m_sFilterEnvelope.MinY ||
+                 dfMinYShape > m_sFilterEnvelope.MaxY))
+            {
+                nNextFID ++;
+                VSIFSeekL(fp, sizeof(OGRRawPoint) * nNodes, SEEK_CUR);
+                continue;
+            }
+
+            OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nNodes);
+            if (poRawPoints == NULL)
+            {
+                return NULL;
+            }
+
+            if ((unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes)
+            {
+                VSIFree(poRawPoints);
+                return NULL;
+            }
+
+#if defined(CPL_MSB)
+            for(unsigned int iNode=0; iNode<nNodes; iNode++)
+            {
+                CPL_LSBPTR64(&poRawPoints[iNode].x);
+                CPL_LSBPTR64(&poRawPoints[iNode].y);
+            }
+#endif
+
+            OGRLineString* poGeom = new OGRLineString();
+            poGeom->setPoints(nNodes, poRawPoints, NULL);
+
+            VSIFree(poRawPoints);
+
+            if (poSRS)
+                poGeom->assignSpatialReference(poSRS);
+            OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+            poFeature->SetField(0, dfId);
+            poFeature->SetFID(nNextFID ++);
+            poFeature->SetGeometryDirectly(poGeom);
+            return poFeature;
+        }
+        else /* if (eGeomType == wkbPolygon) */
+        {
+            double dfId;
+            double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape;
+            unsigned int nParts;
+            unsigned int nTotalNodes;
+
+            if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
+                VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
+            {
+                return NULL;
+            }
+            CPL_LSBPTR64(&dfId);
+            CPL_LSBPTR64(&dfMinXShape);
+            CPL_LSBPTR64(&dfMaxXShape);
+            CPL_LSBPTR64(&dfMinYShape);
+            CPL_LSBPTR64(&dfMaxYShape);
+            if (VSIFReadL(&nParts, sizeof(unsigned int), 1, fp) != 1 ||
+                VSIFReadL(&nTotalNodes, sizeof(unsigned int), 1, fp) != 1)
+            {
+                return NULL;
+            }
+            CPL_LSBPTR32(&nParts);
+            CPL_LSBPTR32(&nTotalNodes);
+
+            if (nParts > 100000 || nTotalNodes > 100 * 1000 * 1000)
+                return NULL;
+
+            if (m_poFilterGeom != NULL &&
+                (dfMaxXShape < m_sFilterEnvelope.MinX ||
+                 dfMinXShape > m_sFilterEnvelope.MaxX ||
+                 dfMaxYShape < m_sFilterEnvelope.MinY ||
+                 dfMinYShape > m_sFilterEnvelope.MaxY))
+            {
+                unsigned int iPart;
+                for(iPart = 0; iPart < nParts; iPart ++)
+                {
+                    unsigned int nNodes;
+                    if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
+                        return NULL;
+                    CPL_LSBPTR32(&nNodes);
+                    if (nNodes > nTotalNodes)
+                        return NULL;
+                    VSIFSeekL(fp, sizeof(OGRRawPoint) * nNodes, SEEK_CUR);
+                }
+                nNextFID ++;
+                continue;
+            }
+
+            OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nTotalNodes);
+            if (poRawPoints == NULL)
+            {
+                return NULL;
+            }
+
+            unsigned int iPart;
+            OGRPolygon* poGeom = new OGRPolygon();
+            for(iPart = 0; iPart < nParts; iPart ++)
+            {
+                unsigned int nNodes;
+                if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
+                {
+                    VSIFree(poRawPoints);
+                    delete poGeom;
+                    return NULL;
+                }
+                CPL_LSBPTR32(&nNodes);
+
+                if (nNodes > nTotalNodes ||
+                    (unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes)
+                {
+                    VSIFree(poRawPoints);
+                    delete poGeom;
+                    return NULL;
+                }
+
+#if defined(CPL_MSB)
+                for(unsigned int iNode=0; iNode<nNodes; iNode++)
+                {
+                    CPL_LSBPTR64(&poRawPoints[iNode].x);
+                    CPL_LSBPTR64(&poRawPoints[iNode].y);
+                }
+#endif
+
+                OGRLinearRing* poLR = new OGRLinearRing();
+                poGeom->addRingDirectly(poLR);
+                poLR->setPoints(nNodes, poRawPoints, NULL);
+            }
+
+            VSIFree(poRawPoints);
+
+            if (poSRS)
+                poGeom->assignSpatialReference(poSRS);
+            OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+            poFeature->SetField(0, dfId);
+            poFeature->SetFID(nNextFID ++);
+            poFeature->SetGeometryDirectly(poGeom);
+            return poFeature;
+        }
+    }
+}
+
+/************************************************************************/
+/*                             SetExtent()                              */
+/************************************************************************/
+
+void OGRIdrisiLayer::SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+{
+    bExtentValid = TRUE;
+    this->dfMinX = dfMinX;
+    this->dfMinY = dfMinY;
+    this->dfMaxX = dfMaxX;
+    this->dfMaxY = dfMaxY;
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr OGRIdrisiLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    if (!bExtentValid)
+        return OGRLayer::GetExtent(psExtent, bForce);
+
+    psExtent->MinX = dfMinX;
+    psExtent->MinY = dfMinY;
+    psExtent->MaxX = dfMaxX;
+    psExtent->MaxY = dfMaxY;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRIdrisiLayer::GetFeatureCount( int bForce )
+{
+    if (nTotalFeatures > 0 && m_poFilterGeom == NULL && m_poAttrQuery == NULL)
+        return nTotalFeatures;
+
+    return OGRLayer::GetFeatureCount(bForce);
+}
diff --git a/ogr/ogrsf_frmts/ili/drv_ili.html b/ogr/ogrsf_frmts/ili/drv_ili.html
index 42e74c5..ca90a80 100644
--- a/ogr/ogrsf_frmts/ili/drv_ili.html
+++ b/ogr/ogrsf_frmts/ili/drv_ili.html
@@ -25,8 +25,8 @@ With the usage of unified, documented geodata and the flexible exchange possibil
 <h2>Model</h2>
 
 Data is read and written into transfer files which have different formats in INTERLIS 1 (.itf) and INTERLIS 2 (.xml).
-For using the INTERLIS model (.ili) a Java interpreter is needed at runtime, 
-and the ili2c.jar file from <a href="http://www.interlis.ch/interlis2/docs23/ili2c-4.2.0.zip">ili2c-4.2.0.zip</a> must be in the Java path.
+For using the INTERLIS model (.ili) a Java interpreter is needed at runtime and ili2c.jar (included in the 
+<a href="http://interlis.ch/interlis2/download23_e.php#outils">Compiler for INTERLIS 2</a>) must be in the Java path.
 The model file can be added to the transfer file seperated by a comma.<p>
 Some possible transformations using <a href="http://www.gdal.org/ogr/ogr2ogr.html">ogr2ogr</a>.<p>
 <ul>
diff --git a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
index c621f66..61772e7 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1layer.cpp 16925 2009-05-03 14:16:49Z rouault $
+ * $Id: ogrili1layer.cpp 22143 2011-04-12 13:32:38Z pka $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_geos.h"
 
-CPL_CVSID("$Id: ogrili1layer.cpp 16925 2009-05-03 14:16:49Z rouault $");
+CPL_CVSID("$Id: ogrili1layer.cpp 22143 2011-04-12 13:32:38Z pka $");
 
 /************************************************************************/
 /*                           OGRILI1Layer()                              */
@@ -522,7 +522,12 @@ void OGRILI1Layer::PolygonizeAreaLayer()
     poAreaReferenceLayer->ResetReading();
     while (OGRFeature *feature = poAreaReferenceLayer->GetNextFeatureRef())
     {
-        GEOSGeom point = (GEOSGeom)feature->GetGeometryRef()->exportToGEOS();
+        OGRGeometry* geomRef = feature->GetGeometryRef();
+        if( !geomRef )
+        {
+            continue;
+        }
+        GEOSGeom point = (GEOSGeom)(geomRef->exportToGEOS());
         for (i = 0; i < polys->getNumGeometries(); i++ )
         {
             if (ahInGeoms[i] && GEOSWithin(point, ahInGeoms[i]))
diff --git a/ogr/ogrsf_frmts/kml/drv_kml.html b/ogr/ogrsf_frmts/kml/drv_kml.html
index 368d646..8c5de71 100644
--- a/ogr/ogrsf_frmts/kml/drv_kml.html
+++ b/ogr/ogrsf_frmts/kml/drv_kml.html
@@ -84,6 +84,17 @@ for further information.
 <pre>ogr2ogr -f KML output.kml input.shp -dsco AltitudeMode=absolute</pre>
 </li>  
 </ul>
+
+
+<h2>VSI Virtual File System API support</h2>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
+
 <h2>Example</h2>
 The ogr2ogr utility can be used to dump the results of a PostGIS query to
 KML:
diff --git a/ogr/ogrsf_frmts/kml/kml.cpp b/ogr/ogrsf_frmts/kml/kml.cpp
index d519cb2..52c418f 100644
--- a/ogr/ogrsf_frmts/kml/kml.cpp
+++ b/ogr/ogrsf_frmts/kml/kml.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kml.cpp 17946 2009-11-01 18:31:43Z rouault $
+ * $Id: kml.cpp 23589 2011-12-17 14:21:01Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -213,6 +213,15 @@ void XMLCALL KML::startElement(void* pUserData, const char* pszName, const char*
     if(poKML->poTrunk_ == NULL 
     || (poKML->poCurrent_->getName()).compare("description") != 0)
     {
+        if (poKML->nDepth_ == 1024)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Too big depth level (%d) while parsing KML.",
+                      poKML->nDepth_ );
+            XML_StopParser(poKML->oCurrentParser, XML_FALSE);
+            return;
+        }
+
         poMynew = new KMLNode();
             poMynew->setName(pszName);
         poMynew->setLevel(poKML->nDepth_);
@@ -463,12 +472,20 @@ void XMLCALL KML::dataHandler(void* pUserData, const char* pszData, int nLen)
         XML_StopParser(poKML->oCurrentParser, XML_FALSE);
     }
 
-    std::string sData(pszData, nLen);
+    try
+    {
+        std::string sData(pszData, nLen);
 
-    if(poKML->poCurrent_->numContent() == 0)
-        poKML->poCurrent_->addContent(sData);
-    else
-        poKML->poCurrent_->appendContent(sData);
+        if(poKML->poCurrent_->numContent() == 0)
+            poKML->poCurrent_->addContent(sData);
+        else
+            poKML->poCurrent_->appendContent(sData);
+    }
+    catch(const std::exception& ex)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "libstdc++ exception : %s", ex.what());
+        XML_StopParser(poKML->oCurrentParser, XML_FALSE);
+    }
 }
 
 bool KML::isValid()
@@ -487,9 +504,9 @@ std::string KML::getError() const
 	return sError_;
 }
 
-void KML::classifyNodes()
+int KML::classifyNodes()
 {
-    poTrunk_->classify(this);
+    return poTrunk_->classify(this);
 }
 
 void KML::eliminateEmpty()
diff --git a/ogr/ogrsf_frmts/kml/kml.h b/ogr/ogrsf_frmts/kml/kml.h
index 9e07bfa..cc49baf 100644
--- a/ogr/ogrsf_frmts/kml/kml.h
+++ b/ogr/ogrsf_frmts/kml/kml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kml.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: kml.h 23589 2011-12-17 14:21:01Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -76,7 +76,7 @@ public:
 	void parse();
 	void print(unsigned short what = 3);
     std::string getError() const;
-	void classifyNodes();
+	int classifyNodes();
 	void eliminateEmpty();
 	int getNumLayers() const;
     bool selectLayer(int);
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.cpp b/ogr/ogrsf_frmts/kml/kmlnode.cpp
index 383cf21..6216a00 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlnode.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.cpp 20602 2010-09-13 18:37:20Z rouault $
+ * $Id: kmlnode.cpp 23589 2011-12-17 14:21:01Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -200,11 +200,20 @@ void KMLNode::print(unsigned int what)
 //    return spaces;
 //}
 
-void KMLNode::classify(KML* poKML)
+int KMLNode::classify(KML* poKML, int nRecLevel)
 {
     Nodetype curr = Unknown;
     Nodetype all = Empty;
-    
+
+    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    if( nRecLevel == 32 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Too many recursiong level (%d) while parsing KML geometry.",
+                    nRecLevel );
+        return NULL;
+    }
+
     //CPLDebug("KML", "%s<%s>", genSpaces(), sName_.c_str());
     //nDepth ++;
     
@@ -245,7 +254,8 @@ void KMLNode::classify(KML* poKML)
         //CPLDebug("KML", "%s[%d] %s", genSpaces(), z, (*pvpoChildren_)[z]->sName_.c_str());
 
         // Classify pvpoChildren_
-        (*pvpoChildren_)[z]->classify(poKML);
+        if (!(*pvpoChildren_)[z]->classify(poKML, nRecLevel + 1))
+            return FALSE;
 
         curr = (*pvpoChildren_)[z]->eType_;
         b25D_ |= (*pvpoChildren_)[z]->b25D_;
@@ -283,6 +293,8 @@ void KMLNode::classify(KML* poKML)
 
     //nDepth --;
     //CPLDebug("KML", "%s</%s> --> eType=%s", genSpaces(), sName_.c_str(), Nodetype2String(eType_).c_str());
+
+    return TRUE;
 }
 
 void KMLNode::eliminateEmpty(KML* poKML)
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.h b/ogr/ogrsf_frmts/kml/kmlnode.h
index 16fad38..d56627f 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.h
+++ b/ogr/ogrsf_frmts/kml/kmlnode.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.h 17512 2009-08-03 20:12:58Z rouault $
+ * $Id: kmlnode.h 23589 2011-12-17 14:21:01Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -47,7 +47,7 @@ public:
     ~KMLNode();
 
     void print(unsigned int what = 3);
-    void classify(KML* poKML);
+    int classify(KML* poKML, int nRecLevel = 0);
     void eliminateEmpty(KML* poKML);
     
     void setType(Nodetype type);
diff --git a/ogr/ogrsf_frmts/kml/ogr_kml.h b/ogr/ogrsf_frmts/kml/ogr_kml.h
index 9a7bdfd..dd5a270 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 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_kml.h 23022 2011-09-01 19:10:17Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Declarations for OGR wrapper classes for KML, and OGR->KML
@@ -72,6 +72,8 @@ public:
     //
     void SetLayerNumber( int nLayer );
 
+    void SetClosedForWriting() { bClosedForWriting = TRUE; }
+
 private:
     OGRKMLDataSource* poDS_;
     OGRSpatialReference* poSRS_;
@@ -84,6 +86,7 @@ private:
     int bWriter_;
     int nLayerNumber_;
     int nWroteFeatureCount_;
+    int bClosedForWriting;
     char* pszName_;
 
     int nLastAsked;
@@ -153,7 +156,6 @@ private:
     VSILFILE* fpOutput_;
 
     OGREnvelope oEnvelope_;
-    int nSchemaInsertLocation_;
 	
 	//Have we issued a coordinate transformation already for this datasource
 	bool bIssuedCTError_;		
diff --git a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
index 2fb1f09..dc59a64 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrkmldatasource.cpp 20841 2010-10-16 15:22:05Z rouault $
+ * $Id: ogrkmldatasource.cpp 23589 2011-12-17 14:21:01Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLDataSource class.
@@ -134,7 +134,12 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
 /* -------------------------------------------------------------------- */
 /*      Classify the nodes                                              */
 /* -------------------------------------------------------------------- */
-    poKMLFile_->classifyNodes();
+    if( !poKMLFile_->classifyNodes() )
+    {
+        delete poKMLFile_;
+        poKMLFile_ = NULL;
+        return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Eliminate the empty containers                                  */
@@ -279,11 +284,12 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    pszName_ = CPLStrdup( pszName );
 
-    if( EQUAL(pszName, "stdout") || EQUAL(pszName, "/vsistdout/") )
+    if (strcmp(pszName, "/dev/stdout") == 0)
         pszName = "/vsistdout/";
 
+    pszName_ = CPLStrdup( pszName );
+
     fpOutput_ = VSIFOpenL( pszName, "wb" );
     if( fpOutput_ == NULL )
     {
@@ -296,8 +302,6 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 /*      Write out "standard" header.                                    */
 /* -------------------------------------------------------------------- */
     VSIFPrintfL( fpOutput_, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" );	
-
-    nSchemaInsertLocation_ = VSIFTellL( fpOutput_ );
     
     VSIFPrintfL( fpOutput_, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document>" );
 
@@ -335,6 +339,7 @@ OGRKMLDataSource::CreateLayer( const char * pszLayerName,
     if (GetLayerCount() > 0)
     {
         VSIFPrintfL( fpOutput_, "</Folder>\n");
+        ((OGRKMLLayer*)GetLayer(GetLayerCount()-1))->SetClosedForWriting();
     }
     
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
index d630e4a..3d821ed 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrkmllayer.cpp 21194 2010-12-04 18:01:45Z rouault $
+ * $Id: ogrkmllayer.cpp 22872 2011-08-06 20:32:14Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLLayer class.
@@ -102,6 +102,7 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
 
     bWriter_ = bWriterIn;
     nWroteFeatureCount_ = 0;
+    bClosedForWriting = (bWriterIn == FALSE);
 
     pszName_ = CPLStrdup(pszName);
 }
@@ -243,6 +244,13 @@ OGRErr OGRKMLLayer::CreateFeature( OGRFeature* poFeature )
     if( !bWriter_ )
         return OGRERR_FAILURE;
 
+    if( bClosedForWriting )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Interleaved feature adding to different layers is not supported");
+        return OGRERR_FAILURE;
+    }
+
     VSILFILE *fp = poDS_->GetOutputFP();
     CPLAssert( NULL != fp );
 
@@ -529,6 +537,9 @@ int OGRKMLLayer::TestCapability( const char * pszCap )
 //        return poFClass->GetFeatureCount() != -1;
     }
 
+    else if (EQUAL(pszCap, OLCStringsAsUTF8))
+        return TRUE;
+
     return FALSE;
 }
 
diff --git a/ogr/ogrsf_frmts/libkml/drv_libkml.html b/ogr/ogrsf_frmts/libkml/drv_libkml.html
index b5b1bac..4ce1174 100644
--- a/ogr/ogrsf_frmts/libkml/drv_libkml.html
+++ b/ogr/ogrsf_frmts/libkml/drv_libkml.html
@@ -250,7 +250,16 @@
     Setting the enviroment variable LIBKML_WRAPDATELINE to "yes" will cause the
     libkml driver to split the geometry at the dateline when read.
   </p>
-  
+
+<h2>VSI Virtual File System API support</h2>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/ (read-write) , /vsigzip/ (read-write) , /vsicurl/ (read-only) domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
+
   <h2>Example</h2>
  
   <p>
diff --git a/ogr/ogrsf_frmts/libkml/ogr_libkml.h b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
index 16500a8..5e326e2 100644
--- a/ogr/ogrsf_frmts/libkml/ogr_libkml.h
+++ b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
@@ -118,7 +118,11 @@ class OGRLIBKMLLayer:public OGRLayer
     ElementPtr                GetKmlLayerRoot () { return m_poKmlLayerRoot; };
     SchemaPtr                 GetKmlSchema () { return m_poKmlSchema; };
     const char               *GetFileName (  ) { return m_pszFileName; };
-    };
+
+
+    static CPLString          LaunderFieldNames(CPLString osName);
+
+};
 
 /******************************************************************************
   datasource class
@@ -279,7 +283,6 @@ class OGRLIBKMLDataSource:public OGRDataSource
 
 class OGRLIBKMLDriver:public OGRSFDriver
 {
-    int bUpdate;
     KmlFactory               *m_poKmlFactory;
     
   public:
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
index 105ea11..fdf0bba 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
@@ -661,7 +661,19 @@ int OGRLIBKMLDataSource::ParseLayers (
 
             std::string oKmlFeatName;
             if ( poKmlFeat->has_name (  ) ) {
-                oKmlFeatName = poKmlFeat->get_name (  );
+                /* Strip leading and trailing spaces */
+                const char* pszName = poKmlFeat->get_name (  ).c_str();
+                while(*pszName == ' ' || *pszName == '\n' || *pszName == '\r' || *pszName == '\t' )
+                    pszName ++;
+                oKmlFeatName = pszName;
+                int nSize = (int)oKmlFeatName.size();
+                while (nSize > 0 &&
+                       (oKmlFeatName[nSize-1] == ' ' || oKmlFeatName[nSize-1] == '\n' ||
+                        oKmlFeatName[nSize-1] == '\r' || oKmlFeatName[nSize-1] == '\t'))
+                {
+                    nSize --;
+                    oKmlFeatName.resize(nSize);
+                }
             }
 
             /***** use the feature index number as the name *****/
@@ -699,8 +711,8 @@ int OGRLIBKMLDataSource::ParseLayers (
 
 ******************************************************************************/
 
-ContainerPtr GetContainerFromRoot (
-    ElementPtr poKmlRoot )
+static ContainerPtr GetContainerFromRoot (
+    KmlFactory *m_poKmlFactory, ElementPtr poKmlRoot )
 {
     ContainerPtr poKmlContainer = NULL;
 
@@ -717,6 +729,12 @@ ContainerPtr GetContainerFromRoot (
 
                 if ( poKmlFeat->IsA ( kmldom::Type_Container ) )
                     poKmlContainer = AsContainer ( poKmlFeat );
+                else if ( poKmlFeat->IsA ( kmldom::Type_Placemark ) )
+                {
+                    poKmlContainer = m_poKmlFactory->CreateDocument (  );
+                    poKmlContainer->add_feature ( kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
+                }
+
             }
 
         }
@@ -751,7 +769,7 @@ int OGRLIBKMLDataSource::ParseIntoStyleTable (
     
     ContainerPtr poKmlContainer;
 
-    if ( !( poKmlContainer = GetContainerFromRoot ( poKmlRoot ) ) ) {
+    if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
         return false;
     }
     
@@ -825,7 +843,7 @@ int OGRLIBKMLDataSource::OpenKml (
 
     /***** get the container from root  *****/
 
-    if ( !( m_poKmlDSContainer = GetContainerFromRoot ( poKmlRoot ) ) ) {
+    if ( !( m_poKmlDSContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
         CPLError ( CE_Failure, CPLE_OpenFailed,
                    "ERROR Parseing kml %s :%s %s",
                    pszFilename, "This file does not fit the OGR model,",
@@ -941,7 +959,7 @@ int OGRLIBKMLDataSource::OpenKmz (
 
     ContainerPtr poKmlContainer;
 
-    if (!(poKmlContainer = GetContainerFromRoot ( poKmlDocKmlRoot ))) {
+    if (!(poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlDocKmlRoot ))) {
         CPLError ( CE_Failure, CPLE_OpenFailed,
                    "ERROR Parseing %s from %s :%s",
                    oKmlKmlPath.c_str (  ),
@@ -1011,7 +1029,7 @@ int OGRLIBKMLDataSource::OpenKmz (
                 /***** get the container from root  *****/
 
                 ContainerPtr poKmlLyrContainer =
-                    GetContainerFromRoot ( poKmlLyrRoot );
+                    GetContainerFromRoot ( m_poKmlFactory, poKmlLyrRoot );
 
                 if ( !poKmlLyrContainer )
                 {
@@ -1174,7 +1192,7 @@ int OGRLIBKMLDataSource::OpenDir (
 
         ContainerPtr poKmlContainer;
 
-        if ( !( poKmlContainer = GetContainerFromRoot ( poKmlRoot ) ) ) {
+        if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
             CPLError ( CE_Failure, CPLE_OpenFailed,
                        "ERROR Parseing kml %s :%s %s",
                        pszFilename,
@@ -1262,7 +1280,7 @@ int OGRLIBKMLDataSource::Open (
     /***** dir *****/
 
     VSIStatBufL sStatBuf = { };
-    if ( !VSIStatL ( pszFilename, &sStatBuf ) &&
+    if ( !VSIStatExL ( pszFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) &&
          VSI_ISDIR ( sStatBuf.st_mode ) )
         return OpenDir ( pszFilename, bUpdate );
 
@@ -1423,12 +1441,17 @@ int OGRLIBKMLDataSource::Create (
 
     int bResult = FALSE;
 
+    if (strcmp(pszFilename, "/dev/stdout") == 0)
+        pszFilename = "/vsistdout/";
+
     pszName = CPLStrdup ( pszFilename );
     bUpdate = TRUE;
 
     /***** kml *****/
 
-    if ( EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
+    if ( strcmp(pszFilename, "/vsistdout/") == 0 ||
+         strncmp(pszFilename, "/vsigzip/", 9) == 0 ||
+         EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
         bResult = CreateKml ( pszFilename, papszOptions );
 
     /***** kmz *****/
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
index c1baa29..26c8cfc 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
@@ -186,7 +186,7 @@ int OGRLIBKMLDriver::TestCapability (
         return TRUE;
 
     else if ( EQUAL ( pszCap, ODrCDeleteDataSource ) )
-        return bUpdate;
+        return TRUE;
 
     return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
index 58b73b1..6d57322 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
@@ -194,6 +194,7 @@ void featurestyle2kml (
     }
 }
 
+
 /******************************************************************************
  function to read a kml style into ogr's featurestyle
 ******************************************************************************/
@@ -205,18 +206,9 @@ void kml2featurestyle (
     OGRFeature * poOgrFeat )
 {
 
-    /***** does the placemark have a styleselector and a style url? *****/
-
-    if ( poKmlPlacemark->has_styleselector (  )
-         && poKmlPlacemark->has_styleurl (  ) ) {
-
-        /* todo do the style and styleurl part */
-
-    }
-
-    /***** is the style a style url *****/
+    /***** does the placemark have a style url? *****/
 
-    else if ( poKmlPlacemark->has_styleurl (  ) ) {
+    if (    poKmlPlacemark->has_styleurl (  ) ) {
 
         const string poKmlStyleUrl = poKmlPlacemark->get_styleurl (  );
 
@@ -227,16 +219,18 @@ void kml2featurestyle (
         OGRStyleTable *poOgrSTBLLayer;
         const char *pszTest = NULL;
 
-        if ( *pszUrl == '#'
-             && ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) ) {
+        /***** is it a layer style ? *****/
 
-            pszTest = poOgrSTBLLayer->Find ( pszUrl + 1 );
+        if ( *pszUrl == '#'
+             && ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) )
+        {
+             pszTest = poOgrSTBLLayer->Find ( pszUrl + 1 );
         }
-        
+
         if ( pszTest ) {
 
             /***** should we resolve the style *****/
-            
+
             const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
 
             if (EQUAL(pszResolve, "yes")) {
@@ -248,32 +242,31 @@ void kml2featurestyle (
 
                 *pszUrl = '@';
 
-                poOgrFeat->SetStyleStringDirectly ( pszUrl );
+                poOgrFeat->SetStyleString( pszUrl );
 
             }
 
         }
 
-        /***** not a layer style *****/
+        /***** is it a dataset style? *****/
         
-
         else {
 
-            /***** is it a dataset style? *****/
-
             int nPathLen = strlen ( poOgrDS->GetStylePath (  ) );
 
-            if ( nPathLen == 0 || EQUALN ( pszUrl, poOgrDS->GetStylePath (  ), nPathLen )) {
-
+            if (    nPathLen == 0
+                 || EQUALN ( pszUrl, poOgrDS->GetStylePath (  ), nPathLen ))
+            {
 
                 /***** should we resolve the style *****/
-            
+
                 const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
 
-                if ( EQUAL(pszResolve, "yes") &&
-                     ( poOgrSTBLLayer = poOgrDS->GetStyleTable (  ) ) &&
-                     ( pszTest = poOgrSTBLLayer->Find ( pszUrl + nPathLen + 1) )
-                    ) {
+                if (    EQUAL(pszResolve, "yes")
+                     && ( poOgrSTBLLayer = poOgrDS->GetStyleTable (  ) )
+                     && ( pszTest = poOgrSTBLLayer->Find ( pszUrl + nPathLen + 1) )
+                   )
+                {
 
                     poOgrFeat->SetStyleString ( pszTest );
                 }
@@ -283,10 +276,9 @@ void kml2featurestyle (
                     pszUrl[nPathLen] = '@';
                     poOgrFeat->SetStyleString ( pszUrl + nPathLen );
                 }
-
-                
+       
             }
-        
+            
             /**** its someplace else *****/
 
             else {
@@ -300,7 +292,7 @@ void kml2featurestyle (
                     char *pszUrlTmp = CPLStrdup(pszUrl);
                     char *pszPound;
                     if ((pszPound = strchr(pszUrlTmp, '#'))) {
-
+                        
                         *pszPound = '\0';
                     }
 
@@ -308,12 +300,11 @@ void kml2featurestyle (
 
                     VSILFILE *fp = NULL;
 
-                    if ((fp = VSIFOpenL( CPLFormFilename("/vsicurl/",
-                                                        pszUrlTmp,
-                                                        NULL),
-                                        "r" )) ||
-                        (fp = VSIFOpenL( pszUrlTmp,
-                                        "r" )))
+                    if (    (fp = VSIFOpenL( CPLFormFilename( "/vsicurl/",
+                                                              pszUrlTmp,
+                                                              NULL),
+                                             "r" ))
+                        ||  (fp = VSIFOpenL( pszUrlTmp, "r" )))
                     {
 
                         char szbuf[1025];
@@ -322,19 +313,19 @@ void kml2featurestyle (
                         /***** loop, read and copy to a string *****/
 
                         size_t nRead;
-                        
+                    
                         do {
-
+                            
                             nRead = VSIFReadL(szbuf, 1, sizeof(szbuf) - 1, fp);
                             
                             if (nRead == 0)
                                 break;
-                            
+
                             /***** copy buf to the string *****/
-                            
+
                             szbuf[nRead] = '\0';
                             oStyle.append( szbuf );
-    
+
                         } while (!VSIFEofL(fp));
 
                         VSIFCloseL(fp);
@@ -348,14 +339,13 @@ void kml2featurestyle (
                                               poOgrLayer,
                                               poOgrFeat );
                         }
-                        
+
                         else {
 
                             /***** if failed just store the url *****/
-                            
+
                             poOgrFeat->SetStyleString ( pszUrl );
                         }
-
                     }
                     CPLFree(pszUrlTmp);
                 }
@@ -366,14 +356,14 @@ void kml2featurestyle (
                 }
             }
 
-            CPLFree ( pszUrl );
         }
+        CPLFree ( pszUrl );
 
     }
 
     /***** does the placemark have a style selector *****/
 
-    else if ( poKmlPlacemark->has_styleselector (  ) ) {
+   if ( poKmlPlacemark->has_styleselector (  ) ) {
 
         StyleSelectorPtr poKmlStyleSelector =
             poKmlPlacemark->get_styleselector (  );
@@ -385,15 +375,27 @@ void kml2featurestyle (
 
             OGRStyleMgr *poOgrSM = new OGRStyleMgr;
 
-            poOgrSM->InitStyleString ( NULL );
+            /***** if were resolveing style the feature  *****/
+            /***** might already have styling to add too *****/
+            
+            const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
+            if (EQUAL(pszResolve, "yes")) {
+                 poOgrSM->InitFromFeature ( poOgrFeat );
+            }
+            else {
+
+                /***** if featyurestyle gets a name tool this needs changed to the above *****/
+                
+                poOgrSM->InitStyleString ( NULL );
+            }
 
             /***** read the style *****/
 
             kml2stylestring ( poKmlStyle, poOgrSM );
 
             /***** add the style to the feature *****/
-
-            poOgrSM->SetFeatureStyleString ( poOgrFeat );
+            
+            poOgrFeat->SetStyleString(poOgrSM->GetStyleString(NULL));
 
             delete poOgrSM;
         }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
index 46e9596..21440aa 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
@@ -37,6 +37,7 @@ using kmldom::ExtendedDataPtr;
 using kmldom::SchemaPtr;
 using kmldom::SchemaDataPtr;
 using kmldom::SimpleDataPtr;
+using kmldom::DataPtr;
 
 using kmldom::TimeStampPtr;
 using kmldom::TimeSpanPtr;
@@ -219,6 +220,37 @@ void ogr2tessellate_rec (
     }
 }
 
+
+/************************************************************************/
+/*                 OGRLIBKMLSanitizeUTF8String()                        */
+/************************************************************************/
+
+static char* OGRLIBKMLSanitizeUTF8String(const char* pszString)
+{
+    if (!CPLIsUTF8(pszString, -1) &&
+         CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
+    {
+        static int bFirstTime = TRUE;
+        if (bFirstTime)
+        {
+            bFirstTime = FALSE;
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
+                    "If you still want the original string and change the XML file encoding\n"
+                    "afterwards, you can define OGR_FORCE_ASCII=NO as configuration option.\n"
+                    "This warning won't be issued anymore", pszString);
+        }
+        else
+        {
+            CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
+                    pszString);
+        }
+        return CPLForceToASCII(pszString, -1, '?');
+    }
+    else
+        return CPLStrdup(pszString);
+}
+
 /******************************************************************************
  function to output ogr fields in kml
 
@@ -318,28 +350,28 @@ void field2kml (
 
         case OFTString:        //     String of ASCII chars
             {
-
+                char* pszUTF8String = OGRLIBKMLSanitizeUTF8String(
+                                        poOgrFeat->GetFieldAsString ( i ));
                 /***** name *****/
 
                 if ( EQUAL ( name, namefield ) ) {
-                    poKmlPlacemark->set_name ( poOgrFeat->
-                                               GetFieldAsString ( i ) );
+                    poKmlPlacemark->set_name ( pszUTF8String );
+                    CPLFree( pszUTF8String );
                     continue;
                 }
 
                 /***** description *****/
 
                 else if ( EQUAL ( name, descfield ) ) {
-                    poKmlPlacemark->set_description ( poOgrFeat->
-                                                      GetFieldAsString ( i ) );
+                    poKmlPlacemark->set_description ( pszUTF8String );
+                    CPLFree( pszUTF8String );
                     continue;
                 }
 
                 /***** altitudemode *****/
 
                 else if ( EQUAL ( name, altitudeModefield ) ) {
-                    const char *pszAltitudeMode =
-                        poOgrFeat->GetFieldAsString ( i );
+                    const char *pszAltitudeMode = pszUTF8String ;
 
                     int isGX = FALSE;
                     int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
@@ -375,6 +407,8 @@ void field2kml (
 
                     }
 
+                    CPLFree( pszUTF8String );
+
                     continue;
                 }
                 
@@ -384,9 +418,11 @@ void field2kml (
 
                     TimeStampPtr poKmlTimeStamp =
                         poKmlFactory->CreateTimeStamp (  );
-                    poKmlTimeStamp->set_when ( poOgrFeat->GetFieldAsString ( i )  );
+                    poKmlTimeStamp->set_when ( pszUTF8String  );
                     poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp );
 
+                    CPLFree( pszUTF8String );
+
                     continue;
                 }
 
@@ -399,7 +435,9 @@ void field2kml (
                         poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
                     }
 
-                    poKmlTimeSpan->set_begin ( poOgrFeat->GetFieldAsString ( i ) );
+                    poKmlTimeSpan->set_begin ( pszUTF8String );
+
+                    CPLFree( pszUTF8String );
 
                     continue;
 
@@ -414,7 +452,9 @@ void field2kml (
                         poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
                     }
 
-                    poKmlTimeSpan->set_end ( poOgrFeat->GetFieldAsString ( i ) );
+                    poKmlTimeSpan->set_end ( pszUTF8String );
+
+                    CPLFree( pszUTF8String );
 
                     continue;
                 }
@@ -423,8 +463,9 @@ void field2kml (
 
                 poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
                 poKmlSimpleData->set_name ( name );
-                poKmlSimpleData->set_text ( poOgrFeat->
-                                            GetFieldAsString ( i ) );
+                poKmlSimpleData->set_text ( pszUTF8String );
+
+                CPLFree( pszUTF8String );
 
                 break;
             }
@@ -1205,6 +1246,28 @@ void kml2field (
                 }
             }
         }
+
+        if (nSchemaData == 0 &&  poKmlExtendedData->get_data_array_size() > 0 )
+        {
+            int bLaunderFieldNames =
+                        CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
+            size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
+            for(size_t i=0; i < nDataArraySize; i++)
+            {
+                const DataPtr& data = poKmlExtendedData->get_data_array_at(i);
+                if (data->has_name() && data->has_value())
+                {
+                    CPLString osName = data->get_name();
+                    if (bLaunderFieldNames)
+                        osName = OGRLIBKMLLayer::LaunderFieldNames(osName);
+                    int iField = poOgrFeat->GetFieldIndex ( osName );
+                    if (iField >= 0)
+                    {
+                        poOgrFeat->SetField ( iField, data->get_value().c_str() );
+                    }
+                }
+            }
+        }
     }
 
 }
@@ -1311,48 +1374,48 @@ void kml2FeatureDef (
             pszType = oType.c_str (  );
         }
 
-        if ( poKmlSimpleField->has_displayname (  ) ) {
+        /* FIXME? We cannot set displayname as the field name because in kml2field() we make the */
+        /* lookup on fields based on their name. We would need some map if we really */
+        /* want to use displayname, but that might not be a good idea because displayname */
+        /* may have HTML formatting, which makes it impractical when converting to other */
+        /* drivers or to make requests */
+        /* Example: http://www.jasonbirch.com/files/newt_combined.kml */
+        /*if ( poKmlSimpleField->has_displayname (  ) ) {
             const string oName = poKmlSimpleField->get_displayname (  );
 
             pszName = oName.c_str (  );
         }
 
-        else if ( poKmlSimpleField->has_name (  ) ) {
+        else*/ if ( poKmlSimpleField->has_name (  ) ) {
             const string oName = poKmlSimpleField->get_name (  );
 
             pszName = oName.c_str (  );
         }
 
-        if ( EQUAL ( pszType, "string" ) ) {
-            OGRFieldDefn oOgrFieldName (
-    pszName,
-    OFTString );
+        if ( EQUAL ( pszType, "bool" ) ||
+             EQUAL ( pszType, "int" ) ||
+             EQUAL ( pszType, "short" ) ||
+             EQUAL ( pszType, "ushort" ) ) {
+            OGRFieldDefn oOgrFieldName ( pszName, OFTInteger );
 
             poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
         }
-        if ( EQUAL ( pszType, "int" ) ) {
-            OGRFieldDefn oOgrFieldName (
-    pszName,
-    OFTInteger );
+        else if ( EQUAL ( pszType, "float" ) ||
+                  EQUAL ( pszType, "double" ) ||
 
-            poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
-        }
-        if ( EQUAL ( pszType, "float" ) ) {
-            OGRFieldDefn oOgrFieldName (
-    pszName,
-    OFTReal );
+                  /* a too big uint wouldn't fit in a int, so we map it to OFTReal for now ... */
+                  EQUAL ( pszType, "uint" ) ) {
+            OGRFieldDefn oOgrFieldName ( pszName, OFTReal );
 
             poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
         }
-        if ( EQUAL ( pszType, "bool" ) ) {
-            OGRFieldDefn oOgrFieldName (
-    pszName,
-    OFTBinary );
+        else /* string, or any other unrecognized type */
+        {
+            OGRFieldDefn oOgrFieldName ( pszName, OFTString );
 
             poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
         }
 
-
     }
 
 
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
index a909a43..5fb5fc2 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
@@ -46,6 +46,7 @@ using kmlengine::KmlFile;
 using kmlengine::Bbox;
 using kmldom::ExtendedDataPtr;
 using kmldom::SchemaDataPtr;
+using kmldom::DataPtr;
 
 #include "ogrlibkmlfeature.h"
 #include "ogrlibkmlfield.h"
@@ -244,10 +245,27 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
                             kml2FeatureDef ( m_poKmlSchema,
                                              m_poOgrFeatureDefn );
                         }
-
-
-
-
+                    }
+                }
+                else if ( poKmlExtendedData->get_data_array_size() > 0 )
+                {
+                    /* Use the <Data> of the first placemark to build the feature definition */
+                    /* If others have different fields, too bad... */
+                    int bLaunderFieldNames =
+                        CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
+                    size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
+                    for(size_t i=0; i < nDataArraySize; i++)
+                    {
+                        const DataPtr& data = poKmlExtendedData->get_data_array_at(i);
+                        if (data->has_name())
+                        {
+                            CPLString osName = data->get_name();
+                            if (bLaunderFieldNames)
+                                osName = LaunderFieldNames(osName);
+                            OGRFieldDefn oOgrField ( osName,
+                                                    OFTString );
+                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                        }
                     }
                 }
             }
@@ -304,7 +322,7 @@ OGRLIBKMLLayer::~OGRLIBKMLLayer (  )
 
     CPLFree ( ( void * )m_pszName );
     CPLFree ( ( void * )m_pszFileName );
-    delete m_poOgrSRS;
+    m_poOgrSRS->Release();
 
     m_poOgrFeatureDefn->Release (  );
 
@@ -638,18 +656,41 @@ int OGRLIBKMLLayer::TestCapability (
 
     if ( EQUAL ( pszCap, OLCRandomRead ) )
         result = FALSE;
-    if ( EQUAL ( pszCap, OLCSequentialWrite ) )
+    else if ( EQUAL ( pszCap, OLCSequentialWrite ) )
         result = bUpdate;
-    if ( EQUAL ( pszCap, OLCRandomWrite ) )
+    else if ( EQUAL ( pszCap, OLCRandomWrite ) )
         result = FALSE;
-    if ( EQUAL ( pszCap, OLCFastFeatureCount ) )
+    else if ( EQUAL ( pszCap, OLCFastFeatureCount ) )
         result = FALSE;
-    if ( EQUAL ( pszCap, OLCFastSetNextByIndex ) )
+    else if ( EQUAL ( pszCap, OLCFastSetNextByIndex ) )
         result = FALSE;
-    if ( EQUAL ( pszCap, OLCCreateField ) )
+    else if ( EQUAL ( pszCap, OLCCreateField ) )
         result = bUpdate;
-    if ( EQUAL ( pszCap, OLCDeleteFeature ) )
+    else if ( EQUAL ( pszCap, OLCDeleteFeature ) )
         result = FALSE;
+    else if ( EQUAL(pszCap, OLCStringsAsUTF8) )
+        result = TRUE;
 
     return result;
 }
+
+/************************************************************************/
+/*                        LaunderFieldNames()                           */
+/************************************************************************/
+
+CPLString OGRLIBKMLLayer::LaunderFieldNames(CPLString osName)
+{
+    CPLString osLaunderedName;
+    for(int i=0;i<(int)osName.size();i++)
+    {
+        char ch = osName[i];
+        if ((ch >= '0' && ch <= '9') ||
+            (ch >= 'a' && ch <= 'z') ||
+            (ch >= 'A' && ch <= 'Z') ||
+            (ch == '_'))
+            osLaunderedName += ch;
+        else
+            osLaunderedName += "_";
+    }
+    return osLaunderedName;
+}
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
index 724a780..7efeb6b 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
@@ -271,9 +271,10 @@ void addstylestring2kml (
 
                 /***** scale *****/
 
-                double dfScale = poStyleLabel->Size ( nullcheck );
+                double dfScale = poStyleLabel->Stretch ( nullcheck );
 
                 if ( !nullcheck ) {
+                    dfScale /= 100.0;
                     poKmlLabelStyle->set_scale ( dfScale );
                 }
                 
@@ -352,28 +353,32 @@ void addstylestring2kml (
 ******************************************************************************/
 
 OGRStylePen *kml2pen (
-    LineStylePtr poKmlLineStyle );
+    LineStylePtr poKmlLineStyle,
+    OGRStylePen *poOgrStylePen);
 
 /******************************************************************************
  kml2brush
 ******************************************************************************/
 
 OGRStyleBrush *kml2brush (
-    PolyStylePtr poKmlPolyStyle );
+    PolyStylePtr poKmlPolyStyle,
+    OGRStyleBrush *poOgrStyleBrush);
 
 /******************************************************************************
- kml2brush
+ kml2symbol
 ******************************************************************************/
 
 OGRStyleSymbol *kml2symbol (
-    IconStylePtr poKmlIconStyle );
+    IconStylePtr poKmlIconStyle,
+    OGRStyleSymbol *poOgrStyleSymbol);
 
 /******************************************************************************
  kml2label
 ******************************************************************************/
 
 OGRStyleLabel *kml2label (
-    LabelStylePtr poKmlLabelStyle );
+    LabelStylePtr poKmlLabelStyle,
+    OGRStyleLabel *poOgrStyleLabel);
 
 /******************************************************************************
  kml2stylemgr
@@ -382,56 +387,154 @@ OGRStyleLabel *kml2label (
 void kml2stylestring (
     StylePtr poKmlStyle,
     OGRStyleMgr * poOgrSM )
+
 {
 
+    OGRStyleMgr * poOgrNewSM ;
+    OGRStyleTool *poOgrST = NULL;
+    OGRStyleTool *poOgrTmpST = NULL;
+    int i;
+
+    poOgrNewSM = new OGRStyleMgr( NULL );
+    
     /***** linestyle / pen *****/
 
     if ( poKmlStyle->has_linestyle (  ) ) {
+
+        poOgrNewSM->InitStyleString ( NULL );
+        
         LineStylePtr poKmlLineStyle = poKmlStyle->get_linestyle (  );
 
-        OGRStylePen *poOgrStylePen = kml2pen ( poKmlLineStyle );
+        poOgrTmpST = NULL;
+        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
+            poOgrST = poOgrSM->GetPart ( i, NULL );
 
-        poOgrSM->AddPart ( poOgrStylePen );
+            if ( !poOgrST )
+                continue;
+        
+            if ( poOgrST->GetType ( ) == OGRSTCPen ) {
+                poOgrTmpST = poOgrST;
+            }
+            else {
+                poOgrNewSM->AddPart ( poOgrST );
+                delete poOgrST;
+            }
+        }
+        
+        OGRStylePen *poOgrStylePen = kml2pen ( poKmlLineStyle,
+                                               ( OGRStylePen *) poOgrTmpST);
+        
+        poOgrNewSM->AddPart ( poOgrStylePen );
 
         delete poOgrStylePen;
+        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
+        
     }
 
     /***** polystyle / brush *****/
 
     if ( poKmlStyle->has_polystyle (  ) ) {
+
+        poOgrNewSM->InitStyleString ( NULL );
+
         PolyStylePtr poKmlPolyStyle = poKmlStyle->get_polystyle (  );
 
-        OGRStyleBrush *poOgrStyleBrush = kml2brush ( poKmlPolyStyle );
+        poOgrTmpST = NULL;
+        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
+            poOgrST = poOgrSM->GetPart ( i, NULL );
+
+            if ( !poOgrST )
+                continue;
+        
+            if ( poOgrST->GetType ( ) == OGRSTCBrush ) {
+                poOgrTmpST = poOgrST;
+            }
+            else {
+                poOgrNewSM->AddPart ( poOgrST );
+                delete poOgrST;
+            }
+        }
+
+        OGRStyleBrush *poOgrStyleBrush = kml2brush ( poKmlPolyStyle,
+                                                     ( OGRStyleBrush *) poOgrTmpST );
 
-        poOgrSM->AddPart ( poOgrStyleBrush );
+        poOgrNewSM->AddPart ( poOgrStyleBrush );
 
         delete poOgrStyleBrush;
+        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
+
     }
 
     /***** iconstyle / symbol *****/
 
     if ( poKmlStyle->has_iconstyle (  ) ) {
+        
+        poOgrNewSM->InitStyleString ( NULL );
+
         IconStylePtr poKmlIconStyle = poKmlStyle->get_iconstyle (  );
 
-        OGRStyleSymbol *poOgrStyleSymbol = kml2symbol ( poKmlIconStyle );
+        poOgrTmpST = NULL;
+        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
+            poOgrST = poOgrSM->GetPart ( i, NULL );
+
+            if ( !poOgrST )
+                continue;
+        
+            if ( poOgrST->GetType ( ) == OGRSTCSymbol ) {
+                poOgrTmpST = poOgrST;
+            }
+            else {
+                poOgrNewSM->AddPart ( poOgrST );
+                delete poOgrST;
+            }
+        }
+
+        OGRStyleSymbol *poOgrStyleSymbol = kml2symbol ( poKmlIconStyle,
+                                                     ( OGRStyleSymbol *) poOgrTmpST );
 
-        poOgrSM->AddPart ( poOgrStyleSymbol );
+        poOgrNewSM->AddPart ( poOgrStyleSymbol );
 
         delete poOgrStyleSymbol;
+        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
+
     }
 
     /***** labelstyle / label *****/
 
     if ( poKmlStyle->has_labelstyle (  ) ) {
+        
+        poOgrNewSM->InitStyleString ( NULL );
+
         LabelStylePtr poKmlLabelStyle = poKmlStyle->get_labelstyle (  );
 
-        OGRStyleLabel *poOgrStyleLabel = kml2label ( poKmlLabelStyle );
+        poOgrTmpST = NULL;
+        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
+            poOgrST = poOgrSM->GetPart ( i, NULL );
+
+            if ( !poOgrST )
+                continue;
+        
+            if ( poOgrST->GetType ( ) == OGRSTCLabel ) {
+                poOgrTmpST = poOgrST;
+            }
+            else {
+                poOgrNewSM->AddPart ( poOgrST );
+                delete poOgrST;
+            }
+        }
+
+        OGRStyleLabel *poOgrStyleLabel = kml2label ( poKmlLabelStyle,
+                                                     ( OGRStyleLabel *) poOgrTmpST );
 
-        poOgrSM->AddPart ( poOgrStyleLabel );
+        poOgrNewSM->AddPart ( poOgrStyleLabel );
 
         delete poOgrStyleLabel;
+        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
+
     }
 
+    delete poOgrNewSM;
+
 }
 
 
@@ -441,10 +544,16 @@ void kml2stylestring (
 ******************************************************************************/
 
 OGRStylePen *kml2pen (
-    LineStylePtr poKmlLineStyle )
+    LineStylePtr poKmlLineStyle,
+    OGRStylePen *poOgrStylePen)
 {
 
-    OGRStylePen *poOgrStylePen = new OGRStylePen (  );
+    if (!poOgrStylePen)
+        poOgrStylePen = new OGRStylePen (  );
+
+    /***** <LineStyle> should always have a width in pixels *****/
+    
+    poOgrStylePen->SetUnit(OGRSTUPixel);
 
     /***** width *****/
 
@@ -471,10 +580,12 @@ OGRStylePen *kml2pen (
 ******************************************************************************/
 
 OGRStyleBrush *kml2brush (
-    PolyStylePtr poKmlPolyStyle )
+    PolyStylePtr poKmlPolyStyle,
+    OGRStyleBrush *poOgrStyleBrush)
 {
 
-    OGRStyleBrush *poOgrStyleBrush = new OGRStyleBrush (  );
+    if (!poOgrStyleBrush)
+        poOgrStyleBrush = new OGRStyleBrush (  );
 
     /***** color *****/
 
@@ -496,10 +607,12 @@ OGRStyleBrush *kml2brush (
 ******************************************************************************/
 
 OGRStyleSymbol *kml2symbol (
-    IconStylePtr poKmlIconStyle )
+    IconStylePtr poKmlIconStyle,
+    OGRStyleSymbol *poOgrStyleSymbol)
 {
 
-    OGRStyleSymbol *poOgrStyleSymbol = new OGRStyleSymbol (  );
+    if (!poOgrStyleSymbol)
+        poOgrStyleSymbol = new OGRStyleSymbol (  );
 
     /***** id (kml icon) *****/
 
@@ -557,10 +670,12 @@ OGRStyleSymbol *kml2symbol (
 ******************************************************************************/
 
 OGRStyleLabel *kml2label (
-    LabelStylePtr poKmlLabelStyle )
+    LabelStylePtr poKmlLabelStyle,
+    OGRStyleLabel *poOgrStyleLabel)
 {
 
-    OGRStyleLabel *poOgrStyleLabel = new OGRStyleLabel (  );
+    if (!poOgrStyleLabel)
+        poOgrStyleLabel = new OGRStyleLabel (  );
 
     /***** color *****/
 
@@ -574,6 +689,13 @@ OGRStyleLabel *kml2label (
         poOgrStyleLabel->SetForColor ( szColor );
     }
 
+    if ( poKmlLabelStyle->has_scale (  ) ) {
+        double dfScale = poKmlLabelStyle->get_scale (  );
+        dfScale *= 100.0;
+
+        poOgrStyleLabel->SetStretch(dfScale);
+    }
+    
     return poOgrStyleLabel;
 }
 
diff --git a/ogr/ogrsf_frmts/makefile.vc b/ogr/ogrsf_frmts/makefile.vc
index 865d7a3..8e70b00 100644
--- a/ogr/ogrsf_frmts/makefile.vc
+++ b/ogr/ogrsf_frmts/makefile.vc
@@ -3,11 +3,14 @@ GDAL_ROOT	=	..\..
 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 vfk pgdump gpsbabel \
-			sua openair pds htf aeronavfaa $(ARCOBJECTS_DIR) \
+			sua openair pds htf aeronavfaa edigeo svg idrisi arcgen \
+			segukooa segy \
+			$(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)
+			$(PCIDSK_DIR) $(LIBKMLDIR) $(WFSDIR) $(SOSIDIR) $(GFTDIR) \
+			$(COUCHDBDIR) $(FGDB_DIR) $(XLSDIR)
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
@@ -26,8 +29,8 @@ OGDIOBJ =	ogdi\*.obj
 !ENDIF
 
 !IFDEF ODBC_SUPPORTED
-ODBCDIR	=	odbc pgeo mssqlspatial
-ODBCOBJ =	odbc\*.obj pgeo\*.obj mssqlspatial\*.obj
+ODBCDIR	=	odbc pgeo mssqlspatial geomedia
+ODBCOBJ =	odbc\*.obj pgeo\*.obj mssqlspatial\*.obj geomedia\*.obj
 !ENDIF
 
 !IFDEF SQLITE_LIB
@@ -60,6 +63,14 @@ SDE_DIR = sde
 SDE_OBJ = sde\*.obj
 !ENDIF
 
+!IFDEF FGDB_LIB
+!IF "$(FGDB_PLUGIN)" != "YES"
+FGDB_DIR = filegdb
+FGDB_OBJ = filegdb\*.obj
+!ENDIF
+!ENDIF
+
+
 !IFDEF HAS_ARCOBJECTS
 ARCOBJECTS_DIR = arcobjects
 ARCOBJECTS_OBJ = arcobjects\*.obj
@@ -106,6 +117,21 @@ SOSIDIR = sosi
 SOSI_OBJ = sosi\*.obj
 !ENDIF
 
+!IFDEF CURL_LIB
+GFTDIR = gft
+GFT_OBJ = gft\*.obj
+!ENDIF
+
+!IFDEF CURL_LIB
+COUCHDBDIR = couchdb
+COUCHDB_OBJ = couchdb\*.obj
+!ENDIF
+
+!IFDEF FREEXL_LIBS
+XLSDIR = xls
+XLS_OBJ = xls\*.obj
+!ENDIF
+
 default:
 	for %d in ( $(DIRLIST) ) do \
 		cd %d \
@@ -122,12 +148,13 @@ default:
 				 gpx\*.obj xplane\*.obj georss\*.obj gtm\*.obj \
 				 dxf\*.obj vfk\*.obj pgdump\*.obj gpsbabel\*.obj \
 				 sua\*.obj openair\*.obj pds\*.obj htf\*.obj \
-				 aeronavfaa\*.obj \
+				 aeronavfaa\*.obj edigeo\*.obj svg\*.obj idrisi\*.obj \
+				 arcgen\*.obj segukooa\*.obj segy\*.obj \
 				$(OGDIOBJ) $(ODBCOBJ) $(SQLITE_OBJ) \
 				$(FMEOBJ) $(OCIOBJ) $(PG_OBJ) $(MYSQL_OBJ) \
-				$(ILI_OBJ) $(DWG_OBJ) $(SDE_OBJ) $(ARCDRIVER_OBJ) $(IDB_OBJ) \
+				$(ILI_OBJ) $(DWG_OBJ) $(SDE_OBJ) $(FGDB_OBJ) $(ARCDRIVER_OBJ) $(IDB_OBJ) \
 				$(DODS_OBJ) $(NAS_OBJ) $(PCIDSKOBJ) $(LIBKMLOBJ) $(WFS_OBJ) \
-				$(SOSI_OBJ)
+				$(SOSI_OBJ) $(GFT_OBJ) $(COUCHDB_OBJ) $(XLS_OBJ)
 	lib /out:ogrsf_frmts_sup.lib \
 				 ..\..\frmts\iso8211\*.obj \
 				 ..\..\frmts\sdts\sdtsattrreader.obj \
diff --git a/ogr/ogrsf_frmts/mdb/GNUmakefile b/ogr/ogrsf_frmts/mdb/GNUmakefile
new file mode 100644
index 0000000..33f7425
--- /dev/null
+++ b/ogr/ogrsf_frmts/mdb/GNUmakefile
@@ -0,0 +1,15 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrmdbdatasource.o ogrmdblayer.o ogrmdbdriver.o \
+		ogrmdbjackcess.o
+
+CPPFLAGS	:=	-I.. $(GDAL_INCLUDE) $(JAVA_INC) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_mdb.h
diff --git a/ogr/ogrsf_frmts/mdb/drv_mdb.html b/ogr/ogrsf_frmts/mdb/drv_mdb.html
new file mode 100644
index 0000000..0137a77
--- /dev/null
+++ b/ogr/ogrsf_frmts/mdb/drv_mdb.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
+
+<html>
+<head>
+
+  <title>Access MDB databases</title>
+</head>
+
+<body bgcolor="#FFFFFF">
+  <h1>Access MDB databases</h1>
+
+  <p>GDAL/OGR >= 1.9.0</p>
+
+  <p>OGR optionally supports reading access .mdb
+  files by using the Java <a href="http://jackcess.sourceforge.net/">Jackcess</a> library.</p>
+
+  <p>This driver is primarly meant as being used on Unix platforms to overcome the
+     issues often met with the MDBTools library that acts as the ODBC driver for MDB databases.</p>
+
+  <p>The driver can detect ESRI Personal Geodatabases and Geomedia MDB databases, and will
+     deal them exactly as the <a href="drv_pgeo.html">PGeo</a> and
+     <a href="drv_geomedia.html">Geomedia</a> drivers do. For other MDB databases, all the tables
+     will be presented as OGR layers.</p>
+
+  <h2>How to build the MDB driver (on Linux)</h2>
+
+  You need a JDK (a JRE is not enough) to build the driver.
+
+  On Ubuntu 10.04 with the openjdk-6-jdk package installed,
+
+  <pre>./configure --with-java=yes --with-mdb=yes</pre>
+
+  It is possible to add the <i>--with-jvm-lib-add-rpath</i> option to embed the path to the libjvm.so in the GDAL library.<p>
+
+  On others Linux flavours, you may need to specify :
+
+  <pre>./configure --with-java=/path/to/jdk/root/path --with-jvm-lib=/path/to/libjvm/directory --with-mdb=yes</pre>
+
+  where /path/to/libjvm/directory is for example /usr/lib/jvm/java-6-openjdk/jre/lib/amd64
+
+  <h2>How to run the MDB driver (on Linux)</h2>
+
+  You need a JRE and 3 external JARs to run the driver.
+
+  <ol>
+  <li>If you didn't specify --with-jvm-lib-add-rpath at configure time, set the path of the directory that contains libjvm.so in LD_LIBRARY_PATH or in /etc/ld.so.conf.</li>
+  <li>Download jackcess-1.2.2.jar, commons-lang-2.4.jar and commons-logging-1.1.1.jar (other versions might work)</li>
+  <li>Put the 3 JARs either in the lib/ext directory of the JRE (e.g. /usr/lib/jvm/java-6-openjdk/jre/lib/ext) or in another directory
+  and explicitely point them with the CLASSPATH environment variable.</li>
+  </ol>
+
+  <h2>Resources</h2>
+
+  <ul>
+  <li><a href="http://jackcess.sourceforge.net/">Jackcess</a> library home page</li>
+  <li>Utility that contains the needed <a href="http://mdb-sqlite.googlecode.com/files/mdb-sqlite-1.0.2.tar.bz2">JARs dependencies</a></lib>
+  </ul>
+
+  <h2>See also</h2>
+
+  <ul>
+  <li><a href="drv_pgeo.html">PGeo</a> driver page</li>
+  <li><a href="drv_geomedia.html">Geomedia</a> driver page</li>
+  </ul>
+
+</body>
+</html>
+
diff --git a/ogr/ogrsf_frmts/mdb/ogr_mdb.h b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
new file mode 100644
index 0000000..5ac3a90
--- /dev/null
+++ b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
@@ -0,0 +1,345 @@
+/******************************************************************************
+ * $Id: ogr_mdb.h 21557 2011-01-22 23:42:14Z 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>
+ *
+ * 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_MDB_H_INCLUDED
+#define _OGR_MDB_H_INCLUDED
+
+#include <jni.h>
+#include <vector>
+
+#include "ogrsf_frmts.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+
+/************************************************************************/
+/*                            OGRMDBJavaEnv                             */
+/************************************************************************/
+
+class OGRMDBJavaEnv
+{
+    public:
+        OGRMDBJavaEnv();
+        ~OGRMDBJavaEnv();
+
+        int Init();
+
+
+    JavaVM *jvm;
+    JNIEnv *env;
+    int bCalledFromJava;
+
+    int ExceptionOccured();
+
+    jclass byteArray_class;
+
+    jclass file_class;
+    jmethodID file_constructor;
+    jclass database_class;
+    jmethodID database_open;
+    jmethodID database_close;
+    jmethodID database_getTableNames;
+    jmethodID database_getTable;
+
+    jclass table_class;
+    jmethodID table_getColumns;
+    jmethodID table_iterator;
+    jmethodID table_getRowCount;
+
+    jclass column_class;
+    jmethodID column_getName;
+    jmethodID column_getType;
+    jmethodID column_getLength;
+    jmethodID column_isVariableLength;
+
+    jclass datatype_class;
+    jmethodID datatype_getValue;
+
+    jclass list_class;
+    jmethodID list_iterator;
+
+    jclass set_class;
+    jmethodID set_iterator;
+
+    jclass map_class;
+    jmethodID map_get;
+
+    jclass iterator_class;
+    jmethodID iterator_hasNext;
+    jmethodID iterator_next;
+
+    jclass object_class;
+    jmethodID object_toString;
+    jmethodID object_getClass;
+
+    jclass boolean_class;
+    jmethodID boolean_booleanValue;
+
+    jclass byte_class;
+    jmethodID byte_byteValue;
+
+    jclass short_class;
+    jmethodID short_shortValue;
+    
+    jclass integer_class;
+    jmethodID integer_intValue;
+
+    jclass float_class;
+    jmethodID float_floatValue;
+
+    jclass double_class;
+    jmethodID double_doubleValue;
+};
+
+/************************************************************************/
+/*                           OGRMDBDatabase                             */
+/************************************************************************/
+
+class OGRMDBTable;
+
+class OGRMDBDatabase
+{
+    OGRMDBJavaEnv* env;
+    jobject database;
+
+    OGRMDBDatabase();
+public:
+    static OGRMDBDatabase* Open(OGRMDBJavaEnv* env, const char* pszName);
+    ~OGRMDBDatabase();
+
+    std::vector<CPLString>   apoTableNames;
+    int                FetchTableNames();
+    OGRMDBTable* GetTable(const char* pszTableName);
+};
+
+/************************************************************************/
+/*                             OGRMDBTable                              */
+/************************************************************************/
+
+class OGRMDBTable
+{
+    OGRMDBJavaEnv* env;
+    OGRMDBDatabase* poDB;
+    jobject table;
+
+    jobject table_iterator_obj;
+    jobject row;
+
+    jobject GetColumnVal(int iCol);
+
+    CPLString osTableName;
+
+    std::vector<CPLString> apoColumnNames;
+    std::vector<jstring>   apoColumnNameObjects;
+    std::vector<int>       apoColumnTypes;
+    std::vector<int>       apoColumnLengths;
+
+public:
+    OGRMDBTable(OGRMDBJavaEnv* env, OGRMDBDatabase* poDB, jobject table, const char* pszTableName);
+    ~OGRMDBTable();
+
+    OGRMDBDatabase* GetDB() { return poDB; }
+
+    const char* GetName() { return osTableName.c_str(); }
+
+    int GetColumnCount() { return (int)apoColumnNames.size(); }
+    int GetColumnIndex(const char* pszColName, int bEmitErrorIfNotFound = FALSE);
+    const char* GetColumnName(int iIndex) { return apoColumnNames[iIndex].c_str(); }
+    int GetColumnType(int iIndex) { return apoColumnTypes[iIndex]; }
+    int GetColumnLength(int iIndex) { return apoColumnLengths[iIndex]; }
+
+    void DumpTable();
+
+    int FetchColumns();
+
+    int GetRowCount();
+    int GetNextRow();
+    void ResetReading();
+
+    char* GetColumnAsString(int iCol);
+    int GetColumnAsInt(int iCol);
+    double GetColumnAsDouble(int iCol);
+    GByte* GetColumnAsBinary(int iCol, int* pnBytes);
+
+};
+
+typedef enum 
+{
+    MDB_Boolean = 0x01,
+    MDB_Byte = 0x02,
+    MDB_Short = 0x03,
+    MDB_Int = 0x04,
+    MDB_Money = 0x05,
+    MDB_Float = 0x06,
+    MDB_Double = 0x07,
+    MDB_ShortDateTime = 0x08,
+    MDB_Binary = 0x09,
+    MDB_Text = 0x0A,
+    MDB_OLE = 0x0B,
+    MDB_Memo = 0x0C,
+    MDB_Unknown = 0x0D,
+    MDB_GUID = 0x0F,
+    MDB_Numeric = 0x10
+} MDBType;
+
+typedef enum
+{
+    MDB_GEOM_NONE,
+    MDB_GEOM_PGEO,
+    MDB_GEOM_GEOMEDIA
+} MDBGeometryType;
+
+/************************************************************************/
+/*                            OGRMDBLayer                              */
+/************************************************************************/
+
+class OGRMDBDataSource;
+    
+class OGRMDBLayer : public OGRLayer
+{
+  protected:
+    OGRMDBTable* poMDBTable;
+
+    MDBGeometryType     eGeometryType;
+
+    OGRFeatureDefn     *poFeatureDefn;
+
+    // Layer spatial reference system, and srid.
+    OGRSpatialReference *poSRS;
+    int                 nSRSId;
+
+    int                 iNextShapeId;
+
+    OGRMDBDataSource    *poDS;
+
+    int                 iGeomColumn;
+    char                *pszGeomColumn;
+    char                *pszFIDColumn;
+
+    int                *panFieldOrdinals;
+
+    int                 bHasExtent;
+    OGREnvelope         sExtent;
+
+    void                LookupSRID( int );
+
+  public:
+                        OGRMDBLayer(OGRMDBDataSource* poDS, OGRMDBTable* poMDBTable);
+    virtual             ~OGRMDBLayer();
+
+    CPLErr              BuildFeatureDefn();
+
+    CPLErr              Initialize( const char *pszTableName,
+                                    const char *pszGeomCol,
+                                    int nShapeType,
+                                    double dfExtentLeft,
+                                    double dfExtentRight,
+                                    double dfExtentBottom,
+                                    double dfExtentTop,
+                                    int nSRID,
+                                    int bHasZ );
+
+    CPLErr              Initialize( const char *pszTableName,
+                                    const char *pszGeomCol,
+                                    OGRSpatialReference* poSRS );
+
+    virtual void        ResetReading();
+    virtual int         GetFeatureCount( int bForce );
+    virtual OGRFeature *GetNextRawFeature();
+    virtual OGRFeature *GetNextFeature();
+
+    virtual OGRFeature *GetFeature( long nFeatureId );
+    
+    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 );
+};
+
+/************************************************************************/
+/*                           OGRMDBDataSource                            */
+/************************************************************************/
+
+class OGRMDBDataSource : public OGRDataSource
+{
+    OGRMDBLayer        **papoLayers;
+    int                 nLayers;
+
+    OGRMDBLayer        **papoLayersInvisible;
+    int                 nLayersWithInvisible;
+
+    char               *pszName;
+
+    OGRMDBJavaEnv       env;
+
+    OGRMDBDatabase*     poDB;
+
+    int                 OpenGDB(OGRMDBTable* poGDB_GeomColumns);
+    int                 OpenGeomediaWarehouse(OGRMDBTable* poGAliasTable);
+    OGRSpatialReference* GetGeomediaSRS(const char* pszGCoordSystemTable,
+                                        const char* pszGCoordSystemGUID);
+
+  public:
+                        OGRMDBDataSource();
+                        ~OGRMDBDataSource();
+
+    int                 Open( const char *, int bUpdate, int bTestOpen );
+    int                 OpenTable( const char *pszTableName, 
+                                   const char *pszGeomCol,
+                                   int bUpdate );
+
+    const char          *GetName() { return pszName; }
+    int                 GetLayerCount() { return nLayers; }
+    OGRLayer            *GetLayer( int );
+    OGRLayer            *GetLayerByName( const char* pszLayerName );
+
+    int                 TestCapability( const char * );
+};
+
+/************************************************************************/
+/*                             OGRMDBDriver                             */
+/************************************************************************/
+
+class OGRMDBDriver : public OGRSFDriver
+{
+  public:
+                ~OGRMDBDriver();
+
+    const char  *GetName();
+    OGRDataSource *Open( const char *, int );
+
+    int          TestCapability( const char * );
+};
+
+#endif /* ndef _OGR_MDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
new file mode 100644
index 0000000..e0654f4
--- /dev/null
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
@@ -0,0 +1,441 @@
+/******************************************************************************
+ * $Id: ogrmdbdatasource.cpp 21562 2011-01-23 12:29:25Z 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>
+ *
+ * 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_mdb.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include <vector>
+#include "ogrgeomediageometry.h"
+
+CPL_CVSID("$Id: ogrmdbdatasource.cpp 21562 2011-01-23 12:29:25Z rouault $");
+
+/************************************************************************/
+/*                         OGRMDBDataSource()                          */
+/************************************************************************/
+
+OGRMDBDataSource::OGRMDBDataSource()
+
+{
+    pszName = NULL;
+    papoLayers = NULL;
+    papoLayersInvisible = NULL;
+    nLayers = 0;
+    nLayersWithInvisible = 0;
+    poDB = NULL;
+}
+
+/************************************************************************/
+/*                         ~OGRMDBDataSource()                         */
+/************************************************************************/
+
+OGRMDBDataSource::~OGRMDBDataSource()
+
+{
+    int         i;
+
+    CPLFree( pszName );
+
+    for( i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    for( i = 0; i < nLayersWithInvisible; i++ )
+        delete papoLayersInvisible[i];
+    CPLFree( papoLayersInvisible );
+
+
+    delete poDB;
+}
+
+
+/************************************************************************/
+/*                              OpenGDB()                               */
+/************************************************************************/
+
+int OGRMDBDataSource::OpenGDB(OGRMDBTable* poGDB_GeomColumns)
+{
+    int iTableName = poGDB_GeomColumns->GetColumnIndex("TableName", TRUE);
+    int iFieldName = poGDB_GeomColumns->GetColumnIndex("FieldName", TRUE);
+    int iShapeType = poGDB_GeomColumns->GetColumnIndex("ShapeType", TRUE);
+    int iExtentLeft = poGDB_GeomColumns->GetColumnIndex("ExtentLeft", TRUE);
+    int iExtentRight = poGDB_GeomColumns->GetColumnIndex("ExtentRight", TRUE);
+    int iExtentBottom = poGDB_GeomColumns->GetColumnIndex("ExtentBottom", TRUE);
+    int iExtentTop = poGDB_GeomColumns->GetColumnIndex("ExtentTop", TRUE);
+    int iSRID = poGDB_GeomColumns->GetColumnIndex("SRID", TRUE);
+    int iHasZ = poGDB_GeomColumns->GetColumnIndex("HasZ", TRUE);
+
+    if (iTableName < 0 || iFieldName < 0 || iShapeType < 0 ||
+        iExtentLeft < 0 || iExtentRight < 0 || iExtentBottom < 0 ||
+        iExtentTop < 0 || iSRID < 0 || iHasZ < 0)
+        return FALSE;
+
+    while(poGDB_GeomColumns->GetNextRow())
+    {
+        OGRMDBLayer  *poLayer;
+
+        char* pszTableName = poGDB_GeomColumns->GetColumnAsString(iTableName);
+        char* pszFieldName = poGDB_GeomColumns->GetColumnAsString(iFieldName);
+        if (pszTableName == NULL || pszFieldName == NULL)
+        {
+            CPLFree(pszTableName);
+            CPLFree(pszFieldName);
+            continue;
+        }
+
+        OGRMDBTable* poTable = poDB->GetTable(pszTableName);
+        if (poTable == NULL)
+        {
+            CPLFree(pszTableName);
+            CPLFree(pszFieldName);
+            continue;
+        }
+
+        poLayer = new OGRMDBLayer( this, poTable );
+
+        if( poLayer->Initialize( pszTableName,
+                                 pszFieldName,
+                                 poGDB_GeomColumns->GetColumnAsInt(iShapeType),
+                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentLeft),
+                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentRight),
+                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentBottom),
+                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentTop),
+                                 poGDB_GeomColumns->GetColumnAsInt(iSRID),
+                                 poGDB_GeomColumns->GetColumnAsInt(iHasZ) )
+            != CE_None )
+        {
+            delete poLayer;
+        }
+        else
+        {
+            papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
+            papoLayers[nLayers++] = poLayer;
+        }
+
+        CPLFree(pszTableName);
+        CPLFree(pszFieldName);
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        OpenGeomediaWarehouse()                       */
+/************************************************************************/
+
+int OGRMDBDataSource::OpenGeomediaWarehouse(OGRMDBTable* poGAliasTable)
+{
+    int iTableName = poGAliasTable->GetColumnIndex("TableName", TRUE);
+    int iTableType = poGAliasTable->GetColumnIndex("TableType", TRUE);
+
+    if (iTableName < 0 || iTableType < 0)
+        return FALSE;
+
+    char* pszFeatureTableName = NULL;
+    char* pszGeometryProperties = NULL;
+    char* pszGCoordSystemTable = NULL;
+    while(poGAliasTable->GetNextRow())
+    {
+        char* pszTableType = poGAliasTable->GetColumnAsString(iTableType);
+        if (pszTableType == NULL)
+            continue;
+
+        if (strcmp(pszTableType, "INGRFeatures") == 0)
+        {
+            pszFeatureTableName = poGAliasTable->GetColumnAsString(iTableName);
+        }
+        else if (strcmp(pszTableType, "INGRGeometryProperties") == 0)
+        {
+            pszGeometryProperties = poGAliasTable->GetColumnAsString(iTableName);
+        }
+        else if (strcmp(pszTableType, "GCoordSystemTable") == 0)
+        {
+            pszGCoordSystemTable = poGAliasTable->GetColumnAsString(iTableName);
+        }
+
+        CPLFree(pszTableType);
+    }
+
+    if (pszFeatureTableName == NULL)
+    {
+        CPLFree(pszGeometryProperties);
+        CPLFree(pszGCoordSystemTable);
+        return FALSE;
+    }
+
+    OGRMDBTable* poGFeaturesTable = poDB->GetTable(pszFeatureTableName);
+    CPLFree(pszFeatureTableName);
+    pszFeatureTableName = NULL;
+
+    OGRMDBTable* poGeometryPropertiesTable;
+    if (pszGeometryProperties)
+        poGeometryPropertiesTable = poDB->GetTable(pszGeometryProperties);
+    else
+        poGeometryPropertiesTable = NULL;
+    CPLFree(pszGeometryProperties);
+    pszGeometryProperties = NULL;
+
+    if (poGFeaturesTable == NULL)
+    {
+        delete poGeometryPropertiesTable;
+        CPLFree(pszGCoordSystemTable);
+        return FALSE;
+    }
+
+    int iFeatureName = poGFeaturesTable->GetColumnIndex("FeatureName", TRUE);
+    int iGeometryType = poGFeaturesTable->GetColumnIndex("GeometryType", TRUE);
+    int iPrimaryGeometryFieldName = poGFeaturesTable->GetColumnIndex("PrimaryGeometryFieldName", TRUE);
+
+    if (iFeatureName < 0 || iGeometryType < 0 || iPrimaryGeometryFieldName < 0)
+    {
+        delete poGeometryPropertiesTable;
+        delete poGFeaturesTable;
+        CPLFree(pszGCoordSystemTable);
+        return FALSE;
+    }
+
+    if (poGeometryPropertiesTable != NULL && poGeometryPropertiesTable->GetRowCount() != poGFeaturesTable->GetRowCount())
+    {
+        delete poGeometryPropertiesTable;
+        poGeometryPropertiesTable = NULL;
+    }
+
+    int iGCoordSystemGUID = -1;
+    if (poGeometryPropertiesTable)
+    {
+        iGCoordSystemGUID = poGeometryPropertiesTable->GetColumnIndex("GCoordSystemGUID", TRUE);
+        if (iGCoordSystemGUID < 0)
+        {
+            delete poGeometryPropertiesTable;
+            delete poGFeaturesTable;
+            CPLFree(pszGCoordSystemTable);
+            return FALSE;
+        }
+    }
+
+    while(poGFeaturesTable->GetNextRow() &&
+          (poGeometryPropertiesTable == NULL || poGeometryPropertiesTable->GetNextRow()))
+    {
+        char* pszFeatureName = poGFeaturesTable->GetColumnAsString(iFeatureName);
+        //int nGeometryType = poGFeaturesTable->GetColumnAsInt(iGeometryType);
+        char* pszGeometryFieldName = poGFeaturesTable->GetColumnAsString(iPrimaryGeometryFieldName);
+        char* pszGCoordSystemGUID;
+        if (poGeometryPropertiesTable)
+            pszGCoordSystemGUID = poGeometryPropertiesTable->GetColumnAsString(iGCoordSystemGUID);
+        else
+            pszGCoordSystemGUID = NULL;
+        if (pszFeatureName && pszGeometryFieldName)
+        {
+            OGRMDBTable* poTable = poDB->GetTable(pszFeatureName);
+            if (poTable)
+            {
+                OGRMDBLayer* poLayer = new OGRMDBLayer( this, poTable );
+
+                if( poLayer->Initialize( pszFeatureName,
+                                         pszGeometryFieldName,
+                                         GetGeomediaSRS(pszGCoordSystemTable, pszGCoordSystemGUID) )
+                    != CE_None )
+                {
+                    delete poLayer;
+                }
+                else
+                {
+                    papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
+                    papoLayers[nLayers++] = poLayer;
+                }
+            }
+        }
+        CPLFree(pszFeatureName);
+        CPLFree(pszGeometryFieldName);
+        CPLFree(pszGCoordSystemGUID);
+    }
+
+    delete poGeometryPropertiesTable;
+    delete poGFeaturesTable;
+    CPLFree(pszGCoordSystemTable);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRMDBDataSource::Open( const char * pszNewName, int bUpdate,
+                              int bTestOpen )
+
+{
+    CPLAssert( nLayers == 0 );
+
+    pszName = CPLStrdup( pszNewName );
+
+    if (!env.Init())
+        return FALSE;
+
+    poDB = OGRMDBDatabase::Open(&env, pszNewName);
+    if (!poDB)
+        return FALSE;
+
+    poDB->FetchTableNames();
+
+    /* Is it a ESRI Personal Geodatabase ? */
+    OGRMDBTable* poGDB_GeomColumns = poDB->GetTable("GDB_GeomColumns");
+    if (poGDB_GeomColumns && !CSLTestBoolean(CPLGetConfigOption("MDB_RAW", "OFF")))
+    {
+        int nRet = OpenGDB(poGDB_GeomColumns);
+        delete poGDB_GeomColumns;
+        return nRet;
+    }
+    delete poGDB_GeomColumns;
+
+    /* Is it a Geomedia warehouse ? */
+    OGRMDBTable* poGAliasTable = poDB->GetTable("GAliasTable");
+    if (poGAliasTable && !CSLTestBoolean(CPLGetConfigOption("MDB_RAW", "OFF")))
+    {
+        int nRet = OpenGeomediaWarehouse(poGAliasTable);
+        delete poGAliasTable;
+        return nRet;
+    }
+    delete poGAliasTable;
+
+    /* Well, no, just a regular MDB */
+    int nTables = (int) poDB->apoTableNames.size();
+    for(int i=0;i<nTables;i++)
+    {
+        OGRMDBTable* poTable = poDB->GetTable(poDB->apoTableNames[i]);
+        if (poTable == NULL)
+            continue;
+
+        OGRMDBLayer* poLayer = new OGRMDBLayer( this, poTable );
+        if( poLayer->BuildFeatureDefn() != CE_None )
+        {
+            delete poLayer;
+            continue;
+        }
+
+        papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
+        papoLayers[nLayers++] = poLayer;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRMDBDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRMDBDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRMDBDataSource::GetLayerByName( const char* pszName )
+
+{
+    if (pszName == NULL)
+        return NULL;
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszName);
+    if (poLayer)
+        return poLayer;
+
+    for( int i = 0; i < nLayersWithInvisible; i++ )
+    {
+        poLayer = papoLayersInvisible[i];
+
+        if( strcmp( pszName, poLayer->GetName() ) == 0 )
+            return poLayer;
+    }
+
+    OGRMDBTable* poTable = poDB->GetTable(pszName);
+    if (poTable == NULL)
+        return NULL;
+
+    OGRMDBLayer* poMDBLayer = new OGRMDBLayer( this, poTable );
+    if( poMDBLayer->BuildFeatureDefn() != CE_None )
+    {
+        delete poMDBLayer;
+        return NULL;
+    }
+
+    papoLayersInvisible = (OGRMDBLayer**)CPLRealloc(papoLayersInvisible,
+                            (nLayersWithInvisible+1) * sizeof(OGRMDBLayer*));
+    papoLayersInvisible[nLayersWithInvisible++] = poMDBLayer;
+
+    return poMDBLayer;
+}
+
+/************************************************************************/
+/*                          GetGeomediaSRS()                            */
+/************************************************************************/
+
+OGRSpatialReference* OGRMDBDataSource::GetGeomediaSRS(const char* pszGCoordSystemTable,
+                                                      const char* pszGCoordSystemGUID)
+{
+    if (pszGCoordSystemTable == NULL || pszGCoordSystemGUID == NULL)
+        return NULL;
+
+    OGRLayer* poGCoordSystemTable = GetLayerByName(pszGCoordSystemTable);
+    if (poGCoordSystemTable == NULL)
+        return NULL;
+
+    poGCoordSystemTable->ResetReading();
+    
+    OGRFeature* poFeature;
+    while((poFeature = poGCoordSystemTable->GetNextFeature()) != NULL)
+    {
+        const char* pszCSGUID = poFeature->GetFieldAsString("CSGUID");
+        if (pszCSGUID && strcmp(pszCSGUID, pszGCoordSystemGUID) == 0)
+        {
+            OGRSpatialReference* poSRS = OGRGetGeomediaSRS(poFeature);
+            delete poFeature;
+            return poSRS;
+        }
+
+        delete poFeature;
+    }
+
+    return NULL;
+}
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
new file mode 100644
index 0000000..9fdf148
--- /dev/null
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
@@ -0,0 +1,107 @@
+/******************************************************************************
+ * $Id: ogrmdbdriver.cpp 21560 2011-01-23 12:11:33Z 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>
+ *
+ * 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_mdb.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrmdbdriver.cpp 21560 2011-01-23 12:11:33Z 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
+
+extern "C" void RegisterOGRMDB();
+
+/************************************************************************/
+/*                            ~OGRODBCDriver()                            */
+/************************************************************************/
+
+OGRMDBDriver::~OGRMDBDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRMDBDriver::GetName()
+
+{
+    return "MDB";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRMDBDriver::Open( const char * pszFilename,
+                                    int bUpdate )
+
+{
+    OGRMDBDataSource     *poDS;
+
+    if( !EQUAL(CPLGetExtension(pszFilename),"mdb") )
+        return NULL;
+
+    VSIStatBuf sStat;
+    if (VSIStat(pszFilename, &sStat) != 0)
+        return NULL;
+
+    // Open data source
+    poDS = new OGRMDBDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
+    {
+        delete poDS;
+        return NULL;
+    }
+    else
+        return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRMDBDriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+
+/************************************************************************/
+/*                           RegisterOGRMDB()                           */
+/************************************************************************/
+
+void RegisterOGRMDB()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRMDBDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
new file mode 100644
index 0000000..a72b6d4
--- /dev/null
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
@@ -0,0 +1,752 @@
+/******************************************************************************
+ * $Id: ogrmdbjackcess.cpp 22156 2011-04-13 20:08:07Z 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>
+ *
+ * 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_mdb.h"
+
+CPL_CVSID("$Id: ogrmdbjackcess.cpp 22156 2011-04-13 20:08:07Z rouault $");
+
+static JavaVM *jvm_static = NULL;
+static JNIEnv *env_static = NULL;
+
+/************************************************************************/
+/*                         OGRMDBJavaEnv()                              */
+/************************************************************************/
+
+OGRMDBJavaEnv::OGRMDBJavaEnv()
+{
+    jvm = NULL;
+    env = NULL;
+    bCalledFromJava = FALSE;
+
+    byteArray_class = NULL;
+
+    file_class = NULL;
+    file_constructor = NULL;
+    database_class = NULL;
+    database_open = NULL;
+    database_close = NULL;
+    database_getTableNames = NULL;
+    database_getTable = NULL;
+
+    table_class = NULL;
+    table_getColumns = NULL;
+    table_iterator = NULL;
+    table_getRowCount = NULL;
+
+    column_class = NULL;
+    column_getName = NULL;
+    column_getType = NULL;
+    column_getLength = NULL;
+    column_isVariableLength = NULL;
+
+    datatype_class = NULL;
+    datatype_getValue = NULL;
+
+    list_class = NULL;
+    list_iterator = NULL;
+
+    set_class = NULL;
+    set_iterator = NULL;
+
+    map_class = NULL;
+    map_get = NULL;
+
+    iterator_class = NULL;
+    iterator_hasNext = NULL;
+    iterator_next = NULL;
+
+    object_class = NULL;
+    object_toString = NULL;
+    object_getClass = NULL;
+
+    boolean_class = NULL;
+    boolean_booleanValue = NULL;
+
+    byte_class = NULL;
+    byte_byteValue = NULL;
+
+    short_class = NULL;
+    short_shortValue = NULL;
+
+    integer_class = NULL;
+    integer_intValue = NULL;
+
+    float_class = NULL;
+    float_floatValue = NULL;
+
+    double_class = NULL;
+    double_doubleValue = NULL;
+}
+
+/************************************************************************/
+/*                        ~OGRMDBJavaEnv()                              */
+/************************************************************************/
+
+OGRMDBJavaEnv::~OGRMDBJavaEnv()
+{
+    if (jvm)
+    {
+        env->DeleteLocalRef(byteArray_class);
+
+        env->DeleteLocalRef(file_class);
+        env->DeleteLocalRef(database_class);
+
+        env->DeleteLocalRef(table_class);
+
+        env->DeleteLocalRef(column_class);
+
+        env->DeleteLocalRef(datatype_class);
+
+        env->DeleteLocalRef(list_class);
+
+        env->DeleteLocalRef(set_class);
+
+        env->DeleteLocalRef(map_class);
+
+        env->DeleteLocalRef(iterator_class);
+
+        env->DeleteLocalRef(object_class);
+
+        env->DeleteLocalRef(boolean_class);
+        env->DeleteLocalRef(byte_class);
+        env->DeleteLocalRef(short_class);
+        env->DeleteLocalRef(integer_class);
+        env->DeleteLocalRef(float_class);
+        env->DeleteLocalRef(double_class);
+
+        /*if (!bCalledFromJava)
+        {
+            CPLDebug("MDB", "Destroying JVM");
+            int ret = jvm->DestroyJavaVM();
+            CPLDebug("MDB", "ret=%d", ret);
+        }*/
+    }
+}
+
+#define CHECK(x, y) do {x = y; if (!x) { CPLError(CE_Failure, CPLE_AppDefined, #y " failed"); return FALSE;} } while(0)
+
+/************************************************************************/
+/*                              Init()                                  */
+/************************************************************************/
+
+int OGRMDBJavaEnv::Init()
+{
+    if (jvm_static == NULL)
+    {
+        JavaVM* vmBuf[1];
+        jsize nVMs;
+
+        /* Are we already called from Java ? */
+        if (JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs) == JNI_OK && nVMs == 1)
+        {
+            jvm = vmBuf[0];
+            if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK)
+            {
+                bCalledFromJava = TRUE;
+            }
+            else
+            {
+                jvm = NULL;
+                env = NULL;
+            }
+        }
+        else
+        {
+            JavaVMInitArgs args;
+            JavaVMOption options[1];
+            args.version = JNI_VERSION_1_2;
+            const char* pszClassPath = CPLGetConfigOption("CLASSPATH", NULL);
+            CPLString osClassPathOption;
+            if (pszClassPath)
+            {
+                args.nOptions = 1;
+                osClassPathOption.Printf("-Djava.class.path=%s", pszClassPath);
+                options[0].optionString = (char*) osClassPathOption.c_str();
+                args.options = options;
+            }
+            else
+                args.nOptions = 0;
+            args.ignoreUnrecognized = JNI_FALSE;
+
+            int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
+            if (ret != 0 || jvm == NULL || env == NULL)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "JNI_CreateJavaVM failed (%d)", ret);
+                return FALSE;
+            }
+
+            jvm_static = jvm;
+            env_static = env;
+        }
+    }
+    else
+    {
+        jvm = jvm_static;
+        env = env_static;
+    }
+
+    CHECK(byteArray_class, env->FindClass("[B"));
+    CHECK(file_class, env->FindClass("java/io/File"));
+    CHECK(file_constructor, env->GetMethodID(file_class, "<init>", "(Ljava/lang/String;)V"));
+    CHECK(database_class, env->FindClass("com/healthmarketscience/jackcess/Database"));
+
+    CHECK(database_open, env->GetStaticMethodID(database_class, "open", "(Ljava/io/File;Z)Lcom/healthmarketscience/jackcess/Database;"));
+    CHECK(database_close, env->GetMethodID(database_class, "close", "()V"));
+    CHECK(database_getTableNames, env->GetMethodID(database_class, "getTableNames", "()Ljava/util/Set;"));
+    CHECK(database_getTable, env->GetMethodID(database_class, "getTable", "(Ljava/lang/String;)Lcom/healthmarketscience/jackcess/Table;"));
+
+    CHECK(table_class, env->FindClass("com/healthmarketscience/jackcess/Table"));
+    CHECK(table_getColumns, env->GetMethodID(table_class, "getColumns", "()Ljava/util/List;"));
+    CHECK(table_iterator, env->GetMethodID(table_class, "iterator", "()Ljava/util/Iterator;"));
+    CHECK(table_getRowCount, env->GetMethodID(table_class, "getRowCount", "()I"));
+
+    CHECK(column_class, env->FindClass("com/healthmarketscience/jackcess/Column"));
+    CHECK(column_getName, env->GetMethodID(column_class, "getName", "()Ljava/lang/String;"));
+    CHECK(column_getType, env->GetMethodID(column_class, "getType", "()Lcom/healthmarketscience/jackcess/DataType;"));
+    CHECK(column_getLength, env->GetMethodID(column_class, "getLength", "()S"));
+    CHECK(column_isVariableLength, env->GetMethodID(column_class, "isVariableLength", "()Z"));
+
+    CHECK(datatype_class, env->FindClass("com/healthmarketscience/jackcess/DataType"));
+    CHECK(datatype_getValue, env->GetMethodID(datatype_class, "getValue", "()B"));
+
+    CHECK(list_class, env->FindClass("java/util/List"));
+    CHECK(list_iterator, env->GetMethodID(list_class, "iterator", "()Ljava/util/Iterator;"));
+
+    CHECK(set_class, env->FindClass("java/util/Set"));
+    CHECK(set_iterator, env->GetMethodID(set_class, "iterator", "()Ljava/util/Iterator;"));
+
+    CHECK(map_class, env->FindClass("java/util/Map"));
+    CHECK(map_get, env->GetMethodID(map_class, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"));
+
+    CHECK(iterator_class,  env->FindClass("java/util/Iterator"));
+    CHECK(iterator_hasNext, env->GetMethodID(iterator_class, "hasNext", "()Z"));
+    CHECK(iterator_next, env->GetMethodID(iterator_class, "next", "()Ljava/lang/Object;"));
+
+    CHECK(object_class,  env->FindClass("java/lang/Object"));
+    CHECK(object_toString, env->GetMethodID(object_class, "toString", "()Ljava/lang/String;"));
+    CHECK(object_getClass, env->GetMethodID(object_class, "getClass", "()Ljava/lang/Class;"));
+
+    CHECK(boolean_class,  env->FindClass("java/lang/Boolean"));
+    CHECK(boolean_booleanValue, env->GetMethodID(boolean_class, "booleanValue", "()Z"));
+
+    CHECK(byte_class,  env->FindClass("java/lang/Byte"));
+    CHECK(byte_byteValue, env->GetMethodID(byte_class, "byteValue", "()B"));
+
+    CHECK(short_class,  env->FindClass("java/lang/Short"));
+    CHECK(short_shortValue, env->GetMethodID(short_class, "shortValue", "()S"));
+
+    CHECK(integer_class,  env->FindClass("java/lang/Integer"));
+    CHECK(integer_intValue, env->GetMethodID(integer_class, "intValue", "()I"));
+
+    CHECK(float_class,  env->FindClass("java/lang/Float"));
+    CHECK(float_floatValue, env->GetMethodID(float_class, "floatValue", "()F"));
+
+    CHECK(double_class,  env->FindClass("java/lang/Double"));
+    CHECK(double_doubleValue, env->GetMethodID(integer_class, "doubleValue", "()D"));
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                       ExceptionOccured()                             */
+/************************************************************************/
+
+int OGRMDBJavaEnv::ExceptionOccured()
+{
+    jthrowable exc = env->ExceptionOccurred();
+    if (exc)
+    {
+         env->ExceptionDescribe();
+         env->ExceptionClear();
+         return TRUE;
+    }
+    return FALSE;
+}
+
+
+/************************************************************************/
+/*                           OGRMDBDatabase()                           */
+/************************************************************************/
+
+OGRMDBDatabase::OGRMDBDatabase()
+{
+    env = NULL;
+    database = NULL;
+}
+
+/************************************************************************/
+/*                          ~OGRMDBDatabase()                           */
+/************************************************************************/
+
+OGRMDBDatabase::~OGRMDBDatabase()
+{
+    if (database)
+    {
+        CPLDebug("MDB", "Closing database");
+        env->env->CallVoidMethod(database, env->database_close);
+
+        env->env->DeleteGlobalRef(database);
+    }
+}
+
+/************************************************************************/
+/*                               Open()                                 */
+/************************************************************************/
+
+OGRMDBDatabase* OGRMDBDatabase::Open(OGRMDBJavaEnv* env, const char* pszName)
+{
+    jstring jstr = env->env->NewStringUTF(pszName);
+    jobject file = env->env->NewObject(env->file_class, env->file_constructor, jstr);
+    if (env->ExceptionOccured()) return NULL;
+    env->env->ReleaseStringUTFChars(jstr, NULL);
+
+    jobject database = env->env->CallStaticObjectMethod(env->database_class, env->database_open, file, JNI_TRUE);
+
+    env->env->DeleteLocalRef(file);
+
+    if (env->ExceptionOccured()) return NULL;
+    if (database == NULL)
+        return NULL;
+
+    OGRMDBDatabase* poDB = new OGRMDBDatabase();
+    poDB->env = env;
+    poDB->database = env->env->NewGlobalRef(database);
+    env->env->DeleteLocalRef(database);
+    return poDB;
+}
+
+/************************************************************************/
+/*                        FetchTableNames()                             */
+/************************************************************************/
+
+int OGRMDBDatabase::FetchTableNames()
+{
+    if (env->bCalledFromJava)
+        env->Init();
+
+    jobject table_set = env->env->CallObjectMethod(database, env->database_getTableNames);
+    if (env->ExceptionOccured()) return FALSE;
+    jobject iterator = env->env->CallObjectMethod(table_set, env->set_iterator);
+    if (env->ExceptionOccured()) return FALSE;
+
+    while( env->env->CallBooleanMethod(iterator, env->iterator_hasNext) )
+    {
+        if (env->ExceptionOccured()) return FALSE;
+        jstring table_name_jstring = (jstring) env->env->CallObjectMethod(iterator, env->iterator_next);
+        if (env->ExceptionOccured()) return FALSE;
+        jboolean is_copy;
+        const char* table_name_str = env->env->GetStringUTFChars(table_name_jstring, &is_copy);
+
+        apoTableNames.push_back(table_name_str);
+        //CPLDebug("MDB", "Table %s", table_name_str);
+
+        env->env->ReleaseStringUTFChars(table_name_jstring, table_name_str);
+        env->env->DeleteLocalRef(table_name_jstring);
+    }
+    env->env->DeleteLocalRef(iterator);
+    env->env->DeleteLocalRef(table_set);
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            GetTable()                                */
+/************************************************************************/
+
+OGRMDBTable* OGRMDBDatabase::GetTable(const char* pszTableName)
+{
+    if (env->bCalledFromJava)
+        env->Init();
+
+    jstring table_name_jstring = env->env->NewStringUTF(pszTableName);
+    jobject table = env->env->CallObjectMethod(database, env->database_getTable, table_name_jstring);
+    if (env->ExceptionOccured()) return NULL;
+    env->env->DeleteLocalRef(table_name_jstring);
+
+    if (!table)
+        return NULL;
+
+    jobject global_table = env->env->NewGlobalRef(table);
+    env->env->DeleteLocalRef(table);
+    table = global_table;
+
+    OGRMDBTable* poTable = new OGRMDBTable(env, this, table, pszTableName);
+    if (!poTable->FetchColumns())
+    {
+        delete poTable;
+        return NULL;
+    }
+    return poTable;
+}
+
+/************************************************************************/
+/*                           OGRMDBTable()                              */
+/************************************************************************/
+
+OGRMDBTable::OGRMDBTable(OGRMDBJavaEnv* env, OGRMDBDatabase* poDB, jobject table, const char* pszTableName )
+{
+    this->env = env;
+    this->poDB = poDB;
+    this->table = table;
+    osTableName = pszTableName;
+    table_iterator_obj = NULL;
+    row = NULL;
+}
+
+/************************************************************************/
+/*                          ~OGRMDBTable()                              */
+/************************************************************************/
+
+OGRMDBTable::~OGRMDBTable()
+{
+    if (env)
+    {
+        //CPLDebug("MDB", "Freeing table %s", osTableName.c_str());
+        if (env->bCalledFromJava)
+            env->Init();
+
+        int i;
+        for(i=0;i<(int)apoColumnNameObjects.size();i++)
+            env->env->DeleteGlobalRef(apoColumnNameObjects[i]);
+
+        env->env->DeleteGlobalRef(table_iterator_obj);
+        env->env->DeleteGlobalRef(row);
+        env->env->DeleteGlobalRef(table);
+    }
+}
+
+/************************************************************************/
+/*                          FetchColumns()                              */
+/************************************************************************/
+
+int OGRMDBTable::FetchColumns()
+{
+    if (env->bCalledFromJava)
+        env->Init();
+
+    jobject column_lists = env->env->CallObjectMethod(table, env->table_getColumns);
+    if (env->ExceptionOccured()) return FALSE;
+
+    jobject iterator_cols = env->env->CallObjectMethod(column_lists, env->list_iterator);
+    if (env->ExceptionOccured()) return FALSE;
+
+    while( env->env->CallBooleanMethod(iterator_cols, env->iterator_hasNext) )
+    {
+        if (env->ExceptionOccured()) return FALSE;
+
+        jobject column = env->env->CallObjectMethod(iterator_cols, env->iterator_next);
+        if (env->ExceptionOccured()) return FALSE;
+
+        jstring column_name_jstring = (jstring) env->env->CallObjectMethod(column, env->column_getName);
+        if (env->ExceptionOccured()) return FALSE;
+        jboolean is_copy;
+        const char* column_name_str = env->env->GetStringUTFChars(column_name_jstring, &is_copy);
+        apoColumnNames.push_back(column_name_str);
+        env->env->ReleaseStringUTFChars(column_name_jstring, column_name_str);
+
+        apoColumnNameObjects.push_back((jstring) env->env->NewGlobalRef(column_name_jstring));
+        env->env->DeleteLocalRef(column_name_jstring);
+
+        jobject column_type = env->env->CallObjectMethod(column, env->column_getType);
+        if (env->ExceptionOccured()) return FALSE;
+        int type = env->env->CallByteMethod(column_type, env->datatype_getValue);
+        if (env->ExceptionOccured()) return FALSE;
+        apoColumnTypes.push_back(type);
+
+        int isvariablelength = env->env->CallBooleanMethod(column, env->column_isVariableLength);
+        if (env->ExceptionOccured()) return FALSE;
+        if (!isvariablelength)
+        {
+            int length = env->env->CallShortMethod(column, env->column_getLength);
+            if (env->ExceptionOccured()) return FALSE;
+            apoColumnLengths.push_back(length);
+        }
+        else
+            apoColumnLengths.push_back(0);
+
+        //CPLDebug("MDB", "Column %s, type = %d", apoColumnNames[apoColumnNames.size()-1].c_str(), type);
+
+        env->env->DeleteLocalRef(column_type);
+
+        env->env->DeleteLocalRef(column);
+    }
+    env->env->DeleteLocalRef(iterator_cols);
+    env->env->DeleteLocalRef(column_lists);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          ResetReading()                              */
+/************************************************************************/
+
+void OGRMDBTable::ResetReading()
+{
+    if (env->bCalledFromJava)
+        env->Init();
+
+    env->env->DeleteGlobalRef(table_iterator_obj);
+    table_iterator_obj = NULL;
+    env->env->DeleteGlobalRef(row);
+    row = NULL;
+}
+
+/************************************************************************/
+/*                           GetNextRow()                               */
+/************************************************************************/
+
+int OGRMDBTable::GetNextRow()
+{
+    if (env->bCalledFromJava)
+        env->Init();
+
+    if (table_iterator_obj == NULL)
+    {
+        table_iterator_obj = env->env->CallObjectMethod(table, env->table_iterator);
+        if (env->ExceptionOccured()) return FALSE;
+        if (table_iterator_obj)
+        {
+            jobject global_table_iterator_obj = env->env->NewGlobalRef(table_iterator_obj);
+            env->env->DeleteLocalRef(table_iterator_obj);
+            table_iterator_obj = global_table_iterator_obj;
+        }
+    }
+    if (table_iterator_obj == NULL)
+        return FALSE;
+
+    if (!env->env->CallBooleanMethod(table_iterator_obj, env->iterator_hasNext))
+        return FALSE;
+    if (env->ExceptionOccured()) return FALSE;
+
+    if (row)
+    {
+        env->env->DeleteGlobalRef(row);
+        row = NULL;
+    }
+
+    row = env->env->CallObjectMethod(table_iterator_obj, env->iterator_next);
+    if (env->ExceptionOccured()) return FALSE;
+    if (row == NULL)
+        return FALSE;
+
+    jobject global_row = env->env->NewGlobalRef(row);
+    env->env->DeleteLocalRef(row);
+    row = global_row;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          GetColumnVal()                              */
+/************************************************************************/
+
+jobject OGRMDBTable::GetColumnVal(int iCol)
+{
+    if (row == NULL)
+        return NULL;
+
+    jobject val = env->env->CallObjectMethod(row, env->map_get, apoColumnNameObjects[iCol]);
+    if (env->ExceptionOccured()) return NULL;
+    return val;
+}
+
+/************************************************************************/
+/*                        GetColumnAsString()                           */
+/************************************************************************/
+
+char* OGRMDBTable::GetColumnAsString(int iCol)
+{
+    jobject val = GetColumnVal(iCol);
+    if (!val) return NULL;
+
+    jstring val_jstring = (jstring) env->env->CallObjectMethod(val, env->object_toString);
+    if (env->ExceptionOccured()) return NULL;
+    jboolean is_copy;
+    const char* val_str = env->env->GetStringUTFChars(val_jstring, &is_copy);
+    char* dup_str = (val_str) ? CPLStrdup(val_str) : NULL;
+    env->env->ReleaseStringUTFChars(val_jstring, val_str);
+    env->env->DeleteLocalRef(val_jstring);
+
+    env->env->DeleteLocalRef(val);
+
+    return dup_str;
+}
+
+/************************************************************************/
+/*                          GetColumnAsInt()                            */
+/************************************************************************/
+
+int OGRMDBTable::GetColumnAsInt(int iCol)
+{
+    jobject val = GetColumnVal(iCol);
+    if (!val) return 0;
+
+    int int_val = 0;
+    if (apoColumnTypes[iCol] == MDB_Boolean)
+        int_val = env->env->CallBooleanMethod(val, env->boolean_booleanValue);
+    else if (apoColumnTypes[iCol] == MDB_Byte)
+        int_val = env->env->CallByteMethod(val, env->byte_byteValue);
+    else if (apoColumnTypes[iCol] == MDB_Short)
+        int_val = env->env->CallShortMethod(val, env->short_shortValue);
+    else if (apoColumnTypes[iCol] == MDB_Int)
+        int_val = env->env->CallIntMethod(val, env->integer_intValue);
+    if (env->ExceptionOccured()) return 0;
+
+    env->env->DeleteLocalRef(val);
+
+    return int_val;
+}
+
+/************************************************************************/
+/*                        GetColumnAsDouble()                           */
+/************************************************************************/
+
+double OGRMDBTable::GetColumnAsDouble(int iCol)
+{
+    jobject val = GetColumnVal(iCol);
+    if (!val) return 0;
+
+    double double_val = 0;
+    if (apoColumnTypes[iCol] == MDB_Double)
+        double_val = env->env->CallDoubleMethod(val, env->double_doubleValue);
+    else if (apoColumnTypes[iCol] == MDB_Float)
+        double_val = env->env->CallFloatMethod(val, env->float_floatValue);
+    if (env->ExceptionOccured()) return 0;
+
+    env->env->DeleteLocalRef(val);
+
+    return double_val;
+}
+
+/************************************************************************/
+/*                        GetColumnAsBinary()                           */
+/************************************************************************/
+
+GByte* OGRMDBTable::GetColumnAsBinary(int iCol, int* pnBytes)
+{
+    *pnBytes = 0;
+
+    jobject val = GetColumnVal(iCol);
+    if (!val) return NULL;
+
+    if (!env->env->IsInstanceOf(val, env->byteArray_class))
+        return NULL;
+
+    jbyteArray byteArray = (jbyteArray) val;
+    *pnBytes = env->env->GetArrayLength(byteArray);
+    if (env->ExceptionOccured()) return NULL;
+    jboolean is_copy;
+    jbyte* elts = env->env->GetByteArrayElements(byteArray, &is_copy);
+    if (env->ExceptionOccured()) return NULL;
+
+    GByte* pData = (GByte*)CPLMalloc(*pnBytes);
+    memcpy(pData, elts, *pnBytes);
+
+    env->env->ReleaseByteArrayElements(byteArray, elts, JNI_ABORT);
+
+    env->env->DeleteLocalRef(val);
+
+    return pData;
+}
+
+/************************************************************************/
+/*                              DumpTable()                             */
+/************************************************************************/
+
+void OGRMDBTable::DumpTable()
+{
+    ResetReading();
+    int iRow = 0;
+    int nCols = apoColumnNames.size();
+    while(GetNextRow())
+    {
+        printf("Row = %d\n", iRow ++);
+        for(int i=0;i<nCols;i++)
+        {
+            printf("%s = ", apoColumnNames[i].c_str());
+            if (apoColumnTypes[i] == MDB_Float ||
+                apoColumnTypes[i] == MDB_Double)
+            {
+                printf("%.15f\n", GetColumnAsDouble(i));
+            }
+            else if (apoColumnTypes[i] == MDB_Boolean ||
+                     apoColumnTypes[i] == MDB_Byte ||
+                     apoColumnTypes[i] == MDB_Short ||
+                     apoColumnTypes[i] == MDB_Int)
+            {
+                printf("%d\n", GetColumnAsInt(i));
+            }
+            else if (apoColumnTypes[i] == MDB_Binary ||
+                     apoColumnTypes[i] == MDB_OLE)
+            {
+                int nBytes;
+                GByte* pData = GetColumnAsBinary(i, &nBytes);
+                printf("(%d bytes)\n", nBytes);
+                CPLFree(pData);
+            }
+            else
+            {
+                char* val = GetColumnAsString(i);
+                printf("'%s'\n", val);
+                CPLFree(val);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                            GetColumnIndex()                          */
+/************************************************************************/
+
+int OGRMDBTable::GetColumnIndex(const char* pszColName, int bEmitErrorIfNotFound)
+{
+    int nCols = apoColumnNames.size();
+    CPLString osColName(pszColName);
+    for(int i=0;i<nCols;i++)
+    {
+        if (apoColumnNames[i] == osColName)
+            return i;
+    }
+    if (bEmitErrorIfNotFound)
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find column %s", pszColName);
+    return -1;
+}
+
+/************************************************************************/
+/*                             GetRowCount()                            */
+/************************************************************************/
+
+int OGRMDBTable::GetRowCount()
+{
+    if (env->bCalledFromJava)
+        env->Init();
+    int nRowCount = env->env->CallIntMethod(table, env->table_getRowCount);
+    if (env->ExceptionOccured()) return 0;
+    return nRowCount;
+}
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
new file mode 100644
index 0000000..5d42a16
--- /dev/null
+++ b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
@@ -0,0 +1,632 @@
+/******************************************************************************
+ * $Id: ogrmdblayer.cpp 22156 2011-04-13 20:08:07Z 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>
+ *
+ * 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_mdb.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogrpgeogeometry.h"
+#include "ogrgeomediageometry.h"
+
+CPL_CVSID("$Id: ogrmdblayer.cpp 22156 2011-04-13 20:08:07Z rouault $");
+
+/************************************************************************/
+/*                            OGRMDBLayer()                            */
+/************************************************************************/
+
+OGRMDBLayer::OGRMDBLayer(OGRMDBDataSource* poDS, OGRMDBTable* poMDBTable)
+
+{
+    this->poDS = poDS;
+    this->poMDBTable = poMDBTable;
+
+    eGeometryType = MDB_GEOM_NONE;
+
+    iGeomColumn = -1;
+    pszGeomColumn = NULL;
+    pszFIDColumn = NULL;
+
+    panFieldOrdinals = NULL;
+
+    poFeatureDefn = NULL;
+
+    iNextShapeId = 0;
+
+    poSRS = NULL;
+    nSRSId = -2; // we haven't even queried the database for it yet.
+
+    bHasExtent = FALSE;
+}
+
+/************************************************************************/
+/*                            ~OGRMDBLayer()                             */
+/************************************************************************/
+
+OGRMDBLayer::~OGRMDBLayer()
+
+{
+    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    {
+        CPLDebug( "MDB", "%d features read on layer '%s'.",
+                  (int) m_nFeaturesRead, 
+                  poFeatureDefn->GetName() );
+    }
+
+    if( poFeatureDefn != NULL )
+    {
+        poFeatureDefn->Release();
+        poFeatureDefn = NULL;
+    }
+
+    CPLFree( pszGeomColumn );
+    CPLFree( pszFIDColumn );
+
+    CPLFree( panFieldOrdinals );
+
+    if( poSRS != NULL )
+    {
+        poSRS->Release();
+        poSRS = NULL;
+    }
+
+    delete poMDBTable;
+}
+
+/************************************************************************/
+/*                          BuildFeatureDefn()                          */
+/*                                                                      */
+/*      Build feature definition from a set of column definitions       */
+/*      set on a statement.  Sift out geometry and FID fields.          */
+/************************************************************************/
+
+CPLErr OGRMDBLayer::BuildFeatureDefn()
+
+{
+    poFeatureDefn = new OGRFeatureDefn( poMDBTable->GetName() );
+
+    poFeatureDefn->Reference();
+
+
+    int nRawColumns = poMDBTable->GetColumnCount();
+    panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
+
+    for( int iCol = 0; iCol < nRawColumns; iCol++ )
+    {
+        const char* pszColName = poMDBTable->GetColumnName(iCol);
+        OGRFieldDefn    oField(pszColName, OFTString );
+
+        if( pszGeomColumn != NULL
+            && EQUAL(pszColName,pszGeomColumn) )
+            continue;
+
+        if( eGeometryType == MDB_GEOM_PGEO
+            && pszFIDColumn == NULL
+            && EQUAL(pszColName,"OBJECTID") )
+        {
+            pszFIDColumn = CPLStrdup(pszColName);
+        }
+
+        if( eGeometryType == MDB_GEOM_PGEO
+            && pszGeomColumn == NULL 
+            && EQUAL(pszColName,"Shape") )
+        {
+            pszGeomColumn = CPLStrdup(pszColName);
+            continue;
+        }
+        
+        switch( poMDBTable->GetColumnType(iCol) )
+        {
+          case MDB_Boolean:
+            oField.SetType( OFTInteger );
+            oField.SetWidth(1);
+            break;
+
+          case MDB_Byte:
+          case MDB_Short:
+          case MDB_Int:
+            oField.SetType( OFTInteger );
+            break;
+
+          case MDB_Binary:
+          case MDB_OLE:
+            oField.SetType( OFTBinary );
+            break;
+
+          case MDB_Float:
+          case MDB_Double:
+            oField.SetType( OFTReal );
+            break;
+
+          case MDB_Text:
+            oField.SetWidth(poMDBTable->GetColumnLength(iCol));
+            break;
+
+          default:
+            /* leave it as OFTString */;
+        }
+
+        poFeatureDefn->AddFieldDefn( &oField );
+        panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
+    }
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRMDBLayer::ResetReading()
+
+{
+    iNextShapeId = 0;
+    poMDBTable->ResetReading();
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRMDBLayer::GetFeatureCount(int bForce)
+{
+    if (m_poFilterGeom != NULL || m_poAttrQuery != NULL)
+        return OGRLayer::GetFeatureCount(bForce);
+    return poMDBTable->GetRowCount();
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRMDBLayer::GetNextFeature()
+
+{
+    for( ; 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;
+    }
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRMDBLayer::GetNextRawFeature()
+
+{
+    OGRErr err = OGRERR_NONE;
+
+    if( !poMDBTable->GetNextRow() )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create a feature from the current result.                       */
+/* -------------------------------------------------------------------- */
+    int         iField;
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    if( pszFIDColumn != NULL && poMDBTable->GetColumnIndex(pszFIDColumn) > -1 )
+        poFeature->SetFID( 
+            poMDBTable->GetColumnAsInt(poMDBTable->GetColumnIndex(pszFIDColumn)) );
+    else
+        poFeature->SetFID( iNextShapeId );
+
+    iNextShapeId++;
+    m_nFeaturesRead++;
+
+/* -------------------------------------------------------------------- */
+/*      Set the fields.                                                 */
+/* -------------------------------------------------------------------- */
+    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        int iSrcField = panFieldOrdinals[iField]-1;
+        char *pszValue = poMDBTable->GetColumnAsString( iSrcField );
+        OGRFieldType eType = poFeature->GetFieldDefnRef(iField)->GetType();
+
+        if( pszValue == NULL )
+            /* no value */;
+        else if( eType == OFTBinary )
+        {
+            int nBytes = 0;
+            GByte* pData = poMDBTable->GetColumnAsBinary( iSrcField, &nBytes);
+            poFeature->SetField( iField, 
+                                 nBytes,
+                                 pData );
+            CPLFree(pData);
+        }
+        else if ( eType == OFTInteger && EQUAL(pszValue, "true"))
+        {
+           poFeature->SetField( iField, 1 );
+        }
+        else
+        {
+           poFeature->SetField( iField, pszValue );
+        }
+
+        CPLFree(pszValue);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to extract a geometry.                                      */
+/* -------------------------------------------------------------------- */
+    if( eGeometryType == MDB_GEOM_PGEO && iGeomColumn >= 0)
+    {
+        int nBytes = 0;
+        GByte* pData = poMDBTable->GetColumnAsBinary( iGeomColumn, &nBytes);
+        OGRGeometry *poGeom = NULL;
+
+        if( pData != NULL )
+        {
+            err = OGRCreateFromShapeBin( pData, &poGeom, nBytes );
+            if( OGRERR_NONE != err )
+            {
+                CPLDebug( "MDB",
+                          "Translation shape binary to OGR geometry failed (FID=%ld)",
+                           (long)poFeature->GetFID() );
+            }
+        }
+
+        CPLFree(pData);
+
+        if( poGeom != NULL && OGRERR_NONE == err )
+        {
+            poGeom->assignSpatialReference( poSRS );
+            poFeature->SetGeometryDirectly( poGeom );
+        }
+    }
+    else if( eGeometryType == MDB_GEOM_GEOMEDIA && iGeomColumn >= 0)
+    {
+        int nBytes = 0;
+        GByte* pData = poMDBTable->GetColumnAsBinary( iGeomColumn, &nBytes);
+        OGRGeometry *poGeom = NULL;
+
+        if( pData != NULL )
+        {
+            err = OGRCreateFromGeomedia( pData, &poGeom, nBytes );
+            if( OGRERR_NONE != err )
+            {
+                CPLDebug( "MDB",
+                          "Translation geomedia binary to OGR geometry failed (FID=%ld)",
+                           (long)poFeature->GetFID() );
+            }
+        }
+
+        CPLFree(pData);
+
+        if( poGeom != NULL && OGRERR_NONE == err )
+        {
+            poGeom->assignSpatialReference( poSRS );
+            poFeature->SetGeometryDirectly( poGeom );
+        }
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRMDBLayer::GetFeature( long nFeatureId )
+
+{
+    /* This should be implemented directly! */
+
+    return OGRLayer::GetFeature( nFeatureId );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRMDBLayer::TestCapability( const char * pszCap )
+
+{
+    /*if( EQUAL(pszCap,OLCRandomRead) )
+        return TRUE;
+
+    else*/
+    if( EQUAL(pszCap,OLCFastFeatureCount) ||
+        EQUAL(pszCap,OLCFastGetExtent) )
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
+
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+
+OGRSpatialReference *OGRMDBLayer::GetSpatialRef()
+
+{
+    return poSRS;
+}
+
+/************************************************************************/
+/*                           LookupSRID()                               */
+/************************************************************************/
+
+void OGRMDBLayer::LookupSRID( int nSRID )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Fetch the corresponding WKT from the SpatialRef table.          */
+/* -------------------------------------------------------------------- */
+    OGRMDBDatabase* poDB = poMDBTable->GetDB();
+    OGRMDBTable* poSRSTable = poDB->GetTable("GDB_SpatialRefs");
+    if (poSRSTable == NULL)
+        return;
+
+    int iSRTEXT = poSRSTable->GetColumnIndex("SRTEXT", TRUE);
+    int iSRID = poSRSTable->GetColumnIndex("SRID", TRUE);
+
+    if (iSRTEXT < 0 || iSRID < 0)
+    {
+        delete poSRSTable;
+        return;
+    }
+
+    char* pszSRText = NULL;
+    while(poSRSTable->GetNextRow())
+    {
+        int nTableSRID = poSRSTable->GetColumnAsInt(iSRID);
+        if (nTableSRID == nSRID)
+        {
+            pszSRText = poSRSTable->GetColumnAsString(iSRTEXT);
+            break;
+        }
+    }
+
+    if (pszSRText == NULL)
+    {
+        delete poSRSTable;
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check that it isn't just a GUID.  We don't know how to          */
+/*      translate those.                                                */
+/* -------------------------------------------------------------------- */
+
+    if( pszSRText[0] == '{' )
+    {
+        CPLDebug( "MDB", "Ignoreing GUID SRTEXT: %s", pszSRText );
+        delete poSRSTable;
+        CPLFree(pszSRText);
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Turn it into an OGRSpatialReference.                            */
+/* -------------------------------------------------------------------- */
+    poSRS = new OGRSpatialReference();
+
+    char* pszSRTextPtr = pszSRText;
+    if( poSRS->importFromWkt( &pszSRTextPtr ) != OGRERR_NONE )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "importFromWKT() failed on SRS '%s'.",
+                  pszSRText);
+        delete poSRS;
+        poSRS = NULL;
+    }
+    else if( poSRS->morphFromESRI() != OGRERR_NONE )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "morphFromESRI() failed on SRS." );
+        delete poSRS;
+        poSRS = NULL;
+    }
+    else
+        nSRSId = nSRID;
+
+    delete poSRSTable;
+    CPLFree(pszSRText);
+}
+
+/************************************************************************/
+/*                            GetFIDColumn()                            */
+/************************************************************************/
+
+const char *OGRMDBLayer::GetFIDColumn()
+
+{
+    if( pszFIDColumn != NULL )
+        return pszFIDColumn;
+    else
+        return "";
+}
+
+/************************************************************************/
+/*                         GetGeometryColumn()                          */
+/************************************************************************/
+
+const char *OGRMDBLayer::GetGeometryColumn()
+
+{
+    if( pszGeomColumn != NULL )
+        return pszGeomColumn;
+    else
+        return "";
+}
+
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+CPLErr OGRMDBLayer::Initialize( const char *pszTableName,
+                                const char *pszGeomCol,
+                                int nShapeType,
+                                double dfExtentLeft,
+                                double dfExtentRight,
+                                double dfExtentBottom,
+                                double dfExtentTop,
+                                int nSRID,
+                                int bHasZ )
+
+
+{
+    CPLFree( pszGeomColumn );
+
+    if( pszGeomCol == NULL )
+        pszGeomColumn = NULL;
+    else
+    {
+        pszGeomColumn = CPLStrdup( pszGeomCol );
+        iGeomColumn = poMDBTable->GetColumnIndex( pszGeomColumn );
+    }
+
+    CPLFree( pszFIDColumn );
+    pszFIDColumn = NULL;
+
+    bHasExtent = TRUE;
+    sExtent.MinX = dfExtentLeft;
+    sExtent.MaxX = dfExtentRight;
+    sExtent.MinY = dfExtentBottom;
+    sExtent.MaxY = dfExtentTop;
+
+    LookupSRID( nSRID );
+
+    eGeometryType = MDB_GEOM_PGEO;
+
+    CPLErr eErr;
+    eErr = BuildFeatureDefn();
+    if( eErr != CE_None )
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      Setup geometry type.                                            */
+/* -------------------------------------------------------------------- */
+    OGRwkbGeometryType  eOGRType;
+
+    switch( nShapeType )
+    {
+        case ESRI_LAYERGEOMTYPE_NULL:
+            eOGRType = wkbNone;
+            break;
+
+        case ESRI_LAYERGEOMTYPE_POINT:
+            eOGRType = wkbPoint;
+            break;
+
+        case ESRI_LAYERGEOMTYPE_MULTIPOINT:
+            eOGRType = wkbMultiPoint;
+            break;
+
+        case ESRI_LAYERGEOMTYPE_POLYLINE:
+            eOGRType = wkbLineString;
+            break;
+
+        case ESRI_LAYERGEOMTYPE_POLYGON:
+        case ESRI_LAYERGEOMTYPE_MULTIPATCH:
+            eOGRType = wkbPolygon;
+            break;
+
+        default:
+            CPLDebug("MDB", "Unexpected value for shape type : %d", nShapeType);
+            eOGRType = wkbUnknown;
+            break;
+    }
+
+    if( eOGRType != wkbUnknown && eOGRType != wkbNone && bHasZ )
+        eOGRType = (OGRwkbGeometryType)(((int) eOGRType) | wkb25DBit);
+
+    poFeatureDefn->SetGeomType(eOGRType);
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+CPLErr OGRMDBLayer::Initialize( const char *pszTableName,
+                                const char *pszGeomCol,
+                                OGRSpatialReference* poSRS )
+
+
+{
+    CPLFree( pszGeomColumn );
+
+    if( pszGeomCol == NULL )
+        pszGeomColumn = NULL;
+    else
+    {
+        pszGeomColumn = CPLStrdup( pszGeomCol );
+        iGeomColumn = poMDBTable->GetColumnIndex( pszGeomColumn );
+    }
+
+    CPLFree( pszFIDColumn );
+    pszFIDColumn = NULL;
+
+    eGeometryType = MDB_GEOM_GEOMEDIA;
+
+    this->poSRS = poSRS;
+
+    CPLErr eErr;
+    eErr = BuildFeatureDefn();
+    if( eErr != CE_None )
+        return eErr;
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr OGRMDBLayer::GetExtent( OGREnvelope *psExtent, int bForce )
+
+{
+    if (bHasExtent)
+    {
+        *psExtent = sExtent;
+        return OGRERR_NONE;
+    }
+    else
+    {
+        return OGRLayer::GetExtent(psExtent, bForce);
+    }
+}
diff --git a/ogr/ogrsf_frmts/mem/ogr_mem.h b/ogr/ogrsf_frmts/mem/ogr_mem.h
index 708b4b5..3a112ab 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 17807 2009-10-13 18:18:09Z rouault $
+ * $Id: ogr_mem.h 22369 2011-05-13 18:00:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the OGR Memory driver.
@@ -71,6 +71,9 @@ class OGRMemLayer : public OGRLayer
 
     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 OGRSpatialReference *GetSpatialRef();
     
diff --git a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
index 366d6df..0f6c82d 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmemlayer.cpp 17807 2009-10-13 18:18:09Z rouault $
+ * $Id: ogrmemlayer.cpp 23064 2011-09-05 20:39:52Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemLayer class.
@@ -29,8 +29,9 @@
 
 #include "ogr_mem.h"
 #include "cpl_conv.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmemlayer.cpp 17807 2009-10-13 18:18:09Z rouault $");
+CPL_CVSID("$Id: ogrmemlayer.cpp 23064 2011-09-05 20:39:52Z rouault $");
 
 /************************************************************************/
 /*                            OGRMemLayer()                             */
@@ -132,7 +133,7 @@ OGRErr OGRMemLayer::SetNextByIndex( long nIndex )
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::SetNextByIndex( nIndex );
         
-    if (iNextReadFID < 0 || iNextReadFID >= nMaxFeatureCount)
+    if (nIndex < 0 || nIndex >= nMaxFeatureCount)
         return OGRERR_FAILURE;
 
     iNextReadFID = nIndex;
@@ -293,7 +294,10 @@ int OGRMemLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCDeleteFeature) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCCreateField) )
+    else if( EQUAL(pszCap,OLCCreateField) ||
+             EQUAL(pszCap,OLCDeleteField) ||
+             EQUAL(pszCap,OLCReorderFields) ||
+             EQUAL(pszCap,OLCAlterFieldDefn) )
         return TRUE;
 
     else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
@@ -352,6 +356,137 @@ OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
 }
 
 /************************************************************************/
+/*                            DeleteField()                             */
+/************************************************************************/
+
+OGRErr OGRMemLayer::DeleteField( int iField )
+{
+    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Update all the internal features.  Hopefully there aren't any   */
+/*      external features referring to our OGRFeatureDefn!              */
+/* -------------------------------------------------------------------- */
+    for( int i = 0; i < nMaxFeatureCount; i++ )
+    {
+        if( papoFeatures[i] == NULL )
+            continue;
+
+        OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
+        if( papoFeatures[i]->IsFieldSet(iField) )
+        {
+            /* Little trick to unallocate the field */
+            OGRField sField;
+            sField.Set.nMarker1 = OGRUnsetMarker;
+            sField.Set.nMarker2 = OGRUnsetMarker;
+            papoFeatures[i]->SetField(iField, &sField);
+        }
+
+        if (iField < poFeatureDefn->GetFieldCount() - 1)
+        {
+            memmove( poFieldRaw, poFieldRaw + 1,
+                     sizeof(OGRField) * (poFeatureDefn->GetFieldCount() - 1 - iField) );
+        }
+    }
+
+    return poFeatureDefn->DeleteFieldDefn( iField );
+}
+
+/************************************************************************/
+/*                           ReorderFields()                            */
+/************************************************************************/
+
+OGRErr OGRMemLayer::ReorderFields( int* panMap )
+{
+    if (poFeatureDefn->GetFieldCount() == 0)
+        return OGRERR_NONE;
+
+    OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      Remap all the internal features.  Hopefully there aren't any    */
+/*      external features referring to our OGRFeatureDefn!              */
+/* -------------------------------------------------------------------- */
+    for( int i = 0; i < nMaxFeatureCount; i++ )
+    {
+        if( papoFeatures[i] != NULL )
+            papoFeatures[i]->RemapFields( NULL, panMap );
+    }
+
+    return poFeatureDefn->ReorderFieldDefns( panMap );
+}
+
+/************************************************************************/
+/*                           AlterFieldDefn()                           */
+/************************************************************************/
+
+OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+{
+    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
+
+    if ((nFlags & ALTER_TYPE_FLAG) &&
+        poFieldDefn->GetType() != poNewFieldDefn->GetType())
+    {
+        if (poNewFieldDefn->GetType() != OFTString)
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Can only convert to OFTString");
+            return OGRERR_FAILURE;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Update all the internal features.  Hopefully there aren't any   */
+/*      external features referring to our OGRFeatureDefn!              */
+/* -------------------------------------------------------------------- */
+        for( int i = 0; i < nMaxFeatureCount; i++ )
+        {
+            if( papoFeatures[i] == NULL )
+                continue;
+
+            OGRField* poFieldRaw = papoFeatures[i]->GetRawFieldRef(iField);
+            if( papoFeatures[i]->IsFieldSet(iField) )
+            {
+                char* pszVal = CPLStrdup(papoFeatures[i]->GetFieldAsString(iField));
+
+                /* Little trick to unallocate the field */
+                OGRField sField;
+                sField.Set.nMarker1 = OGRUnsetMarker;
+                sField.Set.nMarker2 = OGRUnsetMarker;
+                papoFeatures[i]->SetField(iField, &sField);
+
+                poFieldRaw->String = pszVal;
+            }
+        }
+
+        poFieldDefn->SetType(poNewFieldDefn->GetType());
+    }
+
+    if (nFlags & ALTER_NAME_FLAG)
+        poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
+    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    {
+        poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
+        poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                           GetSpatialRef()                            */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
index 142fa33..eb3a934 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_coordsys.cpp,v 1.41 2010-10-07 18:46:26 aboudreault Exp $
+ * $Id: mitab_coordsys.cpp,v 1.42 2011-06-11 00:35:00 fwarmerdam Exp $
  *
  * Name:     mitab_coordsys.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -31,6 +31,9 @@
  **********************************************************************
  *
  * $Log: mitab_coordsys.cpp,v $
+ * Revision 1.42  2011-06-11 00:35:00  fwarmerdam
+ * add support for reading google mercator (#4115)
+ *
  * Revision 1.41  2010-10-07 18:46:26  aboudreault
  * Fixed bad use of atof when locale setting doesn't use . for float (GDAL bug #3775)
  *
@@ -785,6 +788,15 @@ OGRSpatialReference *MITABCoordSys2SpatialRef( const char * pszCoordSys )
                       -adfDatumParm[3], -adfDatumParm[4], -adfDatumParm[5], 
                       adfDatumParm[6] );
 
+    /*-----------------------------------------------------------------
+     * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115)
+     *----------------------------------------------------------------*/
+
+    if( nBaseProjection == 10 && nDatum == 157 )
+    {
+        poSR->SetNode( "PROJCS", "WGS 84 / Pseudo-Mercator" );
+        poSR->SetExtension( "PROJCS", "PROJ4", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
+    }
 /* -------------------------------------------------------------------- */
 /*      Report on translation.                                          */
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
index a1c3072..efd6e41 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_feature.cpp,v 1.99 2010-10-08 19:36:44 aboudreault Exp $
+ * $Id: mitab_feature.cpp,v 1.100 2010-10-12 19:55:32 aboudreault Exp $
  *
  * Name:     mitab_feature.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -30,6 +30,9 @@
  **********************************************************************
  *
  * $Log: mitab_feature.cpp,v $
+ * Revision 1.100  2010-10-12 19:55:32  aboudreault
+ * Fixed style string ID parameter to use the proper delimiter as per OGR Feature Style Specification
+ *
  * Revision 1.99  2010-10-08 19:36:44  aboudreault
  * Fixed memory leak (GDAL bug #3045)
  *
diff --git a/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp b/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
index 69b8e23..7267d98 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_middatafile.cpp,v 1.14 2006-01-27 13:54:06 fwarmerdam Exp $
+ * $Id: mitab_middatafile.cpp,v 1.15 2010-10-12 19:02:40 aboudreault Exp $
  *
  * Name:     mitab_datfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -31,6 +31,9 @@
  **********************************************************************
  *
  * $Log: mitab_middatafile.cpp,v $
+ * Revision 1.15  2010-10-12 19:02:40  aboudreault
+ * Fixed incomplet patch to handle differently indented lines in mif files (gdal #3694)
+ *
  * Revision 1.14  2006-01-27 13:54:06  fwarmerdam
  * fixed memory leak
  *
diff --git a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
index 1dcac69..9c0898c 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_miffile.cpp,v 1.55 2010-10-08 18:50:52 aboudreault Exp $
+ * $Id: mitab_miffile.cpp,v 1.58 2011-09-22 21:57:46 dmorissette Exp $
  *
  * Name:     mitab_miffile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -32,6 +32,15 @@
  **********************************************************************
  *
  * $Log: mitab_miffile.cpp,v $
+ * Revision 1.58  2011-09-22 21:57:46  dmorissette
+ *  Fixed problem with tab delimiter used in MIF files (GDAL #4257)
+ *
+ * Revision 1.57  2010-10-15 12:06:44  aboudreault
+ * Fixed crash when trying to get the same mitab mif feature twice (GDAL #3765)
+ *
+ * Revision 1.56  2010-10-12 19:02:40  aboudreault
+ * Fixed incomplet patch to handle differently indented lines in mif files (gdal #3694)
+ *
  * Revision 1.55  2010-10-08 18:50:52  aboudreault
  * Fixed handle differently indented lines in mif files. (GDAL bug #3694)
  *
@@ -877,7 +886,7 @@ void MIFFile::PreParseFile()
         }
 
         CSLDestroy(papszToken);
-        papszToken = CSLTokenizeString(pszLine);
+        papszToken = CSLTokenizeString2(pszLine, " \t", CSLT_HONOURSTRINGS);
 
         if (EQUALN(pszLine,"POINT",5))
         {
@@ -1331,7 +1340,7 @@ TABFeature *MIFFile::GetFeatureRef(int nFeatureId)
         {
             // Special case, we need to know two lines to decide the type
             char **papszToken;
-            papszToken = CSLTokenizeString(pszLine);
+            papszToken = CSLTokenizeString2(pszLine, " \t", CSLT_HONOURSTRINGS);
             
             if (CSLCount(papszToken) !=3)
             {
diff --git a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
index 93290e3..4c9f643 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_spatialref.cpp,v 1.54 2010-10-07 18:46:26 aboudreault Exp $
+ * $Id: mitab_spatialref.cpp,v 1.55 2011-06-11 00:35:00 fwarmerdam Exp $
  *
  * Name:     mitab_spatialref.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -30,6 +30,9 @@
  **********************************************************************
  *
  * $Log: mitab_spatialref.cpp,v $
+ * Revision 1.55  2011-06-11 00:35:00  fwarmerdam
+ * add support for reading google mercator (#4115)
+ *
  * Revision 1.54  2010-10-07 18:46:26  aboudreault
  * Fixed bad use of atof when locale setting doesn't use . for float (GDAL bug #3775)
  *
@@ -375,6 +378,7 @@ MapInfoDatumInfo asDatumInfoList[] =
 {150, "Hartebeesthoek94",           0, 0,    0,   0,    0, 0, 0, 0, 0},
 {151, "ATS77",                      51, 0, 0, 0, 0, 0, 0, 0, 0},
 {152, "JGD2000",                    0, 0, 0, 0, 0, 0, 0, 0, 0},
+{157, "WGS_1984",                   54,0, 0, 0, 0, 0, 0, 0, 0}, // Google merc
 {1000,"DHDN_Potsdam_Rauenberg",     10,582,  105, 414, -1.04, -0.35, 3.08, 8.3, 0},
 {1001,"Pulkovo_1942",               3, 24,   -123, -94, -0.02, 0.25, 0.13, 1.1, 0},
 {1002,"NTF_Paris_Meridian",         30,-168, -60, 320, 0, 0, 0, 0, 2.337229166667},
@@ -460,6 +464,7 @@ MapInfoSpheroidInfo asSpheroidInfoList[] =
 { 1,"WGS 72",                                   6378135.0,      298.26},
 {28,"WGS 84",                                   6378137.0,      298.257223563},
 {29,"WGS 84 (MAPINFO Datum 0)",                 6378137.01,     298.257223563},
+{54,"WGS 84 (MAPINFO Datum 157)",               6378137.01,     298.257223563},
 {-1,NULL,                                       0.0,            0.0}
 };
  
@@ -1063,6 +1068,17 @@ OGRSpatialReference *TABFile::GetSpatialRef()
                                     psDatumInfo->dfDatumParm3 );
     }
 
+    /*-----------------------------------------------------------------
+     * Special case for Google Mercator (datum=157, ellipse=54, gdal #4115)
+     *----------------------------------------------------------------*/
+    if( sTABProj.nProjId == 10 
+        && sTABProj.nDatumId == 157
+        && sTABProj.nEllipsoidId == 54 )
+    {
+        m_poSpatialRef->SetNode( "PROJCS", "WGS 84 / Pseudo-Mercator" );
+        m_poSpatialRef->SetExtension( "PROJCS", "PROJ4", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
+    }
+
     return m_poSpatialRef;
 }
 
diff --git a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
index 8f43bba..1f68ead 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
+++ b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
@@ -16,9 +16,10 @@
 To connect to a MSSQL datasource, use a connection string specifying the database name,
 with additional parameters as necessary. The connection strings must be prefixed 
     with '<i>MSSQL:</i>'.<br>
-<blockquote><pre>MSSQL:server=.\MSSQLSERVER2008;database=dbname;Integrated Security=true</pre></blockquote>
+<blockquote><pre>
+MSSQL:server=.\MSSQLSERVER2008;database=dbname;trusted_connection=yes</pre></blockquote>
 In addition to the standard parameters of the 
-    <a href="http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring.aspx">connection string</a> 
+    <a href="http://msdn.microsoft.com/en-us/library/ms130822.aspx">ODBC driver connection string</a> 
     format the following custom parameters can also be used in the following syntax:
 
 <ul>
@@ -30,7 +31,10 @@ In addition to the standard parameters of the
 
 </ul>
     <p>The parameter names are not case sensitive in the connection strings.</p> 
-    <p>Specifying the <b>Initial Catalog (Database)</b> parameter is required by the driver in order to select the proper database.</p> 
+    <p>Specifying the <b>
+    Database</b> parameter is required by the driver in order to select the proper database.</p> 
+    <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>SQL statements</h2>
 
@@ -96,13 +100,16 @@ The corresponding entry should already be added to the spatial_ref_sys metadata
 <h2>Examples</h2>
 
 <p>Creating a layer from an OGR data source</p>
-<blockquote><pre>ogr2ogr -overwrite -f MSSQLSpatial "MSSQL:server=.\MSSQLSERVER2008;database=geodb;Integrated Security=true" "rivers.tab"</pre></blockquote>
+<blockquote><pre>
+ogr2ogr -overwrite -f MSSQLSpatial "MSSQL:server=.\MSSQLSERVER2008;database=geodb;trusted_connection=yes" "rivers.tab"</pre></blockquote>
 
 <p>Connecting to a layer and dump the contents</p>
-<blockquote><pre>ogrinfo -al "MSSQL:server=.\MSSQLSERVER2008;database=geodb;tables=rivers;Integrated Security=true"</pre></blockquote>
+<blockquote><pre>
+ogrinfo -al "MSSQL:server=.\MSSQLSERVER2008;database=geodb;tables=rivers;trusted_connection=yes"</pre></blockquote>
 
 <p>Creating a spatial index</p>
-<blockquote><pre>ogrinfo -sql "create spatial index on rivers" "MSSQL:server=.\MSSQLSERVER2008;database=geodb;Integrated Security=true"</pre></blockquote>
+<blockquote><pre>
+ogrinfo -sql "create spatial index on rivers" "MSSQL:server=.\MSSQLSERVER2008;database=geodb;trusted_connection=yes"</pre></blockquote>
 
 </body>
 </html>
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
index 80f2c8c..2f24dea 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 21938 2011-03-11 21:54:57Z tamas $
+ * $Id: ogr_mssqlspatial.h 21939 2011-03-11 21:55:49Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp
index 1449806..9b4a0f8 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlgeometryvalidator.cpp 20863 2010-10-17 15:48:40Z tamas $
+ * $Id: ogrmssqlgeometryvalidator.cpp 21933 2011-03-11 16:50:10Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLGeometryValidator class to create valid SqlGeometries.
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlgeometryvalidator.cpp 20863 2010-10-17 15:48:40Z tamas $");
+CPL_CVSID("$Id: ogrmssqlgeometryvalidator.cpp 21933 2011-03-11 16:50:10Z tamas $");
 
 /************************************************************************/
 /*                   OGRMSSQLGeometryValidator()                        */
@@ -107,10 +107,18 @@ int OGRMSSQLGeometryValidator::ValidateLineString(OGRLineString * poGeom)
         // create a compatible geometry
         if (poPoint0 != NULL)
         {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linestring has no distinct points constructing point geometry instead." );
+            
             // create a point
             poValidGeometry = poPoint0;
             poPoint0 = NULL;
         }
+        else
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linestring has no points. Removing the geometry from the output." );
+        }
     }
 
     if (poPoint0)
@@ -168,6 +176,9 @@ int OGRMSSQLGeometryValidator::ValidateLinearRing(OGRLinearRing * poGeom)
         // create a compatible geometry
         if (poPoint1 != NULL)
         {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has only 2 distinct points constructing linestring geometry instead." );
+            
             // create a linestring
             poValidGeometry = new OGRLineString();
             ((OGRLineString*)poValidGeometry)->setNumPoints( 2 );
@@ -176,10 +187,18 @@ int OGRMSSQLGeometryValidator::ValidateLinearRing(OGRLinearRing * poGeom)
         }
         else if (poPoint0 != NULL)
         {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has no distinct points constructing point geometry instead." );
+            
             // create a point
             poValidGeometry = poPoint0;
             poPoint0 = NULL;
         }
+        else
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has no points. Removing the geometry from the output." );
+        }
     }
 
     if (poPoint0)
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
index c6d71f6..8f5e847 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialdatasource.cpp 21938 2011-03-11 21:54:57Z tamas $
+ * $Id: ogrmssqlspatialdatasource.cpp 23571 2011-12-14 11:06:58Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialDataSource class..
@@ -29,7 +29,7 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 21938 2011-03-11 21:54:57Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 23571 2011-12-14 11:06:58Z tamas $");
 
 /************************************************************************/
 /*                          OGRMSSQLSpatialDataSource()                 */
@@ -450,6 +450,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     char* pszTableSpec = NULL;
     char* pszGeometryFormat = NULL;
     char* pszConnectionName = CPLStrdup(pszNewName + 6);
+    char* pszDriver = NULL;
     int nCurrent, nNext, nTerm;
     nCurrent = nNext = nTerm = strlen(pszConnectionName);
 
@@ -462,10 +463,6 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
             continue;
         }
 
-        if (ParseValue(&pszCatalog, pszConnectionName, "initial catalog=", 
-            nCurrent, nNext, nTerm, FALSE))
-            continue;
-
         if (ParseValue(&pszCatalog, pszConnectionName, "database=", 
             nCurrent, nNext, nTerm, FALSE))
             continue;
@@ -474,6 +471,10 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
             nCurrent, nNext, nTerm, TRUE))
             continue;
 
+        if (ParseValue(&pszDriver, pszConnectionName, "driver=", 
+            nCurrent, nNext, nTerm, FALSE))
+            continue;
+
         if (ParseValue(&pszGeometryFormat, pszConnectionName, 
             "geometryformat=", nCurrent, nNext, nTerm, TRUE))
         {
@@ -492,6 +493,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
                 CPLFree(pszTableSpec);
                 CPLFree(pszGeometryFormat);
                 CPLFree(pszConnectionName);
+                CPLFree(pszDriver);
                 return FALSE;
             }
 
@@ -504,13 +506,13 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     /* Determine if the connection string contains the catalog portion */
     if( pszCatalog == NULL )
     {
-        if( !bTestOpen )
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s does not contain the initial catalog portion\n", pszNewName );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                      "'%s' does not contain the 'database' portion\n", pszNewName );
         
         CPLFree(pszTableSpec);
         CPLFree(pszGeometryFormat);
         CPLFree(pszConnectionName);
+        CPLFree(pszDriver);
         return FALSE;
     }
     
@@ -578,9 +580,23 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     CPLFree(pszTableSpec);
 
     /* Initialize the SQL Server connection. */
-    CPLDebug( "OGR_MSSQLSpatial", "EstablishSession(Connection:\"%s\")", pszConnectionName);
+    int nResult;
+    if ( pszDriver != NULL )
+    {
+        /* driver has been specified */
+        CPLDebug( "OGR_MSSQLSpatial", "EstablishSession(Connection:\"%s\")", pszConnectionName);
+        nResult = oSession.EstablishSession( pszConnectionName, "", "" );
+    }
+    else
+    {
+        /* no driver has been specified, defautls to SQL Server */
+        CPLDebug( "OGR_MSSQLSpatial", "EstablishSession(Connection:\"%s\")", pszConnectionName);
+        nResult = oSession.EstablishSession( CPLSPrintf("DRIVER=SQL Server;%s", pszConnectionName), "", "" );
+    }
+
+    CPLFree(pszDriver);
 
-    if( !oSession.EstablishSession( CPLSPrintf("DRIVER=SQL Server;%s", pszConnectionName), "", "" ) )
+    if( !nResult )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Unable to initialize connection to the server for %s,\n"
@@ -595,7 +611,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
         CPLFree(pszConnectionName);
         return FALSE;
     }
-    
+
     char** papszTypes = NULL;
 
     /* Determine the available tables if not specified. */
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
index 4afdf50..505dc94 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatiallayer.cpp 22661 2011-07-07 14:16:02Z tamas $
+ * $Id: ogrmssqlspatiallayer.cpp 22660 2011-07-07 14:15:31Z 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 22661 2011-07-07 14:16:02Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 22660 2011-07-07 14:15:31Z tamas $");
 /************************************************************************/
 /*                        OGRMSSQLSpatialLayer()                        */
 /************************************************************************/
@@ -342,7 +342,7 @@ OGRFeature *OGRMSSQLSpatialLayer::GetNextRawFeature()
             {
                 eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
                                                       NULL, &poGeom);
-            }
+            }    
         }
         
         if ( eErr != OGRERR_NONE )
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
index f54971d..2498eb0 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialtablelayer.cpp 21942 2011-03-12 18:24:09Z tamas $
+ * $Id: ogrmssqlspatialtablelayer.cpp 21943 2011-03-12 18:25:22Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialTableLayer class, access to an existing table.
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 21942 2011-03-12 18:24:09Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 21943 2011-03-12 18:25:22Z tamas $");
 
 /************************************************************************/
 /*                         OGRMSSQLAppendEscaped( )                     */
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
index 5a00c3e..289c794 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqldatasource.cpp 20460 2010-08-27 20:06:26Z rouault $
+ * $Id: ogrmysqldatasource.cpp 22607 2011-06-28 20:43:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLDataSource class.
@@ -36,7 +36,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmysqldatasource.cpp 20460 2010-08-27 20:06:26Z rouault $");
+CPL_CVSID("$Id: ogrmysqldatasource.cpp 22607 2011-06-28 20:43:27Z rouault $");
 /************************************************************************/
 /*                         OGRMySQLDataSource()                         */
 /************************************************************************/
@@ -500,7 +500,6 @@ OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
     if( pszWKT == NULL || poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
     {
         delete poSRS;
-        CPLFree(pszWKTOri);
         poSRS = NULL;
     }
 
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
index ae31b10..815a93c 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmysqltablelayer.cpp 20460 2010-08-27 20:06:26Z rouault $
+ * $Id: ogrmysqltablelayer.cpp 22123 2011-04-05 19:41:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLTableLayer class.
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_mysql.h"
 
-CPL_CVSID("$Id: ogrmysqltablelayer.cpp 20460 2010-08-27 20:06:26Z rouault $");
+CPL_CVSID("$Id: ogrmysqltablelayer.cpp 22123 2011-04-05 19:41:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRMySQLTableLayer()                         */
@@ -129,6 +129,7 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 /* -------------------------------------------------------------------- */
     OGRFeatureDefn *poDefn = new OGRFeatureDefn( pszTable );
     char           **papszRow;
+    OGRwkbGeometryType eForcedGeomType = wkbUnknown;
 
     poDefn->Reference();
 
@@ -136,20 +137,23 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
     {
         const char      *pszType;
         OGRFieldDefn    oField( papszRow[0], OFTString);
+        int             nLenType;
 
         pszType = papszRow[1];
 
         if( pszType == NULL )
             continue;
 
+        nLenType = (int)strlen(pszType);
+
         if( EQUAL(pszType,"varbinary")
-            || (strlen(pszType)>3 && EQUAL(pszType+strlen(pszType)-4,"blob")))
+            || (nLenType>=4 && EQUAL(pszType+nLenType-4,"blob")))
         {
             oField.SetType( OFTBinary );
         }
         else if( EQUAL(pszType,"varchar") 
-                 || EQUAL(pszType+strlen(pszType)-4,"enum") 
-                 || EQUAL(pszType+strlen(pszType)-4,"set") )
+                 || (nLenType>=4 && EQUAL(pszType+nLenType-4,"enum"))
+                 || (nLenType>=3 && EQUAL(pszType+nLenType-3,"set")) )
         {
             oField.SetType( OFTString );
 
@@ -160,16 +164,18 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             char ** papszTokens;
 
             papszTokens = CSLTokenizeString2(pszType,"(),",0);
-            
-            /* width is the second */
-            oField.SetWidth(atoi(papszTokens[1]));
+            if (CSLCount(papszTokens) >= 2)
+            {
+                /* width is the second */
+                oField.SetWidth(atoi(papszTokens[1]));
+            }
 
             CSLDestroy( papszTokens );
             oField.SetType( OFTString );
 
         }
         
-        if(strlen(pszType)>3 && EQUAL(pszType+strlen(pszType)-4,"text"))
+        if(nLenType>=4 && EQUAL(pszType+nLenType-4,"text"))
         {
             oField.SetType( OFTString );            
         }
@@ -184,9 +190,11 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             char ** papszTokens;
 
             papszTokens = CSLTokenizeString2(pszType,"(),",0);
-            
-            /* width is the second */
-            oField.SetWidth(atoi(papszTokens[1]));
+            if (CSLCount(papszTokens) >= 2)
+            {
+                /* width is the second */
+                oField.SetWidth(atoi(papszTokens[1]));
+            }
 
             CSLDestroy( papszTokens );
             oField.SetType( OFTString );
@@ -221,10 +229,12 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             char ** papszTokens;
 
             papszTokens = CSLTokenizeString2(pszType,"(),",0);
-            
-            /* width is the second and precision is the third */
-            oField.SetWidth(atoi(papszTokens[1]));
-            oField.SetPrecision(atoi(papszTokens[2]));
+            if (CSLCount(papszTokens) >= 3)
+            {
+                /* width is the second and precision is the third */
+                oField.SetWidth(atoi(papszTokens[1]));
+                oField.SetPrecision(atoi(papszTokens[2]));
+            }
             CSLDestroy( papszTokens );
 
 
@@ -246,9 +256,12 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             
             char ** papszTokens=NULL;
             papszTokens = CSLTokenizeString2(pszType,"(),",0);
-            /* width is the second and precision is the third */
-            oField.SetWidth(atoi(papszTokens[1]));
-            oField.SetPrecision(atoi(papszTokens[2]));
+            if (CSLCount(papszTokens) >= 3)
+            {
+                /* width is the second and precision is the third */
+                oField.SetWidth(atoi(papszTokens[1]));
+                oField.SetPrecision(atoi(papszTokens[2]));
+            }
             CSLDestroy( papszTokens );  
 
             oField.SetType( OFTReal );
@@ -275,10 +288,20 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
             oField.SetType( OFTString );
             oField.SetWidth( 10 );
         }
-        else if( EQUAL(pszType, "geometry") ) 
+        else if( EQUAL(pszType, "geometry") ||
+                 OGRFromOGCGeomType(pszType) != wkbUnknown)
         {
             if (pszGeomColumn == NULL)
+            {
                 pszGeomColumn = CPLStrdup(papszRow[0]);
+                eForcedGeomType = OGRFromOGCGeomType(pszType);
+            }
+            else
+            {
+                CPLDebug("MYSQL",
+                         "Ignoring %s as geometry column. Another one(%s) has already been found before",
+                         papszRow[0], pszGeomColumn);
+            }
             continue;
         }
         // Is this an integer primary key field?
@@ -341,7 +364,9 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 
             poDefn->SetGeomType( nGeomType );
 
-        } 
+        }
+        else if (eForcedGeomType != wkbUnknown)
+            poDefn->SetGeomType(eForcedGeomType);
 
         if( hResult != NULL )
             mysql_free_result( hResult );   //Free our query results for finding type.
diff --git a/ogr/ogrsf_frmts/nas/nashandler.cpp b/ogr/ogrsf_frmts/nas/nashandler.cpp
index 989e8e3..60b8b37 100644
--- a/ogr/ogrsf_frmts/nas/nashandler.cpp
+++ b/ogr/ogrsf_frmts/nas/nashandler.cpp
@@ -60,6 +60,30 @@ NASHandler::~NASHandler()
     CPLFree( m_pszGeometry );
 }
 
+/************************************************************************/
+/*                        GetAttributes()                               */
+/************************************************************************/
+
+CPLString NASHandler::GetAttributes(const Attributes* attrs)
+{
+    CPLString osRes;
+    char *pszString;
+
+    for(unsigned int i=0; i < attrs->getLength(); i++)
+    {
+        osRes += " ";
+        pszString = tr_strdup(attrs->getQName(i));
+        osRes += pszString;
+        CPLFree( pszString );
+        osRes += "=\"";
+        pszString = tr_strdup(attrs->getValue(i));
+        osRes += pszString;
+        CPLFree( pszString );
+        osRes += "\"";
+    }
+    return osRes;
+}
+
 
 /************************************************************************/
 /*                            startElement()                            */
@@ -73,6 +97,7 @@ void NASHandler::startElement(const XMLCh* const    uri,
 {
     char        szElementName[MAX_TOKEN_SIZE];
     GMLReadState *poState = m_poReader->GetState();
+    const char *pszLast = NULL;
 
     tr_strcpy( szElementName, localname );
 
@@ -102,31 +127,72 @@ void NASHandler::startElement(const XMLCh* const    uri,
         || IsGeometryElement( szElementName ) )
     {
         int nLNLen = tr_strlen( localname );
+        CPLString osAttributes = GetAttributes( &attrs );
 
         /* should save attributes too! */
 
         if( m_pszGeometry == NULL )
             m_nGeometryDepth = poState->m_nPathLength;
         
-        if( m_nGeomLen + nLNLen + 4 > m_nGeomAlloc )
+        if( m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc )
         {
-            m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + 1000);
+            m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + osAttributes.size() + 1000);
             m_pszGeometry = (char *) 
                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
         }
 
         strcpy( m_pszGeometry+m_nGeomLen, "<" );
         tr_strcpy( m_pszGeometry+m_nGeomLen+1, localname );
-        strcat( m_pszGeometry+m_nGeomLen+nLNLen+1, ">" );
+        
+        if( osAttributes.size() > 0 )
+        {
+            strcat( m_pszGeometry+m_nGeomLen, " " );
+            strcat( m_pszGeometry+m_nGeomLen, osAttributes );
+        }
+
+        strcat( m_pszGeometry+m_nGeomLen, ">" );
         m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
     }
     
 /* -------------------------------------------------------------------- */
+/*      Is this the ogc:Filter element in a wfs:Delete operation?       */
+/*      If so we translate it as a specialized sort of feature.         */
+/* -------------------------------------------------------------------- */
+    else if( EQUAL(szElementName,"Filter") 
+             && (pszLast = m_poReader->GetState()->GetLastComponent()) != NULL
+             && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace")) )
+    {
+        const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
+        if ( pszFilteredClassName != NULL &&
+             strcmp("Delete", pszFilteredClassName) != 0 )
+        {
+            m_bIgnoreFeature = TRUE;
+            m_nDepthFeature = m_nDepth;
+            m_nDepth ++;
+
+            return;
+        }
+
+        m_bIgnoreFeature = FALSE;
+
+        m_poReader->PushFeature( "Delete", attrs );
+
+        m_nDepthFeature = m_nDepth;
+        m_nDepth ++;
+            
+        m_poReader->SetFeaturePropertyDirectly( "typeName", CPLStrdup(m_osLastTypeName) );
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Is it a feature?  If so push a whole new state, and return.     */
 /* -------------------------------------------------------------------- */
     else if( m_poReader->IsFeatureElement( szElementName ) )
     {
+        m_osLastTypeName = szElementName;
+
         const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
+
         if ( pszFilteredClassName != NULL &&
              strcmp(szElementName, pszFilteredClassName) != 0 )
         {
@@ -148,6 +214,27 @@ void NASHandler::startElement(const XMLCh* const    uri,
     }
 
 /* -------------------------------------------------------------------- */
+/*      If it is the wfs:Delete element, then remember the typeName     */
+/*      attribute so we can assign it to the feature that will be       */
+/*      produced when we process the Filter element.                    */
+/* -------------------------------------------------------------------- */
+    else if( EQUAL(szElementName,"Delete") )
+    {
+        int nIndex;
+        XMLCh  Name[100];
+
+        tr_strcpy( Name, "typeName" );
+        nIndex = attrs.getIndex( Name );
+        
+        if( nIndex != -1 )
+        {
+            char *pszTypeName = tr_strdup( attrs.getValue( nIndex ) );
+            m_osLastTypeName = pszTypeName;
+            CPLFree( pszTypeName );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      If it is (or at least potentially is) a simple attribute,       */
 /*      then start collecting it.                                       */
 /* -------------------------------------------------------------------- */
@@ -158,6 +245,11 @@ void NASHandler::startElement(const XMLCh* const    uri,
 
         // Capture href as OB property.
         m_poReader->CheckForRelations( szElementName, attrs );
+
+        // Capture "fid" attribute as part of the property value - 
+        // primarily this is for wfs:Delete operation's FeatureId attribute.
+        if( EQUAL(szElementName,"FeatureId") )
+            m_poReader->CheckForFID( attrs, &m_pszCurField );
     }
 
 /* -------------------------------------------------------------------- */
@@ -204,8 +296,7 @@ void NASHandler::endElement(const   XMLCh* const    uri,
     {
         CPLAssert( poState->m_poFeature != NULL );
         
-        m_poReader->SetFeatureProperty( poState->m_pszPath, m_pszCurField );
-        CPLFree( m_pszCurField );
+        m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(), m_pszCurField );
         m_pszCurField = NULL;
     }
 
@@ -234,10 +325,13 @@ void NASHandler::endElement(const   XMLCh* const    uri,
         if( poState->m_nPathLength == m_nGeometryDepth+1 )
         {
             if( poState->m_poFeature != NULL )
-                poState->m_poFeature->SetGeometryDirectly( m_pszGeometry );
-            else
-                CPLFree( m_pszGeometry );
+            {
+                CPLXMLNode* psNode = CPLParseXMLString(m_pszGeometry);
+                if (psNode)
+                    poState->m_poFeature->SetGeometryDirectly( psNode );
+            }
 
+            CPLFree( m_pszGeometry );
             m_pszGeometry = NULL;
             m_nGeomAlloc = m_nGeomLen = 0;
         }
@@ -257,6 +351,20 @@ void NASHandler::endElement(const   XMLCh* const    uri,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Ends of a wfs:Delete should be triggered on the close of the    */
+/*      <Filter> element.                                               */
+/* -------------------------------------------------------------------- */
+    else if( m_nDepth == m_nDepthFeature 
+             && poState->m_poFeature != NULL
+             && EQUAL(szElementName,"Filter") 
+             && EQUAL(poState->m_poFeature->GetClass()->GetElementName(),
+                      "Delete") )
+    {
+        m_nDepthFeature = 0;
+        m_poReader->PopState();
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Otherwise, we just pop the element off the local read states    */
 /*      element stack.                                                  */
 /* -------------------------------------------------------------------- */
@@ -290,8 +398,12 @@ void NASHandler::characters(const XMLCh* const chars_in,
     {
         int     nCurFieldLength = strlen(m_pszCurField);
 
-        while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
-            chars++;
+        if (nCurFieldLength == 0)
+        {
+            // Ignore white space
+            while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
+                chars++;
+        }
 
         char *pszTranslated = tr_strdup(chars);
         
@@ -311,9 +423,12 @@ void NASHandler::characters(const XMLCh* const chars_in,
     }
     else if( m_pszGeometry != NULL )
     {
-        // Ignore white space
-        while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
-            chars++;
+        if (m_nGeomLen == 0)
+        {
+            // Ignore white space
+            while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
+                chars++;
+        }
         
         int nCharsLen = tr_strlen(chars);
 
diff --git a/ogr/ogrsf_frmts/nas/nasreader.cpp b/ogr/ogrsf_frmts/nas/nasreader.cpp
index adbc305..ed4f577 100644
--- a/ogr/ogrsf_frmts/nas/nasreader.cpp
+++ b/ogr/ogrsf_frmts/nas/nasreader.cpp
@@ -30,6 +30,7 @@
 #include "gmlreader.h"
 #include "cpl_error.h"
 #include "cpl_string.h"
+#include "gmlutils.h"
 
 #define SUPPORT_GEOMETRY
 
@@ -92,6 +93,9 @@ NASReader::~NASReader()
 
     CleanupParser();
 
+    if (CSLTestBoolean(CPLGetConfigOption("NAS_XERCES_TERMINATE", "FALSE")))
+        XMLPlatformUtils::Terminate();
+
     CPLFree( m_pszFilteredClassName );
 }
 
@@ -331,8 +335,7 @@ void NASReader::PushFeature( const char *pszElement,
     if( nFIDIndex != -1 )
     {
         char *pszFID = tr_strdup( attrs.getValue( nFIDIndex ) );
-        SetFeatureProperty( "gml_id", pszFID );
-        CPLFree( pszFID );
+        SetFeaturePropertyDirectly( "gml_id", pszFID );
     }
 
 }
@@ -356,7 +359,8 @@ int NASReader::IsFeatureElement( const char *pszElement )
     // -- either a wfs:Insert or a gml:featureMember. 
 
     if( (nLen < 6 || !EQUAL(pszLast+nLen-6,"Insert")) 
-        && (nLen < 13 || !EQUAL(pszLast+nLen-13,"featureMember")) )
+        && (nLen < 13 || !EQUAL(pszLast+nLen-13,"featureMember"))
+        && (nLen < 6 || !EQUAL(pszLast+nLen-7,"Replace")) )
         return FALSE;
 
     // If the class list isn't locked, any element that is a featureMember
@@ -399,7 +403,7 @@ int NASReader::IsAttributeElement( const char *pszElement )
         osElemPath = pszElement;
     else
     {
-        osElemPath = m_poState->m_pszPath;
+        osElemPath = m_poState->osPath;
         osElemPath += "|";
         osElemPath += pszElement;
     }
@@ -512,12 +516,11 @@ void NASReader::ClearClasses()
 /*                                                                      */
 /*      Set the property value on the current feature, adding the       */
 /*      property name to the GMLFeatureClass if required.               */
-/*      Eventually this function may also "refine" the property         */
-/*      type based on what is encountered.                              */
+/*      The pszValue ownership is passed to this function.              */
 /************************************************************************/
 
-void NASReader::SetFeatureProperty( const char *pszElement, 
-                                    const char *pszValue )
+void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
+                                            char *pszValue )
 
 {
     GMLFeature *poFeature = GetState()->m_poFeature;
@@ -543,6 +546,7 @@ void NASReader::SetFeatureProperty( const char *pszElement,
         if( poClass->IsSchemaLocked() )
         {
             CPLDebug("GML","Encountered property missing from class schema.");
+            CPLFree(pszValue);
             return;
         }
 
@@ -572,17 +576,57 @@ void NASReader::SetFeatureProperty( const char *pszElement,
     }
 
 /* -------------------------------------------------------------------- */
+/*      We want to handle <lage> specially to ensure it is zero         */
+/*      filled, and treated as a string depspite the numeric            */
+/*      content. https://trac.wheregroup.com/PostNAS/ticket/9           */
+/* -------------------------------------------------------------------- */
+    if( strcmp(poClass->GetProperty(iProperty)->GetName(),"lage") == 0 )
+    {
+        if( strlen(pszValue) < 5 )
+        {
+            CPLString osValue = "00000";
+            osValue += pszValue;
+            poFeature->SetPropertyDirectly( iProperty, CPLStrdup(osValue + osValue.size() - 5) );
+            CPLFree(pszValue);
+        }
+        else
+            poFeature->SetPropertyDirectly( iProperty, pszValue );
+
+        
+        if( !poClass->IsSchemaLocked() )
+        {
+            poClass->GetProperty(iProperty)->SetWidth( 5 );
+            poClass->GetProperty(iProperty)->SetType( GMLPT_String );
+        }
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Set the property                                                */
 /* -------------------------------------------------------------------- */
-    poFeature->SetProperty( iProperty, pszValue );
+    poFeature->SetPropertyDirectly( iProperty, pszValue );
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to update the property type?                         */
 /* -------------------------------------------------------------------- */
     if( !poClass->IsSchemaLocked() )
     {
-        poClass->GetProperty(iProperty)->AnalysePropertyValue(
-                             poFeature->GetProperty(iProperty));
+        // Special handling for punktkennung per NAS #12
+        if( strcmp(poClass->GetProperty(iProperty)->GetName(),
+                   "punktkennung") == 0)
+        {
+            poClass->GetProperty(iProperty)->SetWidth( 15 );
+            poClass->GetProperty(iProperty)->SetType( GMLPT_String );
+        }
+        // Special handling for artDerFlurstuecksgrenze per http://trac.osgeo.org/gdal/ticket/4255
+        else if( strcmp(poClass->GetProperty(iProperty)->GetName(),
+                   "artDerFlurstuecksgrenze") == 0)
+        {
+            poClass->GetProperty(iProperty)->SetType( GMLPT_IntegerList );
+        }
+        else
+            poClass->GetProperty(iProperty)->AnalysePropertyValue(
+                poFeature->GetProperty(iProperty));
     }
 }
 
@@ -776,6 +820,8 @@ int NASReader::PrescanForSchema( int bGetExtents )
     if( !SetupParser() )
         return FALSE;
 
+    std::string osWork;
+
     while( (poFeature = NextFeature()) != NULL )
     {
         GMLFeatureClass *poClass = poFeature->GetClass();
@@ -790,11 +836,10 @@ int NASReader::PrescanForSchema( int bGetExtents )
         {
             OGRGeometry *poGeometry = NULL;
 
-            if( poFeature->GetGeometry() != NULL 
-                && strlen(poFeature->GetGeometry()) != 0 )
+            const CPLXMLNode* const * papsGeometry = poFeature->GetGeometryList();
+            if( papsGeometry[0] != NULL )
             {
-                poGeometry = (OGRGeometry *) OGR_G_CreateFromGML( 
-                    poFeature->GetGeometry() );
+                poGeometry = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[0]);
             }
 
             if( poGeometry != NULL )
@@ -804,6 +849,12 @@ int NASReader::PrescanForSchema( int bGetExtents )
                 OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
                     poClass->GetGeometryType();
 
+                // Merge SRSName into layer.
+                const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork, FALSE);
+//                if (pszSRSName != NULL)
+//                    m_bCanUseGlobalSRSName = FALSE;
+                poClass->MergeSRSName(pszSRSName);
+
                 // Merge geometry type into layer.
                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
                     eGType = wkbNone;
@@ -861,6 +912,35 @@ void NASReader::ResetReading()
 }
 
 /************************************************************************/
+/*                            CheckForFID()                             */
+/*                                                                      */
+/*      Merge the fid attribute into the current field text.            */
+/************************************************************************/
+
+void NASReader::CheckForFID( const Attributes &attrs,
+                             char **ppszCurField )
+
+{
+    int nIndex;
+    XMLCh  Name[100];
+
+    tr_strcpy( Name, "fid" );
+    nIndex = attrs.getIndex( Name );
+
+    if( nIndex != -1 )
+    {
+        char *pszFID = tr_strdup( attrs.getValue( nIndex ) );
+        CPLString osCurField = *ppszCurField;
+
+        osCurField += pszFID;
+        CPLFree( pszFID );
+
+        CPLFree( *ppszCurField );
+        *ppszCurField = CPLStrdup(osCurField);
+    }
+}
+
+/************************************************************************/
 /*                         CheckForRelations()                          */
 /************************************************************************/
 
@@ -890,6 +970,32 @@ void NASReader::CheckForRelations( const char *pszElement,
 }
 
 /************************************************************************/
+/*                         HugeFileResolver()                           */
+/*      Returns TRUE for success                                        */
+/************************************************************************/
+
+int NASReader::HugeFileResolver( const char *pszFile,
+                              int bSqliteIsTempFile,
+                              int iSqliteCacheMB )
+
+{
+    CPLDebug( "NAS", "HugeFileResolver() not currently implemented for NAS." );
+    return FALSE;
+}
+
+/************************************************************************/
+/*                         PrescanForTemplate()                         */
+/*      Returns TRUE for success                                        */
+/************************************************************************/
+
+int NASReader::PrescanForTemplate( void )
+
+{
+    CPLDebug( "NAS", "PrescanForTemplate() not currently implemented for NAS." );
+    return FALSE;
+}
+
+/************************************************************************/
 /*                           ResolveXlinks()                            */
 /*      Returns TRUE for success                                        */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/nas/nasreaderp.h b/ogr/ogrsf_frmts/nas/nasreaderp.h
index c06b650..c79afc0 100644
--- a/ogr/ogrsf_frmts/nas/nasreaderp.h
+++ b/ogr/ogrsf_frmts/nas/nasreaderp.h
@@ -33,6 +33,7 @@
 #include "gmlreader.h"
 #include "gmlreaderp.h"
 #include "ogr_api.h"
+#include "cpl_string.h"
 
 IGMLReader *CreateNASReader();
 
@@ -63,6 +64,8 @@ class NASHandler : public DefaultHandler
     int        m_nDepthFeature;
     int        m_bIgnoreFeature;
 
+    CPLString  m_osLastTypeName;
+
 public:
     NASHandler( NASReader *poReader );
     virtual ~NASHandler();
@@ -87,6 +90,8 @@ public:
 #endif
 
     void fatalError(const SAXParseException&);
+
+    CPLString GetAttributes( const Attributes* attr );
 };
 
 /************************************************************************/
@@ -172,6 +177,7 @@ public:
     int              SaveClasses( const char *pszFile = NULL );
 
     int              PrescanForSchema(int bGetExtents = TRUE );
+    int              PrescanForTemplate( void );
     void             ResetReading();
 
     int              ParseXSD( const char *pszFile ) { return FALSE; }
@@ -181,6 +187,10 @@ public:
                                     char **papszSkip = NULL,
                                     const int bStrict = FALSE );
 
+    int              HugeFileResolver( const char *pszFile,
+                                       int bSqliteIsTempFile,
+                                       int iSqliteCacheMB );
+
 // --- 
 
     GMLReadState     *GetState() const { return m_poState; }
@@ -193,11 +203,12 @@ public:
     void        PushFeature( const char *pszElement, 
                              const Attributes &attrs );
 
-    void        SetFeatureProperty( const char *pszElement,
-                                    const char *pszValue );
+    void        SetFeaturePropertyDirectly( const char *pszElement,
+                                    char *pszValue );
 
     int         HasStoppedParsing() { return FALSE; }
 
+    void        CheckForFID( const Attributes &attrs, char **ppszCurField );
     void        CheckForRelations( const char *pszElement, 
                                    const Attributes &attrs );
 
diff --git a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
index eaf7702..2c78381 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
@@ -33,6 +33,14 @@
 
 CPL_CVSID("$Id: ogrgmldatasource.cpp 12743 2007-11-13 13:59:37Z dron $");
 
+static const char *apszURNNames[] = 
+{ 
+    "DE_DHDN_3GK2_*", "EPSG:31466", 
+    "DE_DHDN_3GK3_*", "EPSG:31467", 
+    "ETRS89_UTM32", "EPSG:25832", 
+    NULL, NULL 
+};
+
 /************************************************************************/
 /*                         OGRNASDataSource()                         */
 /************************************************************************/
@@ -183,7 +191,10 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen )
 /*      will have mechanisms for remembering the schema and related     */
 /*      information.                                                    */
 /* -------------------------------------------------------------------- */
-    if( !bHaveSchema && !poReader->PrescanForSchema( TRUE ) )
+    CPLErrorReset();
+    if( !bHaveSchema 
+        && !poReader->PrescanForSchema( TRUE ) 
+        && CPLGetLastErrorType() == CE_Failure )
     {
         // we assume an errors have been reported.
         return FALSE;
@@ -193,7 +204,7 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen )
 /*      Save the schema file if possible.  Don't make a fuss if we      */
 /*      can't ... could be read-only directory or something.            */
 /* -------------------------------------------------------------------- */
-    if( !bHaveSchema )
+    if( !bHaveSchema && poReader->GetClassCount() > 0 )
     {
         FILE    *fp = NULL;
 
@@ -246,9 +257,52 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
         eGType = wkbUnknown;
 
 /* -------------------------------------------------------------------- */
+/*      Translate SRS.                                                  */
+/* -------------------------------------------------------------------- */
+    const char* pszSRSName = poClass->GetSRSName();
+    OGRSpatialReference* poSRS = NULL;
+    if (pszSRSName)
+    {
+        int i;
+
+        poSRS = new OGRSpatialReference();
+        
+        const char *pszHandle = strrchr( pszSRSName, ':' );
+        if( pszHandle != NULL )
+            pszHandle += 1;
+
+        for( i = 0; apszURNNames[i*2+0] != NULL; i++ )
+        {
+            const char *pszTarget = apszURNNames[i*2+0];
+            int nTLen = strlen(pszTarget);
+
+            // Are we just looking for a prefix match?
+            if( pszTarget[nTLen-1] == '*' )
+            {
+                if( EQUALN(pszTarget,pszHandle,nTLen-1) )
+                    pszSRSName = apszURNNames[i*2+1];
+            }
+            else
+            {
+                if( EQUAL(pszTarget,pszHandle) )
+                    pszSRSName = apszURNNames[i*2+1];
+            }
+        }
+        
+        if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE)
+        {
+            CPLDebug( "NAS", "Failed to translate srsName='%s'", 
+                      pszSRSName );
+            delete poSRS;
+            poSRS = NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Create an empty layer.                                          */
 /* -------------------------------------------------------------------- */
-    poLayer = new OGRNASLayer( poClass->GetName(), NULL, eGType, this );
+    poLayer = new OGRNASLayer( poClass->GetName(), poSRS, eGType, this );
+    delete poSRS;
 
 /* -------------------------------------------------------------------- */
 /*      Added attributes (properties).                                  */
@@ -328,7 +382,8 @@ void OGRNASDataSource::PopulateRelations()
         for( i = 0; papszOBProperties != NULL && papszOBProperties[i] != NULL;
              i++ )
         {
-            const GMLProperty *psGMLId = poFeature->GetProperty( "gml_id" );
+            int nGMLIdIndex = poFeature->GetClass()->GetPropertyIndex( "gml_id" );
+            const GMLProperty *psGMLId = (nGMLIdIndex >= 0) ? poFeature->GetProperty(nGMLIdIndex ) : NULL;
             char *pszName = NULL;
             const char *pszValue = CPLParseNameValue( papszOBProperties[i], 
                                                       &pszName );
diff --git a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
index 9d856dc..8239d89 100644
--- a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
@@ -144,11 +144,10 @@ OGRFeature *OGRNASLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Does it satisfy the spatial query, if there is one?             */
 /* -------------------------------------------------------------------- */
-
-        if( poNASFeature->GetGeometry() != NULL )
+        const CPLXMLNode* const * papsGeometry = poNASFeature->GetGeometryList();
+        if (papsGeometry[0] != NULL)
         {
-            poGeom = (OGRGeometry*) 
-                OGR_G_CreateFromGML( poNASFeature->GetGeometry() );
+            poGeom = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[0]);
 
             // We assume the createFromNAS() function would have already
             // reported the error. 
diff --git a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
index 381a1df..51c377f 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 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ntf_raster.cpp 21977 2011-03-18 19:53:18Z warmerdam $
  *
  * 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 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ntf_raster.cpp 21977 2011-03-18 19:53:18Z warmerdam $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -241,8 +241,7 @@ OGRNTFRasterLayer::OGRNTFRasterLayer( OGRNTFDataSource *poDSIn,
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint25D );
 
-    OGRFieldDefn      oHeight( "HEIGHT", OFTInteger );
-    oHeight.SetWidth(5);
+    OGRFieldDefn      oHeight( "HEIGHT", OFTReal );
     poFeatureDefn->AddFieldDefn( &oHeight );
 
     poReader = poReaderIn;
@@ -387,7 +386,7 @@ OGRFeature *OGRNTFRasterLayer::GetFeature( long nFeatureId )
         new OGRPoint( padfGeoTransform[0] + padfGeoTransform[1] * iReqColumn,
                       padfGeoTransform[3] + padfGeoTransform[5] * iReqRow,
                       pafColumn[iReqRow] ) );
-    poFeature->SetField( 0, (int) pafColumn[iReqRow] );
+    poFeature->SetField( 0, pafColumn[iReqRow] );
     
     return poFeature;
 }
diff --git a/ogr/ogrsf_frmts/oci/GNUmakefile b/ogr/ogrsf_frmts/oci/GNUmakefile
index 6fd89f4..d6e7d48 100644
--- a/ogr/ogrsf_frmts/oci/GNUmakefile
+++ b/ogr/ogrsf_frmts/oci/GNUmakefile
@@ -16,6 +16,8 @@ default:	$(O_OBJ:.o=.$(OBJ_EXT))
 clean:
 	rm -f *.o $(O_OBJ)
 
+$(O_OBJ):	ogr_oci.h 
+
 fastload:	fastload.cpp
 	$(CXX) $(CPPFLAGS) $(CFLAGS) fastload.cpp -L../../.. -lgdal.1.1 \
 		-o fastload
diff --git a/ogr/ogrsf_frmts/oci/drv_oci.html b/ogr/ogrsf_frmts/oci/drv_oci.html
index d428d5d..ca51c95 100644
--- a/ogr/ogrsf_frmts/oci/drv_oci.html
+++ b/ogr/ogrsf_frmts/oci/drv_oci.html
@@ -94,9 +94,13 @@ in USER_SDO_GEOM_METADATA and rebuilding the spatial index.<p>
 <li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
 desired name to be destroyed before creating the requested layer.<p>
 
+<li> <b>TRUNCATE</b>: This may be "YES" to force the existing table to 
+be reused, but to first truncate all records in the table, preserving 
+indexes or dependencies.<p>
+
 <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
-Oracle.  This converts to lower case and converts some special characters
+Oracle.  This converts to upper case and converts some special characters
 like "-" and "#" to "_".  The default value is "NO".<p>
 
 <li> <b>PRECISION</b>: This may be "YES" to force new fields created on this
@@ -116,15 +120,15 @@ when the spatial index is created.  For instance setting INDEX_PARAMETERS to
 SDO_LEVEL=5 would cause a 5 level tile index to be used.  By default no 
 parameters are passed causing a default R-Tree spatial index to be created.<p>
 
-<li> <b>DIMINFO_X</b>: This may be set to <xmin>,<xmax>,<xres> values to
+<li> <b>DIMINFO_X</b>: This may be set to xmin,xmax,xres values to
 control the X dimension info written into the USER_SDO_GEOM_METADATA table.
 By default extents are collected from the actual data written.<p>
 
-<li> <b>DIMINFO_Y</b>: This may be set to <ymin>,<ymax>,<yres> values to
+<li> <b>DIMINFO_Y</b>: This may be set to ymin,ymax,yres values to
 control the Y dimension info written into the USER_SDO_GEOM_METADATA table.
 By default extents are collected from the actual data written.<p>
 
-<li> <b>DIMINFO_Z</b>: This may be set to <zmin>,<zmax>,<zres> values to
+<li> <b>DIMINFO_Z</b>: This may be set to zmin,zmax,zres values to
 control the Y dimension info written into the USER_SDO_GEOM_METADATA table.
 By default fixed values of -100000,100000,0.002 are used for layers with
 a third dimension.<p>
diff --git a/ogr/ogrsf_frmts/oci/ogr_oci.h b/ogr/ogrsf_frmts/oci/ogr_oci.h
index 2ba1872..edb2620 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 20120 2010-07-23 02:41:07Z ilucena $
+ * $Id: ogr_oci.h 22346 2011-05-10 03:02:15Z warmerdam $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Oracle Spatial OGR Driver Declarations. 
@@ -388,6 +388,8 @@ class OGROCITableLayer : public OGROCIWritableLayer
     int                 bUpdateAccess;
     int                 bNewLayer;
     OGREnvelope         sExtent;
+    bool                bExtentUpdated;
+
     int                 iNextFIDToWrite;
     int                 bHaveSpatialIndex;
 
@@ -402,9 +404,13 @@ class OGROCITableLayer : public OGROCIWritableLayer
 
     int                 bValidTable;
 
+    CPLString           osTableName;
+    CPLString           osOwner;
+
     OCIArray           *hOrdVARRAY;
     OCIArray           *hElemInfoVARRAY;
 
+    void                UpdateLayerExtents();
     void                FinalizeNewLayer();
 
     void                TestForSpatialIndex( const char * );
@@ -510,6 +516,7 @@ class OGROCIDataSource : public OGRDataSource
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
 
+    virtual OGRErr      DeleteLayer(int);
     virtual OGRLayer    *CreateLayer( const char *, 
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
@@ -518,6 +525,8 @@ class OGROCIDataSource : public OGRDataSource
     int                 TestCapability( const char * );
 
     void                DeleteLayer( const char * );
+
+    void                TruncateLayer( const char * );
     void                ValidateLayer( const char * );
     
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
diff --git a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
index 92fa218..0c0797f 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocidatasource.cpp 20120 2010-07-23 02:41:07Z ilucena $
+ * $Id: ogrocidatasource.cpp 22299 2011-05-04 21:23:02Z warmerdam $
  *
  * 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 20120 2010-07-23 02:41:07Z ilucena $");
+CPL_CVSID("$Id: ogrocidatasource.cpp 22299 2011-05-04 21:23:02Z warmerdam $");
 
 static int anEPSGOracleMapping[] = 
 {
@@ -351,7 +351,52 @@ void OGROCIDataSource::ValidateLayer( const char *pszLayerName )
 }
 
 /************************************************************************/
-/*                            DeleteLayer()                             */
+/*                           DeleteLayer(int)                           */
+/************************************************************************/
+
+OGRErr OGROCIDataSource::DeleteLayer( int iLayer )
+
+{
+/* -------------------------------------------------------------------- */
+/*      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( "OCI", "DeleteLayer(%s)", osLayerName.c_str() );
+
+    delete papoLayers[iLayer];
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1, 
+             sizeof(void *) * (nLayers - iLayer - 1) );
+    nLayers--;
+
+/* -------------------------------------------------------------------- */
+/*      Remove from the database.                                       */
+/* -------------------------------------------------------------------- */
+    OGROCIStatement oCommand( poSession );
+    CPLString       osCommand;
+    int             nFailures = 0;
+
+    osCommand.Printf( "DROP TABLE \"%s\"", osLayerName.c_str() );
+    if( oCommand.Execute( osCommand ) != CE_None )
+        nFailures++;
+
+    osCommand.Printf( 
+        "DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = UPPER('%s')",
+        osLayerName.c_str() );
+
+    if( oCommand.Execute( osCommand ) != CE_None )
+        nFailures++;
+
+    if( nFailures == 0 )
+        return OGRERR_NONE;
+    else
+        return OGRERR_FAILURE;
+}
+
+/************************************************************************/
+/*                      DeleteLayer(const char *)                       */
 /************************************************************************/
 
 void OGROCIDataSource::DeleteLayer( const char *pszLayerName )
@@ -378,32 +423,30 @@ void OGROCIDataSource::DeleteLayer( const char *pszLayerName )
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Blow away our OGR structures related to the layer.  This is     */
-/*      pretty dangerous if anything has a reference to this layer!     */
-/* -------------------------------------------------------------------- */
-    CPLDebug( "OCI", "DeleteLayer(%s)", pszLayerName );
+    DeleteLayer( iLayer );
+}
 
-    delete papoLayers[iLayer];
-    memmove( papoLayers + iLayer, papoLayers + iLayer + 1, 
-             sizeof(void *) * (nLayers - iLayer - 1) );
-    nLayers--;
+/************************************************************************/
+/*                           TruncateLayer()                            */
+/************************************************************************/
+
+void OGROCIDataSource::TruncateLayer( const char *pszLayerName )
+
+{
 
 /* -------------------------------------------------------------------- */
-/*      Remove from the database.                                       */
+/*      Set OGR Debug statement explaining what is happening            */
+/* -------------------------------------------------------------------- */
+    CPLDebug( "OCI", "Truncate TABLE %s", pszLayerName );
+    
+/* -------------------------------------------------------------------- */
+/*      Truncate the layer in the database.                             */
 /* -------------------------------------------------------------------- */
     OGROCIStatement oCommand( poSession );
-    char            szCommand[1024];
+    CPLString       osCommand;
 
-    sprintf( szCommand, "DROP TABLE \"%s\"", pszLayerName );
-    oCommand.Execute( szCommand );
-
-    sprintf( szCommand, 
-             "DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = UPPER('%s')",
-             pszLayerName );
-    oCommand.Execute( szCommand );
-
-    CPLFree( (char *) pszLayerName );
+    osCommand.Printf( "TRUNCATE TABLE \"%s\"", pszLayerName );
+    oCommand.Execute( osCommand );
 }
 
 /************************************************************************/
@@ -421,35 +464,45 @@ OGROCIDataSource::CreateLayer( const char * pszLayerName,
     char               *pszSafeLayerName = CPLStrdup(pszLayerName);
 
     poSession->CleanName( pszSafeLayerName );
+    CPLDebug( "OCI", "In Create Layer ..." );
+              
 
 /* -------------------------------------------------------------------- */
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
     int iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    
+    if( CSLFetchBoolean( papszOptions, "TRUNCATE", FALSE ) )
     {
-        if( EQUAL(pszSafeLayerName,
-                  papoLayers[iLayer]->GetLayerDefn()->GetName()) )
+        CPLDebug( "OCI", "Calling TruncateLayer for %s", pszLayerName );
+        TruncateLayer( pszSafeLayerName );
+    }
+    else
+    {  
+        for( iLayer = 0; iLayer < nLayers; iLayer++ )
         {
-            if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
-                && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
-            {
-                DeleteLayer( pszSafeLayerName );
-            }
-            else
+            if( EQUAL(pszSafeLayerName,
+                      papoLayers[iLayer]->GetLayerDefn()->GetName()) )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, 
-                          "Layer %s already exists, CreateLayer failed.\n"
-                          "Use the layer creation option OVERWRITE=YES to "
-                          "replace it.",
-                          pszSafeLayerName );
-                CPLFree( pszSafeLayerName );
-                return NULL;
+                if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
+                    && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
+                {
+                    DeleteLayer( pszSafeLayerName );
+                }
+                else
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, 
+                              "Layer %s already exists, CreateLayer failed.\n"
+                              "Use the layer creation option OVERWRITE=YES to "
+                              "replace it.",
+                              pszSafeLayerName );
+                    CPLFree( pszSafeLayerName );
+                    return NULL;
+                }              
             }
         }
-    }
+    } 
 
 /* -------------------------------------------------------------------- */
 /*      Try to get the SRS Id of this spatial reference system,         */
@@ -485,27 +538,30 @@ OGROCIDataSource::CreateLayer( const char * pszLayerName,
 /*      If geometry type is wkbNone, do not create a geoemtry column    */
 /* -------------------------------------------------------------------- */
 
-    if (eType == wkbNone)
-    {
-        sprintf( szCommand,
-             "CREATE TABLE \"%s\" ( "
-             "%s INTEGER)",
-             pszSafeLayerName, pszExpectedFIDName);
-    }
-    else
+    if ( CSLFetchNameValue( papszOptions, "TRUNCATE" ) == NULL  )
     {
-        sprintf( szCommand,
-             "CREATE TABLE \"%s\" ( "
-             "%s INTEGER, "
-             "%s %s )",
-             pszSafeLayerName, pszExpectedFIDName, pszGeometryName, SDO_GEOMETRY );
-    }
+        if (eType == wkbNone)
+        {
+            sprintf( szCommand,
+                     "CREATE TABLE \"%s\" ( "
+                     "%s INTEGER)",
+                     pszSafeLayerName, pszExpectedFIDName);
+        }
+        else
+        {
+            sprintf( szCommand,
+                     "CREATE TABLE \"%s\" ( "
+                     "%s INTEGER, "
+                     "%s %s )",
+                     pszSafeLayerName, pszExpectedFIDName, pszGeometryName, SDO_GEOMETRY );
+        }
 
-    if( oStatement.Execute( szCommand ) != CE_None )
-    {
-        CPLFree( pszSafeLayerName );
-        return NULL;
-    }
+        if( oStatement.Execute( szCommand ) != CE_None )
+        {
+            CPLFree( pszSafeLayerName );
+            return NULL;
+        }
+    }  
 
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
@@ -557,6 +613,8 @@ int OGROCIDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) && bDSUpdate )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCDeleteLayer) && bDSUpdate )
+        return TRUE;
     else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp b/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
index ab06237..46b1e64 100644
--- a/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrociloaderlayer.cpp 19871 2010-06-15 04:32:45Z ilucena $
+ * $Id: ogrociloaderlayer.cpp 22346 2011-05-10 03:02:15Z warmerdam $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCILoaderLayer class.  This implements
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociloaderlayer.cpp 19871 2010-06-15 04:32:45Z ilucena $");
+CPL_CVSID("$Id: ogrociloaderlayer.cpp 22346 2011-05-10 03:02:15Z warmerdam $");
 
 /************************************************************************/
 /*                         OGROCILoaderLayer()                          */
@@ -494,7 +494,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
     char szLength[9]; 
     size_t  nStringLen = strlen(oLine.GetString());
 
-    sprintf( szLength, "%08d", nStringLen-8 );
+    sprintf( szLength, "%08d", (int) (nStringLen-8) );
     strncpy( oLine.GetString(), szLength, 8 );
 
     if( VSIFWrite( oLine.GetString(), 1, nStringLen, fpData ) != nStringLen )
diff --git a/ogr/ogrsf_frmts/oci/ogrocisession.cpp b/ogr/ogrsf_frmts/oci/ogrocisession.cpp
index 1cf089f..d256147 100644
--- a/ogr/ogrsf_frmts/oci/ogrocisession.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocisession.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocisession.cpp 19000 2010-03-03 04:28:00Z ilucena $
+ * $Id: ogrocisession.cpp 22346 2011-05-10 03:02:15Z warmerdam $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of OGROCISession, which encapsulates much of the
@@ -31,7 +31,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocisession.cpp 19000 2010-03-03 04:28:00Z ilucena $");
+CPL_CVSID("$Id: ogrocisession.cpp 22346 2011-05-10 03:02:15Z warmerdam $");
 
 /************************************************************************/
 /*                          OGRGetOCISession()                          */
@@ -384,7 +384,7 @@ OGROCISession::GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Column length (%d) longer than column name buffer (%d) in\n"
                   "OGROCISession::GetParmInfo()", 
-                  nColLen, sizeof(szTermColName) );
+                  nColLen, (int) sizeof(szTermColName) );
         return CE_Failure;
     }
 
diff --git a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
index 25ad754..dae96a0 100644
--- a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrocitablelayer.cpp 22298 2011-05-04 21:18:48Z warmerdam $
+ * $Id: ogrocitablelayer.cpp 23102 2011-09-22 16:12:14Z ilucena $
  *
  * 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 22298 2011-05-04 21:18:48Z warmerdam $");
+CPL_CVSID("$Id: ogrocitablelayer.cpp 23102 2011-09-22 16:12:14Z ilucena $");
 
 static int nDiscarded = 0;
 static int nHits = 0;
@@ -106,10 +106,7 @@ OGROCITableLayer::~OGROCITableLayer()
 {
     int   i;
 
-    if( bNewLayer )
-        FinalizeNewLayer();
-    else
-        FlushPendingFeatures();
+    SyncToDisk();
 
     CPLFree( panWriteFIDs );
     if( papWriteFields != NULL )
@@ -160,15 +157,15 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
 /* -------------------------------------------------------------------- */
 /*      Split out the owner if available.                               */
 /* -------------------------------------------------------------------- */
-    const char *pszTableName = pszTable;
-    char *pszOwner = NULL;
-
-    if( strstr(pszTableName,".") != NULL )
+    if( strstr(pszTable,".") != NULL )
     {
-        pszOwner = CPLStrdup(pszTableName);
-        pszTableName = strstr(pszTableName,".") + 1;
-
-        *(strstr(pszOwner,".")) = '\0';
+        osTableName = strstr(pszTable,".") + 1;
+        osOwner.assign( pszTable, strlen(pszTable)-osTableName.size() - 1 );
+    }
+    else
+    {
+        osTableName = pszTable;
+        osOwner = "";
     }
 
 /* -------------------------------------------------------------------- */
@@ -267,11 +264,13 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
         char **papszResult;
         int iDim = -1;
 
-        oDimCmd.Append( "SELECT a." );
-        oDimCmd.Append( pszGeomName  );
-        oDimCmd.Append( ".GET_DIMS() DIM FROM " );
-        oDimCmd.Append( pszTableName );
-        oDimCmd.Append( " a WHERE ROWNUM = 1" );
+		oDimCmd.Append( "SELECT COUNT(*) FROM ALL_SDO_GEOM_METADATA u," );
+		oDimCmd.Append( "  TABLE(u.diminfo) t" );
+		oDimCmd.Append( "  WHERE u.table_name = '" );
+		oDimCmd.Append( osTableName );
+		oDimCmd.Append( "' AND u.column_name = '" );
+		oDimCmd.Append( pszGeomName  );
+		oDimCmd.Append( "'" );
 
         oDimStatement.Execute( oDimCmd.GetString() );
 
@@ -283,13 +282,15 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
             OGROCIStatement oDimStatement2( poSession );
             char **papszResult2;
 
+            CPLErrorReset();
+			
             oDimCmd2.Appendf( 1024,
                 "select m.sdo_index_dims\n"
                 "from   all_sdo_index_metadata m, all_sdo_index_info i\n"
                 "where  i.index_name = m.sdo_index_name\n"
                 "   and i.sdo_index_owner = m.sdo_index_owner\n"
                 "   and i.table_name = upper('%s')",
-                pszTableName );
+                osTableName.c_str() );
 
             oDimStatement2.Execute( oDimCmd2.GetString() );
 
@@ -299,6 +300,11 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable )
             {
                 iDim = atoi( papszResult2[0] );
             }
+            else
+            {
+            	// we want to clear any errors to avoid confusing the application.
+            	CPLErrorReset();
+            }
         }
         else
         {
@@ -758,12 +764,17 @@ OGRErr OGROCITableLayer::CreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Add extents of this geometry to the existing layer extents.     */
 /* -------------------------------------------------------------------- */
-   if( poFeature->GetGeometryRef() != NULL )
+    if( poFeature->GetGeometryRef() != NULL )
     {
         OGREnvelope  sThisExtent;
         
         poFeature->GetGeometryRef()->getEnvelope( &sThisExtent );
-        sExtent.Merge( sThisExtent );
+
+        if( !sExtent.Contains( sThisExtent ) )				
+        {
+            sExtent.Merge( sThisExtent );
+            bExtentUpdated = true;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1161,20 +1172,6 @@ OGRErr OGROCITableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     }
 
 /* -------------------------------------------------------------------- */
-/*      Split out the owner if available.                               */
-/* -------------------------------------------------------------------- */
-    const char *pszTableName = GetLayerDefn()->GetName();
-    char *pszOwner = NULL;
-
-    if( strstr(pszTableName,".") != NULL )
-    {
-        pszOwner = CPLStrdup(pszTableName);
-        pszTableName = strstr(pszTableName,".") + 1;
-
-        *(strstr(pszOwner,".")) = '\0';
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Build query command.                                        */
 /* -------------------------------------------------------------------- */
     CPLAssert( NULL != pszGeomName );
@@ -1188,24 +1185,23 @@ OGRErr OGROCITableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
                       "FROM ALL_SDO_GEOM_METADATA m, ",
                       pszGeomName, pszGeomName, pszGeomName, pszGeomName );
 
-    if( pszOwner != NULL )
+    if( osOwner != "" )
     {
         oCommand.Appendf( 500, " %s.%s t ",
-                          pszOwner, pszTableName );
+                          osOwner.c_str(), osTableName.c_str() );
     }
     else
     {
         oCommand.Appendf( 500, " %s t ",
-                          pszTableName );
+                          osTableName.c_str() );
     }
 
     oCommand.Appendf( 500, "WHERE m.TABLE_NAME = UPPER('%s') AND m.COLUMN_NAME = UPPER('%s')",
-                      pszTableName, pszGeomName );
+                      osTableName.c_str(), pszGeomName );
 
-    if( pszOwner != NULL )
+    if( osOwner != "" )
     {
-        oCommand.Appendf( 500, " AND OWNER = UPPER('%s')", pszOwner );
-        CPLFree( pszOwner );
+        oCommand.Appendf( 500, " AND OWNER = UPPER('%s')", osOwner.c_str() );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1242,7 +1238,7 @@ OGRErr OGROCITableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
         err = OGRLayer::GetExtent( psExtent, bForce );
         CPLDebug( "OCI", 
                   "Failing to query extent of %s using default GetExtent",
-                  pszTableName );
+                  osTableName.c_str() );
     }
 
     return err;
@@ -1313,34 +1309,77 @@ int OGROCITableLayer::GetFeatureCount( int bForce )
 }
 
 /************************************************************************/
-/*                          FinalizeNewLayer()                          */
-/*                                                                      */
-/*      Our main job here is to update the USER_SDO_GEOM_METADATA       */
-/*      table to include the correct array of dimension object with     */
-/*      the appropriate extents for this layer.  We may also do         */
-/*      spatial indexing at this point.                                 */
+/*                         UpdateLayerExtents()                         */
 /************************************************************************/
 
-void OGROCITableLayer::FinalizeNewLayer()
+void OGROCITableLayer::UpdateLayerExtents()
 
 {
-    OGROCIStringBuf  sDimUpdate;
+    if( !bExtentUpdated )
+        return;
 
-    FlushPendingFeatures();
+    bExtentUpdated = false;
 
 /* -------------------------------------------------------------------- */
-/*      If the dimensions are degenerate (all zeros) then we assume     */
-/*      there were no geometries, and we don't bother setting the       */
-/*      dimensions.                                                     */
+/*      Do we have existing layer extents we need to merge in to the    */
+/*      ones we collected as we created features?                       */
 /* -------------------------------------------------------------------- */
-    if( sExtent.MaxX == 0 && sExtent.MinX == 0
-        && sExtent.MaxY == 0 && sExtent.MinY == 0 )
+    bool bHaveOldExtent = false;
+
+    if( !bNewLayer && pszGeomName )
     {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "Layer %s appears to have no geometry ... not setting SDO DIMINFO metadata.", 
-                  poFeatureDefn->GetName() );
-        return;
-                  
+        OGROCIStringBuf oCommand;
+
+        oCommand.Appendf(1000, 
+                          "select min(case when r=1 then sdo_lb else null end) minx, min(case when r=2 then sdo_lb else null end) miny, " 
+                          "min(case when r=1 then sdo_ub else null end) maxx, min(case when r=2 then sdo_ub else null end) maxy" 
+                          " from (SELECT d.sdo_dimname, d.sdo_lb, sdo_ub, sdo_tolerance, rownum r" 
+                          " FROM ALL_SDO_GEOM_METADATA m, table(m.diminfo) d"  
+                          " where m.table_name = UPPER('%s') and m.COLUMN_NAME = UPPER('%s')", 
+                          osTableName.c_str(), pszGeomName ); 
+ 		 
+        if( osOwner != "" ) 
+        { 
+            oCommand.Appendf(500, " AND OWNER = UPPER('%s')", osOwner.c_str() ); 
+        } 
+ 		 
+        oCommand.Append(" ) ");
+
+        OGROCISession *poSession = poDS->GetSession();
+        CPLAssert( NULL != poSession );
+        
+        OGROCIStatement oGetExtent( poSession );
+        
+        if( oGetExtent.Execute( oCommand.GetString() ) == CE_None )
+        {
+            char **papszRow = oGetExtent.SimpleFetchRow();
+            
+            if( papszRow != NULL
+                && papszRow[0] != NULL && papszRow[1] != NULL
+                && papszRow[2] != NULL && papszRow[3] != NULL )
+            {
+                OGREnvelope sOldExtent;
+
+                bHaveOldExtent = true;
+
+                sOldExtent.MinX = CPLAtof(papszRow[0]);
+                sOldExtent.MinY = CPLAtof(papszRow[1]);
+                sOldExtent.MaxX = CPLAtof(papszRow[2]);
+                sOldExtent.MaxY = CPLAtof(papszRow[3]);
+
+                if( sOldExtent.Contains( sExtent ) )
+                {
+                    // nothing to do!
+                    sExtent = sOldExtent;
+                    bExtentUpdated = false;
+                    return;
+                }
+                else
+                {
+                    sExtent.Merge( sOldExtent );
+                }
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1370,107 +1409,157 @@ void OGROCITableLayer::FinalizeNewLayer()
     dfZMax = 100000.0;
     dfZRes = 0.002;
     ParseDIMINFO( "DIMINFO_Z", &dfZMin, &dfZMax, &dfZRes );
-    
+
 /* -------------------------------------------------------------------- */
-/*      Prepare dimension update statement.                             */
+/*      If we already have an extent in the table, we will need to      */
+/*      update it in place.                                             */
 /* -------------------------------------------------------------------- */
-    sDimUpdate.Append( "INSERT INTO USER_SDO_GEOM_METADATA VALUES " );
-    sDimUpdate.Appendf( strlen(poFeatureDefn->GetName()) + 100,
-                        "('%s', '%s', ",
-                        poFeatureDefn->GetName(),
-                        pszGeomName );
-
-    sDimUpdate.Append( "MDSYS.SDO_DIM_ARRAY(" );
-    sDimUpdate.Appendf(200,
-                       "MDSYS.SDO_DIM_ELEMENT('X',%.16g,%.16g,%.12g)",
-                       dfXMin, dfXMax, dfXRes );
-    sDimUpdate.Appendf(200,
-                       ",MDSYS.SDO_DIM_ELEMENT('Y',%.16g,%.16g,%.12g)",
-                       dfYMin, dfYMax, dfYRes );
-
-    if( nDimension == 3 )
+    OGROCIStringBuf  sDimUpdate;
+
+    if( bHaveOldExtent )
     {
+        sDimUpdate.Append( "UPDATE USER_SDO_GEOM_METADATA " );
+        sDimUpdate.Append( "SET DIMINFO =" );
+        sDimUpdate.Append( "MDSYS.SDO_DIM_ARRAY(" );
         sDimUpdate.Appendf(200,
-                           ",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
-                           dfZMin, dfZMax, dfZRes );
-    }
+                           "MDSYS.SDO_DIM_ELEMENT('X',%.16g,%.16g,%.12g)",
+                           dfXMin, dfXMax, dfXRes );
+        sDimUpdate.Appendf(200,
+                           ",MDSYS.SDO_DIM_ELEMENT('Y',%.16g,%.16g,%.12g)",
+                           dfYMin, dfYMax, dfYRes );
 
-    if( nSRID == -1 )
-        sDimUpdate.Append( "), NULL)" );
+        if( nDimension == 3 )
+        {
+            sDimUpdate.Appendf(200,
+                               ",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
+                               dfZMin, dfZMax, dfZRes );
+        }      
+    
+        sDimUpdate.Appendf(strlen(poFeatureDefn->GetName()) + 100,") WHERE TABLE_NAME = '%s'", poFeatureDefn->GetName());    
+        
+    } 
     else
-        sDimUpdate.Appendf( 100, "), %d)", nSRID );
+    {	  
+/* -------------------------------------------------------------------- */
+/*      Prepare dimension update statement.                             */
+/* -------------------------------------------------------------------- */
+        sDimUpdate.Append( "INSERT INTO USER_SDO_GEOM_METADATA VALUES " );
+        sDimUpdate.Appendf( strlen(poFeatureDefn->GetName()) + 100,
+                            "('%s', '%s', ",
+                            poFeatureDefn->GetName(),
+                            pszGeomName );
+
+        sDimUpdate.Append( "MDSYS.SDO_DIM_ARRAY(" );
+        sDimUpdate.Appendf(200,
+                           "MDSYS.SDO_DIM_ELEMENT('X',%.16g,%.16g,%.12g)",
+                           dfXMin, dfXMax, dfXRes );
+        sDimUpdate.Appendf(200,
+                           ",MDSYS.SDO_DIM_ELEMENT('Y',%.16g,%.16g,%.12g)",
+                           dfYMin, dfYMax, dfYRes );
+
+        if( nDimension == 3 )
+        {
+            sDimUpdate.Appendf(200,
+                               ",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
+                               dfZMin, dfZMax, dfZRes );
+        }
+
+        if( nSRID == -1 )
+            sDimUpdate.Append( "), NULL)" );
+        else
+            sDimUpdate.Appendf( 100, "), %d)", nSRID );
+    }
 
 /* -------------------------------------------------------------------- */
-/*      Execute the metadata update.                                    */
+/*      Run the update/insert command.                                  */
 /* -------------------------------------------------------------------- */
     OGROCIStatement oExecStatement( poDS->GetSession() );
+    
+    oExecStatement.Execute( sDimUpdate.GetString() );
+}
 
-    if( oExecStatement.Execute( sDimUpdate.GetString() ) != CE_None )
-        return;
+/************************************************************************/
+/*                          FinalizeNewLayer()                          */
+/*                                                                      */
+/*      Our main job here is to update the USER_SDO_GEOM_METADATA       */
+/*      table to include the correct array of dimension object with     */
+/*      the appropriate extents for this layer.  We may also do         */
+/*      spatial indexing at this point.                                 */
+/************************************************************************/
+
+void OGROCITableLayer::FinalizeNewLayer()
 
+{
+    UpdateLayerExtents();
+
+/* -------------------------------------------------------------------- */
+/*      For new layers we try to create a spatial index.                */
+/* -------------------------------------------------------------------- */
+    if( bNewLayer && sExtent.IsInit() )
+    {
 /* -------------------------------------------------------------------- */
 /*      If the user has disabled INDEX support then don't create the    */
 /*      index.                                                          */
 /* -------------------------------------------------------------------- */
-    if( !CSLFetchBoolean( papszOptions, "INDEX", TRUE ) )
-        return;
+        if( !CSLFetchBoolean( papszOptions, "INDEX", TRUE ) )
+            return;
 
 /* -------------------------------------------------------------------- */
 /*      Establish an index name.  For some reason Oracle 8.1.7 does     */
 /*      not support spatial index names longer than 18 characters so    */
 /*      we magic up an index name if it would be too long.              */
 /* -------------------------------------------------------------------- */
-    char  szIndexName[20];
+        char  szIndexName[20];
 
-    if( strlen(poFeatureDefn->GetName()) < 15 )
-        sprintf( szIndexName, "%s_idx", poFeatureDefn->GetName() );
-    else if( strlen(poFeatureDefn->GetName()) < 17 )
-        sprintf( szIndexName, "%si", poFeatureDefn->GetName() );
-    else
-    {
-        int i, nHash = 0;
-        const char *pszSrcName = poFeatureDefn->GetName();
+        if( strlen(poFeatureDefn->GetName()) < 15 )
+            sprintf( szIndexName, "%s_idx", poFeatureDefn->GetName() );
+        else if( strlen(poFeatureDefn->GetName()) < 17 )
+            sprintf( szIndexName, "%si", poFeatureDefn->GetName() );
+        else
+        {
+            int i, nHash = 0;
+            const char *pszSrcName = poFeatureDefn->GetName();
 
-        for( i = 0; pszSrcName[i] != '\0'; i++ )
-            nHash = (nHash + i * pszSrcName[i]) % 987651;
+            for( i = 0; pszSrcName[i] != '\0'; i++ )
+                nHash = (nHash + i * pszSrcName[i]) % 987651;
         
-        sprintf( szIndexName, "OSI_%d", nHash );
-    }
+            sprintf( szIndexName, "OSI_%d", nHash );
+        }
 
-    poDS->GetSession()->CleanName( szIndexName );
+        poDS->GetSession()->CleanName( szIndexName );
 
 /* -------------------------------------------------------------------- */
 /*      Try creating an index on the table now.  Use a simple 5         */
 /*      level quadtree based index.  Would R-tree be a better default?  */
 /* -------------------------------------------------------------------- */
+        OGROCIStringBuf  sIndexCmd;
+        OGROCIStatement oExecStatement( poDS->GetSession() );
+    
 
-// Disable for now, spatial index creation always seems to cause me to 
-// lose my connection to the database!
-    OGROCIStringBuf  sIndexCmd;
-
-    sIndexCmd.Appendf( 10000, "CREATE INDEX \"%s\" ON %s(\"%s\") "
-                       "INDEXTYPE IS MDSYS.SPATIAL_INDEX ",
-                       szIndexName, 
-                       poFeatureDefn->GetName(), 
-                       pszGeomName );
+        sIndexCmd.Appendf( 10000, "CREATE INDEX \"%s\" ON %s(\"%s\") "
+                           "INDEXTYPE IS MDSYS.SPATIAL_INDEX ",
+                           szIndexName, 
+                           poFeatureDefn->GetName(), 
+                           pszGeomName );
 
-    if( CSLFetchNameValue( papszOptions, "INDEX_PARAMETERS" ) != NULL )
-    {
-        sIndexCmd.Append( " PARAMETERS( '" );
-        sIndexCmd.Append( CSLFetchNameValue(papszOptions,"INDEX_PARAMETERS") );
-        sIndexCmd.Append( "' )" );
-    }
+        if( CSLFetchNameValue( papszOptions, "INDEX_PARAMETERS" ) != NULL )
+        {
+            sIndexCmd.Append( " PARAMETERS( '" );
+            sIndexCmd.Append( CSLFetchNameValue(papszOptions,"INDEX_PARAMETERS") );
+            sIndexCmd.Append( "' )" );
+        }
 
-    if( oExecStatement.Execute( sIndexCmd.GetString() ) != CE_None )
-    {
-        char szDropCommand[2000];
-        sprintf( szDropCommand, "DROP INDEX \"%s\"", szIndexName );
-        oExecStatement.Execute( szDropCommand );
-    }
+        if( oExecStatement.Execute( sIndexCmd.GetString() ) != CE_None )
+        {
+            CPLString osDropCommand;
+            osDropCommand.Printf( "DROP INDEX \"%s\"", szIndexName );
+            oExecStatement.Execute( osDropCommand );
+        }
+    }  
 }
 
 /************************************************************************/
-/*                        AllocAndBindForWrite(int eType)                        */
+/*                   AllocAndBindForWrite(int eType)                    */
 /************************************************************************/
 
 /* -------------------------------------------------------------------- */
@@ -1905,6 +1994,10 @@ OGRErr OGROCITableLayer::FlushPendingFeatures()
 OGRErr OGROCITableLayer::SyncToDisk()
 
 {
-    return FlushPendingFeatures();
+    OGRErr eErr = FlushPendingFeatures();
+
+    UpdateLayerExtents();
+
+    return eErr;
 }
 
diff --git a/ogr/ogrsf_frmts/ogdi/drv_ogdi.html b/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
index 8bd3f6f..77e05d4 100644
--- a/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
+++ b/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
@@ -18,6 +18,8 @@ supported for read access for the following family types:
 </ul>
 <p>
 
+OGDI can (among other formats) read VPF products, such as DCW and VMAP.<p>
+
 If an OGDI gltp url is opened directly the OGDI 3.1 capabilities for the
 driver/server are queried to get a list of layers.  One OGR layer is created
 for each OGDI family available for each layer in the datastore.  For drivers
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
index de1c174..71cda9e 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdilayer.cpp 20207 2010-08-06 22:07:29Z rouault $
+ * $Id: ogrogdilayer.cpp 23014 2011-08-31 18:40:35Z rouault $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDILayer class.
@@ -56,7 +56,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrogdilayer.cpp 20207 2010-08-06 22:07:29Z rouault $");
+CPL_CVSID("$Id: ogrogdilayer.cpp 23014 2011-08-31 18:40:35Z rouault $");
 
 /************************************************************************/
 /*                           OGROGDILayer()                            */
@@ -381,7 +381,14 @@ OGRFeature *OGROGDILayer::GetFeature( long nFeatureId )
     if (m_nTotalShapeCount != -1 && nFeatureId > m_nTotalShapeCount)
         return NULL;
 
-    if (m_iNextShapeId > nFeatureId )
+    /* Reset reading if we are not the current layer */
+    /* WARNING : this does not allow interleaved reading of layers */
+    if( m_poODS->GetCurrentLayer() != this )
+    {
+        m_poODS->SetCurrentLayer(this);
+        ResetReading();
+    }
+    else if ( nFeatureId < m_iNextShapeId )
         ResetReading();
 
     while(m_iNextShapeId != nFeatureId)
diff --git a/ogr/ogrsf_frmts/ogr_formats.html b/ogr/ogrsf_frmts/ogr_formats.html
index f85cdbf..08e54dd 100644
--- a/ogr/ogrsf_frmts/ogr_formats.html
+++ b/ogr/ogrsf_frmts/ogr_formats.html
@@ -45,6 +45,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_arcgen.html">Arc/Info Generate</a>
+</td><td> ARCGEN
+</td><td> No
+</td><td> No
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="drv_bna.html">Atlas BNA</a>
 </td><td> BNA
 </td><td> Yes
@@ -52,6 +59,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_dwg.html">AutoCAD DWG</a>
+</td><td> DWG
+</td><td> No
+</td><td> No
+</td><td> No
+</td></tr>
+
 <tr><td> <a href="drv_dxf.html">AutoCAD DXF</a>
 </td><td> DXF
 </td><td> Yes
@@ -66,6 +80,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_couchdb.html">CouchDB / GeoCouch</a>
+</td><td> CouchDB
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs libcurl
+</td></tr>
+
 <tr><td> <a href="drv_dods.html">DODS/OPeNDAP</a>
 </td><td> DODS
 </td><td> No
@@ -73,6 +94,20 @@
 </td><td> No, needs libdap
 </td></tr>
 
+<tr><td> <a href="drv_edigeo.html">EDIGEO</a>
+</td><td> EDIGEO
+</td><td> No
+</td><td> Yes
+</td><td> Yes
+</td></tr>
+
+<tr><td> <a href="drv_filegdb.html">ESRI FileGDB</a>
+</td><td> FileGDB
+</td><td> Yes
+</td><td> Yes
+</td><td> No, needs FileGDB API library
+</td></tr>
+
 <tr><td> <a href="drv_pgeo.html">ESRI Personal GeoDatabase</a>
 </td><td> PGeo
 </td><td> No
@@ -115,6 +150,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_geomedia.html">Geomedia .mdb</a>
+</td><td> Geomedia
+</td><td> No
+</td><td> No
+</td><td> No, needs ODBC library
+</td></tr>
+
 <tr><td> <a href="drv_georss.html">GeoRSS</a>
 </td><td> GeoRSS
 </td><td> Yes
@@ -122,6 +164,13 @@
 </td><td> Yes (read support needs libexpat)
 </td></tr>
 
+<tr><td> <a href="drv_gft.html">Google Fusion Tables</a>
+</td><td> GFT
+</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
@@ -171,6 +220,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_idrisi.html">Idrisi Vector (.VCT)</a>
+</td><td> Idrisi
+</td><td> No
+</td><td> Yes
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="drv_idb.html">Informix DataBlade</a>
 </td><td> IDB
 </td><td> Yes
@@ -221,6 +277,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_mdb.html">Access MDB (PGeo and Geomedia capable)</a>
+</td><td> MDB
+</td><td> No
+</td><td> Yes
+</td><td> No, needs JDK/JRE
+</td></tr>
+
 <tr><td> <a href="drv_memory.html">Memory</a>
 </td><td> Memory
 </td><td> Yes
@@ -263,7 +326,7 @@
 </td><td> No, needs ODBC library
 </td></tr>
 
-<tr><td> <a href="drv_ogdi.html">OGDI Vectors</a>
+<tr><td> <a href="drv_ogdi.html">OGDI Vectors (VPF, VMAP, DCW)</a>
 </td><td> OGDI
 </td><td> No
 </td><td> Yes
@@ -326,6 +389,20 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_segukooa.html">SEG-P1 / UKOOA P1/90</a>
+</td><td> SEGUKOOA
+</td><td> No
+</td><td> Yes
+</td><td> Yes
+</td></tr>
+
+<tr><td> <a href="drv_segy.html">SEG-Y</a>
+</td><td> SEGY
+</td><td> No
+</td><td> No
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="http://trac.osgeo.org/gdal/ticket/3638">Norwegian SOSI Standard</a>
 </td><td> SOSI
 </td><td> No
@@ -347,6 +424,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_svg.html">SVG</a>
+</td><td> SVG
+</td><td> No
+</td><td> Yes
+</td><td> No, needs libexpat
+</td></tr>
+
 <tr><td> <a href="drv_ntf.html">UK .NTF</a>
 </td><td> UK. NTF
 </td><td> No
@@ -377,11 +461,18 @@
 
 <tr><td> <a href="drv_wfs.html">OGC WFS (Web Feature Service)</a>
 </td><td> WFS
-</td><td> No
+</td><td> Yes
 </td><td> Yes
 </td><td> No, needs libcurl
 </td></tr>
 
+<tr><td> <a href="drv_xls.html">MS Excel format</a>
+</td><td> XLS
+</td><td> No
+</td><td> No
+</td><td> No, needs libfreexl
+</td></tr>
+
 <tr><td> <a href="drv_xplane.html">X-Plane/Flighgear aeronautical data</a>
 </td><td> XPLANE
 </td><td> No
@@ -393,5 +484,3 @@
 
 </body>
 </html>
-
-
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.dox b/ogr/ogrsf_frmts/ogrsf_frmts.dox
index 81c73a8..097e9e9 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.dox
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.dox
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.dox 21018 2010-10-30 11:30:51Z rouault $
+ * $Id: ogrsf_frmts.dox 22368 2011-05-13 17:59:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Documentation for ogrsf_frmts.h classes.
@@ -46,6 +46,10 @@
   If this method fails, CPLGetLastErrorMsg() can be used to check if there
   is an error message explaining why.
 
+  For drivers supporting the VSI virtual file API, it is possible to open
+  a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
+  (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+ 
   This method is the same as the C function OGROpen().
 
   @param pszName the name of the file, or data source to open. UTF-8 encoded.
@@ -93,6 +97,10 @@
   If this function fails, CPLGetLastErrorMsg() can be used to check if there
   is an error message explaining why.
 
+  For drivers supporting the VSI virtual file API, it is possible to open
+  a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
+  (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+
   This function is the same as the C++ method OGRSFDriverRegistrar::Open().
 
   @param pszName the name of the file, or data source to open.
@@ -370,6 +378,10 @@
   if GetDriver() is called on the datasource.  The application may directly
   call SetDriver() after opening with this method to avoid this problem.
 
+  For drivers supporting the VSI virtual file API, it is possible to open
+  a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
+  (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+
   This method is the same as the C function OGR_Dr_Open().
 
   @param pszName the name of the file, or data source to try and open.
@@ -2092,6 +2104,15 @@ 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>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
+existing fields on the current layer using DeleteField(), otherwise FALSE.<p>
+
+ <li> <b>OLCReorderFields</b> / "ReorderFields": TRUE if this layer can reorder
+existing fields on the current layer using ReorderField() or ReorderFields(), otherwise FALSE.<p>
+
+ <li> <b>OLCAlterFieldDefn</b> / "AlterFieldDefn": TRUE if this layer can alter
+the definition of an existing field on the current layer using AlterFieldDefn(), otherwise FALSE.<p>
+
  <li> <b>OLCDeleteFeature</b> / "DeleteFeature": TRUE if the DeleteFeature()
 method is supported on this layer, otherwise FALSE.<p>
 
@@ -2174,6 +2195,15 @@ 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>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
+existing fields on the current layer using DeleteField(), otherwise FALSE.<p>
+
+ <li> <b>OLCReorderFields</b> / "ReorderFields": TRUE if this layer can reorder
+existing fields on the current layer using ReorderField() or ReorderFields(), otherwise FALSE.<p>
+
+ <li> <b>OLCAlterFieldDefn</b> / "AlterFieldDefn": TRUE if this layer can alter
+the definition of an existing field on the current layer using AlterFieldDefn(), otherwise FALSE.<p>
+
  <li> <b>OLCDeleteFeature</b> / "DeleteFeature": TRUE if the DeleteFeature()
 method is supported on this layer, otherwise FALSE.<p>
 
@@ -2365,6 +2395,14 @@ 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 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 function OGR_L_CreateField().
 
 @param poField field definition to write to disk. 
@@ -2386,6 +2424,14 @@ 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.
@@ -2398,6 +2444,272 @@ form depending on the limitations of the format driver.
 */
 
 /**
+\fn OGRErr OGRLayer::DeleteField( int iField );
+
+\brief Delete an existing field on a layer.
+
+You must use this to delete existing fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the deleted 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 OLCDeleteField 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_DeleteField().
+
+ at param iField index of the field to delete.
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
+
+\fn OGRErr OGR_L_DeleteField( OGRLayerH hLayer, int iField);
+
+\brief Create a new field on a layer.
+
+You must use this to delete existing fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the deleted 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 OLCDeleteField 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::DeleteField().
+
+ at param hLayer handle to the layer.
+ at param iField index of the field to delete.
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
+\fn OGRErr OGRLayer::ReorderFields( int* panMap );
+
+\brief Reorder all the fields of a layer.
+
+You must use this to reorder existing fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the reordering of the fields.  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.
+
+panMap is such that,for each field definition at position i after reordering,
+its position before reordering was panMap[i].
+
+For example, let suppose the fields were "0","1","2","3","4" initially.
+ReorderFields([0,2,3,1,4]) will reorder them as "0","2","3","1","4".
+
+Not all drivers support this method. You can query a layer to check if it supports it
+with the OLCReorderFields 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_ReorderFields().
+
+ at param panMap an array of GetLayerDefn()->GetFieldCount() elements which
+is a permutation of [0, GetLayerDefn()->GetFieldCount()-1].
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
+
+\fn OGRErr OGR_L_ReorderFields( OGRLayerH hLayer, int* panMap );
+
+\brief Reorder all the fields of a layer.
+
+You must use this to reorder existing fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the reordering of the fields.  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.
+
+panMap is such that,for each field definition at position i after reordering,
+its position before reordering was panMap[i].
+
+For example, let suppose the fields were "0","1","2","3","4" initially.
+ReorderFields([0,2,3,1,4]) will reorder them as "0","2","3","1","4".
+
+Not all drivers support this function. You can query a layer to check if it supports it
+with the OLCReorderFields 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::ReorderFields().
+
+ at param hLayer handle to the layer.
+ at param panMap an array of GetLayerDefn()->GetFieldCount() elements which
+is a permutation of [0, GetLayerDefn()->GetFieldCount()-1].
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
+\fn OGRErr OGRLayer::ReorderField( int iOldFieldPos, int iNewFieldPos );
+
+\brief Reorder an existing field on a layer.
+
+This method is a conveniency wrapper of ReorderFields() dedicated to move a single field.
+It is a non-virtual method, so drivers should implement ReorderFields() instead.
+
+You must use this to reorder existing fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the reordering of the fields.  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.
+
+The field definition that was at initial position iOldFieldPos will be moved at
+position iNewFieldPos, and elements between will be shuffled accordingly.
+
+For example, let suppose the fields were "0","1","2","3","4" initially.
+ReorderField(1, 3) will reorder them as "0","2","3","1","4".
+
+Not all drivers support this method. You can query a layer to check if it supports it
+with the OLCReorderFields 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_ReorderField().
+
+ at param iOldFieldPos previous position of the field to move. Must be in the range [0,GetFieldCount()-1].
+ at param iNewFieldPos new position of the field to move. Must be in the range [0,GetFieldCount()-1].
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
+
+\fn OGRErr OGR_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos, int iNewFieldPos );
+
+\brief Reorder an existing field on a layer.
+
+This function is a conveniency wrapper of OGR_L_ReorderFields() dedicated to move a single field.
+
+You must use this to reorder existing fields
+on a real layer. Internally the OGRFeatureDefn for the layer will be updated
+to reflect the reordering of the fields.  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.
+
+The field definition that was at initial position iOldFieldPos will be moved at
+position iNewFieldPos, and elements between will be shuffled accordingly.
+
+For example, let suppose the fields were "0","1","2","3","4" initially.
+ReorderField(1, 3) will reorder them as "0","2","3","1","4".
+
+Not all drivers support this function. You can query a layer to check if it supports it
+with the OLCReorderFields 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::ReorderField().
+
+ at param hLayer handle to the layer.
+ at param iOldFieldPos previous position of the field to move. Must be in the range [0,GetFieldCount()-1].
+ at param iNewFieldPos new position of the field to move. Must be in the range [0,GetFieldCount()-1].
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
+\fn OGRErr OGRLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+
+\brief Alter the definition of an existing field on a layer.
+
+You must use this to alter the definition of an existing field of a real layer.
+Internally the OGRFeatureDefn for the layer will be updated
+to reflect the altered 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 OLCAlterFieldDefn 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. Some drivers might also not support
+all update flags.
+
+This function is the same as the C function OGR_L_AlterFieldDefn().
+
+ at param iField index of the field whose definition must be altered.
+ at param poNewFieldDefn new field definition
+ at param nFlags combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and ALTER_WIDTH_PRECISION_FLAG
+to indicate which of the name and/or type and/or width and precision fields from the new field
+definition must be taken into account.
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
+\fn OGRErr OGR_L_AlterFieldDefn( OGRLayerH hLayer, int iField, OGRFieldDefnH hNewFieldDefn, int nFlags )
+
+\brief Alter the definition of an existing field on a layer.
+
+You must use this to alter the definition of an existing field of a real layer.
+Internally the OGRFeatureDefn for the layer will be updated
+to reflect the altered 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 OLCAlterFieldDefn 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. Some drivers might also not support
+all update flags.
+
+This function is the same as the C++ method OGRLayer::AlterFieldDefn().
+
+ at param hLayer handle to the layer.
+ at param iField index of the field whose definition must be altered.
+ at param hNewFieldDefn new field definition
+ at param nFlags combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and ALTER_WIDTH_PRECISION_FLAG
+to indicate which of the name and/or type and/or width and precision fields from the new field
+definition must be taken into account.
+
+ at return OGRERR_NONE on success.
+
+ at since OGR 1.9.0
+*/
+
+/**
  \fn  void OGRLayer::GetStyleTable();
 
  \brief Returns layer style table.
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.h b/ogr/ogrsf_frmts/ogrsf_frmts.h
index a0a84ff..376d46f 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.h
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.h 21372 2011-01-01 23:53:54Z rouault $
+ * $Id: ogrsf_frmts.h 23554 2011-12-12 18:10:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to format registration, and file opening.
@@ -95,6 +95,9 @@ class CPL_DLL OGRLayer
 
     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();
 
@@ -117,7 +120,12 @@ class CPL_DLL OGRLayer
     int                 GetRefCount() const;
 
     GIntBig             GetFeaturesRead();
-    
+
+    /* non virtual : conveniency wrapper for ReorderFields() */
+    OGRErr              ReorderField( int iOldFieldPos, int iNewFieldPos );
+
+    int                 AttributeFilterEvaluationNeedsGeometry();
+
     /* consider these private */
     OGRErr               InitializeIndexSupport( const char * );
     OGRLayerAttrIndex   *GetIndex() { return m_poAttrIndex; }
@@ -201,6 +209,11 @@ class CPL_DLL OGRDataSource
 
     OGRErr              ProcessSQLCreateIndex( const char * );
     OGRErr              ProcessSQLDropIndex( const char * );
+    OGRErr              ProcessSQLDropTable( const char * );
+    OGRErr              ProcessSQLAlterTableAddColumn( const char * );
+    OGRErr              ProcessSQLAlterTableDropColumn( const char * );
+    OGRErr              ProcessSQLAlterTableAlterColumn( const char * );
+    OGRErr              ProcessSQLAlterTableRenameColumn( const char * );
 
     OGRStyleTable      *m_poStyleTable;
     int                 m_nRefCount;
@@ -297,6 +310,7 @@ class CPL_DLL OGRSFDriverRegistrar
 CPL_C_START
 void CPL_DLL OGRRegisterAll();
 
+void CPL_DLL RegisterOGRFileGDB();
 void CPL_DLL RegisterOGRShape();
 void CPL_DLL RegisterOGRNTF();
 void CPL_DLL RegisterOGRFME();
@@ -330,6 +344,7 @@ void CPL_DLL RegisterOGRGRASS();
 void CPL_DLL RegisterOGRPGeo();
 void CPL_DLL RegisterOGRDXFDWG();
 void CPL_DLL RegisterOGRDXF();
+void CPL_DLL RegisterOGRDWG();
 void CPL_DLL RegisterOGRSDE();
 void CPL_DLL RegisterOGRIDB();
 void CPL_DLL RegisterOGRGMT();
@@ -352,6 +367,17 @@ void CPL_DLL RegisterOGRWFS();
 void CPL_DLL RegisterOGRSOSI();
 void CPL_DLL RegisterOGRHTF();
 void CPL_DLL RegisterOGRAeronavFAA();
+void CPL_DLL RegisterOGRGeomedia();
+void CPL_DLL RegisterOGRMDB();
+void CPL_DLL RegisterOGREDIGEO();
+void CPL_DLL RegisterOGRGFT();
+void CPL_DLL RegisterOGRSVG();
+void CPL_DLL RegisterOGRCouchDB();
+void CPL_DLL RegisterOGRIdrisi();
+void CPL_DLL RegisterOGRARCGEN();
+void CPL_DLL RegisterOGRSEGUKOOA();
+void CPL_DLL RegisterOGRSEGY();
+void CPL_DLL RegisterOGRXLS();
 CPL_C_END
 
 
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
index 7ee79a3..e3e577f 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenairdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogropenairdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirDataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogropenairdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogropenairdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
 
 /************************************************************************/
 /*                        OGROpenAirDataSource()                        */
@@ -97,15 +97,6 @@ int OGROpenAirDataSource::Open( const char * pszFilename, int bUpdateIn)
 
     pszName = CPLStrdup( pszFilename );
 
-/* -------------------------------------------------------------------- */
-/*      Determine what sort of object this is.                          */
-/* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
-
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 ||
-        !VSI_ISREG(sStatBuf.st_mode) )
-        return FALSE;
-    
 // -------------------------------------------------------------------- 
 //      Does this appear to be an openair file?
 // --------------------------------------------------------------------
diff --git a/ogr/ogrsf_frmts/pcidsk/ogrpcidskdatasource.cpp b/ogr/ogrsf_frmts/pcidsk/ogrpcidskdatasource.cpp
index 8f9cac1..7e61496 100644
--- a/ogr/ogrsf_frmts/pcidsk/ogrpcidskdatasource.cpp
+++ b/ogr/ogrsf_frmts/pcidsk/ogrpcidskdatasource.cpp
@@ -34,6 +34,8 @@
 
 CPL_CVSID("$Id: ogrcsvdatasource.cpp 17806 2009-10-13 17:27:54Z rouault $");
 
+const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
+
 /************************************************************************/
 /*                        OGRPCIDSKDataSource()                         */
 /************************************************************************/
@@ -102,7 +104,10 @@ int OGRPCIDSKDataSource::Open( const char * pszFilename, int bUpdateIn )
         return FALSE;
 
     osName = pszFilename;
-    bUpdate = bUpdateIn;
+    if( bUpdateIn )
+        bUpdate = true;
+    else
+        bUpdate = false;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file, and create layer for each vector segment.        */
@@ -115,7 +120,8 @@ int OGRPCIDSKDataSource::Open( const char * pszFilename, int bUpdateIn )
         if( bUpdateIn )
             pszAccess = "r+";
 
-        poFile = PCIDSK::Open( pszFilename, pszAccess, NULL );
+        poFile = PCIDSK::Open( pszFilename, pszAccess,
+                               PCIDSK2GetInterfaces() );
 
         for( segobj = poFile->GetSegment( PCIDSK::SEG_VEC, "" );
              segobj != NULL;
@@ -124,6 +130,10 @@ int OGRPCIDSKDataSource::Open( const char * pszFilename, int bUpdateIn )
         {
             apoLayers.push_back( new OGRPCIDSKLayer( segobj, bUpdate ) );
         }
+
+        /* Check if this is a raster-only PCIDSK file */
+        if ( !bUpdate && apoLayers.size() == 0 && poFile->GetChannels() != 0 )
+            return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -142,10 +152,6 @@ int OGRPCIDSKDataSource::Open( const char * pszFilename, int bUpdateIn )
         return FALSE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      We presume that this is indeed intended to be a PCIDSK          */
-/*      datasource if over half the files were .csv files.              */
-/* -------------------------------------------------------------------- */
     return TRUE;
 }
 
diff --git a/ogr/ogrsf_frmts/pcidsk/ogrpcidskdriver.cpp b/ogr/ogrsf_frmts/pcidsk/ogrpcidskdriver.cpp
index c72ad53..50c9457 100644
--- a/ogr/ogrsf_frmts/pcidsk/ogrpcidskdriver.cpp
+++ b/ogr/ogrsf_frmts/pcidsk/ogrpcidskdriver.cpp
@@ -32,6 +32,8 @@
 
 CPL_CVSID("$Id: ogrcsvdriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
 
+const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
+
 /************************************************************************/
 /*                          ~OGRPCIDSKDriver()                          */
 /************************************************************************/
@@ -84,7 +86,8 @@ OGRDataSource *OGRPCIDSKDriver::CreateDataSource( const char * pszName,
         PCIDSK::PCIDSKFile *poFile;
 
         // at some point we should use gdal/frmts/pcidsk io interface.
-        poFile = PCIDSK::Create( pszName, 512, 512, 0, NULL, "BAND", NULL );
+        poFile = PCIDSK::Create( pszName, 512, 512, 0, NULL, "BAND", 
+                                 PCIDSK2GetInterfaces() );
         delete poFile;
 
         // TODO: should we ensure this driver gets used?
diff --git a/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp b/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp
index 1b29986..8b49432 100644
--- a/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp
+++ b/ogr/ogrsf_frmts/pcidsk/ogrpcidsklayer.cpp
@@ -177,7 +177,8 @@ OGRPCIDSKLayer::~OGRPCIDSKLayer()
 
     poFeatureDefn->Release();
 
-    delete poSRS;
+    if (poSRS)
+        poSRS->Release();
 }
 
 /************************************************************************/
@@ -326,10 +327,13 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( long nFID )
         {
             if( aoVertices.size() == 1 )
             {
-                poFeature->SetGeometryDirectly(
-                    new OGRPoint( aoVertices[0].x, 
+                OGRPoint* poPoint =
+                    new OGRPoint( aoVertices[0].x,
                                   aoVertices[0].y, 
-                                  aoVertices[0].z ) );
+                                  aoVertices[0].z );
+                if (poSRS)
+                    poPoint->assignSpatialReference(poSRS);
+                poFeature->SetGeometryDirectly(poPoint);
             }
             else
             {
@@ -357,6 +361,8 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( long nFID )
                                     aoVertices[i].x, 
                                     aoVertices[i].y, 
                                     aoVertices[i].z );
+                if (poSRS)
+                    poLS->assignSpatialReference(poSRS);
 
                 poFeature->SetGeometryDirectly( poLS );
             }
@@ -409,6 +415,9 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( long nFID )
                 poPoly->addRingDirectly( poRing );
             }
 
+            if (poSRS)
+                poPoly->assignSpatialReference(poSRS);
+
             poFeature->SetGeometryDirectly( poPoly );
         }    
     }
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
index 63921d0..0ad1bc2 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpdsdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrpdsdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSDataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrpdsdatasource.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrpdsdatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
 
 /************************************************************************/
 /*                           OGRPDSDataSource()                         */
@@ -284,16 +284,7 @@ int OGRPDSDataSource::Open( const char * pszFilename, int bUpdateIn)
 
     pszName = CPLStrdup( pszFilename );
 
-/* -------------------------------------------------------------------- */
-/*      Determine what sort of object this is.                          */
-/* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
-
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 ||
-        !VSI_ISREG(sStatBuf.st_mode) )
-        return FALSE;
-    
-// -------------------------------------------------------------------- 
+// --------------------------------------------------------------------
 //      Does this appear to be a .PDS table file?
 // --------------------------------------------------------------------
 
diff --git a/ogr/ogrsf_frmts/pg/GNUmakefile b/ogr/ogrsf_frmts/pg/GNUmakefile
index c9d8d53..e393d6e 100644
--- a/ogr/ogrsf_frmts/pg/GNUmakefile
+++ b/ogr/ogrsf_frmts/pg/GNUmakefile
@@ -3,7 +3,7 @@
 include ../../../GDALmake.opt
 
 OBJ	=	ogrpgdriver.o ogrpgdatasource.o ogrpglayer.o ogrpgtablelayer.o\
-		ogrpgresultlayer.o ogrpgdebug.o
+		ogrpgresultlayer.o ogrpgutility.o
 
 CPPFLAGS	:=	$(GDAL_INCLUDE) $(PG_INC) $(CPPFLAGS)
 
diff --git a/ogr/ogrsf_frmts/pg/drv_pg.html b/ogr/ogrsf_frmts/pg/drv_pg.html
index 1e778fa..cd52697 100644
--- a/ogr/ogrsf_frmts/pg/drv_pg.html
+++ b/ogr/ogrsf_frmts/pg/drv_pg.html
@@ -118,6 +118,9 @@ to speed up queries. Set to OFF to disable. (Has effect only when PostGIS is ava
 <li> <b>NONE_AS_UNKNOWN</b>: (From GDAL 1.8.1) Can bet set to TRUE to force non-spatial layers (wkbNone) to be created as
 spatial tables of type GEOMETRY (wkbUnknown), which was the behaviour prior to GDAL 1.8.0. Defaults to NO, in which case
 a regular table is created and not recorded in the PostGIS geometry_columns table.<p>
+<li> <b>FID</b>: (From GDAL 1.9.0) Name of the FID column to create. Defaults to 'ogc_fid'.<p>
+<li> <b>EXTRACT_SCHEMA_FROM_LAYER_NAME</b>: (From GDAL 1.9.0) Can be set to NO to avoid considering the dot character
+as the separator between the schema and the table name. Defaults to YES.<p>
 </ul>
 
 <h3>Configuration Options</h3>
@@ -129,7 +132,8 @@ 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>
-<li><b>PGSQL_OGR_FID</b>: Set name of primary key instead of 'ogc_fid' (read-only, ignored by CreateLayer()).</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 -->
 <!-- <li><b>PG_USE_TEXT</b>: (GDAL >= 1.8.0) If set to "YES", geometries will be fetched as text instead of their default HEXEWKB form.</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.
diff --git a/ogr/ogrsf_frmts/pg/makefile.vc b/ogr/ogrsf_frmts/pg/makefile.vc
index 31e6e74..c3d5609 100755
--- a/ogr/ogrsf_frmts/pg/makefile.vc
+++ b/ogr/ogrsf_frmts/pg/makefile.vc
@@ -1,6 +1,6 @@
 
 OBJ	=	ogrpgdriver.obj ogrpgdatasource.obj ogrpglayer.obj \
-		ogrpgtablelayer.obj ogrpgresultlayer.obj ogrpgdebug.obj
+		ogrpgtablelayer.obj ogrpgresultlayer.obj ogrpgutility.obj
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/pg/ogr_pg.h b/ogr/ogrsf_frmts/pg/ogr_pg.h
index 353f40f..11ade95 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 21037 2010-11-01 12:59:54Z rouault $
+ * $Id: ogr_pg.h 23652 2011-12-29 09:33:53Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL driver.
@@ -34,10 +34,7 @@
 #include "libpq-fe.h"
 #include "cpl_string.h"
 
-#ifdef DEBUG
-PGresult *OGRPG_PQexec_dbg(PGconn *conn, const char *query);
-#define PQexec OGRPG_PQexec_dbg
-#endif
+#include "ogrpgutility.h"
 
 /* These are the OIDs for some builtin types, as returned by PQftype(). */
 /* They were copied from pg_type.h in src/include/catalog/pg_type.h */
@@ -76,6 +73,9 @@ PGresult *OGRPG_PQexec_dbg(PGconn *conn, const char *query);
 CPLString OGRPGEscapeString(PGconn *hPGConn,
                             const char* pszStrValue, int nMaxLength,
                             const char* pszFieldName);
+CPLString OGRPGEscapeColumnName(const char* pszColumnName);
+
+#define UNDETERMINED_SRID       -2 /* Special value when we haven't yet looked for SRID */
 
 /************************************************************************/
 /*                            OGRPGLayer                                */
@@ -112,7 +112,6 @@ class OGRPGLayer : public OGRLayer
 
     char               *pszCursorName;
     PGresult           *hCursorResult;
-    int                 bCursorActive;
 
     int                 nResultOffset;
 
@@ -131,11 +130,17 @@ class OGRPGLayer : public OGRLayer
     int                 ParsePGDate( const char *, OGRField * );
 
     void                SetInitialQueryCursor();
+    void                CloseCursor();
 
     OGRErr              RunGetExtentRequest( OGREnvelope *psExtent, int bForce,
                                              CPLString osCommand);
     void                CreateMapFromFieldNameToIndex();
 
+    OGRFeatureDefn     *ReadResultDefinition(PGresult *hInitialResultIn);
+
+    OGRFeature         *RecordToFeature( int iRecord );
+    OGRFeature         *GetNextRawFeature();
+
   public:
                         OGRPGLayer();
     virtual             ~OGRPGLayer();
@@ -154,10 +159,6 @@ class OGRPGLayer : public OGRLayer
     virtual const char *GetGeometryColumn();
 
     virtual OGRErr      SetNextByIndex( long nIndex );
-
-    /* custom methods */
-    virtual OGRFeature *RecordToFeature( int iRecord );
-    virtual OGRFeature *GetNextRawFeature();
 };
 
 /************************************************************************/
@@ -224,7 +225,7 @@ public:
                                          const char * pszGeomColumnIn,
                                          int bUpdate,
                                          int bAdvertizeGeomColumn,
-                                         int nSRSId = -2 );
+                                         int nSRSId = UNDETERMINED_SRID );
                         ~OGRPGTableLayer();
 
     void                SetGeometryInformation(const char* pszGeomType,
@@ -252,6 +253,8 @@ public:
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
+    virtual OGRErr      DeleteField( int iField );
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
 
     virtual OGRSpatialReference *GetSpatialRef();
 
@@ -286,8 +289,6 @@ class OGRPGResultLayer : public OGRPGLayer
 
     CPLString           osWHERE;
 
-    OGRFeatureDefn     *ReadResultDefinition(PGresult *hInitialResultIn);
-
   public:
                         OGRPGResultLayer( OGRPGDataSource *,
                                           const char * pszRawStatement,
@@ -349,12 +350,17 @@ class OGRPGDataSource : public OGRDataSource
 
     CPLString           GetCurrentSchema();
 
+    int                 nUndefinedSRID;
+
   public:
     PGver               sPostgreSQLVersion;
     PGver               sPostGISVersion;
 
     int                 bUseBinaryCursor;
     int                 bBinaryTimeFormatIsInt8;
+    int                 bUseEscapeStringSyntax;
+
+    int                GetUndefinedSRID() const { return nUndefinedSRID; }
 
   public:
                         OGRPGDataSource();
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
index 3ffbff6..7a00260 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdatasource.cpp 22019 2011-03-23 20:38:08Z rouault $
+ * $Id: ogrpgdatasource.cpp 23652 2011-12-29 09:33:53Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -29,12 +29,13 @@
 
 #include <string.h>
 #include "ogr_pg.h"
-#include "ogrpgutility.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
 
-CPL_CVSID("$Id: ogrpgdatasource.cpp 22019 2011-03-23 20:38:08Z rouault $");
+#define PQexec this_is_an_error
+
+CPL_CVSID("$Id: ogrpgdatasource.cpp 23652 2011-12-29 09:33:53Z rouault $");
 
 static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 
@@ -55,6 +56,7 @@ OGRPGDataSource::OGRPGDataSource()
     bUseBinaryCursor = FALSE;
     nSoftTransactionLevel = 0;
     bBinaryTimeFormatIsInt8 = FALSE;
+    bUseEscapeStringSyntax = FALSE;
     
     nGeometryOID = (Oid) 0;
     nGeographyOID = (Oid) 0;
@@ -64,6 +66,7 @@ OGRPGDataSource::OGRPGDataSource()
     papoSRS = NULL;
 
     poLayerInCopyMode = NULL;
+    nUndefinedSRID = -1; /* actual value will be autotected if PostGIS >= 2.0 detected */
 }
 
 /************************************************************************/
@@ -113,7 +116,7 @@ CPLString OGRPGDataSource::GetCurrentSchema()
     /* -------------------------------------------- */
     /*          Get the current schema              */
     /* -------------------------------------------- */
-    PGresult    *hResult = PQexec(hPGConn,"SELECT current_schema()");
+    PGresult    *hResult = OGRPG_PQexec(hPGConn,"SELECT current_schema()");
     if ( hResult && PQntuples(hResult) == 1 && !PQgetisnull(hResult,0,0) )
     {
         osCurrentSchema = PQgetvalue(hResult,0,0);
@@ -224,7 +227,7 @@ static void OGRPGTableEntryAddGeomColumn(PGTableEntry* psTableEntry,
                                          const char* pszName,
                                          const char* pszGeomType = NULL,
                                          int nCoordDimension = 0,
-                                         int nSRID = 0,
+                                         int nSRID = UNDETERMINED_SRID,
                                          PostgisType ePostgisType = GEOM_TYPE_UNKNOWN)
 {
     psTableEntry->pasGeomColumns = (PGGeomColumnDesc*)
@@ -551,7 +554,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     {
         CPLString osCommand;
         osCommand.Printf("SET search_path='%s',public", osActiveSchema.c_str());
-        PGresult    *hResult = PQexec(hPGConn, osCommand );
+        PGresult    *hResult = OGRPG_PQexec(hPGConn, osCommand );
 
         if( !hResult || PQresultStatus(hResult) != PGRES_COMMAND_OK )
         {
@@ -573,7 +576,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     sPostgreSQLVersion.nMinor = -1;
     sPostgreSQLVersion.nRelease = -1;
 
-    hResult = PQexec(hPGConn, "SELECT version()" );
+    hResult = OGRPG_PQexec(hPGConn, "SELECT version()" );
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) > 0 )
     {
@@ -597,6 +600,20 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     CPLAssert(NULL == hResult); /* Test if safe PQclear has not been broken */
 
 /* -------------------------------------------------------------------- */
+/*      Test if standard_conforming_strings is recognized               */
+/* -------------------------------------------------------------------- */
+
+    hResult = OGRPG_PQexec(hPGConn, "SHOW standard_conforming_strings" );
+    if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
+        && PQntuples(hResult) == 1 )
+    {
+        /* Whatever the value is, it means that we can use the E'' */
+        /* syntax */
+        bUseEscapeStringSyntax = TRUE;
+    }
+    OGRPGClearResult(hResult);
+
+/* -------------------------------------------------------------------- */
 /*      Test if time binary format is int8 or float8                    */
 /* -------------------------------------------------------------------- */
 #if !defined(PG_PRE74)
@@ -604,13 +621,13 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     {
         SoftStartTransaction();
 
-        hResult = PQexec(hPGConn, "DECLARE gettimebinaryformat BINARY CURSOR FOR SELECT CAST ('00:00:01' AS time)");
+        hResult = OGRPG_PQexec(hPGConn, "DECLARE gettimebinaryformat BINARY CURSOR FOR SELECT CAST ('00:00:01' AS time)");
 
         if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
         {
             OGRPGClearResult( hResult );
 
-            hResult = PQexec(hPGConn, "FETCH ALL IN gettimebinaryformat" );
+            hResult = OGRPG_PQexec(hPGConn, "FETCH ALL IN gettimebinaryformat" );
 
             if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK  && PQntuples(hResult) == 1 )
             {
@@ -645,7 +662,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 
         OGRPGClearResult( hResult );
 
-        hResult = PQexec(hPGConn, "CLOSE gettimebinaryformat");
+        hResult = OGRPG_PQexec(hPGConn, "CLOSE gettimebinaryformat");
         OGRPGClearResult( hResult );
 
         SoftCommit();
@@ -659,7 +676,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     {
         /* Starting with PostgreSQL 9.0, the default output format for values of type bytea */
         /* is hex, whereas we traditionnaly expect escape */
-        hResult = PQexec(hPGConn, "SET bytea_output TO escape");
+        hResult = OGRPG_PQexec(hPGConn, "SET bytea_output TO escape");
         OGRPGClearResult( hResult );
     }
 #endif
@@ -669,14 +686,14 @@ 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 = PQexec(hPGConn, "BEGIN");
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
 
     if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
     {
         OGRPGClearResult( hResult );
         CPLAssert(NULL == hResult);
 
-        hResult = PQexec(hPGConn,
+        hResult = OGRPG_PQexec(hPGConn,
                          "SELECT oid FROM pg_type WHERE typname = 'geometry'" );
     }
 
@@ -703,7 +720,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 
     if( bHavePostGIS )
     {
-        hResult = PQexec(hPGConn, "SELECT postgis_version()" );
+        hResult = OGRPG_PQexec(hPGConn, "SELECT postgis_version()" );
         if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
             && PQntuples(hResult) > 0 )
         {
@@ -720,7 +737,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         if (sPostGISVersion.nMajor == 0 && sPostGISVersion.nMinor < 8)
         {
             // Turning off sequential scans for PostGIS < 0.8
-            hResult = PQexec(hPGConn, "SET ENABLE_SEQSCAN = OFF");
+            hResult = OGRPG_PQexec(hPGConn, "SET ENABLE_SEQSCAN = OFF");
             
             CPLDebug( "PG", "SET ENABLE_SEQSCAN=OFF" );
         }
@@ -728,12 +745,32 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         {
             // PostGIS >=0.8 is correctly integrated with query planner,
             // thus PostgreSQL will use indexes whenever appropriate.
-            hResult = PQexec(hPGConn, "SET ENABLE_SEQSCAN = ON");
+            hResult = OGRPG_PQexec(hPGConn, "SET ENABLE_SEQSCAN = ON");
+        }
+        OGRPGClearResult( hResult );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find out "unknown SRID" value                                   */
+/* -------------------------------------------------------------------- */
+
+    if (sPostGISVersion.nMajor >= 2)
+    {
+        hResult = OGRPG_PQexec(hPGConn,
+                        "SELECT ST_Srid('POINT EMPTY'::GEOMETRY)" );
+
+        if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
+            && PQntuples(hResult) > 0)
+        {
+            nUndefinedSRID = atoi(PQgetvalue(hResult,0,0));
         }
+
         OGRPGClearResult( hResult );
     }
+    else
+        nUndefinedSRID = -1;
 
-    hResult = PQexec(hPGConn, "COMMIT");
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
 /* -------------------------------------------------------------------- */
@@ -752,7 +789,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         else
             pszAllowedRelations = "'r','v'";
         
-        hResult = PQexec(hPGConn, "BEGIN");
+        hResult = OGRPG_PQexec(hPGConn, "BEGIN");
 
         if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
         {
@@ -773,7 +810,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
                     (sPostGISVersion.nMajor == 1 && sPostGISVersion.nMinor >= 5)) &&
                     CSLTestBoolean(CPLGetConfigOption("PG_USE_GEOGRAPHY", "YES")) )
                 {
-                    hResult = PQexec(hPGConn,
+                    hResult = OGRPG_PQexec(hPGConn,
                                     "SELECT oid FROM pg_type WHERE typname = 'geography'" );
 
                     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
@@ -809,13 +846,13 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
                                  "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid)",
                                  pszAllowedRelations);
                                 
-            hResult = PQexec(hPGConn, osCommand.c_str());
+            hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
         }
 
         if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
         {
             OGRPGClearResult( hResult );
-            hResult = PQexec(hPGConn, "FETCH ALL in mycursor" );
+            hResult = OGRPG_PQexec(hPGConn, "FETCH ALL in mycursor" );
         }
 
         if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
@@ -883,22 +920,22 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     /* -------------------------------------------------------------------- */
         OGRPGClearResult( hResult );
 
-        hResult = PQexec(hPGConn, "CLOSE mycursor");
+        hResult = OGRPG_PQexec(hPGConn, "CLOSE mycursor");
         OGRPGClearResult( hResult );
 
-        hResult = PQexec(hPGConn, "COMMIT");
+        hResult = OGRPG_PQexec(hPGConn, "COMMIT");
         OGRPGClearResult( hResult );
 
         if ( bHavePostGIS && !bListAllTables )
         {
-            hResult = PQexec(hPGConn, "BEGIN");
+            hResult = OGRPG_PQexec(hPGConn, "BEGIN");
 
             OGRPGClearResult( hResult );
 
         /* -------------------------------------------------------------------- */
         /*      Fetch inherited tables                                          */
         /* -------------------------------------------------------------------- */
-            hResult = PQexec(hPGConn,
+            hResult = OGRPG_PQexec(hPGConn,
                                 "DECLARE mycursor CURSOR for "
                                 "SELECT c1.relname AS derived, c2.relname AS parent, n.nspname "
                                 "FROM pg_class c1, pg_class c2, pg_namespace n, pg_inherits i "
@@ -909,7 +946,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
             if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
             {
                 OGRPGClearResult( hResult );
-                hResult = PQexec(hPGConn, "FETCH ALL in mycursor" );
+                hResult = OGRPG_PQexec(hPGConn, "FETCH ALL in mycursor" );
             }
 
             if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
@@ -984,10 +1021,10 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         /* -------------------------------------------------------------------- */
             OGRPGClearResult( hResult );
 
-            hResult = PQexec(hPGConn, "CLOSE mycursor");
+            hResult = OGRPG_PQexec(hPGConn, "CLOSE mycursor");
             OGRPGClearResult( hResult );
 
-            hResult = PQexec(hPGConn, "COMMIT");
+            hResult = OGRPG_PQexec(hPGConn, "COMMIT");
             OGRPGClearResult( hResult );
 
         }
@@ -1143,7 +1180,7 @@ int OGRPGDataSource::DeleteLayer( int iLayer )
     PGresult            *hResult;
     CPLString            osCommand;
 
-    hResult = PQexec(hPGConn, "BEGIN");
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
     OGRPGClearResult( hResult );
 
     if( bHavePostGIS )
@@ -1154,15 +1191,15 @@ int OGRPGDataSource::DeleteLayer( int iLayer )
                  "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() );
 
-        hResult = PQexec( hPGConn, osCommand.c_str() );
+        hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
         OGRPGClearResult( hResult );
     }
 
     osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE", osSchemaName.c_str(), osTableName.c_str() );
-    hResult = PQexec( hPGConn, osCommand.c_str() );
+    hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "COMMIT");
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
     return OGRERR_NONE;
@@ -1189,6 +1226,23 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
     if (pszLayerName == NULL)
         return NULL;
 
+    const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
+    CPLString osFIDColumnName;
+    if (pszFIDColumnName == NULL)
+        osFIDColumnName = "OGC_FID";
+    else
+    {
+        if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+        {
+            char* pszLaunderedFid = LaunderName(pszFIDColumnName);
+            osFIDColumnName += OGRPGEscapeColumnName(pszLaunderedFid);
+            CPLFree(pszLaunderedFid);
+        }
+        else
+            osFIDColumnName += OGRPGEscapeColumnName(pszFIDColumnName);
+    }
+    pszFIDColumnName = osFIDColumnName.c_str();
+
     if (strncmp(pszLayerName, "pg", 2) == 0)
     {
         CPLError(CE_Warning, CPLE_AppDefined,
@@ -1208,13 +1262,17 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
     if (bNoneAsUnknown && eType == wkbNone)
         eType = wkbUnknown;
 
+
+    int bExtractSchemaFromLayerName = CSLTestBoolean(CSLFetchNameValueDef(
+                                    papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
+
     /* Postgres Schema handling:
        Extract schema name from input layer name or passed with -lco SCHEMA.
        Set layer name to "schema.table" or to "table" if schema == current_schema()
        Usage without schema name is backwards compatible
     */
     const char* pszDotPos = strstr(pszLayerName,".");
-    if ( pszDotPos != NULL )
+    if ( pszDotPos != NULL && bExtractSchemaFromLayerName )
     {
       int length = pszDotPos - pszLayerName;
       pszSchemaName = (char*)CPLMalloc(length+1);
@@ -1348,7 +1406,7 @@ OGRPGDataSource::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 nSRSId = nUndefinedSRID;
 
     if( poSRS != NULL )
         nSRSId = FetchSRSId( poSRS );
@@ -1358,7 +1416,7 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 /*      Create a basic table with the FID.  Also include the            */
 /*      geometry if this is not a PostGIS enabled table.                */
 /* -------------------------------------------------------------------- */
-    hResult = PQexec(hPGConn, "BEGIN");
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
     OGRPGClearResult( hResult );
     
     const char *pszGFldName = NULL;
@@ -1379,10 +1437,13 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
     {
         osCommand.Printf(
                  "%s ( "
-                 "   OGC_FID SERIAL, "
+                 "    %s SERIAL, "
                  "   WKB_GEOMETRY %s, "
-                 "   CONSTRAINT \"%s_pk\" PRIMARY KEY (OGC_FID) )",
-                 osCreateTable.c_str(), pszGeomType, pszTableName );
+                 "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                 osCreateTable.c_str(),
+                 pszFIDColumnName,
+                 pszGeomType,
+                 pszTableName, pszFIDColumnName);
     }
     else if ( eType != wkbNone && EQUAL(pszGeomType, "geography") )
     {
@@ -1393,21 +1454,27 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
         
         if (nSRSId)
             osCommand.Printf(
-                     "%s ( OGC_FID SERIAL, \"%s\" geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (OGC_FID) )",
-                     osCreateTable.c_str(), pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", nSRSId, pszTableName );
+                     "%s ( %s SERIAL, %s geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                     osCreateTable.c_str(), pszFIDColumnName,
+                     OGRPGEscapeColumnName(pszGFldName).c_str(), pszGeometryType,
+                     nDimension == 2 ? "" : "Z", nSRSId, pszTableName,
+                     pszFIDColumnName);
         else
             osCommand.Printf(
-                     "%s ( OGC_FID SERIAL, \"%s\" geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (OGC_FID) )",
-                     osCreateTable.c_str(), pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", pszTableName );
+                     "%s ( %s SERIAL, %s geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                     osCreateTable.c_str(), pszFIDColumnName,
+                     OGRPGEscapeColumnName(pszGFldName).c_str(), pszGeometryType,
+                     nDimension == 2 ? "" : "Z", pszTableName,
+                     pszFIDColumnName);
     }
     else
     {
         osCommand.Printf(
-                 "%s ( OGC_FID SERIAL, CONSTRAINT \"%s_pk\" PRIMARY KEY (OGC_FID) )",
-                 osCreateTable.c_str(), pszTableName );
+                 "%s ( %s SERIAL, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                 osCreateTable.c_str(), pszFIDColumnName, pszTableName, pszFIDColumnName );
     }
 
-    hResult = PQexec(hPGConn, osCommand.c_str());
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
     if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1416,13 +1483,16 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
         CPLFree( pszSchemaName );
 
         OGRPGClearResult( hResult );
-        hResult = PQexec( hPGConn, "ROLLBACK" );
+        hResult = OGRPG_PQexec( hPGConn, "ROLLBACK" );
         OGRPGClearResult( hResult );
         return NULL;
     }
 
     OGRPGClearResult( hResult );
 
+    CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn, pszTableName, -1, "");
+    const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
+
 /* -------------------------------------------------------------------- */
 /*      Eventually we should be adding this table to a table of         */
 /*      "geometric layers", capturing the WKT projection, and           */
@@ -1435,23 +1505,27 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
         else
             pszGFldName = "wkb_geometry";
 
-        /* Sometimes there is an old cruft entry in the geometry_columns
-         * table if things were not properly cleaned up before.  We make
-         * an effort to clean out such cruft.
-         */
-        osCommand.Printf(
-                 "DELETE FROM geometry_columns WHERE f_table_name = '%s' AND f_table_schema = '%s'",
-                 pszTableName, pszSchemaName );
+        if (sPostGISVersion.nMajor <= 1)
+        {
+            /* Sometimes there is an old cruft entry in the geometry_columns
+            * table if things were not properly cleaned up before.  We make
+            * an effort to clean out such cruft.
+            * 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 );
 
-        hResult = PQexec(hPGConn, osCommand.c_str());
-        OGRPGClearResult( hResult );
+            hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+            OGRPGClearResult( hResult );
+        }
 
         osCommand.Printf(
-                 "SELECT AddGeometryColumn('%s','%s','%s',%d,'%s',%d)",
-                 pszSchemaName, pszTableName, pszGFldName,
+                 "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s',%d)",
+                 pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
                  nSRSId, pszGeometryType, nDimension );
 
-        hResult = PQexec(hPGConn, osCommand.c_str());
+        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
         if( !hResult
             || PQresultStatus(hResult) != PGRES_TUPLES_OK )
@@ -1465,7 +1539,7 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 
             OGRPGClearResult( hResult );
 
-            hResult = PQexec(hPGConn, "ROLLBACK");
+            hResult = OGRPG_PQexec(hPGConn, "ROLLBACK");
             OGRPGClearResult( hResult );
 
             return NULL;
@@ -1487,10 +1561,11 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
         {
             osCommand.Printf("CREATE INDEX \"%s_geom_idx\" "
                              "ON \"%s\".\"%s\" "
-                             "USING GIST (\"%s\")",
-                    pszTableName, pszSchemaName, pszTableName, pszGFldName);
+                             "USING GIST (%s)",
+                             pszTableName, pszSchemaName, pszTableName,
+                             OGRPGEscapeColumnName(pszGFldName).c_str());
 
-            hResult = PQexec(hPGConn, osCommand.c_str());
+            hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
             if( !hResult
                 || PQresultStatus(hResult) != PGRES_COMMAND_OK )
@@ -1504,7 +1579,7 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 
                 OGRPGClearResult( hResult );
 
-                hResult = PQexec(hPGConn, "ROLLBACK");
+                hResult = OGRPG_PQexec(hPGConn, "ROLLBACK");
                 OGRPGClearResult( hResult );
 
                 return NULL;
@@ -1516,7 +1591,7 @@ OGRPGDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Complete, and commit the transaction.                           */
 /* -------------------------------------------------------------------- */
-    hResult = PQexec(hPGConn, "COMMIT");
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
 /* -------------------------------------------------------------------- */
@@ -1715,7 +1790,7 @@ OGRSpatialReference *OGRPGDataSource::FetchSRS( int nId )
              "SELECT srtext FROM spatial_ref_sys "
              "WHERE srid = %d",
              nId );
-    hResult = PQexec(hPGConn, osCommand.c_str() );
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
     if( hResult
         && PQresultStatus(hResult) == PGRES_TUPLES_OK
@@ -1761,11 +1836,11 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     PGresult            *hResult = NULL;
     CPLString           osCommand;
     char                *pszWKT = NULL;
-    int                 nSRSId = -1;
+    int                 nSRSId = nUndefinedSRID;
     const char*         pszAuthorityName;
 
     if( poSRS == NULL )
-        return -1;
+        return nUndefinedSRID;
 
     OGRSpatialReference oSRS(*poSRS);
     poSRS = NULL;
@@ -1809,7 +1884,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                          "auth_name = '%s' AND auth_srid = %d",
                          pszAuthorityName,
                          nAuthorityCode );
-        hResult = PQexec(hPGConn, osCommand.c_str());
+        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
         if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
             && PQntuples(hResult) > 0 )
@@ -1830,20 +1905,20 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
     {
         CPLFree(pszWKT);
-        return -1;
+        return nUndefinedSRID;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Try to find in the existing table.                              */
 /* -------------------------------------------------------------------- */
-    hResult = PQexec(hPGConn, "BEGIN");
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
     OGRPGClearResult( hResult );
 
     CPLString osWKT = OGRPGEscapeString(hPGConn, pszWKT, -1, "srtext");
     osCommand.Printf(
              "SELECT srid FROM spatial_ref_sys WHERE srtext = %s",
              osWKT.c_str() );
-    hResult = PQexec(hPGConn, osCommand.c_str() );
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
     CPLFree( pszWKT );  // CM:  Added to prevent mem leaks
     pszWKT = NULL;      // CM:  Added
 
@@ -1857,7 +1932,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
         OGRPGClearResult( hResult );
 
-        hResult = PQexec(hPGConn, "COMMIT");
+        hResult = OGRPG_PQexec(hPGConn, "COMMIT");
         OGRPGClearResult( hResult );
 
         return nSRSId;
@@ -1874,22 +1949,22 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "COMMIT");
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
     if( bTableMissing )
     {
         if( InitializeMetadataTables() != OGRERR_NONE )
-            return -1;
+            return nUndefinedSRID;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get the current maximum srid in the srs table.                  */
 /* -------------------------------------------------------------------- */
-    hResult = PQexec(hPGConn, "BEGIN");
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "SELECT MAX(srid) FROM spatial_ref_sys" );
+    hResult = OGRPG_PQexec(hPGConn, "SELECT MAX(srid) FROM spatial_ref_sys" );
 
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK )
     {
@@ -1908,7 +1983,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     if( oSRS.exportToProj4( &pszProj4 ) != OGRERR_NONE )
     {
         CPLFree( pszProj4 );
-        return -1;
+        return nUndefinedSRID;
     }
 
     CPLString osProj4 = OGRPGEscapeString(hPGConn, pszProj4, -1, "proj4text");
@@ -1936,10 +2011,10 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     CPLFree( pszProj4 );
     CPLFree( pszWKT);
 
-    hResult = PQexec(hPGConn, osCommand.c_str() );
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "COMMIT");
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
     return nSRSId;
@@ -1964,7 +2039,7 @@ OGRErr OGRPGDataSource::SoftStartTransaction()
         PGconn      *hPGConn = GetPGConn();
 
         //CPLDebug( "PG", "BEGIN Transaction" );
-        hResult = PQexec(hPGConn, "BEGIN");
+        hResult = OGRPG_PQexec(hPGConn, "BEGIN");
 
         if( !hResult || PQresultStatus(hResult) != PGRES_COMMAND_OK )
         {
@@ -2007,7 +2082,7 @@ OGRErr OGRPGDataSource::SoftCommit()
         PGconn      *hPGConn = GetPGConn();
 
         //CPLDebug( "PG", "COMMIT Transaction" );
-        hResult = PQexec(hPGConn, "COMMIT");
+        hResult = OGRPG_PQexec(hPGConn, "COMMIT");
 
         if( !hResult || PQresultStatus(hResult) != PGRES_COMMAND_OK )
         {
@@ -2045,7 +2120,7 @@ OGRErr OGRPGDataSource::SoftRollback()
     PGresult    *hResult = NULL;
     PGconn      *hPGConn = GetPGConn();
 
-    hResult = PQexec(hPGConn, "ROLLBACK");
+    hResult = OGRPG_PQexec(hPGConn, "ROLLBACK");
 
     if( !hResult || PQresultStatus(hResult) != PGRES_COMMAND_OK )
     {
@@ -2084,6 +2159,99 @@ OGRErr OGRPGDataSource::FlushSoftTransaction()
     return SoftCommit();
 }
 
+
+/************************************************************************/
+/*                     OGRPGNoResetResultLayer                          */
+/************************************************************************/
+
+class OGRPGNoResetResultLayer : public OGRPGLayer
+{
+  public:
+                        OGRPGNoResetResultLayer(OGRPGDataSource *poDSIn,
+                                                PGresult *hResultIn);
+
+    virtual             ~OGRPGNoResetResultLayer();
+
+    virtual void        ResetReading();
+
+    virtual int         TestCapability( const char * ) { return FALSE; }
+
+    virtual OGRFeature *GetNextFeature();
+};
+
+
+/************************************************************************/
+/*                     OGRPGNoResetResultLayer()                        */
+/************************************************************************/
+
+OGRPGNoResetResultLayer::OGRPGNoResetResultLayer( OGRPGDataSource *poDSIn,
+                                                  PGresult *hResultIn )
+{
+    poDS = poDSIn;
+    poFeatureDefn = ReadResultDefinition(hResultIn);
+    hCursorResult = hResultIn;
+    CreateMapFromFieldNameToIndex();
+}
+
+/************************************************************************/
+/*                   ~OGRPGNoResetResultLayer()                         */
+/************************************************************************/
+
+OGRPGNoResetResultLayer::~OGRPGNoResetResultLayer()
+
+{
+    OGRPGClearResult( hCursorResult );
+    hCursorResult = NULL;
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRPGNoResetResultLayer::ResetReading()
+{
+    iNextShapeId = 0;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRPGNoResetResultLayer::GetNextFeature()
+
+{
+    if (iNextShapeId == PQntuples(hCursorResult))
+    {
+        return NULL;
+    }
+    return RecordToFeature(iNextShapeId ++);
+}
+
+/************************************************************************/
+/*                      OGRPGMemLayerWrapper                            */
+/************************************************************************/
+
+class OGRPGMemLayerWrapper : public OGRLayer
+{
+  private:
+      OGRDataSource  *poMemDS;
+      OGRLayer       *poMemLayer;
+
+  public:
+                        OGRPGMemLayerWrapper( OGRDataSource  *poMemDSIn )
+                        {
+                            poMemDS = poMemDSIn;
+                            poMemLayer = poMemDS->GetLayer(0);
+                        }
+
+                        ~OGRPGMemLayerWrapper() { delete poMemDS; }
+
+    virtual void        ResetReading() { poMemLayer->ResetReading(); }
+    virtual OGRFeature *GetNextFeature() { return poMemLayer->GetNextFeature(); }
+    virtual OGRFeatureDefn *GetLayerDefn() { return poMemLayer->GetLayerDefn(); }
+    virtual int         TestCapability( const char * ) { return FALSE; }
+};
+
 /************************************************************************/
 /*                             ExecuteSQL()                             */
 /************************************************************************/
@@ -2093,6 +2261,10 @@ OGRLayer * OGRPGDataSource::ExecuteSQL( const char *pszSQLCommand,
                                         const char *pszDialect )
 
 {
+    /* Skip leading spaces */
+    while(*pszSQLCommand == ' ')
+        pszSQLCommand ++;
+    
 /* -------------------------------------------------------------------- */
 /*      Use generic implementation for OGRSQL dialect.                  */
 /* -------------------------------------------------------------------- */
@@ -2133,10 +2305,29 @@ OGRLayer * OGRPGDataSource::ExecuteSQL( const char *pszSQLCommand,
     if( EQUALN(pszSQLCommand,"VACUUM",6) 
         || SoftStartTransaction() == OGRERR_NONE  )
     {
-        if (EQUALN(pszSQLCommand, "SELECT", 6) == FALSE)
+        if (EQUALN(pszSQLCommand, "SELECT", 6) == FALSE ||
+            (strstr(pszSQLCommand, "from") == NULL && strstr(pszSQLCommand, "FROM") == NULL))
         {
-            hResult = PQexec(hPGConn, pszSQLCommand );
-            CPLDebug( "PG", "Command Results Tuples = %d", PQntuples(hResult) );
+            hResult = OGRPG_PQexec(hPGConn, pszSQLCommand, TRUE /* multiple allowed */ );
+            if (hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK)
+            {
+                CPLDebug( "PG", "Command Results Tuples = %d", PQntuples(hResult) );
+                FlushSoftTransaction();
+
+                OGRSFDriver* poMemDriver = OGRSFDriverRegistrar::GetRegistrar()->
+                                GetDriverByName("Memory");
+                if (poMemDriver)
+                {
+                    OGRPGLayer* poResultLayer = new OGRPGNoResetResultLayer( this, hResult );
+                    OGRDataSource* poMemDS = poMemDriver->CreateDataSource("");
+                    poMemDS->CopyLayer(poResultLayer, "sql_statement");
+                    OGRPGMemLayerWrapper* poResLayer = new OGRPGMemLayerWrapper(poMemDS);
+                    delete poResultLayer;
+                    return poResLayer;
+                }
+                else
+                    return NULL;
+            }
         }
         else
         {
@@ -2144,43 +2335,42 @@ OGRLayer * OGRPGDataSource::ExecuteSQL( const char *pszSQLCommand,
             osCommand.Printf( "DECLARE %s CURSOR for %s",
                                 "executeSQLCursor", pszSQLCommand );
 
-            hResult = PQexec(hPGConn, osCommand );
-            OGRPGClearResult( hResult );
-
-            osCommand.Printf( "FETCH 0 in %s", "executeSQLCursor" );
-            hResult = PQexec(hPGConn, osCommand );
-        }
-    }
+            hResult = OGRPG_PQexec(hPGConn, osCommand );
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a tuple result? If so, instantiate a results         */
 /*      layer for it.                                                   */
 /* -------------------------------------------------------------------- */
+            if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
+            {
+                OGRPGResultLayer *poLayer = NULL;
 
-    if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
-        && (EQUALN(pszSQLCommand, "SELECT", 6) || PQntuples(hResult) > 0) )
-    {
-        OGRPGResultLayer *poLayer = NULL;
+                OGRPGClearResult( hResult );
 
-        poLayer = new OGRPGResultLayer( this, pszSQLCommand, hResult );
+                osCommand.Printf( "FETCH 0 in %s", "executeSQLCursor" );
+                hResult = OGRPG_PQexec(hPGConn, osCommand );
 
-        OGRPGClearResult( hResult );
+                poLayer = new OGRPGResultLayer( this, pszSQLCommand, hResult );
+
+                OGRPGClearResult( hResult );
 
-        if( poSpatialFilter != NULL )
-            poLayer->SetSpatialFilter( poSpatialFilter );
+                if( poSpatialFilter != NULL )
+                    poLayer->SetSpatialFilter( poSpatialFilter );
 
-        return poLayer;
+                return poLayer;
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Generate an error report if an error occured.                   */
 /* -------------------------------------------------------------------- */
-    if( hResult &&
+    if( !hResult ||
         (PQresultStatus(hResult) == PGRES_NONFATAL_ERROR
          || PQresultStatus(hResult) == PGRES_FATAL_ERROR ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s", PQresultErrorMessage( hResult ) );
+                  "%s", PQerrorMessage( hPGConn ) );
     }
 
     OGRPGClearResult( hResult );
@@ -2212,7 +2402,7 @@ char *OGRPGDataSource::LaunderName( const char *pszSrcName )
     for( int i = 0; pszSafeName[i] != '\0'; i++ )
     {
         pszSafeName[i] = (char) tolower( pszSafeName[i] );
-        if( pszSafeName[i] == '-' || pszSafeName[i] == '#' )
+        if( pszSafeName[i] == '\'' || pszSafeName[i] == '-' || pszSafeName[i] == '#' )
             pszSafeName[i] = '_';
     }
 
diff --git a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
index 984749e..41f8262 100644
--- a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpglayer.cpp 20698 2010-09-26 13:38:41Z rouault $
+ * $Id: ogrpglayer.cpp 23565 2011-12-13 20:33:20Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGLayer class  which implements shared handling
@@ -58,13 +58,13 @@ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */
 
 #include "ogr_pg.h"
-#include "ogrpgutility.h"
 #include "ogr_p.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
-#include "cpl_base64.h"
 
-CPL_CVSID("$Id: ogrpglayer.cpp 20698 2010-09-26 13:38:41Z rouault $");
+#define PQexec this_is_an_error
+
+CPL_CVSID("$Id: ogrpglayer.cpp 23565 2011-12-13 20:33:20Z rouault $");
 
 #define CURSOR_PAGE     500
 
@@ -106,12 +106,11 @@ OGRPGLayer::OGRPGLayer()
     nCoordDimension = 2; // initialize in case PostGIS is not available
 
     poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet.
+    nSRSId = UNDETERMINED_SRID; // we haven't even queried the database for it yet.
 
     pszCursorName = CPLStrdup(CPLSPrintf("OGRPGLayerReader%p", this));
     
     hCursorResult = NULL;
-    bCursorActive = FALSE;
 
     bCanUseBinaryCursor = TRUE;
 
@@ -149,30 +148,22 @@ OGRPGLayer::~OGRPGLayer()
 }
 
 /************************************************************************/
-/*                            ResetReading()                            */
+/*                            CloseCursor()                             */
 /************************************************************************/
 
-void OGRPGLayer::ResetReading()
-
+void OGRPGLayer::CloseCursor()
 {
     PGconn      *hPGConn = poDS->GetPGConn();
-    CPLString    osCommand;
-
-    GetLayerDefn();
-
-    iNextShapeId = 0;
 
     if( hCursorResult != NULL )
     {
         OGRPGClearResult( hCursorResult );
 
-        if( bCursorActive )
-        {
-            osCommand.Printf("CLOSE %s", pszCursorName );
+        CPLString    osCommand;
+        osCommand.Printf("CLOSE %s", pszCursorName );
 
-            hCursorResult = PQexec(hPGConn, osCommand.c_str());
-            OGRPGClearResult( hCursorResult );
-        }
+        hCursorResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+        OGRPGClearResult( hCursorResult );
 
         poDS->FlushSoftTransaction();
 
@@ -181,6 +172,20 @@ void OGRPGLayer::ResetReading()
 }
 
 /************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRPGLayer::ResetReading()
+
+{
+    GetLayerDefn();
+
+    iNextShapeId = 0;
+
+    CloseCursor();
+}
+
+/************************************************************************/
 /*                    OGRPGGetStrFromBinaryNumeric()                    */
 /************************************************************************/
 
@@ -265,18 +270,18 @@ OGRPGGetStrFromBinaryNumeric(NumericVar *var)
                                 dig -= d1 * 1000;
                                 putit |= (d1 > 0);
                                 if (putit)
-                                        *cp++ = d1 + '0';
+                                        *cp++ = (char)(d1 + '0');
                                 d1 = dig / 100;
                                 dig -= d1 * 100;
                                 putit |= (d1 > 0);
                                 if (putit)
-                                        *cp++ = d1 + '0';
+                                        *cp++ = (char)(d1 + '0');
                                 d1 = dig / 10;
                                 dig -= d1 * 10;
                                 putit |= (d1 > 0);
                                 if (putit)
-                                        *cp++ = d1 + '0';
-                                *cp++ = dig + '0';
+                                        *cp++ = (char)(d1 + '0');
+                                *cp++ = (char)(dig + '0');
                         }
                 }
         }
@@ -296,14 +301,14 @@ OGRPGGetStrFromBinaryNumeric(NumericVar *var)
                         CPL_MSBPTR16(&dig);
                         d1 = dig / 1000;
                         dig -= d1 * 1000;
-                        *cp++ = d1 + '0';
+                        *cp++ = (char)(d1 + '0');
                         d1 = dig / 100;
                         dig -= d1 * 100;
-                        *cp++ = d1 + '0';
+                        *cp++ = (char)(d1 + '0');
                         d1 = dig / 10;
                         dig -= d1 * 10;
-                        *cp++ = d1 + '0';
-                        *cp++ = dig + '0';
+                        *cp++ = (char)(d1 + '0');
+                        *cp++ = (char)(dig + '0');
                 }
                 cp = endcp;
         }
@@ -375,7 +380,7 @@ OGRPGdt2timeInt8(GIntBig jd, int *hour, int *min, int *sec, double *fsec)
 	*min = (int) (time / USECS_PER_MIN);
 	time -=  (GIntBig) (*min) * USECS_PER_MIN;
 	*sec = (int)time / USECS_PER_SEC;
-	*fsec = time - *sec * USECS_PER_SEC;
+	*fsec = (double)(time - *sec * USECS_PER_SEC);
 }	/* dt2time() */
 
 static
@@ -1320,13 +1325,16 @@ void OGRPGLayer::SetInitialQueryCursor()
         osCommand.Printf( "DECLARE %s CURSOR for %s",
                             pszCursorName, pszQueryStatement );
 
-    hCursorResult = PQexec(hPGConn, osCommand );
+    hCursorResult = OGRPG_PQexec(hPGConn, osCommand );
+    if ( !hCursorResult || PQresultStatus(hCursorResult) != PGRES_COMMAND_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", PQerrorMessage( hPGConn ) );
+    }
     OGRPGClearResult( hCursorResult );
 
     osCommand.Printf( "FETCH %d in %s", CURSOR_PAGE, pszCursorName );
-    hCursorResult = PQexec(hPGConn, osCommand );
-
-    bCursorActive = TRUE;
+    hCursorResult = OGRPG_PQexec(hPGConn, osCommand );
 
     CreateMapFromFieldNameToIndex();
 
@@ -1368,14 +1376,16 @@ OGRFeature *OGRPGLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Do we need to fetch more records?                               */
 /* -------------------------------------------------------------------- */
-    if( PQntuples(hCursorResult) > 0 &&
-        nResultOffset >= PQntuples(hCursorResult)
-        && bCursorActive )
+
+    /* We test for PQntuples(hCursorResult) == 1 in the case the previous */
+    /* request was a SetNextByIndex() */
+    if( (PQntuples(hCursorResult) == 1 || PQntuples(hCursorResult) == CURSOR_PAGE) &&
+        nResultOffset == PQntuples(hCursorResult) )
     {
         OGRPGClearResult( hCursorResult );
         
         osCommand.Printf( "FETCH %d in %s", CURSOR_PAGE, pszCursorName );
-        hCursorResult = PQexec(hPGConn, osCommand );
+        hCursorResult = OGRPG_PQexec(hPGConn, osCommand );
 
         nResultOffset = 0;
     }
@@ -1384,22 +1394,9 @@ OGRFeature *OGRPGLayer::GetNextRawFeature()
 /*      Are we out of results?  If so complete the transaction, and     */
 /*      cleanup, but don't reset the next shapeid.                      */
 /* -------------------------------------------------------------------- */
-    if( nResultOffset >= PQntuples(hCursorResult) )
+    if( nResultOffset == PQntuples(hCursorResult) )
     {
-        OGRPGClearResult( hCursorResult );
-
-        if( bCursorActive )
-        {
-            osCommand.Printf( "CLOSE %s", pszCursorName );
-
-            hCursorResult = PQexec(hPGConn, osCommand);
-            OGRPGClearResult( hCursorResult );
-        }
-
-        poDS->FlushSoftTransaction();
-
-        hCursorResult = NULL;
-        bCursorActive = FALSE;
+        CloseCursor();
 
         iNextShapeId = MAX(1,iNextShapeId);
 
@@ -1458,28 +1455,15 @@ OGRErr OGRPGLayer::SetNextByIndex( long nIndex )
     OGRPGClearResult( hCursorResult );
     
     osCommand.Printf( "FETCH ABSOLUTE %ld in %s", nIndex+1, pszCursorName );
-    hCursorResult = PQexec(hPGConn, osCommand );
-    
+    hCursorResult = OGRPG_PQexec(hPGConn, osCommand );
+
     if (PQresultStatus(hCursorResult) != PGRES_TUPLES_OK ||
         PQntuples(hCursorResult) != 1)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to read feature at invalid index (%ld).", nIndex );
-                  
-        OGRPGClearResult( hCursorResult );
-
-        if( bCursorActive )
-        {
-            osCommand.Printf( "CLOSE %s", pszCursorName );
-
-            hCursorResult = PQexec(hPGConn, osCommand);
-            OGRPGClearResult( hCursorResult );
-        }
-
-        poDS->FlushSoftTransaction();
 
-        hCursorResult = NULL;
-        bCursorActive = FALSE;
+        CloseCursor();
 
         iNextShapeId = 0;
 
@@ -1615,7 +1599,7 @@ char *OGRPGLayer::GeometryToHex( OGRGeometry * poGeometry, int nSRSId )
     memcpy( &geomType, pabyWKB+1, 4 );
 
     /* Now add the SRID flag if an SRID is provided */
-    if (nSRSId != -1)
+    if (nSRSId > 0)
     {
         /* Change the flag to wkbNDR (little) endianess */
         GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
@@ -1630,7 +1614,7 @@ char *OGRPGLayer::GeometryToHex( OGRGeometry * poGeometry, int nSRSId )
     pszTextBufCurrent += 8;
 
     /* Now include SRID if provided */
-    if (nSRSId != -1)
+    if (nSRSId > 0)
     {
         /* Force the srsid to wkbNDR (little) endianess */
         GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
@@ -1890,16 +1874,14 @@ OGRErr OGRPGLayer::RollbackTransaction()
 OGRSpatialReference *OGRPGLayer::GetSpatialRef()
 
 {
-    if (nSRSId == -2)
+    if (nSRSId == UNDETERMINED_SRID)
         GetLayerDefn();
 
-    if( poSRS == NULL && nSRSId > -1 )
+    if( poSRS == NULL && nSRSId > 0 )
     {
         poSRS = poDS->FetchSRS( nSRSId );
         if( poSRS != NULL )
             poSRS->Reference();
-        else
-            nSRSId = -1;
     }
 
     return poSRS;
@@ -1950,7 +1932,7 @@ OGRErr OGRPGLayer::RunGetExtentRequest( OGREnvelope *psExtent, int bForce,
         PGconn      *hPGConn = poDS->GetPGConn();
         PGresult    *hResult = NULL;
 
-        hResult = PQexec( hPGConn, osCommand );
+        hResult = OGRPG_PQexec( hPGConn, osCommand );
         if( ! hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK || PQgetisnull(hResult,0,0) )
         {
             OGRPGClearResult( hResult );
@@ -2020,3 +2002,188 @@ OGRFeatureDefn * OGRPGLayer::GetLayerDefn()
 {
     return poFeatureDefn;
 }
+
+/************************************************************************/
+/*                        ReadResultDefinition()                        */
+/*                                                                      */
+/*      Build a schema from the current resultset.                      */
+/************************************************************************/
+
+OGRFeatureDefn *OGRPGLayer::ReadResultDefinition(PGresult *hInitialResultIn)
+
+{
+    PGresult            *hResult = hInitialResultIn;
+
+/* -------------------------------------------------------------------- */
+/*      Parse the returned table information.                           */
+/* -------------------------------------------------------------------- */
+    OGRFeatureDefn *poDefn = new OGRFeatureDefn( "sql_statement" );
+    int            iRawField;
+
+    poDefn->Reference();
+
+    for( iRawField = 0; iRawField < PQnfields(hResult); iRawField++ )
+    {
+        OGRFieldDefn    oField( PQfname(hResult,iRawField), OFTString);
+        Oid             nTypeOID;
+
+        nTypeOID = PQftype(hResult,iRawField);
+
+        if( EQUAL(oField.GetNameRef(),"ogc_fid") )
+        {
+            if (bHasFid)
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "More than one ogc_fid column was found in the result of the SQL request. Only last one will be used");
+            }
+            bHasFid = TRUE;
+            CPLFree(pszFIDColumn);
+            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") )
+        {
+            if (bHasPostGISGeometry || bHasPostGISGeography )
+            {
+                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");
+            }
+            if (nTypeOID == poDS->GetGeographyOID())
+                bHasPostGISGeography = TRUE;
+            else
+                bHasPostGISGeometry = TRUE;
+            CPLFree(pszGeomColumn);
+            pszGeomColumn = CPLStrdup(oField.GetNameRef());
+            continue;
+        }
+        else if( EQUAL(oField.GetNameRef(),"WKB_GEOMETRY") )
+        {
+            bHasWkb = TRUE;
+            if( nTypeOID == OIDOID )
+                bWkbAsOid = TRUE;
+            continue;
+        }
+
+        if( nTypeOID == BYTEAOID )
+        {
+            oField.SetType( OFTBinary );
+        }
+        else if( nTypeOID == CHAROID ||
+                 nTypeOID == TEXTOID ||
+                 nTypeOID == BPCHAROID ||
+                 nTypeOID == VARCHAROID )
+        {
+            oField.SetType( OFTString );
+
+            /* See http://www.mail-archive.com/pgsql-hackers@postgresql.org/msg57726.html */
+            /* nTypmod = width + 4 */
+            int nTypmod = PQfmod(hResult, iRawField);
+            if (nTypmod >= 4 && (nTypeOID == BPCHAROID ||
+                               nTypeOID == VARCHAROID ) )
+            {
+                oField.SetWidth( nTypmod - 4);
+            }
+        }
+        else if( nTypeOID == BOOLOID )
+        {
+            oField.SetType( OFTInteger );
+            oField.SetWidth( 1 );
+        }
+        else if (nTypeOID == INT2OID )
+        {
+            oField.SetType( OFTInteger );
+            oField.SetWidth( 5 );
+        }
+        else if (nTypeOID == INT4OID )
+        {
+            oField.SetType( OFTInteger );
+        }
+        else if ( nTypeOID == INT8OID )
+        {
+            /* FIXME: OFTInteger can not handle 64bit integers */
+            oField.SetType( OFTInteger );
+        }
+        else if( nTypeOID == FLOAT4OID ||
+                 nTypeOID == FLOAT8OID )
+        {
+            oField.SetType( OFTReal );
+        }
+        else if( nTypeOID == NUMERICOID )
+        {
+            /* See http://www.mail-archive.com/pgsql-hackers@postgresql.org/msg57726.html */
+            /* typmod = (width << 16) + precision + 4 */
+            int nTypmod = PQfmod(hResult, iRawField);
+            if (nTypmod >= 4)
+            {
+                int nWidth = (nTypmod - 4) >> 16;
+                int nPrecision = (nTypmod - 4) & 0xFFFF;
+                if (nWidth <= 10 && nPrecision == 0)
+                {
+                    oField.SetType( OFTInteger );
+                    oField.SetWidth( nWidth );
+                }
+                else
+                {
+                    oField.SetType( OFTReal );
+                    oField.SetWidth( nWidth );
+                    oField.SetPrecision( nPrecision );
+                }
+            }
+            else
+                oField.SetType( OFTReal );
+        }
+        else if ( nTypeOID == INT4ARRAYOID )
+        {
+            oField.SetType ( OFTIntegerList );
+        }
+        else if ( nTypeOID == FLOAT4ARRAYOID ||
+                  nTypeOID == FLOAT8ARRAYOID )
+        {
+            oField.SetType ( OFTRealList );
+        }
+        else if ( nTypeOID == TEXTARRAYOID ||
+                  nTypeOID == BPCHARARRAYOID ||
+                  nTypeOID == VARCHARARRAYOID )
+        {
+            oField.SetType ( OFTStringList );
+        }
+        else if ( nTypeOID == DATEOID )
+        {
+            oField.SetType( OFTDate );
+        }
+        else if ( nTypeOID == TIMEOID )
+        {
+            oField.SetType( OFTTime );
+        }
+        else if ( nTypeOID == TIMESTAMPOID ||
+                  nTypeOID == TIMESTAMPTZOID )
+        {
+            /* We can't deserialize properly timestamp with time zone */
+            /* with binary cursors */
+            if (nTypeOID == TIMESTAMPTZOID)
+                bCanUseBinaryCursor = FALSE;
+
+            oField.SetType( OFTDateTime );
+        }
+        else /* unknown type */
+        {
+            CPLDebug("PG", "Unhandled OID (%d) for column %d. Defaulting to String.", nTypeOID, iRawField);
+            oField.SetType( OFTString );
+        }
+
+        poDefn->AddFieldDefn( &oField );
+    }
+
+    return poDefn;
+}
diff --git a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
index a99820b..d654bf8 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgresultlayer.cpp 20698 2010-09-26 13:38:41Z rouault $
+ * $Id: ogrpgresultlayer.cpp 23674 2012-01-01 14:32:18Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGResultLayer class, access the resultset from
@@ -30,10 +30,10 @@
 
 #include "cpl_conv.h"
 #include "ogr_pg.h"
-#include "ogrpgutility.h"
 
-CPL_CVSID("$Id: ogrpgresultlayer.cpp 20698 2010-09-26 13:38:41Z rouault $");
+CPL_CVSID("$Id: ogrpgresultlayer.cpp 23674 2012-01-01 14:32:18Z rouault $");
 
+#define PQexec this_is_an_error
 
 /************************************************************************/
 /*                          OGRPGResultLayer()                          */
@@ -60,13 +60,13 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
     if (bHasPostGISGeometry)
     {
         CPLString osGetSRID;
-        osGetSRID += "SELECT getsrid(\"";
-        osGetSRID += pszGeomColumn;
-        osGetSRID += "\") FROM (";
+        osGetSRID += "SELECT getsrid(";
+        osGetSRID += OGRPGEscapeColumnName(pszGeomColumn);
+        osGetSRID += ") FROM (";
         osGetSRID += pszRawStatement;
         osGetSRID += ") AS ogrpggetsrid LIMIT 1";
 
-        PGresult* hSRSIdResult = PQexec(poDS->GetPGConn(), osGetSRID );
+        PGresult* hSRSIdResult = OGRPG_PQexec(poDS->GetPGConn(), osGetSRID );
 
         if( hSRSIdResult && PQresultStatus(hSRSIdResult) == PGRES_TUPLES_OK)
         {
@@ -86,12 +86,6 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
         // FIXME? But for the moment, PostGIS 1.5 only handles SRID:4326.
         nSRSId = 4326;
     }
-
-    /* Now set the cursor that will fetch the first rows */
-    /* This is usefull when used in situations like */
-    /* ds->ReleaseResultSet(ds->ExecuteSQL("SELECT AddGeometryColumn(....)")) */
-    /* when people don't actually try to get elements */
-    SetInitialQueryCursor();
 }
 
 /************************************************************************/
@@ -104,190 +98,6 @@ OGRPGResultLayer::~OGRPGResultLayer()
     CPLFree( pszRawStatement );
 }
 
-/************************************************************************/
-/*                        ReadResultDefinition()                        */
-/*                                                                      */
-/*      Build a schema from the current resultset.                      */
-/************************************************************************/
-
-OGRFeatureDefn *OGRPGResultLayer::ReadResultDefinition(PGresult *hInitialResultIn)
-
-{
-    PGresult            *hResult = hInitialResultIn;
-
-/* -------------------------------------------------------------------- */
-/*      Parse the returned table information.                           */
-/* -------------------------------------------------------------------- */
-    OGRFeatureDefn *poDefn = new OGRFeatureDefn( "sql_statement" );
-    int            iRawField;
-
-    poDefn->Reference();
-
-    for( iRawField = 0; iRawField < PQnfields(hResult); iRawField++ )
-    {
-        OGRFieldDefn    oField( PQfname(hResult,iRawField), OFTString);
-        Oid             nTypeOID;
-
-        nTypeOID = PQftype(hResult,iRawField);
-        
-        if( EQUAL(oField.GetNameRef(),"ogc_fid") )
-        {
-            if (bHasFid)
-            {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "More than one ogc_fid column was found in the result of the SQL request. Only last one will be used");
-            }
-            bHasFid = TRUE;
-            CPLFree(pszFIDColumn);
-            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") )
-        {
-            if (bHasPostGISGeometry || bHasPostGISGeography )
-            {
-                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");
-            }
-            if (nTypeOID == poDS->GetGeographyOID())
-                bHasPostGISGeography = TRUE;
-            else
-                bHasPostGISGeometry = TRUE;
-            CPLFree(pszGeomColumn);
-            pszGeomColumn = CPLStrdup(oField.GetNameRef());
-            continue;
-        }
-        else if( EQUAL(oField.GetNameRef(),"WKB_GEOMETRY") )
-        {
-            bHasWkb = TRUE;
-            if( nTypeOID == OIDOID )
-                bWkbAsOid = TRUE;
-            continue;
-        }
-
-        if( nTypeOID == BYTEAOID )
-        {
-            oField.SetType( OFTBinary );
-        }
-        else if( nTypeOID == CHAROID ||
-                 nTypeOID == TEXTOID ||
-                 nTypeOID == BPCHAROID ||
-                 nTypeOID == VARCHAROID )
-        {
-            oField.SetType( OFTString );
-
-            /* See http://www.mail-archive.com/pgsql-hackers@postgresql.org/msg57726.html */
-            /* nTypmod = width + 4 */
-            int nTypmod = PQfmod(hResult, iRawField);
-            if (nTypmod >= 4 && (nTypeOID == BPCHAROID ||
-                               nTypeOID == VARCHAROID ) )
-            {
-                oField.SetWidth( nTypmod - 4);
-            }
-        }
-        else if( nTypeOID == BOOLOID )
-        {
-            oField.SetType( OFTInteger );
-            oField.SetWidth( 1 );
-        }
-        else if (nTypeOID == INT2OID )
-        {
-            oField.SetType( OFTInteger );
-            oField.SetWidth( 5 );
-        }
-        else if (nTypeOID == INT4OID )
-        {
-            oField.SetType( OFTInteger );
-        }
-        else if ( nTypeOID == INT8OID )
-        {
-            /* FIXME: OFTInteger can not handle 64bit integers */
-            oField.SetType( OFTInteger );
-        }
-        else if( nTypeOID == FLOAT4OID ||
-                 nTypeOID == FLOAT8OID )
-        {
-            oField.SetType( OFTReal );
-        }
-        else if( nTypeOID == NUMERICOID )
-        {
-            /* See http://www.mail-archive.com/pgsql-hackers@postgresql.org/msg57726.html */
-            /* typmod = (width << 16) + precision + 4 */
-            int nTypmod = PQfmod(hResult, iRawField);
-            if (nTypmod >= 4)
-            {
-                int nWidth = (nTypmod - 4) >> 16;
-                int nPrecision = (nTypmod - 4) & 0xFFFF;
-                if (nWidth <= 10 && nPrecision == 0)
-                {
-                    oField.SetType( OFTInteger );
-                    oField.SetWidth( nWidth );
-                }
-                else
-                {
-                    oField.SetType( OFTReal );
-                    oField.SetWidth( nWidth );
-                    oField.SetPrecision( nPrecision );
-                }
-            }
-            else
-                oField.SetType( OFTReal );
-        }
-        else if ( nTypeOID == INT4ARRAYOID )
-        {
-            oField.SetType ( OFTIntegerList );
-        }
-        else if ( nTypeOID == FLOAT4ARRAYOID ||
-                  nTypeOID == FLOAT8ARRAYOID )
-        {
-            oField.SetType ( OFTRealList );
-        }
-        else if ( nTypeOID == TEXTARRAYOID ||
-                  nTypeOID == BPCHARARRAYOID ||
-                  nTypeOID == VARCHARARRAYOID )
-        {
-            oField.SetType ( OFTStringList );
-        }
-        else if ( nTypeOID == DATEOID )
-        {
-            oField.SetType( OFTDate );
-        }
-        else if ( nTypeOID == TIMEOID )
-        {
-            oField.SetType( OFTTime );
-        }
-        else if ( nTypeOID == TIMESTAMPOID ||
-                  nTypeOID == TIMESTAMPTZOID )
-        {
-            /* We can't deserialize properly timestamp with time zone */
-            /* with binary cursors */
-            if (nTypeOID == TIMESTAMPTZOID)
-                bCanUseBinaryCursor = FALSE;
-
-            oField.SetType( OFTDateTime );
-        }
-        else /* unknown type */
-        {
-            CPLDebug("PG", "Unhandled OID (%d) for column %d. Defaulting to String.", nTypeOID, iRawField);
-            oField.SetType( OFTString );
-        }
-        
-        poDefn->AddFieldDefn( &oField );
-    }
-
-    return poDefn;
-}
 
 /************************************************************************/
 /*                      BuildFullQueryStatement()                       */
@@ -340,7 +150,7 @@ int OGRPGResultLayer::GetFeatureCount( int bForce )
         "SELECT count(*) FROM (%s) AS ogrpgcount",
         pszQueryStatement );
 
-    hResult = PQexec(hPGConn, osCommand);
+    hResult = OGRPG_PQexec(hPGConn, osCommand);
     if( hResult != NULL && PQresultStatus(hResult) == PGRES_TUPLES_OK )
         nCount = atoi(PQgetvalue(hResult,0,0));
     else
@@ -361,13 +171,13 @@ int OGRPGResultLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCFastFeatureCount) ||
         EQUAL(pszCap,OLCFastSetNextByIndex) )
         return (m_poFilterGeom == NULL || 
-                ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != -2)) && m_poAttrQuery == NULL;
+                ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)) && m_poAttrQuery == NULL;
 
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != -2) && m_poAttrQuery == NULL;
+        return ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID) && m_poAttrQuery == NULL;
 
     else if( EQUAL(pszCap,OLCFastGetExtent) )
-        return (bHasPostGISGeometry && nSRSId != -2) && m_poAttrQuery == NULL;
+        return (bHasPostGISGeometry && nSRSId != UNDETERMINED_SRID) && m_poAttrQuery == NULL;
         
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
@@ -394,7 +204,7 @@ OGRFeature *OGRPGResultLayer::GetNextFeature()
             return NULL;
 
         if( (m_poFilterGeom == NULL
-            || ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != -2)
+            || ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)
             || FilterGeometry( poFeature->GetGeometryRef() ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
@@ -413,7 +223,7 @@ void OGRPGResultLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 {
     if( InstallFilter( poGeomIn ) )
     {
-        if ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != -2)
+        if ((bHasPostGISGeometry || bHasPostGISGeography) && nSRSId != UNDETERMINED_SRID)
         {
             if( m_poFilterGeom != NULL)
             {
@@ -429,8 +239,10 @@ void OGRPGResultLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
                 snprintf(szBox3D_2, sizeof(szBox3D_2), "%.12f %.12f", sEnvelope.MaxX, sEnvelope.MaxY);
                 while((pszComma = strchr(szBox3D_2, ',')) != NULL)
                     *pszComma = '.';
-                osWHERE.Printf("WHERE \"%s\" && SetSRID('BOX3D(%s, %s)'::box3d,%d) ",
-                            pszGeomColumn, szBox3D_1, szBox3D_2, nSRSId );
+                osWHERE.Printf("WHERE %s && %s('BOX3D(%s, %s)'::box3d,%d) ",
+                               OGRPGEscapeColumnName(pszGeomColumn).c_str(),
+                               (poDS->sPostGISVersion.nMajor >= 2) ? "ST_SetSRID" : "SetSRID",
+                               szBox3D_1, szBox3D_2, nSRSId );
             }
             else
             {
@@ -456,17 +268,25 @@ OGRErr OGRPGResultLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 {
     CPLString   osCommand;
 
+    const char* pszExtentFct;
+    if (poDS->sPostGISVersion.nMajor >= 2)
+        pszExtentFct = "ST_Extent";
+    else
+        pszExtentFct = "Extent";
+
     if ( TestCapability(OLCFastGetExtent) )
     {
         /* Do not take the spatial filter into account */
-        osCommand.Printf( "SELECT Extent(\"%s\") FROM (%s) AS ogrpgextent", 
-                         pszGeomColumn, pszRawStatement );
+        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 Extent(ST_GeomFromWKB(ST_AsBinary(\"%s\"))) FROM (%s) AS ogrpgextent", 
-                          pszGeomColumn, pszRawStatement );
+        osCommand.Printf( "SELECT %s(ST_GeomFromWKB(ST_AsBinary(%s))) FROM (%s) AS ogrpgextent",
+                          pszExtentFct, OGRPGEscapeColumnName(pszGeomColumn).c_str(),
+                          pszRawStatement );
     }
     
     return RunGetExtentRequest(psExtent, bForce, osCommand);
diff --git a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
index a3f2343..6f4c20f 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgtablelayer.cpp 22158 2011-04-14 18:10:01Z rouault $
+ * $Id: ogrpgtablelayer.cpp 23674 2012-01-01 14:32:18Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGTableLayer class, access to an existing table.
@@ -28,12 +28,13 @@
  ****************************************************************************/
 
 #include "ogr_pg.h"
-#include "ogrpgutility.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: ogrpgtablelayer.cpp 22158 2011-04-14 18:10:01Z rouault $");
+#define PQexec this_is_an_error
+
+CPL_CVSID("$Id: ogrpgtablelayer.cpp 23674 2012-01-01 14:32:18Z rouault $");
 
 #define USE_COPY_UNSET  -10
 static CPLString OGRPGEscapeStringList(PGconn *hPGConn,
@@ -66,6 +67,7 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
     bGeometryInformationSet = FALSE;
 
     bLaunderColumnNames = TRUE;
+    bPreservePrecision = TRUE;
     bCopyActive = FALSE;
     bUseCopy = USE_COPY_UNSET;  // unknown
 
@@ -98,7 +100,9 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
             osDefnName.Printf( "%s.%s(%s)", pszSchemaNameIn, pszTableName, pszGeomColumnIn );
         else
             osDefnName.Printf("%s.%s", pszSchemaNameIn, pszTableName );
-        pszSqlTableName = CPLStrdup(CPLString().Printf("\"%s\".\"%s\"", pszSchemaNameIn, pszTableName ));
+        pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
+                               OGRPGEscapeColumnName(pszSchemaNameIn).c_str(),
+                               OGRPGEscapeColumnName(pszTableName).c_str() ));
     }
     else
     {
@@ -109,7 +113,7 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
             osDefnName.Printf( "%s(%s)", pszTableName, pszGeomColumnIn );
         else
             osDefnName = pszTableName;
-        pszSqlTableName = CPLStrdup(CPLString().Printf("\"%s\"", pszTableName ));
+        pszSqlTableName = CPLStrdup(OGRPGEscapeColumnName(pszTableName));
     }
 
     osPrimaryKey = CPLGetConfigOption( "PGSQL_OGR_FID", "ogc_fid" );
@@ -138,7 +142,7 @@ void  OGRPGTableLayer::SetGeometryInformation(const char* pszType,
                                                int nSRID,
                                                PostgisType ePostgisType)
 {
-    if (pszType == NULL || nCoordDimension == 0 || nSRID == 0 ||
+    if (pszType == NULL || nCoordDimension == 0 || nSRID == UNDETERMINED_SRID ||
         ePostgisType == GEOM_TYPE_UNKNOWN)
         return;
 
@@ -200,6 +204,9 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
     else
         pszTypnameEqualsAnyClause = "ANY(ARRAY['int2','int4','serial'])";
 
+    CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn, pszTableName, -1, "");
+    const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
+
     /* See #1889 for why we don't use 'AND a.attnum = ANY(i.indkey)' */
     osCommand.Printf("SELECT a.attname, a.attnum, t.typname, "
               "t.typname = %s AS isfid "
@@ -207,14 +214,14 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
               "WHERE a.attnum > 0 AND a.attrelid = c.oid "
               "AND a.atttypid = t.oid AND c.relnamespace = n.oid "
               "AND c.oid = i.indrelid AND i.indisprimary = 't' "
-              "AND t.typname !~ '^geom' AND c.relname = '%s' "
+              "AND t.typname !~ '^geom' AND c.relname = %s "
               "AND (i.indkey[0]=a.attnum OR i.indkey[1]=a.attnum OR i.indkey[2]=a.attnum "
               "OR i.indkey[3]=a.attnum OR i.indkey[4]=a.attnum OR i.indkey[5]=a.attnum "
               "OR i.indkey[6]=a.attnum OR i.indkey[7]=a.attnum OR i.indkey[8]=a.attnum "
               "OR i.indkey[9]=a.attnum) %s ORDER BY a.attnum",
-              pszTypnameEqualsAnyClause, pszTableName, osSchemaClause.c_str() );
+              pszTypnameEqualsAnyClause, pszEscapedTableNameSingleQuote, osSchemaClause.c_str() );
      
-    hResult = PQexec(hPGConn, osCommand.c_str() );
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
     if ( hResult && PGRES_TUPLES_OK == PQresultStatus(hResult) )
     {
@@ -247,7 +254,7 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
 /* -------------------------------------------------------------------- */
 /*      Fire off commands to get back the columns of the table.          */
 /* -------------------------------------------------------------------- */
-    hResult = PQexec(hPGConn, "BEGIN");
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
 
     if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
     {
@@ -256,22 +263,23 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
         osCommand.Printf(
                  "DECLARE mycursor CURSOR for "
                  "SELECT DISTINCT a.attname, t.typname, a.attlen,"
-                 "       format_type(a.atttypid,a.atttypmod) "
+                 "       format_type(a.atttypid,a.atttypmod), a.attnum "
                  "FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n "
-                 "WHERE c.relname = '%s' "
+                 "WHERE c.relname = %s "
                  "AND a.attnum > 0 AND a.attrelid = c.oid "
                  "AND a.atttypid = t.oid "
                  "AND c.relnamespace=n.oid "
-                 "%s",
-                 pszTableName, osSchemaClause.c_str());
+                 "%s"
+                 "ORDER BY a.attnum",
+                 pszEscapedTableNameSingleQuote, osSchemaClause.c_str());
 
-        hResult = PQexec(hPGConn, osCommand.c_str() );
+        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
     }
 
     if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
     {
         OGRPGClearResult( hResult );
-        hResult = PQexec(hPGConn, "FETCH ALL in mycursor" );
+        hResult = OGRPG_PQexec(hPGConn, "FETCH ALL in mycursor" );
     }
 
     if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
@@ -287,10 +295,10 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
     {
         OGRPGClearResult( hResult );
 
-        hResult = PQexec(hPGConn, "CLOSE mycursor");
+        hResult = OGRPG_PQexec(hPGConn, "CLOSE mycursor");
         OGRPGClearResult( hResult );
 
-        hResult = PQexec(hPGConn, "COMMIT");
+        hResult = OGRPG_PQexec(hPGConn, "COMMIT");
         OGRPGClearResult( hResult );
 
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -316,7 +324,6 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
         pszType = PQgetvalue(hResult, iRecord, 1 );
         pszFormatType = PQgetvalue(hResult,iRecord,3);
 
-        /* TODO: Add detection of other primary key to use as FID */
         if( EQUAL(oField.GetNameRef(),osPrimaryKey) )
         {
             bHasFid = TRUE;
@@ -461,10 +468,10 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
 
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "CLOSE mycursor");
+    hResult = OGRPG_PQexec(hPGConn, "CLOSE mycursor");
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "COMMIT");
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
     /* If geometry type, SRID, etc... have always been set by SetGeometryInformation() */
@@ -484,7 +491,7 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
       {
         osCommand.Printf(
             "SELECT type, coord_dimension%s FROM %s WHERE f_table_name='%s'",
-            (nSRSId == -2) ? ", srid" : "",
+            (nSRSId == UNDETERMINED_SRID) ? ", srid" : "",
             (bHasPostGISGeometry) ? "geometry_columns" : "geography_columns",
             (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName);
         if (pszGeomColumn)
@@ -498,7 +505,7 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
             osCommand += CPLString().Printf(" AND f_table_schema='%s'", pszSchemaName);
         }
 
-        hResult = PQexec(hPGConn,osCommand);
+        hResult = OGRPG_PQexec(hPGConn,osCommand);
 
         if ( hResult && PQntuples(hResult) == 1 && !PQgetisnull(hResult,0,0) )
         {
@@ -506,7 +513,7 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
 
             nCoordDimension = MAX(2,MIN(3,atoi(PQgetvalue(hResult,0,1))));
 
-            if (nSRSId == -2)
+            if (nSRSId == UNDETERMINED_SRID)
                 nSRSId = atoi(PQgetvalue(hResult,0,2));
 
             SetGeometryInformation(pszType, nCoordDimension, nSRSId,
@@ -516,24 +523,28 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
         }
         else
         {
+            CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn,
+                    (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName, -1, "");
+            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'))",
-                                (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName, 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, pszSchemaName );
             }
             else
             {
                 osCommand.Printf("SELECT pg_class.relname FROM pg_class WHERE oid = "
                                 "(SELECT pg_inherits.inhparent FROM pg_inherits WHERE inhrelid = "
-                                "(SELECT pg_class.oid FROM pg_class WHERE relname = '%s'))",
-                                (pszSqlGeomParentTableName) ? pszSqlGeomParentTableName : pszTableName );
+                                "(SELECT pg_class.oid FROM pg_class WHERE relname = %s))",
+                                pszEscapedTableNameSingleQuote );
             }
 
             OGRPGClearResult( hResult );
-            hResult = PQexec(hPGConn, osCommand.c_str() );
+            hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
             if ( hResult && PQntuples( hResult ) == 1 && !PQgetisnull( hResult,0,0 ) )
             {
@@ -550,8 +561,8 @@ OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition()
         OGRPGClearResult( hResult );
       }
 
-      if (nSRSId == -2)
-          nSRSId = -1;
+      if (nSRSId == UNDETERMINED_SRID)
+          nSRSId = poDS->GetUndefinedSRID();
     }
     else if (pszGeomColumn == NULL)
     {
@@ -606,8 +617,10 @@ void OGRPGTableLayer::BuildWhere()
         snprintf(szBox3D_2, sizeof(szBox3D_2), "%.12f %.12f", sEnvelope.MaxX, sEnvelope.MaxY);
         while((pszComma = strchr(szBox3D_2, ',')) != NULL)
             *pszComma = '.';
-        osWHERE.Printf("WHERE \"%s\" && SetSRID('BOX3D(%s, %s)'::box3d,%d) ",
-                       pszGeomColumn, szBox3D_1, szBox3D_2, nSRSId );
+        osWHERE.Printf("WHERE %s && %s('BOX3D(%s, %s)'::box3d,%d) ",
+                       OGRPGEscapeColumnName(pszGeomColumn).c_str(),
+                       (poDS->sPostGISVersion.nMajor >= 2) ? "ST_SetSRID" : "SetSRID",
+                       szBox3D_1, szBox3D_2, nSRSId );
     }
 
     if( strlen(osQuery) > 0 )
@@ -709,9 +722,7 @@ CPLString OGRPGTableLayer::BuildFields()
 
     if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) == -1 )
     {
-        osFieldList += "\"";
-        osFieldList += pszFIDColumn;
-        osFieldList += "\"";
+        osFieldList += OGRPGEscapeColumnName(pszFIDColumn);
     }
 
     if( pszGeomColumn )
@@ -723,19 +734,17 @@ CPLString OGRPGTableLayer::BuildFields()
         {
             if ( poDS->bUseBinaryCursor )
             {
-                osFieldList += "\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\"";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
             }
             else if (CSLTestBoolean(CPLGetConfigOption("PG_USE_BASE64", "NO")) &&
                      nCoordDimension != 4 /* we don't know how to decode 4-dim EWKB for now */)
             {
                 if (poDS->sPostGISVersion.nMajor >= 2)
-                    osFieldList += "encode(ST_AsEWKB(\"";
+                    osFieldList += "encode(ST_AsEWKB(";
                 else
-                    osFieldList += "encode(AsEWKB(\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\"), 'base64') AS EWKBBase64";
+                    osFieldList += "encode(AsEWKB(";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += "), 'base64') AS EWKBBase64";
             }
             else if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) &&
                      nCoordDimension != 4 && /* we don't know how to decode 4-dim EWKB for now */
@@ -744,58 +753,52 @@ CPLString OGRPGTableLayer::BuildFields()
                       (poDS->sPostGISVersion.nMajor == 1 && poDS->sPostGISVersion.nMinor >= 1)) )
             {
                 /* This will return EWKB in an hex encoded form */
-                osFieldList += "\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\"";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
             }
             else if ( poDS->sPostGISVersion.nMajor >= 1 )
             {
                 if (poDS->sPostGISVersion.nMajor >= 2)
-                    osFieldList += "ST_AsEWKT(\"";
+                    osFieldList += "ST_AsEWKT(";
                 else
-                    osFieldList += "AsEWKT(\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\")";
+                    osFieldList += "AsEWKT(";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += ")";
             }
             else
             {
-                osFieldList += "AsText(\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\")";
+                osFieldList += "AsText(";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += ")";
             }
         }
         else if ( bHasPostGISGeography )
         {
             if ( poDS->bUseBinaryCursor )
             {
-                osFieldList += "ST_AsBinary(\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\")";
+                osFieldList += "ST_AsBinary(";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += ")";
             }
             else if (CSLTestBoolean(CPLGetConfigOption("PG_USE_BASE64", "NO")))
             {
-                osFieldList += "encode(ST_AsBinary(\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\"), 'base64') AS BinaryBase64";
+                osFieldList += "encode(ST_AsBinary(";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += "), 'base64') AS BinaryBase64";
             }
             else if ( !CSLTestBoolean(CPLGetConfigOption("PG_USE_TEXT", "NO")) )
             {
-                osFieldList += "\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\"";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
             }
             else
             {
-                osFieldList += "ST_AsText(\"";
-                osFieldList += pszGeomColumn;
-                osFieldList += "\")";
+                osFieldList += "ST_AsText(";
+                osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
+                osFieldList += ")";
             }
         }
         else
         {
-            osFieldList += "\"";
-            osFieldList += pszGeomColumn;
-            osFieldList += "\"";
+            osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
         }
     }
 
@@ -811,15 +814,13 @@ CPLString OGRPGTableLayer::BuildFields()
         if ( poDS->bUseBinaryCursor &&
              poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime)
         {
-            osFieldList += "CAST (\"";
-            osFieldList += pszName ;
-            osFieldList += "\" AS text)";
+            osFieldList += "CAST (";
+            osFieldList += OGRPGEscapeColumnName(pszName);
+            osFieldList += " AS text)";
         }
         else
         {
-            osFieldList += "\"";
-            osFieldList += pszName;
-            osFieldList += "\"" ;
+            osFieldList += OGRPGEscapeColumnName(pszName);
         }
     }
 
@@ -877,8 +878,8 @@ OGRErr OGRPGTableLayer::DeleteFeature( long nFID )
 /* -------------------------------------------------------------------- */
 /*      Form the statement to drop the record.                          */
 /* -------------------------------------------------------------------- */
-    osCommand.Printf( "DELETE FROM %s WHERE \"%s\" = %ld",
-                      pszSqlTableName, pszFIDColumn, nFID );
+    osCommand.Printf( "DELETE FROM %s WHERE %s = %ld",
+                      pszSqlTableName, OGRPGEscapeColumnName(pszFIDColumn).c_str(), nFID );
 
 /* -------------------------------------------------------------------- */
 /*      Execute the delete.                                             */
@@ -889,7 +890,7 @@ OGRErr OGRPGTableLayer::DeleteFeature( long nFID )
     if( eErr != OGRERR_NONE )
         return eErr;
 
-    hResult = PQexec(hPGConn, osCommand);
+    hResult = OGRPG_PQexec(hPGConn, osCommand);
 
     if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
     {
@@ -997,6 +998,9 @@ void OGRPGTableLayer::AppendFieldValue(PGconn *hPGConn, CPLString& osCommand,
     // Binary formatting
     else if( nOGRFieldType == OFTBinary )
     {
+        if (poDS->bUseEscapeStringSyntax)
+            osCommand += "E";
+
         osCommand += "'";
 
         int nLen = 0;
@@ -1116,6 +1120,8 @@ OGRErr OGRPGTableLayer::SetFeature( OGRFeature *poFeature )
 
                 if( pszBytea != NULL )
                 {
+                    if (poDS->bUseEscapeStringSyntax)
+                        osCommand += "E";
                     osCommand = osCommand + "'" + pszBytea + "'";
                     CPLFree( pszBytea );
                 }
@@ -1140,38 +1146,59 @@ OGRErr OGRPGTableLayer::SetFeature( OGRFeature *poFeature )
     }
     else if( bHasPostGISGeometry || bHasPostGISGeography )
     {
-        osCommand = osCommand + "\"" + pszGeomColumn + "\" = ";
-        char    *pszWKT = NULL;
-
+        osCommand = osCommand + OGRPGEscapeColumnName(pszGeomColumn) + " = ";
+        OGRGeometry *poGeom = NULL;
+        
         if( poFeature->GetGeometryRef() != NULL )
         {
-            OGRGeometry *poGeom = (OGRGeometry *) poFeature->GetGeometryRef();
+            poGeom = (OGRGeometry *) poFeature->GetGeometryRef();
 
             poGeom->closeRings();
             poGeom->setCoordinateDimension( nCoordDimension );
 
-            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 = GeometryToHex( poGeom, nSRSId );
+                if ( bHasPostGISGeography )
+                    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 );
 
+            if( pszWKT != 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 );
+            }
+            else
+                osCommand += "NULL";
+
+        }
         bNeedComma = TRUE;
     }
 
@@ -1183,7 +1210,7 @@ OGRErr OGRPGTableLayer::SetFeature( OGRFeature *poFeature )
             bNeedComma = TRUE;
 
         osCommand = osCommand 
-            + "\"" + poFeatureDefn->GetFieldDefn(i)->GetNameRef() + "\" = ";
+            + OGRPGEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + " = ";
 
         if( !poFeature->IsFieldSet( i ) )
         {
@@ -1197,13 +1224,13 @@ OGRErr OGRPGTableLayer::SetFeature( OGRFeature *poFeature )
 
     /* Add the WHERE clause */
     osCommand += " WHERE ";
-    osCommand = osCommand + "\"" + pszFIDColumn + "\" = ";
+    osCommand = osCommand + OGRPGEscapeColumnName(pszFIDColumn) + " = ";
     osCommand += CPLString().Printf( "%ld ", poFeature->GetFID() );
 
 /* -------------------------------------------------------------------- */
 /*      Execute the update.                                             */
 /* -------------------------------------------------------------------- */
-    hResult = PQexec(hPGConn, osCommand);
+    hResult = OGRPG_PQexec(hPGConn, osCommand);
     if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1255,6 +1282,29 @@ OGRErr OGRPGTableLayer::CreateFeature( OGRFeature *poFeature )
 }
 
 /************************************************************************/
+/*                       OGRPGEscapeColumnName( )                       */
+/************************************************************************/
+
+CPLString OGRPGEscapeColumnName(const char* pszColumnName)
+{
+    CPLString osStr;
+
+    osStr += "\"";
+
+    char ch;
+    for(int i=0; (ch = pszColumnName[i]) != '\0'; i++)
+    {
+        if (ch == '"')
+            osStr.append(1, ch);
+        osStr.append(1, ch);
+    }
+
+    osStr += "\"";
+
+    return osStr;
+}
+
+/************************************************************************/
 /*                         OGRPGEscapeString( )                         */
 /************************************************************************/
 
@@ -1388,6 +1438,8 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
         return eErr;
     }
 
+    int bEmptyInsert = FALSE;
+
 /* -------------------------------------------------------------------- */
 /*      Form the INSERT command.                                        */
 /* -------------------------------------------------------------------- */
@@ -1402,20 +1454,17 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
     }
     else if( (bHasPostGISGeometry || bHasPostGISGeography) && poGeom != NULL )
     {
-        osCommand = osCommand + "\"" + pszGeomColumn + "\" ";
+        osCommand = osCommand + OGRPGEscapeColumnName(pszGeomColumn) + " ";
         bNeedComma = TRUE;
     }
 
-    /* REMOVE ME ? */
-    /* Hum, this is weird if we create a feature with an already existings */
-    /* FID ! I see this code path is never taken in the coverage analysis of */
-    /* the autotest suite, so we could probably remove it ? */
+    /* Use case of ogr_pg_60 test */
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     {
         if( bNeedComma )
             osCommand += ", ";
         
-        osCommand = osCommand + "\"" + pszFIDColumn + "\" ";
+        osCommand = osCommand + OGRPGEscapeColumnName(pszFIDColumn) + " ";
         bNeedComma = TRUE;
     }
 
@@ -1431,43 +1480,59 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
             osCommand += ", ";
 
         osCommand = osCommand 
-            + "\"" + poFeatureDefn->GetFieldDefn(i)->GetNameRef() + "\"";
+            + OGRPGEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     }
 
+    if (!bNeedComma)
+        bEmptyInsert = TRUE;
+
     osCommand += ") VALUES (";
 
     /* Set the geometry */
     bNeedComma = FALSE;
     if( (bHasPostGISGeometry || bHasPostGISGeography) && poGeom != NULL)
     {
-        char    *pszWKT = NULL;
         
         CheckGeomTypeCompatibility(poGeom);
 
         poGeom->closeRings();
         poGeom->setCoordinateDimension( nCoordDimension );
 
-        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 );
+            char    *pszHexEWKB = GeometryToHex( poGeom, nSRSId );
+            if ( bHasPostGISGeography )
+                osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
             else
-                osCommand += 
-                    CPLString().Printf(
-                        "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
-            OGRFree( pszWKT );
+                osCommand += CPLString().Printf("'%s'::GEOMETRY", pszHexEWKB);
+            OGRFree( pszHexEWKB );
         }
         else
-            osCommand += "''";
+        { 
+            char    *pszWKT = NULL;
+            poGeom->exportToWkt( &pszWKT );
+
+            if( pszWKT != 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 );
+            }
+            else
+                osCommand += "''";
             
+        }
         bNeedComma = TRUE;
     }
     else if( bHasWkb && !bWkbAsOid && poGeom != NULL )
@@ -1476,6 +1541,8 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 
         if( pszBytea != NULL )
         {
+            if (poDS->bUseEscapeStringSyntax)
+                osCommand += "E";
             osCommand = osCommand + "'" + pszBytea + "'";
             CPLFree( pszBytea );
         }
@@ -1498,11 +1565,6 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
         bNeedComma = TRUE;
     }
 
-    /* REMOVE ME ? */
-    /* Hum, this is weird if we create a feature with an already existings */
-    /* FID ! I see this code path is never taken in the coverage analysis of */
-    /* the autotest suite, so we could probably remove it ? */
-    /* Set the FID */
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     {
         if( bNeedComma )
@@ -1527,6 +1589,9 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 
     osCommand += ")";
 
+    if (bEmptyInsert)
+        osCommand.Printf( "INSERT INTO %s DEFAULT VALUES", pszSqlTableName );
+
     int bReturnRequested = FALSE;
     /* RETURNING is only available since Postgres 8.2 */
     /* We only get the FID, but we also could add the unset fields to get */
@@ -1537,13 +1602,13 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
     {
         bReturnRequested = TRUE;
         osCommand += " RETURNING ";
-        osCommand += pszFIDColumn;
+        osCommand += OGRPGEscapeColumnName(pszFIDColumn);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Execute the insert.                                             */
 /* -------------------------------------------------------------------- */
-    hResult = PQexec(hPGConn, osCommand);
+    hResult = OGRPG_PQexec(hPGConn, osCommand);
     if (bReturnRequested && PQresultStatus(hResult) == PGRES_TUPLES_OK &&
         PQntuples(hResult) == 1 && PQnfields(hResult) == 1 )
     {
@@ -1829,10 +1894,14 @@ int OGRPGTableLayer::TestCapability( const char * pszCap )
 
     if ( bUpdateAccess )
     {
-        if( EQUAL(pszCap,OLCSequentialWrite) || EQUAL(pszCap,OLCCreateField) )
+        if( EQUAL(pszCap,OLCSequentialWrite) ||
+            EQUAL(pszCap,OLCCreateField) ||
+            EQUAL(pszCap,OLCDeleteField) ||
+            EQUAL(pszCap,OLCAlterFieldDefn) )
             return TRUE;
 
-        else if( EQUAL(pszCap,OLCRandomWrite) )
+        else if( EQUAL(pszCap,OLCRandomWrite) ||
+                 EQUAL(pszCap,OLCDeleteFeature) )
             return bHasFid;
     }
 
@@ -1860,38 +1929,14 @@ int OGRPGTableLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                            CreateField()                             */
+/*                        OGRPGTableLayerGetType()                      */
 /************************************************************************/
 
-OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
-
+static CPLString OGRPGTableLayerGetType(OGRFieldDefn& oField,
+                                        int bPreservePrecision,
+                                        int bApproxOK)
 {
-    PGconn              *hPGConn = poDS->GetPGConn();
-    PGresult            *hResult = NULL;
-    CPLString           osCommand;
     char                szFieldType[256];
-    OGRFieldDefn        oField( poFieldIn );
-
-    GetLayerDefn();
-
-/* -------------------------------------------------------------------- */
-/*      Do we want to "launder" the column names into Postgres          */
-/*      friendly format?                                                */
-/* -------------------------------------------------------------------- */
-    if( bLaunderColumnNames )
-    {
-        char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
-
-        oField.SetName( pszSafeName );
-        CPLFree( pszSafeName );
-
-        if( EQUAL(oField.GetNameRef(),"oid") )
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Renaming field 'oid' to 'oid_' to avoid conflict with internal oid field." );
-            oField.SetName( "oid_" );
-        }
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Work out the PostgreSQL type.                                   */
@@ -1914,10 +1959,10 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     }
     else if( oField.GetType() == OFTString )
     {
-        if( oField.GetWidth() == 0 || !bPreservePrecision )
-            strcpy( szFieldType, "VARCHAR" );
+        if (oField.GetWidth() > 0 &&  bPreservePrecision )
+            sprintf( szFieldType, "VARCHAR(%d)",  oField.GetWidth() );
         else
-            sprintf( szFieldType, "CHAR(%d)", oField.GetWidth() );
+            strcpy( szFieldType, "VARCHAR");
     }
     else if( oField.GetType() == OFTIntegerList )
     {
@@ -1961,20 +2006,61 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
                   "Can't create field %s with type %s on PostgreSQL layers.",
                   oField.GetNameRef(),
                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
+        strcpy( szFieldType, "");
+    }
 
-        return OGRERR_FAILURE;
+    return szFieldType;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/************************************************************************/
+
+OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
+
+{
+    PGconn              *hPGConn = poDS->GetPGConn();
+    PGresult            *hResult = NULL;
+    CPLString           osCommand;
+    CPLString           osFieldType;
+    OGRFieldDefn        oField( poFieldIn );
+
+    GetLayerDefn();
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to "launder" the column names into Postgres          */
+/*      friendly format?                                                */
+/* -------------------------------------------------------------------- */
+    if( bLaunderColumnNames )
+    {
+        char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
+
+        oField.SetName( pszSafeName );
+        CPLFree( pszSafeName );
+
+        if( EQUAL(oField.GetNameRef(),"oid") )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Renaming field 'oid' to 'oid_' to avoid conflict with internal oid field." );
+            oField.SetName( "oid_" );
+        }
     }
 
+    osFieldType = OGRPGTableLayerGetType(oField, bPreservePrecision, bApproxOK);
+    if (osFieldType.size() == 0)
+        return OGRERR_FAILURE;
+
 /* -------------------------------------------------------------------- */
 /*      Create the new field.                                           */
 /* -------------------------------------------------------------------- */
     poDS->FlushSoftTransaction();
-    hResult = PQexec(hPGConn, "BEGIN");
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
     OGRPGClearResult( hResult );
 
-    osCommand.Printf( "ALTER TABLE %s ADD COLUMN \"%s\" %s",
-                      pszSqlTableName, oField.GetNameRef(), szFieldType );
-    hResult = PQexec(hPGConn, osCommand);
+    osCommand.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
+                      pszSqlTableName, OGRPGEscapeColumnName(oField.GetNameRef()).c_str(),
+                      osFieldType.c_str() );
+    hResult = OGRPG_PQexec(hPGConn, osCommand);
     if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1984,7 +2070,7 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 
         OGRPGClearResult( hResult );
 
-        hResult = PQexec( hPGConn, "ROLLBACK" );
+        hResult = OGRPG_PQexec( hPGConn, "ROLLBACK" );
         OGRPGClearResult( hResult );
 
         return OGRERR_FAILURE;
@@ -1992,7 +2078,7 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "COMMIT");
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
     OGRPGClearResult( hResult );
 
     poFeatureDefn->AddFieldDefn( &oField );
@@ -2001,6 +2087,202 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
 }
 
 /************************************************************************/
+/*                            DeleteField()                             */
+/************************************************************************/
+
+OGRErr OGRPGTableLayer::DeleteField( int iField )
+{
+    PGconn              *hPGConn = poDS->GetPGConn();
+    PGresult            *hResult = NULL;
+    CPLString           osCommand;
+
+    GetLayerDefn();
+
+    if( !bUpdateAccess )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't delete fields on a read-only datasource.");
+        return OGRERR_FAILURE;
+    }
+
+    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    poDS->FlushSoftTransaction();
+
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
+    OGRPGClearResult( hResult );
+
+    osCommand.Printf( "ALTER TABLE %s DROP COLUMN %s",
+                      pszSqlTableName,
+                      OGRPGEscapeColumnName(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()).c_str() );
+    hResult = OGRPG_PQexec(hPGConn, osCommand);
+    if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s\n%s",
+                  osCommand.c_str(),
+                  PQerrorMessage(hPGConn) );
+
+        OGRPGClearResult( hResult );
+
+        hResult = OGRPG_PQexec( hPGConn, "ROLLBACK" );
+        OGRPGClearResult( hResult );
+
+        return OGRERR_FAILURE;
+    }
+
+    OGRPGClearResult( hResult );
+
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
+    OGRPGClearResult( hResult );
+
+    return poFeatureDefn->DeleteFieldDefn( iField );
+}
+
+/************************************************************************/
+/*                           AlterFieldDefn()                           */
+/************************************************************************/
+
+OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+{
+    PGconn              *hPGConn = poDS->GetPGConn();
+    PGresult            *hResult = NULL;
+    CPLString           osCommand;
+
+    GetLayerDefn();
+
+    if( !bUpdateAccess )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't alter field definition on a read-only datasource.");
+        return OGRERR_FAILURE;
+    }
+
+    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    OGRFieldDefn       *poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
+    OGRFieldDefn        oField( poNewFieldDefn );
+
+    poDS->FlushSoftTransaction();
+
+    hResult = OGRPG_PQexec(hPGConn, "BEGIN");
+    OGRPGClearResult( hResult );
+
+    if (!(nFlags & ALTER_TYPE_FLAG))
+        oField.SetType(poFieldDefn->GetType());
+
+    if (!(nFlags & ALTER_WIDTH_PRECISION_FLAG))
+    {
+        oField.SetWidth(poFieldDefn->GetWidth());
+        oField.SetPrecision(poFieldDefn->GetPrecision());
+    }
+
+    if ((nFlags & ALTER_TYPE_FLAG) ||
+        (nFlags & ALTER_WIDTH_PRECISION_FLAG))
+    {
+        CPLString osFieldType = OGRPGTableLayerGetType(oField,
+                                                       bPreservePrecision,
+                                                       TRUE);
+        if (osFieldType.size() == 0)
+        {
+            hResult = OGRPG_PQexec( hPGConn, "ROLLBACK" );
+            OGRPGClearResult( hResult );
+
+            return OGRERR_FAILURE;
+        }
+
+        osCommand.Printf( "ALTER TABLE %s ALTER COLUMN %s TYPE %s",
+                        pszSqlTableName,
+                        OGRPGEscapeColumnName(poFieldDefn->GetNameRef()).c_str(),
+                        osFieldType.c_str() );
+        hResult = OGRPG_PQexec(hPGConn, osCommand);
+        if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "%s\n%s",
+                    osCommand.c_str(),
+                    PQerrorMessage(hPGConn) );
+
+            OGRPGClearResult( hResult );
+
+            hResult = OGRPG_PQexec( hPGConn, "ROLLBACK" );
+            OGRPGClearResult( hResult );
+
+            return OGRERR_FAILURE;
+        }
+        OGRPGClearResult( hResult );
+    }
+
+
+    if( (nFlags & ALTER_NAME_FLAG) )
+    {
+        if (bLaunderColumnNames)
+        {
+            char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
+            oField.SetName( pszSafeName );
+            CPLFree( pszSafeName );
+        }
+
+        if( EQUAL(oField.GetNameRef(),"oid") )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Renaming field 'oid' to 'oid_' to avoid conflict with internal oid field." );
+            oField.SetName( "oid_" );
+        }
+
+        if ( strcmp(poFieldDefn->GetNameRef(), oField.GetNameRef()) != 0 )
+        {
+            osCommand.Printf( "ALTER TABLE %s RENAME COLUMN %s TO %s",
+                            pszSqlTableName,
+                            OGRPGEscapeColumnName(poFieldDefn->GetNameRef()).c_str(),
+                            OGRPGEscapeColumnName(oField.GetNameRef()).c_str() );
+            hResult = OGRPG_PQexec(hPGConn, osCommand);
+            if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "%s\n%s",
+                        osCommand.c_str(),
+                        PQerrorMessage(hPGConn) );
+
+                OGRPGClearResult( hResult );
+
+                hResult = OGRPG_PQexec( hPGConn, "ROLLBACK" );
+                OGRPGClearResult( hResult );
+
+                return OGRERR_FAILURE;
+            }
+            OGRPGClearResult( hResult );
+        }
+    }
+
+    hResult = OGRPG_PQexec(hPGConn, "COMMIT");
+    OGRPGClearResult( hResult );
+
+    if (nFlags & ALTER_NAME_FLAG)
+        poFieldDefn->SetName(oField.GetNameRef());
+    if (nFlags & ALTER_TYPE_FLAG)
+        poFieldDefn->SetType(oField.GetType());
+    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    {
+        poFieldDefn->SetWidth(oField.GetWidth());
+        poFieldDefn->SetPrecision(oField.GetPrecision());
+    }
+
+    return OGRERR_NONE;
+
+}
+
+/************************************************************************/
 /*                             GetFeature()                             */
 /************************************************************************/
 
@@ -2031,18 +2313,18 @@ OGRFeature *OGRPGTableLayer::GetFeature( long nFeatureId )
 
     osCommand.Printf(
              "DECLARE getfeaturecursor %s for "
-             "SELECT %s FROM %s WHERE \"%s\" = %ld",
+             "SELECT %s FROM %s WHERE %s = %ld",
               ( poDS->bUseBinaryCursor ) ? "BINARY CURSOR" : "CURSOR",
-             osFieldList.c_str(), pszSqlTableName, pszFIDColumn,
+             osFieldList.c_str(), pszSqlTableName, OGRPGEscapeColumnName(pszFIDColumn).c_str(),
              nFeatureId );
 
-    hResult = PQexec(hPGConn, osCommand.c_str() );
+    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
     if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )
     {
         OGRPGClearResult( hResult );
 
-        hResult = PQexec(hPGConn, "FETCH ALL in getfeaturecursor" );
+        hResult = OGRPG_PQexec(hPGConn, "FETCH ALL in getfeaturecursor" );
 
         if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK )
         {
@@ -2068,13 +2350,18 @@ OGRFeature *OGRPGTableLayer::GetFeature( long nFeatureId )
             }
         }
     }
+    else if ( hResult && PQresultStatus(hResult) == PGRES_FATAL_ERROR )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", PQresultErrorMessage( hResult ) );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
     OGRPGClearResult( hResult );
 
-    hResult = PQexec(hPGConn, "CLOSE getfeaturecursor");
+    hResult = OGRPG_PQexec(hPGConn, "CLOSE getfeaturecursor");
     OGRPGClearResult( hResult );
 
     poDS->FlushSoftTransaction();
@@ -2109,7 +2396,7 @@ int OGRPGTableLayer::GetFeatureCount( int bForce )
         "SELECT count(*) FROM %s %s",
         pszSqlTableName, osWHERE.c_str() );
 
-    hResult = PQexec(hPGConn, osCommand);
+    hResult = OGRPG_PQexec(hPGConn, osCommand);
     if( hResult != NULL && PQresultStatus(hResult) == PGRES_TUPLES_OK )
         nCount = atoi(PQgetvalue(hResult,0,0));
     else
@@ -2123,20 +2410,20 @@ 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 -2 (meaning we           */
-/*      haven't yet even looked for it).                                */
+/*      geometry_columns table if the srsid is UNDETERMINED_SRID        */
+/*      (meaning we haven't yet even looked for it).                    */
 /************************************************************************/
 
 OGRSpatialReference *OGRPGTableLayer::GetSpatialRef()
 
 {
-    if( nSRSId == -2 )
+    if( nSRSId == UNDETERMINED_SRID )
     {
         PGconn      *hPGConn = poDS->GetPGConn();
         PGresult    *hResult = NULL;
         CPLString    osCommand;
 
-        nSRSId = -1;
+        nSRSId = poDS->GetUndefinedSRID();
 
         poDS->SoftStartTransaction();
 
@@ -2155,7 +2442,7 @@ OGRSpatialReference *OGRPGTableLayer::GetSpatialRef()
             osCommand += CPLString().Printf(" AND f_table_schema = '%s'", pszSchemaName);
         }
 
-        hResult = PQexec(hPGConn, osCommand.c_str() );
+        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
         if( hResult
             && PQresultStatus(hResult) == PGRES_TUPLES_OK
@@ -2185,16 +2472,23 @@ OGRErr OGRPGTableLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 
     GetLayerDefn();
 
+    const char* pszExtentFct;
+    if (poDS->sPostGISVersion.nMajor >= 2)
+        pszExtentFct = "ST_Extent";
+    else
+        pszExtentFct = "Extent";
+
     if ( TestCapability(OLCFastGetExtent) )
     {
-        osCommand.Printf( "SELECT Extent(\"%s\") FROM %s", 
-                          pszGeomColumn, pszSqlTableName );
+        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 Extent(ST_GeomFromWKB(ST_AsBinary(\"%s\"))) FROM %s", 
-                          pszGeomColumn, pszSqlTableName );
+        osCommand.Printf( "SELECT %s(ST_GeomFromWKB(ST_AsBinary(%s))) FROM %s",
+                          pszExtentFct,
+                          OGRPGEscapeColumnName(pszGeomColumn).c_str(), pszSqlTableName );
     }
 
     return RunGetExtentRequest(psExtent, bForce, osCommand);
@@ -2222,7 +2516,7 @@ OGRErr OGRPGTableLayer::StartCopy()
              pszSqlTableName, osFields.c_str() );
 
     PGconn *hPGConn = poDS->GetPGConn();
-    PGresult *hResult = PQexec(hPGConn, pszCommand);
+    PGresult *hResult = OGRPG_PQexec(hPGConn, pszCommand);
 
     if ( !hResult || (PQresultStatus(hResult) != PGRES_COPY_IN))
     {
@@ -2315,9 +2609,7 @@ CPLString OGRPGTableLayer::BuildCopyFields()
 
     if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) != -1 )
     {
-        osFieldList += "\"";
-        osFieldList += pszFIDColumn;
-        osFieldList += "\"";
+        osFieldList += OGRPGEscapeColumnName(pszFIDColumn);
     }
 
     if( pszGeomColumn )
@@ -2325,9 +2617,7 @@ CPLString OGRPGTableLayer::BuildCopyFields()
         if( strlen(osFieldList) > 0 )
             osFieldList += ", ";
 
-        osFieldList += "\"";
-        osFieldList += pszGeomColumn;
-        osFieldList += "\"";
+        osFieldList += OGRPGEscapeColumnName(pszGeomColumn);
     }
 
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
@@ -2337,9 +2627,7 @@ CPLString OGRPGTableLayer::BuildCopyFields()
         if( strlen(osFieldList) > 0 )
             osFieldList += ", ";
 
-        osFieldList += "\"";
-        osFieldList += pszName;
-        osFieldList += "\"" ;
+        osFieldList += OGRPGEscapeColumnName(pszName);
     }
 
     return osFieldList;
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
new file mode 100644
index 0000000..ebfac7e
--- /dev/null
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
@@ -0,0 +1,92 @@
+/******************************************************************************
+ * $Id: ogrpgutility.cpp 22919 2011-08-10 18:12:05Z 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
+ *
+ * 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_pg.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrpgutility.cpp 22919 2011-08-10 18:12:05Z rouault $");
+
+/************************************************************************/
+/*                         OGRPG_PQexec()                               */
+/************************************************************************/
+
+PGresult *OGRPG_PQexec(PGconn *conn, const char *query, int bMultipleCommandAllowed)
+{
+    PGresult* hResult;
+#if defined(PG_PRE74)
+    /* PQexecParams introduced in PG >= 7.4 */
+    hResult = PQexec(conn, query);
+#else
+    if (bMultipleCommandAllowed)
+        hResult = PQexec(conn, query);
+    else
+        hResult = PQexecParams(conn, query, 0, NULL, NULL, NULL, NULL, 0);
+#endif
+
+#ifdef DEBUG
+    const char* pszRetCode = "UNKNOWN";
+    char szNTuples[32];
+    szNTuples[0] = '\0';
+    if (hResult)
+    {
+        switch(PQresultStatus(hResult))
+        {
+            case PGRES_TUPLES_OK:
+                pszRetCode = "PGRES_TUPLES_OK";
+                sprintf(szNTuples, ", ntuples = %d", PQntuples(hResult));
+                break;
+            case PGRES_COMMAND_OK:
+                pszRetCode = "PGRES_COMMAND_OK";
+                break;
+            case PGRES_NONFATAL_ERROR:
+                pszRetCode = "PGRES_NONFATAL_ERROR";
+                break;
+            case PGRES_FATAL_ERROR:
+                pszRetCode = "PGRES_FATAL_ERROR";
+                break;
+            default: break;
+        }
+    }
+    if (bMultipleCommandAllowed)
+        CPLDebug("PG", "PQexec(%s) = %s%s", query, pszRetCode, szNTuples);
+    else
+        CPLDebug("PG", "PQexecParams(%s) = %s%s", query, pszRetCode, szNTuples);
+
+/* -------------------------------------------------------------------- */
+/*      Generate an error report if an error occured.                   */
+/* -------------------------------------------------------------------- */
+    if ( !hResult || (PQresultStatus(hResult) == PGRES_NONFATAL_ERROR ||
+                      PQresultStatus(hResult) == PGRES_FATAL_ERROR ) )
+    {
+        CPLDebug( "PG", "%s", PQerrorMessage( conn ) );
+    }
+#endif
+
+    return hResult;
+}
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.h b/ogr/ogrsf_frmts/pg/ogrpgutility.h
index 976a51f..de6a1a3 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgutility.h
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgutility.h 10931 2007-03-11 11:22:31Z mloskot $
+ * $Id: ogrpgutility.h 22450 2011-05-28 21:25:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private utilities for OGR/PostgreSQL driver.
@@ -32,6 +32,9 @@
 
 #include "libpq-fe.h"
 
+PGresult *OGRPG_PQexec(PGconn *conn, const char *query,
+                       int bMultipleCommandAllowed = FALSE);
+
 /************************************************************************/
 /*                            OGRPGClearResult                          */
 /*                                                                      */
diff --git a/ogr/ogrsf_frmts/pgdump/drv_pgdump.html b/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
index 988b108..48a8041 100644
--- a/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
+++ b/ogr/ogrsf_frmts/pgdump/drv_pgdump.html
@@ -18,9 +18,6 @@ This driver is very similar to the PostGIS shp2pgsql utility.<p>
 
 Most creation options are shared with the regular PostgreSQL driver.<p>
 
-The driver opens the output file through the VSIF Large API, so it is possible
-to specify /vsistdout/ as output file to output on the standard output.<p>
-
 <h2>Creation options</h2>
 
 <h3>Dataset Creation Options</h3>
@@ -68,6 +65,12 @@ This option will have no effect if PG_USE_COPY environment variable is to YES.<p
 <li> <b>DROP_TABLE</b>: (OGR >= 1.8.1) Set to ON by default so that tables are destroyed before being recreated.
 Set to OFF to prevent DROP TABLE from being emitted. Set to IF_EXISTS in order DROP TABLE IF EXISTS to be emitted (needs PostgreSQL >= 8.2)<p>
 <li> <b>SRID</b>: Set the SRID of the geometry. Defaults to -1, unless a SRS is associated with the layer. In the case, if the EPSG code is mentionned, it will be used as the SRID. (Note: the spatial_ref_sys table must be correctly populated with the specified SRID) <p>
+<li> <b>NONE_AS_UNKNOWN</b>: (From GDAL 1.9.0) Can bet set to TRUE to force non-spatial layers (wkbNone) to be created as
+spatial tables of type GEOMETRY (wkbUnknown), which was the behaviour prior to GDAL 1.8.0. Defaults to NO, in which case
+a regular table is created and not recorded in the PostGIS geometry_columns table.<p>
+<li> <b>FID</b>: (From GDAL 1.9.0) Name of the FID column to create. Defaults to 'ogc_fid'.<p>
+<li> <b>EXTRACT_SCHEMA_FROM_LAYER_NAME</b>: (From GDAL 1.9.0) Can be set to NO to avoid considering the dot character
+as the separator between the schema and the table name. Defaults to YES.<p>
 </ul>
 
 <h3>Environment variables</h3>
@@ -77,6 +80,15 @@ Set to OFF to prevent DROP TABLE from being emitted. Set to IF_EXISTS in order D
 COPY is less robust than INSERT, but significantly faster.</li><p>
 </ul>
 
+<h3>VSI Virtual File System API support</h3>
+
+(Some features below might require OGR >= 1.9.0)<p>
+
+The driver supports rwriting to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/, /vsigzip/ domains.<p>
+
+Writing to /dev/stdout or /vsistdout/ is also supported.<p>
+
 <h3>Example</h3>
 
 <ul>
diff --git a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
index 5ee90d0..5e14081 100755
--- a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
+++ b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pgdump.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogr_pgdump.h 22821 2011-07-28 17:54:47Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL dump driver.
@@ -33,6 +33,10 @@
 #include "ogrsf_frmts.h"
 #include "cpl_string.h"
 
+CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName);
+CPLString OGRPGDumpEscapeString(   const char* pszStrValue, int nMaxLength,
+                                   const char* pszFieldName);
+
 /************************************************************************/
 /*                          OGRPGDumpLayer                              */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
index 390f3f0..9cbe1e7 100755
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdumpdatasource.cpp 22138 2011-04-11 18:03:16Z rouault $
+ * $Id: ogrpgdumpdatasource.cpp 22821 2011-07-28 17:54:47Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpDataSource class.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 22138 2011-04-11 18:03:16Z rouault $");
+CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 22821 2011-07-28 17:54:47Z rouault $");
 
 /************************************************************************/
 /*                      OGRPGDumpDataSource()                           */
@@ -139,7 +139,7 @@ char *OGRPGDumpDataSource::LaunderName( const char *pszSrcName )
     for( int i = 0; pszSafeName[i] != '\0'; i++ )
     {
         pszSafeName[i] = (char) tolower( pszSafeName[i] );
-        if( pszSafeName[i] == '-' || pszSafeName[i] == '#' )
+        if( pszSafeName[i] == '\'' || pszSafeName[i] == '-' || pszSafeName[i] == '#' )
             pszSafeName[i] = '_';
     }
 
@@ -155,7 +155,7 @@ char *OGRPGDumpDataSource::LaunderName( const char *pszSrcName )
 /************************************************************************/
 
 OGRLayer *
-OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
+OGRPGDumpDataSource::CreateLayer( const char * pszLayerName,
                                   OGRSpatialReference *poSRS,
                                   OGRwkbGeometryType eType,
                                   char ** papszOptions )
@@ -163,17 +163,29 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
 {
     CPLString            osCommand;
     const char          *pszGeomType = NULL;
-    char                *pszLayerName = NULL;
-    const char          *pszTableName = NULL;
+    char                *pszTableName = NULL;
     char                *pszSchemaName = NULL;
     int                  nDimension = 3;
-    const char          *pszFIDColumn = "OGC_FID";
     int                  bHavePostGIS = TRUE;
 
-    if (pszLayerNameIn == NULL)
-        return NULL;
+    const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
+    CPLString osFIDColumnName;
+    if (pszFIDColumnName == NULL)
+        osFIDColumnName = "OGC_FID";
+    else
+    {
+        if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+        {
+            char* pszLaunderedFid = LaunderName(pszFIDColumnName);
+            osFIDColumnName += OGRPGDumpEscapeColumnName(pszLaunderedFid);
+            CPLFree(pszLaunderedFid);
+        }
+        else
+            osFIDColumnName += OGRPGDumpEscapeColumnName(pszFIDColumnName);
+    }
+    pszFIDColumnName = osFIDColumnName.c_str();
 
-    if (strncmp(pszLayerNameIn, "pg", 2) == 0)
+    if (strncmp(pszLayerName, "pg", 2) == 0)
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "The layer name should not begin by 'pg' as it is a reserved prefix");
@@ -181,44 +193,53 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
     
     //bHavePostGIS = CSLFetchBoolean(papszOptions,"POSTGIS", TRUE);
 
-    if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
-    {
-        pszLayerName = LaunderName( pszLayerNameIn );
-        
-    }
-    else
-        pszLayerName = CPLStrdup( pszLayerNameIn );
-    
     int bCreateTable = CSLFetchBoolean(papszOptions,"CREATE_TABLE", TRUE);
     int bCreateSchema = CSLFetchBoolean(papszOptions,"CREATE_SCHEMA", TRUE);
     const char* pszDropTable = CSLFetchNameValueDef(papszOptions,"DROP_TABLE", "YES");
 
-    if (eType == wkbNone)
-        bHavePostGIS = FALSE;
-    else if( wkbFlatten(eType) == eType )
+    if( wkbFlatten(eType) == eType )
         nDimension = 2;
 
     if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
         nDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));
 
+    /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
+    /* so they are still recorded in geometry_columns table ? (#4012) */
+    int bNoneAsUnknown = CSLTestBoolean(CSLFetchNameValueDef(
+                                    papszOptions, "NONE_AS_UNKNOWN", "NO"));
+    if (bNoneAsUnknown && eType == wkbNone)
+        eType = wkbUnknown;
+    else if (eType == wkbNone)
+        bHavePostGIS = FALSE;
+
+    int bExtractSchemaFromLayerName = CSLTestBoolean(CSLFetchNameValueDef(
+                                    papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
+
     /* Postgres Schema handling:
        Extract schema name from input layer name or passed with -lco SCHEMA.
        Set layer name to "schema.table" or to "table" if schema == current_schema()
        Usage without schema name is backwards compatible
     */
-    pszTableName = strstr(pszLayerName,".");
-    if ( pszTableName != NULL )
+    const char* pszDotPos = strstr(pszLayerName,".");
+    if ( pszDotPos != NULL && bExtractSchemaFromLayerName )
     {
-      int length = pszTableName - pszLayerName;
+      int length = pszDotPos - pszLayerName;
       pszSchemaName = (char*)CPLMalloc(length+1);
       strncpy(pszSchemaName, pszLayerName, length);
       pszSchemaName[length] = '\0';
-      ++pszTableName; //skip "."
+
+      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+          pszTableName = LaunderName( pszDotPos + 1 ); //skip "."
+      else
+          pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
     }
     else
     {
       pszSchemaName = NULL;
-      pszTableName = pszLayerName;
+      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+          pszTableName = LaunderName( pszLayerName ); //skip "."
+      else
+          pszTableName = CPLStrdup( pszLayerName ); //skip "."
     }
 
     Commit();
@@ -254,7 +275,7 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Layer %s already exists, CreateLayer failed.\n", 
                       pszLayerName );
-            CPLFree( pszLayerName );
+            CPLFree( pszTableName );
             CPLFree( pszSchemaName );
             return NULL;
         }
@@ -288,7 +309,7 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
                     "GEOM_TYPE in PostGIS enabled databases must be 'geometry' or 'geography'.\n"
                     "Creation of layer %s with GEOM_TYPE %s has failed.",
                     pszLayerName, pszGeomType );
-        CPLFree( pszLayerName );
+        CPLFree( pszTableName );
         CPLFree( pszSchemaName );
         return NULL;
     }
@@ -320,6 +341,9 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
         }
     }
 
+    CPLString osEscapedTableNameSingleQuote = OGRPGDumpEscapeString(pszTableName, -1, "");
+    const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
+
     const char *pszGeometryType = OGRToOGCGeomType(eType);
 
     const char *pszGFldName = NULL;
@@ -335,8 +359,8 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
         * an effort to clean out such cruft.
         */
         osCommand.Printf(
-                "DELETE FROM geometry_columns WHERE f_table_name = '%s' AND f_table_schema = '%s'",
-                pszTableName, pszSchemaName );
+                "DELETE FROM geometry_columns WHERE f_table_name = %s AND f_table_schema = '%s'",
+                pszEscapedTableNameSingleQuote, pszSchemaName );
         if (bCreateTable)
             Log(osCommand);
     }
@@ -368,14 +392,14 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
                     "%s ( "
                     "   %s SERIAL, "
                     "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                    osCreateTable.c_str(), pszFIDColumn, pszTableName, pszFIDColumn );
+                    osCreateTable.c_str(), pszFIDColumnName, pszTableName, pszFIDColumnName );
         else
             osCommand.Printf(
                     "%s ( "
                     "   %s SERIAL, "
                     "   WKB_GEOMETRY %s, "
                     "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                    osCreateTable.c_str(), pszFIDColumn, pszGeomType, pszTableName, pszFIDColumn );
+                    osCreateTable.c_str(), pszFIDColumnName, pszGeomType, pszTableName, pszFIDColumnName );
     }
     else if ( EQUAL(pszGeomType, "geography") )
     {
@@ -387,17 +411,17 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
         if (nSRSId)
             osCommand.Printf(
                      "%s ( %s SERIAL, \"%s\" geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), pszFIDColumn, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", nSRSId, pszTableName, pszFIDColumn );
+                     osCreateTable.c_str(), pszFIDColumnName, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", nSRSId, pszTableName, pszFIDColumnName );
         else
             osCommand.Printf(
                      "%s ( %s SERIAL, \"%s\" geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), pszFIDColumn, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", pszTableName, pszFIDColumn );
+                     osCreateTable.c_str(), pszFIDColumnName, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", pszTableName, pszFIDColumnName );
     }
     else
     {
         osCommand.Printf(
                  "%s ( %s SERIAL, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                 osCreateTable.c_str(), pszFIDColumn, pszTableName, pszFIDColumn );
+                 osCreateTable.c_str(), pszFIDColumnName, pszTableName, pszFIDColumnName );
     }
 
     if (bCreateTable)
@@ -411,8 +435,8 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
     if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography"))
     {
         osCommand.Printf(
-                "SELECT AddGeometryColumn('%s','%s','%s',%d,'%s',%d)",
-                pszSchemaName, pszTableName, pszGFldName,
+                "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s',%d)",
+                pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
                 nSRSId, pszGeometryType, nDimension );
         Log(osCommand);
     }
@@ -444,8 +468,8 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
 
     int bWriteAsHex = !CSLFetchBoolean(papszOptions,"WRITE_EWKT_GEOM",FALSE);
 
-    poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszLayerName, pszGFldName,
-                                  pszFIDColumn, nDimension, nSRSId, bWriteAsHex, bCreateTable );
+    poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszTableName, pszGFldName,
+                                  pszFIDColumnName, nDimension, nSRSId, bWriteAsHex, bCreateTable );
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
 
@@ -457,7 +481,7 @@ OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn,
 
     papoLayers[nLayers++] = poLayer;
 
-    CPLFree( pszLayerName );
+    CPLFree( pszTableName );
     CPLFree( pszSchemaName );
 
     return poLayer;
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
index 0bb9700..c4b30c7 100755
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdumpdriver.cpp 19705 2010-05-14 19:42:02Z rouault $
+ * $Id: ogrpgdumpdriver.cpp 23022 2011-09-01 19:10:17Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_pgdump.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgdumpdriver.cpp 19705 2010-05-14 19:42:02Z rouault $");
+CPL_CVSID("$Id: ogrpgdumpdriver.cpp 23022 2011-09-01 19:10:17Z rouault $");
 
 /************************************************************************/
 /*                         ~OGRPGDumpDriver()                           */
@@ -72,6 +72,9 @@ OGRDataSource *OGRPGDumpDriver::CreateDataSource( const char * pszName,
 {
     OGRPGDumpDataSource     *poDS;
 
+    if (strcmp(pszName, "/dev/stdout") == 0)
+        pszName = "/vsistdout/";
+
     poDS = new OGRPGDumpDataSource(pszName, papszOptions);
 
     return poDS;
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
index ec0a437..e556de1 100755
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdumplayer.cpp 22158 2011-04-14 18:10:01Z rouault $
+ * $Id: ogrpgdumplayer.cpp 22969 2011-08-23 20:43:21Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDumpLayer class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrpgdumplayer.cpp 22158 2011-04-14 18:10:01Z rouault $");
+CPL_CVSID("$Id: ogrpgdumplayer.cpp 22969 2011-08-23 20:43:21Z rouault $");
 
 #define USE_COPY_UNSET -1
 
@@ -50,7 +50,7 @@ static CPLString OGRPGDumpEscapeStringList(
 
 OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
                                const char* pszSchemaName,
-                               const char* pszLayerName,
+                               const char* pszTableName,
                                const char* pszGeomColumn,
                                const char *pszFIDColumn,
                                int         nCoordDimension,
@@ -59,10 +59,12 @@ OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
                                int         bCreateTable)
 {
     this->poDS = poDS;
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    poFeatureDefn = new OGRFeatureDefn( pszTableName );
     poFeatureDefn->Reference();
     nFeatures = 0;
-    pszSqlTableName = CPLStrdup(CPLSPrintf("\"%s\".\"%s\"", pszSchemaName, pszLayerName));
+    pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
+                               OGRPGDumpEscapeColumnName(pszSchemaName).c_str(),
+                               OGRPGDumpEscapeColumnName(pszTableName).c_str() ));
     this->pszGeomColumn = (pszGeomColumn) ? CPLStrdup(pszGeomColumn) : NULL;
     this->pszFIDColumn = CPLStrdup(pszFIDColumn);
     this->nCoordDimension = nCoordDimension;
@@ -230,6 +232,7 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
     int                 i = 0;
     int                 bNeedComma = FALSE;
     OGRErr              eErr = OGRERR_FAILURE;
+    int bEmptyInsert = FALSE;
     
     if( NULL == poFeature )
     {
@@ -246,7 +249,7 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     if( poGeom != NULL && pszGeomColumn != NULL )
     {
-        osCommand = osCommand + "\"" + pszGeomColumn + "\" ";
+        osCommand = osCommand + OGRPGDumpEscapeColumnName(pszGeomColumn) + " ";
         bNeedComma = TRUE;
     }
 
@@ -255,7 +258,7 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
         if( bNeedComma )
             osCommand += ", ";
         
-        osCommand = osCommand + "\"" + pszFIDColumn + "\" ";
+        osCommand = osCommand + OGRPGDumpEscapeColumnName(pszFIDColumn) + " ";
         bNeedComma = TRUE;
     }
 
@@ -270,9 +273,12 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
             osCommand += ", ";
 
         osCommand = osCommand 
-            + "\"" + poFeatureDefn->GetFieldDefn(i)->GetNameRef() + "\"";
+            + OGRPGDumpEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     }
 
+    if (!bNeedComma)
+        bEmptyInsert = TRUE;
+
     osCommand += ") VALUES (";
 
     /* Set the geometry */
@@ -336,6 +342,9 @@ OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 
     osCommand += ")";
 
+    if (bEmptyInsert)
+        osCommand.Printf( "INSERT INTO %s DEFAULT VALUES", pszSqlTableName );
+
 /* -------------------------------------------------------------------- */
 /*      Execute the insert.                                             */
 /* -------------------------------------------------------------------- */
@@ -615,9 +624,7 @@ CPLString OGRPGDumpLayer::BuildCopyFields()
 
     if( /*bHasFid &&*/ poFeatureDefn->GetFieldIndex( pszFIDColumn ) != -1 )
     {
-        osFieldList += "\"";
-        osFieldList += pszFIDColumn;
-        osFieldList += "\"";
+        osFieldList += OGRPGDumpEscapeColumnName(pszFIDColumn);
     }
 
     if( pszGeomColumn )
@@ -625,9 +632,7 @@ CPLString OGRPGDumpLayer::BuildCopyFields()
         if( strlen(osFieldList) > 0 )
             osFieldList += ", ";
 
-        osFieldList += "\"";
-        osFieldList += pszGeomColumn;
-        osFieldList += "\"";
+        osFieldList += OGRPGDumpEscapeColumnName(pszGeomColumn);
     }
 
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
@@ -637,19 +642,40 @@ CPLString OGRPGDumpLayer::BuildCopyFields()
         if( strlen(osFieldList) > 0 )
             osFieldList += ", ";
 
-        osFieldList += "\"";
-        osFieldList += pszName;
-        osFieldList += "\"" ;
+        osFieldList += OGRPGDumpEscapeColumnName(pszName);
     }
 
     return osFieldList;
 }
 
 /************************************************************************/
+/*                       OGRPGDumpEscapeColumnName( )                   */
+/************************************************************************/
+
+CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName)
+{
+    CPLString osStr;
+
+    osStr += "\"";
+
+    char ch;
+    for(int i=0; (ch = pszColumnName[i]) != '\0'; i++)
+    {
+        if (ch == '"')
+            osStr.append(1, ch);
+        osStr.append(1, ch);
+    }
+
+    osStr += "\"";
+
+    return osStr;
+}
+
+/************************************************************************/
 /*                             EscapeString( )                          */
 /************************************************************************/
 
-static CPLString OGRPGDumpEscapeString(
+CPLString OGRPGDumpEscapeString(
                                    const char* pszStrValue, int nMaxLength,
                                    const char* pszFieldName)
 {
@@ -1002,10 +1028,10 @@ OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
     }
     else if( oField.GetType() == OFTString )
     {
-        if( oField.GetWidth() == 0 || !bPreservePrecision )
-            strcpy( szFieldType, "VARCHAR" );
+        if (oField.GetWidth() > 0 &&  bPreservePrecision )
+            sprintf( szFieldType, "VARCHAR(%d)",  oField.GetWidth() );
         else
-            sprintf( szFieldType, "CHAR(%d)", oField.GetWidth() );
+            strcpy( szFieldType, "VARCHAR");
     }
     else if( oField.GetType() == OFTIntegerList )
     {
@@ -1056,8 +1082,9 @@ OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
 /* -------------------------------------------------------------------- */
 /*      Create the new field.                                           */
 /* -------------------------------------------------------------------- */
-    osCommand.Printf( "ALTER TABLE %s ADD COLUMN \"%s\" %s",
-                      pszSqlTableName, oField.GetNameRef(), szFieldType );
+    osCommand.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
+                      pszSqlTableName, OGRPGDumpEscapeColumnName(oField.GetNameRef()).c_str(),
+                      szFieldType );
     if (bCreateTable)
         poDS->Log(osCommand);
 
diff --git a/ogr/ogrsf_frmts/pgeo/drv_pgeo.html b/ogr/ogrsf_frmts/pgeo/drv_pgeo.html
index f4116be..3c85388 100644
--- a/ogr/ogrsf_frmts/pgeo/drv_pgeo.html
+++ b/ogr/ogrsf_frmts/pgeo/drv_pgeo.html
@@ -31,7 +31,7 @@
   the PGEO_DRIVER_TEMPLATE Config Option was added to provide a way to 
   programmatically set the DSN programmatically with the filename as 
   an argument.   In cases where the driver name is known, this allows for
-  the construction of the DNS based on that information in a manner similar
+  the construction of the DSN based on that information in a manner similar
   to the default (used for Windows access to the Microsoft Access Driver).</p>
   
   <p>OGR treats all feature tables as layers. Most geometry types
@@ -51,6 +51,9 @@ method, as name of the SQL dialect.</p>
 
   <h2>How to use PGeo driver with unixODBC and MDB Tools (on Unix and Linux)</h2>
 
+  <p>Starting with GDAL/OGR 1.9.0, the <a href="drv_mdb.html">MDB</a> driver is an alternate
+     way of reading ESRI Personal GeoDatabase .mdb files without requiring unixODBC and MDB Tools</p>
+
   <p>This article gives step-by-step explanation of how to use OGR
   with unixODBC package and how to access Personal Geodatabase with
   PGeo driver. See also <a href="http://trac.osgeo.org/gdal/wiki/mdbtools">GDAL wiki for other details</a></p>
@@ -204,13 +207,15 @@ Layer name: ...
 
   <ul>
       <li><a href="http://www.esri.com/software/arcgis/geodatabase/index.html">About ESRI Geodatabase</a></li>
-      <li><a href="http://sourceforge.net/mailarchive/forum.php?thread_id=10463538&forum_id=5183">[mdbtools-dev] DSN-less connection not supported?</a></li>
+      <li><a href="http://sourceforge.net/mailarchive/message.php?msg_id=5998236">[mdbtools-dev] DSN-less connection not supported?</a></li>
+  </ul>
+
+  <h2>See also</h2>
+
+  <ul>
+  <li><a href="drv_mdb.html">MDB</a> driver page</li>
   </ul>
 
-  <p>If you have any comments or questions, don't hesitate to post
-  them on the <a href=
-  "mailto:gdal-dev at lists.maptools.org">gdal-dev at lists.maptools.org</a>
-  mailing list.</p>
 </body>
 </html>
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h b/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
index 3eda3d0..4b3e77a 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 17844 2009-10-17 09:40:47Z rouault $
+ * $Id: ogr_pgeo.h 21550 2011-01-22 18:01:57Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for Personal Geodatabase driver.
@@ -34,31 +34,6 @@
 #include "cpl_odbc.h"
 #include "cpl_error.h"
 
-#define SHPT_NULL          0
-
-#define SHPT_POINT         1
-#define SHPT_POINTM       21
-#define SHPT_POINTZM      11
-#define SHPT_POINTZ        9
-
-#define SHPT_MULTIPOINT    8
-#define SHPT_MULTIPOINTM  28
-#define SHPT_MULTIPOINTZM 18
-#define SHPT_MULTIPOINTZ  20
-
-#define SHPT_ARC           3
-#define SHPT_ARCM         23
-#define SHPT_ARCZM        13
-#define SHPT_ARCZ         10
-
-#define SHPT_POLYGON       5
-#define SHPT_POLYGONM     25
-#define SHPT_POLYGONZM    15
-#define SHPT_POLYGONZ     19
-
-#define SHPT_MULTIPATCHM  31
-#define SHPT_MULTIPATCH   32
-
 /************************************************************************/
 /*                            OGRPGeoLayer                              */
 /************************************************************************/
@@ -89,9 +64,6 @@ class OGRPGeoLayer : public OGRLayer
                                           CPLODBCStatement *poStmt );
 
     virtual CPLODBCStatement *  GetStatement() { return poStmt; }
-    OGRErr              createFromShapeBin( GByte *pabyShape, 
-                                            OGRGeometry **ppoGeom,
-                                            int nBytes );
 
     void                LookupSRID( int );
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
index 68e3e51..3bd77e2 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeodriver.cpp 18168 2009-12-03 23:56:59Z warmerdam $
+ * $Id: ogrpgeodriver.cpp 21550 2011-01-22 18:01:57Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -30,7 +30,7 @@
 #include "ogr_pgeo.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgeodriver.cpp 18168 2009-12-03 23:56:59Z warmerdam $");
+CPL_CVSID("$Id: ogrpgeodriver.cpp 21550 2011-01-22 18:01:57Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRODBCDriver()                            */
@@ -65,6 +65,32 @@ OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
         && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
         return NULL;
 
+    if( !EQUALN(pszFilename,"PGEO:",5) &&
+        EQUAL(CPLGetExtension(pszFilename),"mdb") )
+    {
+        VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+        if (!fp)
+            return NULL;
+        GByte* pabyHeader = (GByte*) CPLMalloc(100000);
+        VSIFReadL(pabyHeader, 100000, 1, fp);
+        VSIFCloseL(fp);
+
+        /* Look for GDB_GeomColumns table */
+        const GByte pabyNeedle[] = { 'G', 0, 'D', 0, 'B', 0, '_', 0, 'G', 0, 'e', 0, 'o', 0, 'm', 0, 'C', 0, 'o', 0, 'l', 0, 'u', 0, 'm', 0, 'n', 0, 's' };
+        int bFound = FALSE;
+        for(int i=0;i<100000 - (int)sizeof(pabyNeedle);i++)
+        {
+            if (memcmp(pabyHeader + i, pabyNeedle, sizeof(pabyNeedle)) == 0)
+            {
+                bFound = TRUE;
+                break;
+            }
+        }
+        CPLFree(pabyHeader);
+        if (!bFound)
+            return NULL;
+    }
+
 #ifndef WIN32
     // Try to register MDB Tools driver
     //
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
index 51bf7e4..cd7e8b8 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeolayer.cpp 19778 2010-05-27 20:44:52Z rouault $
+ * $Id: ogrpgeolayer.cpp 21540 2011-01-22 00:06:04Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoLayer class, code shared between 
@@ -31,8 +31,9 @@
 #include "cpl_conv.h"
 #include "ogr_pgeo.h"
 #include "cpl_string.h"
+#include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeolayer.cpp 19778 2010-05-27 20:44:52Z rouault $");
+CPL_CVSID("$Id: ogrpgeolayer.cpp 21540 2011-01-22 00:06:04Z rouault $");
 
 /************************************************************************/
 /*                            OGRPGeoLayer()                            */
@@ -283,7 +284,7 @@ OGRFeature *OGRPGeoLayer::GetNextRawFeature()
 
         if( pabyShape != NULL )
         {
-            err = createFromShapeBin( pabyShape, &poGeom, nBytes );
+            err = OGRCreateFromShapeBin( pabyShape, &poGeom, nBytes );
             if( OGRERR_NONE != err )
             {
                 CPLDebug( "PGeo",
@@ -403,485 +404,6 @@ void OGRPGeoLayer::LookupSRID( int nSRID )
 }
 
 /************************************************************************/
-/*                         createFromShapeBin()                         */
-/*                                                                      */
-/*      Translate shapefile binary representation to an OGR             */
-/*      geometry.                                                       */
-/************************************************************************/
-
-OGRErr OGRPGeoLayer::createFromShapeBin( GByte *pabyShape, 
-                                         OGRGeometry **ppoGeom,
-                                         int nBytes )
-
-{
-    *ppoGeom = NULL;
-
-    if( nBytes < 1 )
-        return OGRERR_FAILURE;
-
-    int nSHPType = pabyShape[0];
-
-
-//    CPLDebug( "PGeo", 
-//              "Shape type read from PGeo data is nSHPType = %d", 
-//              nSHPType );
-
-/* -------------------------------------------------------------------- */
-/*      type 50 appears to just be an alias for normal line             */
-/*      strings. (#1484)                                                */
-/*      Type 51 appears to just be an alias for normal polygon. (#3100) */
-/*      TODO: These types include additional attributes including       */
-/*      non-linear segments and such. They should be handled.           */
-/* -------------------------------------------------------------------- */
-    switch( nSHPType )
-    {
-      case 50:
-        nSHPType = SHPT_ARC;
-        break;
-      case 51:
-        nSHPType = SHPT_POLYGON;
-        break;
-      case 52:
-        nSHPType = SHPT_POINT;
-        break;
-      case 53:
-        nSHPType = SHPT_MULTIPOINT;
-        break;
-      case 54:
-        nSHPType = SHPT_MULTIPATCH;
-    }
-
-/* ==================================================================== */
-/*  Extract vertices for a Polygon or Arc.				*/
-/* ==================================================================== */
-    if(    nSHPType == SHPT_ARC
-        || nSHPType == SHPT_ARCZ
-        || nSHPType == SHPT_ARCM
-        || nSHPType == SHPT_ARCZM
-        || nSHPType == SHPT_POLYGON 
-        || nSHPType == SHPT_POLYGONZ
-        || nSHPType == SHPT_POLYGONM
-        || nSHPType == SHPT_POLYGONZM
-        || nSHPType == SHPT_MULTIPATCH 
-        || nSHPType == SHPT_MULTIPATCHM)
-    {
-        GInt32         nPoints, nParts;
-        int            i, nOffset;
-        GInt32         *panPartStart;
-
-        if (nBytes < 44)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
-            return OGRERR_FAILURE;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Extract part/point count, and build vertex and part arrays      */
-/*      to proper size.                                                 */
-/* -------------------------------------------------------------------- */
-	memcpy( &nPoints, pabyShape + 40, 4 );
-	memcpy( &nParts, pabyShape + 36, 4 );
-
-	CPL_LSBPTR32( &nPoints );
-	CPL_LSBPTR32( &nParts );
-
-        if (nPoints < 0 || nParts < 0 ||
-            nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d.",
-                     nPoints, nParts);
-            return OGRERR_FAILURE;
-        }
-
-        int bHasZ = (  nSHPType == SHPT_POLYGONZ
-                    || nSHPType == SHPT_POLYGONZM
-                    || nSHPType == SHPT_ARCZ
-                    || nSHPType == SHPT_ARCZM
-                    || nSHPType == SHPT_MULTIPATCH 
-                    || nSHPType == SHPT_MULTIPATCHM );
-
-        int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM );
-
-        /* With the previous checks on nPoints and nParts, */
-        /* we should not overflow here and after */
-        /* since 50 M * (16 + 8 + 8) = 1 600 MB */
-        int nRequiredSize = 44 + 4 * nParts + 16 * nPoints;
-        if ( bHasZ )
-        {
-            nRequiredSize += 16 + 8 * nPoints;
-        }
-        if( bIsMultiPatch )
-        {
-            nRequiredSize += 4 * nParts;
-        }
-        if (nRequiredSize > nBytes)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d",
-                     nPoints, nParts, nBytes, nSHPType);
-            return OGRERR_FAILURE;
-        }
-
-        panPartStart = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
-        if (panPartStart == NULL)
-        {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
-            return OGRERR_FAILURE;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Copy out the part array from the record.                        */
-/* -------------------------------------------------------------------- */
-	memcpy( panPartStart, pabyShape + 44, 4 * nParts );
-	for( i = 0; i < nParts; i++ )
-	{
-            CPL_LSBPTR32( panPartStart + i );
-
-            /* We check that the offset is inside the vertex array */
-            if (panPartStart[i] < 0 ||
-                panPartStart[i] >= nPoints)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d",
-                         i, panPartStart[i], nPoints); 
-                CPLFree(panPartStart);
-                return OGRERR_FAILURE;
-            }
-            if (i > 0 && panPartStart[i] <= panPartStart[i-1])
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Corrupted Shape : panPartStart[%d] = %d, panPartStart[%d] = %d",
-                         i, panPartStart[i], i - 1, panPartStart[i - 1]); 
-                CPLFree(panPartStart);
-                return OGRERR_FAILURE;
-            }
-	}
-
-	nOffset = 44 + 4*nParts;
-
-/* -------------------------------------------------------------------- */
-/*      If this is a multipatch, we will also have parts types.  For    */
-/*      now we ignore and skip past them.                               */
-/* -------------------------------------------------------------------- */
-        if( bIsMultiPatch )
-            nOffset += 4*nParts;
-        
-/* -------------------------------------------------------------------- */
-/*      Copy out the vertices from the record.                          */
-/* -------------------------------------------------------------------- */
-        double *padfX = (double *) VSIMalloc(sizeof(double)*nPoints);
-        double *padfY = (double *) VSIMalloc(sizeof(double)*nPoints);
-        double *padfZ = (double *) VSICalloc(sizeof(double),nPoints);
-        if (padfX == NULL || padfY == NULL || padfZ == NULL)
-        {
-            CPLFree( panPartStart );
-            CPLFree( padfX );
-            CPLFree( padfY );
-            CPLFree( padfZ );
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
-            return OGRERR_FAILURE;
-        }
-
-	for( i = 0; i < nPoints; i++ )
-	{
-	    memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
-	    memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
-            CPL_LSBPTR64( padfX + i );
-            CPL_LSBPTR64( padfY + i );
-	}
-
-        nOffset += 16*nPoints;
-        
-/* -------------------------------------------------------------------- */
-/*      If we have a Z coordinate, collect that now.                    */
-/* -------------------------------------------------------------------- */
-        if( bHasZ )
-        {
-            for( i = 0; i < nPoints; i++ )
-            {
-                memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
-                CPL_LSBPTR64( padfZ + i );
-            }
-
-            nOffset += 16 + 8*nPoints;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Build corresponding OGR objects.                                */
-/* -------------------------------------------------------------------- */
-        if(    nSHPType == SHPT_ARC 
-            || nSHPType == SHPT_ARCZ
-            || nSHPType == SHPT_ARCM
-            || nSHPType == SHPT_ARCZM )
-        {
-/* -------------------------------------------------------------------- */
-/*      Arc - As LineString                                             */
-/* -------------------------------------------------------------------- */
-            if( nParts == 1 )
-            {
-                OGRLineString *poLine = new OGRLineString();
-                *ppoGeom = poLine;
-
-                poLine->setPoints( nPoints, padfX, padfY, padfZ );
-            }
-
-/* -------------------------------------------------------------------- */
-/*      Arc - As MultiLineString                                        */
-/* -------------------------------------------------------------------- */
-            else
-            {
-                OGRMultiLineString *poMulti = new OGRMultiLineString;
-                *ppoGeom = poMulti;
-
-                for( i = 0; i < nParts; i++ )
-                {
-                    OGRLineString *poLine = new OGRLineString;
-                    int nVerticesInThisPart;
-
-                    if( i == nParts-1 )
-                        nVerticesInThisPart = nPoints - panPartStart[i];
-                    else
-                        nVerticesInThisPart = 
-                            panPartStart[i+1] - panPartStart[i];
-
-                    poLine->setPoints( nVerticesInThisPart, 
-                                       padfX + panPartStart[i], 
-                                       padfY + panPartStart[i], 
-                                       padfZ + panPartStart[i] );
-
-                    poMulti->addGeometryDirectly( poLine );
-                }
-            }
-        } /* ARC */
-
-/* -------------------------------------------------------------------- */
-/*      Polygon                                                         */
-/* -------------------------------------------------------------------- */
-        else if(    nSHPType == SHPT_POLYGON
-                 || nSHPType == SHPT_POLYGONZ
-                 || nSHPType == SHPT_POLYGONM
-                 || nSHPType == SHPT_POLYGONZM )
-        {
-            if (nParts != 0)
-            {
-                if (nParts == 1)
-                {
-                    OGRPolygon *poOGRPoly = new OGRPolygon;
-                    *ppoGeom = poOGRPoly;
-                    OGRLinearRing *poRing = new OGRLinearRing;
-                    int nVerticesInThisPart = nPoints - panPartStart[0];
-                    
-                    poRing->setPoints( nVerticesInThisPart, 
-                                       padfX + panPartStart[0], 
-                                       padfY + panPartStart[0], 
-                                       padfZ + panPartStart[0] );
-                    
-                    poOGRPoly->addRingDirectly( poRing );
-                }
-                else 
-                {
-                    OGRGeometry *poOGR = NULL;
-                    OGRPolygon** tabPolygons = new OGRPolygon*[nParts];
-               
-                    for( i = 0; i < nParts; i++ )
-                    {
-                        tabPolygons[i] = new OGRPolygon();
-                        OGRLinearRing *poRing = new OGRLinearRing;
-                        int nVerticesInThisPart;
-                        
-                        if( i == nParts-1 )
-                            nVerticesInThisPart = nPoints - panPartStart[i];
-                        else
-                            nVerticesInThisPart = 
-                                panPartStart[i+1] - panPartStart[i];
-                        
-                        poRing->setPoints( nVerticesInThisPart, 
-                                           padfX + panPartStart[i], 
-                                           padfY + panPartStart[i], 
-                                           padfZ + panPartStart[i] );
-                        tabPolygons[i]->addRingDirectly(poRing);
-                    }
-
-                    int isValidGeometry;
-                    const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
-                    poOGR = OGRGeometryFactory::organizePolygons( 
-                        (OGRGeometry**)tabPolygons, nParts, &isValidGeometry, papszOptions );
-
-                    if (!isValidGeometry)
-                    {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                 "Geometry of polygon cannot be translated to Simple Geometry. "
-                                 "All polygons will be contained in a multipolygon.\n");
-                    }
-
-                    *ppoGeom = poOGR;
-                    delete[] tabPolygons;
-                }
-            }
-        } /* polygon */
-
-/* -------------------------------------------------------------------- */
-/*      Multipatch                                                      */
-/* -------------------------------------------------------------------- */
-        else if( bIsMultiPatch )
-        {
-            /* return to this later */
-        } 
-
-        CPLFree( panPartStart );
-        CPLFree( padfX );
-        CPLFree( padfY );
-        CPLFree( padfZ );
-
-        if( !bHasZ )
-            (*ppoGeom)->setCoordinateDimension( 2 );
-
-        return OGRERR_NONE;
-    }
-
-/* ==================================================================== */
-/*  Extract vertices for a MultiPoint.					*/
-/* ==================================================================== */
-    else if(    nSHPType == SHPT_MULTIPOINT
-             || nSHPType == SHPT_MULTIPOINTM
-             || nSHPType == SHPT_MULTIPOINTZ
-             || nSHPType == SHPT_MULTIPOINTZM )
-    {
-#ifdef notdef
-	int32		nPoints;
-	int    		i, nOffset;
-
-	memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
-	if( bBigEndian ) SwapWord( 4, &nPoints );
-
-	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));
-
-	for( i = 0; i < nPoints; i++ )
-	{
-	    memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
-	    memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
-
-	    if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
-	    if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
-	}
-
-        nOffset = 48 + 16*nPoints;
-        
-/* -------------------------------------------------------------------- */
-/*	Get the X/Y bounds.						*/
-/* -------------------------------------------------------------------- */
-        memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
-        memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
-        memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
-        memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
-
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
-
-/* -------------------------------------------------------------------- */
-/*      If we have a Z coordinate, collect that now.                    */
-/* -------------------------------------------------------------------- */
-        if( psShape->nSHPType == SHPT_MULTIPOINTZ || psShape->nSHPType == SHPT_MULTIPOINTZM )
-        {
-            memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
-            
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
-            
-            for( i = 0; i < nPoints; i++ )
-            {
-                memcpy( psShape->padfZ + i,
-                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
-                if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
-            }
-
-            nOffset += 16 + 8*nPoints;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      If we have a M measure value, then read it now.  We assume      */
-/*      that the measure can be present for any shape if the size is    */
-/*      big enough, but really it will only occur for the Z shapes      */
-/*      (options), and the M shapes.                                    */
-/* -------------------------------------------------------------------- */
-        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
-        {
-            memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
-            memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
-            
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
-            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
-            
-            for( i = 0; i < nPoints; i++ )
-            {
-                memcpy( psShape->padfM + i,
-                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
-                if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
-            }
-        }
-#endif
-    }
-
-/* ==================================================================== */
-/*      Extract vertices for a point.                                   */
-/* ==================================================================== */
-    else if(    nSHPType == SHPT_POINT
-             || nSHPType == SHPT_POINTM
-             || nSHPType == SHPT_POINTZ
-             || nSHPType == SHPT_POINTZM )
-    {
-        int	nOffset;
-        double  dfX, dfY, dfZ = 0;
-
-        int bHasZ = (nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM);
-
-        if (nBytes < 4 + 8 + 8 + ((nSHPType == SHPT_POINTZ) ? 8 : 0))
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
-            return OGRERR_FAILURE;
-        }
-        
-	memcpy( &dfX, pabyShape + 4, 8 );
-	memcpy( &dfY, pabyShape + 4 + 8, 8 );
-
-        CPL_LSBPTR64( &dfX );
-        CPL_LSBPTR64( &dfY );
-        nOffset = 20 + 8;
-        
-        if( bHasZ )
-        {
-            memcpy( &dfZ, pabyShape + 4 + 16, 8 );
-            CPL_LSBPTR64( &dfZ );
-        }
-
-        *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
-
-        if( !bHasZ )
-            (*ppoGeom)->setCoordinateDimension( 2 );
-
-        return OGRERR_NONE;
-    }
-
-    char* pszHex = CPLBinaryToHex( nBytes, pabyShape );
-    CPLDebug( "PGEO", "Unsupported geometry type:%d\nnBytes=%d, hex=%s",
-              nSHPType, nBytes, pszHex );
-    CPLFree(pszHex);
-
-    return OGRERR_FAILURE;
-}
-
-/************************************************************************/
 /*                            GetFIDColumn()                            */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
index ec0585c..b1a01db 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeotablelayer.cpp 20579 2010-09-12 11:43:35Z rouault $
+ * $Id: ogrpgeotablelayer.cpp 22155 2011-04-13 19:52:57Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoTableLayer class, access to an existing table.
@@ -29,8 +29,9 @@
 
 #include "cpl_conv.h"
 #include "ogr_pgeo.h"
+#include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeotablelayer.cpp 20579 2010-09-12 11:43:35Z rouault $");
+CPL_CVSID("$Id: ogrpgeotablelayer.cpp 22155 2011-04-13 19:52:57Z rouault $");
 
 /************************************************************************/
 /*                          OGRPGeoTableLayer()                         */
@@ -100,33 +101,34 @@ CPLErr OGRPGeoTableLayer::Initialize( const char *pszTableName,
 
     switch( nShapeType )
     {
-        case SHPT_POINT:
-        case SHPT_POINTM:
-        case SHPT_POINTZ:
-        case SHPT_POINTZM:
+        case ESRI_LAYERGEOMTYPE_NULL:
+            eOGRType = wkbNone;
+            break;
+
+        case ESRI_LAYERGEOMTYPE_POINT:
             eOGRType = wkbPoint;
             break;
 
-        case SHPT_ARC:
-        case SHPT_ARCZ:
-        case SHPT_ARCM:
-        case SHPT_ARCZM:
+        case ESRI_LAYERGEOMTYPE_MULTIPOINT:
+            eOGRType = wkbMultiPoint;
+            break;
+
+        case ESRI_LAYERGEOMTYPE_POLYLINE:
             eOGRType = wkbLineString;
             break;
-            
-        case SHPT_MULTIPOINT:
-        case SHPT_MULTIPOINTZ:
-        case SHPT_MULTIPOINTM:
-        case SHPT_MULTIPOINTZM:
-            eOGRType = wkbMultiPoint;
+
+        case ESRI_LAYERGEOMTYPE_POLYGON:
+        case ESRI_LAYERGEOMTYPE_MULTIPATCH:
+            eOGRType = wkbPolygon;
             break;
 
         default:
+            CPLDebug("PGeo", "Unexpected value for shape type : %d", nShapeType);
             eOGRType = wkbUnknown;
             break;
     }
 
-    if( eOGRType != wkbUnknown && bHasZ )
+    if( eOGRType != wkbUnknown && eOGRType != wkbNone && bHasZ )
         eOGRType = (OGRwkbGeometryType)(((int) eOGRType) | wkb25DBit);
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/s57/s57.h b/ogr/ogrsf_frmts/s57/s57.h
index ac0bde8..16c7c0a 100644
--- a/ogr/ogrsf_frmts/s57/s57.h
+++ b/ogr/ogrsf_frmts/s57/s57.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57.h 11537 2007-05-16 03:35:17Z warmerdam $
+ * $Id: s57.h 22469 2011-05-31 14:19:18Z warmerdam $
  *
  * Project:  S-57 Translator
  * Purpose:  Declarations for S-57 translator not including the
@@ -93,7 +93,7 @@ char **S57FileCollector( const char * pszDataset );
 /************************************************************************/
 
 #define MAX_CLASSES 23000
-#define MAX_ATTRIBUTES 25000
+#define MAX_ATTRIBUTES 65535
 
 class CPL_DLL S57ClassRegistrar
 {
@@ -116,7 +116,7 @@ class CPL_DLL S57ClassRegistrar
     char     ***papapszAttrValues;
     char       *pachAttrType;
     char       *pachAttrClass;
-    int        *panAttrIndex; // sorted by acronym.
+    GUInt16    *panAttrIndex; // sorted by acronym.
 
     int         FindFile( const char *pszTarget, const char *pszDirectory,
                           int bReportErr, FILE **fp );
@@ -161,7 +161,7 @@ public:
 #define SAT_FREE_TEXT   'S'
 
     char        GetAttrClass( int i ) { return pachAttrClass[i]; }
-    int         FindAttrByAcronym( const char * );
+    GInt16      FindAttrByAcronym( const char * );
 
 };
 
diff --git a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
index df7cd11..03f3832 100644
--- a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
+++ b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57classregistrar.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: s57classregistrar.cpp 22616 2011-06-29 19:19:03Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57ClassRegistrar class for keeping track of
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: s57classregistrar.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: s57classregistrar.cpp 22616 2011-06-29 19:19:03Z rouault $");
 
 
 #ifdef S57_BUILTIN_CLASSES
@@ -199,7 +199,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     }
     else if( strlen(pszProfile) > 0 )
     {
-       sprintf( szTargetFile, "s57objectclasses_%s.csv", pszProfile );
+       snprintf( szTargetFile, sizeof(szTargetFile), "s57objectclasses_%s.csv", pszProfile );
     }
     else
     {
@@ -220,6 +220,8 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "s57objectclasses columns don't match expected format!\n" );
+        if( fp != NULL )
+            VSIFClose( fp );
         return FALSE;
     }
 
@@ -270,7 +272,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     }
     else if( strlen(pszProfile) > 0 )
     {
-       sprintf( szTargetFile, "s57attributes_%s.csv", pszProfile );
+       snprintf( szTargetFile, sizeof(szTargetFile), "s57attributes_%s.csv", pszProfile );
     }
     else
     {
@@ -290,6 +292,8 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "s57attributes columns don't match expected format!\n" );
+        if( fp != NULL )
+            VSIFClose( fp );
         return FALSE;
     }
     
@@ -302,12 +306,12 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     //papapszAttrValues = (char ***) CPLCalloc(sizeof(char **),MAX_ATTRIBUTES);
     pachAttrType = (char *) CPLCalloc(sizeof(char),MAX_ATTRIBUTES);
     pachAttrClass = (char *) CPLCalloc(sizeof(char),MAX_ATTRIBUTES);
-    panAttrIndex = (int *) CPLCalloc(sizeof(int),MAX_ATTRIBUTES);
+    panAttrIndex = (GUInt16 *) CPLCalloc(sizeof(GUInt16),MAX_ATTRIBUTES);
     
 /* -------------------------------------------------------------------- */
 /*      Read and form string list.                                      */
 /* -------------------------------------------------------------------- */
-    int         iAttr;
+    GUInt16         iAttr;
     
     while( (pszLine = ReadLine(fp)) != NULL )
     {
@@ -320,7 +324,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
             continue;
         }
         
-        iAttr = atoi(papszTokens[0]);
+        iAttr = (GUInt16) atoi(papszTokens[0]);
         if( iAttr < 0 || iAttr >= nAttrMax
             || papszAttrNames[iAttr] != NULL )
         {
@@ -363,7 +367,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
             if( strcmp(papszAttrAcronym[panAttrIndex[iAttr]],
                        papszAttrAcronym[panAttrIndex[iAttr+1]]) > 0 )
             {
-                int     nTemp;
+                GInt16     nTemp;
 
                 nTemp = panAttrIndex[iAttr];
                 panAttrIndex[iAttr] = panAttrIndex[iAttr+1];
@@ -572,7 +576,7 @@ char **S57ClassRegistrar::GetPrimitives()
 /*                         FindAttrByAcronym()                          */
 /************************************************************************/
 
-int     S57ClassRegistrar::FindAttrByAcronym( const char * pszName )
+GInt16    S57ClassRegistrar::FindAttrByAcronym( const char * pszName )
 
 {
     int         iStart, iEnd, iCandidate;
diff --git a/ogr/ogrsf_frmts/s57/s57reader.cpp b/ogr/ogrsf_frmts/s57/s57reader.cpp
index 5a92d2e..a5e49d9 100644
--- a/ogr/ogrsf_frmts/s57/s57reader.cpp
+++ b/ogr/ogrsf_frmts/s57/s57reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57reader.cpp 19774 2010-05-27 15:12:33Z warmerdam $
+ * $Id: s57reader.cpp 23595 2011-12-18 22:58:47Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Reader class.
@@ -35,7 +35,7 @@
 #include <string>
 #include <fstream>
 
-CPL_CVSID("$Id: s57reader.cpp 19774 2010-05-27 15:12:33Z warmerdam $");
+CPL_CVSID("$Id: s57reader.cpp 23595 2011-12-18 22:58:47Z rouault $");
 
 #ifndef PI
 #define PI  3.14159265358979323846
@@ -358,6 +358,8 @@ int S57Reader::Ingest()
     while( (poRecord = poModule->ReadRecord()) != NULL )
     {
         DDFField        *poKeyField = poRecord->GetField(1);
+        if (poKeyField == NULL)
+            return FALSE;
         
         if( EQUAL(poKeyField->GetFieldDefn()->GetName(),"VRID") )
         {
@@ -383,7 +385,8 @@ int S57Reader::Ingest()
                 break;
 
               default:
-                CPLAssert( FALSE );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unhandled value for RCNM ; %d", nRCNM);
                 break;
             }
         }
@@ -1276,33 +1279,48 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 /* -------------------------------------------------------------------- */
 /*      Collect an edge geometry.                                       */
 /* -------------------------------------------------------------------- */
-    else if( nRCNM == RCNM_VE && poRecord->FindField( "SG2D" ) != NULL )
+    else if( nRCNM == RCNM_VE )
     {
-        int i, nVCount = poRecord->FindField("SG2D")->GetRepeatCount();
+        int nPoints = 0;
+        DDFField *poSG2D;
         OGRLineString *poLine = new OGRLineString();
 
-        poLine->setNumPoints( nVCount );
-        
-        for( i = 0; i < nVCount; i++ )
+        for( int iField = 0; iField < poRecord->GetFieldCount(); ++iField )
         {
-            poLine->setPoint( 
-                i, 
-                poRecord->GetIntSubfield("SG2D",0,"XCOO",i) / (double)nCOMF,
-                poRecord->GetIntSubfield("SG2D",0,"YCOO",i) / (double)nCOMF );
+            poSG2D = poRecord->GetField( iField );
+
+            if( EQUAL(poSG2D->GetFieldDefn()->GetName(), "SG2D") )
+            {
+                int nVCount = poSG2D->GetRepeatCount();
+
+                poLine->setNumPoints( nPoints + nVCount );
+
+                for( int i = 0; i < nVCount; ++i )
+                {
+                    poLine->setPoint
+                        (nPoints++,
+                        poRecord->GetIntSubfield("SG2D",0,"XCOO",i) / (double)nCOMF,
+                        poRecord->GetIntSubfield("SG2D",0,"YCOO",i) / (double)nCOMF );
+                }
+            }
         }
+
         poFeature->SetGeometryDirectly( poLine );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Special edge fields.                                            */
+/*      Allow either 2 VRPT fields or one VRPT field with 2 rows        */
 /* -------------------------------------------------------------------- */
     DDFField *poVRPT;
 
     if( nRCNM == RCNM_VE 
         && (poVRPT = poRecord->FindField( "VRPT" )) != NULL )
     {
+        int iField = 0, iSubField = 1;
+
         poFeature->SetField( "NAME_RCNM_0", RCNM_VC );
-        poFeature->SetField( "NAME_RCID_0", ParseName( poVRPT, 0 ) );
+        poFeature->SetField( "NAME_RCID_0", ParseName( poVRPT ) );
         poFeature->SetField( "ORNT_0", 
                              poRecord->GetIntSubfield("VRPT",0,"ORNT",0) );
         poFeature->SetField( "USAG_0", 
@@ -1312,17 +1330,38 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
         poFeature->SetField( "MASK_0", 
                              poRecord->GetIntSubfield("VRPT",0,"MASK",0) );
                              
+        if( poVRPT->GetRepeatCount() == 1 )
+        {
+            // Only one row, need a second VRPT field
+            iField = 1; iSubField = 0;
+
+            if( (poVRPT = poRecord->FindField( "VRPT", iField )) == NULL )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Unable to fetch last edge node.\n"
+                          "Feature OBJL=%s, RCID=%d may have corrupt or"
+                          " missing geometry.",
+                          poFeature->GetDefnRef()->GetName(),
+                          poFeature->GetFieldAsInteger( "RCID" ) );
+
+                return poFeature;
+            }
+        }
         
+        poFeature->SetField( "NAME_RCID_1", ParseName( poVRPT, iSubField ) );
         poFeature->SetField( "NAME_RCNM_1", RCNM_VC );
-        poFeature->SetField( "NAME_RCID_1", ParseName( poVRPT, 1 ) );
         poFeature->SetField( "ORNT_1", 
-                             poRecord->GetIntSubfield("VRPT",0,"ORNT",1) );
+                             poRecord->GetIntSubfield("VRPT",iField,
+                             "ORNT",iSubField) );
         poFeature->SetField( "USAG_1", 
-                             poRecord->GetIntSubfield("VRPT",0,"USAG",1) );
+                             poRecord->GetIntSubfield("VRPT",iField,
+                             "USAG",iSubField) );
         poFeature->SetField( "TOPI_1", 
-                             poRecord->GetIntSubfield("VRPT",0,"TOPI",1) );
+                             poRecord->GetIntSubfield("VRPT",iField,
+                             "TOPI",iSubField) );
         poFeature->SetField( "MASK_1", 
-                             poRecord->GetIntSubfield("VRPT",0,"MASK",1) );
+                             poRecord->GetIntSubfield("VRPT",iField,
+                             "MASK",iSubField) );
     }
 
     return poFeature;
@@ -1492,20 +1531,39 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
                           OGRLineString *poLine )
 
 {
-    int             nVCount;
-    DDFField        *poSG2D = poSRecord->FindField( "SG2D" );
-    DDFField        *poAR2D = poSRecord->FindField( "AR2D" );
+    int             nPoints = 0;
+    DDFField        *poSG2D, *poAR2D;
     DDFSubfieldDefn *poXCOO=NULL, *poYCOO=NULL;
     int bStandardFormat = TRUE;
 
-    if( poSG2D == NULL && poAR2D != NULL )
-        poSG2D = poAR2D;
+/* -------------------------------------------------------------------- */
+/*      Points may be multiple rows in one SG2D/AR2D field or           */
+/*      multiple SG2D/AR2D fields (or a combination of both)            */
+/*      Iterate over all the SG2D/AR2D fields in the record             */
+/* -------------------------------------------------------------------- */
+
+    for( int iField = 0; iField < poSRecord->GetFieldCount(); ++iField )
+    {
+        poSG2D = poSRecord->GetField( iField );
+
+        if( EQUAL(poSG2D->GetFieldDefn()->GetName(), "SG2D") )
+        {
+            poAR2D = NULL;
+        }
+        else if( EQUAL(poSG2D->GetFieldDefn()->GetName(), "AR2D") )
+        {
+            poAR2D = poSG2D;
+        }
+        else
+        {
+            /* Other types of fields are skipped */
+            continue;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Get some basic definitions.                                     */
 /* -------------------------------------------------------------------- */
-    if( poSG2D != NULL )
-    {
+
         poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("XCOO");
         poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("YCOO");
 
@@ -1515,43 +1573,40 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
             return FALSE;
         }
 
-        nVCount = poSG2D->GetRepeatCount();
-    }
-    else
-    {
-        return TRUE;
-    }
+        int nVCount = poSG2D->GetRepeatCount();
 
 /* -------------------------------------------------------------------- */
 /*      It is legitimate to have zero vertices for line segments        */
 /*      that just have the start and end node (bug 840).                */
+/*                                                                      */
+/*      This is bogus! nVCount != 0, because poXCOO != 0 here           */
+/*      In case of zero vertices, there will not be any SG2D fields     */
 /* -------------------------------------------------------------------- */
-    if( nVCount == 0 )
-        return TRUE;
+        if( nVCount == 0 )
+            continue;
  
 /* -------------------------------------------------------------------- */
 /*      Make sure out line is long enough to hold all the vertices      */
 /*      we will apply.                                                  */
 /* -------------------------------------------------------------------- */
-    int nVBase;
+        int nVBase;
 
-    if( iDirection < 0 )
-        nVBase = iStartVertex + nVCount;
-    else
-        nVBase = iStartVertex;
+        if( iDirection < 0 )
+            nVBase = iStartVertex + nPoints + nVCount;
+        else
+            nVBase = iStartVertex + nPoints;
 
-    if( poLine->getNumPoints() < iStartVertex + nVCount )
-        poLine->setNumPoints( iStartVertex + nVCount );
-        
+        if( poLine->getNumPoints() < iStartVertex + nPoints + nVCount )
+            poLine->setNumPoints( iStartVertex + nPoints + nVCount );
+
+        nPoints += nVCount;
 /* -------------------------------------------------------------------- */
 /*      Are the SG2D and XCOO/YCOO definitions in the form we expect?   */
 /* -------------------------------------------------------------------- */
-    if( poSG2D->GetFieldDefn()->GetSubfieldCount() != 2 )
-        bStandardFormat = FALSE;
-
-    if( !EQUAL(poXCOO->GetFormat(),"b24") 
-        || !EQUAL(poYCOO->GetFormat(),"b24") )
-        bStandardFormat = FALSE;
+        bStandardFormat = 
+            (poSG2D->GetFieldDefn()->GetSubfieldCount() == 2) &&
+            EQUAL(poXCOO->GetFormat(),"b24") &&
+            EQUAL(poYCOO->GetFormat(),"b24");
 
 /* -------------------------------------------------------------------- */
 /*      Collect the vertices:                                           */
@@ -1561,35 +1616,35 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
 /*      extra calls to low level DDF methods as they are quite          */
 /*      expensive.                                                      */
 /* -------------------------------------------------------------------- */
-    if( bStandardFormat )
-    {
-        const char  *pachData;
-        int         nBytesRemaining;
-
-        pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,0);
-        
-        for( int i = 0; i < nVCount; i++ )
+        if( bStandardFormat )
         {
-            double      dfX, dfY;
-            GInt32      nXCOO, nYCOO;
+            const char  *pachData;
+            int         nBytesRemaining;
 
-            memcpy( &nYCOO, pachData, 4 );
-            pachData += 4;
-            memcpy( &nXCOO, pachData, 4 );
-            pachData += 4;
+            pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,0);
+
+            for( int i = 0; i < nVCount; i++ )
+            {
+                double      dfX, dfY;
+                GInt32      nXCOO, nYCOO;
+
+                memcpy( &nYCOO, pachData, 4 );
+                pachData += 4;
+                memcpy( &nXCOO, pachData, 4 );
+                pachData += 4;
 
 #ifdef CPL_MSB
-            CPL_SWAP32PTR( &nXCOO );
-            CPL_SWAP32PTR( &nYCOO );
+                CPL_SWAP32PTR( &nXCOO );
+                CPL_SWAP32PTR( &nYCOO );
 #endif
-            dfX = nXCOO / (double) nCOMF;
-            dfY = nYCOO / (double) nCOMF;
+                dfX = nXCOO / (double) nCOMF;
+                dfY = nYCOO / (double) nCOMF;
 
-            poLine->setPoint( nVBase, dfX, dfY );
+                poLine->setPoint( nVBase, dfX, dfY );
 
-            nVBase += iDirection;
+                nVBase += iDirection;
+            }
         }
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Collect the vertices:                                           */
@@ -1599,51 +1654,52 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
 /*      things are changed about the SG2D fields such as making them    */
 /*      floating point or a different byte order.                       */
 /* -------------------------------------------------------------------- */
-    else
-    {
-        for( int i = 0; i < nVCount; i++ )
+        else
         {
-            double      dfX, dfY;
-            const char  *pachData;
-            int         nBytesRemaining;
+            for( int i = 0; i < nVCount; i++ )
+            {
+                double      dfX, dfY;
+                const char  *pachData;
+                int         nBytesRemaining;
 
-            pachData = poSG2D->GetSubfieldData(poXCOO,&nBytesRemaining,i);
-                
-            dfX = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                / (double) nCOMF;
+                pachData = poSG2D->GetSubfieldData(poXCOO,&nBytesRemaining,i);
 
-            pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,i);
+                dfX = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
+                    / (double) nCOMF;
 
-            dfY = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                / (double) nCOMF;
-                
-            poLine->setPoint( nVBase, dfX, dfY );
+                pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,i);
 
-            nVBase += iDirection;
-        }
-    }
+                dfY = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
+                    / (double) nCOMF;
+
+                poLine->setPoint( nVBase, dfX, dfY );
+
+                nVBase += iDirection;
+            }
+       }
 
 /* -------------------------------------------------------------------- */
 /*      If this is actually an arc, turn the start, end and center      */
 /*      of rotation into a "stroked" arc linestring.                    */
 /* -------------------------------------------------------------------- */
-    if( poAR2D != NULL && poLine->getNumPoints() >= 3 )
-    {
-        OGRLineString *poArc;
-        int i, iLast = poLine->getNumPoints() - 1;
-        
-        poArc = S57StrokeArcToOGRGeometry_Points( 
-            poLine->getX(iLast-0), poLine->getY(iLast-0), 
-            poLine->getX(iLast-1), poLine->getY(iLast-1),
-            poLine->getX(iLast-2), poLine->getY(iLast-2),
-            30 );
-
-        if( poArc != NULL )
+        if( poAR2D != NULL && poLine->getNumPoints() >= 3 )
         {
-            for( i = 0; i < poArc->getNumPoints(); i++ )
-                poLine->setPoint( iLast-2+i, poArc->getX(i), poArc->getY(i) );
+            OGRLineString *poArc;
+            int i, iLast = poLine->getNumPoints() - 1;
+
+            poArc = S57StrokeArcToOGRGeometry_Points(
+                poLine->getX(iLast-0), poLine->getY(iLast-0),
+                poLine->getX(iLast-1), poLine->getY(iLast-1),
+                poLine->getX(iLast-2), poLine->getY(iLast-2),
+                30 );
+
+            if( poArc != NULL )
+            {
+                for( i = 0; i < poArc->getNumPoints(); i++ )
+                        poLine->setPoint( iLast-2+i, poArc->getX(i), poArc->getY(i) );
 
-            delete poArc;
+                delete poArc;
+            }
         }
     }
 
@@ -1683,9 +1739,12 @@ void S57Reader::AssemblePointGeometry( DDFRecord * poFRecord,
 
     double      dfX = 0.0, dfY = 0.0, dfZ = 0.0;
 
-    if( !FetchPoint( nRCNM, nRCID, &dfX, &dfY, &dfZ ) )
+    if( nRCID == -1 || !FetchPoint( nRCNM, nRCID, &dfX, &dfY, &dfZ ) )
     {
-        CPLAssert( FALSE );
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Failed to fetch %d/%d point geometry for point feature.\n"
+                  "Feature will have empty geometry.",
+                  nRCNM, nRCID );
         return;
     }
 
@@ -1781,6 +1840,33 @@ void S57Reader::AssembleSoundingGeometry( DDFRecord * poFRecord,
 }
 
 /************************************************************************/
+/*                            GetIntSubfield()                          */
+/************************************************************************/
+
+static int
+GetIntSubfield( DDFField *poField,
+                const char * pszSubfield,
+                int iSubfieldIndex)
+{
+    DDFSubfieldDefn *poSFDefn =
+        poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
+
+    if( poSFDefn == NULL )
+        return 0;
+
+/* -------------------------------------------------------------------- */
+/*      Get a pointer to the data.                                      */
+/* -------------------------------------------------------------------- */
+    int nBytesRemaining;
+
+    const char *pachData = poField->GetSubfieldData( poSFDefn,
+                                &nBytesRemaining,
+                                iSubfieldIndex );
+
+    return( poSFDefn->ExtractIntData( pachData, nBytesRemaining, NULL ) );
+}
+
+/************************************************************************/
 /*                        AssembleLineGeometry()                        */
 /************************************************************************/
 
@@ -1789,111 +1875,133 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
 
 {
     DDFField    *poFSPT;
-    int         nEdgeCount;
+    OGRLineString *poLine = new OGRLineString();
+    OGRMultiLineString *poMLS = new OGRMultiLineString();
+    double dlastfX( 0.0 ), dlastfY( 0.0 ), dfX, dfY;
 
 /* -------------------------------------------------------------------- */
-/*      Find the FSPT field.                                            */
+/*      Loop collecting edges.                                          */
+/*      Iterate over the FSPT fields.                                   */
 /* -------------------------------------------------------------------- */
-    poFSPT = poFRecord->FindField( "FSPT" );
-    if( poFSPT == NULL )
-        return;
+    const int nFieldCount = poFRecord->GetFieldCount();
 
-    nEdgeCount = poFSPT->GetRepeatCount();
+    for( int iField = 0; iField < nFieldCount; ++iField )
+    {
+        poFSPT = poFRecord->GetField( iField );
 
-/* ==================================================================== */
-/*      Loop collecting edges.                                          */
-/* ==================================================================== */
-    OGRLineString *poLine = new OGRLineString();
-    OGRMultiLineString *poMLS = new OGRMultiLineString();
+        if( !EQUAL(poFSPT->GetFieldDefn()->GetName(), "FSPT") )
+            continue;
 
-    for( int iEdge = 0; iEdge < nEdgeCount; iEdge++ )
-    {
-        DDFRecord       *poSRecord;
-        int             nRCID;
+/* -------------------------------------------------------------------- */
+/*      Loop over the rows of each FSPT field                           */
+/* -------------------------------------------------------------------- */
+        const int nEdgeCount = poFSPT->GetRepeatCount();
+
+        for( int iEdge = 0; iEdge < nEdgeCount; ++iEdge )
+        {
+            int  nVC_RCID_firstnode, nVC_RCID_lastnode;
+            bool bReverse = (GetIntSubfield( poFSPT, "ORNT", iEdge ) == 2);
 
 /* -------------------------------------------------------------------- */
 /*      Find the spatial record for this edge.                          */
 /* -------------------------------------------------------------------- */
-        nRCID = ParseName( poFSPT, iEdge );
+            int nRCID = ParseName( poFSPT, iEdge );
 
-        poSRecord = oVE_Index.FindRecord( nRCID );
-        if( poSRecord == NULL )
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Couldn't find spatial record %d.\n"
-                      "Feature OBJL=%s, RCID=%d may have corrupt or"
-                      "missing geometry.",
-                      nRCID,
-                      poFeature->GetDefnRef()->GetName(),
-                      poFRecord->GetIntSubfield( "FRID", 0, "RCID", 0 ) );
-            continue;
-        }
+            DDFRecord *poSRecord = oVE_Index.FindRecord( nRCID );
+            if( poSRecord == NULL )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Couldn't find spatial record %d.\n"
+                          "Feature OBJL=%s, RCID=%d may have corrupt or"
+                          "missing geometry.",
+                          nRCID,
+                          poFeature->GetDefnRef()->GetName(),
+                          GetIntSubfield( poFSPT, "RCID", 0 ) );
+                continue;
+            }
     
 /* -------------------------------------------------------------------- */
-/*      Establish the number of vertices, and whether we need to        */
-/*      reverse or not.                                                 */
+/*      Get the first and last nodes                                    */
 /* -------------------------------------------------------------------- */
-        int             nVCount;
-        int             nStart, nEnd, nInc;
-        DDFField        *poSG2D = poSRecord->FindField( "SG2D" );
-        DDFField        *poAR2D = poSRecord->FindField( "AR2D" );
-        DDFSubfieldDefn *poXCOO=NULL, *poYCOO=NULL;
+            DDFField *poVRPT = poSRecord->FindField( "VRPT" );
+            if( poVRPT == NULL )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                    "Unable to fetch start node for RCID %d.\n"
+                    "Feature OBJL=%s, RCID=%d may have corrupt or"
+                    "missing geometry.",
+                    nRCID,
+                    poFeature->GetDefnRef()->GetName(),
+                    GetIntSubfield( poFSPT, "RCID", 0 ) );
+                continue;
+            }
 
-        if( poSG2D == NULL && poAR2D != NULL )
-            poSG2D = poAR2D;
+            // The "VRPT" field has only one row
+            // Get the next row from a second "VRPT" field
+            if( poVRPT->GetRepeatCount() == 1 )
+            {
+                nVC_RCID_firstnode = ParseName( poVRPT );
+                poVRPT = poSRecord->FindField( "VRPT", 1 );
 
-        if( poSG2D != NULL )
-        {
-            poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("XCOO");
-            poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("YCOO");
+                if( poVRPT == NULL )
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Unable to fetch end node for RCID %d.\n"
+                            "Feature OBJL=%s, RCID=%d may have corrupt or"
+                            "missing geometry.",
+                            nRCID,
+                            poFeature->GetDefnRef()->GetName(),
+                            GetIntSubfield( poFSPT, "RCID", 0 ) );
+                    continue;
+                }
 
-            nVCount = poSG2D->GetRepeatCount();
-        }
-        else
-            nVCount = 0;
+                nVC_RCID_lastnode = ParseName( poVRPT );
 
-        if( poFRecord->GetIntSubfield( "FSPT", 0, "ORNT", iEdge ) == 2 )
-        {
-            nStart = nVCount-1;
-            nEnd = 0;
-            nInc = -1;
-        }
-        else
-        {
-            nStart = 0;
-            nEnd = nVCount-1;
-            nInc = 1;
-        }
+                if( bReverse )
+                {
+                    int tmp = nVC_RCID_lastnode;
+                    nVC_RCID_lastnode = nVC_RCID_firstnode;
+                    nVC_RCID_firstnode = tmp;
+                }
+            }
+            else if( bReverse )
+            {
+                nVC_RCID_lastnode = ParseName( poVRPT );
+                nVC_RCID_firstnode = ParseName( poVRPT, 1 );
+            }
+            else
+            {
+                nVC_RCID_firstnode = ParseName( poVRPT );
+                nVC_RCID_lastnode = ParseName( poVRPT, 1 );
+            }
+
+            if( nVC_RCID_firstnode == -1 ||
+                ! FetchPoint( RCNM_VC, nVC_RCID_firstnode, &dfX, &dfY ) )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                    "Unable to fetch start node RCID=%d.\n"
+                    "Feature OBJL=%s, RCID=%d may have corrupt or"
+                    " missing geometry.",
+                    nVC_RCID_firstnode,
+                    poFeature->GetDefnRef()->GetName(),
+                    poFRecord->GetIntSubfield( "FRID", 0,
+                                "RCID", 0 ) );
+
+                continue;
+            }
 
 /* -------------------------------------------------------------------- */
-/*      Fetch the first node.  Does it match the trailing node on       */
-/*      the existing line string?  If so, skip it, otherwise if the     */
-/*      existing linestring is not empty we need to push it out and     */
-/*      start a new one as it means things are not connected.           */
+/*      Does the first node match the trailing node on the existing     */
+/*      line string?  If so, skip it, otherwise if the existing         */
+/*      linestring is not empty we need to push it out and start a      */
+/*      new one as it means things are not connected.                   */
 /* -------------------------------------------------------------------- */
-        {
-            int         nVC_RCID;
-            double      dfX, dfY;
-            
-            if( nInc == 1 )
-                nVC_RCID = ParseName( poSRecord->FindField( "VRPT" ), 0 );
-            else
-                nVC_RCID = ParseName( poSRecord->FindField( "VRPT" ), 1 );
-
-            if( !FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Unable to fetch start node RCID%d.\n"
-                          "Feature OBJL=%s, RCID=%d may have corrupt or"
-                          " missing geometry.", 
-                          nVC_RCID, 
-                          poFeature->GetDefnRef()->GetName(),
-                          poFRecord->GetIntSubfield( "FRID", 0, "RCID", 0 ) );
-            else if( poLine->getNumPoints() == 0 )
+            if( poLine->getNumPoints() == 0 )
             {
                 poLine->addPoint( dfX, dfY );
             }
-            else if( ABS(poLine->getX(poLine->getNumPoints()-1) - dfX) > 0.00000001 
-                     || ABS(poLine->getY(poLine->getNumPoints()-1) - dfY) > 0.00000001 )
+            else if( ABS(dlastfX - dfX) > 0.00000001 ||
+                ABS(dlastfY - dfY) > 0.00000001 )
             {
                 // we need to start a new linestring.
                 poMLS->addGeometryDirectly( poLine );
@@ -1902,56 +2010,89 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
             }
             else
                 /* omit point, already present */;
-        }
+
+            // remember the coordinates of the last point
+            dlastfX = dfX; dlastfY = dfY;
         
 /* -------------------------------------------------------------------- */
 /*      Collect the vertices.                                           */
+/*      Iterate over all the SG2D fields in the Spatial record          */
 /* -------------------------------------------------------------------- */
-        int             nVBase = poLine->getNumPoints();
-        
-        poLine->setNumPoints( nVCount+nVBase );
+            int             nVBase, nVCount;
+            int             nStart, nEnd, nInc;
+            DDFField        *poSG2D;
+            DDFSubfieldDefn *poXCOO=NULL, *poYCOO=NULL;
 
-        for( int i = nStart; i != nEnd+nInc; i += nInc )
-        {
-            double      dfX, dfY;
-            const char  *pachData;
-            int         nBytesRemaining;
+            for( int iSField = 0; iSField < poSRecord->GetFieldCount();
+                ++iSField )
+            {
+                poSG2D = poSRecord->GetField( iSField );
 
-            pachData = poSG2D->GetSubfieldData(poXCOO,&nBytesRemaining,i);
-            
-            dfX = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                    / (double) nCOMF;
-            
-            pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,i);
-            
-            dfY = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
-                / (double) nCOMF;
-                
-            poLine->setPoint( nVBase++, dfX, dfY );
-        }
+                if( EQUAL(poSG2D->GetFieldDefn()->GetName(), "SG2D") ||
+                    EQUAL(poSG2D->GetFieldDefn()->GetName(), "AR2D") )
+                {
+                    poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("XCOO");
+                    poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn("YCOO");
+
+                    nVCount = poSG2D->GetRepeatCount();
+
+                    if( bReverse )
+                    {
+                        nStart = nVCount-1;
+                        nEnd = 0;
+                        nInc = -1;
+                    }
+                    else
+                    {
+                        nStart = 0;
+                        nEnd = nVCount-1;
+                        nInc = 1;
+                    }
+
+                    nVBase = poLine->getNumPoints();
+                    poLine->setNumPoints( nVBase + nVCount );
+
+                    const char *pachData;
+                    int nBytesRemaining;
+
+                    for( int i = nStart; i != nEnd+nInc; i += nInc )
+                    {
+                        pachData = poSG2D->GetSubfieldData(poXCOO,&nBytesRemaining,i);
+
+                        dfX = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
+                            / (double) nCOMF;
+
+                        pachData = poSG2D->GetSubfieldData(poYCOO,&nBytesRemaining,i);
+
+                        dfY = poXCOO->ExtractIntData(pachData,nBytesRemaining,NULL)
+                            / (double) nCOMF;
+
+                        poLine->setPoint( nVBase++, dfX, dfY );
+                    }
+                }
+            }
+            dlastfX = dfX; dlastfY = dfY;
 
 /* -------------------------------------------------------------------- */
 /*      Add the end node.                                               */
 /* -------------------------------------------------------------------- */
-        {
-            int         nVC_RCID;
-            double      dfX, dfY;
-            
-            if( nInc == 1 )
-                nVC_RCID = ParseName( poSRecord->FindField( "VRPT" ), 1 );
-            else
-                nVC_RCID = ParseName( poSRecord->FindField( "VRPT" ), 0 );
-
-            if( FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
+            if( nVC_RCID_lastnode != -1 &&
+                FetchPoint( RCNM_VC, nVC_RCID_lastnode, &dfX, &dfY ) )
+            {
                 poLine->addPoint( dfX, dfY );
+                dlastfX = dfX; dlastfY = dfY;
+            }
             else
-                CPLError( CE_Warning, CPLE_AppDefined, 
-                          "Unable to fetch end node RCID=%d.\n"
-                          "Feature OBJL=%s, RCID=%d may have corrupt or"
-                          " missing geometry.", 
-                          nVC_RCID, 
-                          poFeature->GetDefnRef()->GetName(),
-                          poFRecord->GetIntSubfield( "FRID", 0, "RCID", 0 ) );
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                    "Unable to fetch end node RCID=%d.\n"
+                    "Feature OBJL=%s, RCID=%d may have corrupt or"
+                    " missing geometry.",
+                    nVC_RCID_lastnode,
+                    poFeature->GetDefnRef()->GetName(),
+                    poFRecord->GetIntSubfield( "FRID", 0, "RCID", 0 ) );
+                continue;
+            }
         }
     }
 
@@ -1991,10 +2132,15 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
 /* -------------------------------------------------------------------- */
 /*      Find the FSPT fields.                                           */
 /* -------------------------------------------------------------------- */
-    for( int iFSPT = 0; 
-         (poFSPT = poFRecord->FindField( "FSPT", iFSPT )) != NULL;
-         iFSPT++ )
+    const int nFieldCount = poFRecord->GetFieldCount();
+
+    for( int iFSPT = 0; iFSPT < nFieldCount; ++iFSPT )
     {
+        poFSPT = poFRecord->GetField(iFSPT);
+
+        if ( !EQUAL(poFSPT->GetFieldDefn()->GetName(), "FSPT") )
+            continue;
+
         int         nEdgeCount;
 
         nEdgeCount = poFSPT->GetRepeatCount();
@@ -2016,7 +2162,12 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
             if( poSRecord == NULL )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Couldn't find spatial record %d.\n", nRCID );
+                    "Couldn't find spatial record %d.\n"
+                    "Feature OBJL=%s, RCID=%d may have corrupt or"
+                    "missing geometry.",
+                    nRCID,
+                    poFeature->GetDefnRef()->GetName(),
+                    GetIntSubfield( poFSPT, "RCID", 0 ) );
                 continue;
             }
     
@@ -2028,17 +2179,16 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
 /* -------------------------------------------------------------------- */
 /*      Add the start node.                                             */
 /* -------------------------------------------------------------------- */
+            DDFField *poVRPT = poSRecord->FindField( "VRPT" );
+            if( poVRPT != NULL )
             {
-                int         nVC_RCID;
-                double      dfX, dfY;
-            
-                nVC_RCID = ParseName( poSRecord->FindField( "VRPT" ), 0 );
+                int nVC_RCID = ParseName( poVRPT );
+                double dfX, dfY;
 
-                if( nVC_RCID != -1
-                    && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
+                if( nVC_RCID != -1 && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
                     poLine->addPoint( dfX, dfY );
             }
-        
+
 /* -------------------------------------------------------------------- */
 /*      Collect the vertices.                                           */
 /* -------------------------------------------------------------------- */
@@ -2051,13 +2201,20 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
 /* -------------------------------------------------------------------- */
 /*      Add the end node.                                               */
 /* -------------------------------------------------------------------- */
+            if( poVRPT->GetRepeatCount() > 1 )
             {
-                int         nVC_RCID;
-                double      dfX, dfY;
-            
-                nVC_RCID = ParseName( poSRecord->FindField( "VRPT" ), 1 );
+                int nVC_RCID = ParseName( poVRPT, 1 );
+                double dfX, dfY;
+
+                if( nVC_RCID != -1 && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
+                    poLine->addPoint( dfX, dfY );
+            }
+            else if( (poVRPT = poSRecord->FindField( "VRPT", 1 )) != NULL )
+            {
+                int nVC_RCID = ParseName( poVRPT );
+                double dfX, dfY;
 
-                if( FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
+                if( nVC_RCID != -1 && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
                     poLine->addPoint( dfX, dfY );
             }
 
@@ -2155,6 +2312,7 @@ OGRFeatureDefn * S57Reader::FindFDefn( DDFRecord * poRecord )
 /*                                                                      */
 /*      Pull the RCNM and RCID values from a NAME field.  The RCID      */
 /*      is returned and the RCNM can be gotten via the pnRCNM argument. */
+/*      Note: nIndex is the index of the requested 'NAME' instance      */
 /************************************************************************/
 
 int S57Reader::ParseName( DDFField * poField, int nIndex, int * pnRCNM )
@@ -2433,16 +2591,33 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         /* If we don't have SG2D, check for SG3D */
         if( poDstSG2D == NULL )
         {
-            poSrcSG2D = poUpdate->FindField( "SG3D" );
             poDstSG2D = poTarget->FindField( "SG3D" );
+            if (poDstSG2D != NULL) 
+            { 
+                poSrcSG2D = poUpdate->FindField("SG3D"); 
+            } 
         }
 
-        if( (poSrcSG2D == NULL && nCCUI != 2) || poDstSG2D == NULL )
+        if( (poSrcSG2D == NULL && nCCUI != 2) 
+            || (poDstSG2D == NULL && nCCUI != 1) )
         {
             CPLAssert( FALSE );
             return FALSE;
         }
 
+        if (poDstSG2D == NULL) 
+        {
+            poTarget->AddField(poTarget->GetModule()->FindFieldDefn("SG2D"));
+            poDstSG2D = poTarget->FindField("SG2D");
+            if (poDstSG2D == NULL) {
+                CPLAssert( FALSE );
+                return FALSE;
+            }
+
+            // Delete null default data that was created
+            poTarget->SetFieldRaw( poDstSG2D, 0, NULL, 0 );
+        }
+
         nCoordSize = poDstSG2D->GetFieldDefn()->GetFixedWidth();
 
         if( nCCUI == 1 ) /* INSERT */
diff --git a/ogr/ogrsf_frmts/s57/s57writer.cpp b/ogr/ogrsf_frmts/s57/s57writer.cpp
index 15189af..40fc740 100644
--- a/ogr/ogrsf_frmts/s57/s57writer.cpp
+++ b/ogr/ogrsf_frmts/s57/s57writer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57writer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: s57writer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Writer class.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: s57writer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: s57writer.cpp 21684 2011-02-11 22:14:01Z warmerdam $");
 
 /************************************************************************/
 /*                             S57Writer()                              */
@@ -549,7 +549,7 @@ DDFRecord *S57Writer::MakeRecord()
     unsigned char abyData[3];
 
     abyData[0] = nNext0001Index % 256;
-    abyData[1] = nNext0001Index / 256; 
+    abyData[1] = (unsigned char) (nNext0001Index / 256); 
     abyData[2] = DDF_FIELD_TERMINATOR;
 
     poField = poRec->AddField( poModule->FindFieldDefn( "0001" ) );
@@ -736,9 +736,9 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
         nRCID = poFeature->GetFieldAsInteger( "NAME_RCID_0");
         szName[0] = RCNM_VC;
         szName[1] = nRCID & 0xff;
-        szName[2] = (nRCID & 0xff00) >> 8;
-        szName[3] = (nRCID & 0xff0000) >> 16;
-        szName[4] = (nRCID & 0xff000000) >> 24;
+        szName[2] = (char) ((nRCID & 0xff00) >> 8);
+        szName[3] = (char) ((nRCID & 0xff0000) >> 16);
+        szName[4] = (char) ((nRCID & 0xff000000) >> 24);
         
         poRec->SetStringSubfield( "VRPT", 0, "NAME", 0, szName, 5 );
         poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 0, 
@@ -753,9 +753,9 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
         nRCID = poFeature->GetFieldAsInteger( "NAME_RCID_1");
         szName[0] = RCNM_VC;
         szName[1] = nRCID & 0xff;
-        szName[2] = (nRCID & 0xff00) >> 8;
-        szName[3] = (nRCID & 0xff0000) >> 16;
-        szName[4] = (nRCID & 0xff000000) >> 24;
+        szName[2] = (char) ((nRCID & 0xff00) >> 8);
+        szName[3] = (char) ((nRCID & 0xff0000) >> 16);
+        szName[4] = (char) ((nRCID & 0xff000000) >> 24);
 
         poRec->SetStringSubfield( "VRPT", 0, "NAME", 1, szName, 5 );
         poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 1, 
@@ -781,13 +781,13 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
 /*                             GetHEXChar()                             */
 /************************************************************************/
 
-static int GetHEXChar( const char *pszSrcHEXString )
+static char GetHEXChar( const char *pszSrcHEXString )
 
 {
     int nResult = 0;
 
     if( pszSrcHEXString[0] == '\0' || pszSrcHEXString[1] == '\0' )
-        return 0;
+        return (char) 0;
 
     if( pszSrcHEXString[0] >= '0' && pszSrcHEXString[0] <= '9' )
         nResult += (pszSrcHEXString[0] - '0') * 16;
@@ -803,7 +803,7 @@ static int GetHEXChar( const char *pszSrcHEXString )
     else if( pszSrcHEXString[1] >= 'A' && pszSrcHEXString[1] <= 'F' )
         nResult += pszSrcHEXString[1] - 'A' + 10;
 
-    return nResult;
+    return (char) nResult;
 }
 
 /************************************************************************/
@@ -894,11 +894,11 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
         {
             GInt32 nRCID = CPL_LSBWORD32(panRCID[i]);
 
-            pabyRawData[i*8 + 0] = panRCNM[i];
+            pabyRawData[i*8 + 0] = (GByte) panRCNM[i];
             memcpy( pabyRawData + i*8 + 1, &nRCID, 4 );
-            pabyRawData[i*8 + 5] = panORNT[i];
-            pabyRawData[i*8 + 6] = panUSAG[i];
-            pabyRawData[i*8 + 7] = panMASK[i];
+            pabyRawData[i*8 + 5] = (GByte) panORNT[i];
+            pabyRawData[i*8 + 6] = (GByte) panUSAG[i];
+            pabyRawData[i*8 + 7] = (GByte) panMASK[i];
         }
 
         poField = poRec->AddField( poModule->FindFieldDefn( "FSPT" ) );
diff --git a/ogr/ogrsf_frmts/sde/drv_sde.html b/ogr/ogrsf_frmts/sde/drv_sde.html
index b067ff2..b93c9db 100644
--- a/ogr/ogrsf_frmts/sde/drv_sde.html
+++ b/ogr/ogrsf_frmts/sde/drv_sde.html
@@ -92,6 +92,11 @@ to <b>always</b> use fully-qualified table names. <p>
         time.  By default, multiversion tables are created when layers are created 
         on an SDE datasource.
     </li>
+    <li>
+        <b>USE_NSTRING</b>: If this option is set to "TRUE" then string fields
+        will be created as type NSTRING.  This option was added for GDAL/OGR 
+        1.9.0.
+    </li>
 </ul>
 
 
@@ -113,6 +118,14 @@ to <b>always</b> use fully-qualified table names. <p>
     does nothing to reconsile any edits that existed on that version before 
     doing so and essentially throws them away.
 </li>
+<li>
+    <b>OGR_SDE_USE_NSTRING</b>: If this option is set to "TRUE" then string 
+    fields will be created as type NSTRING.  This option was added for 
+    GDAL/OGR 1.9.0.  
+</li>
+
+<li> 
+   
 
 </ul>
 
diff --git a/ogr/ogrsf_frmts/sde/ogr_sde.h b/ogr/ogrsf_frmts/sde/ogr_sde.h
index fbae6e9..460d932 100644
--- a/ogr/ogrsf_frmts/sde/ogr_sde.h
+++ b/ogr/ogrsf_frmts/sde/ogr_sde.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sde.h 14242 2008-04-09 20:51:50Z hobu $
+ * $Id: ogr_sde.h 22263 2011-04-30 02:51:52Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR SDE driver.
@@ -88,6 +88,8 @@ class OGRSDELayer : public OGRLayer
 
     int                 iShapeColumn;
 
+    int                 bUseNSTRING; 
+
 
     char              **papszAllColumns;
     std::vector<int>    anFieldMap;     // SDE index of OGR field.
@@ -146,6 +148,8 @@ class OGRSDELayer : public OGRLayer
                                 { nFIDColumnType = nType; }
     void                SetPrecisionFlag( int bFlag )
                                 { bPreservePrecision = bFlag; }
+    void                SetUseNSTRING( int bFlag )
+                                { bUseNSTRING = bFlag; }
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
index 7a75a83..8dd9e77 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdedatasource.cpp 14243 2008-04-09 21:17:06Z hobu $
+ * $Id: ogrsdedatasource.cpp 22470 2011-05-31 18:18:26Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDEDataSource class.
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "gdal.h"
 
-CPL_CVSID("$Id: ogrsdedatasource.cpp 14243 2008-04-09 21:17:06Z hobu $");
+CPL_CVSID("$Id: ogrsdedatasource.cpp 22470 2011-05-31 18:18:26Z warmerdam $");
 
 /************************************************************************/
 /*                          OGRSDEDataSource()                           */
@@ -71,7 +71,8 @@ OGRSDEDataSource::~OGRSDEDataSource()
     
     // Commit our transactions if we were opened for update
     if (bDSUpdate && bDSUseVersionEdits && (nNextState != -2 && nState != SE_DEFAULT_STATE_ID )  ) {
-        CPLDebug("OGR_SDE", "Moving states from %ld to %ld", nState, nNextState);
+        CPLDebug("OGR_SDE", "Moving states from %ld to %ld", 
+                 (long) nState, (long) nNextState);
 
         SE_connection_commit_transaction(hConnection);
         nSDEErr = SE_state_close(hConnection, nNextState);
@@ -554,8 +555,8 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
 
     
     if (bDSUpdate && bDSUseVersionEdits) {
-        LONG nLockCount;
-        SE_VERSION_LOCK* pahLocks;
+        LONG nLockCount = 0;
+        SE_VERSION_LOCK* pahLocks = NULL;
         nSDEErr = SE_version_get_locks(hConnection, pszVersionName, &nLockCount, &pahLocks);
     
         if( nSDEErr != SE_SUCCESS )
@@ -836,20 +837,21 @@ OGRSDEDataSource::CreateLayer( const char * pszLayerName,
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
     int iLayer;
+    CPLString osFullName = pszLayerName;
 
-
-    // TODO: This is deficient. You can open a layer as 'tablename', but it
-    // will be known as 'SDE.tablename' or whatever fully-qualified name.
-    // This won't match in that case.
+    if( strchr(pszLayerName,'.') == NULL )
+        osFullName = "SDE." + osFullName;
 
     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     {
-
-        if( EQUAL(pszLayerName,
-                  papoLayers[iLayer]->GetLayerDefn()->GetName()) )
+        // We look for an exact match or for SDE.layername which is how
+        // the layer will be known after reading back. 
+        if( EQUAL(osFullName,
+                  papoLayers[iLayer]->GetLayerDefn()->GetName())
+            || EQUAL(pszLayerName, 
+                     papoLayers[iLayer]->GetLayerDefn()->GetName()) )
         {
-            if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
-                && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
+            if( CSLFetchBoolean( papszOptions, "OVERWRITE", FALSE ) )
             {
                 DeleteLayer( iLayer );
             }
@@ -866,6 +868,51 @@ OGRSDEDataSource::CreateLayer( const char * pszLayerName,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Sometimes there are residual layers left around and we need     */
+/*      to blow them away.                                              */
+/* -------------------------------------------------------------------- */
+    SE_REGINFO *ahTableList;
+    LONG nTableListCount;
+    int iTable;
+
+    nSDEErr = SE_registration_get_info_list( hConnection, &ahTableList,
+                                             &nTableListCount );
+    if( nSDEErr != SE_SUCCESS )
+    {
+        IssueSDEError( nSDEErr, "SE_registration_get_info_list" );
+        return NULL;
+    }
+
+    for( iTable = 0; iTable < nTableListCount; iTable++ )
+    {
+        char szTableName[SE_QUALIFIED_TABLE_NAME+1];
+        szTableName[0] = '\0';
+
+        SE_reginfo_get_table_name( ahTableList[iTable], szTableName );
+        if( EQUAL(szTableName,pszLayerName) 
+            || EQUAL(szTableName,osFullName) )
+        {
+            if( !CSLFetchBoolean( papszOptions, "OVERWRITE", FALSE ) )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                          "Registration informatin for  %s already exists, CreateLayer failed.\n"
+                          "Use the layer creation option OVERWRITE=YES to pre-clear it.",
+                          pszLayerName );
+                return NULL;
+            }
+
+            CPLDebug( "SDE", "sde_layer_delete(%s) - hidden/residual layer.",
+                      osFullName.c_str() );
+
+            SE_layer_delete( hConnection, szTableName, "SHAPE");
+            SE_registration_delete( hConnection, szTableName );
+            SE_table_delete( hConnection, szTableName );
+        }
+    }
+
+    SE_registration_free_info_list( nTableListCount, ahTableList );
+
+/* -------------------------------------------------------------------- */
 /*      Get various layer creation options.                             */
 /* -------------------------------------------------------------------- */
     const char         *pszExpectedFIDName;
@@ -959,10 +1006,15 @@ OGRSDEDataSource::CreateLayer( const char * pszLayerName,
              || wkbFlatten(eType) == wkbMultiLineString )
         nLayerShapeTypes |= ( SE_LINE_TYPE_MASK | SE_SIMPLE_LINE_TYPE_MASK );
 
-    else if( wkbFlatten(eType) == wkbPolygon
-             || wkbFlatten(eType) == wkbMultiPolygon )
+    else if( wkbFlatten(eType) == wkbPolygon )
+    {
         nLayerShapeTypes |= SE_AREA_TYPE_MASK;
-    
+    }
+    else if( wkbFlatten(eType) == wkbMultiPolygon )
+    {
+        nLayerShapeTypes |= SE_AREA_TYPE_MASK;
+        nLayerShapeTypes |= SE_MULTIPART_TYPE_MASK;
+    }
     else if( eType == wkbUnknown )
     {
         nLayerShapeTypes |= (  SE_POINT_TYPE_MASK
@@ -1036,7 +1088,12 @@ OGRSDEDataSource::CreateLayer( const char * pszLayerName,
             return NULL;
         }
     }
-    
+
+    CPLDebug( "SDE", "Creating layer with envelope (%g,%g) to (%g,%g)",
+              sLayerEnvelope.minx,
+              sLayerEnvelope.miny,
+              sLayerEnvelope.maxx,
+              sLayerEnvelope.maxy );
     nSDEErr = SE_layerinfo_set_envelope( hLayerInfo, &sLayerEnvelope );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1203,6 +1260,9 @@ OGRSDEDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     poLayer->SetFIDColType( SE_REGISTRATION_ROW_ID_COLUMN_TYPE_SDE );
 
+    poLayer->SetUseNSTRING( 
+        CSLFetchBoolean( papszOptions, "USE_NSTRING", FALSE ) );
+
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
@@ -1262,7 +1322,9 @@ void OGRSDEDataSource::EnumerateSpatialTables()
         return;
     }
 
-    CPLDebug( "OGR_SDE", "SDE::EnumerateSpatialTables() found %ld tables.", nTableListCount );
+    CPLDebug( "OGR_SDE", 
+              "SDE::EnumerateSpatialTables() found %d tables.", 
+              (int) nTableListCount );
 
 /* -------------------------------------------------------------------- */
 /*      Process the tables, turning any appropriate ones into layers.   */
@@ -1318,15 +1380,21 @@ void OGRSDEDataSource::CreateLayerFromRegInfo( SE_REGINFO& reginfo )
     LONG nFIDColType;
     LONG nSDEErr;
 
-    // Ignore non-spatial, or hidden tables. 
-    if( !SE_reginfo_has_layer( reginfo ) || SE_reginfo_is_hidden( reginfo ) )
+    nSDEErr = SE_reginfo_get_table_name( reginfo, szTableName );
+    if( nSDEErr != SE_SUCCESS )
     {
+        CPLDebug( "SDE", 
+                  "Ignoring reginfo '%p', no table name.",
+                  reginfo );
         return;
     }
 
-    nSDEErr = SE_reginfo_get_table_name( reginfo, szTableName );
-    if( nSDEErr != SE_SUCCESS )
+    // Ignore non-spatial, or hidden tables. 
+    if( !SE_reginfo_has_layer( reginfo ) || SE_reginfo_is_hidden( reginfo ) )
     {
+        CPLDebug( "SDE", 
+                  "Ignoring layer '%s' as it is hidden or does not have a reginfo layer.", 
+                  szTableName );
         return;
     }
 
@@ -1408,7 +1476,34 @@ OGRErr OGRSDEDataSource::ConvertOSRtoSDESpatRef( OGRSpatialReference *poSRS,
     if( SE_coordref_set_by_description( *psCoordRef, pszWkt ) != SE_SUCCESS )
         return OGRERR_FAILURE;
     
+    {
+        SE_ENVELOPE     sGenericEnvelope;
+        SE_coordref_get_xy_envelope( *psCoordRef, &sGenericEnvelope );
+
+        CPLDebug( "SDE", 
+                  "Created coordref '%s' with envelope (%g,%g) to (%g,%g)",
+                  pszWkt,
+                  sGenericEnvelope.minx,
+                  sGenericEnvelope.miny,
+                  sGenericEnvelope.maxx,
+                  sGenericEnvelope.maxy );
+    }
+
+    if( poSRS && poSRS->IsGeographic() )
+    {
+        LONG nSDEErr;
+
+        // Reset the offset and precision to match the ordinary values
+        // for SDE geographic coordinate systems. 
+        nSDEErr = SE_coordref_set_xy( *psCoordRef, -400, -400, 1.11195e9 );
+
+        if( nSDEErr != SE_SUCCESS ) 
+        {
+            IssueSDEError( nSDEErr, "SE_coordref_set_xy()" );
+        }
+    }
+
     CPLFree( pszWkt );
-    
+
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
index f0b46e1..be6bb99 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdelayer.cpp 14190 2008-04-05 04:30:14Z hobu $
+ * $Id: ogrsdelayer.cpp 22470 2011-05-31 18:18:26Z warmerdam $
  *
  * 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 14190 2008-04-05 04:30:14Z hobu $");
+CPL_CVSID("$Id: ogrsdelayer.cpp 22470 2011-05-31 18:18:26Z warmerdam $");
 
 /************************************************************************/
 /*                            OGRSDELayer()                             */
@@ -60,6 +60,7 @@ OGRSDELayer::OGRSDELayer( OGRSDEDataSource *poDSIn, int bUpdate )
     hCoordRef = NULL;
     papszAllColumns = NULL;
     bHaveLayerInfo = FALSE;
+    bUseNSTRING = FALSE;
 }
 
 /************************************************************************/
@@ -215,16 +216,12 @@ int OGRSDELayer::Initialize( const char *pszTableName,
 #ifdef SE_UUID_TYPE
           case SE_UUID_TYPE:
 #endif
-            eOGRType = OFTString;
-            nWidth = asColumnDefs[iCol].size;
-            break;
-
 #ifdef SE_NSTRING_TYPE
           case SE_NSTRING_TYPE:
-            eOGRType = OFTWideString;
+#endif
+            eOGRType = OFTString;
             nWidth = asColumnDefs[iCol].size;
             break;
-#endif
 
           case SE_BLOB_TYPE:
             eOGRType = OFTBinary;
@@ -344,6 +341,11 @@ int OGRSDELayer::NeedLayerInfo()
             poSRS = new OGRSpatialReference(szWKT);
             poSRS->morphFromESRI();
         }
+
+	LFLOAT falsex, falsey, xyunits;
+	nSDEErr = SE_coordref_get_xy( hCoordRef, &falsex, &falsey, &xyunits );
+	CPLDebug( "SDE", "SE_coordref_get_xy(%s) = %g/%g/%g",
+		  pszDbTableName, falsex, falsey, xyunits );
     }
 
     return TRUE;
@@ -359,7 +361,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
         return wkbUnknown;
 
     int nSDEErr;
-    long nShapeTypeMask = 0;
+    LONG nShapeTypeMask = 0;
   
 /* -------------------------------------------------------------------- */
 /*      Check layerinfo flags to establish what geometry types may      */
@@ -960,6 +962,26 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
             }
         }
         
+        else if( poFieldDefn->GetType() == OFTString 
+                 && anFieldTypeMap[iFieldDefnIdx] == SE_NSTRING_TYPE )
+        {
+            SE_WCHAR *pszUTF16 = (SE_WCHAR *) 
+                CPLRecodeToWChar( poField->String, CPL_ENC_UTF8, 
+                                  CPL_ENC_UTF16 );
+
+            nSDEErr = SE_stream_set_nstring( hStream, iCurColNum++,
+                                             pszUTF16 );
+            CPLFree( pszUTF16 );
+
+            if( nSDEErr != SE_SUCCESS )
+            {
+                poDS->IssueSDEError( nSDEErr, "SE_stream_set_nstring" );
+                CSLDestroy( papszInsertCols );
+                CPLFree( paiColToDefMap );
+                return OGRERR_FAILURE;
+            }
+        }
+        
         else if( poFieldDefn->GetType() == OFTString )
         {
             nSDEErr = SE_stream_set_string( hStream, iCurColNum++,
@@ -1673,7 +1695,7 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
       {
           CPLError( CE_Warning, CPLE_NotSupported, 
                     "Unsupported geometry type: %d", 
-                    nSDEGeomType );
+                    (int) nSDEGeomType );
       }
     }
 
@@ -1788,6 +1810,32 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
           }
           break;
 
+          case SE_NSTRING_TYPE:
+          {
+              SE_WCHAR * pszTempStringUTF16 = (SE_WCHAR *) 
+                  CPLMalloc ((poFieldDef->GetWidth()+1) * sizeof(SE_WCHAR ));
+
+              nSDEErr = SE_stream_get_nstring( hStream, anFieldMap[i]+1, 
+                                               pszTempStringUTF16 );
+
+              if( nSDEErr == SE_SUCCESS ) 
+              {
+                  char* pszUTF8 = CPLRecodeFromWChar((const wchar_t*)pszTempStringUTF16, CPL_ENC_UTF16, CPL_ENC_UTF8);
+
+                  poFeat->SetField( i, pszUTF8 );
+                  CPLFree( pszUTF8 );
+
+              } 
+              else if( nSDEErr != SE_NULL_VALUE )
+              {
+                  poDS->IssueSDEError( nSDEErr, "SE_stream_get_nstring" );
+                  CPLFree( pszTempStringUTF16 );
+
+                  return NULL;
+              }
+              CPLFree( pszTempStringUTF16 );
+          }
+          break;
 
 #ifdef SE_UUID_TYPE
           case SE_UUID_TYPE:
@@ -2196,8 +2244,15 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
         sColumnDef.sde_type = SE_DOUBLE_TYPE;
 
     else if( oField.GetType() == OFTString )
-        sColumnDef.sde_type = SE_STRING_TYPE;
+    {
+        const char *pszUseNSTRING = 
+            CPLGetConfigOption( "OGR_SDE_USE_NSTRING", "FALSE" );
 
+        if( bUseNSTRING || CSLTestBoolean( pszUseNSTRING ) )
+            sColumnDef.sde_type = SE_NSTRING_TYPE;
+        else
+            sColumnDef.sde_type = SE_STRING_TYPE;
+    }
     else if(    oField.GetType() == OFTDate
              || oField.GetType() == OFTTime
              || oField.GetType() == OFTDateTime
@@ -2272,6 +2327,7 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     }
 
     poFeatureDefn->AddFieldDefn( &oField );
+    anFieldTypeMap.push_back( sColumnDef.sde_type );
     
     return OGRERR_NONE;
 }
@@ -2410,7 +2466,8 @@ OGRErr OGRSDELayer::DeleteFeature( long nFID )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Layer \"%s\": Tried to delete a feature by FID, but no "
-                  "rows were deleted!" );
+                  "rows were deleted!",
+                  poFeatureDefn->GetName() );
     }
     else if( nSDEErr != SE_SUCCESS )
     {
@@ -2450,6 +2507,14 @@ int OGRSDELayer::TestCapability( const char * pszCap )
              || EQUAL(pszCap,OLCRandomWrite) )
         return bUpdateAccess;
     
+    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+    {
+        // We always treat NSTRING fields by translating to UTF8, but
+        // we don't do anything to regular string fields so this is a
+        // bit hard to answer simply.  Also, whether writes support UTF8
+        // depend on whether the field(s) were created as NSTRING fields. 
+        return TRUE;
+    }
     else 
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/segukooa/GNUmakefile b/ogr/ogrsf_frmts/segukooa/GNUmakefile
new file mode 100644
index 0000000..5138434
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrsegukooadriver.o ogrsegukooadatasource.o ogrsegukooalayer.o
+
+CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_segukooa.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/segukooa/drv_segukooa.html b/ogr/ogrsf_frmts/segukooa/drv_segukooa.html
new file mode 100644
index 0000000..f906b7a
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/drv_segukooa.html
@@ -0,0 +1,25 @@
+<html>
+<head>
+<title>SEG-P1 / UKOOA P1/90</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>SEG-P1 / UKOOA P1/90</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver reads files in SEG-P1 and UKOOA P1/90 formats. Those files are simple
+ASCII files that contain seismic shotpoints. Two layers are reported : one with
+the points, and another ones where sequential points with same line name are merged
+together in a single feature with a line geometry.<p>
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="http://www.seg.org/documents/10161/77915/seg_p1_p2_p3.pdf">Description of SEG-P1 format</a><p>
+<li> <a href="http://www.seg.org/documents/10161/77915/ukooa_p1_90.pdf">Description of UKOOA P1/90 format</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/segukooa/makefile.vc b/ogr/ogrsf_frmts/segukooa/makefile.vc
new file mode 100644
index 0000000..8776738
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrsegukooadriver.obj ogrsegukooadatasource.obj ogrsegukooalayer.obj
+EXTRAFLAGS =	-I.. -I..\..
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
new file mode 100644
index 0000000..6542518
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
@@ -0,0 +1,180 @@
+/******************************************************************************
+ * $Id: ogr_segukooa.h 23220 2011-10-11 21:50:55Z 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>
+ *
+ * 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, DAMSEGUKOOAS 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_SEGUKOOA_H_INCLUDED
+#define _OGR_SEGUKOOA_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+/************************************************************************/
+/*                        OGRSEGUKOOABaseLayer                          */
+/************************************************************************/
+
+class OGRSEGUKOOABaseLayer : public OGRLayer
+{
+  protected:
+    OGRFeatureDefn*    poFeatureDefn;
+    int                bEOF;
+    int                nNextFID;
+
+    virtual OGRFeature *       GetNextRawFeature() = 0;
+
+  public:
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    virtual int                 TestCapability( const char * ) { return FALSE; }
+};
+
+/************************************************************************/
+/*                          OGRUKOOAP190Layer                           */
+/************************************************************************/
+
+class OGRUKOOAP190Layer : public OGRSEGUKOOABaseLayer
+{
+    OGRSpatialReference* poSRS;
+
+    VSILFILE*          fp;
+
+    int                bUseEastingNorthingAsGeometry;
+    int                nYear;
+    void               ParseHeaders();
+
+  protected:
+    OGRFeature *       GetNextRawFeature();
+
+  public:
+                        OGRUKOOAP190Layer(const char* pszFilename,
+                                         VSILFILE* fp);
+                        ~OGRUKOOAP190Layer();
+
+
+    virtual void                ResetReading();
+
+    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
+
+};
+
+/************************************************************************/
+/*                        OGRSEGUKOOALineLayer                          */
+/************************************************************************/
+
+class OGRSEGUKOOALineLayer : public OGRSEGUKOOABaseLayer
+{
+    OGRLayer          *poBaseLayer;
+    OGRFeature        *poNextBaseFeature;
+
+  protected:
+    OGRFeature *       GetNextRawFeature();
+
+  public:
+                        OGRSEGUKOOALineLayer(const char* pszFilename,
+                                             OGRLayer *poBaseLayer);
+                        ~OGRSEGUKOOALineLayer();
+
+    virtual void                ResetReading();
+
+    virtual OGRSpatialReference *GetSpatialRef() { return poBaseLayer->GetSpatialRef(); }
+};
+
+
+/************************************************************************/
+/*                         OGRSEGP1Layer                                */
+/************************************************************************/
+
+class OGRSEGP1Layer: public OGRSEGUKOOABaseLayer
+{
+    OGRSpatialReference* poSRS;
+
+    VSILFILE*          fp;
+    int                nLatitudeCol;
+
+    int                bUseEastingNorthingAsGeometry;
+
+  protected:
+    OGRFeature *       GetNextRawFeature();
+
+  public:
+                        OGRSEGP1Layer(const char* pszFilename,
+                                      VSILFILE* fp,
+                                      int nLatitudeCol);
+                        ~OGRSEGP1Layer();
+
+    virtual void                ResetReading();
+
+    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
+
+public:
+    static char* ExpandTabs(const char* pszLine);
+    static int   DetectLatitudeColumn(const char* pzLine);
+};
+
+/************************************************************************/
+/*                         OGRSEGUKOOADataSource                        */
+/************************************************************************/
+
+class OGRSEGUKOOADataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+  public:
+                        OGRSEGUKOOADataSource();
+                        ~OGRSEGUKOOADataSource();
+
+    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 * );
+};
+
+/************************************************************************/
+/*                          OGRSEGUKOOADriver                           */
+/************************************************************************/
+
+class OGRSEGUKOOADriver : public OGRSFDriver
+{
+  public:
+                ~OGRSEGUKOOADriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual int                 TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_SEGUKOOA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
new file mode 100644
index 0000000..a419035
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
@@ -0,0 +1,199 @@
+/******************************************************************************
+ * $Id: ogrsegukooadatasource.cpp 23259 2011-10-20 21:11:42Z 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>
+ *
+ * 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, DAMSEGUKOOAS 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_segukooa.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogrsegukooadatasource.cpp 23259 2011-10-20 21:11:42Z rouault $");
+
+/************************************************************************/
+/*                        OGRSEGUKOOADataSource()                       */
+/************************************************************************/
+
+OGRSEGUKOOADataSource::OGRSEGUKOOADataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+}
+
+/************************************************************************/
+/*                       ~OGRSEGUKOOADataSource()                       */
+/************************************************************************/
+
+OGRSEGUKOOADataSource::~OGRSEGUKOOADataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSEGUKOOADataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRSEGUKOOADataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRSEGUKOOADataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (bUpdateIn)
+    {
+        return FALSE;
+    }
+
+    pszName = CPLStrdup( pszFilename );
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+    if (fp == NULL)
+        return FALSE;
+
+    const char* pszLine;
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    pszLine = CPLReadLine2L(fp,81,NULL);
+    CPLPopErrorHandler();
+    CPLErrorReset();
+
+    /* Both UKOOA P1/90 and SEG-P1 begins by a H character */
+    if (pszLine == NULL || pszLine[0] != 'H')
+    {
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+
+// --------------------------------------------------------------------
+//      Does this appear to be a UKOOA P1/90 file?
+// --------------------------------------------------------------------
+
+    if (strncmp(pszLine, "H0100 ", 6) == 0)
+    {
+        VSIFSeekL( fp, 0, SEEK_SET );
+
+        VSILFILE* fp2 = VSIFOpenL(pszFilename, "rb");
+        if (fp2 == NULL)
+        {
+            VSIFCloseL(fp);
+            return FALSE;
+        }
+
+        nLayers = 2;
+        papoLayers = (OGRLayer**) CPLMalloc(2 * sizeof(OGRLayer*));
+        papoLayers[0] = new OGRUKOOAP190Layer(pszName, fp);
+        papoLayers[1] = new OGRSEGUKOOALineLayer(pszName,
+                                         new OGRUKOOAP190Layer(pszName, fp2));
+
+        return TRUE;
+    }
+
+// --------------------------------------------------------------------
+//      Does this appear to be a SEG-P1 file?
+// --------------------------------------------------------------------
+
+    /* Check first 20 header lines, and fetch the first point */
+    for(int iLine = 0; iLine < 21; iLine ++)
+    {
+        const char* szPtr = pszLine;
+        for(;*szPtr != '\0';szPtr++)
+        {
+            if (*szPtr != 9 && *szPtr < 32)
+            {
+                VSIFCloseL(fp);
+                return FALSE;
+            }
+        }
+
+        if (iLine == 20)
+            break;
+
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        pszLine = CPLReadLine2L(fp,81,NULL);
+        CPLPopErrorHandler();
+        CPLErrorReset();
+        if (pszLine == NULL)
+        {
+            VSIFCloseL(fp);
+            return FALSE;
+        }
+    }
+
+    char* pszExpandedLine = OGRSEGP1Layer::ExpandTabs(pszLine);
+    int nLatitudeCol = OGRSEGP1Layer::DetectLatitudeColumn(pszExpandedLine);
+    CPLFree(pszExpandedLine);
+
+    if (nLatitudeCol > 0)
+    {
+        VSIFSeekL( fp, 0, SEEK_SET );
+
+        VSILFILE* fp2 = VSIFOpenL(pszFilename, "rb");
+        if (fp2 == NULL)
+        {
+            VSIFCloseL(fp);
+            return FALSE;
+        }
+
+        nLayers = 2;
+        papoLayers = (OGRLayer**) CPLMalloc(2 * sizeof(OGRLayer*));
+        papoLayers[0] = new OGRSEGP1Layer(pszName, fp, nLatitudeCol);
+        papoLayers[1] = new OGRSEGUKOOALineLayer(pszName,
+                                         new OGRSEGP1Layer(pszName, fp2,
+                                                           nLatitudeCol));
+
+        return TRUE;
+    }
+
+    VSIFCloseL(fp);
+    return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
new file mode 100644
index 0000000..b0f3cd9
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * $Id: ogrsegukooadriver.cpp 23220 2011-10-11 21:50:55Z 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>
+ *
+ * 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, DAMSEGUKOOAS 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_segukooa.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrsegukooadriver.cpp 23220 2011-10-11 21:50:55Z rouault $");
+
+extern "C" void RegisterOGRSEGUKOOA();
+
+/************************************************************************/
+/*                         ~OGRSEGUKOOADriver()                         */
+/************************************************************************/
+
+OGRSEGUKOOADriver::~OGRSEGUKOOADriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRSEGUKOOADriver::GetName()
+
+{
+    return "SEGUKOOA";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRSEGUKOOADriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRSEGUKOOADataSource   *poDS = new OGRSEGUKOOADataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSEGUKOOADriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRSEGUKOOA()                           */
+/************************************************************************/
+
+void RegisterOGRSEGUKOOA()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRSEGUKOOADriver );
+}
+
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
new file mode 100644
index 0000000..7a4dedb
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
@@ -0,0 +1,818 @@
+/******************************************************************************
+ * $Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z 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>
+ *
+ * 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, DAMSEGUKOOAS 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_segukooa.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_p.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: ogrsegukooalayer.cpp 23222 2011-10-11 22:29:08Z rouault $");
+
+/************************************************************************/
+/*                            ExtractField()                            */
+/************************************************************************/
+
+static void ExtractField(char* szField, const char* pszLine, int nOffset, int nLen)
+{
+    memcpy(szField, pszLine + nOffset, nLen);
+    szField[nLen] = '\0';
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRSEGUKOOABaseLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    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;
+    }
+}
+
+/************************************************************************/
+/*                         OGRUKOOAP190Layer()                          */
+/************************************************************************/
+
+typedef struct
+{
+    const char*     pszName;
+    OGRFieldType    eType;
+} FieldDesc;
+
+static const FieldDesc UKOOAP190Fields[] =
+{
+    { "LINENAME", OFTString },
+    { "VESSEL_ID", OFTString },
+    { "SOURCE_ID", OFTString },
+    { "OTHER_ID", OFTString },
+    { "POINTNUMBER", OFTInteger },
+    { "LONGITUDE", OFTReal },
+    { "LATITUDE", OFTReal },
+    { "EASTING", OFTReal },
+    { "NORTHING", OFTReal },
+    { "DEPTH", OFTReal },
+    { "DAYOFYEAR", OFTInteger },
+    { "TIME", OFTTime },
+    { "DATETIME", OFTDateTime }
+};
+
+#define FIELD_LINENAME      0
+#define FIELD_VESSEL_ID     1
+#define FIELD_SOURCE_ID     2
+#define FIELD_OTHER_ID      3
+#define FIELD_POINTNUMBER   4
+#define FIELD_LONGITUDE     5
+#define FIELD_LATITUDE      6
+#define FIELD_EASTING       7
+#define FIELD_NORTHING      8
+#define FIELD_DEPTH         9
+#define FIELD_DAYOFYEAR     10
+#define FIELD_TIME          11
+#define FIELD_DATETIME      12
+
+OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
+                                      VSILFILE* fp )
+
+{
+    this->fp = fp;
+    nNextFID = 0;
+    bEOF = FALSE;
+    poSRS = NULL;
+    nYear = 0;
+
+    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbPoint );
+
+    for(int i=0;i<(int)(sizeof(UKOOAP190Fields)/sizeof(UKOOAP190Fields[0]));i++)
+    {
+        OGRFieldDefn    oField( UKOOAP190Fields[i].pszName,
+                                UKOOAP190Fields[i].eType );
+        poFeatureDefn->AddFieldDefn( &oField );
+    }
+
+    bUseEastingNorthingAsGeometry =
+        CSLTestBoolean(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
+
+    ParseHeaders();
+}
+
+/************************************************************************/
+/*                         ~OGRUKOOAP190Layer()                         */
+/************************************************************************/
+
+OGRUKOOAP190Layer::~OGRUKOOAP190Layer()
+
+{
+    poFeatureDefn->Release();
+
+    VSIFCloseL( fp );
+
+    if (poSRS)
+        poSRS->Release();
+}
+
+/************************************************************************/
+/*                          ParseHeaders()                              */
+/************************************************************************/
+
+void OGRUKOOAP190Layer::ParseHeaders()
+{
+    while(TRUE)
+    {
+        const char* pszLine = CPLReadLine2L(fp,81,NULL);
+        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
+        {
+            break;
+        }
+
+        int nLineLen = strlen(pszLine);
+        while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
+        {
+            ((char*)pszLine)[nLineLen-1] = '\0';
+            nLineLen --;
+        }
+
+        if (pszLine[0] != 'H')
+            break;
+
+        if (nLineLen < 33)
+            continue;
+
+        if (!bUseEastingNorthingAsGeometry &&
+            strncmp(pszLine, "H1500", 5) == 0 && poSRS == NULL)
+        {
+            if (strncmp(pszLine + 33 - 1, "WGS84", 5) == 0 ||
+                strncmp(pszLine + 33 - 1, "WGS-84", 6) == 0)
+            {
+                poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
+            }
+            else if (strncmp(pszLine + 33 - 1, "WGS72", 5) == 0)
+            {
+                poSRS = new OGRSpatialReference();
+                poSRS->SetFromUserInput("WGS72");
+            }
+        }
+        else if (!bUseEastingNorthingAsGeometry &&
+                 strncmp(pszLine, "H1501", 5) == 0 && poSRS != NULL &&
+                 nLineLen >= 32 + 6 * 6 + 10)
+        {
+            char aszParams[6][6+1];
+            char szZ[10+1];
+            int i;
+            for(i=0;i<6;i++)
+            {
+                ExtractField(aszParams[i], pszLine, 33 - 1 + i * 6, 6);
+            }
+            ExtractField(szZ, pszLine, 33 - 1 + 6 * 6, 10);
+            poSRS->SetTOWGS84(atof(aszParams[0]),
+                              atof(aszParams[1]),
+                              atof(aszParams[2]),
+                              atof(aszParams[3]),
+                              atof(aszParams[4]),
+                              atof(aszParams[5]),
+                              atof(szZ));
+        }
+        else if (strncmp(pszLine, "H0200", 5) == 0)
+        {
+            char** papszTokens = CSLTokenizeString(pszLine + 33 - 1);
+            for(int i = 0; papszTokens[i] != NULL; i++)
+            {
+                if (strlen(papszTokens[i]) == 4)
+                {
+                    int nVal = atoi(papszTokens[i]);
+                    if (nVal >= 1900)
+                    {
+                        if (nYear != 0 && nYear != nVal)
+                        {
+                            CPLDebug("SEGUKOOA",
+                                     "Several years found in H0200. Ignoring them!");
+                            nYear = 0;
+                            break;
+                        }
+                        nYear = nVal;
+                    }
+                }
+            }
+            CSLDestroy(papszTokens);
+        }
+    }
+    VSIFSeekL( fp, 0, SEEK_SET );
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRUKOOAP190Layer::ResetReading()
+
+{
+    nNextFID = 0;
+    bEOF = FALSE;
+    VSIFSeekL( fp, 0, SEEK_SET );
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
+{
+    if (bEOF)
+        return NULL;
+
+    const char* pszLine;
+
+    while(TRUE)
+    {
+        pszLine = CPLReadLine2L(fp,81,NULL);
+        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
+        {
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        int nLineLen = strlen(pszLine);
+        while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
+        {
+            ((char*)pszLine)[nLineLen-1] = '\0';
+            nLineLen --;
+        }
+
+        if (pszLine[0] == 'H' || nLineLen < 46)
+            continue;
+
+        OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+        poFeature->SetFID(nNextFID ++);
+
+        char szLineName[12 + 1];
+        ExtractField(szLineName, pszLine, 2-1, 12);
+        int i = 11;
+        while (i >= 0)
+        {
+            if (szLineName[i] == ' ')
+                szLineName[i] = '\0';
+            else
+                break;
+            i --;
+        }
+        poFeature->SetField(FIELD_LINENAME, szLineName);
+
+        char szVesselId[1+1];
+        szVesselId[0] = pszLine[17-1];
+        if (szVesselId[0] != ' ')
+        {
+            szVesselId[1] = '\0';
+            poFeature->SetField(FIELD_VESSEL_ID, szVesselId);
+        }
+
+        char szSourceId[1+1];
+        szSourceId[0] = pszLine[18-1];
+        if (szSourceId[0] != ' ')
+        {
+            szSourceId[1] = '\0';
+            poFeature->SetField(FIELD_SOURCE_ID, szSourceId);
+        }
+
+        char szOtherId[1+1];
+        szOtherId[0] = pszLine[19-1];
+        if (szOtherId[0] != ' ')
+        {
+            szOtherId[1] = '\0';
+            poFeature->SetField(FIELD_OTHER_ID, szOtherId);
+        }
+
+        char szPointNumber[6+1];
+        ExtractField(szPointNumber, pszLine, 20-1, 6);
+        poFeature->SetField(4, atoi(szPointNumber));
+
+        char szDeg[3+1];
+        char szMin[2+1];
+        char szSec[5+1];
+
+        ExtractField(szDeg, pszLine, 26-1, 2);
+        ExtractField(szMin, pszLine, 26+2-1, 2);
+        ExtractField(szSec, pszLine, 26+2+2-1, 5);
+        double dfLat = atoi(szDeg) + atoi(szMin) / 60.0 + atof(szSec) / 3600.0;
+        if (pszLine[26+2+2+5-1] == 'S')
+            dfLat = -dfLat;
+        poFeature->SetField(FIELD_LATITUDE, dfLat);
+
+        ExtractField(szDeg, pszLine, 36-1, 3);
+        ExtractField(szMin, pszLine, 36+3-1, 2);
+        ExtractField(szSec, pszLine, 36+3+2-1, 5);
+        double dfLon = atoi(szDeg) + atoi(szMin) / 60.0 + atof(szSec) / 3600.0;
+        if (pszLine[36+3+2+5-1] == 'W')
+            dfLon = -dfLon;
+        poFeature->SetField(FIELD_LONGITUDE, dfLon);
+
+        OGRGeometry* poGeom = NULL;
+        if (!bUseEastingNorthingAsGeometry)
+            poGeom = new OGRPoint(dfLon, dfLat);
+
+        if (nLineLen >= 64)
+        {
+            char szEasting[9+1];
+            ExtractField(szEasting, pszLine, 47-1, 9);
+            double dfEasting = atof(szEasting);
+            poFeature->SetField(FIELD_EASTING, dfEasting);
+
+            char szNorthing[9+1];
+            ExtractField(szNorthing, pszLine, 56-1, 9);
+            double dfNorthing = atof(szNorthing);
+            poFeature->SetField(FIELD_NORTHING, dfNorthing);
+
+            if (bUseEastingNorthingAsGeometry)
+                poGeom = new OGRPoint(dfEasting, dfNorthing);
+        }
+
+        if (poGeom)
+        {
+            if (poSRS)
+                poGeom->assignSpatialReference(poSRS);
+            poFeature->SetGeometryDirectly(poGeom);
+        }
+
+        if (nLineLen >= 70)
+        {
+            char szDepth[6+1];
+            ExtractField(szDepth, pszLine, 65-1, 6);
+            double dfDepth = atof(szDepth);
+            poFeature->SetField(FIELD_DEPTH, dfDepth);
+        }
+
+        int nDayOfYear = 0;
+        if (nLineLen >= 73)
+        {
+            char szDayOfYear[3+1];
+            ExtractField(szDayOfYear, pszLine, 71-1, 3);
+            nDayOfYear = atoi(szDayOfYear);
+            poFeature->SetField(FIELD_DAYOFYEAR, nDayOfYear);
+        }
+
+        if (nLineLen >= 79)
+        {
+            char szH[2+1], szM[2+1], szS[2+1];
+            ExtractField(szH, pszLine, 74-1, 2);
+            ExtractField(szM, pszLine, 74-1+2, 2);
+            ExtractField(szS, pszLine, 74-1+2+2, 2);
+            poFeature->SetField(FIELD_TIME, 0, 0, 0, atoi(szH), atoi(szM), atoi(szS) );
+
+            if (nYear != 0)
+            {
+                #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+                static const int mon_lengths[2][12] = {
+                    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+                    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+                } ;
+                int bIsLeap = isleap(nYear);
+                int nMonth = 0;
+                int nDays = 0;
+                if ((bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 366) ||
+                    (!bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 365))
+                {
+                    while(nDayOfYear > nDays + mon_lengths[bIsLeap][nMonth])
+                    {
+                        nDays += mon_lengths[bIsLeap][nMonth];
+                        nMonth ++;
+                    }
+                    int nDayOfMonth = nDayOfYear - nDays;
+                    nMonth ++;
+
+                    poFeature->SetField(FIELD_DATETIME, nYear, nMonth, nDayOfMonth,
+                                        atoi(szH), atoi(szM), atoi(szS) );
+                }
+
+            }
+        }
+
+        return poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           OGRSEGP1Layer()                            */
+/************************************************************************/
+
+static const FieldDesc SEGP1Fields[] =
+{
+    { "LINENAME", OFTString },
+    { "POINTNUMBER", OFTInteger },
+    { "RESHOOTCODE", OFTString },
+    { "LONGITUDE", OFTReal },
+    { "LATITUDE", OFTReal },
+    { "EASTING", OFTReal },
+    { "NORTHING", OFTReal },
+    { "DEPTH", OFTReal },
+#if 0
+    { "YEAR", OFTInteger },
+    { "DAYOFYEAR", OFTInteger },
+    { "TIME", OFTTime },
+    { "DATETIME", OFTDateTime }
+#endif
+};
+
+#define SEGP1_FIELD_LINENAME      0
+#define SEGP1_FIELD_POINTNUMBER   1
+#define SEGP1_FIELD_RESHOOTCODE   2
+#define SEGP1_FIELD_LONGITUDE     3
+#define SEGP1_FIELD_LATITUDE      4
+#define SEGP1_FIELD_EASTING       5
+#define SEGP1_FIELD_NORTHING      6
+#define SEGP1_FIELD_DEPTH         7
+#define SEGP1_FIELD_DAYOFYEAR     8
+#define SEGP1_FIELD_TIME          9
+#define SEGP1_FIELD_DATETIME      10
+
+OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
+                              VSILFILE* fp,
+                              int nLatitudeCol )
+
+{
+    this->fp = fp;
+    this->nLatitudeCol = nLatitudeCol;
+    nNextFID = 0;
+    bEOF = FALSE;
+    poSRS = NULL;
+
+    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbPoint );
+
+    for(int i=0;i<(int)(sizeof(SEGP1Fields)/sizeof(SEGP1Fields[0]));i++)
+    {
+        OGRFieldDefn    oField( SEGP1Fields[i].pszName,
+                                SEGP1Fields[i].eType );
+        poFeatureDefn->AddFieldDefn( &oField );
+    }
+
+    bUseEastingNorthingAsGeometry =
+        CSLTestBoolean(CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO"));
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                            ~OGRSEGP1Layer()                          */
+/************************************************************************/
+
+OGRSEGP1Layer::~OGRSEGP1Layer()
+
+{
+    poFeatureDefn->Release();
+
+    VSIFCloseL( fp );
+
+    if (poSRS)
+        poSRS->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRSEGP1Layer::ResetReading()
+
+{
+    nNextFID = 0;
+    bEOF = FALSE;
+    VSIFSeekL( fp, 0, SEEK_SET );
+
+    /* Skip first 20 header lines */
+    const char* pszLine = NULL;
+    for(int i=0; i<20;i++)
+    {
+        pszLine = CPLReadLine2L(fp,81,NULL);
+        if (pszLine == NULL)
+        {
+            bEOF = TRUE;
+            break;
+        }
+    }
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
+{
+    if (bEOF)
+        return NULL;
+
+    const char* pszLine = NULL;
+    while(TRUE)
+    {
+        pszLine = CPLReadLine2L(fp,81,NULL);
+        if (pszLine == NULL || EQUALN(pszLine, "EOF", 3))
+        {
+            bEOF = TRUE;
+            return NULL;
+        }
+
+        int nLineLen = strlen(pszLine);
+        while(nLineLen > 0 && pszLine[nLineLen-1] == ' ')
+        {
+            ((char*)pszLine)[nLineLen-1] = '\0';
+            nLineLen --;
+        }
+
+        char* pszExpandedLine = ExpandTabs(pszLine);
+        pszLine = pszExpandedLine;
+        nLineLen = strlen(pszLine);
+
+        OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+        poFeature->SetFID(nNextFID ++);
+
+        OGRGeometry* poGeom = NULL;
+
+        if (nLatitudeCol-1 + 19 <= nLineLen)
+        {
+            char szDeg[3+1];
+            char szMin[2+1];
+            char szSec[4+1];
+
+            ExtractField(szDeg, pszLine, nLatitudeCol-1, 2);
+            ExtractField(szMin, pszLine, nLatitudeCol+2-1, 2);
+            ExtractField(szSec, pszLine, nLatitudeCol+2+2-1, 4);
+            double dfLat = atoi(szDeg) + atoi(szMin) / 60.0 + atoi(szSec) / 100.0 / 3600.0;
+            if (pszLine[nLatitudeCol+2+2+4-1] == 'S')
+                dfLat = -dfLat;
+            poFeature->SetField(SEGP1_FIELD_LATITUDE, dfLat);
+
+            ExtractField(szDeg, pszLine, nLatitudeCol+9-1, 3);
+            ExtractField(szMin, pszLine, nLatitudeCol+9+3-1, 2);
+            ExtractField(szSec, pszLine, nLatitudeCol+9+3+2-1, 4);
+            double dfLon = atoi(szDeg) + atoi(szMin) / 60.0 + atoi(szSec) / 100.0 / 3600.0;
+            if (pszLine[nLatitudeCol+9+3+2+4-1] == 'W')
+                dfLon = -dfLon;
+            poFeature->SetField(SEGP1_FIELD_LONGITUDE, dfLon);
+
+            if (!bUseEastingNorthingAsGeometry)
+                poGeom = new OGRPoint(dfLon, dfLat);
+        }
+
+        /* Normal layout -> extract other fields */
+        if (nLatitudeCol == 27)
+        {
+            char szLineName[16 + 1];
+            ExtractField(szLineName, pszLine, 2-1, 16);
+            int i = 15;
+            while (i >= 0)
+            {
+                if (szLineName[i] == ' ')
+                    szLineName[i] = '\0';
+                else
+                    break;
+                i --;
+            }
+            poFeature->SetField(SEGP1_FIELD_LINENAME, szLineName);
+
+            char szPointNumber[8+1];
+            ExtractField(szPointNumber, pszLine, 18-1, 8);
+            poFeature->SetField(SEGP1_FIELD_POINTNUMBER, atoi(szPointNumber));
+
+            char szReshootCode[1+1];
+            ExtractField(szReshootCode, pszLine, 26-1, 1);
+            poFeature->SetField(SEGP1_FIELD_RESHOOTCODE, szReshootCode);
+
+            if (nLineLen >= 61)
+            {
+                char szEasting[8+1];
+                ExtractField(szEasting, pszLine, 46-1, 8);
+                double dfEasting = atof(szEasting);
+                poFeature->SetField(SEGP1_FIELD_EASTING, dfEasting);
+
+                char szNorthing[8+1];
+                ExtractField(szNorthing, pszLine, 54-1, 8);
+                double dfNorthing = atof(szNorthing);
+                poFeature->SetField(SEGP1_FIELD_NORTHING, dfNorthing);
+
+                if (bUseEastingNorthingAsGeometry)
+                    poGeom = new OGRPoint(dfEasting, dfNorthing);
+            }
+
+            if (nLineLen >= 66)
+            {
+                char szDepth[5+1];
+                ExtractField(szDepth, pszLine, 62-1, 5);
+                double dfDepth = atof(szDepth);
+                poFeature->SetField(SEGP1_FIELD_DEPTH, dfDepth);
+            }
+        }
+
+        if (poGeom)
+        {
+            if (poSRS)
+                poGeom->assignSpatialReference(poSRS);
+            poFeature->SetGeometryDirectly(poGeom);
+        }
+
+        CPLFree(pszExpandedLine);
+
+        return poFeature;
+    }
+}
+
+/************************************************************************/
+/*                           ExpandTabs()                               */
+/************************************************************************/
+
+char* OGRSEGP1Layer::ExpandTabs(const char* pszLine)
+{
+    char* pszExpandedLine = (char*)CPLMalloc(strlen(pszLine) * 8 + 1);
+    int j = 0;
+    for(int i=0; pszLine[i] != '\0'; i++)
+    {
+        /* A tab must be space-expanded to reach the next column number */
+        /* which is a multiple of 8 */
+        if (pszLine[i] == 9)
+        {
+            do
+            {
+                pszExpandedLine[j ++] = ' ';
+            } while ((j % 8) != 0);
+        }
+        else
+            pszExpandedLine[j ++] = pszLine[i];
+    }
+    pszExpandedLine[j] = '\0';
+
+    return pszExpandedLine;
+}
+
+/************************************************************************/
+/*                        DetectLatitudeColumn()                        */
+/************************************************************************/
+
+/* Some SEG-P1 files have unusual offsets for latitude/longitude, so */
+/* we try our best to identify it even in case of non-standard layout */
+/* Return non-0 if detection is successfull (column number starts at 1) */
+
+int OGRSEGP1Layer::DetectLatitudeColumn(const char* pszLine)
+{
+    int nLen = strlen(pszLine);
+    if (nLen >= 45 && pszLine[0] == ' ' &&
+        (pszLine[35-1] == 'N' || pszLine[35-1] == 'S') &&
+        (pszLine[45-1] == 'E' || pszLine[45-1] == 'W'))
+        return 27;
+
+    for(int i=8;i<nLen-10;i++)
+    {
+        if ((pszLine[i] == 'N' || pszLine[i] == 'S') &&
+            (pszLine[i+10] == 'E' || pszLine[i+10] == 'W'))
+            return i - 8 + 1;
+    }
+
+    return 0;
+}
+
+
+/************************************************************************/
+/*                        OGRSEGUKOOALineLayer()                        */
+/************************************************************************/
+
+OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
+                                           OGRLayer *poBaseLayer)
+{
+    nNextFID = 0;
+    bEOF = FALSE;
+
+    poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_lines",
+                                                   CPLGetBasename(pszFilename)) );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbLineString );
+
+    OGRFieldDefn    oField( "LINENAME", OFTString );
+    poFeatureDefn->AddFieldDefn( &oField );
+
+    this->poBaseLayer = poBaseLayer;
+    poNextBaseFeature = NULL;
+}
+
+/************************************************************************/
+/*                       ~OGRSEGUKOOALineLayer()                        */
+/************************************************************************/
+
+OGRSEGUKOOALineLayer::~OGRSEGUKOOALineLayer()
+{
+    delete poNextBaseFeature;
+    delete poBaseLayer;
+
+    poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRSEGUKOOALineLayer::ResetReading()
+
+{
+    nNextFID = 0;
+    bEOF = FALSE;
+    delete poNextBaseFeature;
+    poNextBaseFeature = NULL;
+    poBaseLayer->ResetReading();
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
+{
+    if (bEOF)
+        return NULL;
+
+    /* Merge points of base layer that have same value for attribute(0) */
+    /* into a single linestring */
+
+    OGRFeature* poFeature = NULL;
+    OGRLineString* poLS = NULL;
+
+    if (poNextBaseFeature == NULL)
+        poNextBaseFeature = poBaseLayer->GetNextFeature();
+
+    while(poNextBaseFeature != NULL)
+    {
+        if (poNextBaseFeature->IsFieldSet(0) &&
+            poNextBaseFeature->GetFieldAsString(0)[0] != '\0')
+        {
+            if (poFeature != NULL &&
+                strcmp(poFeature->GetFieldAsString(0),
+                    poNextBaseFeature->GetFieldAsString(0)) != 0)
+            {
+                return poFeature;
+            }
+
+            OGRPoint* poPoint =
+                (OGRPoint*) poNextBaseFeature->GetGeometryRef();
+            if (poPoint != NULL)
+            {
+                if (poFeature == NULL)
+                {
+                    poFeature = new OGRFeature(poFeatureDefn);
+                    poFeature->SetFID(nNextFID ++);
+                    poFeature->SetField(0,
+                        poNextBaseFeature->GetFieldAsString(0));
+                    poLS = new OGRLineString();
+                    if (poBaseLayer->GetSpatialRef())
+                        poLS->assignSpatialReference(
+                                    poBaseLayer->GetSpatialRef());
+                    poFeature->SetGeometryDirectly(poLS);
+                }
+
+                poLS->addPoint(poPoint);
+            }
+        }
+
+        delete poNextBaseFeature;
+        poNextBaseFeature = poBaseLayer->GetNextFeature();
+    }
+
+    bEOF = TRUE;
+    return poFeature;
+}
diff --git a/ogr/ogrsf_frmts/segukooa/segukooa.txt b/ogr/ogrsf_frmts/segukooa/segukooa.txt
new file mode 100644
index 0000000..ad1fa77
--- /dev/null
+++ b/ogr/ogrsf_frmts/segukooa/segukooa.txt
@@ -0,0 +1,13 @@
+http://www.litho.ucalgary.ca/geometry/abitibi/seg401.tr
+http://www.litho.ucalgary.ca/geometry/Alberta/l1.seg
+http://www.litho.ucalgary.ca/geometry/Alberta/l11.tr
+http://www.litho.ucalgary.ca/geometry/Alberta/SALT21.segp1
+http://quashnet.er.usgs.gov/data/pubs/of99-037/of99-37_cd1/nav/shotnav/dumpsite.seg
+http://quashnet.er.usgs.gov/data/pubs/of99-037/of99-37_cd1/nav/shotnav/mosaic.seg
+http://pubs.usgs.gov/of/2000/ofr-00-0286/NPRANAV.SEG
+
+http://www.polarhovercraft.no/uploads/Main/Yermak2010_1.UKOOA.dat
+http://cotuit.er.usgs.gov/Data/1974-019-FA/LN/001/74019nav.txt
+
+http://www.seg.org/documents/10161/77915/seg_p1_p2_p3.pdf
+http://www.polarhovercraft.no/uploads/Main/ukooa_p1_90.pdf
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/segy/GNUmakefile b/ogr/ogrsf_frmts/segy/GNUmakefile
new file mode 100644
index 0000000..f457ee7
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrsegydriver.o ogrsegydatasource.o ogrsegylayer.o
+
+CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_segy.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/segy/drv_segy.html b/ogr/ogrsf_frmts/segy/drv_segy.html
new file mode 100644
index 0000000..2b5a18f
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/drv_segy.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+<title>SEG-Y / SEGY</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>SEG-Y / SEGY</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver reads files in SEG-Y format. Those files are binary files that contain single-line seismic digital data.
+The driver will report the attributes of the trace header (in their raw form, see the SEG-Y specification for more
+information), and use the receiver group coordinates as geometry. The sample values are also reported.<p>
+
+A layer "{basefilename}_header" is also created and contains a single feature with the content of the text and binary file
+headers.<p>
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="http://www.seg.org/documents/10161/77915/seg_y_rev1.pdf">Description of SEG-Y format Rev1</a><p>
+<li> <a href="http://en.wikipedia.org/wiki/SEG_Y">Wikipedia page about SEG-Y format</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/segy/makefile.vc b/ogr/ogrsf_frmts/segy/makefile.vc
new file mode 100644
index 0000000..9162220
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrsegydriver.obj ogrsegydatasource.obj ogrsegylayer.obj
+EXTRAFLAGS =	-I.. -I..\..
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/segy/ogr_segy.h b/ogr/ogrsf_frmts/segy/ogr_segy.h
new file mode 100644
index 0000000..d7fb72c
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/ogr_segy.h
@@ -0,0 +1,179 @@
+/******************************************************************************
+ * $Id: ogr_segy.h 23268 2011-10-22 09:50:46Z 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>
+ *
+ * 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, DAMSEGYS 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_SEGY_H_INCLUDED
+#define _OGR_SEGY_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+GInt16 SEGYReadMSBInt16(const GByte* pabyVal);
+GInt32 SEGYReadMSBInt32(const GByte* pabyVal);
+
+typedef struct
+{
+    int nJobIdNumber;
+    int nLineNumber;
+    int nReelNumber;
+    int nDataTracesPerEnsemble;
+    int nAuxTracesPerEnsemble;
+    int nSampleInterval;
+    int nSampleIntervalOriginal;
+    int nSamplesPerDataTrace;
+    int nSamplesPerDataTraceOriginal;
+    int nDataSampleType;
+    int nEnsembleFold;
+    int nTraceSortingCode;
+    int nVerticalSumCode;
+    int nSweepFrequencyAtStart;
+    int nSweepFrequencyAtEnd;
+    int nSweepLength;
+    int nSweepType;
+    int nTraceNumberOfSweepChannel;
+    int nSweepTraceTaperLengthAtStart;
+    int nSweepTraceTaperLengthAtEnd;
+    int nTaperType;
+    int nCorrelated;
+    int nBinaryGainRecovered;
+    int nAmplitudeRecoveryMethod;
+    int nMeasurementSystem;
+    int nImpulseSignalPolarity;
+    int nVibratoryPolaryCode;
+    int nSEGYRevisionNumber;
+    double dfSEGYRevisionNumber;
+    int nFixedLengthTraceFlag;
+    int nNumberOfExtendedTextualFileHeader;
+} SEGYBinaryFileHeader;
+
+/************************************************************************/
+/*                          OGRSEGYLayer                                */
+/************************************************************************/
+
+class OGRSEGYLayer: public OGRLayer
+{
+    OGRSpatialReference* poSRS;
+    OGRFeatureDefn*    poFeatureDefn;
+    int                bEOF;
+    int                nNextFID;
+    VSILFILE*          fp;
+
+    SEGYBinaryFileHeader sBFH;
+    int                nDataSize;
+
+    OGRFeature *       GetNextRawFeature();
+
+  public:
+                        OGRSEGYLayer(const char* pszFilename,
+                                     VSILFILE* fp,
+                                     SEGYBinaryFileHeader* psBFH);
+                        ~OGRSEGYLayer();
+
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual void                ResetReading();
+
+    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
+
+    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    virtual int                 TestCapability( const char * ) { return FALSE; }
+};
+
+/************************************************************************/
+/*                        OGRSEGYHeaderLayer                            */
+/************************************************************************/
+
+class OGRSEGYHeaderLayer: public OGRLayer
+{
+    OGRFeatureDefn*    poFeatureDefn;
+    int                bEOF;
+
+    SEGYBinaryFileHeader sBFH;
+    char*                pszHeaderText;
+
+    OGRFeature *       GetNextRawFeature();
+
+  public:
+                        OGRSEGYHeaderLayer(const char* pszLayerName,
+                                           SEGYBinaryFileHeader* psBFH,
+                                           char* pszHeaderText);
+                        ~OGRSEGYHeaderLayer();
+
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual void                ResetReading();
+
+    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
+
+    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+
+    virtual int                 TestCapability( const char * ) { return FALSE; }
+};
+
+/************************************************************************/
+/*                          OGRSEGYDataSource                           */
+/************************************************************************/
+
+class OGRSEGYDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+  public:
+                        OGRSEGYDataSource();
+                        ~OGRSEGYDataSource();
+
+    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 * );
+};
+
+/************************************************************************/
+/*                            OGRSEGYDriver                             */
+/************************************************************************/
+
+class OGRSEGYDriver : public OGRSFDriver
+{
+  public:
+                ~OGRSEGYDriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual int                 TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_SEGY_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp b/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
new file mode 100644
index 0000000..dfa0cd3
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
@@ -0,0 +1,321 @@
+/******************************************************************************
+ * $Id: ogrsegydatasource.cpp 23268 2011-10-22 09:50:46Z 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>
+ *
+ * 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, DAMSEGYS 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_segy.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogrsegydatasource.cpp 23268 2011-10-22 09:50:46Z rouault $");
+
+/************************************************************************/
+/*                        OGRSEGYDataSource()                       */
+/************************************************************************/
+
+OGRSEGYDataSource::OGRSEGYDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+}
+
+/************************************************************************/
+/*                       ~OGRSEGYDataSource()                       */
+/************************************************************************/
+
+OGRSEGYDataSource::~OGRSEGYDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSEGYDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRSEGYDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                        SEGYReadMSBInt16()                            */
+/************************************************************************/
+
+GInt16 SEGYReadMSBInt16(const GByte* pabyVal)
+{
+    GInt16 nVal;
+    memcpy(&nVal, pabyVal, 2);
+    CPL_MSBPTR16(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                        SEGYReadMSBInt32()                            */
+/************************************************************************/
+
+GInt32 SEGYReadMSBInt32(const GByte* pabyVal)
+{
+    GInt32 nVal;
+    memcpy(&nVal, pabyVal, 4);
+    CPL_MSBPTR32(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                           EBCDICToASCII                              */
+/************************************************************************/
+
+static const GByte EBCDICToASCII[] =
+{
+0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
+0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F,
+};
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRSEGYDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (bUpdateIn)
+    {
+        return FALSE;
+    }
+
+    pszName = CPLStrdup( pszFilename );
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+    if (fp == NULL)
+        return FALSE;
+
+
+// --------------------------------------------------------------------
+//      Read the first 3200 bytes, where the Textual File Header is
+//      located
+// --------------------------------------------------------------------
+
+    GByte* pabyTextHeader = (GByte*) CPLMalloc(3200 + 1);
+    GByte* pabyASCIITextHeader = (GByte*) CPLMalloc(3200 + 40 + 1);
+    if ((int)VSIFReadL(pabyTextHeader, 1, 3200, fp) != 3200)
+    {
+        VSIFCloseL(fp);
+        CPLFree(pabyTextHeader);
+        CPLFree(pabyASCIITextHeader);
+        return FALSE;
+    }
+
+// --------------------------------------------------------------------
+//      Try to decode the header encoded as EBCDIC and then ASCII
+// --------------------------------------------------------------------
+
+    int i, j, k;
+    for( k=0; k<2; k++)
+    {
+        for( i=0, j=0;i<3200;i++)
+        {
+            GByte chASCII = (k == 0) ? EBCDICToASCII[pabyTextHeader[i]] :
+                                       pabyTextHeader[i];
+            if (chASCII < 32 && chASCII != '\t' &&
+                chASCII != '\n' && chASCII != '\r')
+            {
+                break;
+            }
+            pabyASCIITextHeader[j++] = chASCII;
+            if (chASCII != '\n' && ((i + 1) % 80) == 0)
+                pabyASCIITextHeader[j++] = '\n';
+        }
+        pabyASCIITextHeader[j] = '\0';
+
+        if (i == 3200)
+            break;
+        if (k == 1)
+        {
+            VSIFCloseL(fp);
+            CPLFree(pabyTextHeader);
+            CPLFree(pabyASCIITextHeader);
+            return FALSE;
+        }
+    }
+
+    CPLDebug("SIGY", "Header = \n%s", pabyASCIITextHeader);
+    CPLFree(pabyTextHeader);
+
+
+// --------------------------------------------------------------------
+//      SEGYRead the next 400 bytes, where the Binary File Header is
+//      located
+// --------------------------------------------------------------------
+
+    GByte abyFileHeader[400];
+    if ((int)VSIFReadL(abyFileHeader, 1, 400, fp) != 400)
+    {
+        VSIFCloseL(fp);
+        CPLFree(pabyASCIITextHeader);
+        return FALSE;
+    }
+
+// --------------------------------------------------------------------
+//      First check that this binary header is not EBCDIC nor ASCII
+// --------------------------------------------------------------------
+    for( k=0;k<2;k++ )
+    {
+        for( i=0;i<400;i++)
+        {
+            GByte chASCII = (k == 0) ? abyFileHeader[i] :
+                                       EBCDICToASCII[abyFileHeader[i]];
+            /* A translated 0 value, when source value is not 0, means an invalid */
+            /* EBCDIC value. Bail out also for control characters */
+            if (chASCII < 32 && chASCII != '\t' &&
+                chASCII != '\n' && chASCII != '\r')
+            {
+                break;
+            }
+        }
+        if (i == 400)
+        {
+            VSIFCloseL(fp);
+            CPLFree(pabyASCIITextHeader);
+            return FALSE;
+        }
+    }
+
+    SEGYBinaryFileHeader sBFH;
+
+    sBFH.nJobIdNumber = SEGYReadMSBInt32(abyFileHeader + 0);
+    sBFH.nLineNumber = SEGYReadMSBInt32(abyFileHeader + 4);
+    sBFH.nReelNumber = SEGYReadMSBInt32(abyFileHeader + 8);
+    sBFH.nDataTracesPerEnsemble = SEGYReadMSBInt16(abyFileHeader + 12);
+    sBFH.nAuxTracesPerEnsemble = SEGYReadMSBInt16(abyFileHeader + 14);
+    sBFH.nSampleInterval = SEGYReadMSBInt16(abyFileHeader + 16);
+    sBFH.nSampleIntervalOriginal = SEGYReadMSBInt16(abyFileHeader + 18);
+    sBFH.nSamplesPerDataTrace = SEGYReadMSBInt16(abyFileHeader + 20);
+    sBFH.nSamplesPerDataTraceOriginal = SEGYReadMSBInt16(abyFileHeader + 22);
+    sBFH.nDataSampleType = SEGYReadMSBInt16(abyFileHeader + 24);
+    sBFH.nEnsembleFold = SEGYReadMSBInt16(abyFileHeader + 26);
+    sBFH.nTraceSortingCode = SEGYReadMSBInt16(abyFileHeader + 28);
+    sBFH.nVerticalSumCode = SEGYReadMSBInt16(abyFileHeader + 30);
+    sBFH.nSweepFrequencyAtStart = SEGYReadMSBInt16(abyFileHeader + 32);
+    sBFH.nSweepFrequencyAtEnd = SEGYReadMSBInt16(abyFileHeader + 34);
+    sBFH.nSweepLength = SEGYReadMSBInt16(abyFileHeader + 36);
+    sBFH.nSweepType = SEGYReadMSBInt16(abyFileHeader + 38);
+    sBFH.nTraceNumberOfSweepChannel = SEGYReadMSBInt16(abyFileHeader + 40);
+    sBFH.nSweepTraceTaperLengthAtStart = SEGYReadMSBInt16(abyFileHeader + 42);
+    sBFH.nSweepTraceTaperLengthAtEnd = SEGYReadMSBInt16(abyFileHeader + 44);
+    sBFH.nTaperType = SEGYReadMSBInt16(abyFileHeader + 46);
+    sBFH.nCorrelated = SEGYReadMSBInt16(abyFileHeader + 48);
+    sBFH.nBinaryGainRecovered = SEGYReadMSBInt16(abyFileHeader + 50);
+    sBFH.nAmplitudeRecoveryMethod = SEGYReadMSBInt16(abyFileHeader + 52);
+    sBFH.nMeasurementSystem = SEGYReadMSBInt16(abyFileHeader + 54);
+    sBFH.nImpulseSignalPolarity = SEGYReadMSBInt16(abyFileHeader + 56);
+    sBFH.nVibratoryPolaryCode = SEGYReadMSBInt16(abyFileHeader + 58);
+    sBFH.nSEGYRevisionNumber = SEGYReadMSBInt16(abyFileHeader + 300) & 0xffff;
+    sBFH.dfSEGYRevisionNumber = sBFH.nSEGYRevisionNumber / 256.0;
+    sBFH.nFixedLengthTraceFlag = SEGYReadMSBInt16(abyFileHeader + 302);
+    sBFH.nNumberOfExtendedTextualFileHeader = SEGYReadMSBInt16(abyFileHeader + 304);
+
+#if 0
+    CPLDebug("SIGY", "nJobIdNumber = %d", sBFH.nJobIdNumber);
+    CPLDebug("SIGY", "nLineNumber = %d", sBFH.nLineNumber);
+    CPLDebug("SIGY", "nReelNumber = %d", sBFH.nReelNumber);
+    CPLDebug("SIGY", "nDataTracesPerEnsemble = %d", sBFH.nDataTracesPerEnsemble);
+    CPLDebug("SIGY", "nAuxTracesPerEnsemble = %d", sBFH.nAuxTracesPerEnsemble);
+    CPLDebug("SIGY", "nSampleInterval = %d", sBFH.nSampleInterval);
+    CPLDebug("SIGY", "nSampleIntervalOriginal = %d", sBFH.nSampleIntervalOriginal);
+    CPLDebug("SIGY", "nSamplesPerDataTrace = %d", sBFH.nSamplesPerDataTrace);
+    CPLDebug("SIGY", "nSamplesPerDataTraceOriginal = %d", sBFH.nSamplesPerDataTraceOriginal);
+    CPLDebug("SIGY", "nDataSampleType = %d", sBFH.nDataSampleType);
+    CPLDebug("SIGY", "nEnsembleFold = %d", sBFH.nEnsembleFold);
+    CPLDebug("SIGY", "nTraceSortingCode = %d", sBFH.nTraceSortingCode);
+    CPLDebug("SIGY", "nVerticalSumCode = %d", sBFH.nVerticalSumCode);
+    CPLDebug("SIGY", "nSweepFrequencyAtStart = %d", sBFH.nSweepFrequencyAtStart);
+    CPLDebug("SIGY", "nSweepFrequencyAtEnd = %d", sBFH.nSweepFrequencyAtEnd);
+    CPLDebug("SIGY", "nSweepLength = %d", sBFH.nSweepLength);
+    CPLDebug("SIGY", "nSweepType = %d", sBFH.nSweepType);
+    CPLDebug("SIGY", "nTraceNumberOfSweepChannel = %d", sBFH.nTraceNumberOfSweepChannel);
+    CPLDebug("SIGY", "nSweepTraceTaperLengthAtStart = %d", sBFH.nSweepTraceTaperLengthAtStart);
+    CPLDebug("SIGY", "nSweepTraceTaperLengthAtEnd = %d", sBFH.nSweepTraceTaperLengthAtEnd);
+    CPLDebug("SIGY", "nTaperType = %d", sBFH.nTaperType);
+    CPLDebug("SIGY", "nCorrelated = %d", sBFH.nCorrelated);
+    CPLDebug("SIGY", "nBinaryGainRecovered = %d", sBFH.nBinaryGainRecovered);
+    CPLDebug("SIGY", "nAmplitudeRecoveryMethod = %d", sBFH.nAmplitudeRecoveryMethod);
+    CPLDebug("SIGY", "nMeasurementSystem = %d", sBFH.nMeasurementSystem);
+    CPLDebug("SIGY", "nImpulseSignalPolarity = %d", sBFH.nImpulseSignalPolarity);
+    CPLDebug("SIGY", "nVibratoryPolaryCode = %d", sBFH.nVibratoryPolaryCode);
+    CPLDebug("SIGY", "nSEGYRevisionNumber = %d", sBFH.nSEGYRevisionNumber);
+    CPLDebug("SIGY", "dfSEGYRevisionNumber = %f", sBFH.dfSEGYRevisionNumber);
+    CPLDebug("SIGY", "nFixedLengthTraceFlag = %d", sBFH.nFixedLengthTraceFlag);
+    CPLDebug("SIGY", "nNumberOfExtendedTextualFileHeader = %d", sBFH.nNumberOfExtendedTextualFileHeader);
+#endif
+
+// --------------------------------------------------------------------
+//      Create layer
+// --------------------------------------------------------------------
+
+    nLayers = 2;
+    papoLayers = (OGRLayer**) CPLMalloc(nLayers * sizeof(OGRLayer*));
+    papoLayers[0] = new OGRSEGYLayer(pszName, fp, &sBFH);
+    papoLayers[1] = new OGRSEGYHeaderLayer(CPLSPrintf("%s_header", CPLGetBasename(pszName)), &sBFH, (char*) pabyASCIITextHeader);
+
+    return TRUE;
+}
diff --git a/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
new file mode 100644
index 0000000..ed7368d
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
@@ -0,0 +1,91 @@
+/******************************************************************************
+ * $Id: ogrsegydriver.cpp 23268 2011-10-22 09:50:46Z 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>
+ *
+ * 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, DAMSEGYS 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_segy.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrsegydriver.cpp 23268 2011-10-22 09:50:46Z rouault $");
+
+/************************************************************************/
+/*                           ~OGRSEGYDriver()                           */
+/************************************************************************/
+
+OGRSEGYDriver::~OGRSEGYDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRSEGYDriver::GetName()
+
+{
+    return "SEGY";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRSEGYDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRSEGYDataSource   *poDS = new OGRSEGYDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSEGYDriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRSEGY()                           */
+/************************************************************************/
+
+void RegisterOGRSEGY()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRSEGYDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
new file mode 100644
index 0000000..df7a5fc
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
@@ -0,0 +1,929 @@
+/******************************************************************************
+ * $Id: ogrsegylayer.cpp 23292 2011-10-30 09:16:40Z 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>
+ *
+ * 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, DAMSEGYS 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_segy.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_p.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: ogrsegylayer.cpp 23292 2011-10-30 09:16:40Z rouault $");
+
+#define DT_IBM_4BYTES_FP         1
+#define DT_4BYTES_INT            2
+#define DT_2BYTES_INT            3
+#define DT_4BYTES_FP_WITH_GAIN   4
+#define DT_IEEE_4BYTES_FP        5
+#define DT_1BYTE_INT             8
+
+typedef struct
+{
+    const char*     pszName;
+    OGRFieldType    eType;
+} FieldDesc;
+
+static const FieldDesc SEGYFields[] =
+{
+    { "TRACE_NUMBER_WITHIN_LINE", OFTInteger },
+    { "TRACE_NUMBER_WITHIN_FILE", OFTInteger },
+    { "ORIGINAL_FIELD_RECORD_NUMBER", OFTInteger },
+    { "TRACE_NUMBER_WITHIN_ORIGINAL_FIELD_RECORD", OFTInteger },
+    { "TRACE_IDENTIFICATION_CODE", OFTInteger },
+    { "ENSEMBLE_NUMBER", OFTInteger },
+    { "TRACE_NUMBER_WITHIN_ENSEMBLE", OFTInteger },
+    { "NUMBER_VERTICAL_SUMMED_TRACES", OFTInteger },
+    { "NUMBER_HORIZONTAL_STACKED_TRACES", OFTInteger },
+    { "DATA_USE", OFTInteger },
+    { "DISTANCE_SOURCE_GROUP", OFTInteger },
+    { "RECEIVER_GROUP_ELEVATION", OFTInteger },
+    { "SURFACE_ELEVATION_AT_SOURCE", OFTInteger },
+    { "SOURCE_DEPTH_BELOW_SURFACE", OFTInteger },
+    { "DATUM_ELEVATION_AT_RECEIVER_GROUP", OFTInteger },
+    { "DATUM_ELEVATION_AT_SOURCE", OFTInteger },
+    { "WATER_DEPTH_AT_SOURCE", OFTInteger },
+    { "WATER_DEPTH_AT_GROUP", OFTInteger },
+    { "VERTICAL_SCALAR", OFTInteger },
+    { "HORIZONTAL_SCALAR", OFTInteger },
+    { "SOURCE_X", OFTInteger },
+    { "SOURCE_Y", OFTInteger },
+    { "GROUP_X", OFTInteger },
+    { "GROUP_Y", OFTInteger },
+    { "COORDINATE_UNITS", OFTInteger },
+    { "WEATHERING_VELOCITY", OFTInteger },
+    { "SUB_WEATHERING_VELOCITY", OFTInteger },
+    { "UPHOLE_TIME_AT_SOURCE", OFTInteger },
+    { "UPHOLE_TIME_AT_GROUP", OFTInteger },
+    { "SOURCE_STATIC_CORRECTION", OFTInteger },
+    { "GROUP_STATIC_CORRECTION", OFTInteger },
+    { "TOTAL_STATIC_CORRECTION", OFTInteger },
+    { "LAG_TIME_A", OFTInteger },
+    { "LAG_TIME_B", OFTInteger },
+    { "DELAY_RECORDING_TIME", OFTInteger },
+    { "MUTE_TIME_START", OFTInteger },
+    { "MUTE_TIME_END", OFTInteger },
+    { "SAMPLES", OFTInteger },
+    { "SAMPLE_INTERVAL", OFTInteger },
+    { "GAIN_TYPE", OFTInteger },
+    { "INSTRUMENT_GAIN_CONSTANT", OFTInteger },
+    { "INSTRUMENT_INITIAL_GAIN", OFTInteger },
+    { "CORRELATED", OFTInteger },
+    { "SWEEP_FREQUENCY_AT_START", OFTInteger },
+    { "SWEEP_FREQUENCY_AT_END", OFTInteger },
+    { "SWEEP_LENGTH", OFTInteger },
+    { "SWEEP_TYPE", OFTInteger },
+    { "SWEEP_TRACE_TAPER_LENGTH_AT_START", OFTInteger },
+    { "SWEEP_TRACE_TAPER_LENGTH_AT_END", OFTInteger },
+    { "TAPER_TYPE", OFTInteger },
+    { "ALIAS_FILTER_FREQUENCY", OFTInteger },
+    { "ALIAS_FILTER_SLOPE", OFTInteger },
+    { "NOTCH_FILTER_FREQUENCY", OFTInteger },
+    { "NOTCH_FILTER_SLOPE", OFTInteger },
+    { "LOW_CUT_FREQUENCY", OFTInteger },
+    { "HIGH_CUT_FREQUENCY", OFTInteger },
+    { "LOW_CUT_SLOPE", OFTInteger },
+    { "HIGH_CUT_SLOPE", OFTInteger },
+    { "YEAR", OFTInteger },
+    { "DAY_OF_YEAR", OFTInteger },
+    { "HOUR", OFTInteger },
+    { "MINUTE", OFTInteger },
+    { "SECOND", OFTInteger },
+    { "TIME_BASIC_CODE", OFTInteger },
+    { "TRACE_WEIGHTING_FACTOR", OFTInteger },
+    { "GEOPHONE_GROUP_NUMBER_OF_ROLL_SWITH", OFTInteger },
+    { "GEOPHONE_GROUP_NUMBER_OF_TRACE_NUMBER_ONE", OFTInteger },
+    { "GEOPHONE_GROUP_NUMBER_OF_LAST_TRACE", OFTInteger },
+    { "GAP_SIZE", OFTInteger },
+    { "OVER_TRAVEL", OFTInteger },
+};
+
+/* SEGY >= 1.0 */
+static const FieldDesc SEGYFields10[] =
+{
+    { "INLINE_NUMBER", OFTInteger },
+    { "CROSSLINE_NUMBER", OFTInteger },
+    { "SHOTPOINT_NUMBER", OFTInteger },
+    { "SHOTPOINT_SCALAR", OFTInteger },
+};
+
+#define TRACE_NUMBER_WITHIN_LINE 0
+#define TRACE_NUMBER_WITHIN_FILE 1
+#define ORIGINAL_FIELD_RECORD_NUMBER 2
+#define TRACE_NUMBER_WITHIN_ORIGINAL_FIELD_RECORD 3
+#define TRACE_IDENTIFICATION_CODE 4
+#define ENSEMBLE_NUMBER 5
+#define TRACE_NUMBER_WITHIN_ENSEMBLE 6
+#define NUMBER_VERTICAL_SUMMED_TRACES 7
+#define NUMBER_HORIZONTAL_STACKED_TRACES 8
+#define DATA_USE 9
+#define DISTANCE_SOURCE_GROUP 10
+#define RECEIVER_GROUP_ELEVATION 11
+#define SURFACE_ELEVATION_AT_SOURCE 12
+#define SOURCE_DEPTH_BELOW_SURFACE 13
+#define DATUM_ELEVATION_AT_RECEIVER_GROUP 14
+#define DATUM_ELEVATION_AT_SOURCE 15
+#define WATER_DEPTH_AT_SOURCE 16
+#define WATER_DEPTH_AT_GROUP 17
+#define VERTICAL_SCALAR 18
+#define HORIZONTAL_SCALAR 19
+#define SOURCE_X 20
+#define SOURCE_Y 21
+#define GROUP_X 22
+#define GROUP_Y 23
+#define COORDINATE_UNITS 24
+#define WEATHERING_VELOCITY 25
+#define SUB_WEATHERING_VELOCITY 26
+#define UPHOLE_TIME_AT_SOURCE 27
+#define UPHOLE_TIME_AT_GROUP 28
+#define SOURCE_STATIC_CORRECTION 29
+#define GROUP_STATIC_CORRECTION 30
+#define TOTAL_STATIC_CORRECTION 31
+#define LAG_TIME_A 32
+#define LAG_TIME_B 33
+#define DELAY_RECORDING_TIME 34
+#define MUTE_TIME_START 35
+#define MUTE_TIME_END 36
+#define SAMPLES 37
+#define SAMPLE_INTERVAL 38
+#define GAIN_TYPE 39
+#define INSTRUMENT_GAIN_CONSTANT 40
+#define INSTRUMENT_INITIAL_GAIN 41
+#define CORRELATED 42
+#define SWEEP_FREQUENCY_AT_START 43
+#define SWEEP_FREQUENCY_AT_END 44
+#define SWEEP_LENGTH 45
+#define SWEEP_TYPE 46
+#define SWEEP_TRACE_TAPER_LENGTH_AT_START 47
+#define SWEEP_TRACE_TAPER_LENGTH_AT_END 48
+#define TAPER_TYPE 49
+#define ALIAS_FILTER_FREQUENCY 50
+#define ALIAS_FILTER_SLOPE 51
+#define NOTCH_FILTER_FREQUENCY 52
+#define NOTCH_FILTER_SLOPE 53
+#define LOW_CUT_FREQUENCY 54
+#define HIGH_CUT_FREQUENCY 55
+#define LOW_CUT_SLOPE 56
+#define HIGH_CUT_SLOPE 57
+#define YEAR 58
+#define DAY_OF_YEAR 59
+#define HOUR 60
+#define MINUTE 61
+#define SECOND 62
+#define TIME_BASIC_CODE 63
+#define TRACE_WEIGHTING_FACTOR 64
+#define GEOPHONE_GROUP_NUMBER_OF_ROLL_SWITH 65
+#define GEOPHONE_GROUP_NUMBER_OF_TRACE_NUMBER_ONE 66
+#define GEOPHONE_GROUP_NUMBER_OF_LAST_TRACE 67
+#define GAP_SIZE 68
+#define OVER_TRAVEL 69
+#define INLINE_NUMBER 70
+#define CROSSLINE_NUMBER 71
+#define SHOTPOINT_NUMBER 72
+#define SHOTPOINT_SCALAR 73
+
+#if 0
+/************************************************************************/
+/*                       SEGYReadMSBFloat32()                           */
+/************************************************************************/
+
+static float SEGYReadMSBFloat32(const GByte* pabyVal)
+{
+    float fVal;
+    memcpy(&fVal, pabyVal, 4);
+    CPL_MSBPTR32(&fVal);
+    return fVal;
+}
+#endif
+
+/************************************************************************/
+/*                           OGRSEGYLayer()                            */
+/************************************************************************/
+
+
+OGRSEGYLayer::OGRSEGYLayer( const char* pszFilename,
+                            VSILFILE* fp,
+                            SEGYBinaryFileHeader* psBFH )
+
+{
+    this->fp = fp;
+    nNextFID = 0;
+    bEOF = FALSE;
+    poSRS = NULL;
+    memcpy(&sBFH, psBFH, sizeof(sBFH));
+
+    nDataSize = 0;
+    switch (sBFH.nDataSampleType)
+    {
+        case DT_IBM_4BYTES_FP: nDataSize = 4; break;
+        case DT_4BYTES_INT: nDataSize = 4; break;
+        case DT_2BYTES_INT: nDataSize = 2; break;
+        case DT_4BYTES_FP_WITH_GAIN: nDataSize = 4; break;
+        case DT_IEEE_4BYTES_FP: nDataSize = 4; break;
+        case DT_1BYTE_INT: nDataSize = 1; break;
+        default: break;
+    }
+
+    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbPoint );
+
+    int i;
+    for(i=0;i<(int)(sizeof(SEGYFields)/sizeof(SEGYFields[0]));i++)
+    {
+        OGRFieldDefn    oField( SEGYFields[i].pszName,
+                                SEGYFields[i].eType );
+        poFeatureDefn->AddFieldDefn( &oField );
+    }
+
+    if (sBFH.dfSEGYRevisionNumber >= 1.0)
+    {
+        for(i=0;i<(int)(sizeof(SEGYFields10)/sizeof(SEGYFields10[0]));i++)
+        {
+            OGRFieldDefn    oField( SEGYFields10[i].pszName,
+                                    SEGYFields10[i].eType );
+            poFeatureDefn->AddFieldDefn( &oField );
+        }
+    }
+
+    OGRFieldDefn oField( "SAMPLE_ARRAY", OFTRealList );
+    poFeatureDefn->AddFieldDefn(&oField);
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                            ~OGRSEGYLayer()                          */
+/************************************************************************/
+
+OGRSEGYLayer::~OGRSEGYLayer()
+
+{
+    poFeatureDefn->Release();
+
+    VSIFCloseL( fp );
+
+    if (poSRS)
+        poSRS->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRSEGYLayer::ResetReading()
+
+{
+    nNextFID = 0;
+    bEOF = FALSE;
+
+    VSIFSeekL( fp, 3200 + 400 + 3200 * sBFH.nNumberOfExtendedTextualFileHeader,
+               SEEK_SET );
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRSEGYLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    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;
+    }
+}
+
+/************************************************************************/
+/*                             GetIBMFloat()                            */
+/************************************************************************/
+
+static float GetIBMFloat(const GByte* pabyData)
+{
+    int nVal;
+    memcpy(&nVal, pabyData, 4);
+    CPL_MSBPTR32(&nVal);
+    int nSign = 1 - 2 * ((nVal >> 31) & 0x01);
+    int nExp = (nVal >> 24) & 0x7f;
+    int nMant = nVal & 0xffffff;
+
+    if (nExp == 0x7f)
+    {
+        nVal = (nVal & 0x80000000) | (0xff << 23) | (nMant >> 1);
+        float fVal;
+        memcpy(&fVal, &nVal, 4);
+        return fVal;
+    }
+
+    return (float)((double)nSign * nMant * pow(2.0, 4 * (nExp - 64) - 24));
+}
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRSEGYLayer::GetNextRawFeature()
+{
+    if (bEOF)
+        return NULL;
+
+    GByte abyTraceHeader[240];
+
+    if ((int)VSIFReadL(abyTraceHeader, 1, 240, fp) != 240)
+    {
+        bEOF = TRUE;
+        return NULL;
+    }
+
+    int nTraceNumberWithinLine = SEGYReadMSBInt32(abyTraceHeader + 0);
+    int nTraceNumberWithinFile = SEGYReadMSBInt32(abyTraceHeader + 4);
+    int nOriginalFieldRecordNumber = SEGYReadMSBInt32(abyTraceHeader + 8);
+    int nTraceNumberWithinOriginalFieldRecord = SEGYReadMSBInt32(abyTraceHeader + 12);
+    int nEnsembleNumber = SEGYReadMSBInt32(abyTraceHeader + 20);
+    int nTraceNumberWithinEnsemble = SEGYReadMSBInt32(abyTraceHeader + 24);
+    int nTraceIdentificationCode = SEGYReadMSBInt16(abyTraceHeader + 28);
+    int nNumberVerticalSummedTraces = SEGYReadMSBInt16(abyTraceHeader + 30);
+    int nNumberHorizontalStackedTraces = SEGYReadMSBInt16(abyTraceHeader + 32);
+    int nDataUse = SEGYReadMSBInt16(abyTraceHeader + 34);
+    int nDistanceSourceGroup = SEGYReadMSBInt32(abyTraceHeader + 36);
+    int nReceiverGroupElevation = SEGYReadMSBInt32(abyTraceHeader + 40);
+    int nSurfaceElevationAtSource = SEGYReadMSBInt32(abyTraceHeader + 44);
+    int nSourceDepthBelowSurface = SEGYReadMSBInt32(abyTraceHeader + 48);
+    int nDatumElevationAtReceiverGroup = SEGYReadMSBInt32(abyTraceHeader + 52);
+    int nDatumElevationAtSource = SEGYReadMSBInt32(abyTraceHeader + 56);
+    int nWaterDepthAtSource = SEGYReadMSBInt32(abyTraceHeader + 60);
+    int nWaterDepthAtGroup = SEGYReadMSBInt32(abyTraceHeader + 64);
+    int nVerticalScalar = SEGYReadMSBInt16(abyTraceHeader + 68);
+    int nHorizontalScalar = SEGYReadMSBInt16(abyTraceHeader + 70);
+    int nSourceX = SEGYReadMSBInt32(abyTraceHeader + 72);
+    int nSourceY = SEGYReadMSBInt32(abyTraceHeader + 76);
+    int nGroupX = SEGYReadMSBInt32(abyTraceHeader + 80);
+    int nGroupY = SEGYReadMSBInt32(abyTraceHeader + 84);
+    int nCoordinateUnits = SEGYReadMSBInt16(abyTraceHeader + 88);
+    int nWeatheringVelocity = SEGYReadMSBInt16(abyTraceHeader + 90);
+    int nSubWeatheringVelocity = SEGYReadMSBInt16(abyTraceHeader + 92);
+
+    int nUpholeTimeAtSource = SEGYReadMSBInt16(abyTraceHeader + 94);
+    int nUpholeTimeAtGroup = SEGYReadMSBInt16(abyTraceHeader + 96);
+    int nSourceStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 98);
+    int nGroupStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 100);
+    int nTotalStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 102);
+    int nLagTimeA = SEGYReadMSBInt16(abyTraceHeader + 104);
+    int nLagTimeB = SEGYReadMSBInt16(abyTraceHeader + 106);
+    int nDelayRecordingTime = SEGYReadMSBInt16(abyTraceHeader + 108);
+    int nMuteTimeStart = SEGYReadMSBInt16(abyTraceHeader + 110);
+    int nMuteTimeEnd = SEGYReadMSBInt16(abyTraceHeader + 112);
+
+    int nSamples = SEGYReadMSBInt16(abyTraceHeader + 114);
+    if (nSamples == 0) /* Happens with ftp://software.seg.org/pub/datasets/2D/Hess_VTI/timodel_c11.segy.gz */
+        nSamples = sBFH.nSamplesPerDataTrace;
+
+    if (nSamples < 0)
+    {
+        bEOF = TRUE;
+        return NULL;
+    }
+    int nSampleInterval = SEGYReadMSBInt16(abyTraceHeader + 116);
+
+    int nGainType = SEGYReadMSBInt16(abyTraceHeader + 118);
+    int nInstrumentGainConstant = SEGYReadMSBInt16(abyTraceHeader + 120);
+    int nInstrumentInitialGain = SEGYReadMSBInt16(abyTraceHeader + 122);
+    int nCorrelated = SEGYReadMSBInt16(abyTraceHeader + 124);
+    int nSweepFrequencyAtStart = SEGYReadMSBInt16(abyTraceHeader + 126);
+    int nSweepFrequencyAtEnd = SEGYReadMSBInt16(abyTraceHeader + 128);
+    int nSweepLength = SEGYReadMSBInt16(abyTraceHeader + 130);
+    int nSweepType = SEGYReadMSBInt16(abyTraceHeader + 132);
+    int nSweepTraceTaperLengthAtStart = SEGYReadMSBInt16(abyTraceHeader + 134);
+    int nSweepTraceTaperLengthAtEnd = SEGYReadMSBInt16(abyTraceHeader + 136);
+    int nTaperType = SEGYReadMSBInt16(abyTraceHeader + 138);
+    int nAliasFilterFrequency = SEGYReadMSBInt16(abyTraceHeader + 140);
+    int nAliasFilterSlope = SEGYReadMSBInt16(abyTraceHeader + 142);
+    int nNotchFilterFrequency = SEGYReadMSBInt16(abyTraceHeader + 144);
+    int nNotchFilterSlope = SEGYReadMSBInt16(abyTraceHeader + 146);
+    int nLowCutFrequency = SEGYReadMSBInt16(abyTraceHeader + 148);
+    int nHighCutFrequency = SEGYReadMSBInt16(abyTraceHeader + 150);
+    int nLowCutSlope = SEGYReadMSBInt16(abyTraceHeader + 152);
+    int nHighCutSlope = SEGYReadMSBInt16(abyTraceHeader + 154);
+
+    int nYear = SEGYReadMSBInt16(abyTraceHeader + 156);
+    int nDayOfYear = SEGYReadMSBInt16(abyTraceHeader + 158);
+    int nHour = SEGYReadMSBInt16(abyTraceHeader + 160);
+    int nMinute = SEGYReadMSBInt16(abyTraceHeader + 162);
+    int nSecond = SEGYReadMSBInt16(abyTraceHeader + 164);
+    int nTimeBasicCode = SEGYReadMSBInt16(abyTraceHeader + 166);
+
+    int nTraceWeightingFactor = SEGYReadMSBInt16(abyTraceHeader + 168);
+    int nGeophoneGroupNumberOfRollSwith = SEGYReadMSBInt16(abyTraceHeader + 170);
+    int nGeophoneGroupNumberOfTraceNumberOne = SEGYReadMSBInt16(abyTraceHeader + 172);
+    int nGeophoneGroupNumberOfLastTrace = SEGYReadMSBInt16(abyTraceHeader + 174);
+    int nGapSize = SEGYReadMSBInt16(abyTraceHeader + 176);
+    int nOverTravel = SEGYReadMSBInt16(abyTraceHeader + 178);
+
+    int nInlineNumber = SEGYReadMSBInt32(abyTraceHeader + 188);
+    int nCrosslineNumber = SEGYReadMSBInt32(abyTraceHeader + 192);
+    int nShotpointNumber = SEGYReadMSBInt32(abyTraceHeader + 196);
+    int nShotpointScalar = SEGYReadMSBInt16(abyTraceHeader + 200);
+
+#if 0
+    /* Extensions of http://sioseis.ucsd.edu/segy.header.html */
+    float fDeepWaterDelay = SEGYReadMSBFloat32(abyTraceHeader + 180);
+    float fStartMuteTime  = SEGYReadMSBFloat32(abyTraceHeader + 184);
+    float fEndMuteTime  = SEGYReadMSBFloat32(abyTraceHeader + 188);
+    float fSampleInterval  = SEGYReadMSBFloat32(abyTraceHeader + 192);
+    float fWaterBottomTime  = SEGYReadMSBFloat32(abyTraceHeader + 196);
+    int nEndOfRp = SEGYReadMSBInt16(abyTraceHeader + 200);
+    CPLDebug("SIGY", "fDeepWaterDelay = %f", fDeepWaterDelay);
+    CPLDebug("SIGY", "fStartMuteTime = %f", fStartMuteTime);
+    CPLDebug("SIGY", "fEndMuteTime = %f", fEndMuteTime);
+    CPLDebug("SIGY", "fSampleInterval = %f", fSampleInterval);
+    CPLDebug("SIGY", "fWaterBottomTime = %f", fWaterBottomTime);
+    CPLDebug("SIGY", "nEndOfRp = %d", nEndOfRp);
+#endif
+
+    double dfHorizontalScale = (nHorizontalScalar > 0) ? nHorizontalScalar :
+                               (nHorizontalScalar < 0) ? 1.0 / -nHorizontalScalar : 1.0;
+    if (nCoordinateUnits == 2)
+        dfHorizontalScale /= 3600;
+
+    double dfGroupX = nGroupX * dfHorizontalScale;
+    double dfGroupY = nGroupY * dfHorizontalScale;
+
+#if 0
+    double dfSourceX = nSourceX * dfHorizontalScale;
+    double dfSourceY = nSourceY * dfHorizontalScale;
+#endif
+
+#if 0
+    CPLDebug("SIGY", "nTraceNumberWithinLine = %d", nTraceNumberWithinLine);
+    CPLDebug("SIGY", "nTraceNumberWithinFile = %d", nTraceNumberWithinFile);
+    CPLDebug("SIGY", "nOriginalFieldRecordNumber = %d", nOriginalFieldRecordNumber);
+    CPLDebug("SIGY", "nTraceNumberWithinOriginalFieldRecord = %d", nTraceNumberWithinOriginalFieldRecord);
+    CPLDebug("SIGY", "nTraceIdentificationCode = %d", nTraceIdentificationCode);
+    CPLDebug("SIGY", "nEnsembleNumber = %d", nEnsembleNumber);
+    CPLDebug("SIGY", "nTraceNumberWithinEnsemble = %d", nTraceNumberWithinEnsemble);
+    CPLDebug("SIGY", "nNumberVerticalSummedTraces = %d", nNumberVerticalSummedTraces);
+    CPLDebug("SIGY", "nNumberHorizontalStackedTraces = %d", nNumberHorizontalStackedTraces);
+    CPLDebug("SIGY", "nDataUse = %d", nDataUse);
+    CPLDebug("SIGY", "nDistanceSourceGroup = %d", nDistanceSourceGroup);
+    CPLDebug("SIGY", "nReceiverGroupElevation = %d", nReceiverGroupElevation);
+    CPLDebug("SIGY", "nSurfaceElevationAtSource = %d", nSurfaceElevationAtSource);
+    CPLDebug("SIGY", "nSourceDepthBelowSurface = %d", nSourceDepthBelowSurface);
+    CPLDebug("SIGY", "nDatumElevationAtReceiverGroup = %d", nDatumElevationAtReceiverGroup);
+    CPLDebug("SIGY", "nDatumElevationAtSource = %d", nDatumElevationAtSource);
+    CPLDebug("SIGY", "nWaterDepthAtSource = %d", nWaterDepthAtSource);
+    CPLDebug("SIGY", "nWaterDepthAtGroup = %d", nWaterDepthAtGroup);
+    CPLDebug("SIGY", "nVerticalScalar = %d", nVerticalScalar);
+    CPLDebug("SIGY", "nHorizontalScalar = %d", nHorizontalScalar);
+    CPLDebug("SIGY", "nSourceX = %d", nSourceX);
+    CPLDebug("SIGY", "nSourceY = %d", nSourceY);
+    CPLDebug("SIGY", "dfSourceX = %f", dfSourceX);
+    CPLDebug("SIGY", "dfSourceY = %f", dfSourceY);
+    CPLDebug("SIGY", "nGroupX = %d", nGroupX);
+    CPLDebug("SIGY", "nGroupY = %d", nGroupY);
+    CPLDebug("SIGY", "dfGroupX = %f", dfGroupX);
+    CPLDebug("SIGY", "dfGroupY = %f", dfGroupY);
+    CPLDebug("SIGY", "nCoordinateUnits = %d", nCoordinateUnits);
+
+    CPLDebug("SIGY", "nWeatheringVelocity = %d", nWeatheringVelocity);
+    CPLDebug("SIGY", "nSubWeatheringVelocity = %d", nSubWeatheringVelocity);
+    CPLDebug("SIGY", "nUpholeTimeAtSource = %d", nUpholeTimeAtSource);
+    CPLDebug("SIGY", "nUpholeTimeAtGroup = %d", nUpholeTimeAtGroup);
+    CPLDebug("SIGY", "nSourceStaticCorrection = %d", nSourceStaticCorrection);
+    CPLDebug("SIGY", "nGroupStaticCorrection = %d", nGroupStaticCorrection);
+    CPLDebug("SIGY", "nTotalStaticCorrection = %d", nTotalStaticCorrection);
+    CPLDebug("SIGY", "nLagTimeA = %d", nLagTimeA);
+    CPLDebug("SIGY", "nLagTimeB = %d", nLagTimeB);
+    CPLDebug("SIGY", "nDelayRecordingTime = %d", nDelayRecordingTime);
+    CPLDebug("SIGY", "nMuteTimeStart = %d", nMuteTimeStart);
+    CPLDebug("SIGY", "nMuteTimeEnd = %d", nMuteTimeEnd);
+
+    CPLDebug("SIGY", "nSamples = %d", nSamples);
+    CPLDebug("SIGY", "nSampleInterval = %d", nSampleInterval);
+
+    CPLDebug("SIGY", "nGainType = %d", nGainType);
+    CPLDebug("SIGY", "nInstrumentGainConstant = %d", nInstrumentGainConstant);
+    CPLDebug("SIGY", "nInstrumentInitialGain = %d", nInstrumentInitialGain);
+    CPLDebug("SIGY", "nCorrelated = %d", nCorrelated);
+    CPLDebug("SIGY", "nSweepFrequencyAtStart = %d", nSweepFrequencyAtStart);
+    CPLDebug("SIGY", "nSweepFrequencyAtEnd = %d", nSweepFrequencyAtEnd);
+    CPLDebug("SIGY", "nSweepLength = %d", nSweepLength);
+    CPLDebug("SIGY", "nSweepType = %d", nSweepType);
+    CPLDebug("SIGY", "nSweepTraceTaperLengthAtStart = %d", nSweepTraceTaperLengthAtStart);
+    CPLDebug("SIGY", "nSweepTraceTaperLengthAtEnd = %d", nSweepTraceTaperLengthAtEnd);
+    CPLDebug("SIGY", "nTaperType = %d", nTaperType);
+    CPLDebug("SIGY", "nAliasFilterFrequency = %d", nAliasFilterFrequency);
+    CPLDebug("SIGY", "nAliasFilterSlope = %d", nAliasFilterSlope);
+    CPLDebug("SIGY", "nNotchFilterFrequency = %d", nNotchFilterFrequency);
+    CPLDebug("SIGY", "nNotchFilterSlope = %d", nNotchFilterSlope);
+    CPLDebug("SIGY", "nLowCutFrequency = %d", nLowCutFrequency);
+    CPLDebug("SIGY", "nHighCutFrequency = %d", nHighCutFrequency);
+    CPLDebug("SIGY", "nLowCutSlope = %d", nLowCutSlope);
+    CPLDebug("SIGY", "nHighCutSlope = %d", nHighCutSlope);
+    CPLDebug("SIGY", "nYear = %d", nYear);
+    CPLDebug("SIGY", "nDayOfYear = %d", nDayOfYear);
+    CPLDebug("SIGY", "nHour = %d", nHour);
+    CPLDebug("SIGY", "nMinute = %d", nMinute);
+    CPLDebug("SIGY", "nSecond = %d", nSecond);
+    CPLDebug("SIGY", "nTimeBasicCode = %d", nTimeBasicCode);
+    CPLDebug("SIGY", "nTraceWeightingFactor = %d", nTraceWeightingFactor);
+    CPLDebug("SIGY", "nGeophoneGroupNumberOfRollSwith = %d", nGeophoneGroupNumberOfRollSwith);
+    CPLDebug("SIGY", "nGeophoneGroupNumberOfTraceNumberOne = %d", nGeophoneGroupNumberOfTraceNumberOne);
+    CPLDebug("SIGY", "nGeophoneGroupNumberOfLastTrace = %d", nGeophoneGroupNumberOfLastTrace);
+    CPLDebug("SIGY", "nGapSize = %d", nGapSize);
+    CPLDebug("SIGY", "nOverTravel = %d", nOverTravel);
+
+    if (sBFH.dfSEGYRevisionNumber >= 1.0)
+    {
+        CPLDebug("SIGY", "nInlineNumber = %d", nInlineNumber);
+        CPLDebug("SIGY", "nCrosslineNumber = %d", nCrosslineNumber);
+        CPLDebug("SIGY", "nShotpointNumber = %d", nShotpointNumber);
+        CPLDebug("SIGY", "nShotpointScalar = %d", nShotpointScalar);
+    }
+#endif
+
+    GByte* pabyData = (GByte*) VSIMalloc( nDataSize * nSamples );
+    double* padfValues = (double*) VSICalloc( nSamples, sizeof(double) );
+    if (pabyData == NULL || padfValues == NULL)
+    {
+        VSIFSeekL( fp, nDataSize * nSamples, SEEK_CUR );
+    }
+    else
+    {
+        if ((int)VSIFReadL(pabyData, nDataSize, nSamples, fp) != nSamples)
+        {
+            bEOF = TRUE;
+        }
+        for(int i=0;i<nSamples;i++)
+        {
+            switch (sBFH.nDataSampleType)
+            {
+                case DT_IBM_4BYTES_FP:
+                {
+                    padfValues[i] = GetIBMFloat(pabyData + i * 4);
+                    break;
+                }
+
+                case DT_4BYTES_INT:
+                {
+                    int nVal;
+                    memcpy(&nVal, pabyData + i * 4, 4);
+                    CPL_MSBPTR32(&nVal);
+                    padfValues[i] = nVal;
+                    break;
+                }
+
+                case DT_2BYTES_INT:
+                {
+                    GInt16 nVal;
+                    memcpy(&nVal, pabyData + i * 2, 2);
+                    CPL_MSBPTR16(&nVal);
+                    padfValues[i] = nVal;
+                    break;
+                }
+
+                case DT_IEEE_4BYTES_FP:
+                {
+                    float fVal;
+                    memcpy(&fVal, pabyData + i * 4, 4);
+                    CPL_MSBPTR32(&fVal);
+                    padfValues[i] = fVal;
+                    break;
+                }
+
+                case DT_1BYTE_INT:
+                {
+                    padfValues[i] = ((char*)pabyData)[i];
+                    break;
+                }
+
+                default:
+                    break;
+            }
+        }
+    }
+    CPLFree(pabyData);
+
+    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+    poFeature->SetFID(nNextFID ++);
+    if (dfGroupX != 0.0 || dfGroupY != 0.0)
+        poFeature->SetGeometryDirectly(new OGRPoint(dfGroupX, dfGroupY));
+
+    poFeature->SetField(TRACE_NUMBER_WITHIN_LINE, nTraceNumberWithinLine);
+    poFeature->SetField(TRACE_NUMBER_WITHIN_FILE, nTraceNumberWithinFile);
+    poFeature->SetField(ORIGINAL_FIELD_RECORD_NUMBER, nOriginalFieldRecordNumber);
+    poFeature->SetField(TRACE_NUMBER_WITHIN_ORIGINAL_FIELD_RECORD, nTraceNumberWithinOriginalFieldRecord);
+    poFeature->SetField(TRACE_IDENTIFICATION_CODE, nTraceIdentificationCode);
+    poFeature->SetField(ENSEMBLE_NUMBER, nEnsembleNumber);
+    poFeature->SetField(TRACE_NUMBER_WITHIN_ENSEMBLE, nTraceNumberWithinEnsemble);
+    poFeature->SetField(NUMBER_VERTICAL_SUMMED_TRACES, nNumberVerticalSummedTraces);
+    poFeature->SetField(NUMBER_HORIZONTAL_STACKED_TRACES, nNumberHorizontalStackedTraces);
+    poFeature->SetField(DATA_USE, nDataUse);
+    poFeature->SetField(DISTANCE_SOURCE_GROUP, nDistanceSourceGroup);
+    poFeature->SetField(RECEIVER_GROUP_ELEVATION, nReceiverGroupElevation);
+    poFeature->SetField(SURFACE_ELEVATION_AT_SOURCE, nSurfaceElevationAtSource);
+    poFeature->SetField(SOURCE_DEPTH_BELOW_SURFACE, nSourceDepthBelowSurface);
+    poFeature->SetField(DATUM_ELEVATION_AT_RECEIVER_GROUP, nDatumElevationAtReceiverGroup);
+    poFeature->SetField(DATUM_ELEVATION_AT_SOURCE, nDatumElevationAtSource);
+    poFeature->SetField(WATER_DEPTH_AT_SOURCE, nWaterDepthAtSource);
+    poFeature->SetField(WATER_DEPTH_AT_GROUP, nWaterDepthAtGroup);
+    poFeature->SetField(VERTICAL_SCALAR, nVerticalScalar);
+    poFeature->SetField(HORIZONTAL_SCALAR, nHorizontalScalar);
+    poFeature->SetField(SOURCE_X, nSourceX);
+    poFeature->SetField(SOURCE_Y, nSourceY);
+    poFeature->SetField(GROUP_X, nGroupX);
+    poFeature->SetField(GROUP_Y, nGroupY);
+    poFeature->SetField(COORDINATE_UNITS, nCoordinateUnits);
+    poFeature->SetField(WEATHERING_VELOCITY, nWeatheringVelocity);
+    poFeature->SetField(SUB_WEATHERING_VELOCITY, nSubWeatheringVelocity);
+    poFeature->SetField(UPHOLE_TIME_AT_SOURCE, nUpholeTimeAtSource);
+    poFeature->SetField(UPHOLE_TIME_AT_GROUP, nUpholeTimeAtGroup);
+    poFeature->SetField(SOURCE_STATIC_CORRECTION, nSourceStaticCorrection);
+    poFeature->SetField(GROUP_STATIC_CORRECTION, nGroupStaticCorrection);
+    poFeature->SetField(TOTAL_STATIC_CORRECTION, nTotalStaticCorrection);
+    poFeature->SetField(LAG_TIME_A, nLagTimeA);
+    poFeature->SetField(LAG_TIME_B, nLagTimeB);
+    poFeature->SetField(DELAY_RECORDING_TIME, nDelayRecordingTime);
+    poFeature->SetField(MUTE_TIME_START, nMuteTimeStart);
+    poFeature->SetField(MUTE_TIME_END, nMuteTimeEnd);
+    poFeature->SetField(SAMPLES, nSamples);
+    poFeature->SetField(SAMPLE_INTERVAL, nSampleInterval);
+    poFeature->SetField(GAIN_TYPE, nGainType);
+    poFeature->SetField(INSTRUMENT_GAIN_CONSTANT, nInstrumentGainConstant);
+    poFeature->SetField(INSTRUMENT_INITIAL_GAIN, nInstrumentInitialGain);
+    poFeature->SetField(CORRELATED, nCorrelated);
+    poFeature->SetField(SWEEP_FREQUENCY_AT_START, nSweepFrequencyAtStart);
+    poFeature->SetField(SWEEP_FREQUENCY_AT_END, nSweepFrequencyAtEnd);
+    poFeature->SetField(SWEEP_LENGTH, nSweepLength);
+    poFeature->SetField(SWEEP_TYPE, nSweepType);
+    poFeature->SetField(SWEEP_TRACE_TAPER_LENGTH_AT_START, nSweepTraceTaperLengthAtStart);
+    poFeature->SetField(SWEEP_TRACE_TAPER_LENGTH_AT_END, nSweepTraceTaperLengthAtEnd);
+    poFeature->SetField(TAPER_TYPE, nTaperType);
+    poFeature->SetField(ALIAS_FILTER_FREQUENCY, nAliasFilterFrequency);
+    poFeature->SetField(ALIAS_FILTER_SLOPE, nAliasFilterSlope);
+    poFeature->SetField(NOTCH_FILTER_FREQUENCY, nNotchFilterFrequency);
+    poFeature->SetField(NOTCH_FILTER_SLOPE, nNotchFilterSlope);
+    poFeature->SetField(LOW_CUT_FREQUENCY, nLowCutFrequency);
+    poFeature->SetField(HIGH_CUT_FREQUENCY, nHighCutFrequency);
+    poFeature->SetField(LOW_CUT_SLOPE, nLowCutSlope);
+    poFeature->SetField(HIGH_CUT_SLOPE, nHighCutSlope);
+    poFeature->SetField(YEAR, nYear);
+    poFeature->SetField(DAY_OF_YEAR, nDayOfYear);
+    poFeature->SetField(HOUR, nHour);
+    poFeature->SetField(MINUTE, nMinute);
+    poFeature->SetField(SECOND, nSecond);
+    poFeature->SetField(TIME_BASIC_CODE, nTimeBasicCode);
+    poFeature->SetField(TRACE_WEIGHTING_FACTOR, nTraceWeightingFactor);
+    poFeature->SetField(GEOPHONE_GROUP_NUMBER_OF_ROLL_SWITH, nGeophoneGroupNumberOfRollSwith);
+    poFeature->SetField(GEOPHONE_GROUP_NUMBER_OF_TRACE_NUMBER_ONE, nGeophoneGroupNumberOfTraceNumberOne);
+    poFeature->SetField(GEOPHONE_GROUP_NUMBER_OF_LAST_TRACE, nGeophoneGroupNumberOfLastTrace);
+    poFeature->SetField(GAP_SIZE, nGapSize);
+    poFeature->SetField(OVER_TRAVEL, nOverTravel);
+
+    if (sBFH.dfSEGYRevisionNumber >= 1.0)
+    {
+        poFeature->SetField(INLINE_NUMBER, nInlineNumber);
+        poFeature->SetField(CROSSLINE_NUMBER, nCrosslineNumber);
+        poFeature->SetField(SHOTPOINT_NUMBER, nShotpointNumber);
+        poFeature->SetField(SHOTPOINT_SCALAR, nShotpointScalar);
+    }
+
+    if (nSamples > 0 && padfValues != NULL)
+        poFeature->SetField(poFeature->GetFieldCount() - 1, nSamples, padfValues);
+
+    CPLFree(padfValues);
+    return poFeature;
+}
+
+
+
+static const FieldDesc SEGYHeaderFields[] =
+{
+    { "TEXT_HEADER", OFTString },
+    { "JOB_ID_NUMBER", OFTInteger },
+    { "LINE_NUMBER", OFTInteger },
+    { "REEL_NUMBER", OFTInteger },
+    { "DATA_TRACES_PER_ENSEMBLE", OFTInteger },
+    { "AUX_TRACES_PER_ENSEMBLE", OFTInteger },
+    { "SAMPLE_INTERVAL", OFTInteger },
+    { "SAMPLE_INTERVAL_ORIGINAL", OFTInteger },
+    { "SAMPLES_PER_DATA_TRACE", OFTInteger },
+    { "SAMPLES_PER_DATA_TRACE_ORIGINAL", OFTInteger },
+    { "DATA_SAMPLE_TYPE", OFTInteger },
+    { "ENSEMBLE_FOLD", OFTInteger },
+    { "TRACE_SORTING_CODE", OFTInteger },
+    { "VERTICAL_SUM_CODE", OFTInteger },
+    { "SWEEP_FREQUENCY_AT_START", OFTInteger },
+    { "SWEEP_FREQUENCY_AT_END", OFTInteger },
+    { "SWEEP_LENGTH", OFTInteger },
+    { "SWEEP_TYPE", OFTInteger },
+    { "TRACE_NUMBER_OF_SWEEP_CHANNEL", OFTInteger },
+    { "SWEEP_TRACE_TAPER_LENGTH_AT_START", OFTInteger },
+    { "SWEEP_TRACE_TAPER_LENGTH_AT_END", OFTInteger },
+    { "TAPER_TYPE", OFTInteger },
+    { "CORRELATED", OFTInteger },
+    { "BINARY_GAIN_RECOVERED", OFTInteger },
+    { "AMPLITUDE_RECOVERY_METHOD", OFTInteger },
+    { "MEASUREMENT_SYSTEM", OFTInteger },
+    { "IMPULSE_SIGNAL_POLARITY", OFTInteger },
+    { "VIBRATORY_POLARY_CODE", OFTInteger },
+    { "SEGY_REVISION_NUMBER", OFTInteger },
+    { "SEGY_FLOAT_REVISION_NUMBER", OFTReal },
+    { "FIXED_LENGTH_TRACE_FLAG", OFTInteger },
+    { "NUMBER_OF_EXTENDED_TEXTUAL_FILE_HEADER", OFTInteger },
+};
+
+#define HEADER_TEXT_HEADER 0
+#define HEADER_JOB_ID_NUMBER 1
+#define HEADER_LINE_NUMBER 2
+#define HEADER_REEL_NUMBER 3
+#define HEADER_DATA_TRACES_PER_ENSEMBLE 4
+#define HEADER_AUX_TRACES_PER_ENSEMBLE 5
+#define HEADER_SAMPLE_INTERVAL 6
+#define HEADER_SAMPLE_INTERVAL_ORIGINAL 7
+#define HEADER_SAMPLES_PER_DATA_TRACE 8
+#define HEADER_SAMPLES_PER_DATA_TRACE_ORIGINAL 9
+#define HEADER_DATA_SAMPLE_TYPE 10
+#define HEADER_ENSEMBLE_FOLD 11
+#define HEADER_TRACE_SORTING_CODE 12
+#define HEADER_VERTICAL_SUM_CODE 13
+#define HEADER_SWEEP_FREQUENCY_AT_START 14
+#define HEADER_SWEEP_FREQUENCY_AT_END 15
+#define HEADER_SWEEP_LENGTH 16
+#define HEADER_SWEEP_TYPE 17
+#define HEADER_TRACE_NUMBER_OF_SWEEP_CHANNEL 18
+#define HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_START 19
+#define HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_END 20
+#define HEADER_TAPER_TYPE 21
+#define HEADER_CORRELATED 22
+#define HEADER_BINARY_GAIN_RECOVERED 23
+#define HEADER_AMPLITUDE_RECOVERY_METHOD 24
+#define HEADER_MEASUREMENT_SYSTEM 25
+#define HEADER_IMPULSE_SIGNAL_POLARITY 26
+#define HEADER_VIBRATORY_POLARY_CODE 27
+#define HEADER_SEGY_REVISION_NUMBER 28
+#define HEADER_FLOAT_SEGY_REVISION_NUMBER 29
+#define HEADER_FIXED_LENGTH_TRACE_FLAG 30
+#define HEADER_NUMBER_OF_EXTENDED_TEXTUAL_FILE_HEADER 31
+
+
+/************************************************************************/
+/*                         OGRSEGYHeaderLayer()                         */
+/************************************************************************/
+
+
+OGRSEGYHeaderLayer::OGRSEGYHeaderLayer( const char* pszLayerName,
+                                        SEGYBinaryFileHeader* psBFH,
+                                        char* pszHeaderTextIn )
+
+{
+    bEOF = FALSE;
+    memcpy(&sBFH, psBFH, sizeof(sBFH));
+    pszHeaderText = pszHeaderTextIn;
+
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbNone );
+
+    int i;
+    for(i=0;i<(int)(sizeof(SEGYHeaderFields)/sizeof(SEGYHeaderFields[0]));i++)
+    {
+        OGRFieldDefn    oField( SEGYHeaderFields[i].pszName,
+                                SEGYHeaderFields[i].eType );
+        poFeatureDefn->AddFieldDefn( &oField );
+    }
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                            ~OGRSEGYLayer()                          */
+/************************************************************************/
+
+OGRSEGYHeaderLayer::~OGRSEGYHeaderLayer()
+
+{
+    poFeatureDefn->Release();
+    CPLFree(pszHeaderText);
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRSEGYHeaderLayer::ResetReading()
+
+{
+    bEOF = FALSE;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRSEGYHeaderLayer::GetNextFeature()
+{
+    OGRFeature  *poFeature;
+
+    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 *OGRSEGYHeaderLayer::GetNextRawFeature()
+{
+    if (bEOF)
+        return NULL;
+
+    bEOF = TRUE;
+
+    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+    poFeature->SetFID(0);
+
+    poFeature->SetField(HEADER_TEXT_HEADER, pszHeaderText);
+    poFeature->SetField(HEADER_JOB_ID_NUMBER, sBFH.nJobIdNumber);
+    poFeature->SetField(HEADER_LINE_NUMBER, sBFH.nLineNumber);
+    poFeature->SetField(HEADER_REEL_NUMBER, sBFH.nReelNumber);
+    poFeature->SetField(HEADER_DATA_TRACES_PER_ENSEMBLE, sBFH.nDataTracesPerEnsemble);
+    poFeature->SetField(HEADER_AUX_TRACES_PER_ENSEMBLE, sBFH.nAuxTracesPerEnsemble);
+    poFeature->SetField(HEADER_SAMPLE_INTERVAL, sBFH.nSampleInterval);
+    poFeature->SetField(HEADER_SAMPLE_INTERVAL_ORIGINAL, sBFH.nSampleIntervalOriginal);
+    poFeature->SetField(HEADER_SAMPLES_PER_DATA_TRACE, sBFH.nSamplesPerDataTrace);
+    poFeature->SetField(HEADER_SAMPLES_PER_DATA_TRACE_ORIGINAL, sBFH.nSamplesPerDataTraceOriginal);
+    poFeature->SetField(HEADER_DATA_SAMPLE_TYPE, sBFH.nDataSampleType);
+    poFeature->SetField(HEADER_ENSEMBLE_FOLD, sBFH.nEnsembleFold);
+    poFeature->SetField(HEADER_TRACE_SORTING_CODE, sBFH.nTraceSortingCode);
+    poFeature->SetField(HEADER_VERTICAL_SUM_CODE, sBFH.nVerticalSumCode);
+    poFeature->SetField(HEADER_SWEEP_FREQUENCY_AT_START, sBFH.nSweepFrequencyAtStart);
+    poFeature->SetField(HEADER_SWEEP_FREQUENCY_AT_END, sBFH.nSweepFrequencyAtEnd);
+    poFeature->SetField(HEADER_SWEEP_LENGTH, sBFH.nSweepLength);
+    poFeature->SetField(HEADER_SWEEP_TYPE, sBFH.nSweepType);
+    poFeature->SetField(HEADER_TRACE_NUMBER_OF_SWEEP_CHANNEL, sBFH.nTraceNumberOfSweepChannel);
+    poFeature->SetField(HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_START, sBFH.nSweepTraceTaperLengthAtStart);
+    poFeature->SetField(HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_END, sBFH.nSweepTraceTaperLengthAtEnd);
+    poFeature->SetField(HEADER_TAPER_TYPE, sBFH.nTaperType);
+    poFeature->SetField(HEADER_CORRELATED, sBFH.nCorrelated);
+    poFeature->SetField(HEADER_BINARY_GAIN_RECOVERED, sBFH.nBinaryGainRecovered);
+    poFeature->SetField(HEADER_AMPLITUDE_RECOVERY_METHOD, sBFH.nAmplitudeRecoveryMethod);
+    poFeature->SetField(HEADER_MEASUREMENT_SYSTEM, sBFH.nMeasurementSystem);
+    poFeature->SetField(HEADER_IMPULSE_SIGNAL_POLARITY, sBFH.nImpulseSignalPolarity);
+    poFeature->SetField(HEADER_VIBRATORY_POLARY_CODE, sBFH.nVibratoryPolaryCode);
+    poFeature->SetField(HEADER_SEGY_REVISION_NUMBER, sBFH.nSEGYRevisionNumber);
+    poFeature->SetField(HEADER_FLOAT_SEGY_REVISION_NUMBER, sBFH.dfSEGYRevisionNumber);
+    poFeature->SetField(HEADER_FIXED_LENGTH_TRACE_FLAG, sBFH.nFixedLengthTraceFlag);
+    poFeature->SetField(HEADER_NUMBER_OF_EXTENDED_TEXTUAL_FILE_HEADER, sBFH.nNumberOfExtendedTextualFileHeader);
+
+    return poFeature;
+}
diff --git a/ogr/ogrsf_frmts/segy/segy.txt b/ogr/ogrsf_frmts/segy/segy.txt
new file mode 100644
index 0000000..91d706d
--- /dev/null
+++ b/ogr/ogrsf_frmts/segy/segy.txt
@@ -0,0 +1,30 @@
+http://sioseis.ucsd.edu/segy.header.html
+http://www.seg.org/documents/10161/77915/seg_y_rev1.pdf
+
+http://gdr.nrcan.gc.ca/seismtlitho/archive/le/stacks_e.php
+http://apps1.gdr.nrcan.gc.ca/lithoprobe/le/ld0077_file_080.sgy
+
+http://segymat.sourceforge.net/segypy/
+http://www.cg.nrcan.gc.ca/lith_arch/stacks/ksz/ld0057_file_00095.sgy --> ko
+http://apps1.gdr.nrcan.gc.ca/lithoprobe/ksz/ld0057_file_00095.sgy
+
+http://utam.gg.utah.edu/SeismicData/SeismicData.html
+http://utam.gg.utah.edu/SeismicData/NewMont/Acsg.segy
+http://utam.gg.utah.edu/SeismicData/WFault3D/WD_3D.sgy
+
+http://www.syqwestinc.com/stratabox/stratabox%20data%20download/index.htm
+http://www.syqwestinc.com/stratabox/stratabox%20data%20download/20060113100958-1.zip
+
+http://www.syqwestinc.com/B2010/data%20download/index.htm
+http://www.syqwestinc.com/B2010/data%20download/20071121142735_CH1_35P.zip
+
+http://software.seg.org/datasets/2D/Hess_VTI/
+ftp://software.seg.org/pub/datasets/2D/Hess_VTI/timodel_c11.segy.gz
+
+http://www.segy.ca/segy/examples/ --> non standard formats. Do not work with OGR SEGY driver
+
+http://wush.net/trac/geocraft/browser/geoscience_data/trunk/saltmodel
+http://wush.net/trac/geocraft/export/12564/geoscience_data/trunk/saltmodel/SeisSaltDepth20m5km.segy
+http://wush.net/trac/geocraft/export/12564/geoscience_data/trunk/abavo/test_data3far.segy
+
+g++ -fPIC -g -Wall ogr/ogrsf_frmts/segy/*.cpp -shared -o ogr_SEGY.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/segy -L. -lgdal
diff --git a/ogr/ogrsf_frmts/shape/dbfopen.c b/ogr/ogrsf_frmts/shape/dbfopen.c
index 2554905..fbe7b06 100644
--- a/ogr/ogrsf_frmts/shape/dbfopen.c
+++ b/ogr/ogrsf_frmts/shape/dbfopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dbfopen.c,v 1.84 2009-10-29 19:59:48 fwarmerdam Exp $
+ * $Id: dbfopen.c,v 1.89 2011-07-24 05:59:25 fwarmerdam Exp $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of .dbf access API documented in dbf_api.html.
@@ -34,6 +34,21 @@
  ******************************************************************************
  *
  * $Log: dbfopen.c,v $
+ * Revision 1.89  2011-07-24 05:59:25  fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.88  2011-05-13 17:35:17  fwarmerdam
+ * added DBFReorderFields() and DBFAlterFields() functions (from Even)
+ *
+ * Revision 1.87  2011-05-07 22:41:02  fwarmerdam
+ * ensure pending record is flushed when adding a native field (GDAL #4073)
+ *
+ * Revision 1.86  2011-04-17 15:15:29  fwarmerdam
+ * Removed unused variable.
+ *
+ * Revision 1.85  2010-12-06 16:09:34  fwarmerdam
+ * fix buffer read overrun fetching code page (bug 2276)
+ *
  * Revision 1.84  2009-10-29 19:59:48  fwarmerdam
  * avoid crash on truncated header (gdal #3093)
  *
@@ -148,7 +163,7 @@
 #include <ctype.h>
 #include <string.h>
 
-SHP_CVSID("$Id: dbfopen.c,v 1.84 2009-10-29 19:59:48 fwarmerdam Exp $")
+SHP_CVSID("$Id: dbfopen.c,v 1.89 2011-07-24 05:59:25 fwarmerdam Exp $")
 
 #ifndef FALSE
 #  define FALSE		0
@@ -259,14 +274,10 @@ static int DBFFlushRecord( DBFHandle psDBF )
                                      psDBF->nRecordLength, 
                                      1, psDBF->fp ) != 1 )
         {
-#ifdef USE_CPL
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Failure writing DBF record %d.", 
-                      psDBF->nCurrentRecord );
-#else           
-            fprintf( stderr, "Failure writing DBF record %d.", 
+            char szMessage[128];
+            sprintf( szMessage, "Failure writing DBF record %d.", 
                      psDBF->nCurrentRecord );
-#endif
+            psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
     }
@@ -293,28 +304,20 @@ static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
 
 	if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
         {
-#ifdef USE_CPL
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "fseek(%ld) failed on DBF file.\n",
-                      (long) nRecordOffset );
-#else
-            fprintf( stderr, "fseek(%ld) failed on DBF file.\n",
+            char szMessage[128];
+            sprintf( szMessage, "fseek(%ld) failed on DBF file.\n",
                      (long) nRecordOffset );
-#endif
+            psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
 
 	if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord, 
                                  psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
         {
-#ifdef USE_CPL
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "fread(%d) failed on DBF file.\n",
-                      psDBF->nRecordLength );
-#else
-            fprintf( stderr, "fread(%d) failed on DBF file.\n",
+            char szMessage[128];
+            sprintf( szMessage, "fread(%d) failed on DBF file.\n",
                      psDBF->nRecordLength );
-#endif
+            psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
 
@@ -491,8 +494,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     if( pfCPG )
     {
         size_t n;
-        char *buffer = (char *) pabyBuf;
-        buffer[0] = '\0';
+        memset( pabyBuf, 0, nBufSize);
         psDBF->sHooks.FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
         n = strcspn( (char *) pabyBuf, "\n\r" );
         if( n > 0 )
@@ -779,6 +781,26 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
 }
 
 /************************************************************************/
+/*                        DBFGetNullCharacter()                         */
+/************************************************************************/
+
+static char DBFGetNullCharacter(char chType)
+{
+    switch (chType)
+    {
+      case 'N':
+      case 'F':
+        return '*';
+      case 'D':
+        return '0';
+      case 'L':
+       return '?';
+      default:
+       return ' ';
+    }
+}
+
+/************************************************************************/
 /*                            DBFAddField()                             */
 /*                                                                      */
 /*      Add a field to a newly created .dbf file before any records     */
@@ -797,6 +819,10 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     char        chFieldFill;
     SAOffset    nRecordOffset;
 
+    /* make sure that everything is written in .dbf */
+    if( !DBFFlushRecord( psDBF ) )
+        return -1;
+
 /* -------------------------------------------------------------------- */
 /*      Do some checking to ensure we can add records to this file.     */
 /* -------------------------------------------------------------------- */
@@ -884,22 +910,7 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     /* alloc record */
     pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
 
-    switch (chType)
-    {
-      case 'N':
-      case 'F':
-        chFieldFill = '*';
-        break;
-      case 'D':
-        chFieldFill = '0';
-        break;
-      case 'L':
-       chFieldFill = '?';
-       break;
-      default:
-       chFieldFill = ' ';
-       break;
-    }
+    chFieldFill = DBFGetNullCharacter(chType);
 
     for (i = psDBF->nRecords-1; i >= 0; --i)
     {
@@ -926,6 +937,9 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     psDBF->bNoHeader = TRUE;
     DBFUpdateHeader( psDBF );
 
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
     return( psDBF->nFields-1 );
 }
 
@@ -1082,34 +1096,28 @@ DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
     return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
 }
 
+
 /************************************************************************/
-/*                         DBFIsAttributeNULL()                         */
+/*                         DBFIsValueNULL()                             */
 /*                                                                      */
-/*      Return TRUE if value for field is NULL.                         */
-/*                                                                      */
-/*      Contributed by Jim Matthews.                                    */
+/*      Return TRUE if the passed string is NULL.                       */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
-
+static int DBFIsValueNULL( char chType, const char* pszValue )
 {
-    const char	*pszValue;
     int i;
 
-    pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
-
     if( pszValue == NULL )
         return TRUE;
 
-    switch(psDBF->pachFieldType[iField])
+    switch(chType)
     {
       case 'N':
       case 'F':
         /*
-        ** We accept all asterisks or all blanks as NULL 
-        ** though according to the spec I think it should be all 
-        ** asterisks. 
+        ** We accept all asterisks or all blanks as NULL
+        ** though according to the spec I think it should be all
+        ** asterisks.
         */
         if( pszValue[0] == '*' )
             return TRUE;
@@ -1126,7 +1134,7 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
         return strncmp(pszValue,"00000000",8) == 0;
 
       case 'L':
-        /* NULL boolean fields have value "?" */ 
+        /* NULL boolean fields have value "?" */
         return pszValue[0] == '?';
 
       default:
@@ -1136,6 +1144,28 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
 }
 
 /************************************************************************/
+/*                         DBFIsAttributeNULL()                         */
+/*                                                                      */
+/*      Return TRUE if value for field is NULL.                         */
+/*                                                                      */
+/*      Contributed by Jim Matthews.                                    */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    const char	*pszValue;
+
+    pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+
+    if( pszValue == NULL )
+        return TRUE;
+
+    return DBFIsValueNULL( psDBF->pachFieldType[iField], pszValue );
+}
+
+/************************************************************************/
 /*                          DBFGetFieldCount()                          */
 /*                                                                      */
 /*      Return the number of fields in this table.                      */
@@ -1266,33 +1296,9 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 /* -------------------------------------------------------------------- */
     if( pValue == NULL )
     {
-        switch(psDBF->pachFieldType[iField])
-        {
-          case 'N':
-          case 'F':
-	    /* NULL numeric fields have value "****************" */
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*', 
-                    psDBF->panFieldSize[iField] );
-            break;
-
-          case 'D':
-	    /* NULL date fields have value "00000000" */
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0', 
-                    psDBF->panFieldSize[iField] );
-            break;
-
-          case 'L':
-	    /* NULL boolean fields have value "?" */ 
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?', 
-                    psDBF->panFieldSize[iField] );
-            break;
-
-          default:
-            /* empty string fields are considered NULL */
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), ' ', 
-                    psDBF->panFieldSize[iField] );
-            break;
-        }
+        memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]),
+                DBFGetNullCharacter(psDBF->pachFieldType[iField]),
+                psDBF->panFieldSize[iField] );
         return TRUE;
     }
 
@@ -1831,7 +1837,7 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     psDBF->nRecordLength -= nDeletedFieldSize;
 
     /* overwrite field information in header */
-    memcpy(psDBF->pszHeader + iField*32,
+    memmove(psDBF->pszHeader + iField*32,
            psDBF->pszHeader + (iField+1)*32,
            sizeof(char) * (psDBF->nFields - iField)*32);
 
@@ -1879,5 +1885,337 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     /* free record */
     free(pszRecord);
 
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          DBFReorderFields()                          */
+/*                                                                      */
+/*      Reorder the fields of a .dbf file                               */
+/*                                                                      */
+/* panMap must be exactly psDBF->nFields long and be a permutation      */
+/* of [0, psDBF->nFields-1]. This assumption will not be asserted in the*/
+/* code of DBFReorderFields.                                            */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFReorderFields( DBFHandle psDBF, int* panMap )
+{
+    SAOffset nRecordOffset;
+    int      i, iRecord;
+    int     *panFieldOffsetNew;
+    int     *panFieldSizeNew;
+    int     *panFieldDecimalsNew;
+    char    *pachFieldTypeNew;
+    char    *pszHeaderNew;
+    char    *pszRecord;
+    char    *pszRecordNew;
+
+    if ( psDBF->nFields == 0 )
+        return TRUE;
+
+    /* make sure that everything is written in .dbf */
+    if( !DBFFlushRecord( psDBF ) )
+        return FALSE;
+
+    panFieldOffsetNew = (int *) malloc(sizeof(int) * psDBF->nFields);
+    panFieldSizeNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
+    panFieldDecimalsNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
+    pachFieldTypeNew = (char *) malloc(sizeof(char) *  psDBF->nFields);
+    pszHeaderNew = (char*) malloc(sizeof(char) * 32 *  psDBF->nFields);
+
+    /* shuffle fields definitions */
+    for(i=0; i < psDBF->nFields; i++)
+    {
+        panFieldSizeNew[i] = psDBF->panFieldSize[panMap[i]];
+        panFieldDecimalsNew[i] = psDBF->panFieldDecimals[panMap[i]];
+        pachFieldTypeNew[i] = psDBF->pachFieldType[panMap[i]];
+        memcpy(pszHeaderNew + i * 32,
+               psDBF->pszHeader + panMap[i] * 32, 32);
+    }
+    panFieldOffsetNew[0] = 1;
+    for(i=1; i < psDBF->nFields; i++)
+    {
+        panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
+    }
+
+    free(psDBF->pszHeader);
+    psDBF->pszHeader = pszHeaderNew;
+
+    /* we're done if we're dealing with not yet created .dbf */
+    if ( !(psDBF->bNoHeader && psDBF->nRecords == 0) )
+    {
+        /* force update of header with new header and record length */
+        psDBF->bNoHeader = TRUE;
+        DBFUpdateHeader( psDBF );
+
+        /* alloc record */
+        pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+        pszRecordNew = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+
+        /* shuffle fields in records */
+        for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+        {
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* load record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FRead( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+            pszRecordNew[0] = pszRecord[0];
+
+            for(i=0; i < psDBF->nFields; i++)
+            {
+                memcpy(pszRecordNew + panFieldOffsetNew[i],
+                       pszRecord + psDBF->panFieldOffset[panMap[i]],
+                       psDBF->panFieldSize[panMap[i]]);
+            }
+
+            /* write record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( pszRecordNew, psDBF->nRecordLength, 1, psDBF->fp );
+        }
+
+        /* free record */
+        free(pszRecord);
+        free(pszRecordNew);
+    }
+
+    free(psDBF->panFieldOffset);
+    free(psDBF->panFieldSize);
+    free(psDBF->panFieldDecimals);
+    free(psDBF->pachFieldType);
+
+    psDBF->panFieldOffset = panFieldOffsetNew;
+    psDBF->panFieldSize = panFieldSizeNew;
+    psDBF->panFieldDecimals =panFieldDecimalsNew;
+    psDBF->pachFieldType = pachFieldTypeNew;
+
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                          DBFAlterFieldDefn()                         */
+/*                                                                      */
+/*      Alter a field definition in a .dbf file                         */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
+                    char chType, int nWidth, int nDecimals )
+{
+    int   i;
+    int   iRecord;
+    int   nOffset;
+    int   nOldWidth;
+    int   nOldRecordLength;
+    int   nRecordOffset;
+    char* pszFInfo;
+    char  chOldType;
+    int   bIsNULL;
+    char chFieldFill;
+
+    if (iField < 0 || iField >= psDBF->nFields)
+        return FALSE;
+
+    /* make sure that everything is written in .dbf */
+    if( !DBFFlushRecord( psDBF ) )
+        return FALSE;
+
+    chFieldFill = DBFGetNullCharacter(chType);
+
+    chOldType = psDBF->pachFieldType[iField];
+    nOffset = psDBF->panFieldOffset[iField];
+    nOldWidth = psDBF->panFieldSize[iField];
+    nOldRecordLength = psDBF->nRecordLength;
+
+/* -------------------------------------------------------------------- */
+/*      Do some checking to ensure we can add records to this file.     */
+/* -------------------------------------------------------------------- */
+    if( nWidth < 1 )
+        return -1;
+
+    if( nWidth > 255 )
+        nWidth = 255;
+
+/* -------------------------------------------------------------------- */
+/*      Assign the new field information fields.                        */
+/* -------------------------------------------------------------------- */
+    psDBF->panFieldSize[iField] = nWidth;
+    psDBF->panFieldDecimals[iField] = nDecimals;
+    psDBF->pachFieldType[iField] = chType;
+
+/* -------------------------------------------------------------------- */
+/*      Update the header information.                                  */
+/* -------------------------------------------------------------------- */
+    pszFInfo = psDBF->pszHeader + 32 * iField;
+
+    for( i = 0; i < 32; i++ )
+        pszFInfo[i] = '\0';
+
+    if( (int) strlen(pszFieldName) < 10 )
+        strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
+    else
+        strncpy( pszFInfo, pszFieldName, 10);
+
+    pszFInfo[11] = psDBF->pachFieldType[iField];
+
+    if( chType == 'C' )
+    {
+        pszFInfo[16] = (unsigned char) (nWidth % 256);
+        pszFInfo[17] = (unsigned char) (nWidth / 256);
+    }
+    else
+    {
+        pszFInfo[16] = (unsigned char) nWidth;
+        pszFInfo[17] = (unsigned char) nDecimals;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Update offsets                                                  */
+/* -------------------------------------------------------------------- */
+    if (nWidth != nOldWidth)
+    {
+        for (i = iField + 1; i < psDBF->nFields; i++)
+             psDBF->panFieldOffset[i] += nWidth - nOldWidth;
+        psDBF->nRecordLength += nWidth - nOldWidth;
+
+        psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+                                                     psDBF->nRecordLength);
+    }
+
+    /* we're done if we're dealing with not yet created .dbf */
+    if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+        return TRUE;
+
+    /* force update of header with new header and record length */
+    psDBF->bNoHeader = TRUE;
+    DBFUpdateHeader( psDBF );
+
+    if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
+    {
+        char* pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
+        char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+
+        pszOldField[nOldWidth] = 0;
+
+        /* move records to their new positions */
+        for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+        {
+            nRecordOffset =
+                nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* load record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+            memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
+            bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+
+            if (nWidth != nOldWidth)
+            {
+                if ((chOldType == 'N' || chOldType == 'F') && pszOldField[0] == ' ')
+                {
+                    /* Strip leading spaces when truncating a numeric field */
+                    memmove( pszRecord + nOffset,
+                            pszRecord + nOffset + nOldWidth - nWidth,
+                            nWidth );
+                }
+                if (nOffset + nOldWidth < nOldRecordLength)
+                {
+                    memmove( pszRecord + nOffset + nWidth,
+                            pszRecord + nOffset + nOldWidth,
+                            nOldRecordLength - (nOffset + nOldWidth));
+                }
+            }
+
+            /* Convert null value to the appropriate value of the new type */
+            if (bIsNULL)
+            {
+                memset( pszRecord + nOffset, chFieldFill, nWidth);
+            }
+
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* write record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+        }
+
+        free(pszRecord);
+        free(pszOldField);
+    }
+    else if (nWidth > nOldWidth)
+    {
+        char* pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+        char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+
+        pszOldField[nOldWidth] = 0;
+
+        /* move records to their new positions */
+        for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
+        {
+            nRecordOffset =
+                nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* load record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+            memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
+            bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+
+            if (nOffset + nOldWidth < nOldRecordLength)
+            {
+                memmove( pszRecord + nOffset + nWidth,
+                         pszRecord + nOffset + nOldWidth,
+                         nOldRecordLength - (nOffset + nOldWidth));
+            }
+
+            /* Convert null value to the appropriate value of the new type */
+            if (bIsNULL)
+            {
+                memset( pszRecord + nOffset, chFieldFill, nWidth);
+            }
+            else
+            {
+                if ((chOldType == 'N' || chOldType == 'F'))
+                {
+                    /* Add leading spaces when expanding a numeric field */
+                    memmove( pszRecord + nOffset + nWidth - nOldWidth,
+                             pszRecord + nOffset, nOldWidth );
+                    memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
+                }
+                else
+                {
+                    /* Add trailing spaces */
+                    memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
+                }
+            }
+
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* write record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+        }
+
+        free(pszRecord);
+        free(pszOldField);
+    }
+
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
     return TRUE;
 }
diff --git a/ogr/ogrsf_frmts/shape/drv_shapefile.html b/ogr/ogrsf_frmts/shape/drv_shapefile.html
index 25c0a8c..e69974d 100644
--- a/ogr/ogrsf_frmts/shape/drv_shapefile.html
+++ b/ogr/ogrsf_frmts/shape/drv_shapefile.html
@@ -26,7 +26,7 @@ The same applies for SHPT_POLYGON shapefiles, reported as layers of type
 wkbPolygon, but depending on the number of parts of each geometry, the
 actual type can be either OGRPolygon or OGRMultiPolygon.</p>
 
-<p>The new ESRI measure values are discarded if encountered.  MultiPatch 
+<p>ESRI measure values (XYM) are read as XYZ geometries. MultiPatch
 files are read and each patch geometry is turned into a multi-polygon 
 representation with one polygon per triangle in triangle fans and meshes.</p>
 
@@ -42,6 +42,14 @@ analysis based on topological relationships of the parts of the polygons so
 that the resulting polygons are correctly
 defined in the OGC Simple Feature convention. </p>
 
+<p>An attempt is made to read the LDID/codepage setting from the .dbf file 
+and use it to translate string fields to UTF-8 on read, and back when writing.
+LDID "87 / 0x57" is treated as ISO8859_1 which may not be appropriate.  
+The SHAPE_ENCODING <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">
+configuration option</a> may be used to override the encoding interpretation
+of the shapefile with any encoding supported by CPLRecode or to "" to avoid
+any recoding. (Recoding support is new for GDAL/OGR 1.9.0)</p>
+
 <h2>Spatial and Attribute Indexing</h2>
 
 <p>The OGR Shapefile driver supports spatial indexing and a limited form of
@@ -147,6 +155,18 @@ the .dbf file, and then ignored by OGR.  To actually remove them permanently
 (resulting in renumbering of FIDs) invoke the SQL 'REPACK <tablename>' via
 the datasource ExecuteSQL() method.</p>
 
+<h2>Spatial extent</h2>
+
+<p>Shapefiles store the layer spatial extent in the .SHP file. The layer spatial extent
+is automatically updated when inserting a new feature in a shapefile. However when
+updating an existing feature, if its previous shape was touching the bounding box of the
+layer extent but the updated shape does not touch the new extent, the computed extent
+will not be correct. It is then necessary to force a recomputation by invoking the
+SQL 'RECOMPUTE EXTENT ON <tablename>' via the datasource ExecuteSQL() method. The
+same applies for the deletion of a shape.</p>
+
+<p>Note: RECOMPUTE EXTENT ON is available in OGR >= 1.9.0.</p>
+
 <h2>Size Issues</h2>
 
 <p>Geometry: The Shapefile format explicitly uses 32bit offsets and so cannot
@@ -169,8 +189,17 @@ NULL for a simple .dbf file with no .shp file,
  POINT, ARC, POLYGON or MULTIPOINT for 2D, or 
 POINTZ, ARCZ, POLYGONZ or MULTIPOINTZ for 3D.  Shapefiles with <i>measure</i>
 values are not supported, nor are MULTIPATCH files.</li>
+
+<li> <b>ENCODING=</b><i>value</i>: set the encoding value in the DBF file. The
+default value is "LDID/87".  It is not clear what other values may be
+appropriate.</li>
 </ul>
 
+<h3>VSI Virtual File System API support</h3>
+
+The driver supports reading from files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsizip/, /vsigzip/ , /vsicurl/ domains.<p>
+
 <h3>Examples</h3>
 
 <p>A merge of two shapefiles 'file1.shp' and 'file2.shp' into a new file
diff --git a/ogr/ogrsf_frmts/shape/ogrshape.h b/ogr/ogrsf_frmts/shape/ogrshape.h
index 68126b1..6e26b82 100644
--- a/ogr/ogrsf_frmts/shape/ogrshape.h
+++ b/ogr/ogrsf_frmts/shape/ogrshape.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshape.h 21257 2010-12-14 20:23:13Z rouault $
+ * $Id: ogrshape.h 23534 2011-12-11 22:35:51Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the Shapefile driver to implement
@@ -39,21 +39,27 @@
 /* ==================================================================== */
 OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                                OGRFeatureDefn * poDefn, int iShape, 
-                               SHPObject *psShape );
+                               SHPObject *psShape, const char *pszSHPEncoding );
 OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape );
 OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
-                                       SHPHandle hSHP, DBFHandle hDBF );
+                                       SHPHandle hSHP, DBFHandle hDBF,
+                                       const char *pszSHPEncoding );
 OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                            OGRFeatureDefn *poFeatureDefn,
-                           OGRFeature *poFeature );
+                           OGRFeature *poFeature, const char *pszSHPEncoding,
+                           int* pbTruncationWarningEmitted );
 
 /************************************************************************/
 /*                            OGRShapeLayer                             */
 /************************************************************************/
 
+class OGRShapeDataSource;
+
 class OGRShapeLayer : public OGRLayer
 {
-    OGRSpatialReference *poSRS;
+    OGRShapeDataSource  *poDS;
+    OGRSpatialReference *poSRS; /* lazy loaded --> use GetSpatialRef() */
+    int                 bSRSSet;
     OGRFeatureDefn     *poFeatureDefn;
     int                 iNextShapeId;
     int                 nTotalShapeCount;
@@ -76,29 +82,55 @@ class OGRShapeLayer : public OGRLayer
     int                 bHeaderDirty;
 
     int                 bCheckedForQIX;
-    FILE                *fpQIX;
+    SHPTreeDiskHandle   hQIX;
 
     int                 CheckForQIX();
 
     int                 bSbnSbxDeleted;
 
+    CPLString           ConvertCodePage( const char * );
+    CPLString           osEncoding;
+
+    int                 bTruncationWarningEmitted;
+
+    int                 bHSHPWasNonNULL; /* to know if we must try to reopen a .shp */
+    int                 bHDBFWasNonNULL; /* to know if we must try to reopen a .dbf */
+    int                 eFileDescriptorsState; /* current state of opening of file descriptor to .shp and .dbf */
+    int                 TouchLayer();
+    int                 ReopenFileDescriptors();
+
+/* WARNING: each of the below public methods should start with a call to */
+/* TouchLayer() and test its return value, so as to make sure that */
+/* the layer is properly re-opened if necessary */
+
   public:
     OGRErr              CreateSpatialIndex( int nMaxDepth );
     OGRErr              DropSpatialIndex();
     OGRErr              Repack();
+    OGRErr              RecomputeExtent();
 
     const char         *GetFullName() { return pszFullName; }
 
+    void                CloseFileDescriptors();
+
+    /* The 2 following members should not be used by OGRShapeLayer, except */
+    /* in its constructor */
+    OGRShapeLayer      *poPrevLayer; /* Chain to a layer that was used more recently */
+    OGRShapeLayer      *poNextLayer; /* Chain to a layer that was used less recently */
+
+    OGRFeature *        FetchShape(int iShapeId);
+    int                 GetFeatureCountWithSpatialFilterOnly();
+
   public:
-                        OGRShapeLayer( const char * pszName,
+                        OGRShapeLayer( OGRShapeDataSource* poDSIn,
+                                       const char * pszName,
                                        SHPHandle hSHP, DBFHandle hDBF,
-                                       OGRSpatialReference *poSRS,
+                                       OGRSpatialReference *poSRS, int bSRSSet,
                                        int bUpdate, 
                                        OGRwkbGeometryType eReqType );
                         ~OGRShapeLayer();
 
     void                ResetReading();
-    OGRFeature *        FetchShape(int iShapeId);
     OGRFeature *        GetNextFeature();
     virtual OGRErr      SetNextByIndex( long nIndex );
 
@@ -115,10 +147,14 @@ class OGRShapeLayer : public OGRLayer
 
     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 OGRSpatialReference *GetSpatialRef();
     
     int                 TestCapability( const char * );
+
 };
 
 /************************************************************************/
@@ -136,6 +172,12 @@ class OGRShapeDataSource : public OGRDataSource
 
     int                 bSingleFileDataSource;
 
+    OGRShapeLayer      *poMRULayer; /* the most recently used layer */
+    OGRShapeLayer      *poLRULayer; /* the least recently used layer (still opened) */
+    int                 nMRUListSize; /* the size of the list */
+
+    void                AddLayer(OGRShapeLayer* poLayer);
+
   public:
                         OGRShapeDataSource();
                         ~OGRShapeDataSource();
@@ -159,6 +201,9 @@ class OGRShapeDataSource : public OGRDataSource
 
     virtual int          TestCapability( const char * );
     virtual OGRErr       DeleteLayer( int iLayer );
+
+    void                 SetLastUsedLayer( OGRShapeLayer* poLayer );
+    void                 UnchainLayer( OGRShapeLayer* poLayer );
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
index cae1527..2b9aa78 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapedatasource.cpp 21257 2010-12-14 20:23:13Z rouault $
+ * $Id: ogrshapedatasource.cpp 23526 2011-12-11 12:16:27Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeDataSource class.
@@ -31,7 +31,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrshapedatasource.cpp 21257 2010-12-14 20:23:13Z rouault $");
+#define MAX_SIMULTANEOUSLY_OPENED_LAYERS    100
+
+CPL_CVSID("$Id: ogrshapedatasource.cpp 23526 2011-12-11 12:16:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRShapeDataSource()                         */
@@ -44,6 +46,10 @@ OGRShapeDataSource::OGRShapeDataSource()
     papoLayers = NULL;
     nLayers = 0;
     bSingleFileDataSource = FALSE;
+
+    poMRULayer = NULL;
+    poLRULayer = NULL;
+    nMRUListSize = 0;
 }
 
 /************************************************************************/
@@ -61,6 +67,10 @@ OGRShapeDataSource::~OGRShapeDataSource()
 
         delete papoLayers[i];
     }
+
+    CPLAssert( poMRULayer == NULL );
+    CPLAssert( poLRULayer == NULL );
+    CPLAssert( nMRUListSize == 0 );
     
     CPLFree( papoLayers );
 }
@@ -291,7 +301,43 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
     if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") )
     {
         if( bUpdate )
+        {
             hDBF = 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 )
+                {
+                    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");
+                    if( VSIStatExL( pszDBFName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
+                    {
+                        fp = VSIFOpenL(pszDBFName, "r+");
+                        if (fp == NULL)
+                        {
+                            CPLError( CE_Failure, CPLE_OpenFailed,
+                                    "%s exists, but cannot be opened in update mode",
+                                    pszDBFName );
+                            return FALSE;
+                        }
+                    }
+                }
+                if (fp != NULL)
+                    VSIFCloseL(fp);
+            }
+        }
         else
             hDBF = DBFOpen( pszNewName, "r" );
     }
@@ -302,56 +348,42 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
         return FALSE;
 
 /* -------------------------------------------------------------------- */
-/*      Is there an associated .prj file we can read?                   */
-/* -------------------------------------------------------------------- */
-    OGRSpatialReference *poSRS = NULL;
-    const char  *pszPrjFile = CPLResetExtension( pszNewName, "prj" );
-    VSILFILE        *fp = NULL;
-
-    fp = VSIFOpenL( pszPrjFile, "r" );
-
-    if( NULL == fp )
-    {
-        pszPrjFile = CPLResetExtension( pszNewName, "PRJ" );
-        fp = VSIFOpenL( pszPrjFile, "r" );
-    }
-
-    if( fp != NULL )
-    {
-        char    **papszLines;
-
-        VSIFCloseL( fp );
-        
-        papszLines = CSLLoad( pszPrjFile );
-
-        poSRS = new OGRSpatialReference();
-        if( poSRS->importFromESRI( papszLines ) != OGRERR_NONE )
-        {
-            delete poSRS;
-            poSRS = NULL;
-        }
-        CSLDestroy( papszLines );
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
     OGRShapeLayer       *poLayer;
 
-    poLayer = new OGRShapeLayer( pszNewName, hSHP, hDBF, poSRS, bUpdate,
+    poLayer = new OGRShapeLayer( this, pszNewName, hSHP, hDBF, NULL, FALSE, bUpdate,
                                  wkbNone );
 
-
-    poLayer->InitializeIndexSupport( pszNewName );
-
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
+    AddLayer(poLayer);
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                             AddLayer()                               */
+/************************************************************************/
+
+void OGRShapeDataSource::AddLayer(OGRShapeLayer* poLayer)
+{
     papoLayers = (OGRShapeLayer **)
         CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
     papoLayers[nLayers++] = poLayer;
-    
-    return TRUE;
+
+    /* If we reach the limit, then register all the already opened layers */
+    /* Technically this code would not be necessary if there was not the */
+    /* following initial test in SetLastUsedLayer() : */
+    /*      if (nLayers < MAX_SIMULTANEOUSLY_OPENED_LAYERS) */
+    /*         return; */
+    if (nLayers == MAX_SIMULTANEOUSLY_OPENED_LAYERS && nMRUListSize == 0)
+    {
+        for(int i=0;i<nLayers;i++)
+            SetLastUsedLayer(papoLayers[i]);
+    }
 }
 
 /************************************************************************/
@@ -479,9 +511,10 @@ OGRShapeDataSource::CreateLayer( const char * pszLayerName,
         nShapeType = SHPT_MULTIPOINTZ;
         eType = wkbMultiPoint25D;
     }
-    else if( EQUAL(pszOverride,"NONE") )
+    else if( EQUAL(pszOverride,"NONE") || EQUAL(pszOverride,"NULL") )
     {
         nShapeType = SHPT_NULL;
+        eType = wkbNone;
     }
     else
     {
@@ -559,11 +592,19 @@ OGRShapeDataSource::CreateLayer( const char * pszLayerName,
         hSHP = NULL;
 
 /* -------------------------------------------------------------------- */
+/*      Has a specific LDID been specified by the caller?               */
+/* -------------------------------------------------------------------- */
+    const char *pszLDID = CSLFetchNameValue( papszOptions, "ENCODING" );
+
+/* -------------------------------------------------------------------- */
 /*      Create a DBF file.                                              */
 /* -------------------------------------------------------------------- */
     pszFilename = CPLStrdup(CPLFormFilename( NULL, pszBasename, "dbf" ));
-    
-    hDBF = DBFCreate( pszFilename );
+
+    if( pszLDID != NULL )
+        hDBF = DBFCreateEx( pszFilename, pszLDID );
+    else
+        hDBF = DBFCreate( pszFilename );
 
     if( hDBF == NULL )
     {
@@ -608,20 +649,15 @@ OGRShapeDataSource::CreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     OGRShapeLayer       *poLayer;
 
-    poLayer = new OGRShapeLayer( pszBasename, hSHP, hDBF, poSRS, TRUE,
+    poLayer = new OGRShapeLayer( this, pszBasename, hSHP, hDBF, poSRS, TRUE, TRUE,
                                  eType );
-    
-    poLayer->InitializeIndexSupport( pszBasename );
 
     CPLFree( pszBasename );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
-    papoLayers = (OGRShapeLayer **)
-        CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
-    
-    papoLayers[nLayers++] = poLayer;
+    AddLayer(poLayer);
 
     return poLayer;
 }
@@ -663,6 +699,7 @@ OGRLayer *OGRShapeDataSource::GetLayer( int iLayer )
 /*        CREATE SPATIAL INDEX ON layer_name [DEPTH n]                  */
 /*        DROP SPATIAL INDEX ON layer_name                              */
 /*        REPACK layer_name                                             */
+/*        RECOMPUTE EXTENT ON layer_name                                */
 /************************************************************************/
 
 OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
@@ -690,6 +727,25 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
     }
     
 /* ==================================================================== */
+/*      Handle command to recompute extent                             */
+/* ==================================================================== */
+    if( EQUALN(pszStatement, "RECOMPUTE EXTENT ON ", 20) )
+    {
+        OGRShapeLayer *poLayer = (OGRShapeLayer *) 
+            GetLayerByName( pszStatement + 20 );
+
+        if( poLayer != NULL )
+            poLayer->RecomputeExtent();
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, 
+                      "No such layer as '%s' in RECOMPUTE EXTENT.", 
+                      pszStatement + 20 );
+        }
+        return NULL;
+    }
+    
+/* ==================================================================== */
 /*      Handle command to drop a spatial index.                         */
 /* ==================================================================== */
     if( EQUALN(pszStatement, "DROP SPATIAL INDEX ON ", 22) )
@@ -712,8 +768,22 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /*      Handle all comands except spatial index creation generically.   */
 /* ==================================================================== */
     if( !EQUALN(pszStatement,"CREATE SPATIAL INDEX ON ",24) )
+    {
+        char **papszTokens = CSLTokenizeString( pszStatement );
+        if( CSLCount(papszTokens) >=4
+            && (EQUAL(papszTokens[0],"CREATE") || EQUAL(papszTokens[0],"DROP"))
+            && EQUAL(papszTokens[1],"INDEX")
+            && EQUAL(papszTokens[2],"ON") )
+        {
+            OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[3]);
+            if (poLayer != NULL)
+                poLayer->InitializeIndexSupport( poLayer->GetFullName() );
+        }
+        CSLDestroy( papszTokens );
+
         return OGRDataSource::ExecuteSQL( pszStatement, poSpatialFilter, 
                                           pszDialect );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Parse into keywords.                                            */
@@ -748,16 +818,18 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /*      What layer are we operating on.                                 */
 /* -------------------------------------------------------------------- */
     OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[4]);
-    CSLDestroy( papszTokens );
 
     if( poLayer == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Layer %s not recognised.", 
                   papszTokens[4] );
+        CSLDestroy( papszTokens );
         return NULL;
     }
 
+    CSLDestroy( papszTokens );
+
     poLayer->CreateSpatialIndex( nDepth );
     return NULL;
 }
@@ -793,9 +865,11 @@ OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
         return OGRERR_FAILURE;
     }
 
-    pszFilename = CPLStrdup(((OGRShapeLayer*) papoLayers[iLayer])->GetFullName());
+    OGRShapeLayer* poLayerToDelete = (OGRShapeLayer*) papoLayers[iLayer];
 
-    delete papoLayers[iLayer];
+    pszFilename = CPLStrdup(poLayerToDelete->GetFullName());
+
+    delete poLayerToDelete;
 
     while( iLayer < nLayers - 1 )
     {
@@ -815,3 +889,97 @@ OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
 
     return OGRERR_NONE;
 }
+
+/************************************************************************/
+/*                          SetLastUsedLayer()                          */
+/************************************************************************/
+
+void OGRShapeDataSource::SetLastUsedLayer( OGRShapeLayer* poLayer )
+{
+    /* We could remove that check and things would still work in */
+    /* 99.99% cases */
+    /* The only rationale for that test is to avoid breaking applications */
+    /* that would deal with layers of the same datasource in different */
+    /* threads. In GDAL < 1.9.0, this would work in most cases I can */
+    /* imagine as shapefile layers are pretty much independant from each */
+    /* others (although it has never been guaranteed to be a valid use case, */
+    /* and the shape driver is likely more the exception than the rule in */
+    /* permitting accessing layers from different threads !) */
+    /* Anyway the LRU list mechanism leaves the door open to concurrent accesses to it */
+    /* so when the datasource has not many layers, we don't try to build the */
+    /* LRU list to avoid concurrency issues. I haven't bothered making the analysis */
+    /* of how a mutex could be used to protect that (my intuition is that it would */
+    /* need to be placed at the beginning of OGRShapeLayer::TouchLayer() ) */
+    if (nLayers < MAX_SIMULTANEOUSLY_OPENED_LAYERS)
+        return;
+
+    /* If we are already the MRU layer, nothing to do */
+    if (poLayer == poMRULayer)
+        return;
+
+    //CPLDebug("SHAPE", "SetLastUsedLayer(%s)", poLayer->GetName());
+
+    if (poLayer->poPrevLayer != NULL || poLayer->poNextLayer != NULL)
+    {
+        /* Remove current layer from its current place in the list */
+        UnchainLayer(poLayer);
+    }
+    else if (nMRUListSize == MAX_SIMULTANEOUSLY_OPENED_LAYERS)
+    {
+        /* If we have reached the maximum allowed number of layers */
+        /* simultaneously opened, then close the LRU one that */
+        /* was still active until now */
+        CPLAssert(poLRULayer != NULL);
+
+        poLRULayer->CloseFileDescriptors();
+        UnchainLayer(poLRULayer);
+    }
+
+    /* Put current layer on top of MRU list */
+    CPLAssert(poLayer->poPrevLayer == NULL);
+    CPLAssert(poLayer->poNextLayer == NULL);
+    poLayer->poNextLayer = poMRULayer;
+    if (poMRULayer != NULL)
+    {
+        CPLAssert(poMRULayer->poPrevLayer == NULL);
+        poMRULayer->poPrevLayer = poLayer;
+    }
+    poMRULayer = poLayer;
+    if (poLRULayer == NULL)
+        poLRULayer = poLayer;
+    nMRUListSize ++;
+}
+
+
+/************************************************************************/
+/*                            UnchainLayer()                            */
+/*                                                                      */
+/* Remove the layer from the MRU list                                   */
+/************************************************************************/
+
+void OGRShapeDataSource::UnchainLayer( OGRShapeLayer* poLayer )
+{
+    //CPLDebug("SHAPE", "UnchainLayer(%s)", poLayer->GetName());
+
+    OGRShapeLayer* poPrevLayer = poLayer->poPrevLayer;
+    OGRShapeLayer* poNextLayer = poLayer->poNextLayer;
+
+    if (poPrevLayer != NULL)
+        CPLAssert(poPrevLayer->poNextLayer == poLayer);
+    if (poNextLayer != NULL)
+        CPLAssert(poNextLayer->poPrevLayer == poLayer);
+
+    if (poPrevLayer != NULL || poNextLayer != NULL || poLayer == poMRULayer)
+        nMRUListSize --;
+
+    if (poLayer == poMRULayer)
+        poMRULayer = poNextLayer;
+    if (poLayer == poLRULayer)
+        poLRULayer = poPrevLayer;
+    if (poPrevLayer != NULL)
+        poPrevLayer->poNextLayer = poNextLayer;
+    if (poNextLayer != NULL)
+        poNextLayer->poPrevLayer = poPrevLayer;
+    poLayer->poPrevLayer = NULL;
+    poLayer->poNextLayer = NULL;
+}
diff --git a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
index a3b2401..174b2dc 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapelayer.cpp 20885 2010-10-19 00:16:08Z warmerdam $
+ * $Id: ogrshapelayer.cpp 23555 2011-12-12 20:30:46Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeLayer class.
@@ -30,24 +30,33 @@
 #include "ogrshape.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_p.h"
 
 #if defined(_WIN32_WCE)
 #  include <wce_errno.h>
 #endif
 
-CPL_CVSID("$Id: ogrshapelayer.cpp 20885 2010-10-19 00:16:08Z warmerdam $");
+#define FD_OPENED           0
+#define FD_CLOSED           1
+#define FD_CANNOT_REOPEN    2
+
+CPL_CVSID("$Id: ogrshapelayer.cpp 23555 2011-12-12 20:30:46Z rouault $");
 
 /************************************************************************/
 /*                           OGRShapeLayer()                            */
 /************************************************************************/
 
-OGRShapeLayer::OGRShapeLayer( const char * pszName,
+OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
+                              const char * pszName,
                               SHPHandle hSHPIn, DBFHandle hDBFIn, 
-                              OGRSpatialReference *poSRSIn, int bUpdate,
+                              OGRSpatialReference *poSRSIn, int bSRSSetIn,
+                              int bUpdate,
                               OGRwkbGeometryType eReqType )
 
 {
+    poDS = poDSIn;
     poSRS = poSRSIn;
+    bSRSSet = bSRSSetIn;
 
     pszFullName = CPLStrdup(pszName);
     
@@ -59,21 +68,54 @@ OGRShapeLayer::OGRShapeLayer( const char * pszName,
     panMatchingFIDs = NULL;
 
     bCheckedForQIX = FALSE;
-    fpQIX = NULL;
+    hQIX = NULL;
 
     bSbnSbxDeleted = FALSE;
 
     bHeaderDirty = FALSE;
 
     if( hSHP != NULL )
+    {
         nTotalShapeCount = hSHP->nRecords;
+        if( hDBF != NULL && hDBF->nRecords != nTotalShapeCount )
+        {
+            CPLDebug("Shape", "Inconsistant record number in .shp (%d) and in .dbf (%d)",
+                     hSHP->nRecords, hDBF->nRecords);
+        }
+    }
     else 
         nTotalShapeCount = hDBF->nRecords;
     
-    poFeatureDefn = SHPReadOGRFeatureDefn( CPLGetBasename(pszName), 
-                                           hSHP, hDBF );
-
     eRequestedGeomType = eReqType;
+
+    bTruncationWarningEmitted = FALSE;
+
+    
+    if( hDBF != NULL && hDBF->pszCodePage != NULL )
+    {
+        CPLDebug( "Shape", "DBF Codepage = %s for %s", 
+                  hDBF->pszCodePage, pszName );
+
+        // Not too sure about this, but it seems like better than nothing.
+        osEncoding = ConvertCodePage( hDBF->pszCodePage );
+    }
+    
+    if( CPLGetConfigOption( "SHAPE_ENCODING", NULL ) != NULL )
+        osEncoding = CPLGetConfigOption( "SHAPE_ENCODING", "" );
+
+    if( osEncoding != "" )
+        CPLDebug( "Shape", "Treating as encoding '%s'.", osEncoding.c_str() );
+
+    poFeatureDefn = SHPReadOGRFeatureDefn( CPLGetBasename(pszName),
+                                           hSHP, hDBF, osEncoding );
+
+    /* Init info for the LRU layer mechanism */
+    poPrevLayer = NULL;
+    poNextLayer = NULL;
+    bHSHPWasNonNULL = hSHPIn != NULL;
+    bHDBFWasNonNULL = hDBFIn != NULL;
+    eFileDescriptorsState = FD_OPENED;
+    TouchLayer();
 }
 
 /************************************************************************/
@@ -83,6 +125,9 @@ OGRShapeLayer::OGRShapeLayer( const char * pszName,
 OGRShapeLayer::~OGRShapeLayer()
 
 {
+    /* Remove us from the list of LRU layers if necessary */
+    poDS->UnchainLayer(this);
+
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Shape", "%d features read on layer '%s'.",
@@ -107,8 +152,121 @@ OGRShapeLayer::~OGRShapeLayer()
     if( hSHP != NULL )
         SHPClose( hSHP );
 
-    if( fpQIX != NULL )
-        VSIFClose( fpQIX );
+    if( hQIX != NULL )
+        SHPCloseDiskTree( hQIX );
+}
+
+/************************************************************************/
+/*                          ConvertCodePage()                           */
+/************************************************************************/
+
+CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage )
+
+{
+    CPLString osEncoding;
+
+    if( pszCodePage == NULL )
+        return osEncoding;
+
+    if( EQUALN(pszCodePage,"LDID/",5) )
+    {
+        int nCP = -1; // windows code page. 
+
+        //http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM
+        switch( atoi(pszCodePage+5) )
+        {
+          case 1: nCP = 437;      break;
+          case 2: nCP = 850;      break;
+          case 3: nCP = 1252;     break;
+          case 4: nCP = 10000;    break;
+          case 8: nCP = 865;      break;
+          case 10: nCP = 850;     break;
+          case 11: nCP = 437;     break;
+          case 13: nCP = 437;     break;
+          case 14: nCP = 850;     break;
+          case 15: nCP = 437;     break;
+          case 16: nCP = 850;     break;
+          case 17: nCP = 437;     break;
+          case 18: nCP = 850;     break;
+          case 19: nCP = 932;     break;
+          case 20: nCP = 850;     break;
+          case 21: nCP = 437;     break;
+          case 22: nCP = 850;     break;
+          case 23: nCP = 865;     break;
+          case 24: nCP = 437;     break;
+          case 25: nCP = 437;     break;
+          case 26: nCP = 850;     break;
+          case 27: nCP = 437;     break;
+          case 28: nCP = 863;     break;
+          case 29: nCP = 850;     break;
+          case 31: nCP = 852;     break;
+          case 34: nCP = 852;     break;
+          case 35: nCP = 852;     break;
+          case 36: nCP = 860;     break;
+          case 37: nCP = 850;     break;
+          case 38: nCP = 866;     break;
+          case 55: nCP = 850;     break;
+          case 64: nCP = 852;     break;
+          case 77: nCP = 936;     break;
+          case 78: nCP = 949;     break;
+          case 79: nCP = 950;     break;
+          case 80: nCP = 874;     break;
+          case 87: return CPL_ENC_ISO8859_1;
+          case 88: nCP = 1252;     break;
+          case 89: nCP = 1252;     break;
+          case 100: nCP = 852;     break;
+          case 101: nCP = 866;     break;
+          case 102: nCP = 865;     break;
+          case 103: nCP = 861;     break;
+          case 104: nCP = 895;     break;
+          case 105: nCP = 620;     break;
+          case 106: nCP = 737;     break;
+          case 107: nCP = 857;     break;
+          case 108: nCP = 863;     break;
+          case 120: nCP = 950;     break;
+          case 121: nCP = 949;     break;
+          case 122: nCP = 936;     break;
+          case 123: nCP = 932;     break;
+          case 124: nCP = 874;     break;
+          case 134: nCP = 737;     break;
+          case 135: nCP = 852;     break;
+          case 136: nCP = 857;     break;
+          case 150: nCP = 10007;   break;
+          case 151: nCP = 10029;   break;
+          case 200: nCP = 1250;    break;
+          case 201: nCP = 1251;    break;
+          case 202: nCP = 1254;    break;
+          case 203: nCP = 1253;    break;
+          case 204: nCP = 1257;    break;
+          default: break;
+        }
+
+        if( nCP != -1 )
+        {
+            osEncoding.Printf( "CP%d", nCP );
+            return osEncoding;
+        }
+    }
+
+    // From the CPG file
+    // http://resources.arcgis.com/fr/content/kbase?fa=articleShow&d=21106
+    
+    if( (atoi(pszCodePage) >= 437 && atoi(pszCodePage) <= 950)
+        || (atoi(pszCodePage) >= 1250 && atoi(pszCodePage) <= 1258) )
+    {
+        osEncoding.Printf( "CP%d", atoi(pszCodePage) );
+        return osEncoding;
+    }
+    if( EQUALN(pszCodePage,"8859",4) )
+    {
+        osEncoding.Printf( "ISO%s", pszCodePage );
+        return osEncoding;
+    }
+    if( EQUALN(pszCodePage,"UTF-8",5) )
+        return CPL_ENC_UTF8;
+
+    // try just using the CPG value directly.  Works for stuff like Big5.
+    return pszCodePage;
 }
 
 /************************************************************************/
@@ -121,15 +279,15 @@ int OGRShapeLayer::CheckForQIX()
     const char *pszQIXFilename;
 
     if( bCheckedForQIX )
-        return fpQIX != NULL;
+        return hQIX != NULL;
 
     pszQIXFilename = CPLResetExtension( pszFullName, "qix" );
 
-    fpQIX = VSIFOpen( pszQIXFilename, "rb" );
+    hQIX = SHPOpenDiskTree( pszQIXFilename, NULL ); 
 
     bCheckedForQIX = TRUE;
 
-    return fpQIX != NULL;
+    return hQIX != NULL;
 }
 
 /************************************************************************/
@@ -150,6 +308,9 @@ int OGRShapeLayer::ScanIndices()
     if( m_poAttrQuery != NULL )
     {
         CPLAssert( panMatchingFIDs == NULL );
+
+        InitializeIndexSupport( pszFullName );
+
         panMatchingFIDs = m_poAttrQuery->EvaluateAgainstIndices( this,
                                                                  NULL );
     }
@@ -157,19 +318,31 @@ int OGRShapeLayer::ScanIndices()
 /* -------------------------------------------------------------------- */
 /*      Check for spatial index if we have a spatial query.             */
 /* -------------------------------------------------------------------- */
+
+    OGREnvelope oEnvelope;
+    if( m_poFilterGeom != NULL )
+    {
+        m_poFilterGeom->getEnvelope( &oEnvelope );
+
+        OGREnvelope oLayerExtent;
+        if (GetExtent(&oLayerExtent, TRUE) == OGRERR_NONE &&
+            oEnvelope.Contains(oLayerExtent))
+        {
+            // The spatial filter is larger than the layer extent. No use of .qix file for now
+            return TRUE;
+        }
+    }
+
     if( m_poFilterGeom != NULL && !bCheckedForQIX )
         CheckForQIX();
 
 /* -------------------------------------------------------------------- */
 /*      Utilize spatial index if appropriate.                           */
 /* -------------------------------------------------------------------- */
-    if( m_poFilterGeom && fpQIX )
+    if( m_poFilterGeom && hQIX )
     {
         int nSpatialFIDCount, *panSpatialFIDs;
         double adfBoundsMin[4], adfBoundsMax[4];
-        OGREnvelope oEnvelope;
-
-        m_poFilterGeom->getEnvelope( &oEnvelope );
 
         adfBoundsMin[0] = oEnvelope.MinX;
         adfBoundsMin[1] = oEnvelope.MinY;
@@ -180,7 +353,7 @@ int OGRShapeLayer::ScanIndices()
         adfBoundsMax[2] = 0.0;
         adfBoundsMax[3] = 0.0;
 
-        panSpatialFIDs = SHPSearchDiskTree( fpQIX, 
+        panSpatialFIDs = SHPSearchDiskTreeEx( hQIX,
                                             adfBoundsMin, adfBoundsMax, 
                                             &nSpatialFIDCount );
         CPLDebug( "SHAPE", "Used spatial index, got %d matches.", 
@@ -236,6 +409,9 @@ int OGRShapeLayer::ScanIndices()
 void OGRShapeLayer::ResetReading()
 
 {
+    if (!TouchLayer())
+        return;
+
 /* -------------------------------------------------------------------- */
 /*      Clear previous index search result, if any.                     */
 /* -------------------------------------------------------------------- */
@@ -259,6 +435,9 @@ void OGRShapeLayer::ResetReading()
 OGRErr OGRShapeLayer::SetNextByIndex( long nIndex )
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     // Eventually we should try to use panMatchingFIDs list 
     // if available and appropriate. 
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
@@ -287,13 +466,18 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId)
         
         psShape = SHPReadObject( hSHP, iShapeId );
 
-        // do not trust degenerate bounds or bounds on null shapes.
-        if( psShape == NULL || psShape->dfXMin == psShape->dfXMax
-            || psShape->dfYMin == psShape->dfYMax 
+        // do not trust degenerate bounds on non-point geometries
+        // or bounds on null shapes.
+        if( psShape == NULL
+            || (psShape->nSHPType != SHPT_POINT
+                && psShape->nSHPType != SHPT_POINTZ
+                && psShape->nSHPType != SHPT_POINTM
+                && (psShape->dfXMin == psShape->dfXMax
+                 || psShape->dfYMin == psShape->dfYMax))
             || psShape->nSHPType == SHPT_NULL )
         {
             poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
-                                           iShapeId, psShape );
+                                           iShapeId, psShape, osEncoding );
         }
         else if( m_sFilterEnvelope.MaxX < psShape->dfXMin 
                  || m_sFilterEnvelope.MaxY < psShape->dfYMin
@@ -306,13 +490,13 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId)
         else 
         {
             poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
-                                           iShapeId, psShape );
+                                           iShapeId, psShape, osEncoding );
         }                
     } 
     else 
     {
         poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
-                                       iShapeId, NULL );
+                                       iShapeId, NULL, osEncoding );
     }    
     
     return poFeature;
@@ -325,6 +509,9 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId)
 OGRFeature *OGRShapeLayer::GetNextFeature()
 
 {
+    if (!TouchLayer())
+        return NULL;
+
     OGRFeature  *poFeature = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -363,27 +550,33 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
             {
                 return NULL;
             }
-    
-            if ( hDBF && DBFIsRecordDeleted( hDBF, iNextShapeId ) ) {
-                poFeature = NULL;
-            } else {
-                // Check the shape object's geometry, and if it matches
-                // any spatial filter, return it.  
-                poFeature = FetchShape(iNextShapeId);
+
+            if( hDBF )
+            {
+                if (DBFIsRecordDeleted( hDBF, iNextShapeId ))
+                    poFeature = NULL;
+                else if( VSIFEofL((VSILFILE*)hDBF->fp) )
+                    return NULL; /* There's an I/O error */
+                else
+                    poFeature = FetchShape(iNextShapeId);
             }
+            else
+                poFeature = FetchShape(iNextShapeId);
+
             iNextShapeId++;
         }
         
         if( poFeature != NULL )
         {
-            if( poFeature->GetGeometryRef() != NULL )
+            OGRGeometry* poGeom = poFeature->GetGeometryRef();
+            if( poGeom != NULL )
             {
-                poFeature->GetGeometryRef()->assignSpatialReference( poSRS );
+                poGeom->assignSpatialReference( GetSpatialRef() );
             }
 
             m_nFeaturesRead++;
 
-            if( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) )
+            if( (m_poFilterGeom == NULL || FilterGeometry( poGeom ) )
                 && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) )
             {
                 return poFeature;
@@ -391,12 +584,7 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 
             delete poFeature;
         }
-    }        
-
-    /*
-     * NEVER SHOULD GET HERE
-     */
-    CPLAssert(!"OGRShapeLayer::GetNextFeature(): Execution never should get here!");
+    }
 }
 
 /************************************************************************/
@@ -406,13 +594,19 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 OGRFeature *OGRShapeLayer::GetFeature( long nFeatureId )
 
 {
+    if (!TouchLayer())
+        return NULL;
+
     OGRFeature *poFeature = NULL;
-    poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn, nFeatureId, NULL);
+    poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn, nFeatureId, NULL,
+                                   osEncoding );
 
     if( poFeature != NULL )
     {
         if( poFeature->GetGeometryRef() != NULL )
-            poFeature->GetGeometryRef()->assignSpatialReference( poSRS );
+        {
+            poFeature->GetGeometryRef()->assignSpatialReference( GetSpatialRef() );
+        }
 
         m_nFeaturesRead++;
     
@@ -432,10 +626,13 @@ OGRFeature *OGRShapeLayer::GetFeature( long nFeatureId )
 OGRErr OGRShapeLayer::SetFeature( OGRFeature *poFeature )
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     if( !bUpdateAccess )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-            "The SetFeature() operation is not permitted on a read-only shapefile." );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "The SetFeature() operation is not permitted on a read-only shapefile." );
         return OGRERR_FAILURE;
     }
 
@@ -443,7 +640,8 @@ OGRErr OGRShapeLayer::SetFeature( OGRFeature *poFeature )
     if( CheckForQIX() )
         DropSpatialIndex();
 
-    return SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature );
+    return SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature,
+                               osEncoding, &bTruncationWarningEmitted );
 }
 
 /************************************************************************/
@@ -453,10 +651,13 @@ OGRErr OGRShapeLayer::SetFeature( OGRFeature *poFeature )
 OGRErr OGRShapeLayer::DeleteFeature( long nFID )
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     if( !bUpdateAccess )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
-            "The DeleteFeature() operation is not permitted on a read-only shapefile." );
+                  "The DeleteFeature() operation is not permitted on a read-only shapefile." );
         return OGRERR_FAILURE;
     }
 
@@ -506,10 +707,13 @@ OGRErr OGRShapeLayer::CreateFeature( OGRFeature *poFeature )
 {
     OGRErr eErr;
 
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     if( !bUpdateAccess )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
-            "The CreateFeature() operation is not permitted on a read-only shapefile." );
+                  "The CreateFeature() operation is not permitted on a read-only shapefile." );
         return OGRERR_FAILURE;
     }
 
@@ -583,7 +787,8 @@ OGRErr OGRShapeLayer::CreateFeature( OGRFeature *poFeature )
         }
     }
     
-    eErr = SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature );
+    eErr = SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature, 
+                               osEncoding, &bTruncationWarningEmitted );
 
     if( hSHP != NULL )
         nTotalShapeCount = hSHP->nRecords;
@@ -594,28 +799,266 @@ OGRErr OGRShapeLayer::CreateFeature( OGRFeature *poFeature )
 }
 
 /************************************************************************/
-/*                          GetFeatureCount()                           */
+/*               GetFeatureCountWithSpatialFilterOnly()                 */
 /*                                                                      */
-/*      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.              */
+/* Specialized implementation of GetFeatureCount() when there is *only* */
+/* a spatial filter and no attribute filter.                            */
+/************************************************************************/
+
+int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
+
+{
+/* -------------------------------------------------------------------- */
+/*      Collect a matching list if we have attribute or spatial         */
+/*      indices.  Only do this on the first request for a given pass    */
+/*      of course.                                                      */
+/* -------------------------------------------------------------------- */
+    if( panMatchingFIDs == NULL )
+    {
+        ScanIndices();
+    }
+
+    int nFeatureCount = 0;
+    int iLocalMatchingFID = 0;
+    int iLocalNextShapeId = 0;
+    int bExpectPoints = FALSE;
+
+    if (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbPoint)
+        bExpectPoints = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Loop till we find a feature matching our criteria.              */
+/* -------------------------------------------------------------------- */
+
+    SHPObject sShape;
+    memset(&sShape, 0, sizeof(sShape));
+
+    VSILFILE* fpSHP = (VSILFILE*) hSHP->fpSHP;
+
+    while( TRUE )
+    {
+        SHPObject* psShape = NULL;
+        int iShape = -1;
+
+        if( panMatchingFIDs != NULL )
+        {
+            iShape = panMatchingFIDs[iLocalMatchingFID];
+            if( iShape == OGRNullFID )
+                break;
+            iLocalMatchingFID++;
+        }
+        else
+        {
+            if( iLocalNextShapeId >= nTotalShapeCount )
+                break;
+            iShape = iLocalNextShapeId ++;
+
+            if( hDBF )
+            {
+                if (DBFIsRecordDeleted( hDBF, iShape ))
+                    continue;
+
+                if (VSIFEofL((VSILFILE*)hDBF->fp))
+                    break;
+            }
+        }
+
+        /* Read full shape for point layers */
+        if (bExpectPoints)
+            psShape = SHPReadObject( hSHP, iShape);
+
+/* -------------------------------------------------------------------- */
+/*      Only read feature type and bounding box for now. In case of     */
+/*      inconclusive tests on bounding box only, we will read the full  */
+/*      shape later.                                                    */
+/* -------------------------------------------------------------------- */
+        else if (iShape >= 0 && iShape < hSHP->nRecords &&
+                    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 )
+            {
+                memcpy(&(sShape.nSHPType), abyBuf, 4);
+                CPL_LSBPTR32(&(sShape.nSHPType));
+                if ( sShape.nSHPType != SHPT_NULL &&
+                        sShape.nSHPType != SHPT_POINT &&
+                        sShape.nSHPType != SHPT_POINTM &&
+                        sShape.nSHPType != SHPT_POINTZ)
+                {
+                    psShape = &sShape;
+                    memcpy(&(sShape.dfXMin), abyBuf + 4, 8);
+                    memcpy(&(sShape.dfYMin), abyBuf + 12, 8);
+                    memcpy(&(sShape.dfXMax), abyBuf + 20, 8);
+                    memcpy(&(sShape.dfYMax), abyBuf + 28, 8);
+                    CPL_MSBPTR32(&(sShape.dfXMin));
+                    CPL_MSBPTR32(&(sShape.dfYMin));
+                    CPL_MSBPTR32(&(sShape.dfXMax));
+                    CPL_MSBPTR32(&(sShape.dfYMax));
+                }
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        if( psShape != NULL && psShape->nSHPType != SHPT_NULL )
+        {
+            OGRGeometry* poGeometry = NULL;
+            OGREnvelope sGeomEnv;
+            /* Test if we have a degenerated bounding box */
+            if (psShape->nSHPType != SHPT_POINT
+                && psShape->nSHPType != SHPT_POINTZ
+                && psShape->nSHPType != SHPT_POINTM
+                && (psShape->dfXMin == psShape->dfXMax
+                    || psShape->dfYMin == psShape->dfYMax))
+            {
+                /* We need to read the full geometry */
+                /* to compute the envelope */
+                if (psShape == &sShape)
+                    psShape = SHPReadObject( hSHP, iShape);
+                if (psShape)
+                {
+                    poGeometry = SHPReadOGRObject( hSHP, iShape, psShape );
+                    poGeometry->getEnvelope( &sGeomEnv );
+                    psShape = NULL;
+                }
+            }
+            else
+            {
+                /* Trust the shape bounding box as the shape envelope */
+                sGeomEnv.MinX = psShape->dfXMin;
+                sGeomEnv.MinY = psShape->dfYMin;
+                sGeomEnv.MaxX = psShape->dfXMax;
+                sGeomEnv.MaxY = psShape->dfYMax;
+            }
+
+/* -------------------------------------------------------------------- */
+/*      If there is no                                                  */
+/*      intersection between the envelopes we are sure not to have      */
+/*      any intersection.                                               */
+/* -------------------------------------------------------------------- */
+            if( sGeomEnv.MaxX < m_sFilterEnvelope.MinX
+                || sGeomEnv.MaxY < m_sFilterEnvelope.MinY
+                || m_sFilterEnvelope.MaxX < sGeomEnv.MinX
+                || m_sFilterEnvelope.MaxY < sGeomEnv.MinY )
+            {
+            }
+/* -------------------------------------------------------------------- */
+/*      If the filter geometry is its own envelope and if the           */
+/*      envelope of the geometry is inside the filter geometry,         */
+/*      the geometry itself is inside the filter geometry               */
+/* -------------------------------------------------------------------- */
+            else if( m_bFilterIsEnvelope &&
+                sGeomEnv.MinX >= m_sFilterEnvelope.MinX &&
+                sGeomEnv.MinY >= m_sFilterEnvelope.MinY &&
+                sGeomEnv.MaxX <= m_sFilterEnvelope.MaxX &&
+                sGeomEnv.MaxY <= m_sFilterEnvelope.MaxY)
+            {
+                nFeatureCount ++;
+            }
+            else
+            {
+/* -------------------------------------------------------------------- */
+/*      Fallback to full intersect test (using GEOS) if we still        */
+/*      don't know for sure.                                            */
+/* -------------------------------------------------------------------- */
+                if( OGRGeometryFactory::haveGEOS() )
+                {
+                    /* We need to read the full geometry */
+                    if (poGeometry == NULL)
+                    {
+                        if (psShape == &sShape)
+                            psShape = SHPReadObject( hSHP, iShape);
+                        if (psShape)
+                        {
+                            poGeometry =
+                                SHPReadOGRObject( hSHP, iShape, psShape );
+                            psShape = NULL;
+                        }
+                    }
+                    if( poGeometry == NULL ||
+                        m_poFilterGeom->Intersects( poGeometry ) )
+                        nFeatureCount ++;
+                }
+                else
+                    nFeatureCount ++;
+            }
+
+            delete poGeometry;
+        }
+        else
+            nFeatureCount ++;
+
+        if (psShape && psShape != &sShape)
+            SHPDestroyObject( psShape );
+    }
+
+    return nFeatureCount;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
 /************************************************************************/
 
 int OGRShapeLayer::GetFeatureCount( int bForce )
 
 {
-    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
-        return OGRLayer::GetFeatureCount( bForce );
+    /* Check if the spatial filter is non-trivial */
+    int bHasTrivialSpatialFilter;
+    if (m_poFilterGeom != NULL)
+    {
+        OGREnvelope oEnvelope;
+        m_poFilterGeom->getEnvelope( &oEnvelope );
+
+        OGREnvelope oLayerExtent;
+        if (GetExtent(&oLayerExtent, TRUE) == OGRERR_NONE &&
+            oEnvelope.Contains(oLayerExtent))
+        {
+            bHasTrivialSpatialFilter = TRUE;
+        }
+        else
+            bHasTrivialSpatialFilter = FALSE;
+    }
     else
+        bHasTrivialSpatialFilter = TRUE;
+
+
+    if( bHasTrivialSpatialFilter && m_poAttrQuery == NULL )
         return nTotalShapeCount;
+
+    if (!TouchLayer())
+        return 0;
+
+    /* Spatial filter only */
+    if( m_poAttrQuery == NULL && hSHP != NULL )
+    {
+        return GetFeatureCountWithSpatialFilterOnly();
+    }
+
+    /* Attribute filter only */
+    if( m_poAttrQuery != NULL )
+    {
+        /* Let's see if we can ignore reading geometries */
+        int bSaveGeometryIgnored = poFeatureDefn->IsGeometryIgnored();
+        if (!AttributeFilterEvaluationNeedsGeometry())
+            poFeatureDefn->SetGeometryIgnored(TRUE);
+
+        int nRet = OGRLayer::GetFeatureCount( bForce );
+
+        poFeatureDefn->SetGeometryIgnored(bSaveGeometryIgnored);
+        return nRet;
+    }
+
+    return OGRLayer::GetFeatureCount( bForce );
 }
 
 /************************************************************************/
 /*                             GetExtent()                              */
 /*                                                                      */
 /*      Fetch extent of the data currently stored in the dataset.       */
-/*      The bForce flag has no effect on SHO files since that value     */
+/*      The bForce flag has no effect on SHP files since that value     */
 /*      is always in the header.                                        */
 /*                                                                      */
 /*      Returns OGRERR_NONE/OGRRERR_FAILURE.                            */
@@ -626,6 +1069,9 @@ OGRErr OGRShapeLayer::GetExtent (OGREnvelope *psExtent, int bForce)
 {
     UNREFERENCED_PARAM( bForce );
 
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     double adMin[4], adMax[4];
 
     if( hSHP == NULL )
@@ -648,6 +1094,9 @@ OGRErr OGRShapeLayer::GetExtent (OGREnvelope *psExtent, int bForce)
 int OGRShapeLayer::TestCapability( const char * pszCap )
 
 {
+    if (!TouchLayer())
+        return FALSE;
+
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
@@ -672,10 +1121,22 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
 
     else if( EQUAL(pszCap,OLCCreateField) )
         return bUpdateAccess;
-    
+
+    else if( EQUAL(pszCap,OLCDeleteField) )
+        return bUpdateAccess;
+
+    else if( EQUAL(pszCap,OLCReorderFields) )
+        return bUpdateAccess;
+
+    else if( EQUAL(pszCap,OLCAlterFieldDefn) )
+        return bUpdateAccess;
+
     else if( EQUAL(pszCap,OLCIgnoreFields) )
         return TRUE;
 
+    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return strlen(osEncoding) > 0; /* if encoding is defined, we are able to convert to UTF-8 */
+
     else 
         return FALSE;
 }
@@ -687,6 +1148,9 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
 OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     CPLAssert( NULL != poFieldDefn );
     
     int         iNewField;
@@ -699,6 +1163,35 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
     }
 
+    int bDBFJustCreated = FALSE;
+    if( hDBF == NULL )
+    {
+        CPLString osFilename = CPLResetExtension( pszFullName, "dbf" );
+        hDBF = DBFCreate( osFilename );
+
+        if( hDBF == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Failed to create DBF file `%s'.\n",
+                      osFilename.c_str() );
+            return OGRERR_FAILURE;
+        }
+
+        bDBFJustCreated = TRUE;
+    }
+
+    if ( poFeatureDefn->GetFieldCount() == 255 )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Creating a 256th field, but some DBF readers might only support 255 fields" );
+    }
+    if ( hDBF->nHeaderLength + 32 > 65535 )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Cannot add more fields in DBF file.");
+        return OGRERR_FAILURE;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Normalize field name                                            */
 /* -------------------------------------------------------------------- */
@@ -709,7 +1202,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
     size_t nNameSize = strlen( poFieldDefn->GetNameRef() );
     pszTmp = CPLScanString( poFieldDefn->GetNameRef(),
-                                     MIN( nNameSize, 10) , TRUE, TRUE);
+                            MIN( nNameSize, 10) , TRUE, TRUE);
     strncpy(szNewFieldName, pszTmp, 10);
     szNewFieldName[10] = '\0';
 
@@ -755,87 +1248,245 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 /*      Add field to layer                                              */
 /* -------------------------------------------------------------------- */
 
-    if( oModFieldDefn.GetType() == OFTInteger )
+    char chType = 'C';
+    int nWidth = 0;
+    int nDecimals = 0;
+
+    switch( oModFieldDefn.GetType() )
     {
-        if( oModFieldDefn.GetWidth() == 0 )
-            iNewField =
-                DBFAddField( hDBF, oModFieldDefn.GetNameRef(), FTInteger, 10,0);
-        else
-            iNewField = DBFAddField( hDBF, oModFieldDefn.GetNameRef(), FTInteger,
-                                     oModFieldDefn.GetWidth(), 0 );
+        case OFTInteger:
+            chType = 'N';
+            nWidth = oModFieldDefn.GetWidth();
+            if (nWidth == 0) nWidth = 10;
+            break;
+
+        case OFTReal:
+            chType = 'N';
+            nWidth = oModFieldDefn.GetWidth();
+            nDecimals = oModFieldDefn.GetPrecision();
+            if (nWidth == 0)
+            {
+                nWidth = 24;
+                nDecimals = 15;
+            }
+            break;
+
+        case OFTString:
+            chType = 'C';
+            nWidth = oModFieldDefn.GetWidth();
+            if (nWidth == 0) nWidth = 80;
+            else if (nWidth > 255)
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                        "Field %s of width %d truncated to %d.",
+                        oModFieldDefn.GetNameRef(), nWidth, 255 );
+                nWidth = 255;
+            }
+            break;
+
+        case OFTDate:
+            chType = 'D';
+            nWidth = 8;
+            break;
+
+        case OFTDateTime:
+            CPLError( CE_Warning, CPLE_NotSupported,
+                    "Field %s create as date field, though DateTime requested.",
+                    oModFieldDefn.GetNameRef() );
+            chType = 'D';
+            nWidth = 8;
+            oModFieldDefn.SetType( OFTDate );
+            break;
 
-        if( iNewField != -1 )
-            poFeatureDefn->AddFieldDefn( &oModFieldDefn );
+        default:
+            CPLError( CE_Failure, CPLE_NotSupported,
+                    "Can't create fields of type %s on shapefile layers.",
+                    OGRFieldDefn::GetFieldTypeName(oModFieldDefn.GetType()) );
+
+            return OGRERR_FAILURE;
+            break;
     }
-    else if( oModFieldDefn.GetType() == OFTReal )
+
+    oModFieldDefn.SetWidth( nWidth );
+    oModFieldDefn.SetPrecision( nDecimals );
+
+    if ( hDBF->nRecordLength + nWidth > 65535 )
     {
-        if( oModFieldDefn.GetWidth() == 0 )
-            iNewField =
-                DBFAddField( hDBF, oModFieldDefn.GetNameRef(), FTDouble, 24, 15 );
-        else
-            iNewField =
-                DBFAddField( hDBF, oModFieldDefn.GetNameRef(), FTDouble,
-                             oModFieldDefn.GetWidth(), oModFieldDefn.GetPrecision() );
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't create field %s in Shape DBF file. "
+                  "Maximum record length reached.",
+                  oModFieldDefn.GetNameRef() );
+        return OGRERR_FAILURE;
+    }
+
+    iNewField =
+        DBFAddNativeFieldType( hDBF, oModFieldDefn.GetNameRef(),
+                               chType, nWidth, nDecimals );
+
+    if( iNewField != -1 )
+    {
+        poFeatureDefn->AddFieldDefn( &oModFieldDefn );
 
-        if( iNewField != -1 )
-            poFeatureDefn->AddFieldDefn( &oModFieldDefn );
+        if( bDBFJustCreated )
+        {
+            for(int i=0;i<nTotalShapeCount;i++)
+            {
+                DBFWriteNULLAttribute( hDBF, i, 0 );
+            }
+        }
+
+        return OGRERR_NONE;
     }
-    else if( oModFieldDefn.GetType() == OFTString )
+    else        
     {
-        if( oModFieldDefn.GetWidth() < 1 )
-            iNewField =
-                DBFAddField( hDBF, oModFieldDefn.GetNameRef(), FTString, 80, 0 );
-        else
-            iNewField = DBFAddField( hDBF, oModFieldDefn.GetNameRef(), FTString, 
-                                     oModFieldDefn.GetWidth(), 0 );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Can't create field %s in Shape DBF file, reason unknown.",
+                  oModFieldDefn.GetNameRef() );
 
-        if( iNewField != -1 )
-            poFeatureDefn->AddFieldDefn( &oModFieldDefn );
+        return OGRERR_FAILURE;
     }
-    else if( oModFieldDefn.GetType() == OFTDate )
+}
+
+/************************************************************************/
+/*                            DeleteField()                             */
+/************************************************************************/
+
+OGRErr OGRShapeLayer::DeleteField( int iField )
+{
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
+    if( !bUpdateAccess )
     {
-        iNewField =
-            DBFAddNativeFieldType( hDBF, oModFieldDefn.GetNameRef(), 'D', 8, 0 );
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't delete fields on a read-only shapefile layer.");
+        return OGRERR_FAILURE;
+    }
 
-        if( iNewField != -1 )
-            poFeatureDefn->AddFieldDefn( &oModFieldDefn );
+    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
     }
-    else if( oModFieldDefn.GetType() == OFTDateTime )
+
+    if ( DBFDeleteField( hDBF, iField ) )
     {
-        CPLError( CE_Warning, CPLE_NotSupported,
-                  "Field %s create as date field, though DateTime requested.\n",
-                  oModFieldDefn.GetNameRef() );
+        return poFeatureDefn->DeleteFieldDefn( iField );
+    }
+    else
+        return OGRERR_FAILURE;
+}
 
-        iNewField =
-            DBFAddNativeFieldType( hDBF, oModFieldDefn.GetNameRef(), 'D', 8, 0 );
+/************************************************************************/
+/*                           ReorderFields()                            */
+/************************************************************************/
 
-        if( iNewField != -1 )
-        {
-            oModFieldDefn.SetType( OFTDate );
-            poFeatureDefn->AddFieldDefn( &oModFieldDefn );
-        }
+OGRErr OGRShapeLayer::ReorderFields( int* panMap )
+{
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
+    if( !bUpdateAccess )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't reorder fields on a read-only shapefile layer.");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeatureDefn->GetFieldCount() == 0)
+        return OGRERR_NONE;
+
+    OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+    if ( DBFReorderFields( hDBF, panMap ) )
+    {
+        return poFeatureDefn->ReorderFieldDefns( panMap );
     }
     else
+        return OGRERR_FAILURE;
+}
+
+/************************************************************************/
+/*                           AlterFieldDefn()                           */
+/************************************************************************/
+
+OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+{
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
+    if( !bUpdateAccess )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Can't create fields of type %s on shapefile layers.\n",
-                  OGRFieldDefn::GetFieldTypeName(oModFieldDefn.GetType()) );
+                  "Can't alter field definition on a read-only shapefile layer.");
+        return OGRERR_FAILURE;
+    }
 
+    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
         return OGRERR_FAILURE;
     }
 
-    if( iNewField != -1 )
+    OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
+
+    char chNativeType;
+    char            szFieldName[20];
+    int             nWidth, nPrecision;
+    OGRFieldType    eType = poFieldDefn->GetType();
+    DBFFieldType    eDBFType;
+
+    chNativeType = DBFGetNativeFieldType( hDBF, iField );
+    eDBFType = DBFGetFieldInfo( hDBF, iField, szFieldName,
+                                &nWidth, &nPrecision );
+
+    if ((nFlags & ALTER_TYPE_FLAG) &&
+        poNewFieldDefn->GetType() != poFieldDefn->GetType())
     {
-        return OGRERR_NONE;
+        if (poNewFieldDefn->GetType() != OFTString)
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Can only convert to OFTString");
+            return OGRERR_FAILURE;
+        }
+        else
+        {
+            chNativeType = 'C';
+            eType = poNewFieldDefn->GetType();
+        }
     }
-    else        
+
+    if (nFlags & ALTER_NAME_FLAG)
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Can't create field %s in Shape DBF file, reason unknown.\n",
-                  oModFieldDefn.GetNameRef() );
+        strncpy(szFieldName, poNewFieldDefn->GetNameRef(), 10);
+        szFieldName[10] = '\0';
+    }
+    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    {
+        nWidth = poNewFieldDefn->GetWidth();
+        nPrecision = poNewFieldDefn->GetPrecision();
+    }
 
-        return OGRERR_FAILURE;
+    if ( DBFAlterFieldDefn( hDBF, iField, szFieldName,
+                            chNativeType, nWidth, nPrecision) )
+    {
+        if (nFlags & ALTER_TYPE_FLAG)
+            poFieldDefn->SetType(eType);
+        if (nFlags & ALTER_NAME_FLAG)
+            poFieldDefn->SetName(szFieldName);
+        if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+        {
+            poFieldDefn->SetWidth(nWidth);
+            poFieldDefn->SetPrecision(nPrecision);
+        }
+        return OGRERR_NONE;
     }
+    else
+        return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -845,6 +1496,36 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 OGRSpatialReference *OGRShapeLayer::GetSpatialRef()
 
 {
+    if (bSRSSet)
+        return poSRS;
+
+    bSRSSet = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Is there an associated .prj file we can read?                   */
+/* -------------------------------------------------------------------- */
+    const char  *pszPrjFile = CPLResetExtension( pszFullName, "prj" );
+    char    **papszLines;
+
+    char* apszOptions[] = { (char*)"EMIT_ERROR_IF_CANNOT_OPEN_FILE=FALSE", NULL };
+    papszLines = CSLLoad2( pszPrjFile, -1, -1, apszOptions );
+    if (papszLines == NULL)
+    {
+        pszPrjFile = CPLResetExtension( pszFullName, "PRJ" );
+        papszLines = CSLLoad2( pszPrjFile, -1, -1, apszOptions );
+    }
+
+    if( papszLines != NULL )
+    {
+        poSRS = new OGRSpatialReference();
+        if( poSRS->importFromESRI( papszLines ) != OGRERR_NONE )
+        {
+            delete poSRS;
+            poSRS = NULL;
+        }
+        CSLDestroy( papszLines );
+    }
+
     return poSRS;
 }
 
@@ -924,6 +1605,9 @@ int OGRShapeLayer::ResetGeomType( int nNewGeomType )
 OGRErr OGRShapeLayer::SyncToDisk()
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     if( bHeaderDirty )
     {
         if( hSHP != NULL )
@@ -955,6 +1639,9 @@ OGRErr OGRShapeLayer::SyncToDisk()
 OGRErr OGRShapeLayer::DropSpatialIndex()
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     if( !CheckForQIX() )
     {
         CPLError( CE_Warning, CPLE_AppDefined, 
@@ -963,8 +1650,8 @@ OGRErr OGRShapeLayer::DropSpatialIndex()
         return OGRERR_FAILURE;
     }
 
-    VSIFClose( fpQIX );
-    fpQIX = NULL;
+    SHPCloseDiskTree( hQIX );
+    hQIX = NULL;
     bCheckedForQIX = FALSE;
     
     const char *pszQIXFilename;
@@ -1010,6 +1697,9 @@ OGRErr OGRShapeLayer::DropSpatialIndex()
 OGRErr OGRShapeLayer::CreateSpatialIndex( int nMaxDepth )
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
 /* -------------------------------------------------------------------- */
 /*      If we have an existing spatial index, blow it away first.       */
 /* -------------------------------------------------------------------- */
@@ -1074,10 +1764,13 @@ OGRErr OGRShapeLayer::CreateSpatialIndex( int nMaxDepth )
 OGRErr OGRShapeLayer::Repack()
 
 {
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
     if( !bUpdateAccess )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
-            "The REPACK operation is not permitted on a read-only shapefile." );
+                  "The REPACK operation is not permitted on a read-only shapefile." );
         return OGRERR_FAILURE;
     }
     
@@ -1347,3 +2040,167 @@ OGRErr OGRShapeLayer::Repack()
 
     return OGRERR_NONE;
 }
+
+/************************************************************************/
+/*                        RecomputeExtent()                             */
+/*                                                                      */
+/*      Force recomputation of the extent of the .SHP file              */
+/************************************************************************/
+
+OGRErr OGRShapeLayer::RecomputeExtent()
+{
+    if (!TouchLayer())
+        return OGRERR_FAILURE;
+
+    if( !bUpdateAccess )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "The RECOMPUTE EXTENT operation is not permitted on a read-only shapefile." );
+        return OGRERR_FAILURE;
+    }
+    
+    if( hSHP == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "The RECOMPUTE EXTENT operation is not permitted on a layer without .SHP file." );
+        return OGRERR_FAILURE;
+    }
+    
+    double adBoundsMin[4] = { 0.0, 0.0, 0.0, 0.0 };
+    double adBoundsMax[4] = { 0.0, 0.0, 0.0, 0.0 };
+
+    int bHasBeenInit = FALSE;
+
+    for( int iShape = 0; 
+         iShape < nTotalShapeCount; 
+         iShape++ )
+    {
+        if( hDBF == NULL || !DBFIsRecordDeleted( hDBF, iShape ) )
+        {
+            SHPObject *psObject = SHPReadObject( hSHP, iShape );
+            if ( psObject != NULL &&
+                 psObject->nSHPType != SHPT_NULL &&
+                 psObject->nVertices != 0 )
+            {
+                if( !bHasBeenInit )
+                {
+                    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];
+                }
+
+                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]);
+                }
+            }
+            SHPDestroyObject(psObject);
+        }
+    }
+
+    if( memcmp(hSHP->adBoundsMin, adBoundsMin, 4*sizeof(double)) != 0 ||
+        memcmp(hSHP->adBoundsMax, adBoundsMax, 4*sizeof(double)) != 0 )
+    {
+        bHeaderDirty = TRUE;
+        hSHP->bUpdated = TRUE;
+        memcpy(hSHP->adBoundsMin, adBoundsMin, 4*sizeof(double));
+        memcpy(hSHP->adBoundsMax, adBoundsMax, 4*sizeof(double));
+    }
+    
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                              TouchLayer()                            */
+/************************************************************************/
+
+int OGRShapeLayer::TouchLayer()
+{
+    poDS->SetLastUsedLayer(this);
+
+    if (eFileDescriptorsState == FD_OPENED)
+        return TRUE;
+    else if (eFileDescriptorsState == FD_CANNOT_REOPEN)
+        return FALSE;
+    else
+        return ReopenFileDescriptors();
+}
+
+/************************************************************************/
+/*                        ReopenFileDescriptors()                       */
+/************************************************************************/
+
+int OGRShapeLayer::ReopenFileDescriptors()
+{
+    CPLDebug("SHAPE", "ReopenFileDescriptors(%s)", pszFullName);
+
+    if( bHSHPWasNonNULL )
+    {
+        if( bUpdateAccess )
+            hSHP = SHPOpen( pszFullName, "r+" );
+        else
+            hSHP = SHPOpen( pszFullName, "r" );
+
+        if (hSHP == NULL)
+        {
+            eFileDescriptorsState = FD_CANNOT_REOPEN;
+            return FALSE;
+        }
+    }
+
+    if( bHDBFWasNonNULL )
+    {
+        if( bUpdateAccess )
+            hDBF = DBFOpen( pszFullName, "r+" );
+        else
+            hDBF = DBFOpen( pszFullName, "r" );
+
+        if (hDBF == NULL)
+        {
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Cannot reopen %s", CPLResetExtension(pszFullName, "dbf"));
+            eFileDescriptorsState = FD_CANNOT_REOPEN;
+            return FALSE;
+        }
+    }
+
+    eFileDescriptorsState = FD_OPENED;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                        CloseFileDescriptors()                        */
+/************************************************************************/
+
+void OGRShapeLayer::CloseFileDescriptors()
+{
+    CPLDebug("SHAPE", "CloseFileDescriptors(%s)", pszFullName);
+
+    if( hDBF != NULL )
+        DBFClose( hDBF );
+    hDBF = NULL;
+
+    if( hSHP != NULL )
+        SHPClose( hSHP );
+    hSHP = NULL;
+
+    /* We close QIX and reset the check flag, so that CheckForQIX() */
+    /* will retry opening it if necessary when the layer is active again */
+    if( hQIX != NULL )
+        SHPCloseDiskTree( hQIX ); 
+    hQIX = NULL;
+    bCheckedForQIX = FALSE;
+
+    eFileDescriptorsState = FD_CLOSED;
+}
diff --git a/ogr/ogrsf_frmts/shape/shape2ogr.cpp b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
index b06d3c0..67d886a 100644
--- a/ogr/ogrsf_frmts/shape/shape2ogr.cpp
+++ b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shape2ogr.cpp 22348 2011-05-10 18:45:05Z rouault $
+ * $Id: shape2ogr.cpp 23599 2011-12-19 00:54:21Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements translation of Shapefile shapes into OGR
@@ -31,7 +31,7 @@
 #include "ogrshape.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: shape2ogr.cpp 22348 2011-05-10 18:45:05Z rouault $");
+CPL_CVSID("$Id: shape2ogr.cpp 23599 2011-12-19 00:54:21Z warmerdam $");
 
 /************************************************************************/
 /*                        RingStartEnd                                  */
@@ -59,7 +59,7 @@ static void RingStartEnd ( SHPObject *psShape, int ring, int *start, int *end )
 /*                        CreateLinearRing                              */
 /*                                                                      */
 /************************************************************************/
-static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring )
+static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring, int bHasZ )
 {
     OGRLinearRing *poRing;
     int nRingStart, nRingEnd, nRingPoints;
@@ -70,8 +70,13 @@ static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring )
 
     nRingPoints = nRingEnd - nRingStart + 1;
 
-    poRing->setPoints( nRingPoints, psShape->padfX + nRingStart, 
-	       psShape->padfY + nRingStart, psShape->padfZ + nRingStart );
+    if (bHasZ)
+        poRing->setPoints( nRingPoints, psShape->padfX + nRingStart, 
+                           psShape->padfY + nRingStart,
+                           psShape->padfZ + nRingStart );
+    else
+        poRing->setPoints( nRingPoints, psShape->padfX + nRingStart,
+                           psShape->padfY + nRingStart );
 
     return ( poRing );
 }
@@ -101,19 +106,21 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 /* -------------------------------------------------------------------- */
 /*      Point.                                                          */
 /* -------------------------------------------------------------------- */
-    else if( psShape->nSHPType == SHPT_POINT
-             || psShape->nSHPType == SHPT_POINTM
-             || psShape->nSHPType == SHPT_POINTZ )
+    else if( psShape->nSHPType == SHPT_POINT )
+    {
+        poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0] );
+    }
+    else if(psShape->nSHPType == SHPT_POINTZ )
     {
         poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
                               psShape->padfZ[0] );
-
-        if( psShape->nSHPType == SHPT_POINT )
-        {
-            poOGR->setCoordinateDimension( 2 );
-        }
     }
-
+    else if(psShape->nSHPType == SHPT_POINTM )
+    {
+        // Read XYM as XYZ
+        poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
+                              psShape->padfM[0] );
+    }
 /* -------------------------------------------------------------------- */
 /*      Multipoint.                                                     */
 /* -------------------------------------------------------------------- */
@@ -134,8 +141,11 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             {
                 OGRPoint    *poPoint;
 
-                poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
-                                        psShape->padfZ[i] );
+                if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+                    poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
+                                            psShape->padfZ[i] );
+                else
+                    poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i] );
 
                 poOGRMPoint->addGeometry( poPoint );
 
@@ -143,9 +153,6 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             }
 
             poOGR = poOGRMPoint;
-
-            if( psShape->nSHPType == SHPT_MULTIPOINT )
-                poOGR->setCoordinateDimension( 2 );
         }
     }
 
@@ -166,8 +173,16 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
         {
             OGRLineString *poOGRLine = new OGRLineString();
 
-            poOGRLine->setPoints( psShape->nVertices,
-                                  psShape->padfX, psShape->padfY, psShape->padfZ );
+            if( psShape->nSHPType == SHPT_ARCZ )
+                poOGRLine->setPoints( psShape->nVertices,
+                                    psShape->padfX, psShape->padfY, psShape->padfZ );
+            else if( psShape->nSHPType == SHPT_ARCM )
+                // Read XYM as XYZ
+                poOGRLine->setPoints( psShape->nVertices,
+                                    psShape->padfX, psShape->padfY, psShape->padfM );
+            else
+                poOGRLine->setPoints( psShape->nVertices,
+                                    psShape->padfX, psShape->padfY );
 
             poOGR = poOGRLine;
         }
@@ -202,18 +217,26 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                             - psShape->panPartStart[iRing];
                     nRingStart = psShape->panPartStart[iRing];
                 }
-            
-                poLine->setPoints( nRingPoints, 
-                                   psShape->padfX + nRingStart,
-                                   psShape->padfY + nRingStart,
-                                   psShape->padfZ + nRingStart );
+
+                if( psShape->nSHPType == SHPT_ARCZ )
+                    poLine->setPoints( nRingPoints,
+                                    psShape->padfX + nRingStart,
+                                    psShape->padfY + nRingStart,
+                                    psShape->padfZ + nRingStart );
+                else if( psShape->nSHPType == SHPT_ARCM )
+                    // Read XYM as XYZ
+                    poLine->setPoints( nRingPoints,
+                                    psShape->padfX + nRingStart,
+                                    psShape->padfY + nRingStart,
+                                    psShape->padfM + nRingStart );
+                else
+                    poLine->setPoints( nRingPoints,
+                                    psShape->padfX + nRingStart,
+                                    psShape->padfY + nRingStart );
 
                 poOGRMulti->addGeometryDirectly( poLine );
             }
         }
-
-        if( poOGR != NULL && psShape->nSHPType == SHPT_ARC )
-            poOGR->setCoordinateDimension( 2 );
     }
 
 /* -------------------------------------------------------------------- */
@@ -226,6 +249,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
              || psShape->nSHPType == SHPT_POLYGONZ )
     {
         int iRing;
+        int bHasZ = ( psShape->nSHPType == SHPT_POLYGONZ );
         
         //CPLDebug( "Shape", "Shape type: polygon with nParts=%d \n", psShape->nParts );
 
@@ -240,7 +264,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             OGRLinearRing *poRing = NULL;
 
             poOGR = poOGRPoly = new OGRPolygon();
-            poRing = CreateLinearRing ( psShape, 0 );
+            poRing = CreateLinearRing ( psShape, 0, bHasZ );
             poOGRPoly->addRingDirectly( poRing );
         }
 
@@ -250,7 +274,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             for( iRing = 0; iRing < psShape->nParts; iRing++ )
             {
                 tabPolygons[iRing] = new OGRPolygon();
-                tabPolygons[iRing]->addRingDirectly(CreateLinearRing ( psShape, iRing ));
+                tabPolygons[iRing]->addRingDirectly(CreateLinearRing ( psShape, iRing, bHasZ ));
             }
 
             int isValidGeometry;
@@ -268,11 +292,6 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 
             delete[] tabPolygons;
         }
-
-        if( poOGR != NULL && psShape->nSHPType == SHPT_POLYGON )
-        {
-            poOGR->setCoordinateDimension( 2 );
-        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -399,7 +418,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                     poLastPoly = new OGRPolygon();
 
                 poLastPoly->addRingDirectly( 
-                    CreateLinearRing( psShape, iPart ) );
+                    CreateLinearRing( psShape, iPart, TRUE ) );
             }
             else
                 CPLDebug( "OGR", "Unrecognised parttype %d, ignored.", 
@@ -852,7 +871,8 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom )
 /************************************************************************/
 
 OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
-                                       SHPHandle hSHP, DBFHandle hDBF )
+                                       SHPHandle hSHP, DBFHandle hDBF,
+                                       const char* pszSHPEncoding )
 
 {
     OGRFeatureDefn      *poDefn = new OGRFeatureDefn( pszName );
@@ -874,7 +894,16 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
         eDBFType = DBFGetFieldInfo( hDBF, iField, szFieldName,
                                     &nWidth, &nPrecision );
 
-        oField.SetName( szFieldName );
+        if( strlen(pszSHPEncoding) > 0 )
+        {
+            char *pszUTF8Field = CPLRecode( szFieldName,
+                                            pszSHPEncoding, CPL_ENC_UTF8);
+            oField.SetName( pszUTF8Field );
+            CPLFree( pszUTF8Field );
+        }
+        else
+            oField.SetName( szFieldName );
+
         oField.SetWidth( nWidth );
         oField.SetPrecision( nPrecision );
 
@@ -907,38 +936,38 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
         switch( hSHP->nShapeType )
         {
           case SHPT_POINT:
-          case SHPT_POINTM:
             poDefn->SetGeomType( wkbPoint );
             break;
 
           case SHPT_POINTZ:
+          case SHPT_POINTM:
             poDefn->SetGeomType( wkbPoint25D );
             break;
 
           case SHPT_ARC:
-          case SHPT_ARCM:
             poDefn->SetGeomType( wkbLineString );
             break;
 
           case SHPT_ARCZ:
+          case SHPT_ARCM:
             poDefn->SetGeomType( wkbLineString25D );
             break;
 
           case SHPT_MULTIPOINT:
-          case SHPT_MULTIPOINTM:
             poDefn->SetGeomType( wkbMultiPoint );
             break;
 
           case SHPT_MULTIPOINTZ:
+          case SHPT_MULTIPOINTM:
             poDefn->SetGeomType( wkbMultiPoint25D );
             break;
 
           case SHPT_POLYGON:
-          case SHPT_POLYGONM:
             poDefn->SetGeomType( wkbPolygon );
             break;
 
           case SHPT_POLYGONZ:
+          case SHPT_POLYGONM:
             poDefn->SetGeomType( wkbPolygon25D );
             break;
             
@@ -954,7 +983,7 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
 
 OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                                OGRFeatureDefn * poDefn, int iShape,
-                               SHPObject *psShape )
+                               SHPObject *psShape, const char *pszSHPEncoding )
 
 {
     if( iShape < 0 
@@ -1013,10 +1042,20 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
         switch( poDefn->GetFieldDefn(iField)->GetType() )
         {
           case OFTString:
-            poFeature->SetField( iField,
-                                 DBFReadStringAttribute( hDBF, iShape,
-                                                         iField ) );
-            break;
+          {
+              const char *pszFieldVal = 
+                  DBFReadStringAttribute( hDBF, iShape, iField );
+              if( strlen(pszSHPEncoding) > 0 )
+              {
+                  char *pszUTF8Field = CPLRecode( pszFieldVal, 
+                                                  pszSHPEncoding, CPL_ENC_UTF8);
+                  poFeature->SetField( iField, pszUTF8Field );
+                  CPLFree( pszUTF8Field );
+              }
+              else
+                  poFeature->SetField( iField, pszFieldVal );
+          }
+          break;
 
           case OFTInteger:
             poFeature->SetField( iField,
@@ -1034,12 +1073,18 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
           {
               OGRField sFld;
               const char* pszDateValue = 
-                  DBFReadStringAttribute(hDBF,iShape,iField); 
+                  DBFReadStringAttribute(hDBF,iShape,iField);
+
+              /* Some DBF files have fields filled with spaces */
+              /* (trimmed by DBFReadStringAttribute) to indicate null */
+              /* values for dates (#4265) */
+              if (pszDateValue[0] == '\0')
+                  continue;
 
               memset( &sFld, 0, sizeof(sFld) );
 
-              if( pszDateValue[2] == '/' && pszDateValue[5] == '/' 
-                  && strlen(pszDateValue) >= 10 )
+              if( strlen(pszDateValue) >= 10 &&
+                  pszDateValue[2] == '/' && pszDateValue[5] == '/' )
               {
                   sFld.Date.Month = (GByte)atoi(pszDateValue+0);
                   sFld.Date.Day   = (GByte)atoi(pszDateValue+3);
@@ -1077,7 +1122,9 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 
 OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                            OGRFeatureDefn * poDefn, 
-                           OGRFeature * poFeature )
+                           OGRFeature * poFeature,
+                           const char *pszSHPEncoding,
+                           int* pbTruncationWarningEmitted )
 
 {
 #ifdef notdef
@@ -1160,20 +1207,34 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
             continue;
         }
 
+        int nRet = FALSE;
+
         switch( poDefn->GetFieldDefn(iField)->GetType() )
         {
           case OFTString:
-            DBFWriteStringAttribute( hDBF, poFeature->GetFID(), iField, 
-                                     poFeature->GetFieldAsString( iField ));
-            break;
+          {
+              const char *pszStr = poFeature->GetFieldAsString(iField);
+              if( strlen(pszSHPEncoding) > 0 )
+              {
+                  char *pszEncoded = 
+                      CPLRecode( pszStr, CPL_ENC_UTF8, pszSHPEncoding );
+                  nRet = DBFWriteStringAttribute( hDBF, poFeature->GetFID(), iField,
+                                           pszEncoded );
+                  CPLFree( pszEncoded );
+              }
+              else
+                  nRet = DBFWriteStringAttribute( hDBF, poFeature->GetFID(), iField, 
+                                           pszStr );
+          }
+          break;
 
           case OFTInteger:
-            DBFWriteIntegerAttribute( hDBF, poFeature->GetFID(), iField, 
+            nRet = DBFWriteIntegerAttribute( hDBF, poFeature->GetFID(), iField, 
                                       poFeature->GetFieldAsInteger(iField) );
             break;
 
           case OFTReal:
-            DBFWriteDoubleAttribute( hDBF, poFeature->GetFID(), iField, 
+            nRet = DBFWriteDoubleAttribute( hDBF, poFeature->GetFID(), iField, 
                                      poFeature->GetFieldAsDouble(iField) );
             break;
 
@@ -1184,7 +1245,7 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
               if( poFeature->GetFieldAsDateTime( iField, &nYear, &nMonth, &nDay,
                                                  NULL, NULL, NULL, NULL ) )
               {
-                  DBFWriteIntegerAttribute( hDBF, poFeature->GetFID(), iField, 
+                  nRet = DBFWriteIntegerAttribute( hDBF, poFeature->GetFID(), iField, 
                                             nYear*10000 + nMonth*100 + nDay );
               }
           }
@@ -1196,6 +1257,18 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
               break;
           }
         }
+
+        if (!nRet && !(*pbTruncationWarningEmitted) &&
+            strstr(CPLGetLastErrorMsg(), "Failure writing DBF") == NULL)
+        {
+            *pbTruncationWarningEmitted = TRUE;
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Value '%s' of field %s has been truncated to %d characters.\n"
+                     "This warning will not be emitted any more for that layer.",
+                     poFeature->GetFieldAsString(iField),
+                     poDefn->GetFieldDefn(iField)->GetNameRef(),
+                     poDefn->GetFieldDefn(iField)->GetWidth());
+        }
     }
 
     return OGRERR_NONE;
diff --git a/ogr/ogrsf_frmts/shape/shapefil.h b/ogr/ogrsf_frmts/shape/shapefil.h
index 02dee00..6bac393 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 18680 2010-01-28 11:36:02Z warmerdam $
+ * $Id: shapefil.h 23534 2011-12-11 22:35:51Z warmerdam $
  *
  * Project:  Shapelib
  * Purpose:  Primary include file for Shapelib.
@@ -37,6 +37,21 @@
  ******************************************************************************
  *
  * $Log: shapefil.h,v $
+ * Revision 1.52  2011-12-11 22:26:46  fwarmerdam
+ * upgrade .qix access code to use SAHooks (gdal #3365)
+ *
+ * Revision 1.51  2011-07-24 05:59:25  fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.50  2011-05-13 17:35:17  fwarmerdam
+ * added DBFReorderFields() and DBFAlterFields() functions (from Even)
+ *
+ * Revision 1.49  2011-04-16 14:38:21  fwarmerdam
+ * avoid warnings with gcc on SHP_CVSID
+ *
+ * Revision 1.48  2010-08-27 23:42:52  fwarmerdam
+ * add SHPAPI_CALL attribute in code
+ *
  * Revision 1.47  2010-01-28 11:34:34  fwarmerdam
  * handle the shape file length limits more gracefully (#3236)
  *
@@ -132,8 +147,7 @@
 #endif
 
 #ifdef USE_CPL
-#include "cpl_error.h"
-#include "cpl_vsi.h"
+#include "cpl_conv.h"
 #endif
 
 #ifdef __cplusplus
@@ -209,8 +223,12 @@ extern "C" {
 /*      as unreferenced variables resulting in lots of warnings.        */
 /* -------------------------------------------------------------------- */
 #ifndef DISABLE_CVSID
-#  define SHP_CVSID(string)     static char cpl_cvsid[] = string; \
+#  if defined(__GNUC__) && __GNUC__ >= 4
+#    define SHP_CVSID(string)     static char cpl_cvsid[] __attribute__((used)) = string;
+#  else
+#    define SHP_CVSID(string)     static char cpl_cvsid[] = string; \
 static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
+#  endif
 #else
 #  define SHP_CVSID(string)
 #endif
@@ -444,12 +462,8 @@ void    SHPAPI_CALL
 
 int	SHPAPI_CALL
       SHPWriteTree( SHPTree *hTree, const char * pszFilename );
-SHPTree SHPAPI_CALL
-      SHPReadTree( const char * pszFilename );
 
 int	SHPAPI_CALL
-      SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
-int	SHPAPI_CALL
       SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
 int	SHPAPI_CALL
       SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
@@ -470,6 +484,24 @@ SHPSearchDiskTree( FILE *fp,
                    double *padfBoundsMin, double *padfBoundsMax,
                    int *pnShapeCount );
 
+
+typedef struct SHPDiskTreeInfo* SHPTreeDiskHandle;
+
+SHPTreeDiskHandle SHPAPI_CALL
+    SHPOpenDiskTree( const char* pszQIXFilename,
+                     SAHooks *psHooks );
+
+void SHPAPI_CALL
+    SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree );
+
+int SHPAPI_CALL1(*) 
+SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree, 
+                   double *padfBoundsMin, double *padfBoundsMax,
+                   int *pnShapeCount );
+
+int SHPAPI_CALL
+    SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename, SAHooks *psHooks );
+
 /************************************************************************/
 /*                             DBF Support.                             */
 /************************************************************************/
@@ -547,6 +579,13 @@ int	SHPAPI_CALL
 int	SHPAPI_CALL
       DBFDeleteField( DBFHandle hDBF, int iField );
 
+int SHPAPI_CALL
+      DBFReorderFields( DBFHandle psDBF, int* panMap );
+
+int SHPAPI_CALL
+      DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
+                         char chType, int nWidth, int nDecimals );
+
 DBFFieldType SHPAPI_CALL
       DBFGetFieldInfo( DBFHandle psDBF, int iField, 
                        char * pszFieldName, int * pnWidth, int * pnDecimals );
diff --git a/ogr/ogrsf_frmts/shape/shpopen.c b/ogr/ogrsf_frmts/shape/shpopen.c
index be2f03a..24fd314 100644
--- a/ogr/ogrsf_frmts/shape/shpopen.c
+++ b/ogr/ogrsf_frmts/shape/shpopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shpopen.c,v 1.64 2010-01-28 11:34:34 fwarmerdam Exp $
+ * $Id: shpopen.c,v 1.72 2011-12-11 22:45:28 fwarmerdam Exp $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of core Shapefile read/write functions.
@@ -34,6 +34,30 @@
  ******************************************************************************
  *
  * $Log: shpopen.c,v $
+ * Revision 1.72  2011-12-11 22:45:28  fwarmerdam
+ * fix failure return from SHPOpenLL.
+ *
+ * Revision 1.71  2011-09-15 03:33:58  fwarmerdam
+ * fix missing cast (#2344)
+ *
+ * Revision 1.70  2011-07-24 05:59:25  fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.69  2011-07-24 03:24:22  fwarmerdam
+ * fix memory leaks in error cases creating shapefiles (#2061)
+ *
+ * Revision 1.68  2010-08-27 23:42:52  fwarmerdam
+ * add SHPAPI_CALL attribute in code
+ *
+ * Revision 1.67  2010-07-01 08:15:48  fwarmerdam
+ * do not error out on an object with zero vertices
+ *
+ * Revision 1.66  2010-07-01 07:58:57  fwarmerdam
+ * minor cleanup of error handling
+ *
+ * Revision 1.65  2010-07-01 07:27:13  fwarmerdam
+ * white space formatting adjustments
+ *
  * Revision 1.64  2010-01-28 11:34:34  fwarmerdam
  * handle the shape file length limits more gracefully (#3236)
  *
@@ -246,7 +270,7 @@
 #include <string.h>
 #include <stdio.h>
 
-SHP_CVSID("$Id: shpopen.c,v 1.64 2010-01-28 11:34:34 fwarmerdam Exp $")
+SHP_CVSID("$Id: shpopen.c,v 1.72 2011-12-11 22:45:28 fwarmerdam Exp $")
 
 typedef unsigned char uchar;
 
@@ -319,7 +343,7 @@ static void * SfRealloc( void * pMem, int nNewSize )
 /*	contents of the index (.shx) file.				*/
 /************************************************************************/
 
-void SHPWriteHeader( SHPHandle psSHP )
+void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
 
 {
     uchar     	abyHeader[100];
@@ -338,7 +362,7 @@ void SHPWriteHeader( SHPHandle psSHP )
 /*      Prepare header block for .shp file.                             */
 /* -------------------------------------------------------------------- */
     for( i = 0; i < 100; i++ )
-      abyHeader[i] = 0;
+        abyHeader[i] = 0;
 
     abyHeader[2] = 0x27;				/* magic cookie */
     abyHeader[3] = 0x0a;
@@ -418,10 +442,10 @@ void SHPWriteHeader( SHPHandle psSHP )
 
     for( i = 0; i < psSHP->nRecords; i++ )
     {
-	panSHX[i*2  ] = psSHP->panRecOffset[i]/2;
-	panSHX[i*2+1] = psSHP->panRecSize[i]/2;
-	if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
-	if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
+        panSHX[i*2  ] = psSHP->panRecOffset[i]/2;
+        panSHX[i*2+1] = psSHP->panRecSize[i]/2;
+        if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
+        if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
     }
 
     if( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX ) 
@@ -507,9 +531,9 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     pszBasename = (char *) malloc(strlen(pszLayer)+5);
     strcpy( pszBasename, pszLayer );
     for( i = strlen(pszBasename)-1; 
-	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
-	       && pszBasename[i] != '\\';
-	 i-- ) {}
+         i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+             && pszBasename[i] != '\\';
+         i-- ) {}
 
     if( pszBasename[i] == '.' )
         pszBasename[i] = '\0';
@@ -529,15 +553,16 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     
     if( psSHP->fpSHP == NULL )
     {
-#ifdef USE_CPL
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to open %s.shp or %s.SHP.", 
+        char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
+        sprintf( pszMessage, "Unable to open %s.shp or %s.SHP.", 
                   pszBasename, pszBasename );
-#endif
+        psHooks->Error( pszMessage );
+        free( pszMessage );
+
         free( psSHP );
         free( pszBasename );
         free( pszFullname );
-        return( NULL );
+        return NULL;
     }
 
     sprintf( pszFullname, "%s.shx", pszBasename );
@@ -550,11 +575,12 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     
     if( psSHP->fpSHX == NULL )
     {
-#ifdef USE_CPL
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to open %s.shx or %s.SHX.", 
+        char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
+        sprintf( pszMessage, "Unable to open %s.shx or %s.SHX.", 
                   pszBasename, pszBasename );
-#endif
+        psHooks->Error( pszMessage );
+        free( pszMessage );
+
         psSHP->sHooks.FClose( psSHP->fpSHP );
         free( psSHP );
         free( pszBasename );
@@ -572,9 +598,9 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
 
     psSHP->nFileSize = ((unsigned int)pabyBuf[24] * 256 * 256 * 256
-			+ (unsigned int)pabyBuf[25] * 256 * 256
-			+ (unsigned int)pabyBuf[26] * 256
-			+ (unsigned int)pabyBuf[27]) * 2;
+                        + (unsigned int)pabyBuf[25] * 256 * 256
+                        + (unsigned int)pabyBuf[26] * 256
+                        + (unsigned int)pabyBuf[27]) * 2;
 
 /* -------------------------------------------------------------------- */
 /*  Read SHX file Header info                                           */
@@ -586,15 +612,15 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
     {
         psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
-	psSHP->sHooks.FClose( psSHP->fpSHP );
-	psSHP->sHooks.FClose( psSHP->fpSHX );
-	free( psSHP );
+        psSHP->sHooks.FClose( psSHP->fpSHP );
+        psSHP->sHooks.FClose( psSHP->fpSHX );
+        free( psSHP );
 
-	return( NULL );
+        return( NULL );
     }
 
     psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
-      + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
+        + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
     psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
 
     psSHP->nShapeType = pabyBuf[32];
@@ -606,14 +632,14 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         sprintf( szError, 
                  "Record count in .shp header is %d, which seems\n"
                  "unreasonable.  Assuming header is corrupt.",
-                  psSHP->nRecords );
+                 psSHP->nRecords );
         psSHP->sHooks.Error( szError );				       
-	psSHP->sHooks.FClose( psSHP->fpSHP );
-	psSHP->sHooks.FClose( psSHP->fpSHX );
-	free( psSHP );
+        psSHP->sHooks.FClose( psSHP->fpSHP );
+        psSHP->sHooks.FClose( psSHP->fpSHX );
+        free( psSHP );
         free(pabyBuf);
 
-	return( NULL );
+        return( NULL );
     }
 
 /* -------------------------------------------------------------------- */
@@ -676,8 +702,8 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
                 "Probably broken SHP file", 
                 psSHP->nRecords );
         psSHP->sHooks.Error( szError );
-	psSHP->sHooks.FClose( psSHP->fpSHP );
-	psSHP->sHooks.FClose( psSHP->fpSHX );
+        psSHP->sHooks.FClose( psSHP->fpSHP );
+        psSHP->sHooks.FClose( psSHP->fpSHX );
         if (psSHP->panRecOffset) free( psSHP->panRecOffset );
         if (psSHP->panRecSize) free( psSHP->panRecSize );
         if (pabyBuf) free( pabyBuf );
@@ -686,7 +712,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     }
 
     if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ) 
-			!= psSHP->nRecords )
+        != psSHP->nRecords )
     {
         char szError[200];
 
@@ -696,14 +722,14 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         psSHP->sHooks.Error( szError );
 
         /* SHX is short or unreadable for some reason. */
-	psSHP->sHooks.FClose( psSHP->fpSHP );
-	psSHP->sHooks.FClose( psSHP->fpSHX );
+        psSHP->sHooks.FClose( psSHP->fpSHP );
+        psSHP->sHooks.FClose( psSHP->fpSHX );
         free( psSHP->panRecOffset );
         free( psSHP->panRecSize );
         free( pabyBuf );
-	free( psSHP );
+        free( psSHP );
 
-	return( NULL );
+        return( NULL );
     }
     
     /* In read-only mode, we can close the SHX now */
@@ -715,16 +741,16 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 
     for( i = 0; i < psSHP->nRecords; i++ )
     {
-	int32		nOffset, nLength;
+        int32		nOffset, nLength;
 
-	memcpy( &nOffset, pabyBuf + i * 8, 4 );
-	if( !bBigEndian ) SwapWord( 4, &nOffset );
+        memcpy( &nOffset, pabyBuf + i * 8, 4 );
+        if( !bBigEndian ) SwapWord( 4, &nOffset );
 
-	memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
-	if( !bBigEndian ) SwapWord( 4, &nLength );
+        memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
+        if( !bBigEndian ) SwapWord( 4, &nLength );
 
-	psSHP->panRecOffset[i] = nOffset*2;
-	psSHP->panRecSize[i] = nLength*2;
+        psSHP->panRecOffset[i] = nOffset*2;
+        psSHP->panRecSize[i] = nLength*2;
     }
     free( pabyBuf );
 
@@ -828,9 +854,9 @@ SHPHandle SHPAPI_CALL
 SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 
 {
-    char	*pszBasename, *pszFullname;
+    char	*pszBasename = NULL, *pszFullname = NULL;
     int		i;
-    SAFile	fpSHP, fpSHX;
+    SAFile	fpSHP = NULL, fpSHX = NULL;
     uchar     	abyHeader[100];
     int32	i32;
     double	dValue;
@@ -851,9 +877,9 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     pszBasename = (char *) malloc(strlen(pszLayer)+5);
     strcpy( pszBasename, pszLayer );
     for( i = strlen(pszBasename)-1; 
-	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
-	       && pszBasename[i] != '\\';
-	 i-- ) {}
+         i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+             && pszBasename[i] != '\\';
+         i-- ) {}
 
     if( pszBasename[i] == '.' )
         pszBasename[i] = '\0';
@@ -867,7 +893,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( fpSHP == NULL )
     {
         psHooks->Error( "Failed to create file .shp file." );
-        return( NULL );
+        goto error;
     }
 
     sprintf( pszFullname, "%s.shx", pszBasename );
@@ -875,17 +901,17 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( fpSHX == NULL )
     {
         psHooks->Error( "Failed to create file .shx file." );
-        return( NULL );
+        goto error;
     }
 
-    free( pszFullname );
-    free( pszBasename );
+    free( pszFullname ); pszFullname = NULL;
+    free( pszBasename ); pszBasename = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare header block for .shp file.                             */
 /* -------------------------------------------------------------------- */
     for( i = 0; i < 100; i++ )
-      abyHeader[i] = 0;
+        abyHeader[i] = 0;
 
     abyHeader[2] = 0x27;				/* magic cookie */
     abyHeader[3] = 0x0a;
@@ -914,7 +940,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
     {
         psHooks->Error( "Failed to write .shp header." );
-        return NULL;
+        goto error;
     }
 
 /* -------------------------------------------------------------------- */
@@ -927,7 +953,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
     {
         psHooks->Error( "Failed to write .shx header." );
-        return NULL;
+        goto error;
     }
 
 /* -------------------------------------------------------------------- */
@@ -937,6 +963,13 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     psHooks->FClose( fpSHX );
 
     return( SHPOpenLL( pszLayer, "r+b", psHooks ) );
+
+error:
+    if (pszFullname) free(pszFullname);
+    if (pszBasename) free(pszBasename);
+    if (fpSHP) psHooks->FClose( fpSHP );
+    if (fpSHX) psHooks->FClose( fpSHX );
+    return NULL;
 }
 
 /************************************************************************/
@@ -1175,11 +1208,11 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
     if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
     {
-	psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
+        psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
 
-	psSHP->panRecOffset = (unsigned int *) 
+        psSHP->panRecOffset = (unsigned int *) 
             SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * psSHP->nMaxRecords );
-	psSHP->panRecSize = (unsigned int *) 
+        psSHP->panRecSize = (unsigned int *) 
             SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * psSHP->nMaxRecords );
     }
 
@@ -1187,7 +1220,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /*      Initialize record.                                              */
 /* -------------------------------------------------------------------- */
     pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double) 
-			       + psObject->nParts * 8 + 128);
+                               + psObject->nParts * 8 + 128);
     
 /* -------------------------------------------------------------------- */
 /*  Extract vertices for a Polygon or Arc.				*/
@@ -1200,32 +1233,32 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         || psObject->nSHPType == SHPT_ARCM
         || psObject->nSHPType == SHPT_MULTIPATCH )
     {
-	int32		nPoints, nParts;
-	int    		i;
+        int32		nPoints, nParts;
+        int    		i;
 
-	nPoints = psObject->nVertices;
-	nParts = psObject->nParts;
+        nPoints = psObject->nVertices;
+        nParts = psObject->nParts;
 
-	_SHPSetBounds( pabyRec + 12, psObject );
+        _SHPSetBounds( pabyRec + 12, psObject );
 
-	if( bBigEndian ) SwapWord( 4, &nPoints );
-	if( bBigEndian ) SwapWord( 4, &nParts );
+        if( bBigEndian ) SwapWord( 4, &nPoints );
+        if( bBigEndian ) SwapWord( 4, &nParts );
 
-	ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
-	ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
+        ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
+        ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
 
         nRecordSize = 52;
 
         /*
          * Write part start positions.
          */
-	ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
+        ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
                   4 * psObject->nParts );
-	for( i = 0; i < psObject->nParts; i++ )
-	{
-	    if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
+        for( i = 0; i < psObject->nParts; i++ )
+        {
+            if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
             nRecordSize += 4;
-	}
+        }
 
         /*
          * Write multipatch part types if needed.
@@ -1244,19 +1277,19 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         /*
          * Write the (x,y) vertex values.
          */
-	for( i = 0; i < psObject->nVertices; i++ )
-	{
-	    ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
-	    ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
+        for( i = 0; i < psObject->nVertices; i++ )
+        {
+            ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
+            ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
 
-	    if( bBigEndian )
+            if( bBigEndian )
                 SwapWord( 8, pabyRec + nRecordSize );
             
-	    if( bBigEndian )
+            if( bBigEndian )
                 SwapWord( 8, pabyRec + nRecordSize + 8 );
 
             nRecordSize += 2 * 8;
-	}
+        }
 
         /*
          * Write the Z coordinates (if any).
@@ -1286,12 +1319,12 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
          */
         if( psObject->bMeasureIsUsed
             && (psObject->nSHPType == SHPT_POLYGONM
-            || psObject->nSHPType == SHPT_ARCM
+                || psObject->nSHPType == SHPT_ARCM
 #ifndef DISABLE_MULTIPATCH_MEASURE            
-            || psObject->nSHPType == SHPT_MULTIPATCH
+                || psObject->nSHPType == SHPT_MULTIPATCH
 #endif            
-            || psObject->nSHPType == SHPT_POLYGONZ
-            || psObject->nSHPType == SHPT_ARCZ) )
+                || psObject->nSHPType == SHPT_POLYGONZ
+                || psObject->nSHPType == SHPT_ARCZ) )
         {
             ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1317,26 +1350,26 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
              || psObject->nSHPType == SHPT_MULTIPOINTZ
              || psObject->nSHPType == SHPT_MULTIPOINTM )
     {
-	int32		nPoints;
-	int    		i;
+        int32		nPoints;
+        int    		i;
 
-	nPoints = psObject->nVertices;
+        nPoints = psObject->nVertices;
 
         _SHPSetBounds( pabyRec + 12, psObject );
 
-	if( bBigEndian ) SwapWord( 4, &nPoints );
-	ByteCopy( &nPoints, pabyRec + 44, 4 );
+        if( bBigEndian ) SwapWord( 4, &nPoints );
+        ByteCopy( &nPoints, pabyRec + 44, 4 );
 	
-	for( i = 0; i < psObject->nVertices; i++ )
-	{
-	    ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
-	    ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
+        for( i = 0; i < psObject->nVertices; i++ )
+        {
+            ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
+            ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
 
-	    if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
-	    if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
-	}
+            if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
+        }
 
-	nRecordSize = 48 + 16 * psObject->nVertices;
+        nRecordSize = 48 + 16 * psObject->nVertices;
 
         if( psObject->nSHPType == SHPT_MULTIPOINTZ )
         {
@@ -1358,7 +1391,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 
         if( psObject->bMeasureIsUsed
             && (psObject->nSHPType == SHPT_MULTIPOINTZ
-            || psObject->nSHPType == SHPT_MULTIPOINTM) )
+                || psObject->nSHPType == SHPT_MULTIPOINTM) )
         {
             ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1384,11 +1417,11 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
              || psObject->nSHPType == SHPT_POINTZ
              || psObject->nSHPType == SHPT_POINTM )
     {
-	ByteCopy( psObject->padfX, pabyRec + 12, 8 );
-	ByteCopy( psObject->padfY, pabyRec + 20, 8 );
+        ByteCopy( psObject->padfX, pabyRec + 12, 8 );
+        ByteCopy( psObject->padfY, pabyRec + 20, 8 );
 
-	if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
-	if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
+        if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
+        if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
 
         nRecordSize = 28;
         
@@ -1401,7 +1434,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         
         if( psObject->bMeasureIsUsed
             && (psObject->nSHPType == SHPT_POINTZ
-            || psObject->nSHPType == SHPT_POINTM) )
+                || psObject->nSHPType == SHPT_POINTM) )
         {
             ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
             if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
@@ -1435,8 +1468,8 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
         {
             char str[128];
             sprintf( str, "Failed to write shape object. "
-                          "File size cannot reach %u + %u.",
-                          psSHP->nFileSize, nRecordSize );
+                     "File size cannot reach %u + %u.",
+                     psSHP->nFileSize, nRecordSize );
             psSHP->sHooks.Error( str );
             free( pabyRec );
             return -1;
@@ -1514,14 +1547,14 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 
     for( i = 0; i < psObject->nVertices; i++ )
     {
-	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]);
+        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]);
     }
 
     return( nShapeId  );
@@ -1539,8 +1572,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 
 {
     int                  nEntitySize, nRequiredSize;
-    SHPObject		*psShape;
-    char                 pszErrorMsg[128];
+    SHPObject           *psShape;
+    char                 szErrorMsg[128];
 
 /* -------------------------------------------------------------------- */
 /*      Validate the record/entity number.                              */
@@ -1554,13 +1587,13 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     nEntitySize = psSHP->panRecSize[hEntity]+8;
     if( nEntitySize > psSHP->nBufSize )
     {
-	psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
+        psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
         if (psSHP->pabyRec == NULL)
         {
             char szError[200];
 
             /* Reallocate previous successfull size for following features */
-            psSHP->pabyRec = malloc(psSHP->nBufSize);
+            psSHP->pabyRec = (uchar *) malloc(psSHP->nBufSize);
 
             sprintf( szError, 
                      "Not enough memory to allocate requested memory (nBufSize=%d). "
@@ -1570,7 +1603,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
 
         /* Only set new buffer size after successfull alloc */
-	psSHP->nBufSize = nEntitySize;
+        psSHP->nBufSize = nEntitySize;
     }
 
     /* In case we were not able to reallocate the buffer on a previous step */
@@ -1605,8 +1638,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
          */
         char str[128];
         sprintf( str,
-                 "Error in fread() reading object of size %u from .shp file",
-                 nEntitySize);
+                 "Error in fread() reading object of size %u at offset %u from .shp file",
+                 nEntitySize, psSHP->panRecOffset[hEntity] );
 
         psSHP->sHooks.Error( str );
         return NULL;
@@ -1621,9 +1654,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 
     if ( 8 + 4 > nEntitySize )
     {
-        snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
-                    hEntity, nEntitySize); 
-        psSHP->sHooks.Error( pszErrorMsg );
+        snprintf(szErrorMsg, sizeof(szErrorMsg),
+                 "Corrupted .shp file : shape %d : nEntitySize = %d",
+                 hEntity, nEntitySize); 
+        psSHP->sHooks.Error( szErrorMsg );
         SHPDestroyObject(psShape);
         return NULL;
     }
@@ -1641,14 +1675,15 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         || psShape->nSHPType == SHPT_ARCM
         || psShape->nSHPType == SHPT_MULTIPATCH )
     {
-	int32		nPoints, nParts;
-	int    		i, nOffset;
+        int32		nPoints, nParts;
+        int    		i, nOffset;
 
         if ( 40 + 8 + 4 > nEntitySize )
         {
-            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Corrupted .shp file : shape %d : nEntitySize = %d",
                      hEntity, nEntitySize); 
-            psSHP->sHooks.Error( pszErrorMsg );
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
@@ -1660,27 +1695,28 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
         memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
 
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
 
 /* -------------------------------------------------------------------- */
 /*      Extract part/point count, and build vertex and part arrays      */
 /*      to proper size.                                                 */
 /* -------------------------------------------------------------------- */
-	memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
-	memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
+        memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
+        memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
 
-	if( bBigEndian ) SwapWord( 4, &nPoints );
-	if( bBigEndian ) SwapWord( 4, &nParts );
+        if( bBigEndian ) SwapWord( 4, &nPoints );
+        if( bBigEndian ) SwapWord( 4, &nParts );
 
         if (nPoints < 0 || nParts < 0 ||
             nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
         {
-            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
-                        hEntity, nPoints, nParts);
-            psSHP->sHooks.Error( pszErrorMsg );
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
+                     hEntity, nPoints, nParts);
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
@@ -1690,8 +1726,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         /* since 50 M * (16 + 8 + 8) = 1 600 MB */
         nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
         if ( psShape->nSHPType == SHPT_POLYGONZ
-            || psShape->nSHPType == SHPT_ARCZ
-            || psShape->nSHPType == SHPT_MULTIPATCH )
+             || psShape->nSHPType == SHPT_ARCZ
+             || psShape->nSHPType == SHPT_MULTIPATCH )
         {
             nRequiredSize += 16 + 8 * nPoints;
         }
@@ -1701,20 +1737,21 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
         if (nRequiredSize > nEntitySize)
         {
-            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
-                        hEntity, nPoints, nParts, nEntitySize);
-            psSHP->sHooks.Error( pszErrorMsg );
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
+                     hEntity, nPoints, nParts, nEntitySize);
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
 
-	psShape->nVertices = nPoints;
+        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->nParts = nParts;
+        psShape->nParts = nParts;
         psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
         psShape->panPartType = (int *) calloc(nParts,sizeof(int));
         
@@ -1725,10 +1762,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             psShape->panPartStart == NULL ||
             psShape->panPartType == NULL)
         {
-            snprintf(pszErrorMsg, 128,
+            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 );
-            psSHP->sHooks.Error( pszErrorMsg );
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
@@ -1739,32 +1776,35 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
 /*      Copy out the part array from the record.                        */
 /* -------------------------------------------------------------------- */
-	memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
-	for( i = 0; i < nParts; i++ )
-	{
-	    if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+        memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
+        for( i = 0; i < nParts; i++ )
+        {
+            if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
 
             /* We check that the offset is inside the vertex array */
-            if (psShape->panPartStart[i] < 0 ||
-                psShape->panPartStart[i] >= psShape->nVertices)
+            if (psShape->panPartStart[i] < 0
+                || (psShape->panPartStart[i] >= psShape->nVertices
+                    && psShape->nVertices > 0) )
             {
-                snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
+                snprintf(szErrorMsg, sizeof(szErrorMsg),
+                         "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
                          hEntity, i, psShape->panPartStart[i], psShape->nVertices); 
-                psSHP->sHooks.Error( pszErrorMsg );
+                psSHP->sHooks.Error( szErrorMsg );
                 SHPDestroyObject(psShape);
                 return NULL;
             }
             if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
             {
-                snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
+                snprintf(szErrorMsg, sizeof(szErrorMsg),
+                         "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
                          hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]); 
-                psSHP->sHooks.Error( pszErrorMsg );
+                psSHP->sHooks.Error( szErrorMsg );
                 SHPDestroyObject(psShape);
                 return NULL;
             }
-	}
+        }
 
-	nOffset = 44 + 8 + 4*nParts;
+        nOffset = 44 + 8 + 4*nParts;
 
 /* -------------------------------------------------------------------- */
 /*      If this is a multipatch, we will also have parts types.         */
@@ -1783,19 +1823,19 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 /* -------------------------------------------------------------------- */
 /*      Copy out the vertices from the record.                          */
 /* -------------------------------------------------------------------- */
-	for( i = 0; i < nPoints; i++ )
-	{
-	    memcpy(psShape->padfX + i,
-		   psSHP->pabyRec + nOffset + i * 16,
-		   8 );
+        for( i = 0; i < nPoints; i++ )
+        {
+            memcpy(psShape->padfX + i,
+                   psSHP->pabyRec + nOffset + i * 16,
+                   8 );
 
-	    memcpy(psShape->padfY + i,
-		   psSHP->pabyRec + nOffset + i * 16 + 8,
-		   8 );
+            memcpy(psShape->padfY + i,
+                   psSHP->pabyRec + nOffset + i * 16 + 8,
+                   8 );
 
-	    if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
-	    if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
-	}
+            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+            if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+        }
 
         nOffset += 16*nPoints;
         
@@ -1853,26 +1893,28 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
              || psShape->nSHPType == SHPT_MULTIPOINTM
              || psShape->nSHPType == SHPT_MULTIPOINTZ )
     {
-	int32		nPoints;
-	int    		i, nOffset;
+        int32		nPoints;
+        int    		i, nOffset;
 
         if ( 44 + 4 > nEntitySize )
         {
-            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Corrupted .shp file : shape %d : nEntitySize = %d",
                      hEntity, nEntitySize); 
-            psSHP->sHooks.Error( pszErrorMsg );
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
-	memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
+        memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
 
-	if( bBigEndian ) SwapWord( 4, &nPoints );
+        if( bBigEndian ) SwapWord( 4, &nPoints );
 
         if (nPoints < 0 || nPoints > 50 * 1000 * 1000)
         {
-            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d",
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Corrupted .shp file : shape %d : nPoints = %d",
                      hEntity, nPoints); 
-            psSHP->sHooks.Error( pszErrorMsg );
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
@@ -1884,14 +1926,15 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         }
         if (nRequiredSize > nEntitySize)
         {
-            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
                      hEntity, nPoints, nEntitySize); 
-            psSHP->sHooks.Error( pszErrorMsg );
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
         
-	psShape->nVertices = nPoints;
+        psShape->nVertices = nPoints;
         psShape->padfX = (double *) calloc(nPoints,sizeof(double));
         psShape->padfY = (double *) calloc(nPoints,sizeof(double));
         psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
@@ -1902,22 +1945,22 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             psShape->padfZ == NULL ||
             psShape->padfM == NULL)
         {
-            snprintf(pszErrorMsg, 128,
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
                      "Not enough memory to allocate requested memory (nPoints=%d) for shape %d. "
                      "Probably broken SHP file", hEntity, nPoints );
-            psSHP->sHooks.Error( pszErrorMsg );
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
 
-	for( i = 0; i < nPoints; i++ )
-	{
-	    memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
-	    memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
+        for( i = 0; i < nPoints; i++ )
+        {
+            memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
+            memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
 
-	    if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
-	    if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
-	}
+            if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+            if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+        }
 
         nOffset = 48 + 16*nPoints;
         
@@ -1929,10 +1972,10 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
         memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
 
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
-	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+        if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
 
 /* -------------------------------------------------------------------- */
 /*      If we have a Z coordinate, collect that now.                    */
@@ -1988,7 +2031,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     {
         int	nOffset;
         
-	psShape->nVertices = 1;
+        psShape->nVertices = 1;
         psShape->padfX = (double *) calloc(1,sizeof(double));
         psShape->padfY = (double *) calloc(1,sizeof(double));
         psShape->padfZ = (double *) calloc(1,sizeof(double));
@@ -1996,17 +2039,18 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
 
         if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
         {
-            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+            snprintf(szErrorMsg, sizeof(szErrorMsg),
+                     "Corrupted .shp file : shape %d : nEntitySize = %d",
                      hEntity, nEntitySize); 
-            psSHP->sHooks.Error( pszErrorMsg );
+            psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
-	memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
-	memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
+        memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
+        memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
 
-	if( bBigEndian ) SwapWord( 8, psShape->padfX );
-	if( bBigEndian ) SwapWord( 8, psShape->padfY );
+        if( bBigEndian ) SwapWord( 8, psShape->padfX );
+        if( bBigEndian ) SwapWord( 8, psShape->padfY );
 
         nOffset = 20 + 8;
         
@@ -2248,12 +2292,12 @@ SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
                  */
                 if ( ( psObject->padfY[iEdge+nVertStart] < dfTestY
                        && dfTestY <= psObject->padfY[iNext+nVertStart] )
-                    || ( psObject->padfY[iNext+nVertStart] < dfTestY
-                         && dfTestY <= psObject->padfY[iEdge+nVertStart] ) )
+                     || ( psObject->padfY[iNext+nVertStart] < dfTestY
+                          && dfTestY <= psObject->padfY[iEdge+nVertStart] ) )
                 {
                     /* Rule #2:
-                    * Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
-                    */
+                     * Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
+                     */
                     double const intersect = 
                         ( psObject->padfX[iEdge+nVertStart]
                           + ( dfTestY - psObject->padfY[iEdge+nVertStart] ) 
diff --git a/ogr/ogrsf_frmts/shape/shptree.c b/ogr/ogrsf_frmts/shape/shptree.c
index d89a6cf..9a03231 100644
--- a/ogr/ogrsf_frmts/shape/shptree.c
+++ b/ogr/ogrsf_frmts/shape/shptree.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shptree.c,v 1.12 2008/11/12 15:39:50 fwarmerdam Exp $
+ * $Id: shptree.c,v 1.16 2011-12-11 22:26:46 fwarmerdam Exp $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -34,7 +34,19 @@
  ******************************************************************************
  *
  * $Log: shptree.c,v $
- * Revision 1.12  2008/11/12 15:39:50  fwarmerdam
+ * Revision 1.16  2011-12-11 22:26:46  fwarmerdam
+ * upgrade .qix access code to use SAHooks (gdal #3365)
+ *
+ * Revision 1.15  2011-07-24 05:59:25  fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.14  2010-08-27 23:43:27  fwarmerdam
+ * add SHPAPI_CALL attribute in code
+ *
+ * Revision 1.13  2010-06-29 05:50:15  fwarmerdam
+ * fix sign of Z/M comparisons in SHPCheckObjectContained (#2223)
+ *
+ * Revision 1.12  2008-11-12 15:39:50  fwarmerdam
  * improve safety in face of buggy .shp file.
  *
  * Revision 1.11  2007/10/27 03:31:14  fwarmerdam
@@ -78,11 +90,12 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+
 #ifdef USE_CPL
-#include <cpl_error.h>
+#include "cpl_error.h"
 #endif
 
-SHP_CVSID("$Id: shptree.c,v 1.12 2008/11/12 15:39:50 fwarmerdam Exp $")
+SHP_CVSID("$Id: shptree.c,v 1.16 2011-12-11 22:26:46 fwarmerdam Exp $")
 
 #ifndef TRUE
 #  define TRUE 1
@@ -131,13 +144,8 @@ static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
     SHPTreeNode	*psTreeNode;
 
     psTreeNode = (SHPTreeNode *) malloc(sizeof(SHPTreeNode));
-	if( NULL == psTreeNode )
-	{
-#ifdef USE_CPL
-		CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
-#endif
-		return NULL;
-	}
+    if( NULL == psTreeNode )
+        return NULL;
 
     psTreeNode->nShapeCount = 0;
     psTreeNode->panShapeIds = NULL;
@@ -160,8 +168,8 @@ static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
 /************************************************************************/
 
 SHPTree SHPAPI_CALL1(*)
-SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
-               double *padfBoundsMin, double *padfBoundsMax )
+    SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+                   double *padfBoundsMin, double *padfBoundsMax )
 
 {
     SHPTree	*psTree;
@@ -173,13 +181,10 @@ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
 /*      Allocate the tree object                                        */
 /* -------------------------------------------------------------------- */
     psTree = (SHPTree *) malloc(sizeof(SHPTree));
-	if( NULL == psTree )
-	{
-#ifdef USE_CPL
-		CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
-#endif
-		return NULL;
-	}
+    if( NULL == psTree )
+    {
+        return NULL;
+    }
 
     psTree->hSHP = hSHP;
     psTree->nMaxDepth = nMaxDepth;
@@ -217,9 +222,9 @@ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
             psTree->nMaxDepth = MAX_DEFAULT_TREE_DEPTH;
 
 #ifdef USE_CPL
-        CPLDebug( "Shape",
-                  "Falling back to max number of allowed index tree levels (%d).",
-                  MAX_DEFAULT_TREE_DEPTH );
+            CPLDebug( "Shape",
+                      "Falling back to max number of allowed index tree levels (%d).",
+                      MAX_DEFAULT_TREE_DEPTH );
 #endif
         }
     }
@@ -228,20 +233,20 @@ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
 /*      Allocate the root node.                                         */
 /* -------------------------------------------------------------------- */
     psTree->psRoot = SHPTreeNodeCreate( padfBoundsMin, padfBoundsMax );
-	if( NULL == psTree->psRoot )
-	{
-		return NULL;
-	}
+    if( NULL == psTree->psRoot )
+    {
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Assign the bounds to the root node.  If none are passed in,     */
 /*      use the bounds of the provided file otherwise the create        */
 /*      function will have already set the bounds.                      */
 /* -------------------------------------------------------------------- */
-	assert( NULL != psTree );
-	assert( NULL != psTree->psRoot );
+    assert( NULL != psTree );
+    assert( NULL != psTree->psRoot );
 	
-	if( padfBoundsMin == NULL )
+    if( padfBoundsMin == NULL )
     {
         SHPGetInfo( hSHP, NULL, NULL,
                     psTree->psRoot->adfBoundsMin, 
@@ -367,14 +372,14 @@ static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
         return TRUE;
     
     if( psObject->dfZMin < padfBoundsMin[2]
-        || psObject->dfZMax < padfBoundsMax[2] )
+        || psObject->dfZMax > padfBoundsMax[2] )
         return FALSE;
         
     if( nDimension == 3 )
         return TRUE;
 
     if( psObject->dfMMin < padfBoundsMin[3]
-        || psObject->dfMMax < padfBoundsMax[3] )
+        || psObject->dfMMax > padfBoundsMax[3] )
         return FALSE;
 
     return TRUE;
@@ -760,12 +765,58 @@ static void SwapWord( int length, void * wordP )
     }
 }
 
+
+struct SHPDiskTreeInfo
+{
+    SAHooks sHooks;
+    SAFile  fpQIX;
+};
+
+/************************************************************************/
+/*                         SHPOpenDiskTree()                            */
+/************************************************************************/
+
+SHPTreeDiskHandle SHPOpenDiskTree( const char* pszQIXFilename,
+                                   SAHooks *psHooks )
+{
+    SHPTreeDiskHandle hDiskTree;
+
+    hDiskTree = (SHPTreeDiskHandle) calloc(sizeof(struct SHPDiskTreeInfo),1);
+
+    if (psHooks == NULL)
+        SASetupDefaultHooks( &(hDiskTree->sHooks) );
+    else
+        memcpy( &(hDiskTree->sHooks), psHooks, sizeof(SAHooks) );
+
+    hDiskTree->fpQIX = hDiskTree->sHooks.FOpen(pszQIXFilename, "rb");
+    if (hDiskTree->fpQIX == NULL)
+    {
+        free(hDiskTree);
+        return NULL;
+    }
+
+    return hDiskTree;
+}
+
+/***********************************************************************/
+/*                         SHPCloseDiskTree()                           */
+/************************************************************************/
+
+void SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree )
+{
+    if (hDiskTree == NULL)
+        return;
+
+    hDiskTree->sHooks.FClose(hDiskTree->fpQIX);
+    free(hDiskTree);
+}
+
 /************************************************************************/
 /*                       SHPSearchDiskTreeNode()                        */
 /************************************************************************/
 
 static int
-SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
+SHPSearchDiskTreeNode( SHPTreeDiskHandle hDiskTree, double *padfBoundsMin, double *padfBoundsMax,
                        int **ppanResultBuffer, int *pnBufferMax, 
                        int *pnResultCount, int bNeedSwap )
 
@@ -778,11 +829,11 @@ SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
 /* -------------------------------------------------------------------- */
 /*      Read and unswap first part of node info.                        */
 /* -------------------------------------------------------------------- */
-    fread( &offset, 4, 1, fp );
+    hDiskTree->sHooks.FRead( &offset, 4, 1, hDiskTree->fpQIX );
     if ( bNeedSwap ) SwapWord ( 4, &offset );
 
-    fread( adfNodeBoundsMin, sizeof(double), 2, fp );
-    fread( adfNodeBoundsMax, sizeof(double), 2, fp );
+    hDiskTree->sHooks.FRead( adfNodeBoundsMin, sizeof(double), 2, hDiskTree->fpQIX );
+    hDiskTree->sHooks.FRead( adfNodeBoundsMax, sizeof(double), 2, hDiskTree->fpQIX );
     if ( bNeedSwap )
     {
         SwapWord( 8, adfNodeBoundsMin + 0 );
@@ -791,7 +842,7 @@ SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
         SwapWord( 8, adfNodeBoundsMax + 1 );
     }
       
-    fread( &numshapes, 4, 1, fp );
+    hDiskTree->sHooks.FRead( &numshapes, 4, 1, hDiskTree->fpQIX );
     if ( bNeedSwap ) SwapWord ( 4, &numshapes );
 
 /* -------------------------------------------------------------------- */
@@ -802,7 +853,7 @@ SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
                                 padfBoundsMin, padfBoundsMax, 2 ) )
     {
         offset += numshapes*sizeof(int) + sizeof(int);
-        fseek(fp, offset, SEEK_CUR);
+        hDiskTree->sHooks.FSeek(hDiskTree->fpQIX, offset, SEEK_CUR);
         return TRUE;
     }
 
@@ -818,8 +869,8 @@ SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
                 SfRealloc( *ppanResultBuffer, *pnBufferMax * sizeof(int) );
         }
 
-        fread( *ppanResultBuffer + *pnResultCount, 
-               sizeof(int), numshapes, fp );
+        hDiskTree->sHooks.FRead( *ppanResultBuffer + *pnResultCount, 
+               sizeof(int), numshapes, hDiskTree->fpQIX );
 
         if (bNeedSwap )
         {
@@ -833,12 +884,12 @@ SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
 /* -------------------------------------------------------------------- */
 /*      Process the subnodes.                                           */
 /* -------------------------------------------------------------------- */
-    fread( &numsubnodes, 4, 1, fp );
+    hDiskTree->sHooks.FRead( &numsubnodes, 4, 1, hDiskTree->fpQIX );
     if ( bNeedSwap  ) SwapWord ( 4, &numsubnodes );
 
     for(i=0; i<numsubnodes; i++)
     {
-        if( !SHPSearchDiskTreeNode( fp, padfBoundsMin, padfBoundsMax, 
+        if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax, 
                                     ppanResultBuffer, pnBufferMax, 
                                     pnResultCount, bNeedSwap ) )
             return FALSE;
@@ -848,6 +899,29 @@ SHPSearchDiskTreeNode( FILE *fp, double *padfBoundsMin, double *padfBoundsMax,
 }
 
 /************************************************************************/
+/*                          SHPTreeReadLibc()                           */
+/************************************************************************/
+
+static
+SAOffset SHPTreeReadLibc( void *p, SAOffset size, SAOffset nmemb, SAFile file )
+
+{
+    return (SAOffset) fread( p, (size_t) size, (size_t) nmemb,
+                                 (FILE *) file );
+}
+
+/************************************************************************/
+/*                          SHPTreeSeekLibc()                           */
+/************************************************************************/
+
+static
+SAOffset SHPTreeSeekLibc( SAFile file, SAOffset offset, int whence )
+
+{
+    return (SAOffset) fseek( (FILE *) file, (long) offset, whence );
+}
+
+/************************************************************************/
 /*                         SHPSearchDiskTree()                          */
 /************************************************************************/
 
@@ -855,6 +929,28 @@ int SHPAPI_CALL1(*)
 SHPSearchDiskTree( FILE *fp, 
                    double *padfBoundsMin, double *padfBoundsMax,
                    int *pnShapeCount )
+{
+    struct SHPDiskTreeInfo sDiskTree;
+    memset(&sDiskTree.sHooks, 0, sizeof(sDiskTree.sHooks));
+
+    /* We do not use SASetupDefaultHooks() because the FILE* */
+    /* is a libc FILE* */
+    sDiskTree.sHooks.FSeek = SHPTreeSeekLibc;
+    sDiskTree.sHooks.FRead = SHPTreeReadLibc;
+
+    sDiskTree.fpQIX = (SAFile)fp;
+
+    return SHPSearchDiskTreeEx( &sDiskTree, padfBoundsMin, padfBoundsMax,
+                                 pnShapeCount );
+}
+
+/***********************************************************************/
+/*                       SHPSearchDiskTreeEx()                         */
+/************************************************************************/
+
+int* SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree, 
+                     double *padfBoundsMin, double *padfBoundsMax,
+                     int *pnShapeCount )
 
 {
     int i, bNeedSwap, nBufferMax = 0;
@@ -875,8 +971,8 @@ SHPSearchDiskTree( FILE *fp,
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    fseek( fp, 0, SEEK_SET );
-    fread( abyBuf, 16, 1, fp );
+    hDiskTree->sHooks.FSeek( hDiskTree->fpQIX, 0, SEEK_SET );
+    hDiskTree->sHooks.FRead( abyBuf, 16, 1, hDiskTree->fpQIX );
 
     if( memcmp( abyBuf, "SQT", 3 ) != 0 )
         return NULL;
@@ -890,7 +986,7 @@ SHPSearchDiskTree( FILE *fp,
 /* -------------------------------------------------------------------- */
 /*      Search through root node and it's decendents.                   */
 /* -------------------------------------------------------------------- */
-    if( !SHPSearchDiskTreeNode( fp, padfBoundsMin, padfBoundsMax, 
+    if( !SHPSearchDiskTreeNode( hDiskTree, padfBoundsMin, padfBoundsMax, 
                                 &panResultBuffer, &nBufferMax, 
                                 pnShapeCount, bNeedSwap ) )
     {
@@ -937,26 +1033,26 @@ static int SHPGetSubNodeOffset( SHPTreeNode *node)
 /*                          SHPWriteTreeNode()                          */
 /************************************************************************/
 
-static void SHPWriteTreeNode( FILE *fp, SHPTreeNode *node) 
+static void SHPWriteTreeNode( SAFile fp, SHPTreeNode *node, SAHooks* psHooks) 
 {
     int i,j;
     int offset;
     unsigned char *pabyRec = NULL;
-	assert( NULL != node );
+    assert( NULL != node );
 
     offset = SHPGetSubNodeOffset(node);
   
     pabyRec = (unsigned char *) 
         malloc(sizeof(double) * 4
                + (3 * sizeof(int)) + (node->nShapeCount * sizeof(int)) );
-	if( NULL == pabyRec )
-	{
+    if( NULL == pabyRec )
+    {
 #ifdef USE_CPL
-		CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
+        CPLError( CE_Fatal, CPLE_OutOfMemory, "Memory allocation failure");
 #endif
-		assert( 0 );
-	}
-	assert( NULL != pabyRec );
+        assert( 0 );
+        return;
+    }
 
     memcpy( pabyRec, &offset, 4);
 
@@ -971,13 +1067,13 @@ static void SHPWriteTreeNode( FILE *fp, SHPTreeNode *node)
     memcpy( pabyRec+40, node->panShapeIds, j);
     memcpy( pabyRec+j+40, &node->nSubNodes, 4);
 
-    fwrite( pabyRec, 44+j, 1, fp );
+    psHooks->FWrite( pabyRec, 44+j, 1, fp );
     free (pabyRec);
   
     for(i=0; i<node->nSubNodes; i++ ) 
     {
         if(node->apsSubNode[i])
-            SHPWriteTreeNode( fp, node->apsSubNode[i]);
+            SHPWriteTreeNode( fp, node->apsSubNode[i], psHooks);
     }
 }
 
@@ -985,17 +1081,37 @@ static void SHPWriteTreeNode( FILE *fp, SHPTreeNode *node)
 /*                            SHPWriteTree()                            */
 /************************************************************************/
 
-int SHPWriteTree(SHPTree *tree, const char *filename )
+int SHPAPI_CALL SHPWriteTree(SHPTree *tree, const char *filename )
+{
+    SAHooks sHooks;
+
+    SASetupDefaultHooks( &sHooks );
+
+    return SHPWriteTreeLL(tree, filename, &sHooks);
+}
+
+/************************************************************************/
+/*                           SHPWriteTreeLL()                           */
+/************************************************************************/
+
+int SHPWriteTreeLL(SHPTree *tree, const char *filename, SAHooks* psHooks )
 {
     char		signature[4] = "SQT";
     int		        i;
     char		abyBuf[32];
-    FILE                *fp;
+    SAFile              fp;
+
+    SAHooks sHooks;
+    if (psHooks == NULL)
+    {
+        SASetupDefaultHooks( &sHooks );
+        psHooks = &sHooks;
+    }
   
 /* -------------------------------------------------------------------- */
 /*      Open the output file.                                           */
 /* -------------------------------------------------------------------- */
-    fp = fopen(filename, "wb");
+    fp = psHooks->FOpen(filename, "wb");
     if( fp == NULL ) 
     {
         return FALSE;
@@ -1025,21 +1141,21 @@ int SHPWriteTree(SHPTree *tree, const char *filename )
     abyBuf[6] = 0;
     abyBuf[7] = 0;
 
-    fwrite( abyBuf, 8, 1, fp );
+    psHooks->FWrite( abyBuf, 8, 1, fp );
 
-    fwrite( &(tree->nTotalCount), 4, 1, fp );
+    psHooks->FWrite( &(tree->nTotalCount), 4, 1, fp );
 
     /* write maxdepth */
 
-    fwrite( &(tree->nMaxDepth), 4, 1, fp );
+    psHooks->FWrite( &(tree->nMaxDepth), 4, 1, fp );
 
 /* -------------------------------------------------------------------- */
 /*      Write all the nodes "in order".                                 */
 /* -------------------------------------------------------------------- */
 
-    SHPWriteTreeNode( fp, tree->psRoot );  
+    SHPWriteTreeNode( fp, tree->psRoot, psHooks );  
     
-    fclose( fp );
+    psHooks->FClose( fp );
 
     return TRUE;
 }
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
index ea794cd..78afe29 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsosilayer.cpp 21065 2010-11-05 18:47:30Z rouault $
+ * $Id: ogrsosilayer.cpp 21826 2011-02-24 15:25:13Z warmerdam $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSILayer.
@@ -295,6 +295,9 @@ void OGRSOSILayer::ResetReading() {
 /************************************************************************/
 
 int OGRSOSILayer::TestCapability( const char * pszCap ) {
-    CPLDebug( "[TestCapability]","Capability %s not supported by SOSI layer", pszCap);
-    return FALSE;
+
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+    else
+        return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/sqlite/GNUmakefile b/ogr/ogrsf_frmts/sqlite/GNUmakefile
index bb8cd3b..f3d3e56 100644
--- a/ogr/ogrsf_frmts/sqlite/GNUmakefile
+++ b/ogr/ogrsf_frmts/sqlite/GNUmakefile
@@ -3,13 +3,18 @@
 include ../../../GDALmake.opt
 
 OBJ	=	ogrsqlitedatasource.o ogrsqlitelayer.o ogrsqlitedriver.o \
-		ogrsqlitetablelayer.o ogrsqliteselectlayer.o ogrsqlitesinglefeaturelayer.o
+		ogrsqlitetablelayer.o ogrsqliteviewlayer.o ogrsqliteselectlayer.o ogrsqlitesinglefeaturelayer.o \
+		ogrsqlitevfs.o
 
 ifeq ($(HAVE_SPATIALITE),yes)
 CPPFLAGS +=  -DHAVE_SPATIALITE
 endif
 
-CPPFLAGS	:=	-I.. $(GDAL_INCLUDE) $(SQLITE_INC) $(CPPFLAGS)
+ifeq ($(SPATIALITE_AMALGAMATION),yes)
+CPPFLAGS +=  -DSPATIALITE_AMALGAMATION
+endif
+
+CPPFLAGS	:=	-I.. $(GDAL_INCLUDE) $(SQLITE_INC) $(SPATIALITE_INC) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
index 25eb48b..e7794dd 100644
--- a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
+++ b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
@@ -53,33 +53,43 @@ 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>
 
+<h2>VSI Virtual File System API support</h2>
+
+(Require OGR >= 1.9.0 and SQLite >= 3.6.0)<p>
+
+The driver supports reading and writing to files managed by VSI Virtual File System API, which include
+"regular" files, as well as files in the /vsimem/ (read-write), /vsizip/ (read-only), /vsigzip/ (read-only), /vsicurl/ (read-only) domains.<p>
+
+Note: for regular files, the standard I/O operations provided by SQLite are used, in order to benefit
+from its integrity guarantees.<p>
+
 <h2>Using the SpatiaLite library (Spatial extension for SQLite)</h2>
 
 (Starting with GDAL 1.7.0)<p>
 
-The SQLite driver can read and write SpatiaLite databases without needing
-to load the SpatiaLite library. But if you configure GDAL/OGR with explicit linking
-to SpatiaLite library (version >= 2.3), you can take advantage of all the extension
-functions provided by this library, such as spatial indexes, spatial functions, etc...<p>
+The SQLite driver can read and write SpatiaLite databases. Creating or updating a spatialite database requires
+explicit linking against SpatiaLite library (version >= 2.3.1). Explicit linking against SpatiaLite library also
+provides access to functions provided by this library, such as spatial indexes, spatial functions, etc...<p>
 
 A few examples :
 <pre>
-# Duplicate the sample database provided with SpatiaLite (does not need explicit linking with SpatiaLite)
+# Duplicate the sample database provided with SpatiaLite
 ogr2ogr -f SQLite testspatialite.sqlite test-2.3.sqlite  -dsco SPATIALITE=YES
 
-# Add a spatial index on the geometry column of the Towns table (needs explicit linking with SpatiaLite)
-ogrinfo testspatialite.sqlite -sql "SELECT CreateSpatialIndex('Towns', 'geometry')"
+# Make a request with a spatial filter. Will work faster if spatial index has
+# been created and explicit linking against SpatiaLite library.
+ogrinfo testspatialite.sqlite Towns -spat 754000 4692000 770000 4924000
+</pre>
 
-# Make a request with a spatial filter (needs explicit linking with SpatiaLite)
-ogrinfo testspatialite.sqlite \
-     -sql "SELECT Name, asText(geometry) FROM Towns WHERE MBRIntersects(geometry, BuildMBR(754000, 4692000, 770000, 4924000))"
+<h2>Opening with 'VirtualShape:'</h2>
 
-or
+(Require OGR >= 1.9.0 and Spatialite support)<p>
 
-# Will work faster with spatial filter and explicit linking with SpatiaLite
-ogrinfo testspatialite.sqlite Towns -spat 754000 4692000 770000 4924000
+It is possible to open on-the-fly a shapefile as a VirtualShape with Spatialite. The syntax to use for the
+datasource is "VirtualShape:/path/to/shapefile.shp" (the shapefile must be a "real" file).<p>
 
-</pre>
+This gives the capability to use the spatial operations of Spatialite (note that spatial indexes on virtual
+tables are not available).<p>
 
 <h2>Creation Issues</h2>
 
@@ -97,10 +107,20 @@ these metadata tables are created when a new database is created.
 
 <li> <b>SPATIALITE=yes/no</b>: (Starting with GDAL 1.7.0) Create the SpatiaLite flavour of the metadata
 tables, which are a bit differ from the metadata used by this OGR driver and
-from OGC specifications. Implies <b>METADATA=yes</b>.
+from OGC specifications. Implies <b>METADATA=yes</b>.<br>
+Please note: (Starting with GDAL 1.9.0) OGR must be linked against <i>libspatialite</i> in order to support
+insert/write on SpatiaLite; if not, <i>read-only</i> mode is enforced.<br>
+Attempting to perform any insert/write on SpatiaLite skipping the appropriate library support simply produces broken (corrupted) DB-files.<br>
+Important notice: when the underlaying <i>libspatialite</i> is v.2.3.1 (or any previous
+version) any Geometry will be casted to 2D [XY], because earlier versions of this library
+are simply able to support 2D [XY] dimensions. Version 2.4.0 (or any subsequent) is required in order to support 2.5D [XYZ].
 
 <li> <b>INIT_WITH_EPSG=yes/no</b>: (Starting with GDAL 1.8.0) Insert the content of the EPSG CSV files
-into the spatial_ref_sys table. Defaults to no</b>.
+into the spatial_ref_sys table. Defaults to no</b>.<br>
+Please note: if <b>SPATIALITE=yes</b> and the underlaying <i>libspatialite</i> is v.2.4 (or any subsequent 
+version) <b>INIT_WITH_EPSG</b> is ignored anyway;
+any recent version of this library will unconditionally load the EPSG 
+dataset into the spatial_ref_sys table when creating a new DB (<i>self-initialization</i>).
 </ul>
 
 <h3>Layer Creation Options</h3>
@@ -123,14 +143,49 @@ case and some special characters will be changed to underscores.
 of the SpatiaLite flavour, and if OGR is linked against libspatialite, this option
 can be used to control if a spatial index must be created. Default to yes.
 
-</ul>
+<li> <b>COMPRESS_GEOM=yes/no</b>: (Starting with GDAL 1.9.0) If the format of the
+geometry BLOB is of the SpatiaLite flavour, this option can be used to control
+if the compressed format for geometries (LINESTRINGs, POLYGONs) must be used. This
+format is understood by Spatialite v2.4 (or any subsequent version). Default to no.
+Note: when updating an existing Spatialite DB, the COMPRESS_GEOM configuration option
+can be set to produce similar results for appended/overwritten features.
 
+</ul>
 
-<h2>Other Notes</h2>
+<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
+appropriately in order to get optimal performance.
+The default OGR behavior is to COMMIT a transaction every 200 inserted rows. This
+value is surely too low for SQLite; and closing too much frequently the current
+transaction causes severe performance degradation.
+The <b>-gt</b> argument allows to explicitly set the number of rows for each transaction.
+Explicitly defining <b>-gt 1024</b> usually ensures a noticeable performance boost;
+defining an even bigger <b>-gt 65536</b> ensures optimal performance while
+populating some table containing many hundredth thousand or million rows.<p>
+
+SQLite usually has a very minimal memory foot-print; just about 20MB of RAM are
+reserved to store the internal Page Cache [merely 2000 pages]. 
+This value too may well be inappropriate under many circumstances, most notably when
+accessing some really huge DB-file containing many tables related to a corresponding
+Spatial Index.
+Explicitly setting a much more generously dimensioned internal Page Cache may often
+help to get a noticeably better performance.
+Starting since GDAL 1.9.0 you can explicitly set the internal Page Cache size using the 
+configuration option <b>OGR_SQLITE_CACHE</b> <i>value</i> [<i>value</i> being measured in MB];
+if your HW has enough available RAM, defining a Cache size as big as 512MB (or even 1024MB) 
+may sometimes help a lot in order to get better performance.
+
+<h2>Credits</h2>
 <ul>
 <li>Development of the OGR SQLite driver was supported by 
 <a href="http://www.dmsolutions.ca/">DM Solutions Group</a> and 
 <a href="http://www.gomoos.org/">GoMOOS</a>.</li>
+<li>Full support for SpatiaLite was contributed by A.Furieri, with funding from <a href="http://www.regione.toscana.it/">Regione Toscana<a>
+</ul>
+
+<h2>Links</h2>
+<ul>
 <li><a href="http://www.sqlite.org/">http://www.sqlite.org</a>: Main SQLite page.
 <li> <a href="http://www.gaia-gis.it/spatialite/">http://www.gaia-gis.it/spatialite/</a>: SpatiaLite extension to SQLite.
 <li> <A href="http://trac.osgeo.org/fdo/wiki/FDORfc16">FDO RFC 16</a>: FDO Provider for SQLite</li>
diff --git a/ogr/ogrsf_frmts/sqlite/makefile.vc b/ogr/ogrsf_frmts/sqlite/makefile.vc
index 0e61a6f..8491dc0 100644
--- a/ogr/ogrsf_frmts/sqlite/makefile.vc
+++ b/ogr/ogrsf_frmts/sqlite/makefile.vc
@@ -1,7 +1,8 @@
 
 OBJ	=	ogrsqlitedriver.obj ogrsqlitedatasource.obj \
-		ogrsqlitelayer.obj ogrsqlitetablelayer.obj  \
-		ogrsqliteselectlayer.obj ogrsqlitesinglefeaturelayer.obj
+		ogrsqlitelayer.obj ogrsqlitetablelayer.obj ogrsqliteviewlayer.obj  \
+		ogrsqliteselectlayer.obj ogrsqlitesinglefeaturelayer.obj \
+		ogrsqlitevfs.obj
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
index 2f689d9..166fc93 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 20924 2010-10-21 21:02:41Z rouault $
+ * $Id: ogr_sqlite.h 23676 2012-01-01 16:10:36Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/SQLite driver.
@@ -33,14 +33,34 @@
 #include "ogrsf_frmts.h"
 #include "cpl_error.h"
 
-/* When used with Spatialite amalgation, there might be no sqlite3 headers */
-/* in other places than /include/spatialite/ subdir */
 #ifdef HAVE_SPATIALITE
-#include <spatialite/sqlite3.h>
+  #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
+
 /************************************************************************/
 /*      Format used to store geometry data in the database.             */
 /************************************************************************/
@@ -55,6 +75,74 @@ enum OGRSQLiteGeomFormat
 };
 
 /************************************************************************/
+/*      SpatiaLite's own Geometry type IDs.                             */
+/************************************************************************/
+
+enum OGRSpatialiteGeomType
+{
+// 2D [XY]
+    OGRSplitePointXY                     = 1,
+    OGRSpliteLineStringXY                = 2,
+    OGRSplitePolygonXY                   = 3,
+    OGRSpliteMultiPointXY                = 4,
+    OGRSpliteMultiLineStringXY           = 5,
+    OGRSpliteMultiPolygonXY              = 6,
+    OGRSpliteGeometryCollectionXY        = 7,
+// 3D [XYZ]
+    OGRSplitePointXYZ                    = 1001,
+    OGRSpliteLineStringXYZ               = 1002,
+    OGRSplitePolygonXYZ                  = 1003,
+    OGRSpliteMultiPointXYZ               = 1004,
+    OGRSpliteMultiLineStringXYZ          = 1005,
+    OGRSpliteMultiPolygonXYZ             = 1006,
+    OGRSpliteGeometryCollectionXYZ       = 1007,
+// 2D with Measure [XYM] 
+    OGRSplitePointXYM                    = 2001,
+    OGRSpliteLineStringXYM               = 2002,
+    OGRSplitePolygonXYM                  = 2003,
+    OGRSpliteMultiPointXYM               = 2004,
+    OGRSpliteMultiLineStringXYM          = 2005,
+    OGRSpliteMultiPolygonXYM             = 2006,
+    OGRSpliteGeometryCollectionXYM       = 2007,
+// 3D with Measure [XYZM]
+    OGRSplitePointXYZM                   = 3001,
+    OGRSpliteLineStringXYZM              = 3002,
+    OGRSplitePolygonXYZM                 = 3003,
+    OGRSpliteMultiPointXYZM              = 3004,
+    OGRSpliteMultiLineStringXYZM         = 3005,
+    OGRSpliteMultiPolygonXYZM            = 3006,
+    OGRSpliteGeometryCollectionXYZM      = 3007,
+// COMPRESSED: 2D [XY]
+    OGRSpliteComprLineStringXY           = 1000002,
+    OGRSpliteComprPolygonXY              = 1000003,
+    OGRSpliteComprMultiPointXY           = 1000004,
+    OGRSpliteComprMultiLineStringXY      = 1000005,
+    OGRSpliteComprMultiPolygonXY         = 1000006,
+    OGRSpliteComprGeometryCollectionXY   = 1000007,
+// COMPRESSED: 3D [XYZ]
+    OGRSpliteComprLineStringXYZ          = 1001002,
+    OGRSpliteComprPolygonXYZ             = 1001003,
+    OGRSpliteComprMultiPointXYZ          = 1001004,
+    OGRSpliteComprMultiLineStringXYZ     = 1001005,
+    OGRSpliteComprMultiPolygonXYZ        = 1001006,
+    OGRSpliteComprGeometryCollectionXYZ  = 1001007,
+// COMPRESSED: 2D with Measure [XYM]
+    OGRSpliteComprLineStringXYM          = 1002002,
+    OGRSpliteComprPolygonXYM             = 1002003,
+    OGRSpliteComprMultiPointXYM          = 1002004,
+    OGRSpliteComprMultiLineStringXYM     = 1002005,
+    OGRSpliteComprMultiPolygonXYM        = 1002006,
+    OGRSpliteComprGeometryCollectionXYM  = 1002007,
+// COMPRESSED: 3D with Measure [XYZM]
+    OGRSpliteComprLineStringXYZM         = 1003002,
+    OGRSpliteComprPolygonXYZM            = 1003003,
+    OGRSpliteComprMultiPointXYZM         = 1003004,
+    OGRSpliteComprMultiLineStringXYZM    = 1003005,
+    OGRSpliteComprMultiPolygonXYZM       = 1003006,
+    OGRSpliteComprGeometryCollectionXYZM = 1003007
+};
+
+/************************************************************************/
 /*                            OGRSQLiteLayer                            */
 /************************************************************************/
 
@@ -67,12 +155,25 @@ class OGRSQLiteLayer : public OGRLayer
                                                      OGRGeometry **ppoReturn,
                                                      int nBytes,
                                                      OGRwkbByteOrder eByteOrder,
-                                                     int* pnBytesConsumed);
+                                                     int* pnBytesConsumed,
+                                                     int nRecLevel);
+
+    static int          CanBeCompressedSpatialiteGeometry(const OGRGeometry *poGeometry);
+
+    static int          ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
+                                                      int bHasM, int bSpatialite2D,
+                                                      int bUseComprGeom );
+
+    static int          GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
+                                                  int bHasM, int bSpatialite2D,
+                                                  int bUseComprGeom,
+                                                  int bAcceptMultiGeom);
 
-    static int          ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry);
     static int          ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
                                                         OGRwkbByteOrder eByteOrder,
-                                                        GByte* pabyData);
+                                                        int bHasM, int bSpatialite2D,
+                                                        int bUseComprGeom,
+                                                        GByte* pabyData );
 
   protected:
     OGRFeatureDefn     *poFeatureDefn;
@@ -95,6 +196,12 @@ class OGRSQLiteLayer : public OGRLayer
 
     int                *panFieldOrdinals;
     int                 bHasSpatialIndex;
+    int                 bHasM;
+    int                 bSpatialiteReadOnly;
+    int                 bSpatialiteLoaded;
+    int                 iSpatialiteVersion;
+
+    int                 bIsVirtualShape;
 
     CPLErr              BuildFeatureDefn( const char *pszLayerName, 
                                           sqlite3_stmt *hStmt );
@@ -106,7 +213,9 @@ class OGRSQLiteLayer : public OGRLayer
                                                   OGRGeometry ** );
     static OGRErr       ExportSpatiaLiteGeometry( const OGRGeometry *,
                                                   GInt32, OGRwkbByteOrder,
-                                                  GByte **, int * );
+                                                  int, int, int bUseComprGeom, GByte **, int * );
+
+    int                 bUseComprGeom;
 
   public:
                         OGRSQLiteLayer();
@@ -130,6 +239,10 @@ class OGRSQLiteLayer : public OGRLayer
     virtual OGRErr       StartTransaction();
     virtual OGRErr       CommitTransaction();
     virtual OGRErr       RollbackTransaction();
+
+    virtual int          IsTableLayer() { return FALSE; }
+
+    int                  HasSpatialIndex() const { return bHasSpatialIndex; }
 };
 
 /************************************************************************/
@@ -138,16 +251,37 @@ class OGRSQLiteLayer : public OGRLayer
 
 class OGRSQLiteTableLayer : public OGRSQLiteLayer
 {
-    int                 bUpdateAccess;
     int                 bLaunderColumnNames;
+    int                 bSpatialite2D;
 
     CPLString           osWHERE;
     CPLString           osQuery;
+    int                 bHasCheckedSpatialIndexTable;
+
+    char               *pszEscapedTableName;
+
+    sqlite3_stmt       *hInsertStmt;
+    CPLString           osLastInsertStmt;
+    void                ClearInsertStmt();
 
     void                BuildWhere(void);
 
     OGRErr              ResetStatement();
 
+    OGRErr              AddColumnAncientMethod( OGRFieldDefn& oField);
+
+    void                InitFieldListForRecrerate(char* & pszNewFieldList,
+                                                  char* & pszFieldListForSelect,
+                                                  int nExtraSpace = 0);
+    OGRErr              RecreateTable(const char* pszFieldListForSelect,
+                                      const char* pszNewFieldList,
+                                      const char* pszGenericErrorMessage);
+    OGRErr              BindValues( OGRFeature *poFeature,
+                                        sqlite3_stmt* hStmt,
+                                        int bBindNullValues );
+
+    int                 CheckSpatialIndexTable();
+
   public:
                         OGRSQLiteTableLayer( OGRSQLiteDataSource * );
                         ~OGRSQLiteTableLayer();
@@ -158,26 +292,82 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
                                     const char *pszGeomFormat,
                                     OGRSpatialReference *poSRS,
                                     int nSRSId = -1,
-                                    int bHasSpatialIndex = FALSE);
+                                    int bHasSpatialIndex = FALSE,
+                                    int bHasM = FALSE,
+                                    int bSpatialiteReadOnly = FALSE,
+                                    int bSpatialiteLoaded = FALSE,
+                                    int iSpatialiteVersion = -1,
+                                    int bIsVirtualShapeIn = FALSE);
 
     virtual int         GetFeatureCount( int );
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
 
     virtual void        SetSpatialFilter( OGRGeometry * );
     virtual OGRErr      SetAttributeFilter( const char * );
     virtual OGRErr      SetFeature( OGRFeature *poFeature );
+    virtual OGRErr      DeleteFeature( long nFID );
     virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 
     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 OGRFeature *GetFeature( long nFeatureId );
-    
-    virtual OGRSpatialReference *GetSpatialRef();
 
     virtual int         TestCapability( const char * );
 
     // follow methods are not base class overrides
     void                SetLaunderFlag( int bFlag ) 
                                 { bLaunderColumnNames = bFlag; }
+    void                SetSpatialite2D( int bFlag ) 
+                                { bSpatialite2D = bFlag; }
+    void                SetUseCompressGeom( int bFlag )
+                                { bUseComprGeom = bFlag; }
+
+    virtual int          IsTableLayer() { return TRUE; }
+};
+
+/************************************************************************/
+/*                         OGRSQLiteViewLayer                           */
+/************************************************************************/
+
+class OGRSQLiteViewLayer : public OGRSQLiteLayer
+{
+    CPLString           osWHERE;
+    CPLString           osQuery;
+    int                 bHasCheckedSpatialIndexTable;
+
+    char               *pszEscapedTableName;
+    char               *pszEscapedUnderlyingTableName;
+
+    CPLString           osUnderlyingTableName;
+    CPLString           osUnderlyingGeometryColumn;
+
+    void                BuildWhere(void);
+
+    OGRErr              ResetStatement();
+
+  public:
+                        OGRSQLiteViewLayer( OGRSQLiteDataSource * );
+                        ~OGRSQLiteViewLayer();
+
+    CPLErr              Initialize( const char *pszViewName,
+                                    const char *pszViewGeometry,
+                                    const char *pszViewRowid,
+                                    const char *pszTableName,
+                                    const char *pszGeometryColumn,
+                                    int bSpatialiteLoaded);
+
+    virtual int         GetFeatureCount( int );
+
+    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual OGRErr      SetAttributeFilter( const char * );
+
+    virtual OGRFeature *GetFeature( long nFeatureId );
+
+    virtual int         TestCapability( const char * );
 };
 
 /************************************************************************/
@@ -231,6 +421,7 @@ class OGRSQLiteDataSource : public OGRDataSource
     char               *pszName;
 
     sqlite3             *hDB;
+    int                 bUpdate;
 
     int                 nSoftTransactionLevel;
 
@@ -245,18 +436,45 @@ class OGRSQLiteDataSource : public OGRDataSource
     
     virtual void        DeleteLayer( const char *pszLayer );
 
+    int                 DetectSRSWktColumn();
+
+    int                 OpenOrCreateDB(int flags);
+    int                 InitWithEPSG();
+    int                 SetSynchronous();
+    int                 SetCacheSize();
+
+    int                 OpenVirtualTable(const char* pszName, const char* pszSQL);
+
+#ifdef HAVE_SQLITE_VFS
+    sqlite3_vfs*        pMyVFS;
+#endif
+
   public:
                         OGRSQLiteDataSource();
                         ~OGRSQLiteDataSource();
 
-    int                 Open( const char * );
+    int                 Open( const char *, int bUpdateIn );
+    int                 Create( const char *, char **papszOptions );
+
     int                 OpenTable( const char *pszTableName, 
                                    const char *pszGeomCol = NULL,
                                    OGRwkbGeometryType eGeomType = wkbUnknown,
                                    const char *pszGeomFormat = NULL,
                                    OGRSpatialReference *poSRS = NULL,
                                    int nSRID = -1,
-                                   int bHasSpatialIndex = FALSE);
+                                   int bHasSpatialIndex = FALSE,
+                                   int bHasM = FALSE,
+                                   int bSpatialiteReadOnly = FALSE,
+                                   int bSpatialiteLoaded = FALSE,
+                                   int iSpatialiteVersion = -1,
+                                   int bForce2D = FALSE,
+                                   int bIsVirtualShapeIn = FALSE );
+    int                  OpenView( const char *pszViewName,
+                                   const char *pszViewGeometry,
+                                   const char *pszViewRowid,
+                                   const char *pszTableName,
+                                   const char *pszGeometryColumn,
+                                   int bSpatialiteLoaded);
 
     const char          *GetName() { return pszName; }
     int                 GetLayerCount() { return nLayers; }
@@ -286,6 +504,10 @@ class OGRSQLiteDataSource : public OGRDataSource
     char               *LaunderName( const char * );
     int                 FetchSRSId( OGRSpatialReference * poSRS );
     OGRSpatialReference*FetchSRS( int nSRID );
+
+    int                 GetUpdate() const { return bUpdate; }
+
+    void                SetName(const char* pszNameIn);
 };
 
 /************************************************************************/
@@ -294,9 +516,6 @@ class OGRSQLiteDataSource : public OGRDataSource
 
 class OGRSQLiteDriver : public OGRSFDriver
 {
-  private:
-    static int          InitWithEPSG(sqlite3* hDB, int bSpatialite);
-
   public:
                 ~OGRSQLiteDriver();
                 
@@ -305,10 +524,16 @@ class OGRSQLiteDriver : public OGRSFDriver
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
                                              char ** = NULL );
+    virtual OGRErr      DeleteDataSource( const char *pszName );
     
     int                 TestCapability( const char * );
 };
 
+CPLString OGRSQLiteEscape( const char *pszSrcName );
+int OGRSQLiteGetSpatialiteVersionNumber();
+#ifdef HAVE_SQLITE_VFS
+sqlite3_vfs* OGRSQLiteCreateVFS();
+#endif
 
 #endif /* ndef _OGR_SQLITE_H_INCLUDED */
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index e036ebb..93dc4ea 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -1,11 +1,18 @@
 /******************************************************************************
- * $Id: ogrsqlitedatasource.cpp 21298 2010-12-20 10:58:34Z rouault $
+ * $Id: ogrsqlitedatasource.cpp 23676 2012-01-01 16:10:36Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDataSource class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
+ *
+ * Contributor: Alessandro Furieri, a.furieri at lqt.it
+ * Portions of this module properly supporting SpatiaLite Table/Geom creation
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
+ *
+ ******************************************************************************
  * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -31,6 +38,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
+#include "cpl_csv.h"
 
 #ifdef HAVE_SPATIALITE
 #include "spatialite.h"
@@ -38,7 +46,39 @@
 
 static int bSpatialiteLoaded = FALSE;
 
-CPL_CVSID("$Id: ogrsqlitedatasource.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: ogrsqlitedatasource.cpp 23676 2012-01-01 16:10:36Z rouault $");
+
+/************************************************************************/
+/*                      OGRSQLiteInitSpatialite()                       */
+/************************************************************************/
+
+static int OGRSQLiteInitSpatialite()
+{
+/* -------------------------------------------------------------------- */
+/*      Try loading SpatiaLite.                                         */
+/* -------------------------------------------------------------------- */
+#ifdef HAVE_SPATIALITE
+    if (!bSpatialiteLoaded && CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
+    {
+        bSpatialiteLoaded = TRUE;
+        spatialite_init(CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
+    }
+#endif
+    return bSpatialiteLoaded;
+}
+
+/************************************************************************/
+/*               OGRSQLiteGetSpatialiteVersionNumber()                  */
+/************************************************************************/
+
+int OGRSQLiteGetSpatialiteVersionNumber()
+{
+    double v = 0.0;
+#ifdef HAVE_SPATIALITE
+    v = ( atof( spatialite_version() ) + 0.001 )  * 10.0;
+#endif
+    return (int)v;
+}
 
 /************************************************************************/
 /*                        OGRSQLiteDataSource()                         */
@@ -59,6 +99,13 @@ OGRSQLiteDataSource::OGRSQLiteDataSource()
 
     bHaveGeometryColumns = FALSE;
     bIsSpatiaLite = FALSE;
+    bUpdate = FALSE;
+
+    hDB = NULL;
+
+#ifdef HAVE_SQLITE_VFS
+    pMyVFS = NULL;
+#endif
 }
 
 /************************************************************************/
@@ -87,81 +134,556 @@ OGRSQLiteDataSource::~OGRSQLiteDataSource()
 
     if( hDB != NULL )
         sqlite3_close( hDB );
+
+#ifdef HAVE_SQLITE_VFS
+    if (pMyVFS)
+    {
+        sqlite3_vfs_unregister(pMyVFS);
+        CPLFree(pMyVFS);
+    }
+#endif
 }
 
 /************************************************************************/
-/*                                Open()                                */
-/*                                                                      */
-/*      Note, the Open() will implicitly create the database if it      */
-/*      does not already exist.                                         */
+/*                              SetSynchronous()                        */
 /************************************************************************/
 
-int OGRSQLiteDataSource::Open( const char * pszNewName )
+int OGRSQLiteDataSource::SetSynchronous()
+{
+    int rc;
+    const char* pszSqliteSync = CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL);
+    if (pszSqliteSync != NULL)
+    {
+        char* pszErrMsg = NULL;
+        if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
+            EQUAL(pszSqliteSync, "FALSE"))
+            rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
+        else if (EQUAL(pszSqliteSync, "NORMAL") || EQUAL(pszSqliteSync, "1"))
+            rc = sqlite3_exec( hDB, "PRAGMA synchronous = NORMAL", NULL, NULL, &pszErrMsg );
+        else if (EQUAL(pszSqliteSync, "ON") || EQUAL(pszSqliteSync, "FULL") ||
+            EQUAL(pszSqliteSync, "2") || EQUAL(pszSqliteSync, "TRUE"))
+            rc = sqlite3_exec( hDB, "PRAGMA synchronous = FULL", NULL, NULL, &pszErrMsg );
+        else
+        {
+            CPLError( CE_Warning, CPLE_AppDefined, "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
+                      pszSqliteSync);
+            rc = SQLITE_OK;
+        }
+
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to run PRAGMA synchronous : %s",
+                      pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              SetCacheSize()                          */
+/************************************************************************/
 
+int OGRSQLiteDataSource::SetCacheSize()
 {
-    CPLAssert( nLayers == 0 );
+    int rc;
+    const char* pszSqliteCacheMB = CPLGetConfigOption("OGR_SQLITE_CACHE", NULL);
+    if (pszSqliteCacheMB != NULL)
+    {
+        char* pszErrMsg = NULL;
+        char **papszResult;
+        int nRowCount, nColCount;
+        int iSqliteCachePages;
+        int iSqlitePageSize = -1;
+        int iSqliteCacheBytes = atoi( pszSqliteCacheMB ) * 1024 * 1024;
+
+        /* querying the current PageSize */
+        rc = sqlite3_get_table( hDB, "PRAGMA page_size",
+                                &papszResult, &nRowCount, &nColCount,
+                                &pszErrMsg );
+        if( rc == SQLITE_OK )
+        {
+            int iRow;
+            for (iRow = 1; iRow <= nRowCount; iRow++)
+            {
+                iSqlitePageSize = atoi( papszResult[(iRow * nColCount) + 0] );
+            }
+            sqlite3_free_table(papszResult);
+        }
+        if( iSqlitePageSize < 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to run PRAGMA page_size : %s",
+                      pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            return TRUE;
+        }
+		
+        /* computing the CacheSize as #Pages */
+        iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
+        if( iSqliteCachePages <= 0)
+            return TRUE;
+
+        rc = sqlite3_exec( hDB, CPLSPrintf( "PRAGMA cache_size = %d",
+                                            iSqliteCachePages ),
+                           NULL, NULL, &pszErrMsg );
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Unrecognized value for PRAGMA cache_size : %s",
+                      pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            rc = SQLITE_OK;
+        }
+    }
+    return TRUE;
+}
+
+/************************************************************************/
+/*                            OpenOrCreateDB()                          */
+/************************************************************************/
 
-    pszName = CPLStrdup( pszNewName );
+int OGRSQLiteDataSource::OpenOrCreateDB(int flags)
+{
+    int rc;
 
-/* -------------------------------------------------------------------- */
-/*      Try loading SpatiaLite.                                         */
-/* -------------------------------------------------------------------- */
-#ifdef HAVE_SPATIALITE
-    if (!bSpatialiteLoaded && CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
+#ifdef HAVE_SQLITE_VFS
+    int bUseOGRVFS = CSLTestBoolean(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO"));
+    if (bUseOGRVFS || strncmp(pszName, "/vsi", 4) == 0)
     {
-        bSpatialiteLoaded = TRUE;
-        spatialite_init(CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
+        pMyVFS = OGRSQLiteCreateVFS();
+        sqlite3_vfs_register(pMyVFS, 0);
+        rc = sqlite3_open_v2( pszName, &hDB, flags, pMyVFS->zName );
     }
+    else
+        rc = sqlite3_open_v2( pszName, &hDB, flags, NULL );
+#else
+    rc = sqlite3_open( pszName, &hDB );
 #endif
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "sqlite3_open(%s) failed: %s",
+                  pszName, sqlite3_errmsg( hDB ) );
+        return FALSE;
+    }
 
-    int bListAllTables = CSLTestBoolean(CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO"));
+    if (!SetCacheSize())
+        return FALSE;
+
+    if (!SetSynchronous())
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                               Create()                               */
+/************************************************************************/
+
+int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
+{
+    int rc;
+    CPLString osCommand;
+    char *pszErrMsg = NULL;
+
+    pszName = CPLStrdup( pszNameIn );
 
 /* -------------------------------------------------------------------- */
-/*      Try to open the sqlite database properly now.                   */
+/*      Check that spatialite extensions are loaded if required to      */
+/*      create a spatialite database                                    */
 /* -------------------------------------------------------------------- */
-    int rc;
+    int bSpatialite = CSLFetchBoolean( papszOptions, "SPATIALITE", FALSE );
+    int bMetadata = CSLFetchBoolean( papszOptions, "METADATA", TRUE );
 
-    hDB = NULL;
-    rc = sqlite3_open( pszNewName, &hDB );
-    if( rc != SQLITE_OK )
+    if (bSpatialite == TRUE)
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "sqlite3_open(%s) failed: %s", 
-                  pszNewName, sqlite3_errmsg( hDB ) );
-                  
+#ifdef HAVE_SPATIALITE
+        int bSpatialiteLoaded = OGRSQLiteInitSpatialite();
+        if (!bSpatialiteLoaded)
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                    "Creating a Spatialite database, but Spatialite extensions are not loaded." );
+            return FALSE;
+        }
+#else
+        CPLError( CE_Failure, CPLE_NotSupported,
+            "OGR was built without libspatialite support\n"
+            "... sorry, creating/writing any SpatiaLite DB is unsupported\n" );
+
         return FALSE;
+#endif
     }
 
-    char *pszErrMsg = NULL;
+    bIsSpatiaLite = bSpatialite;
 
-    const char* pszSqliteSync = CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL);
-    if (pszSqliteSync != NULL)
+/* -------------------------------------------------------------------- */
+/*      Create the database file.                                       */
+/* -------------------------------------------------------------------- */
+#ifdef HAVE_SQLITE_VFS
+    if (!OpenOrCreateDB(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE))
+#else
+    if (!OpenOrCreateDB(0))
+#endif
+        return FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Create the SpatiaLite metadata tables.                          */
+/* -------------------------------------------------------------------- */
+    if ( bSpatialite )
     {
-        if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
-            EQUAL(pszSqliteSync, "FALSE"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
-        else if (EQUAL(pszSqliteSync, "NORMAL") || EQUAL(pszSqliteSync, "1"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = NORMAL", NULL, NULL, &pszErrMsg );
-        else if (EQUAL(pszSqliteSync, "ON") || EQUAL(pszSqliteSync, "FULL") ||
-            EQUAL(pszSqliteSync, "2") || EQUAL(pszSqliteSync, "TRUE"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = FULL", NULL, NULL, &pszErrMsg );
-        else
+        /*
+        / SpatiaLite full support: calling InitSpatialMetadata()
+        /
+        / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
+        / to directly CREATE "geometry_columns" and "spatial_ref_sys"
+        / [by-passing InitSpatialMetadata() as absolutely required]
+        / will severely [and irremediably] corrupt the DB !!!
+        */
+        osCommand =  "SELECT InitSpatialMetadata()";
+        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
+        if( rc != SQLITE_OK )
         {
-            CPLError( CE_Warning, CPLE_AppDefined, "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
-                      pszSqliteSync);
-            rc = SQLITE_OK;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                "Unable to Initialize SpatiaLite Metadata: %s",
+                    pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            return FALSE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*  Create the geometry_columns and spatial_ref_sys metadata tables.    */
+/* -------------------------------------------------------------------- */
+    else if( bMetadata )
+    {
+        osCommand =
+            "CREATE TABLE geometry_columns ("
+            "     f_table_name VARCHAR, "
+            "     f_geometry_column VARCHAR, "
+            "     geometry_type INTEGER, "
+            "     coord_dimension INTEGER, "
+            "     srid INTEGER,"
+            "     geometry_format VARCHAR )";
+        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to create table geometry_columns: %s",
+                      pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            return FALSE;
         }
 
+        osCommand =
+            "CREATE TABLE spatial_ref_sys        ("
+            "     srid INTEGER UNIQUE,"
+            "     auth_name TEXT,"
+            "     auth_srid TEXT,"
+            "     srtext TEXT)";
+        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to create view geom_cols_ref_sys: %s",
+                      "Unable to create table spatial_ref_sys: %s",
                       pszErrMsg );
             sqlite3_free( pszErrMsg );
             return FALSE;
         }
     }
 
+/* -------------------------------------------------------------------- */
+/*      Optionnaly initialize the content of the spatial_ref_sys table  */
+/*      with the EPSG database                                          */
+/* -------------------------------------------------------------------- */
+    if ( (bSpatialite || bMetadata) &&
+         CSLFetchBoolean( papszOptions, "INIT_WITH_EPSG", FALSE ) )
+    {
+        if (!InitWithEPSG())
+            return FALSE;
+    }
+
+    return Open(pszName, TRUE);
+}
+
+/************************************************************************/
+/*                           InitWithEPSG()                             */
+/************************************************************************/
+
+int OGRSQLiteDataSource::InitWithEPSG()
+{
+    CPLString osCommand;
+    char* pszErrMsg = NULL;
+
+    if ( bIsSpatiaLite )
+    {
+        /*
+        / 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();
+        if ( iSpatialiteVersion >= 24 )
+            return TRUE;
+    }
+
+    int rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "Unable to insert into spatial_ref_sys: %s",
+                pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return FALSE;
+    }
+
+    FILE* fp;
+    int i;
+    for(i=0;i<2 && rc == SQLITE_OK;i++)
+    {
+        const char* pszFilename = (i == 0) ? "gcs.csv" : "pcs.csv";
+        fp = VSIFOpen(CSVFilename(pszFilename), "rt");
+        if (fp == NULL)
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                "Unable to open EPSG support file %s.\n"
+                "Try setting the GDAL_DATA environment variable to point to the\n"
+                "directory containing EPSG csv files.",
+                pszFilename );
+
+            continue;
+        }
+
+        OGRSpatialReference oSRS;
+        char** papszTokens;
+        CSLDestroy(CSVReadParseLine( fp ));
+        while ( (papszTokens = CSVReadParseLine( fp )) != NULL && rc == SQLITE_OK)
+        {
+            int nSRSId = atoi(papszTokens[0]);
+            CSLDestroy(papszTokens);
+
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            oSRS.importFromEPSG(nSRSId);
+            CPLPopErrorHandler();
+
+            if (bIsSpatiaLite)
+            {
+                char    *pszProj4 = NULL;
+
+                CPLPushErrorHandler(CPLQuietErrorHandler);
+                OGRErr eErr = oSRS.exportToProj4( &pszProj4 );
+                CPLPopErrorHandler();
+
+                char    *pszWKT = NULL;
+                if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
+                {
+                    CPLFree(pszWKT);
+                    pszWKT = NULL;
+                }
+
+                if( eErr == OGRERR_NONE )
+                {
+                    const char  *pszProjCS = oSRS.GetAttrValue("PROJCS");
+                    if (pszProjCS == NULL)
+                        pszProjCS = oSRS.GetAttrValue("GEOGCS");
+
+                    int bHasSrsWkt = FALSE;
+
+                /* testing for SRS_WKT column presence */
+                    char **papszResult;
+                    int nRowCount, nColCount;
+                    rc = sqlite3_get_table( hDB, "PRAGMA table_info(spatial_ref_sys)",
+                                            &papszResult, &nRowCount, &nColCount,
+                                            &pszErrMsg );
+
+                    if( rc == SQLITE_OK )
+                    {
+                        int iRow;
+                        for (iRow = 1; iRow <= nRowCount; iRow++)
+                        {
+                            if (EQUAL("srs_wkt",
+                                      papszResult[(iRow * nColCount) + 1]))
+                                bHasSrsWkt = TRUE;
+                        }
+                        sqlite3_free_table(papszResult);
+                    }
+
+                    if (bHasSrsWkt == TRUE)
+                    {
+                    /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
+                        if ( pszProjCS )
+                            osCommand.Printf(
+                                "INSERT INTO spatial_ref_sys "
+                                "(srid, auth_name, auth_srid, ref_sys_name, proj4text, srs_wkt) "
+                                "VALUES (%d, 'EPSG', '%d', ?, ?, ?)",
+                                nSRSId, nSRSId);
+                        else
+                            osCommand.Printf(
+                                "INSERT INTO spatial_ref_sys "
+                                "(srid, auth_name, auth_srid, proj4text, srs_wkt) "
+                                "VALUES (%d, 'EPSG', '%d', ?, ?)",
+                                nSRSId, nSRSId);
+                    }
+                    else
+                    {
+                    /* the SPATIAL_REF_SYS table does not support a SRS_WKT column */
+                        if ( pszProjCS )
+                            osCommand.Printf(
+                                "INSERT INTO spatial_ref_sys "
+                                "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
+                                "VALUES (%d, 'EPSG', '%d', ?, ?)",
+                                nSRSId, nSRSId);
+                        else
+                            osCommand.Printf(
+                                "INSERT INTO spatial_ref_sys "
+                                "(srid, auth_name, auth_srid, proj4text) "
+                                "VALUES (%d, 'EPSG', '%d', ?)",
+                                nSRSId, nSRSId);
+                    }
+
+                    sqlite3_stmt *hInsertStmt = NULL;
+                    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
+
+                    if ( pszProjCS )
+                    {
+                        if( rc == SQLITE_OK)
+                            rc = sqlite3_bind_text( hInsertStmt, 1, pszProjCS, -1, SQLITE_STATIC );
+                        if( rc == SQLITE_OK)
+                            rc = sqlite3_bind_text( hInsertStmt, 2, pszProj4, -1, SQLITE_STATIC );
+                        if (bHasSrsWkt == TRUE)
+                        {
+                        /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
+                            if( rc == SQLITE_OK && pszWKT != NULL)
+                                rc = sqlite3_bind_text( hInsertStmt, 3, pszWKT, -1, SQLITE_STATIC );
+                        }
+                    }
+                    else
+                    {
+                        if( rc == SQLITE_OK)
+                            rc = sqlite3_bind_text( hInsertStmt, 1, pszProj4, -1, SQLITE_STATIC );
+                        if (bHasSrsWkt == TRUE)
+                        {
+                        /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
+                            if( rc == SQLITE_OK && pszWKT != NULL)
+                                rc = sqlite3_bind_text( hInsertStmt, 2, pszWKT, -1, SQLITE_STATIC );
+                        }
+                    }
+
+                    if( rc == SQLITE_OK)
+                        rc = sqlite3_step( hInsertStmt );
+
+                    if( rc != SQLITE_OK && rc != SQLITE_DONE )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                    "Cannot insert %s into spatial_ref_sys : %s",
+                                    pszProj4,
+                                    sqlite3_errmsg(hDB) );
+
+                        sqlite3_finalize( hInsertStmt );
+                        CPLFree(pszProj4);
+                        CPLFree(pszWKT);
+                        break;
+                    }
+                    rc = SQLITE_OK;
+
+                    sqlite3_finalize( hInsertStmt );
+                }
+
+                CPLFree(pszProj4);
+                CPLFree(pszWKT);
+            }
+            else
+            {
+                char    *pszWKT = NULL;
+                if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
+                {
+                    osCommand.Printf(
+                        "INSERT INTO spatial_ref_sys "
+                        "(srid, auth_name, auth_srid, srtext) "
+                        "VALUES (%d, 'EPSG', '%d', ?)",
+                        nSRSId, nSRSId );
+
+                    sqlite3_stmt *hInsertStmt = NULL;
+                    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
+
+                    if( rc == SQLITE_OK)
+                        rc = sqlite3_bind_text( hInsertStmt, 1, pszWKT, -1, SQLITE_STATIC );
+
+                    if( rc == SQLITE_OK)
+                        rc = sqlite3_step( hInsertStmt );
+
+                    if( rc != SQLITE_OK && rc != SQLITE_DONE )
+                    {
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                    "Cannot insert %s into spatial_ref_sys : %s",
+                                    pszWKT,
+                                    sqlite3_errmsg(hDB) );
+
+                        sqlite3_finalize( hInsertStmt );
+                        CPLFree(pszWKT);
+                        break;
+                    }
+                    rc = SQLITE_OK;
+
+                    sqlite3_finalize( hInsertStmt );
+                }
+
+                CPLFree(pszWKT);
+            }
+        }
+        VSIFClose(fp);
+    }
+
+    if (rc == SQLITE_OK)
+        rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
+    else
+        rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, &pszErrMsg );
+
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "Unable to insert into spatial_ref_sys: %s",
+                pszErrMsg );
+        sqlite3_free( pszErrMsg );
+    }
+
+    return (rc == SQLITE_OK);
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn )
+
+{
+    CPLAssert( nLayers == 0 );
+
+    if (pszName == NULL)
+        pszName = CPLStrdup( pszNewName );
+    bUpdate = bUpdateIn;
+
+    int bListAllTables = CSLTestBoolean(CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO"));
+
+/* -------------------------------------------------------------------- */
+/*      Try to open the sqlite database properly now.                   */
+/* -------------------------------------------------------------------- */
+    if (hDB == NULL)
+    {
+        OGRSQLiteInitSpatialite();
+
+#ifdef HAVE_SQLITE_VFS
+        if (!OpenOrCreateDB((bUpdateIn) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY) )
+#else
+        if (!OpenOrCreateDB(0))
+#endif
+            return FALSE;
+    }
+
+    int rc;
+    char *pszErrMsg = NULL;
+
     CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
 
 /* -------------------------------------------------------------------- */
@@ -233,16 +755,45 @@ int OGRSQLiteDataSource::Open( const char * pszNewName )
 
     if ( rc == SQLITE_OK )
     {
-        CPLDebug("SQLITE", "SpatiaLite-style SQLite DB found !");
         
         bIsSpatiaLite = TRUE;
         bHaveGeometryColumns = TRUE;
 
+        int bSpatialiteReadOnly = TRUE;
+        int iSpatialiteVersion = -1;
+
+        /* Only enables write-mode if linked against SpatiaLite */
+        if( bSpatialiteLoaded == TRUE )
+        {
+            iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
+            bSpatialiteReadOnly = FALSE;
+        }
+
+        if (bSpatialiteReadOnly && bUpdate)
+        {
+            CPLDebug("SQLITE", "SpatiaLite-style SQLite DB found, but updating tables disabled because no linking against spatialite library !");
+        }
+        else
+        {
+            CPLDebug("SQLITE", "SpatiaLite-style SQLite DB found !");
+        }
+
+        /*
+        / SpatiaLite v.2.4.0 (or any subsequent) is required
+        / to support 2.5D: if an obsolete version of the library
+        / is found we'll unconditionally activate 2D casting mode
+        */
+        int bForce2D = FALSE;
+        iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
+        if ( iSpatialiteVersion < 24)
+            bForce2D = TRUE;
+
         for ( iRow = 0; iRow < nRowCount; iRow++ )
         {
             char **papszRow = papszResult + iRow * 6 + 6;
             OGRwkbGeometryType eGeomType;
             int nSRID = 0;
+            int bHasM = FALSE;
             int bHasSpatialIndex = FALSE;
 
             if (papszRow[0] == NULL ||
@@ -253,9 +804,16 @@ int OGRSQLiteDataSource::Open( const char * pszNewName )
 
             eGeomType = OGRFromOGCGeomType(papszRow[2]);
 
-            if( atoi(papszRow[3]) > 2 )
+            if( strcmp ( papszRow[3], "XYZ" ) == 0 || 
+                strcmp ( papszRow[3], "XYZM" ) == 0 || 
+                strcmp ( papszRow[3], "3" ) == 0) // SpatiaLite's own 3D geometries 
                 eGeomType = (OGRwkbGeometryType) (((int)eGeomType) | wkb25DBit);
 
+            if( strcmp ( papszRow[3], "XYM" ) == 0 || 
+                strcmp ( papszRow[3], "XYZM" ) == 0 ) // M coordinate declared 
+                bHasM = TRUE;
+
+
             if( papszRow[4] != NULL )
                 nSRID = atoi(papszRow[4]);
 
@@ -264,7 +822,9 @@ int OGRSQLiteDataSource::Open( const char * pszNewName )
                 bHasSpatialIndex = atoi(papszRow[5]);
 
             OpenTable( papszRow[0], papszRow[1], eGeomType, "SpatiaLite",
-                       FetchSRS( nSRID ), nSRID, bHasSpatialIndex );
+                       FetchSRS( nSRID ), nSRID, bHasSpatialIndex, bHasM, 
+                       bSpatialiteReadOnly, bSpatialiteLoaded,
+                       iSpatialiteVersion, bForce2D );
                        
             if (bListAllTables)
                 CPLHashSetInsert(hSet, CPLStrdup(papszRow[0]));
@@ -279,7 +839,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName )
         if (bSpatialiteLoaded)
         {
             rc = sqlite3_get_table( hDB,
-                                "SELECT name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE % USING %VirtualShape%'",
+                                "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
                                 &papszResult, &nRowCount, 
                                 &nColCount, &pszErrMsg );
 
@@ -287,10 +847,19 @@ int OGRSQLiteDataSource::Open( const char * pszNewName )
             {
                 for( iRow = 0; iRow < nRowCount; iRow++ )
                 {
-                    OpenTable( papszResult[iRow+1] );
-                    
-                    if (bListAllTables)
-                        CPLHashSetInsert(hSet, CPLStrdup(papszResult[iRow+1]));
+                    char **papszRow = papszResult + iRow * 2 + 2;
+                    const char *pszName = papszRow[0];
+                    const char *pszSQL = papszRow[1];
+                    if( pszName == NULL || pszSQL == NULL )
+                        continue;
+
+                    if( strstr(pszSQL, "VirtualShape") || strstr(pszSQL, "VirtualXL") )
+                    {
+                        OpenVirtualTable(pszName, pszSQL);
+
+                        if (bListAllTables)
+                            CPLHashSetInsert(hSet, CPLStrdup(pszName));
+                    }
                 }
             }
             else
@@ -305,6 +874,41 @@ int OGRSQLiteDataSource::Open( const char * pszNewName )
         }
 #endif
 
+/* -------------------------------------------------------------------- */
+/*      Detect spatial views                                            */
+/* -------------------------------------------------------------------- */
+        rc = sqlite3_get_table( hDB,
+                                "SELECT view_name, view_geometry, view_rowid, f_table_name, f_geometry_column FROM views_geometry_columns",
+                                &papszResult, &nRowCount,
+                                &nColCount, &pszErrMsg );
+        if ( rc == SQLITE_OK )
+        {
+            for( iRow = 0; iRow < nRowCount; iRow++ )
+            {
+                char **papszRow = papszResult + iRow * 5 + 5;
+                const char* pszViewName = papszRow[0];
+                const char* pszViewGeometry = papszRow[1];
+                const char* pszViewRowid = papszRow[2];
+                const char* pszTableName = papszRow[3];
+                const char* pszGeometryColumn = papszRow[4];
+
+                if (pszViewName == NULL ||
+                    pszViewGeometry == NULL ||
+                    pszViewRowid == NULL ||
+                    pszTableName == NULL ||
+                    pszGeometryColumn == NULL)
+                    continue;
+
+                OpenView( pszViewName, pszViewGeometry, pszViewRowid,
+                          pszTableName, pszGeometryColumn, bSpatialiteLoaded );
+
+                if (bListAllTables)
+                    CPLHashSetInsert(hSet, CPLStrdup(pszViewName));
+            }
+            sqlite3_free_table(papszResult);
+        }
+
+
         if (bListAllTables)
             goto all_tables;
 
@@ -353,6 +957,50 @@ all_tables:
 }
 
 /************************************************************************/
+/*                          OpenVirtualTable()                          */
+/************************************************************************/
+
+int OGRSQLiteDataSource::OpenVirtualTable(const char* pszName, const char* pszSQL)
+{
+    int nSRID = -1;
+    const char* pszVirtualShape = strstr(pszSQL, "VirtualShape");
+    if (pszVirtualShape != NULL)
+    {
+        const char* pszParenthesis = strchr(pszVirtualShape, '(');
+        if (pszParenthesis)
+        {
+            /* CREATE VIRTUAL TABLE table_name VirtualShape(shapename, codepage, srid) */
+            /* Extract 3rd parameter */
+            char** papszTokens = CSLTokenizeString2( pszParenthesis + 1, ",", CSLT_HONOURSTRINGS );
+            if (CSLCount(papszTokens) == 3)
+            {
+                nSRID = atoi(papszTokens[2]);
+            }
+            CSLDestroy(papszTokens);
+        }
+    }
+
+    if (OpenTable(pszName, NULL, wkbUnknown, NULL,
+                 (nSRID > 0) ? FetchSRS( nSRID ) : NULL, nSRID,
+                  FALSE, FALSE, TRUE, FALSE, -1, FALSE,
+                  pszVirtualShape != NULL))
+    {
+        OGRSQLiteLayer* poLayer = papoLayers[nLayers-1];
+        OGRFeature* poFeature = poLayer->GetNextFeature();
+        if (poFeature)
+        {
+            OGRGeometry* poGeom = poFeature->GetGeometryRef();
+            if (poGeom)
+                poLayer->GetLayerDefn()->SetGeomType(poGeom->getGeometryType());
+            delete poFeature;
+        }
+        poLayer->ResetReading();
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
 /*                             OpenTable()                              */
 /************************************************************************/
 
@@ -361,7 +1009,12 @@ int OGRSQLiteDataSource::OpenTable( const char *pszNewName,
                                     OGRwkbGeometryType eGeomType,
                                     const char *pszGeomFormat,
                                     OGRSpatialReference *poSRS, int nSRID,
-                                    int bHasSpatialIndex)
+                                    int bHasSpatialIndex, int bHasM, 
+                                    int bSpatialiteReadOnly,
+                                    int bSpatialiteLoaded,
+                                    int iSpatialiteVersion,
+                                    int bForce2D,
+                                    int bIsVirtualShapeIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -373,11 +1026,16 @@ int OGRSQLiteDataSource::OpenTable( const char *pszNewName,
 
     if( poLayer->Initialize( pszNewName, pszGeomCol, 
                              eGeomType, pszGeomFormat,
-                             poSRS, nSRID, bHasSpatialIndex ) != CE_None )
+                             poSRS, nSRID, bHasSpatialIndex, 
+                             bHasM, bSpatialiteReadOnly,
+                             bSpatialiteLoaded,
+                             iSpatialiteVersion,
+                             bIsVirtualShapeIn) != CE_None )
     {
         delete poLayer;
         return FALSE;
     }
+    poLayer->SetSpatialite2D ( bForce2D );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
@@ -390,6 +1048,43 @@ int OGRSQLiteDataSource::OpenTable( const char *pszNewName,
 }
 
 /************************************************************************/
+/*                             OpenView()                               */
+/************************************************************************/
+
+int OGRSQLiteDataSource::OpenView( const char *pszViewName,
+                                   const char *pszViewGeometry,
+                                   const char *pszViewRowid,
+                                   const char *pszTableName,
+                                   const char *pszGeometryColumn,
+                                   int bSpatialiteLoaded)
+
+{
+/* -------------------------------------------------------------------- */
+/*      Create the layer object.                                        */
+/* -------------------------------------------------------------------- */
+    OGRSQLiteViewLayer  *poLayer;
+
+    poLayer = new OGRSQLiteViewLayer( this );
+
+    if( poLayer->Initialize( pszViewName, pszViewGeometry,
+                             pszViewRowid, pszTableName, pszGeometryColumn,
+                             bSpatialiteLoaded ) != CE_None )
+    {
+        delete poLayer;
+        return FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add layer to data source layer list.                            */
+/* -------------------------------------------------------------------- */
+    papoLayers = (OGRSQLiteLayer **)
+        CPLRealloc( papoLayers,  sizeof(OGRSQLiteLayer *) * (nLayers+1) );
+    papoLayers[nLayers++] = poLayer;
+
+    return TRUE;
+}
+
+/************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
 
@@ -397,9 +1092,9 @@ int OGRSQLiteDataSource::TestCapability( const char * pszCap )
 
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
-        return TRUE;
+        return bUpdate;
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
-        return TRUE;
+        return bUpdate;
     else
         return FALSE;
 }
@@ -491,6 +1186,19 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
                   "In ExecuteSQL(): sqlite3_step(%s):\n  %s", 
                   pszSQLCommand, sqlite3_errmsg(GetDB()) );
         }
+
+        if( EQUALN(pszSQLCommand, "CREATE ", 7) )
+        {
+            char **papszTokens = CSLTokenizeString( pszSQLCommand );
+            if ( CSLCount(papszTokens) >= 4 &&
+                 EQUAL(papszTokens[1], "VIRTUAL") &&
+                 EQUAL(papszTokens[2], "TABLE") )
+            {
+                OpenVirtualTable(papszTokens[3], pszSQLCommand);
+            }
+            CSLDestroy(papszTokens);
+        }
+
         sqlite3_finalize( hSQLStmt );
         return NULL;
     }
@@ -559,12 +1267,29 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
 
 {
     char                *pszLayerName;
+    int                  bForce2D = FALSE;
     const char          *pszGeomFormat;
 
+/* -------------------------------------------------------------------- */
+/*      Verify we are in update mode.                                   */
+/* -------------------------------------------------------------------- */
+    if( !bUpdate )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Data source %s opened read-only.\n"
+                  "New layer %s cannot be created.\n",
+                  pszName, pszLayerNameIn );
+
+        return NULL;
+    }
+
     if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) )
         pszLayerName = LaunderName( pszLayerNameIn );
     else
         pszLayerName = CPLStrdup( pszLayerNameIn );
+
+    CPLString osEscapedLayerName = OGRSQLiteEscape(pszLayerName);
+    const char* pszEscapedLayerName = osEscapedLayerName.c_str();
     
     pszGeomFormat = CSLFetchNameValue( papszOptions, "FORMAT" );
     if( pszGeomFormat == NULL )
@@ -579,12 +1304,27 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
         && !EQUAL(pszGeomFormat,"WKB")
         && !EQUAL(pszGeomFormat, "SpatiaLite") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_NotSupported, 
                   "FORMAT=%s not recognised or supported.", 
                   pszGeomFormat );
         return NULL;
     }
 
+    if (bIsSpatiaLite && !EQUAL(pszGeomFormat, "SpatiaLite") )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "FORMAT=%s not support on a SpatiaLite enabled database.",
+                  pszGeomFormat );
+        return NULL;
+    }
+    if (bIsSpatiaLite && !bSpatialiteLoaded)
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Creating layers on a SpatiaLite enabled database, "
+                  "without Spatialite extensions loaded, is not supported." );
+        return NULL;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
@@ -634,7 +1374,7 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
     if( eType == wkbNone )
         osCommand.Printf( 
             "CREATE TABLE '%s' ( OGC_FID INTEGER PRIMARY KEY )", 
-            pszLayerName );
+            pszEscapedLayerName );
     else
     {
         if( EQUAL(pszGeomFormat,"WKT") )
@@ -644,16 +1384,35 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
                 "CREATE TABLE '%s' ( "
                 "  OGC_FID INTEGER PRIMARY KEY,"
                 "  %s VARCHAR )", 
-                pszLayerName, pszGeomCol );
+                pszEscapedLayerName, pszGeomCol );
         }
         else
         {
             pszGeomCol = "GEOMETRY";
-            osCommand.Printf(
-                "CREATE TABLE '%s' ( "
-                "  OGC_FID INTEGER PRIMARY KEY,"
-                "  %s BLOB )", 
-                pszLayerName, pszGeomCol );
+
+            /* Only if was created as a SpatiaLite DB */
+            if ( bIsSpatiaLite )
+            {
+                /* 
+                / SpatiaLite full support: we must create the 
+                / Geometry in a second time using AddGeometryColumn()
+                /
+                / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
+                / to directly creating some Geometry column 
+                / [by-passing AddGeometryColumn() as absolutely required]
+                / will severely [and irremediably] corrupt the DB !!!
+                */
+                osCommand.Printf( "CREATE TABLE '%s' ( "
+                                  "  OGC_FID INTEGER PRIMARY KEY)",
+                                  pszLayerName);
+            }
+            else
+            {
+                osCommand.Printf( "CREATE TABLE '%s' ( "
+                                  "  OGC_FID INTEGER PRIMARY KEY,"
+                                  "  %s BLOB )", 
+                                  pszLayerName, pszGeomCol );
+            }
         }
     }
 
@@ -686,7 +1445,7 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
          */
         osCommand.Printf(
             "DELETE FROM geometry_columns WHERE f_table_name = '%s'", 
-            pszLayerName );
+            pszEscapedLayerName );
                  
 #ifdef DEBUG
         CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
@@ -703,44 +1462,61 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
             nCoordDim = 2;
         else
             nCoordDim = 3;
+        
+        if ( bIsSpatiaLite )
+        {
+            /*
+            / SpatiaLite full support: calling AddGeometryColumn()
+            /
+            / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
+            / to directly INSERT a row into GEOMETRY_COLUMNS
+            / [by-passing AddGeometryColumn() as absolutely required]
+            / will severely [and irremediably] corrupt the DB !!!
+            */
+            const char *pszType = OGRToOGCGeomType(eType);
+            if (pszType[0] == '\0')
+                pszType = "GEOMETRY";
+
+            /*
+            / SpatiaLite v.2.4.0 (or any subsequent) is required
+            / to support 2.5D: if an obsolete version of the library
+            / is found we'll unconditionally activate 2D casting mode
+            */
+            int iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
+            if ( iSpatialiteVersion < 24 && nCoordDim == 3 )
+            {
+                CPLDebug("SQLITE", "Spatialite < 2.4.0 --> 2.5D geometry not supported. Casting to 2D");
+                nCoordDim = 2;
+                bForce2D = TRUE;
+            }
 
-        if( nSRSId > 0 )
+            osCommand.Printf( "SELECT AddGeometryColumn("
+                              "'%s', '%s', %d, '%s', %d)",
+                              pszLayerName, pszGeomCol, nSRSId,
+                              pszType, nCoordDim );
+        }
+        else
         {
-            if ( bIsSpatiaLite )
-                osCommand.Printf(
-                    "INSERT INTO geometry_columns "
-                    "(f_table_name, f_geometry_column, type, "
-                    "coord_dimension, srid, spatial_index_enabled) "
-                    "VALUES ('%s','%s', '%s', %d, %d, 0)", 
-                    pszLayerName, pszGeomCol, OGRToOGCGeomType(eType),
-                    nCoordDim, nSRSId );
-            else
+            if( nSRSId > 0 )
+            {
                 osCommand.Printf(
                     "INSERT INTO geometry_columns "
                     "(f_table_name, f_geometry_column, geometry_format, "
                     "geometry_type, coord_dimension, srid) VALUES "
                     "('%s','%s','%s', %d, %d, %d)", 
-                    pszLayerName, pszGeomCol, pszGeomFormat,
+                    pszEscapedLayerName, pszGeomCol, pszGeomFormat,
                     (int) wkbFlatten(eType), nCoordDim, nSRSId );
-        }
-        else
-        {
-            if ( bIsSpatiaLite )
-                osCommand.Printf(
-                    "INSERT INTO geometry_columns "
-                    "(f_table_name, f_geometry_column, type, "
-                    "coord_dimension, spatial_index_enabled) "
-                    "VALUES ('%s','%s', '%s', %d, 0)", 
-                    pszLayerName, pszGeomCol, OGRToOGCGeomType(eType),
-                    nCoordDim );
+            }
             else
+            {
                 osCommand.Printf(
                     "INSERT INTO geometry_columns "
                     "(f_table_name, f_geometry_column, geometry_format, "
                     "geometry_type, coord_dimension) VALUES "
-                    "('%s','%s','%s', %d, %d)", 
-                    pszLayerName, pszGeomCol, pszGeomFormat,
+                    "('%s','%s','%s', %d, %d)",
+                    pszEscapedLayerName, pszGeomCol, pszGeomFormat,
                     (int) wkbFlatten(eType), nCoordDim );
+            }
         }
 
 #ifdef DEBUG
@@ -763,6 +1539,15 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
 /*      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) &&
+             (bIsSpatiaLite || EQUAL(pszGeomFormat, "SpatiaLite")) && !bSpatialiteLoaded )
+        {
+            CPLError( CE_Warning, CPLE_OpenFailed,
+                    "Cannot create a spatial index when Spatialite extensions are not loaded." );
+        }
+
 #ifdef HAVE_SPATIALITE
         /* Only if linked against SpatiaLite and the datasource was created as a SpatiaLite DB */
         if ( bIsSpatiaLite && bSpatialiteLoaded )
@@ -770,11 +1555,10 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
         if ( 0 )
 #endif
         {
-            const char* pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
             if( pszSI == NULL || CSLTestBoolean(pszSI) )
             {
                 osCommand.Printf("SELECT CreateSpatialIndex('%s', '%s')",
-                                 pszLayerName, pszGeomCol);
+                                 pszEscapedLayerName, pszGeomCol);
 
                 rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
                 if( rc != SQLITE_OK )
@@ -804,6 +1588,9 @@ OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
     }
 
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
+    if ( CSLFetchBoolean(papszOptions,"COMPRESS_GEOM",FALSE) )
+        poLayer->SetUseCompressGeom( TRUE );
+    poLayer->SetSpatialite2D ( bForce2D );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
@@ -831,7 +1618,7 @@ char *OGRSQLiteDataSource::LaunderName( const char *pszSrcName )
     for( i = 0; pszSafeName[i] != '\0'; i++ )
     {
         pszSafeName[i] = (char) tolower( pszSafeName[i] );
-        if( pszSafeName[i] == '-' || pszSafeName[i] == '#' )
+        if( pszSafeName[i] == '\'' || pszSafeName[i] == '-' || pszSafeName[i] == '#' )
             pszSafeName[i] = '_';
     }
 
@@ -839,6 +1626,22 @@ char *OGRSQLiteDataSource::LaunderName( const char *pszSrcName )
 }
 
 /************************************************************************/
+/*                          OGRSQLiteEscape()                           */
+/************************************************************************/
+
+CPLString OGRSQLiteEscape( const char *pszSrcName )
+{
+    CPLString osVal;
+    for( int i = 0; pszSrcName[i] != '\0'; i++ )
+    {
+        if ( pszSrcName[i] == '\'' )
+            osVal += '\'';
+        osVal += pszSrcName[i];
+    }
+    return osVal;
+}
+
+/************************************************************************/
 /*                            DeleteLayer()                             */
 /************************************************************************/
 
@@ -848,6 +1651,19 @@ void OGRSQLiteDataSource::DeleteLayer( const char *pszLayerName )
     int iLayer;
 
 /* -------------------------------------------------------------------- */
+/*      Verify we are in update mode.                                   */
+/* -------------------------------------------------------------------- */
+    if( !bUpdate )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Data source %s opened read-only.\n"
+                  "Layer %s cannot be deleted.\n",
+                  pszName, pszLayerName );
+
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Try to find layer.                                              */
 /* -------------------------------------------------------------------- */
     for( iLayer = 0; iLayer < nLayers; iLayer++ )
@@ -882,6 +1698,7 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
     }
 
     CPLString osLayerName = GetLayer(iLayer)->GetName();
+    CPLString osGeometryColumn = GetLayer(iLayer)->GetGeometryColumn();
 
 /* -------------------------------------------------------------------- */
 /*      Blow away our OGR structures related to the layer.  This is     */
@@ -900,7 +1717,11 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
     int rc;
     char *pszErrMsg;
 
-    rc = sqlite3_exec( hDB, CPLSPrintf( "DROP TABLE '%s'", osLayerName.c_str() ),
+    CPLString osEscapedLayerName = OGRSQLiteEscape(osLayerName);
+    const char* pszEscapedLayerName = osEscapedLayerName.c_str();
+    const char* pszGeometryColumn = osGeometryColumn.size() ? osGeometryColumn.c_str() : NULL;
+
+    rc = sqlite3_exec( hDB, CPLSPrintf( "DROP TABLE '%s'", pszEscapedLayerName ),
                        NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
@@ -920,7 +1741,7 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
 
         osCommand.Printf( 
             "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
-            osLayerName.c_str() );
+            pszEscapedLayerName );
         
         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
         if( rc != SQLITE_OK )
@@ -931,6 +1752,28 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
             sqlite3_free( pszErrMsg );
             return OGRERR_FAILURE;
         }
+
+/* -------------------------------------------------------------------- */
+/*      Drop spatialite spatial index tables                            */
+/* -------------------------------------------------------------------- */
+        if( bIsSpatiaLite && pszGeometryColumn )
+        {
+            osCommand.Printf( "DROP TABLE idx_%s_%s", pszEscapedLayerName,
+                              pszGeometryColumn);
+            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+
+            osCommand.Printf( "DROP TABLE idx_%s_%s_node", pszEscapedLayerName,
+                              pszGeometryColumn);
+            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+
+            osCommand.Printf( "DROP TABLE idx_%s_%s_parent", pszEscapedLayerName,
+                              pszGeometryColumn);
+            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+
+            osCommand.Printf( "DROP TABLE idx_%s_%s_rowid", pszEscapedLayerName,
+                              pszGeometryColumn);
+            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
+        }
     }
     return OGRERR_NONE;
 }
@@ -1070,6 +1913,41 @@ OGRErr OGRSQLiteDataSource::FlushSoftTransaction()
 }
 
 /************************************************************************/
+/*                            DetectSRSWktColumn()                            */
+/************************************************************************/
+
+int OGRSQLiteDataSource::DetectSRSWktColumn()
+{
+    int bHasSrsWkt = FALSE;
+
+/* testing for SRS_WKT column presence */
+    char **papszResult;
+    int nRowCount, nColCount;
+    char *pszErrMsg = NULL;
+    int rc = sqlite3_get_table( hDB, "PRAGMA table_info(spatial_ref_sys)",
+                            &papszResult, &nRowCount, &nColCount,
+                            &pszErrMsg );
+
+    if( rc == SQLITE_OK )
+    {
+        int iRow;
+        for (iRow = 1; iRow <= nRowCount; iRow++)
+        {
+            if (EQUAL("srs_wkt",
+                        papszResult[(iRow * nColCount) + 1]))
+                bHasSrsWkt = TRUE;
+        }
+        sqlite3_free_table(papszResult);
+    }
+    else
+    {
+        sqlite3_free( pszErrMsg );
+    }
+
+    return bHasSrsWkt;
+}
+
+/************************************************************************/
 /*                             FetchSRSId()                             */
 /*                                                                      */
 /*      Fetch the id corresponding to an SRS, and if not found, add     */
@@ -1188,25 +2066,25 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      Search for existing record using either WKT definition or       */
 /*      PROJ.4 string (SpatiaLite variant).                             */
 /* -------------------------------------------------------------------- */
-    CPLString   osSRS;
+    CPLString   osWKT, osProj4;
 
-    if ( !bIsSpatiaLite )
-    {
 /* -------------------------------------------------------------------- */
 /*      Translate SRS to WKT.                                           */
 /* -------------------------------------------------------------------- */
-        char    *pszWKT = NULL;
+    char    *pszWKT = NULL;
 
-        if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
-        {
-            CPLFree(pszWKT);
-            return -1;
-        }
+    if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
+    {
+        CPLFree(pszWKT);
+        return -1;
+    }
 
-        osSRS = pszWKT;
-        CPLFree( pszWKT );
-        pszWKT = NULL;
+    osWKT = pszWKT;
+    CPLFree( pszWKT );
+    pszWKT = NULL;
 
+    if ( !bIsSpatiaLite )
+    {
 /* -------------------------------------------------------------------- */
 /*      Try to find based on the WKT match.                             */
 /* -------------------------------------------------------------------- */
@@ -1229,7 +2107,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
             return -1;
         }
 
-        osSRS = pszProj4;
+        osProj4 = pszProj4;
         CPLFree( pszProj4 );
         pszProj4 = NULL;
 
@@ -1244,7 +2122,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     rc = sqlite3_prepare( hDB, osCommand, -1, &hSelectStmt, NULL );
 
     if( rc == SQLITE_OK)
-        rc = sqlite3_bind_text( hSelectStmt, 1, osSRS.c_str(), -1, SQLITE_STATIC );
+        rc = sqlite3_bind_text( hSelectStmt, 1, ( !bIsSpatiaLite ) ? osWKT.c_str() : osProj4.c_str(), -1, SQLITE_STATIC );
 
     if( rc == SQLITE_OK)
         rc = sqlite3_step( hSelectStmt );
@@ -1327,7 +2205,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      Try adding the SRS to the SRS table.                            */
 /* -------------------------------------------------------------------- */
 
-    const char* apszToInsert[] = { NULL, NULL, NULL, NULL, NULL };
+    const char* apszToInsert[] = { NULL, NULL, NULL, NULL, NULL, NULL };
 
     if ( !bIsSpatiaLite )
     {
@@ -1337,7 +2215,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                 "INSERT INTO spatial_ref_sys (srid,srtext,auth_name,auth_srid) "
                 "                     VALUES (%d, ?, ?, ?)",
                 nSRSId );
-            apszToInsert[0] = osSRS.c_str();
+            apszToInsert[0] = osWKT.c_str();
             apszToInsert[1] = pszAuthorityName;
             apszToInsert[2] = pszAuthorityCode;
         }
@@ -1347,11 +2225,13 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                 "INSERT INTO spatial_ref_sys (srid,srtext) "
                 "                     VALUES (%d, ?)",
                 nSRSId );
-            apszToInsert[0] = osSRS.c_str();
+            apszToInsert[0] = osWKT.c_str();
         }
     }
     else
     {
+        int bHasSrsWkt = DetectSRSWktColumn();
+
         const char  *pszProjCS = oSRS.GetAttrValue("PROJCS");
         if (pszProjCS == NULL)
             pszProjCS = oSRS.GetAttrValue("GEOGCS");
@@ -1362,24 +2242,30 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
             {
                 osCommand.Printf(
                     "INSERT INTO spatial_ref_sys "
-                    "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
-                    "VALUES (%d, ?, ?, ?, ?)",
-                    nSRSId );
+                    "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) "
+                    "VALUES (%d, ?, ?, ?, ?%s)",
+                    bHasSrsWkt ? ", srs_wkt" : "",
+                    nSRSId,
+                    bHasSrsWkt ? ", ?" : "");
                 apszToInsert[0] = pszAuthorityName;
                 apszToInsert[1] = pszAuthorityCode;
                 apszToInsert[2] = pszProjCS;
-                apszToInsert[3] = osSRS.c_str();
+                apszToInsert[3] = osProj4.c_str();
+                apszToInsert[4] = bHasSrsWkt ? osWKT.c_str() : NULL;
             }
             else
             {
                 osCommand.Printf(
                     "INSERT INTO spatial_ref_sys "
-                    "(srid, auth_name, auth_srid, proj4text) "
-                    "VALUES (%d, ?, ?, ?)",
-                    nSRSId );
+                    "(srid, auth_name, auth_srid, proj4text%s) "
+                    "VALUES (%d, ?, ?, ?%s)",
+                    bHasSrsWkt ? ", srs_wkt" : "",
+                    nSRSId,
+                    bHasSrsWkt ? ", ?" : "");
                 apszToInsert[0] = pszAuthorityName;
                 apszToInsert[1] = pszAuthorityCode;
-                apszToInsert[2] = osSRS.c_str();
+                apszToInsert[2] = osProj4.c_str();
+                apszToInsert[3] = bHasSrsWkt ? osWKT.c_str() : NULL;
             }
         }
         else
@@ -1390,18 +2276,24 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
             {
                 osCommand.Printf(
                     "INSERT INTO spatial_ref_sys "
-                    "(srid, auth_name, auth_srid, ref_sys_name, proj4text) VALUES (%d, 'OGR', %d, ?, ?)",
-                    nSRSId, nSRSId );
+                    "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) VALUES (%d, 'OGR', %d, ?, ?%s)",
+                    bHasSrsWkt ? ", srs_wkt" : "",
+                    nSRSId, nSRSId,
+                    bHasSrsWkt ? ", ?" : "");
                 apszToInsert[0] = pszProjCS;
-                apszToInsert[1] = osSRS.c_str();
+                apszToInsert[1] = osProj4.c_str();
+                apszToInsert[2] = bHasSrsWkt ? osWKT.c_str() : NULL;
             }
             else
             {
                 osCommand.Printf(
                     "INSERT INTO spatial_ref_sys "
-                    "(srid, auth_name, auth_srid, proj4text) VALUES (%d, 'OGR', %d, ?)",
-                    nSRSId, nSRSId );
-                apszToInsert[0] = osSRS.c_str();
+                    "(srid, auth_name, auth_srid, proj4text%s) VALUES (%d, 'OGR', %d, ?%s)",
+                    bHasSrsWkt ? ", srs_wkt" : "",
+                    nSRSId, nSRSId,
+                    bHasSrsWkt ? ", ?" : "");
+                apszToInsert[0] = osProj4.c_str();
+                apszToInsert[1] = bHasSrsWkt ? osWKT.c_str() : NULL;
             }
         }
     }
@@ -1505,15 +2397,19 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
 
 /* -------------------------------------------------------------------- */
 /*      Next try SpatiaLite flavour. SpatiaLite uses PROJ.4 strings     */
-/*      in 'proj4text' column instead of WKT in 'srtext'.               */
+/*      in 'proj4text' column instead of WKT in 'srtext'. Note: recent  */
+/*      versions of spatialite have a srs_wkt column too                */
 /* -------------------------------------------------------------------- */
     else
     {
         sqlite3_free( pszErrMsg );
         pszErrMsg = NULL;
 
+        int bHasSrsWkt = DetectSRSWktColumn();
+
         osCommand.Printf(
-            "SELECT proj4text, auth_name, auth_srid FROM spatial_ref_sys WHERE srid = %d", nId );
+            "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys WHERE srid = %d",
+            bHasSrsWkt ? ", srs_wkt" : "", nId );
         rc = sqlite3_get_table( hDB, osCommand, 
                                 &papszResult, &nRowCount,
                                 &nColCount, &pszErrMsg );
@@ -1531,26 +2427,35 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
             char** papszRow = papszResult + nColCount;
 
             const char* pszProj4Text = papszRow[0];
-            if (pszProj4Text != NULL)
-            {
-                const char* pszAuthName = papszRow[1];
-                int nAuthSRID = (papszRow[2] != NULL) ? atoi(papszRow[2]) : 0;
+            const char* pszAuthName = papszRow[1];
+            int nAuthSRID = (papszRow[2] != NULL) ? atoi(papszRow[2]) : 0;
+            char* pszWKT = (bHasSrsWkt) ? (char*) papszRow[3] : NULL;
 
-                poSRS = new OGRSpatialReference();
+            poSRS = new OGRSpatialReference();
 
-                /* Try first from EPSG code */
-                if (pszAuthName != NULL &&
-                    EQUAL(pszAuthName, "EPSG") &&
-                    poSRS->importFromEPSG( nAuthSRID ) == OGRERR_NONE)
-                {
-                    /* Do nothing */
-                }
-                /* Then from Proj4 string */
-                else if( poSRS->importFromProj4( pszProj4Text ) != OGRERR_NONE )
-                {
-                    delete poSRS;
-                    poSRS = NULL;
-                }
+            /* Try first from EPSG code */
+            if (pszAuthName != NULL &&
+                EQUAL(pszAuthName, "EPSG") &&
+                poSRS->importFromEPSG( nAuthSRID ) == OGRERR_NONE)
+            {
+                /* Do nothing */
+            }
+            /* Then from WKT string */
+            else if( pszWKT != NULL &&
+                     poSRS->importFromWkt( &pszWKT ) == OGRERR_NONE )
+            {
+                /* Do nothing */
+            }
+            /* Finally from Proj4 string */
+            else if( pszProj4Text != NULL &&
+                     poSRS->importFromProj4( pszProj4Text ) == OGRERR_NONE )
+            {
+                /* Do nothing */
+            }
+            else
+            {
+                delete poSRS;
+                poSRS = NULL;
             }
 
             sqlite3_free_table(papszResult);
@@ -1580,3 +2485,13 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
 
     return poSRS;
 }
+
+/************************************************************************/
+/*                              SetName()                               */
+/************************************************************************/
+
+void OGRSQLiteDataSource::SetName(const char* pszNameIn)
+{
+    CPLFree(pszName);
+    pszName = CPLStrdup(pszNameIn);
+}
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
index e0d583f..9a3b45c 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
@@ -1,11 +1,18 @@
 /******************************************************************************
- * $Id: ogrsqlitedriver.cpp 20521 2010-09-04 14:22:20Z rouault $
+ * $Id: ogrsqlitedriver.cpp 23410 2011-11-21 22:00:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDriver class.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
+ *
+ * Contributor: Alessandro Furieri, a.furieri at lqt.it
+ * Portions of this module properly supporting SpatiaLite DB creation
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
+ *
+ ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -29,9 +36,8 @@
 
 #include "ogr_sqlite.h"
 #include "cpl_conv.h"
-#include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrsqlitedriver.cpp 20521 2010-09-04 14:22:20Z rouault $");
+CPL_CVSID("$Id: ogrsqlitedriver.cpp 23410 2011-11-21 22:00:11Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRSQLiteDriver()                        */
@@ -60,21 +66,79 @@ OGRDataSource *OGRSQLiteDriver::Open( const char * pszFilename,
                                      int bUpdate )
 
 {
+
+/* -------------------------------------------------------------------- */
+/*      Check VirtualShape:xxx.shp syntax                               */
+/* -------------------------------------------------------------------- */
+    int nLen = (int) strlen(pszFilename);
+    if (EQUALN(pszFilename, "VirtualShape:", strlen( "VirtualShape:" )) &&
+        nLen > 4 && EQUAL(pszFilename + nLen - 4, ".SHP"))
+    {
+        OGRSQLiteDataSource     *poDS;
+
+        poDS = new OGRSQLiteDataSource();
+
+        char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
+        int nRet = poDS->Create( ":memory:", papszOptions );
+        poDS->SetName(pszFilename);
+        CSLDestroy(papszOptions);
+        if (!nRet)
+        {
+            delete poDS;
+            return NULL;
+        }
+
+        char* pszShapeFilename = CPLStrdup(pszFilename + strlen( "VirtualShape:" ));
+        OGRDataSource* poShapeDS = OGRSFDriverRegistrar::Open(pszShapeFilename);
+        if (poShapeDS == NULL)
+        {
+            CPLFree(pszShapeFilename);
+            delete poDS;
+            return NULL;
+        }
+        delete poShapeDS;
+
+        char* pszLastDot = strrchr(pszShapeFilename, '.');
+        if (pszLastDot)
+            *pszLastDot = '\0';
+
+        const char* pszTableName = CPLGetBasename(pszShapeFilename);
+
+        char* pszSQL = CPLStrdup(CPLSPrintf("CREATE VIRTUAL TABLE %s USING VirtualShape(%s, CP1252, -1)",
+                                            pszTableName, pszShapeFilename));
+        poDS->ExecuteSQL(pszSQL, NULL, NULL);
+        CPLFree(pszSQL);
+        CPLFree(pszShapeFilename);
+        return poDS;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Verify that the target is a real file, and has an               */
 /*      appropriate magic string at the beginning.                      */
 /* -------------------------------------------------------------------- */
-    FILE *fpDB;
     char szHeader[16];
+
+#ifdef HAVE_SQLITE_VFS
+    VSILFILE *fpDB;
+    fpDB = VSIFOpenL( pszFilename, "rb" );
+    if( fpDB == NULL )
+        return NULL;
+    
+    if( VSIFReadL( szHeader, 1, 16, fpDB ) != 16 )
+        memset( szHeader, 0, 16 );
     
+    VSIFCloseL( fpDB );
+#else
+    FILE *fpDB;
     fpDB = VSIFOpen( pszFilename, "rb" );
     if( fpDB == NULL )
         return NULL;
-    
+
     if( VSIFRead( szHeader, 1, 16, fpDB ) != 16 )
         memset( szHeader, 0, 16 );
-    
+
     VSIFClose( fpDB );
+#endif
     
     if( strncmp( szHeader, "SQLite format 3", 15 ) != 0 )
         return NULL;
@@ -87,7 +151,7 @@ OGRDataSource *OGRSQLiteDriver::Open( const char * pszFilename,
 
     poDS = new OGRSQLiteDataSource();
 
-    if( !poDS->Open( pszFilename ) )
+    if( !poDS->Open( pszFilename, bUpdate ) )
     {
         delete poDS;
         return NULL;
@@ -107,9 +171,9 @@ OGRDataSource *OGRSQLiteDriver::CreateDataSource( const char * pszName,
 /* -------------------------------------------------------------------- */
 /*      First, ensure there isn't any such file yet.                    */
 /* -------------------------------------------------------------------- */
-    VSIStatBuf sStatBuf;
+    VSIStatBufL sStatBuf;
 
-    if( VSIStat( pszName, &sStatBuf ) == 0 )
+    if( VSIStatL( pszName, &sStatBuf ) == 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "It seems a file system object called '%s' already exists.",
@@ -119,377 +183,31 @@ OGRDataSource *OGRSQLiteDriver::CreateDataSource( const char * pszName,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Create the database file.                                       */
+/*      Try to create datasource.                                       */
 /* -------------------------------------------------------------------- */
-    sqlite3             *hDB;
-    int rc;
-
-    hDB = NULL;
-    rc = sqlite3_open( pszName, &hDB );
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "sqlite3_open(%s) failed: %s", 
-                  pszName, sqlite3_errmsg( hDB ) );
-        return NULL;
-    }
-
-    int bSpatialite = CSLFetchBoolean( papszOptions, "SPATIALITE", FALSE );
-    int bMetadata = CSLFetchBoolean( papszOptions, "METADATA", TRUE );
-
-    CPLString osCommand;
-    char *pszErrMsg = NULL;
-
-    const char* pszSqliteSync = CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL);
-    if (pszSqliteSync != NULL)
-    {
-        if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
-            EQUAL(pszSqliteSync, "FALSE"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
-        else if (EQUAL(pszSqliteSync, "NORMAL") || EQUAL(pszSqliteSync, "1"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = NORMAL", NULL, NULL, &pszErrMsg );
-        else if (EQUAL(pszSqliteSync, "ON") || EQUAL(pszSqliteSync, "FULL") ||
-            EQUAL(pszSqliteSync, "2") || EQUAL(pszSqliteSync, "TRUE"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = FULL", NULL, NULL, &pszErrMsg );
-        else
-        {
-            CPLError( CE_Warning, CPLE_AppDefined, "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
-                      pszSqliteSync);
-            rc = SQLITE_OK;
-        }
-
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to create view geom_cols_ref_sys: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            sqlite3_close( hDB );
-            return NULL;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create the SpatiaLite metadata tables.                          */
-/* -------------------------------------------------------------------- */
-    if ( bSpatialite )
-    {
-        osCommand = 
-            "CREATE TABLE geometry_columns ("
-            "     f_table_name VARCHAR NOT NULL, "
-            "     f_geometry_column VARCHAR NOT NULL, "
-            "     type VARCHAR NOT NULL, "
-            "     coord_dimension INTEGER NOT NULL, "
-            "     srid INTEGER,"
-            "     spatial_index_enabled INTEGER NOT NULL)";
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to create table geometry_columns: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            sqlite3_close( hDB );
-            return NULL;
-        }
-
-        osCommand = 
-            "CREATE TABLE spatial_ref_sys        ("
-            "     srid INTEGER NOT NULL PRIMARY KEY,"
-            "     auth_name VARCHAR NOT NULL,"
-            "     auth_srid INTEGER NOT NULL,"
-            "     ref_sys_name VARCHAR,"
-            "     proj4text VARCHAR NOT NULL,"
-            "     srs_wkt VARCHAR)";
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to create table spatial_ref_sys: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            sqlite3_close( hDB );
-            return NULL;
-        }
+    OGRSQLiteDataSource     *poDS;
 
-        osCommand = 
-            "CREATE VIEW geom_cols_ref_sys AS"
-            "   SELECT f_table_name, f_geometry_column, type,"
-            "          coord_dimension, spatial_ref_sys.srid AS srid,"
-            "          auth_name, auth_srid, ref_sys_name, proj4text"
-            "   FROM geometry_columns, spatial_ref_sys"
-            "   WHERE geometry_columns.srid = spatial_ref_sys.srid";
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to create view geom_cols_ref_sys: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            sqlite3_close( hDB );
-            return NULL;
-        }
-    }
+    poDS = new OGRSQLiteDataSource();
 
-/* -------------------------------------------------------------------- */
-/*  Create the geometry_columns and spatial_ref_sys metadata tables.    */
-/* -------------------------------------------------------------------- */
-    else if( bMetadata )
+    if( !poDS->Create( pszName, papszOptions ) )
     {
-        osCommand = 
-            "CREATE TABLE geometry_columns ("
-            "     f_table_name VARCHAR, "
-            "     f_geometry_column VARCHAR, "
-            "     geometry_type INTEGER, "
-            "     coord_dimension INTEGER, "
-            "     srid INTEGER,"
-            "     geometry_format VARCHAR )";
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to create table geometry_columns: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            sqlite3_close( hDB );
-            return NULL;
-        }
-
-        osCommand = 
-            "CREATE TABLE spatial_ref_sys        ("
-            "     srid INTEGER UNIQUE,"
-            "     auth_name TEXT,"
-            "     auth_srid TEXT,"
-            "     srtext TEXT)";
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Unable to create table spatial_ref_sys: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            sqlite3_close( hDB );
-            return NULL;
-        }
+        delete poDS;
+        return NULL;
     }
     else
-    {
-/* -------------------------------------------------------------------- */
-/*      Close the DB file so we can reopen it normally.                 */
-/* -------------------------------------------------------------------- */
-        sqlite3_close( hDB );
-
-        OGRSQLiteDataSource     *poDS;
-        poDS = new OGRSQLiteDataSource();
-
-        if( !poDS->Open( pszName ) )
-        {
-            delete poDS;
-            return NULL;
-        }
-        else
-            return poDS;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Optionnaly initialize the content of the spatial_ref_sys table  */
-/*      with the EPSG database                                          */
-/* -------------------------------------------------------------------- */
-    if ( (bSpatialite || bMetadata) &&
-         CSLFetchBoolean( papszOptions, "INIT_WITH_EPSG", FALSE ) )
-    {
-        InitWithEPSG(hDB, bSpatialite);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Close the DB file so we can reopen it normally.                 */
-/* -------------------------------------------------------------------- */
-    sqlite3_close( hDB );
-
-    return Open( pszName, TRUE );
+        return poDS;
 }
 
 /************************************************************************/
-/*                           InitWithEPSG()                             */
+/*                         DeleteDataSource()                           */
 /************************************************************************/
 
-int OGRSQLiteDriver::InitWithEPSG(sqlite3* hDB, int bSpatialite)
+OGRErr OGRSQLiteDriver::DeleteDataSource( const char *pszName )
 {
-    CPLString osCommand;
-    char* pszErrMsg = NULL;
-
-    int rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                "Unable to insert into spatial_ref_sys: %s",
-                pszErrMsg );
-        sqlite3_free( pszErrMsg );
-        return FALSE;
-    }
-
-    FILE* fp;
-    int i;
-    for(i=0;i<2 && rc == SQLITE_OK;i++)
-    {
-        const char* pszFilename = (i == 0) ? "gcs.csv" : "pcs.csv";
-        fp = VSIFOpen(CSVFilename(pszFilename), "rt");
-        if (fp == NULL)
-        {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
-                "Unable to open EPSG support file %s.\n"
-                "Try setting the GDAL_DATA environment variable to point to the\n"
-                "directory containing EPSG csv files.", 
-                pszFilename );
-
-            continue;
-        }
-
-        OGRSpatialReference oSRS;
-        char** papszTokens;
-        CSLDestroy(CSVReadParseLine( fp ));
-        while ( (papszTokens = CSVReadParseLine( fp )) != NULL && rc == SQLITE_OK)
-        {
-            int nSRSId = atoi(papszTokens[0]);
-            CSLDestroy(papszTokens);
-
-            CPLPushErrorHandler(CPLQuietErrorHandler);
-            oSRS.importFromEPSG(nSRSId);
-            CPLPopErrorHandler();
-
-            if (bSpatialite)
-            {
-                char    *pszProj4 = NULL;
-
-                CPLPushErrorHandler(CPLQuietErrorHandler);
-                OGRErr eErr = oSRS.exportToProj4( &pszProj4 );
-                CPLPopErrorHandler();
-
-                char    *pszWKT = NULL;
-                if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
-                {
-                    CPLFree(pszWKT);
-                    pszWKT = NULL;
-                }
-
-                if( eErr == OGRERR_NONE )
-                {
-                    const char  *pszProjCS = oSRS.GetAttrValue("PROJCS");
-                    if (pszProjCS == NULL)
-                        pszProjCS = oSRS.GetAttrValue("GEOGCS");
-
-                    if ( pszProjCS )
-                        osCommand.Printf(
-                            "INSERT INTO spatial_ref_sys "
-                            "(srid, auth_name, auth_srid, ref_sys_name, proj4text, srs_wkt) "
-                            "VALUES (%d, 'EPSG', '%d', ?, ?, ?)",
-                            nSRSId, nSRSId);
-                    else
-                        osCommand.Printf(
-                            "INSERT INTO spatial_ref_sys "
-                            "(srid, auth_name, auth_srid, proj4text, srs_wkt) "
-                            "VALUES (%d, 'EPSG', '%d', ?, ?)",
-                            nSRSId, nSRSId);
-
-                    sqlite3_stmt *hInsertStmt = NULL;
-                    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
-
-                    if ( pszProjCS )
-                    {
-                        if( rc == SQLITE_OK)
-                            rc = sqlite3_bind_text( hInsertStmt, 1, pszProjCS, -1, SQLITE_STATIC );
-                        if( rc == SQLITE_OK)
-                            rc = sqlite3_bind_text( hInsertStmt, 2, pszProj4, -1, SQLITE_STATIC );
-                        if( rc == SQLITE_OK && pszWKT != NULL)
-                            rc = sqlite3_bind_text( hInsertStmt, 3, pszWKT, -1, SQLITE_STATIC );
-                    }
-                    else
-                    {
-                        if( rc == SQLITE_OK)
-                            rc = sqlite3_bind_text( hInsertStmt, 1, pszProj4, -1, SQLITE_STATIC );
-                        if( rc == SQLITE_OK && pszWKT != NULL)
-                            rc = sqlite3_bind_text( hInsertStmt, 2, pszWKT, -1, SQLITE_STATIC );
-                    }
-
-                    if( rc == SQLITE_OK)
-                        rc = sqlite3_step( hInsertStmt );
-
-                    if( rc != SQLITE_OK && rc != SQLITE_DONE )
-                    {
-                        CPLError( CE_Failure, CPLE_AppDefined, 
-                                    "Cannot insert %s into spatial_ref_sys : %s",
-                                    pszProj4,
-                                    sqlite3_errmsg(hDB) );
-
-                        sqlite3_finalize( hInsertStmt );
-                        CPLFree(pszProj4);
-                        CPLFree(pszWKT);
-                        break;
-                    }
-                    rc = SQLITE_OK;
-
-                    sqlite3_finalize( hInsertStmt );
-                }
-
-                CPLFree(pszProj4);
-                CPLFree(pszWKT);
-            }
-            else
-            {
-                char    *pszWKT = NULL;
-                if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
-                {
-                    osCommand.Printf(
-                        "INSERT INTO spatial_ref_sys "
-                        "(srid, auth_name, auth_srid, srtext) "
-                        "VALUES (%d, 'EPSG', '%d', ?)",
-                        nSRSId, nSRSId );
-
-                    sqlite3_stmt *hInsertStmt = NULL;
-                    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
-
-                    if( rc == SQLITE_OK)
-                        rc = sqlite3_bind_text( hInsertStmt, 1, pszWKT, -1, SQLITE_STATIC );
-
-                    if( rc == SQLITE_OK)
-                        rc = sqlite3_step( hInsertStmt );
-
-                    if( rc != SQLITE_OK && rc != SQLITE_DONE )
-                    {
-                        CPLError( CE_Failure, CPLE_AppDefined, 
-                                    "Cannot insert %s into spatial_ref_sys : %s",
-                                    pszWKT,
-                                    sqlite3_errmsg(hDB) );
-
-                        sqlite3_finalize( hInsertStmt );
-                        CPLFree(pszWKT);
-                        break;
-                    }
-                    rc = SQLITE_OK;
-
-                    sqlite3_finalize( hInsertStmt );
-                }
-
-                CPLFree(pszWKT);
-            }
-        }
-        VSIFClose(fp);
-    }
-
-    if (rc == SQLITE_OK)
-        rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
+    if (VSIUnlink( pszName ) == 0)
+        return OGRERR_NONE;
     else
-        rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, &pszErrMsg );
-
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                "Unable to insert into spatial_ref_sys: %s",
-                pszErrMsg );
-        sqlite3_free( pszErrMsg );
-    }
-
-    return (rc == SQLITE_OK);
+        return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -501,6 +219,8 @@ int OGRSQLiteDriver::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODrCCreateDataSource) )
         return TRUE;
+    else if( EQUAL(pszCap,ODrCDeleteDataSource) )
+        return TRUE;
     else
         return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
index 3457acd..89e29cd 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitelayer.cpp 20895 2010-10-19 17:42:22Z rouault $
+ * $Id: ogrsqlitelayer.cpp 23593 2011-12-18 14:02:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteLayer class, code shared between 
@@ -7,6 +7,14 @@
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
+ *
+ * Contributor: Alessandro Furieri, a.furieri at lqt.it
+ * Portions of this module supporting SpatiaLite's own 3D geometries
+ * [XY, XYM, XYZ and XYZM] available since v.2.4.0
+ * Developed for Faunalia ( http://www.faunalia.it) with funding from 
+ * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
+ *
+ ******************************************************************************
  * Copyright (c) 2004, Frank Warmerdam <warmerdam at pobox.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -33,7 +41,7 @@
 #include "ogr_sqlite.h"
 #include <cassert>
 
-CPL_CVSID("$Id: ogrsqlitelayer.cpp 20895 2010-10-19 17:42:22Z rouault $");
+CPL_CVSID("$Id: ogrsqlitelayer.cpp 23593 2011-12-18 14:02:09Z rouault $");
 
 /************************************************************************/
 /*                           OGRSQLiteLayer()                           */
@@ -59,6 +67,14 @@ OGRSQLiteLayer::OGRSQLiteLayer()
 
     bTriedAsSpatiaLite = FALSE;
     bHasSpatialIndex = FALSE;
+    bHasM = FALSE;
+    bSpatialiteReadOnly = FALSE;
+    bSpatialiteLoaded = FALSE;
+    iSpatialiteVersion = -1;
+
+    bIsVirtualShape = FALSE;
+
+    bUseComprGeom = CSLTestBoolean(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"));
 }
 
 /************************************************************************/
@@ -114,7 +130,7 @@ CPLErr OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 
     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( sqlite3_column_name( hStmt, iCol ), 
+        OGRFieldDefn    oField( sqlite3_column_name( hStmt, iCol ),
                                 OFTString );
 
         // In some cases, particularly when there is a real name for
@@ -123,6 +139,14 @@ CPLErr OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         if( poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 )
             continue;
 
+        /* In the case of Spatialite VirtualShape, the PKUID */
+        /* should be considered as a primary key */
+        if( bIsVirtualShape && EQUAL(oField.GetNameRef(), "PKUID") )
+        {
+            CPLFree(pszFIDColumn);
+            pszFIDColumn = CPLStrdup(oField.GetNameRef());
+        }
+
         if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oField.GetNameRef()))
             continue;
 
@@ -140,7 +164,8 @@ CPLErr OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         {
             if (EQUAL(pszDeclType, "INTEGER"))
                 nColType = SQLITE_INTEGER;
-            else if (EQUAL(pszDeclType, "FLOAT"))
+            else if (EQUAL(pszDeclType, "FLOAT") ||
+                     EQUAL(pszDeclType, "DECIMAL"))
                 nColType = SQLITE_FLOAT;
             else if (EQUAL(pszDeclType, "BLOB"))
                 nColType = SQLITE_BLOB;
@@ -153,7 +178,8 @@ CPLErr OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         if( (EQUAL(oField.GetNameRef(),"wkt_geometry") 
              || EQUAL(oField.GetNameRef(),"geometry")
              || EQUALN(oField.GetNameRef(), "asbinary(", 9)
-             || EQUALN(oField.GetNameRef(), "astext(", 7))
+             || EQUALN(oField.GetNameRef(), "astext(", 7)
+             || (EQUALN(oField.GetNameRef(), "st_", 3) && nColType == SQLITE_BLOB ) )
             && osGeomColumn.size() == 0 )
         {
             if( nColType == SQLITE_BLOB )
@@ -514,14 +540,25 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                                                     OGRGeometry **ppoReturn,
                                                     int nBytes,
                                                     OGRwkbByteOrder eByteOrder,
-                                                    int* pnBytesConsumed)
+                                                    int* pnBytesConsumed,
+                                                    int nRecLevel)
 {
     OGRErr      eErr = OGRERR_NONE;
     OGRGeometry *poGeom = NULL;
     GInt32       nGType;
+    GInt32       compressedSize;
 
     *ppoReturn = NULL;
 
+    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    if( nRecLevel == 32 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Too many recursiong level (%d) while parsing Spatialite geometry.",
+                    nRecLevel );
+        return OGRERR_CORRUPT_DATA;
+    }
+
     if (nBytes < 4)
         return OGRERR_NOT_ENOUGH_DATA;
 
@@ -532,13 +569,30 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
     if (NEED_SWAP_SPATIALITE())
         CPL_SWAP32PTR( &nGType );
 
-    if( nGType < 1 || nGType > 7 )
+    if( ( nGType >= OGRSplitePointXY && 
+          nGType <= OGRSpliteGeometryCollectionXY ) ||       // XY types
+        ( nGType >= OGRSplitePointXYZ && 
+          nGType <= OGRSpliteGeometryCollectionXYZ ) ||      // XYZ types
+        ( nGType >= OGRSplitePointXYM && 
+          nGType <= OGRSpliteGeometryCollectionXYM ) ||      // XYM types
+        ( nGType >= OGRSplitePointXYZM && 
+          nGType <= OGRSpliteGeometryCollectionXYZM ) ||     // XYZM types
+        ( nGType >= OGRSpliteComprLineStringXY && 
+          nGType <= OGRSpliteComprGeometryCollectionXY ) ||  // XY compressed
+        ( nGType >= OGRSpliteComprLineStringXYZ && 
+          nGType <= OGRSpliteComprGeometryCollectionXYZ ) || // XYZ compressed
+        ( nGType >= OGRSpliteComprLineStringXYM && 
+          nGType <= OGRSpliteComprGeometryCollectionXYM ) || // XYM compressed
+        ( nGType >= OGRSpliteComprLineStringXYZM && 
+          nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
+        ;
+    else
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
 /* -------------------------------------------------------------------- */
-/*      Point                                                           */
+/*      Point [XY]                                                      */
 /* -------------------------------------------------------------------- */
-    if( nGType == 1 )
+    if( nGType == OGRSplitePointXY )
     {
         double  adfTuple[2];
 
@@ -557,11 +611,83 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if( pnBytesConsumed )
             *pnBytesConsumed = 4 + 2 * 8;
     }
+/* -------------------------------------------------------------------- */
+/*      Point [XYZ]                                                     */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSplitePointXYZ )
+    {
+        double  adfTuple[3];
+
+        if( nBytes < 4 + 3 * 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( adfTuple, pabyData + 4, 3*8 );
+        if (NEED_SWAP_SPATIALITE())
+        {
+            CPL_SWAP64PTR( adfTuple );
+            CPL_SWAP64PTR( adfTuple + 1 );
+            CPL_SWAP64PTR( adfTuple + 2 );
+        }
+
+        poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2] );
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = 4 + 3 * 8;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Point [XYM]                                                     */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSplitePointXYM )
+    {
+        double  adfTuple[3];
+
+        if( nBytes < 4 + 3 * 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( adfTuple, pabyData + 4, 3*8 );
+        if (NEED_SWAP_SPATIALITE())
+        {
+            CPL_SWAP64PTR( adfTuple );
+            CPL_SWAP64PTR( adfTuple + 1 );
+            CPL_SWAP64PTR( adfTuple + 2 );
+        }
+
+        poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = 4 + 3 * 8;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Point [XYZM]                                                    */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSplitePointXYZM )
+    {
+        double  adfTuple[4];
+
+        if( nBytes < 4 + 4 * 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( adfTuple, pabyData + 4, 4*8 );
+        if (NEED_SWAP_SPATIALITE())
+        {
+            CPL_SWAP64PTR( adfTuple );
+            CPL_SWAP64PTR( adfTuple + 1 );
+            CPL_SWAP64PTR( adfTuple + 2 );
+            CPL_SWAP64PTR( adfTuple + 3 );
+        }
+
+        poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2] );
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = 4 + 4 * 8;
+    }
 
 /* -------------------------------------------------------------------- */
-/*      LineString                                                      */
+/*      LineString [XY]                                                 */
 /* -------------------------------------------------------------------- */
-    else if( nGType == 2 )
+    else if( nGType == OGRSpliteLineStringXY )
     {
         double adfTuple[2];
         GInt32 nPointCount;
@@ -601,232 +727,1434 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Polygon                                                         */
+/*      LineString [XYZ]                                                */
 /* -------------------------------------------------------------------- */
-    else if( nGType == 3 )
+    else if( nGType == OGRSpliteLineStringXYZ )
     {
-        double adfTuple[2];
+        double adfTuple[3];
         GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
+        int    iPoint;
+        OGRLineString *poLS;
 
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        memcpy( &nRingCount, pabyData + 4, 4 );
+        memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
-            CPL_SWAP32PTR( &nRingCount );
+            CPL_SWAP32PTR( &nPointCount );
 
-        if (nRingCount < 0 || nRingCount > INT_MAX / 4)
+        if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
             return OGRERR_CORRUPT_DATA;
 
-        /* Each ring has a minimum of 4 bytes */
-        if (nBytes - 8 < nRingCount * 4)
+        if (nBytes - 8 < 3 * 8 * nPointCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
-        
-        poGeom = poPoly = new OGRPolygon();
+        poGeom = poLS = new OGRLineString();
+        poLS->setNumPoints( nPointCount );
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
-            if( nBytes - nNextByte < 4 )
-                return OGRERR_NOT_ENOUGH_DATA;
-
-            memcpy( &nPointCount, pabyData + nNextByte, 4 );
+            memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
             if (NEED_SWAP_SPATIALITE())
-                CPL_SWAP32PTR( &nPointCount );
-
-            if (nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
-                return OGRERR_CORRUPT_DATA;
-
-            nNextByte += 4;
-
-            if( nBytes - nNextByte < 2 * 8 * nPointCount )
-                return OGRERR_NOT_ENOUGH_DATA;
-
-            poLR = new OGRLinearRing();
-            poLR->setNumPoints( nPointCount );
-            
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
-                memcpy( adfTuple, pabyData + nNextByte, 2*8 );
-                nNextByte += 2 * 8;
-
-                if (NEED_SWAP_SPATIALITE())
-                {
-                    CPL_SWAP64PTR( adfTuple );
-                    CPL_SWAP64PTR( adfTuple + 1 );
-                }
-
-                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+                CPL_SWAP64PTR( adfTuple );
+                CPL_SWAP64PTR( adfTuple + 1 );
+                CPL_SWAP64PTR( adfTuple + 2 );
             }
 
-            poPoly->addRingDirectly( poLR );
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
         }
 
         if( pnBytesConsumed )
-            *pnBytesConsumed = nNextByte;
+            *pnBytesConsumed = 8 + 3 * 8 * nPointCount;
     }
 
 /* -------------------------------------------------------------------- */
-/*      GeometryCollections of various kinds.                           */
+/*      LineString [XYM]                                                */
 /* -------------------------------------------------------------------- */
-    else if( nGType == 4         // MultiPoint
-             || nGType == 5      // MultiLineString
-             || nGType == 6      // MultiPolygon
-             || nGType == 7 )    // MultiGeometry
+    else if( nGType == OGRSpliteLineStringXYM )
     {
-        OGRGeometryCollection *poGC = NULL;
-        GInt32 nGeomCount = 0;
-        int iGeom = 0;
-        int nBytesUsed = 0;
-
-        if( nGType == 4 )
-            poGC = new OGRMultiPoint();
-        else if( nGType == 5 )
-            poGC = new OGRMultiLineString();
-        else if( nGType == 6 )
-            poGC = new OGRMultiPolygon();
-        else if( nGType == 7 )
-            poGC = new OGRGeometryCollection();
-
-        assert(NULL != poGC);
+        double adfTuple[3];
+        GInt32 nPointCount;
+        int    iPoint;
+        OGRLineString *poLS;
 
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        memcpy( &nGeomCount, pabyData + 4, 4 );
+        memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
-            CPL_SWAP32PTR( &nGeomCount );
+            CPL_SWAP32PTR( &nPointCount );
 
-        if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
+        if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
             return OGRERR_CORRUPT_DATA;
 
-        /* Each sub geometry takes at least 9 bytes */
-        if (nBytes - 8 < nGeomCount * 9)
+        if (nBytes - 8 < 3 * 8 * nPointCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nBytesUsed = 8;
+        poGeom = poLS = new OGRLineString();
+        poLS->setNumPoints( nPointCount );
 
-        for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
-            int nThisGeomSize;
-            OGRGeometry *poThisGeom = NULL;
-
-            if (nBytes - nBytesUsed < 5)
-                return OGRERR_NOT_ENOUGH_DATA;
-
-            if (pabyData[nBytesUsed] != 0x69)
-                return OGRERR_CORRUPT_DATA;
-
-            nBytesUsed ++;
-
-            eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
-                                                 &poThisGeom, nBytes - nBytesUsed,
-                                                 eByteOrder, &nThisGeomSize);
-            if( eErr != OGRERR_NONE )
+            memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
+            if (NEED_SWAP_SPATIALITE())
             {
-                delete poGC;
-                return eErr;
+                CPL_SWAP64PTR( adfTuple );
+                CPL_SWAP64PTR( adfTuple + 1 );
+                CPL_SWAP64PTR( adfTuple + 2 );
             }
 
-            nBytesUsed += nThisGeomSize;
-            eErr = poGC->addGeometryDirectly( poThisGeom );
-            if( eErr != OGRERR_NONE )
-            {
-                delete poGC;
-                return eErr;
-            }
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
         }
 
-        poGeom = poGC;
         if( pnBytesConsumed )
-            *pnBytesConsumed = nBytesUsed;
+            *pnBytesConsumed = 8 + 3 * 8 * nPointCount;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Currently unsupported geometry.                                 */
+/*      LineString [XYZM]                                               */
 /* -------------------------------------------------------------------- */
-    else
+    else if( nGType == OGRSpliteLineStringXYZM )
     {
-        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
-    }
+        double adfTuple[4];
+        GInt32 nPointCount;
+        int    iPoint;
+        OGRLineString *poLS;
 
-/* -------------------------------------------------------------------- */
-/*      Assign spatial reference system.                                */
-/* -------------------------------------------------------------------- */
-    if( eErr == OGRERR_NONE )
-    {
-        *ppoReturn = poGeom;
-    }
-    else
-    {
-        delete poGeom;
-    }
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
 
-    return eErr;
-}
+        memcpy( &nPointCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nPointCount );
 
-/************************************************************************/
-/*                      ImportSpatiaLiteGeometry()                      */
-/************************************************************************/
+        if( nPointCount < 0 || nPointCount > INT_MAX / (4 * 8))
+            return OGRERR_CORRUPT_DATA;
 
-OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
-                                                 int nBytes,
-                                                 OGRGeometry **ppoGeometry )
+        if (nBytes - 8 < 4 * 8 * nPointCount )
+            return OGRERR_NOT_ENOUGH_DATA;
 
-{
-    OGRwkbByteOrder eByteOrder;
+        poGeom = poLS = new OGRLineString();
+        poLS->setNumPoints( nPointCount );
 
-    *ppoGeometry = NULL;
+        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        {
+            memcpy( adfTuple, pabyData + 8 + 4*8*iPoint, 4*8 );
+            if (NEED_SWAP_SPATIALITE())
+            {
+                CPL_SWAP64PTR( adfTuple );
+                CPL_SWAP64PTR( adfTuple + 1 );
+                CPL_SWAP64PTR( adfTuple + 2 );
+                CPL_SWAP64PTR( adfTuple + 3 );
+            }
 
-    if( nBytes < 44
-        || pabyData[0] != 0
-        || pabyData[38] != 0x7C
-        || pabyData[nBytes-1] != 0xFE )
-        return OGRERR_CORRUPT_DATA;
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+        }
 
-    eByteOrder = (OGRwkbByteOrder) pabyData[1];
+        if( pnBytesConsumed )
+            *pnBytesConsumed = 8 + 4 * 8 * nPointCount;
+    }
 
-    return createFromSpatialiteInternal(pabyData + 39, ppoGeometry,
-                                        nBytes - 39, eByteOrder, NULL);
-}
+/* -------------------------------------------------------------------- */
+/*      LineString [XY] Compressed                                      */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprLineStringXY )
+    {
+        double adfTuple[2];
+        double adfTupleBase[2];
+        float asfTuple[2];
+        GInt32 nPointCount;
+        int    iPoint;
+        OGRLineString *poLS;
+        int    nNextByte;
 
-/************************************************************************/
-/*                  ComputeSpatiaLiteGeometrySize()                     */
-/************************************************************************/
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
 
-int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry)
-{
-    switch (wkbFlatten(poGeometry->getGeometryType()))
-    {
-        case wkbPoint:
-            return 16;
+        memcpy( &nPointCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nPointCount );
 
-        case wkbLineString:
-        case wkbLinearRing:
-            return 4 + 16 * ((OGRLineString*)poGeometry)->getNumPoints();
+        if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 16 * 2) / 8)
+            return OGRERR_CORRUPT_DATA;
 
-        case wkbPolygon:
-        {
-            int nSize = 4;
-            OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
-            if (poPoly->getExteriorRing() != NULL)
-            {
-                nSize += ComputeSpatiaLiteGeometrySize(poPoly->getExteriorRing());
+        compressedSize = 16 * 2;                  // first and last Points 
+        compressedSize += 8 * (nPointCount - 2);  // intermediate Points
 
-                int nInteriorRingCount = poPoly->getNumInteriorRings();
-                for(int i=0;i<nInteriorRingCount;i++)
-                    nSize += ComputeSpatiaLiteGeometrySize(poPoly->getInteriorRing(i));
-            }
-            return nSize;
-        }
+        if (nBytes - 8 < compressedSize )
+            return OGRERR_NOT_ENOUGH_DATA;
 
-        case wkbMultiPoint:
+        poGeom = poLS = new OGRLineString();
+        poLS->setNumPoints( nPointCount );
+
+        nNextByte = 8;
+        adfTupleBase[0] = 0.0;
+        adfTupleBase[1] = 0.0;
+		
+        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        {
+            if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+            {
+                // first and last Points are uncompressed 
+                memcpy( adfTuple, pabyData + nNextByte, 2*8 );
+                nNextByte += 2 * 8;
+			
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                }
+            }
+            else
+            {
+                // any other intermediate Point is compressed
+                memcpy( asfTuple, pabyData + nNextByte, 2*4 );
+                nNextByte += 2 * 4;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP32PTR( asfTuple );
+                    CPL_SWAP32PTR( asfTuple + 1 );
+                }
+                adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+            }
+
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+            adfTupleBase[0] = adfTuple[0];
+            adfTupleBase[1] = adfTuple[1];
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      LineString [XYZ] Compressed                                     */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprLineStringXYZ )
+    {
+        double adfTuple[3];
+        double adfTupleBase[3];
+        float asfTuple[3];
+        GInt32 nPointCount;
+        int    iPoint;
+        OGRLineString *poLS;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nPointCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nPointCount );
+
+        if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 12)
+            return OGRERR_CORRUPT_DATA;
+
+        compressedSize = 24 * 2;                  // first and last Points
+        compressedSize += 12 * (nPointCount - 2);  // intermediate Points
+
+        if (nBytes - 8 < compressedSize )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        poGeom = poLS = new OGRLineString();
+        poLS->setNumPoints( nPointCount );
+
+        nNextByte = 8;
+        adfTupleBase[0] = 0.0;
+        adfTupleBase[1] = 0.0;
+        adfTupleBase[2] = 0.0;
+		
+        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        {
+            if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+            {
+                // first and last Points are uncompressed 
+                memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                nNextByte += 3 * 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                    CPL_SWAP64PTR( adfTuple + 2 );
+                }
+            }
+            else
+            {
+                // any other intermediate Point is compressed 
+                memcpy( asfTuple, pabyData + nNextByte, 3*4 );
+                nNextByte += 3 * 4;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP32PTR( asfTuple );
+                    CPL_SWAP32PTR( asfTuple + 1 );
+                    CPL_SWAP32PTR( asfTuple + 2 );
+                }
+                adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+                adfTuple[2] = asfTuple[2] + adfTupleBase[2];
+            }
+
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+            adfTupleBase[0] = adfTuple[0];
+            adfTupleBase[1] = adfTuple[1];
+            adfTupleBase[2] = adfTuple[2];
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      LineString [XYM] Compressed                                     */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprLineStringXYM )
+    {
+        double adfTuple[2];
+        double adfTupleBase[2];
+        float asfTuple[2];
+        GInt32 nPointCount;
+        int    iPoint;
+        OGRLineString *poLS;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nPointCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nPointCount );
+
+        if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 16)
+            return OGRERR_CORRUPT_DATA;
+
+        compressedSize = 24 * 2;                  // first and last Points
+        compressedSize += 16 * (nPointCount - 2);  // intermediate Points
+
+        if (nBytes - 8 < compressedSize )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        poGeom = poLS = new OGRLineString();
+        poLS->setNumPoints( nPointCount );
+
+        nNextByte = 8;
+        adfTupleBase[0] = 0.0;
+        adfTupleBase[1] = 0.0;
+		
+        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        {
+            if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+            {
+                // first and last Points are uncompressed 
+                memcpy( adfTuple, pabyData + nNextByte, 2*8 );
+                nNextByte += 3 * 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                }
+            }
+            else
+            {
+                // any other intermediate Point is compressed
+                memcpy( asfTuple, pabyData + nNextByte, 2*4 );
+                nNextByte += 2 * 4 + 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP32PTR( asfTuple );
+                    CPL_SWAP32PTR( asfTuple + 1 );
+                }
+                adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+            }
+
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+            adfTupleBase[0] = adfTuple[0];
+            adfTupleBase[1] = adfTuple[1];
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      LineString [XYZM] Compressed                                    */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprLineStringXYZM )
+    {
+        double adfTuple[3];
+        double adfTupleBase[3];
+        float asfTuple[3];
+        GInt32 nPointCount;
+        int    iPoint;
+        OGRLineString *poLS;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nPointCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nPointCount );
+
+        if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 32 * 2) / 20)
+            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 */
+        compressedSize += 20 * (nPointCount - 2);  // intermediate Points
+
+        if (nBytes - 8 < compressedSize )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        poGeom = poLS = new OGRLineString();
+        poLS->setNumPoints( nPointCount );
+
+        nNextByte = 8;
+        adfTupleBase[0] = 0.0;
+        adfTupleBase[1] = 0.0;
+        adfTupleBase[2] = 0.0;
+		
+        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        {
+            if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+            {
+                // first and last Points are uncompressed
+                memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                nNextByte += 4 * 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                    CPL_SWAP64PTR( adfTuple + 2 );
+                }
+            }
+            else
+            {
+                // any other intermediate Point is compressed
+                memcpy( asfTuple, pabyData + nNextByte, 3*4 );
+                nNextByte += 3 * 4 + 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP32PTR( asfTuple );
+                    CPL_SWAP32PTR( asfTuple + 1 );
+                    CPL_SWAP32PTR( asfTuple + 2 );
+                }
+                adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+                adfTuple[2] = asfTuple[2] + adfTupleBase[2];
+            }
+
+            poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+            adfTupleBase[0] = adfTuple[0];
+            adfTupleBase[1] = adfTuple[1];
+            adfTupleBase[2] = adfTuple[2];
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XY]                                                    */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSplitePolygonXY )
+    {
+        double adfTuple[2];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0 || nRingCount > INT_MAX / 4)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes 
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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))
+                return OGRERR_CORRUPT_DATA;
+
+            nNextByte += 4;
+
+            if( nBytes - nNextByte < 2 * 8 * nPointCount )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                memcpy( adfTuple, pabyData + nNextByte, 2*8 );
+                nNextByte += 2 * 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XYZ]                                                   */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSplitePolygonXYZ )
+    {
+        double adfTuple[3];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0 || nRingCount > INT_MAX / 4)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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))
+                return OGRERR_CORRUPT_DATA;
+
+            nNextByte += 4;
+
+            if( nBytes - nNextByte < 3 * 8 * nPointCount )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                nNextByte += 3 * 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                    CPL_SWAP64PTR( adfTuple + 2 );
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XYM]                                                   */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSplitePolygonXYM )
+    {
+        double adfTuple[3];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0 || nRingCount > INT_MAX / 4)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes 
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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))
+                return OGRERR_CORRUPT_DATA;
+
+            nNextByte += 4;
+
+            if( nBytes - nNextByte < 3 * 8 * nPointCount )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                nNextByte += 3 * 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                    CPL_SWAP64PTR( adfTuple + 2 );
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XYZM]                                                  */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSplitePolygonXYZM )
+    {
+        double adfTuple[4];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0 || nRingCount > INT_MAX / 4)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes 
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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))
+                return OGRERR_CORRUPT_DATA;
+
+            nNextByte += 4;
+
+            if( nBytes - nNextByte < 4 * 8 * nPointCount )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                memcpy( adfTuple, pabyData + nNextByte, 4*8 );
+                nNextByte += 4 * 8;
+
+                if (NEED_SWAP_SPATIALITE())
+                {
+                    CPL_SWAP64PTR( adfTuple );
+                    CPL_SWAP64PTR( adfTuple + 1 );
+                    CPL_SWAP64PTR( adfTuple + 2 );
+                    CPL_SWAP64PTR( adfTuple + 3 );
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XY] Compressed                                         */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprPolygonXY  )
+    {
+        double adfTuple[2];
+        double adfTupleBase[2];
+        float asfTuple[2];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0 || nRingCount > INT_MAX / 4)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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)
+                return OGRERR_CORRUPT_DATA;
+
+            compressedSize = 16 * 2;                  // first and last Points
+            compressedSize += 8 * (nPointCount - 2);  // intermediate Points
+
+            nNextByte += 4;
+            adfTupleBase[0] = 0.0;
+            adfTupleBase[1] = 0.0;
+
+            if (nBytes - nNextByte < compressedSize )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+                {
+                    // first and last Points are uncompressed 
+                    memcpy( adfTuple, pabyData + nNextByte, 2*8 );
+                    nNextByte += 2 * 8;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP64PTR( adfTuple );
+                        CPL_SWAP64PTR( adfTuple + 1 );
+                    }
+                }
+                else
+                {
+                    // any other intermediate Point is compressed
+                    memcpy( asfTuple, pabyData + nNextByte, 2*4 );
+                    nNextByte += 2 * 4;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP32PTR( asfTuple );
+                        CPL_SWAP32PTR( asfTuple + 1 );
+                    }
+                    adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                    adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+                adfTupleBase[0] = adfTuple[0];
+                adfTupleBase[1] = adfTuple[1];
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XYZ] Compressed                                        */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprPolygonXYZ )
+    {
+        double adfTuple[3];
+        double adfTupleBase[3];
+        float asfTuple[3];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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)
+                return OGRERR_CORRUPT_DATA;
+
+            compressedSize = 24 * 2;                  	// first and last Points
+            compressedSize += 12 * (nPointCount - 2);  // intermediate Points
+
+            nNextByte += 4;
+            adfTupleBase[0] = 0.0;
+            adfTupleBase[1] = 0.0;
+            adfTupleBase[2] = 0.0;
+
+            if (nBytes - nNextByte < compressedSize )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+                {
+                    // first and last Points are uncompressed 
+                    memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                    nNextByte += 3 * 8;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP64PTR( adfTuple );
+                        CPL_SWAP64PTR( adfTuple + 1 );
+                        CPL_SWAP64PTR( adfTuple + 2 );
+                    }
+                }
+                else
+                {
+                    // any other intermediate Point is compressed
+                    memcpy( asfTuple, pabyData + nNextByte, 3*4 );
+                    nNextByte += 3 * 4;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP32PTR( asfTuple );
+                        CPL_SWAP32PTR( asfTuple + 1 );
+                        CPL_SWAP32PTR( asfTuple + 2 );
+                    }
+                    adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                    adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+                    adfTuple[2] = asfTuple[2] + adfTupleBase[2];
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+                adfTupleBase[0] = adfTuple[0];
+                adfTupleBase[1] = adfTuple[1];
+                adfTupleBase[2] = adfTuple[2];
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XYM] Compressed                                        */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprPolygonXYM )
+    {
+        double adfTuple[2];
+        double adfTupleBase[3];
+        float asfTuple[2];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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) / 16)
+                return OGRERR_CORRUPT_DATA;
+
+            compressedSize = 24 * 2;                   // first and last Points
+            compressedSize += 16 * (nPointCount - 2);  // intermediate Points
+
+            nNextByte += 4;
+			adfTupleBase[0] = 0.0;
+			adfTupleBase[1] = 0.0;
+
+            if (nBytes - nNextByte < compressedSize )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+                {
+                    // first and last Points are uncompressed 
+                    memcpy( adfTuple, pabyData + nNextByte, 2*8 );
+                    nNextByte += 2 * 8;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP64PTR( adfTuple );
+                        CPL_SWAP64PTR( adfTuple + 1 );
+                    }
+                }
+                else
+                {
+                    // any other intermediate Point is compressed
+                    memcpy( asfTuple, pabyData + nNextByte, 2*4 );
+                    nNextByte += 2 * 4 + 8;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP32PTR( asfTuple );
+                        CPL_SWAP32PTR( asfTuple + 1 );
+                    }
+                    adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                    adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
+                adfTupleBase[0] = adfTuple[0];
+                adfTupleBase[1] = adfTuple[1];
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polygon [XYZM] Compressed                                       */
+/* -------------------------------------------------------------------- */
+    else if( nGType == OGRSpliteComprPolygonXYZM )
+    {
+        double adfTuple[3];
+        double adfTupleBase[3];
+        float asfTuple[3];
+        GInt32 nPointCount;
+        GInt32 nRingCount;
+        int    iPoint, iRing;
+        OGRLinearRing *poLR;
+        OGRPolygon *poPoly;
+        int    nNextByte;
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nRingCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nRingCount );
+
+        if (nRingCount < 0)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each ring has a minimum of 4 bytes 
+        if (nBytes - 8 < nRingCount * 4)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nNextByte = 8;
+        
+        poGeom = poPoly = new OGRPolygon();
+
+        for( iRing = 0; iRing < nRingCount; iRing++ )
+        {
+            if( nBytes - nNextByte < 4 )
+                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)
+                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 */
+            compressedSize += 20 * (nPointCount - 2);  // intermediate Points
+
+            nNextByte += 4;
+            adfTupleBase[0] = 0.0;
+            adfTupleBase[1] = 0.0;
+            adfTupleBase[2] = 0.0;
+
+            if (nBytes - nNextByte < compressedSize )
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            poLR = new OGRLinearRing();
+            poLR->setNumPoints( nPointCount );
+            
+            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            {
+                if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
+                {
+                    // first and last Points are uncompressed
+                    memcpy( adfTuple, pabyData + nNextByte, 3*8 );
+                    nNextByte += 4 * 8;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP64PTR( adfTuple );
+                        CPL_SWAP64PTR( adfTuple + 1 );
+                        CPL_SWAP64PTR( adfTuple + 2 );
+                    }
+                }
+                else
+                {
+                    // any other intermediate Point is compressed 
+                    memcpy( asfTuple, pabyData + nNextByte, 3*4 );
+                    nNextByte += 3 * 4 + 8;
+
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP32PTR( asfTuple );
+                        CPL_SWAP32PTR( asfTuple + 1 );
+                        CPL_SWAP32PTR( asfTuple + 2 );
+                    }
+                    adfTuple[0] = asfTuple[0] + adfTupleBase[0];
+                    adfTuple[1] = asfTuple[1] + adfTupleBase[1];
+                    adfTuple[2] = asfTuple[2] + adfTupleBase[2];
+                }
+
+                poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+                adfTupleBase[0] = adfTuple[0];
+                adfTupleBase[1] = adfTuple[1];
+                adfTupleBase[2] = adfTuple[2];
+            }
+
+            poPoly->addRingDirectly( poLR );
+        }
+
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nNextByte;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      GeometryCollections of various kinds.                           */
+/* -------------------------------------------------------------------- */
+    else if( ( nGType >= OGRSpliteMultiPointXY &&
+               nGType <= OGRSpliteGeometryCollectionXY ) ||       // XY types
+             ( nGType >= OGRSpliteMultiPointXYZ &&
+               nGType <= OGRSpliteGeometryCollectionXYZ ) ||      // XYZ types
+             ( nGType >= OGRSpliteMultiPointXYM &&
+               nGType <= OGRSpliteGeometryCollectionXYM ) ||      // XYM types 
+             ( nGType >= OGRSpliteMultiPointXYZM &&
+               nGType <= OGRSpliteGeometryCollectionXYZM ) ||     // XYZM types
+             ( nGType >= OGRSpliteComprMultiLineStringXY &&
+               nGType <= OGRSpliteComprGeometryCollectionXY ) ||  // XY compressed
+             ( nGType >= OGRSpliteComprMultiLineStringXYZ &&
+               nGType <= OGRSpliteComprGeometryCollectionXYZ ) || // XYZ compressed
+             ( nGType >= OGRSpliteComprMultiLineStringXYM &&
+               nGType <= OGRSpliteComprGeometryCollectionXYM ) || // XYM compressed
+             ( nGType >= OGRSpliteComprMultiLineStringXYZM &&
+               nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
+    {
+        OGRGeometryCollection *poGC = NULL;
+        GInt32 nGeomCount = 0;
+        int iGeom = 0;
+        int nBytesUsed = 0;
+
+        switch ( nGType )
+        {
+            case OGRSpliteMultiPointXY:
+            case OGRSpliteMultiPointXYZ: 
+            case OGRSpliteMultiPointXYM: 
+            case OGRSpliteMultiPointXYZM:
+                poGC = new OGRMultiPoint();
+                break;
+            case OGRSpliteMultiLineStringXY: 
+            case OGRSpliteMultiLineStringXYZ: 
+            case OGRSpliteMultiLineStringXYM: 
+            case OGRSpliteMultiLineStringXYZM:
+            case OGRSpliteComprMultiLineStringXY: 
+            case OGRSpliteComprMultiLineStringXYZ: 
+            case OGRSpliteComprMultiLineStringXYM: 
+            case OGRSpliteComprMultiLineStringXYZM:
+                poGC = new OGRMultiLineString();
+                break;
+            case OGRSpliteMultiPolygonXY: 
+            case OGRSpliteMultiPolygonXYZ: 
+            case OGRSpliteMultiPolygonXYM: 
+            case OGRSpliteMultiPolygonXYZM:
+            case OGRSpliteComprMultiPolygonXY: 
+            case OGRSpliteComprMultiPolygonXYZ: 
+            case OGRSpliteComprMultiPolygonXYM: 
+            case OGRSpliteComprMultiPolygonXYZM:
+                poGC = new OGRMultiPolygon();
+                break;
+            case OGRSpliteGeometryCollectionXY: 
+            case OGRSpliteGeometryCollectionXYZ: 
+            case OGRSpliteGeometryCollectionXYM: 
+            case OGRSpliteGeometryCollectionXYZM:
+            case OGRSpliteComprGeometryCollectionXY: 
+            case OGRSpliteComprGeometryCollectionXYZ: 
+            case OGRSpliteComprGeometryCollectionXYM: 
+            case OGRSpliteComprGeometryCollectionXYZM:
+                poGC = new OGRGeometryCollection();
+                break;
+        }
+
+        assert(NULL != poGC);
+
+        if( nBytes < 8 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        memcpy( &nGeomCount, pabyData + 4, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nGeomCount );
+
+        if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
+            return OGRERR_CORRUPT_DATA;
+
+        // Each sub geometry takes at least 9 bytes
+        if (nBytes - 8 < nGeomCount * 9)
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        nBytesUsed = 8;
+
+        for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+        {
+            int nThisGeomSize;
+            OGRGeometry *poThisGeom = NULL;
+
+            if (nBytes - nBytesUsed < 5)
+                return OGRERR_NOT_ENOUGH_DATA;
+
+            if (pabyData[nBytesUsed] != 0x69)
+                return OGRERR_CORRUPT_DATA;
+
+            nBytesUsed ++;
+
+            eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
+                                                 &poThisGeom, nBytes - nBytesUsed,
+                                                 eByteOrder, &nThisGeomSize, nRecLevel + 1);
+            if( eErr != OGRERR_NONE )
+            {
+                delete poGC;
+                return eErr;
+            }
+
+            nBytesUsed += nThisGeomSize;
+            eErr = poGC->addGeometryDirectly( poThisGeom );
+            if( eErr != OGRERR_NONE )
+            {
+                delete poGC;
+                return eErr;
+            }
+        }
+
+        poGeom = poGC;
+        if( pnBytesConsumed )
+            *pnBytesConsumed = nBytesUsed;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Currently unsupported geometry.                                 */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Assign spatial reference system.                                */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE )
+    {
+        *ppoReturn = poGeom;
+    }
+    else
+    {
+        delete poGeom;
+    }
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                      ImportSpatiaLiteGeometry()                      */
+/************************************************************************/
+
+OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
+                                                 int nBytes,
+                                                 OGRGeometry **ppoGeometry )
+
+{
+    OGRwkbByteOrder eByteOrder;
+
+    *ppoGeometry = NULL;
+
+    if( nBytes < 44
+        || pabyData[0] != 0
+        || pabyData[38] != 0x7C
+        || pabyData[nBytes-1] != 0xFE )
+        return OGRERR_CORRUPT_DATA;
+
+    eByteOrder = (OGRwkbByteOrder) pabyData[1];
+
+    return createFromSpatialiteInternal(pabyData + 39, ppoGeometry,
+                                        nBytes - 39, eByteOrder, NULL, 0);
+}
+
+
+/************************************************************************/
+/*                CanBeCompressedSpatialiteGeometry()                   */
+/************************************************************************/
+
+int OGRSQLiteLayer::CanBeCompressedSpatialiteGeometry(const OGRGeometry *poGeometry)
+{
+    switch (wkbFlatten(poGeometry->getGeometryType()))
+    {
+        case wkbLineString:
+        case wkbLinearRing:
+        {
+            int nPoints = ((OGRLineString*)poGeometry)->getNumPoints();
+            return nPoints >= 2;
+        }
+
+        case wkbPolygon:
+        {
+            OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
+            if (poPoly->getExteriorRing() != NULL)
+            {
+                if (!CanBeCompressedSpatialiteGeometry(poPoly->getExteriorRing()))
+                    return FALSE;
+
+                int nInteriorRingCount = poPoly->getNumInteriorRings();
+                for(int i=0;i<nInteriorRingCount;i++)
+                {
+                    if (!CanBeCompressedSpatialiteGeometry(poPoly->getInteriorRing(i)))
+                        return FALSE;
+                }
+            }
+            return TRUE;
+        }
+
+        case wkbMultiPoint:
+        case wkbMultiLineString:
+        case wkbMultiPolygon:
+        case wkbGeometryCollection:
+        {
+            OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
+            int nParts = poGeomCollection->getNumGeometries();
+            for(int i=0;i<nParts;i++)
+            {
+                if (!CanBeCompressedSpatialiteGeometry(poGeomCollection->getGeometryRef(i)))
+                    return FALSE;
+            }
+            return TRUE;
+        }
+
+        default:
+            return FALSE;
+    }
+}
+
+/************************************************************************/
+/*                  ComputeSpatiaLiteGeometrySize()                     */
+/************************************************************************/
+
+int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
+                                                  int bHasM, int bSpatialite2D,
+                                                  int bUseComprGeom)
+{
+    switch (wkbFlatten(poGeometry->getGeometryType()))
+    {
+        case wkbPoint:
+            if ( bSpatialite2D == TRUE )
+                return 16;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return 32;
+                else
+                    return 24;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                    return 24;
+                else
+                    return 16;
+            }
+
+        case wkbLineString:
+        case wkbLinearRing:
+        {
+            int nPoints = ((OGRLineString*)poGeometry)->getNumPoints();
+            int nDimension;
+            int nPointsDouble = nPoints;
+            int nPointsFloat = 0;
+            if ( bSpatialite2D == TRUE )
+            {
+                nDimension = 2;
+                bHasM = FALSE;
+            }
+            else
+            {
+                if ( bUseComprGeom && nPoints >= 2 )
+                {
+                    nPointsDouble = 2;
+                    nPointsFloat = nPoints - 2;
+                }
+                nDimension = poGeometry->getCoordinateDimension();
+            }
+            return 4 + nDimension * (8 * nPointsDouble + 4 * nPointsFloat) + ((bHasM) ? nPoints * 8 : 0);
+        }
+
+        case wkbPolygon:
+        {
+            int nSize = 4;
+            OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
+            bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poGeometry);
+            if (poPoly->getExteriorRing() != NULL)
+            {
+                nSize += ComputeSpatiaLiteGeometrySize(poPoly->getExteriorRing(),
+                                                       bHasM, bSpatialite2D, bUseComprGeom);
+
+                int nInteriorRingCount = poPoly->getNumInteriorRings();
+                for(int i=0;i<nInteriorRingCount;i++)
+                    nSize += ComputeSpatiaLiteGeometrySize(poPoly->getInteriorRing(i),
+                                                           bHasM, bSpatialite2D, bUseComprGeom );
+            }
+            return nSize;
+        }
+
+        case wkbMultiPoint:
         case wkbMultiLineString:
         case wkbMultiPolygon:
         case wkbGeometryCollection:
@@ -835,7 +2163,8 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry)
             OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
             int nParts = poGeomCollection->getNumGeometries();
             for(int i=0;i<nParts;i++)
-                nSize += 5 + ComputeSpatiaLiteGeometrySize(poGeomCollection->getGeometryRef(i));
+                nSize += 5 + ComputeSpatiaLiteGeometrySize(poGeomCollection->getGeometryRef(i),
+                                                           bHasM, bSpatialite2D, bUseComprGeom );
             return nSize;
         }
 
@@ -846,12 +2175,179 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry)
 }
 
 /************************************************************************/
+/*                    GetSpatialiteGeometryCode()                       */
+/************************************************************************/
+
+int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
+                                              int bHasM, int bSpatialite2D,
+                                              int bUseComprGeom,
+                                              int bAcceptMultiGeom)
+{
+    OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
+    switch (eType)
+    {
+        case wkbPoint:
+            if ( bSpatialite2D == TRUE )
+                return OGRSplitePointXY;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return OGRSplitePointXYZM;
+                else
+                    return OGRSplitePointXYZ;
+             }
+             else
+             {
+                if (bHasM == TRUE)
+                    return OGRSplitePointXYM;
+                else
+                    return OGRSplitePointXY;
+            }
+            break;
+
+        case wkbLineString:
+        case wkbLinearRing:
+            if ( bSpatialite2D == TRUE )
+                return OGRSpliteLineStringXY;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return (bUseComprGeom) ? OGRSpliteComprLineStringXYZM : OGRSpliteLineStringXYZM;
+                else
+                    return (bUseComprGeom) ? OGRSpliteComprLineStringXYZ : OGRSpliteLineStringXYZ;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                    return (bUseComprGeom) ? OGRSpliteComprLineStringXYM : OGRSpliteLineStringXYM;
+                else
+                    return (bUseComprGeom) ? OGRSpliteComprLineStringXY : OGRSpliteLineStringXY;
+            }
+            break;
+
+        case wkbPolygon:
+            if ( bSpatialite2D == TRUE )
+                return OGRSplitePolygonXY;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return (bUseComprGeom) ? OGRSpliteComprPolygonXYZM : OGRSplitePolygonXYZM;
+                else
+                    return (bUseComprGeom) ? OGRSpliteComprPolygonXYZ : OGRSplitePolygonXYZ;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                    return (bUseComprGeom) ? OGRSpliteComprPolygonXYM : OGRSplitePolygonXYM;
+                else
+                    return (bUseComprGeom) ? OGRSpliteComprPolygonXY : OGRSplitePolygonXY;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    if (!bAcceptMultiGeom)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
+        return 0;
+    }
+
+    switch (eType)
+    {
+        case wkbMultiPoint:
+            if ( bSpatialite2D == TRUE )
+                return OGRSpliteMultiPointXY;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return OGRSpliteMultiPointXYZM;
+                else
+                    return OGRSpliteMultiPointXYZ;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                    return OGRSpliteMultiPointXYM;
+                else
+                    return OGRSpliteMultiPointXY;
+            }
+            break;
+
+        case wkbMultiLineString:
+            if ( bSpatialite2D == TRUE )
+                return OGRSpliteMultiLineStringXY;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZM :*/ OGRSpliteMultiLineStringXYZM;
+                else
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZ :*/ OGRSpliteMultiLineStringXYZ;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYM :*/ OGRSpliteMultiLineStringXYM;
+                else
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXY :*/ OGRSpliteMultiLineStringXY;
+            }
+            break;
+
+        case wkbMultiPolygon:
+            if ( bSpatialite2D == TRUE )
+                return OGRSpliteMultiPolygonXY;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZM :*/ OGRSpliteMultiPolygonXYZM;
+                else
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZ :*/ OGRSpliteMultiPolygonXYZ;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYM :*/ OGRSpliteMultiPolygonXYM;
+                else
+                    return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXY :*/ OGRSpliteMultiPolygonXY;
+            }
+            break;
+
+
+        case wkbGeometryCollection:
+            if ( bSpatialite2D == TRUE )
+                return OGRSpliteGeometryCollectionXY;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                if (bHasM == TRUE)
+                    return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZM :*/ OGRSpliteGeometryCollectionXYZM;
+                else
+                    return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZ :*/ OGRSpliteGeometryCollectionXYZ;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                    return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYM :*/ OGRSpliteGeometryCollectionXYM;
+                else
+                    return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXY :*/ OGRSpliteGeometryCollectionXY;
+            }
+            break;
+
+        default:
+            CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
+            return 0;
+    }
+}
+
+/************************************************************************/
 /*                      ExportSpatiaLiteGeometry()                      */
 /************************************************************************/
 
 int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
                                                      OGRwkbByteOrder eByteOrder,
-                                                     GByte* pabyData)
+                                                     int bHasM, int bSpatialite2D,
+                                                     int bUseComprGeom,
+                                                     GByte* pabyData )
 {
     switch (wkbFlatten(poGeometry->getGeometryType()))
     {
@@ -867,7 +2363,38 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                 CPL_SWAP64PTR( pabyData );
                 CPL_SWAP64PTR( pabyData + 8 );
             }
-            return 16;
+            if ( bSpatialite2D == TRUE )
+                return 16;
+            else if (poGeometry->getCoordinateDimension() == 3)
+            {
+                double z = poPoint->getZ();
+                memcpy(pabyData + 16, &z, 8);
+                if (NEED_SWAP_SPATIALITE())
+                    CPL_SWAP64PTR( pabyData + 16 );
+                if (bHasM == TRUE)
+                {
+                    double m = 0.0;
+                    memcpy(pabyData + 24, &m, 8);
+                    if (NEED_SWAP_SPATIALITE())
+                        CPL_SWAP64PTR( pabyData + 24 );
+                    return 32;
+                }
+                else
+                    return 24;
+            }
+            else
+            {
+                if (bHasM == TRUE)
+                {
+                    double m = 0.0;
+                    memcpy(pabyData + 16, &m, 8);
+                    if (NEED_SWAP_SPATIALITE())
+                        CPL_SWAP64PTR( pabyData + 16 );
+                    return 24;
+                }
+                else
+                    return 16;
+            }
         }
 
         case wkbLineString:
@@ -879,18 +2406,95 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
             memcpy(pabyData, &nPointCount, 4);
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( pabyData );
+
             for(int i=0;i<nPointCount;i++)
             {
                 double x = poLineString->getX(i);
                 double y = poLineString->getY(i);
-                memcpy(pabyData + nTotalSize, &x, 8);
-                memcpy(pabyData + nTotalSize + 8, &y, 8);
-                if (NEED_SWAP_SPATIALITE())
+
+                if (!bUseComprGeom || i == 0 || i == nPointCount - 1)
+                {
+                    memcpy(pabyData + nTotalSize, &x, 8);
+                    memcpy(pabyData + nTotalSize + 8, &y, 8);
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP64PTR( pabyData + nTotalSize );
+                        CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
+                    }
+                    if (poGeometry->getCoordinateDimension() == 3)
+                    {
+                        double z = poLineString->getZ(i);
+                        memcpy(pabyData + nTotalSize + 16, &z, 8);
+                        if (NEED_SWAP_SPATIALITE())
+                            CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
+                        if (bHasM == TRUE)
+                        {
+                            double m = 0.0;
+                            memcpy(pabyData + nTotalSize + 24, &m, 8);
+                            if (NEED_SWAP_SPATIALITE())
+                                CPL_SWAP64PTR( pabyData + nTotalSize + 24 );
+                            nTotalSize += 32;
+                        }
+                        else
+                            nTotalSize += 24;
+                    }
+                    else
+                    {
+                        if (bHasM == TRUE)
+                        {
+                            double m = 0.0;
+                            memcpy(pabyData + nTotalSize + 16, &m, 8);
+                            if (NEED_SWAP_SPATIALITE())
+                                CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
+                            nTotalSize += 24;
+                        }
+                        else
+                            nTotalSize += 16;
+                    }
+                }
+                else /* Compressed intermediate points */
                 {
-                    CPL_SWAP64PTR( pabyData + nTotalSize );
-                    CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
+                    float deltax = (float)(x - poLineString->getX(i-1));
+                    float deltay = (float)(y - poLineString->getY(i-1));
+                    memcpy(pabyData + nTotalSize, &deltax, 4);
+                    memcpy(pabyData + nTotalSize + 4, &deltay, 4);
+                    if (NEED_SWAP_SPATIALITE())
+                    {
+                        CPL_SWAP32PTR( pabyData + nTotalSize );
+                        CPL_SWAP32PTR( pabyData + nTotalSize + 4 );
+                    }
+                    if (poGeometry->getCoordinateDimension() == 3)
+                    {
+                        double z = poLineString->getZ(i);
+                        float deltaz = (float)(z - poLineString->getZ(i-1));
+                        memcpy(pabyData + nTotalSize + 8, &deltaz, 4);
+                        if (NEED_SWAP_SPATIALITE())
+                            CPL_SWAP32PTR( pabyData + nTotalSize + 8 );
+                        if (bHasM == TRUE)
+                        {
+                            double m = 0.0;
+                            memcpy(pabyData + nTotalSize + 12, &m, 8);
+                            if (NEED_SWAP_SPATIALITE())
+                                CPL_SWAP64PTR( pabyData + nTotalSize + 12 );
+                            nTotalSize += 20;
+                        }
+                        else
+                            nTotalSize += 12;
+                    }
+                    else
+                    {
+                        if (bHasM == TRUE)
+                        {
+                            double m = 0.0;
+                            memcpy(pabyData + nTotalSize + 8, &m, 8);
+                            if (NEED_SWAP_SPATIALITE())
+                                CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
+                            nTotalSize += 16;
+                        }
+                        else
+                            nTotalSize += 8;
+                    }
                 }
-                nTotalSize += 16;
             }
             return nTotalSize;
         }
@@ -909,12 +2513,18 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
                     CPL_SWAP32PTR( pabyData );
 
                 nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getExteriorRing(),
-                                                              eByteOrder, pabyData + nTotalSize);
+                                                              eByteOrder,
+                                                              bHasM, bSpatialite2D,
+                                                              bUseComprGeom,
+                                                              pabyData + nTotalSize);
 
                 for(int i=0;i<nInteriorRingCount;i++)
                 {
                     nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getInteriorRing(i),
-                                                                   eByteOrder, pabyData + nTotalSize);
+                                                                   eByteOrder,
+                                                                   bHasM, bSpatialite2D,
+                                                                   bUseComprGeom,
+                                                                   pabyData + nTotalSize);
                 }
             }
             else
@@ -940,20 +2550,20 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
             {
                 pabyData[nTotalSize] = 0x69;
                 nTotalSize ++;
-                int nCode;
-                switch (wkbFlatten(poGeomCollection->getGeometryRef(i)->getGeometryType()))
-                {
-                    case wkbPoint: nCode = 1; break;
-                    case wkbLineString: nCode = 2; break;
-                    case wkbPolygon: nCode = 3; break;
-                    default: CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type"); return 0;
-                }
+                int nCode = GetSpatialiteGeometryCode(poGeomCollection->getGeometryRef(i),
+                                                      bHasM, bSpatialite2D,
+                                                      bUseComprGeom, FALSE);
+                if (nCode == 0)
+                    return 0;
                 memcpy(pabyData + nTotalSize, &nCode, 4);
                 if (NEED_SWAP_SPATIALITE())
                     CPL_SWAP32PTR( pabyData + nTotalSize );
                 nTotalSize += 4;
                 nTotalSize += ExportSpatiaLiteGeometryInternal(poGeomCollection->getGeometryRef(i),
-                                                               eByteOrder, pabyData + nTotalSize);
+                                                               eByteOrder,
+                                                               bHasM, bSpatialite2D,
+                                                               bUseComprGeom,
+                                                               pabyData + nTotalSize);
             }
             return nTotalSize;
         }
@@ -967,17 +2577,25 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
 OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
                                                  GInt32 nSRID,
                                                  OGRwkbByteOrder eByteOrder,
+                                                 int bHasM, int bSpatialite2D,
+                                                 int bUseComprGeom,
                                                  GByte **ppabyData,
                                                  int *pnDataLenght )
 
 {
-    int     nDataLen = 44 + ComputeSpatiaLiteGeometrySize(poGeometry);
+
+    bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poGeometry);
+
+    int     nDataLen = 44 + ComputeSpatiaLiteGeometrySize( poGeometry,
+                                                           bHasM, 
+                                                           bSpatialite2D,
+                                                           bUseComprGeom );
     OGREnvelope sEnvelope;
 
     *ppabyData =  (GByte *) CPLMalloc( nDataLen );
 
     (*ppabyData)[0] = 0x00;
-    (*ppabyData)[1] = eByteOrder;
+    (*ppabyData)[1] = (GByte) eByteOrder;
 
     // Write out SRID
     memcpy( *ppabyData + 2, &nSRID, 4 );
@@ -991,48 +2609,23 @@ OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
 
     (*ppabyData)[38] = 0x7C;
 
-    int nCode = 0;
-    switch (wkbFlatten(poGeometry->getGeometryType()))
+    int nCode = GetSpatialiteGeometryCode(poGeometry,
+                                          bHasM, bSpatialite2D,
+                                          bUseComprGeom, TRUE);
+    if (nCode == 0)
     {
-        case wkbPoint:
-            nCode = 1;
-            break;
-
-        case wkbLineString:
-        case wkbLinearRing:
-            nCode = 2;
-            break;
-
-        case wkbPolygon:
-            nCode = 3;
-            break;
-
-        case wkbMultiPoint:
-            nCode = 4;
-            break;
-
-        case wkbMultiLineString:
-            nCode = 5;
-            break;
-
-        case wkbMultiPolygon:
-            nCode = 6;
-            break;
-
-        case wkbGeometryCollection:
-            nCode = 7;
-            break;
-
-        default:
-            CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
-            CPLFree(*ppabyData);
-            *ppabyData = NULL;
-            *pnDataLenght = 0;
-            return CE_Failure;
+        CPLFree(*ppabyData);
+        *ppabyData = NULL;
+        *pnDataLenght = 0;
+        return CE_Failure;
     }
     memcpy( *ppabyData + 39, &nCode, 4 );
 
-    int nWritten = ExportSpatiaLiteGeometryInternal(poGeometry, eByteOrder, *ppabyData + 43);
+    int nWritten = ExportSpatiaLiteGeometryInternal(poGeometry, 
+                                                    eByteOrder, 
+                                                    bHasM, bSpatialite2D,
+                                                    bUseComprGeom,
+                                                    *ppabyData + 43);
     if (nWritten == 0)
     {
         CPLFree(*ppabyData);
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index 7ef5af7..b2e8126 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitetablelayer.cpp 21002 2010-10-29 08:17:09Z rouault $
+ * $Id: ogrsqlitetablelayer.cpp 23676 2012-01-01 16:10:36Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
@@ -30,9 +30,10 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_sqlite.h"
+#include "ogr_p.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 21002 2010-10-29 08:17:09Z rouault $");
+CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 23676 2012-01-01 16:10:36Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteTableLayer()                         */
@@ -42,14 +43,20 @@ OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
 
 {
     poDS = poDSIn;
-
-    bUpdateAccess = TRUE;
+	
+    bSpatialite2D = FALSE;
+    bLaunderColumnNames = TRUE;
 
     iNextShapeId = 0;
 
     nSRSId = -1;
 
     poFeatureDefn = NULL;
+    pszEscapedTableName = NULL;
+
+    bHasCheckedSpatialIndexTable = FALSE;
+
+    hInsertStmt = NULL;
 }
 
 /************************************************************************/
@@ -60,6 +67,22 @@ OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
 
 {
     ClearStatement();
+    ClearInsertStmt();
+    CPLFree(pszEscapedTableName);
+}
+
+/************************************************************************/
+/*                          ClearInsertStmt()                           */
+/************************************************************************/
+
+void OGRSQLiteTableLayer::ClearInsertStmt()
+{
+    if( hInsertStmt != NULL )
+    {
+        sqlite3_finalize( hInsertStmt );
+        hInsertStmt = NULL;
+    }
+    osLastInsertStmt = "";
 }
 
 /************************************************************************/
@@ -72,7 +95,12 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
                                         const char *pszGeomFormat,
                                         OGRSpatialReference *poSRS,
                                         int nSRSId,
-                                        int bHasSpatialIndex)
+                                        int bHasSpatialIndex,
+                                        int bHasM, 
+                                        int bSpatialiteReadOnly,
+                                        int bSpatialiteLoaded,
+                                        int iSpatialiteVersion,
+                                        int bIsVirtualShapeIn )
 
 {
     int rc;
@@ -101,17 +129,52 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
     this->poSRS = poSRS;
     this->nSRSId = nSRSId;
     this->bHasSpatialIndex = bHasSpatialIndex;
+    this->bHasM = bHasM;
+    this->bSpatialiteReadOnly = bSpatialiteReadOnly;
+    this->bSpatialiteLoaded = bSpatialiteLoaded;
+    this->iSpatialiteVersion = iSpatialiteVersion;
+    this->bIsVirtualShape = bIsVirtualShapeIn;
+
+    pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszTableName));
+
+    CPLErr eErr;
+    sqlite3_stmt *hColStmt = NULL;
+    const char *pszSQL;
+
+    if ( eGeomFormat == OSGF_SpatiaLite &&
+         bSpatialiteLoaded == TRUE && 
+         iSpatialiteVersion < 24 && poDS->GetUpdate() )
+    {
+    // we need to test version required by Spatialite TRIGGERs 
+        hColStmt = NULL;
+        pszSQL = CPLSPrintf( "SELECT sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = '%s' AND sql LIKE '%%RTreeAlign%%'",
+            pszEscapedTableName );
+
+        int nRowTriggerCount, nColTriggerCount;
+        char **papszTriggerResult, *pszErrMsg;
 
+        rc = sqlite3_get_table( hDB, pszSQL, &papszTriggerResult,
+            &nRowTriggerCount, &nColTriggerCount, &pszErrMsg );
+        if( nRowTriggerCount >= 1 )
+        {
+        // obsolete library version not supporting new triggers
+        // enforcing ReadOnly mode
+            CPLDebug("SQLITE", "Enforcing ReadOnly mode : obsolete library version not supporting new triggers");
+            this->bSpatialiteReadOnly = TRUE;
+        }
+
+        sqlite3_free_table( papszTriggerResult );
+    }
+	
     if( poSRS )
         poSRS->Reference();
 
 /* -------------------------------------------------------------------- */
 /*      Get the column definitions for this table.                      */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-    sqlite3_stmt *hColStmt = NULL;
-    const char *pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
-                                     pszTableName );
+    hColStmt = NULL;
+    pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
+                                     pszEscapedTableName );
 
     rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
     if( rc != SQLITE_OK )
@@ -154,7 +217,6 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
     if( eErr != CE_None )
         return eErr;
 
-
 /* -------------------------------------------------------------------- */
 /*      Set the geometry type if we know it.                            */
 /* -------------------------------------------------------------------- */
@@ -178,8 +240,8 @@ OGRErr OGRSQLiteTableLayer::ResetStatement()
 
     iNextShapeId = 0;
 
-    osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s", 
-                    poFeatureDefn->GetName(), 
+    osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s",
+                    pszEscapedTableName, 
                     osWHERE.c_str() );
 
     rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
@@ -224,9 +286,9 @@ OGRFeature *OGRSQLiteTableLayer::GetFeature( long nFeatureId )
 
     iNextShapeId = nFeatureId;
 
-    osSQL.Printf( "SELECT _rowid_, * FROM '%s' WHERE \"%s\" = %d", 
-                  poFeatureDefn->GetName(), 
-                  pszFIDColumn, (int) nFeatureId );
+    osSQL.Printf( "SELECT _rowid_, * FROM '%s' WHERE \"%s\" = %ld",
+                  pszEscapedTableName, 
+                  pszFIDColumn, nFeatureId );
 
     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
 
@@ -288,6 +350,51 @@ void OGRSQLiteTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 }
 
 /************************************************************************/
+/*                        CheckSpatialIndexTable()                      */
+/************************************************************************/
+
+int OGRSQLiteTableLayer::CheckSpatialIndexTable()
+{
+    if (bHasSpatialIndex && !bHasCheckedSpatialIndexTable)
+    {
+        bHasCheckedSpatialIndexTable = TRUE;
+        char **papszResult;
+        int nRowCount, nColCount;
+        char *pszErrMsg = NULL;
+
+        CPLString osSQL;
+        osSQL.Printf("SELECT name FROM sqlite_master "
+                    "WHERE name='idx_%s_%s'",
+                    pszEscapedTableName, osGeomColumn.c_str());
+
+        int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
+                                    &papszResult, &nRowCount,
+                                    &nColCount, &pszErrMsg );
+
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Error: %s",
+                    pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            bHasSpatialIndex = FALSE;
+        }
+        else
+        {
+            if (nRowCount != 1)
+            {
+                bHasSpatialIndex = FALSE;
+                CPLDebug("SQLITE", "Count not find idx_%s_%s layer. Disabling spatial index",
+                        pszEscapedTableName, osGeomColumn.c_str());
+            }
+
+            sqlite3_free_table(papszResult);
+        }
+    }
+
+    return bHasSpatialIndex;
+}
+
+/************************************************************************/
 /*                             BuildWhere()                             */
 /*                                                                      */
 /*      Build the WHERE statement appropriate to the current set of     */
@@ -299,11 +406,26 @@ void OGRSQLiteTableLayer::BuildWhere()
 {
     osWHERE = "";
 
-    if( m_poFilterGeom != NULL && bHasSpatialIndex )
+    if( m_poFilterGeom != NULL && CheckSpatialIndexTable() )
     {
         OGREnvelope  sEnvelope;
 
         m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        osWHERE.Printf("WHERE ROWID IN ( SELECT pkid FROM 'idx_%s_%s' WHERE "
+                        "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f) ",
+                        pszEscapedTableName, osGeomColumn.c_str(),
+                        sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
+                        sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
+    }
+
+    if( m_poFilterGeom != NULL && bSpatialiteLoaded && !bHasSpatialIndex)
+    {
+        OGREnvelope  sEnvelope;
+
+        m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        /* A bit inefficient but still faster than OGR filtering */
         osWHERE.Printf("WHERE MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f, %d)) ",
                        osGeomColumn.c_str(),
                        sEnvelope.MinX - 1e-11, sEnvelope.MinY - 1e-11,
@@ -344,10 +466,30 @@ int OGRSQLiteTableLayer::TestCapability( const char * pszCap )
 
     else if( EQUAL(pszCap,OLCSequentialWrite) 
              || EQUAL(pszCap,OLCRandomWrite) )
-        return bUpdateAccess;
+    {
+        if ( bSpatialiteReadOnly == TRUE)
+            return FALSE;
+        return poDS->GetUpdate();
+    }
+
+    else if( EQUAL(pszCap,OLCDeleteFeature) )
+    {
+        if ( bSpatialiteReadOnly == TRUE)
+            return FALSE;
+        return poDS->GetUpdate() && pszFIDColumn != NULL;
+    }
 
     else if( EQUAL(pszCap,OLCCreateField) )
-        return bUpdateAccess;
+        return poDS->GetUpdate();
+
+    else if( EQUAL(pszCap,OLCDeleteField) )
+        return poDS->GetUpdate();
+
+    else if( EQUAL(pszCap,OLCAlterFieldDefn) )
+        return poDS->GetUpdate();
+
+    else if( EQUAL(pszCap,OLCReorderFields) )
+        return poDS->GetUpdate();
 
     else 
         return OGRSQLiteLayer::TestCapability( pszCap );
@@ -373,8 +515,25 @@ int OGRSQLiteTableLayer::GetFeatureCount( int bForce )
 /* -------------------------------------------------------------------- */
     const char *pszSQL;
 
-    pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
-                            poFeatureDefn->GetName(), osWHERE.c_str() );
+    if (m_poFilterGeom != NULL && CheckSpatialIndexTable() &&
+        strlen(osQuery) == 0)
+    {
+        OGREnvelope  sEnvelope;
+
+        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, osGeomColumn.c_str(),
+                            sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
+                            sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
+    }
+    else
+    {
+        pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
+                            pszEscapedTableName, osWHERE.c_str() );
+    }
+
+    CPLDebug("SQLITE", "Running %s", pszSQL);
 
 /* -------------------------------------------------------------------- */
 /*      Execute.                                                        */
@@ -384,7 +543,7 @@ int OGRSQLiteTableLayer::GetFeatureCount( int bForce )
     int nResult = -1;
 
     if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult, 
-                           &nColCount, &nRowCount, &pszErrMsg ) != SQLITE_OK )
+                           &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
         return -1;
 
     if( nRowCount == 1 && nColCount == 1 )
@@ -396,17 +555,69 @@ int OGRSQLiteTableLayer::GetFeatureCount( int bForce )
 }
 
 /************************************************************************/
-/*                           GetSpatialRef()                            */
-/*                                                                      */
-/*      We override this to try and fetch the table SRID from the       */
-/*      geometry_columns table if the srsid is -2 (meaning we           */
-/*      haven't yet even looked for it).                                */
+/*                             GetExtent()                              */
 /************************************************************************/
 
-OGRSpatialReference *OGRSQLiteTableLayer::GetSpatialRef()
+OGRErr OGRSQLiteTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+{
+    if (CheckSpatialIndexTable() &&
+        !CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO")))
+    {
+        const char* pszSQL;
+
+        pszSQL = CPLSPrintf("SELECT MIN(xmin), MIN(ymin), MAX(xmax), MAX(ymax) FROM 'idx_%s_%s'",
+                            pszEscapedTableName, osGeomColumn.c_str());
+
+        CPLDebug("SQLITE", "Running %s", pszSQL);
+
+/* -------------------------------------------------------------------- */
+/*      Execute.                                                        */
+/* -------------------------------------------------------------------- */
+        char **papszResult, *pszErrMsg;
+        int nRowCount, nColCount;
+
+        if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
+                               &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
+            return OGRSQLiteLayer::GetExtent(psExtent, bForce);
+
+        OGRErr eErr = OGRERR_FAILURE;
+
+        if( nRowCount == 1 && nColCount == 4 &&
+            papszResult[4+0] != NULL &&
+            papszResult[4+1] != NULL &&
+            papszResult[4+2] != NULL &&
+            papszResult[4+3] != NULL)
+        {
+            psExtent->MinX = atof(papszResult[4+0]);
+            psExtent->MinY = atof(papszResult[4+1]);
+            psExtent->MaxX = atof(papszResult[4+2]);
+            psExtent->MaxY = atof(papszResult[4+3]);
+            eErr = OGRERR_NONE;
+        }
+
+        sqlite3_free_table( papszResult );
 
+        if (eErr == OGRERR_NONE)
+            return eErr;
+    }
+
+    return OGRSQLiteLayer::GetExtent(psExtent, bForce);
+}
+
+/************************************************************************/
+/*                      OGRFieldTypeToSQliteType()                      */
+/************************************************************************/
+
+static const char* OGRFieldTypeToSQliteType( OGRFieldType eType )
 {
-    return OGRSQLiteLayer::GetSpatialRef();
+    if( eType == OFTInteger )
+        return "INTEGER";
+    else if( eType == OFTReal )
+        return "FLOAT";
+    else if( eType == OFTBinary )
+        return "BLOB";
+    else
+        return "VARCHAR";
 }
 
 /************************************************************************/
@@ -421,6 +632,15 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 
     ResetReading();
 
+    if (!poDS->GetUpdate())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't create fields on a read-only layer.");
+        return OGRERR_FAILURE;
+    }
+
+    ClearInsertStmt();
+
 /* -------------------------------------------------------------------- */
 /*      Do we want to "launder" the column names into SQLite            */
 /*      friendly format?                                                */
@@ -433,45 +653,138 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         CPLFree( pszSafeName );
     }
 
+    /* ADD COLUMN only avaliable since sqlite 3.1.3 */
+    if (CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_USE_ADD_COLUMN", "YES")) &&
+        sqlite3_libversion_number() > 3 * 1000000 + 1 * 1000 + 3)
+    {
+        int rc;
+        char *pszErrMsg = NULL;
+        sqlite3 *hDB = poDS->GetDB();
+        CPLString osCommand;
+
+        osCommand.Printf("ALTER TABLE '%s' ADD COLUMN '%s' %s",
+                        pszEscapedTableName,
+                        oField.GetNameRef(),
+                        OGRFieldTypeToSQliteType(oField.GetType()));
+
+    #ifdef DEBUG
+        CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
+    #endif
+
+        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to add field %s to table %s:\n %s",
+                      oField.GetNameRef(), poFeatureDefn->GetName(), 
+                      pszErrMsg );
+            sqlite3_free( pszErrMsg );
+            return OGRERR_FAILURE;
+        }
+    }
+    else
+    {
+        OGRErr eErr = AddColumnAncientMethod(oField);
+        if (eErr != OGRERR_NONE)
+            return eErr;
+    }
+
 /* -------------------------------------------------------------------- */
-/*      How much space do we need for the list of fields.               */
+/*      Add the field to the OGRFeatureDefn.                            */
 /* -------------------------------------------------------------------- */
-    int iField, nFieldListLen = 100;
-    char *pszOldFieldList, *pszNewFieldList;
+    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;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                     InitFieldListForRecrerate()                      */
+/************************************************************************/
+
+void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
+                                                    char* & pszFieldListForSelect,
+                                                    int nExtraSpace)
+{
+    int iField, nFieldListLen = 100 + nExtraSpace;
 
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
-        nFieldListLen += 
+        nFieldListLen +=
             strlen(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) + 50;
     }
 
-    nFieldListLen += strlen( oField.GetNameRef() );
-
-    pszOldFieldList = (char *) CPLCalloc(1,nFieldListLen);
+    pszFieldListForSelect = (char *) CPLCalloc(1,nFieldListLen);
     pszNewFieldList = (char *) CPLCalloc(1,nFieldListLen);
 
 /* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
 /* -------------------------------------------------------------------- */
-    const char *pszType;
-    sprintf( pszOldFieldList, "%s", "OGC_FID" );
-    sprintf( pszNewFieldList, "%s", "OGC_FID INTEGER PRIMARY KEY" );
-    
-    int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
+    sprintf( pszFieldListForSelect, "%s", pszFIDColumn ? pszFIDColumn : "OGC_FID" );
+    sprintf( pszNewFieldList, "%s INTEGER PRIMARY KEY",pszFIDColumn ? pszFIDColumn : "OGC_FID" );
 
     if( poFeatureDefn->GetGeomType() != wkbNone )
     {
-        strcat( pszOldFieldList, "," );
+        strcat( pszFieldListForSelect, "," );
         strcat( pszNewFieldList, "," );
 
-        strcat( pszOldFieldList, osGeomColumn );
+        strcat( pszFieldListForSelect, osGeomColumn );
         strcat( pszNewFieldList, osGeomColumn );
 
         if ( eGeomFormat == OSGF_WKT )
             strcat( pszNewFieldList, " VARCHAR" );
         else
             strcat( pszNewFieldList, " BLOB" );
+    }
+}
+
+/************************************************************************/
+/*                       AddColumnAncientMethod()                       */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
+{
+    
+/* -------------------------------------------------------------------- */
+/*      How much space do we need for the list of fields.               */
+/* -------------------------------------------------------------------- */
+    int iField;
+    char *pszOldFieldList, *pszNewFieldList;
+
+    InitFieldListForRecrerate(pszNewFieldList, pszOldFieldList,
+                              strlen( oField.GetNameRef() ));
+
+/* -------------------------------------------------------------------- */
+/*      Build list of old fields, and the list of new fields.           */
+/* -------------------------------------------------------------------- */
+
+    int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
 
+    if( poFeatureDefn->GetGeomType() != wkbNone )
+    {
         iNextOrdinal++;
     }
 
@@ -480,23 +793,15 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
 
         // we already added OGC_FID so don't do it again
-        if( EQUAL(poFldDefn->GetNameRef(),"OGC_FID") )
+        if( EQUAL(poFldDefn->GetNameRef(),pszFIDColumn ? pszFIDColumn : "OGC_FID") )
             continue;
 
-        if( poFldDefn->GetType() == OFTInteger )
-            pszType = "INTEGER";
-        else if( poFldDefn->GetType() == OFTReal )
-            pszType = "FLOAT";
-        else if( poFldDefn->GetType() == OFTBinary )
-            pszType = "BLOB";
-        else
-            pszType = "VARCHAR";
-        
         sprintf( pszOldFieldList+strlen(pszOldFieldList), 
-                 ", '%s'", poFldDefn->GetNameRef() );
+                 ", \"%s\"", poFldDefn->GetNameRef() );
 
         sprintf( pszNewFieldList+strlen(pszNewFieldList), 
-                 ", '%s' %s", poFldDefn->GetNameRef(), pszType );
+                 ", '%s' %s", poFldDefn->GetNameRef(),
+                 OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
 
         iNextOrdinal++;
     }
@@ -504,17 +809,10 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 /* -------------------------------------------------------------------- */
 /*      Add the new field.                                              */
 /* -------------------------------------------------------------------- */
-    if( oField.GetType() == OFTInteger )
-        pszType = "INTEGER";
-    else if( oField.GetType() == OFTReal )
-        pszType = "FLOAT";
-    else if( oField.GetType() == OFTBinary )
-        pszType = "BLOB";
-    else
-        pszType = "VARCHAR";
-    
+
     sprintf( pszNewFieldList+strlen(pszNewFieldList), 
-             ", '%s' %s", oField.GetNameRef(), pszType );
+             ", '%s' %s", oField.GetNameRef(),
+             OGRFieldTypeToSQliteType(oField.GetType()) );
 
 /* ==================================================================== */
 /*      Backup, destroy, recreate and repopulate the table.  SQLite     */
@@ -535,8 +833,8 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     sqlite3 *hDB = poDS->GetDB();
     CPLString osSQL;
 
-    osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'", 
-                   poFeatureDefn->GetName() );
+    osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'",
+                   pszEscapedTableName );
 
     int nRowTriggerIndexCount, nColTriggerIndexCount;
     char **papszTriggerIndexResult = NULL;
@@ -557,7 +855,7 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         rc = sqlite3_exec( hDB, 
                            CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
                                        pszOldFieldList, 
-                                       poFeatureDefn->GetName() ),
+                                       pszEscapedTableName ),
                            NULL, NULL, &pszErrMsg );
 
 
@@ -567,14 +865,14 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     if( rc == SQLITE_OK )
         rc = sqlite3_exec( hDB, 
                            CPLSPrintf( "DROP TABLE '%s'", 
-                                       poFeatureDefn->GetName() ),
+                                       pszEscapedTableName ),
                            NULL, NULL, &pszErrMsg );
 
     if( rc == SQLITE_OK )
     {
         const char *pszCmd = 
             CPLSPrintf( "CREATE TABLE '%s' (%s)", 
-                        poFeatureDefn->GetName(),
+                        pszEscapedTableName,
                         pszNewFieldList );
         rc = sqlite3_exec( hDB, pszCmd, 
                            NULL, NULL, &pszErrMsg );
@@ -589,7 +887,7 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     if( rc == SQLITE_OK )
         rc = sqlite3_exec( hDB, 
                            CPLSPrintf( "INSERT INTO '%s' SELECT %s, NULL FROM t1_back",
-                                       poFeatureDefn->GetName(),
+                                       pszEscapedTableName,
                                        pszOldFieldList ),
                            NULL, NULL, &pszErrMsg );
 
@@ -645,287 +943,770 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         return OGRERR_FAILURE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Add the field to the OGRFeatureDefn.                            */
-/* -------------------------------------------------------------------- */
-    int iNewField;
-
-    poFeatureDefn->AddFieldDefn( &oField );
-
-    iNewField = poFeatureDefn->GetFieldCount() - 1;
-    panFieldOrdinals = (int *) 
-        CPLRealloc(panFieldOrdinals, (iNewField+1) * sizeof(int) );
-    panFieldOrdinals[iNewField] = iNextOrdinal;
-
     return OGRERR_NONE;
 }
 
 /************************************************************************/
-/*                             SetFeature()                             */
+/*                           RecreateTable()                            */
 /************************************************************************/
 
-OGRErr OGRSQLiteTableLayer::SetFeature( OGRFeature *poFeature )
-
+OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
+                                          const char* pszNewFieldList,
+                                          const char* pszGenericErrorMessage)
 {
-    if( pszFIDColumn == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "SetFeature() without any FID column." );
-        return OGRERR_FAILURE;
-    }
-    
-    if( poFeature->GetFID() == OGRNullFID )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "SetFeature() with unset FID fails." );
-        return OGRERR_FAILURE;
-    }
 /* -------------------------------------------------------------------- */
-/*      Drop the record with this FID.                                  */
+/*      Do this all in a transaction.                                   */
+/* -------------------------------------------------------------------- */
+    poDS->SoftStartTransaction();
+
+/* -------------------------------------------------------------------- */
+/*      Save existing related triggers and index                        */
 /* -------------------------------------------------------------------- */
     int rc;
     char *pszErrMsg = NULL;
-    const char *pszSQL;
+    sqlite3 *hDB = poDS->GetDB();
+    CPLString osSQL;
 
-    pszSQL = 
-        CPLSPrintf( "DELETE FROM '%s' WHERE \"%s\" = %ld", 
-                    poFeatureDefn->GetName(), 
-                    pszFIDColumn,
-                    poFeature->GetFID() );
+    osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'",
+                   pszEscapedTableName );
+
+    int nRowTriggerIndexCount, nColTriggerIndexCount;
+    char **papszTriggerIndexResult = NULL;
+    rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
+                            &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
 
-    CPLDebug( "OGR_SQLITE", "exec(%s)", pszSQL );
-    
-    rc = sqlite3_exec( poDS->GetDB(), pszSQL,
-                       NULL, NULL, &pszErrMsg );
-    
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Attempt to delete old feature with FID %d failed.\n%s", 
-                  (int) poFeature->GetFID(), pszErrMsg );
-        return OGRERR_FAILURE;
-    }
-    
 /* -------------------------------------------------------------------- */
-/*      Recreate the feature.                                           */
+/*      Make a backup of the table.                                     */
 /* -------------------------------------------------------------------- */
-    return CreateFeature( poFeature );
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
 
-OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
+    if( rc == SQLITE_OK )
+        rc = sqlite3_exec( hDB,
+                       CPLSPrintf( "CREATE TABLE t1_back(%s)",
+                                   pszNewFieldList ),
+                       NULL, NULL, &pszErrMsg );
 
-{
-    sqlite3 *hDB = poDS->GetDB();
-    CPLString      osCommand;
-    CPLString      osValues;
-    int            bNeedComma = FALSE;
+    if( rc == SQLITE_OK )
+        rc = sqlite3_exec( hDB,
+                           CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
+                                       pszFieldListForSelect,
+                                       pszEscapedTableName ),
+                           NULL, NULL, &pszErrMsg );
 
-    ResetReading();
 
 /* -------------------------------------------------------------------- */
-/*      Form the INSERT command.                                        */
+/*      Drop the original table                                         */
 /* -------------------------------------------------------------------- */
-    osCommand += CPLSPrintf( "INSERT INTO '%s' (", poFeatureDefn->GetName() );
+    if( rc == SQLITE_OK )
+        rc = sqlite3_exec( hDB,
+                           CPLSPrintf( "DROP TABLE '%s'",
+                                       pszEscapedTableName ),
+                           NULL, NULL, &pszErrMsg );
 
 /* -------------------------------------------------------------------- */
-/*      Add FID if we have a cleartext FID column.                      */
+/*      Rename backup table as new table                                */
 /* -------------------------------------------------------------------- */
-    if( pszFIDColumn != NULL // && !EQUAL(pszFIDColumn,"OGC_FID") 
-        && poFeature->GetFID() != OGRNullFID )
+    if( rc == SQLITE_OK )
     {
-        osCommand += pszFIDColumn;
+        const char *pszCmd =
+            CPLSPrintf( "ALTER TABLE t1_back RENAME TO '%s'",
+                        pszEscapedTableName);
+        rc = sqlite3_exec( hDB, pszCmd,
+                           NULL, NULL, &pszErrMsg );
+    }
 
-        osValues += CPLSPrintf( "%ld", poFeature->GetFID() );
-        bNeedComma = TRUE;
+/* -------------------------------------------------------------------- */
+/*      Recreate existing related tables, triggers and index            */
+/* -------------------------------------------------------------------- */
+
+    if( rc == SQLITE_OK )
+    {
+        int i;
+
+        for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
+        {
+            if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
+                rc = sqlite3_exec( hDB,
+                            papszTriggerIndexResult[i],
+                            NULL, NULL, &pszErrMsg );
+        }
     }
 
 /* -------------------------------------------------------------------- */
-/*      Add geometry.                                                   */
+/*      COMMIT on success or ROLLBACK on failuire.                      */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poGeom = poFeature->GetGeometryRef();
+
+    sqlite3_free_table( papszTriggerIndexResult );
+
+    if( rc == SQLITE_OK )
+    {
+        poDS->SoftCommit();
+
+        return OGRERR_NONE;
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s:\n %s",
+                  pszGenericErrorMessage,
+                  pszErrMsg );
+        sqlite3_free( pszErrMsg );
+
+        poDS->SoftRollback();
+
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                             DeleteField()                            */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
+{
+    if (!poDS->GetUpdate())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't delete fields on a read-only layer.");
+        return OGRERR_FAILURE;
+    }
+
+    if (iFieldToDelete < 0 || iFieldToDelete >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    ResetReading();
+
+/* -------------------------------------------------------------------- */
+/*      Build list of old fields, and the list of new fields.           */
+/* -------------------------------------------------------------------- */
+    int iField;
+    char *pszNewFieldList, *pszFieldListForSelect;
+    InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
+
+    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
+
+        if (iField == iFieldToDelete)
+            continue;
+
+        sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+                 ", \"%s\"", poFldDefn->GetNameRef() );
+
+        sprintf( pszNewFieldList+strlen(pszNewFieldList),
+                 ", '%s' %s", poFldDefn->GetNameRef(),
+                 OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recreate table.                                                 */
+/* -------------------------------------------------------------------- */
+    CPLString osErrorMsg;
+    osErrorMsg.Printf("Failed to remove field %s from table %s",
+                  poFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef(),
+                  poFeatureDefn->GetName());
+
+    OGRErr eErr = RecreateTable(pszFieldListForSelect,
+                                pszNewFieldList,
+                                osErrorMsg.c_str());
+
+    CPLFree( pszFieldListForSelect );
+    CPLFree( pszNewFieldList );
+
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      Finish                                                          */
+/* -------------------------------------------------------------------- */
+    int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
+
+    if( poFeatureDefn->GetGeomType() != wkbNone )
+    {
+        iNextOrdinal++;
+    }
+
+    int iNewField = 0;
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        if (iField == iFieldToDelete)
+            continue;
+
+        panFieldOrdinals[iNewField ++] = iNextOrdinal++;
+    }
+
+    return poFeatureDefn->DeleteFieldDefn( iFieldToDelete );
+}
+
+/************************************************************************/
+/*                           AlterFieldDefn()                           */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
+{
+    if (!poDS->GetUpdate())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't alter field definition on a read-only layer.");
+        return OGRERR_FAILURE;
+    }
+
+    if (iFieldToAlter < 0 || iFieldToAlter >= poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    ClearInsertStmt();
+    ResetReading();
+
+/* -------------------------------------------------------------------- */
+/*      Build list of old fields, and the list of new fields.           */
+/* -------------------------------------------------------------------- */
+    int iField;
+    char *pszNewFieldList, *pszFieldListForSelect;
+    InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect,
+                              strlen(poNewFieldDefn->GetNameRef()));
+
+    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
+
+        sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+                 ", \"%s\"", poFldDefn->GetNameRef() );
+
+        if (iField == iFieldToAlter)
+        {
+            sprintf( pszNewFieldList+strlen(pszNewFieldList),
+                    ", '%s' %s",
+                    (nFlags & ALTER_NAME_FLAG) ? poNewFieldDefn->GetNameRef() :
+                                                 poFldDefn->GetNameRef(),
+                    OGRFieldTypeToSQliteType((nFlags & ALTER_TYPE_FLAG) ?
+                            poNewFieldDefn->GetType() : poFldDefn->GetType()) );
+        }
+        else
+        {
+            sprintf( pszNewFieldList+strlen(pszNewFieldList),
+                    ", '%s' %s", poFldDefn->GetNameRef(),
+                    OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recreate table.                                                 */
+/* -------------------------------------------------------------------- */
+    CPLString osErrorMsg;
+    osErrorMsg.Printf("Failed to alter field %s from table %s",
+                  poFeatureDefn->GetFieldDefn(iFieldToAlter)->GetNameRef(),
+                  poFeatureDefn->GetName());
+
+    OGRErr eErr = RecreateTable(pszFieldListForSelect,
+                                pszNewFieldList,
+                                osErrorMsg.c_str());
+
+    CPLFree( pszFieldListForSelect );
+    CPLFree( pszNewFieldList );
+
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      Finish                                                          */
+/* -------------------------------------------------------------------- */
+
+    OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iFieldToAlter);
+
+    if (nFlags & ALTER_TYPE_FLAG)
+        poFieldDefn->SetType(poNewFieldDefn->GetType());
+    if (nFlags & ALTER_NAME_FLAG)
+        poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
+    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    {
+        poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
+        poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           ReorderFields()                            */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
+{
+    if (!poDS->GetUpdate())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't reorder fields on a read-only layer.");
+        return OGRERR_FAILURE;
+    }
+
+    if (poFeatureDefn->GetFieldCount() == 0)
+        return OGRERR_NONE;
+
+    OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+    ClearInsertStmt();
+    ResetReading();
+
+/* -------------------------------------------------------------------- */
+/*      Build list of old fields, and the list of new fields.           */
+/* -------------------------------------------------------------------- */
+    int iField;
+    char *pszNewFieldList, *pszFieldListForSelect;
+    InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
+
+    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(panMap[iField]);
+
+        sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
+                 ", \"%s\"", poFldDefn->GetNameRef() );
+
+        sprintf( pszNewFieldList+strlen(pszNewFieldList),
+                ", '%s' %s", poFldDefn->GetNameRef(),
+                OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recreate table.                                                 */
+/* -------------------------------------------------------------------- */
+    CPLString osErrorMsg;
+    osErrorMsg.Printf("Failed to reorder fields from table %s",
+                  poFeatureDefn->GetName());
+
+    eErr = RecreateTable(pszFieldListForSelect,
+                                pszNewFieldList,
+                                osErrorMsg.c_str());
+
+    CPLFree( pszFieldListForSelect );
+    CPLFree( pszNewFieldList );
+
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      Finish                                                          */
+/* -------------------------------------------------------------------- */
+
+    return poFeatureDefn->ReorderFieldDefns( panMap );
+}
+
+/************************************************************************/
+/*                             BindValues()                             */
+/************************************************************************/
+
+/* the bBindNullValues is set to TRUE by SetFeature() for UPDATE statements, */
+/* and to FALSE by CreateFeature() for INSERT statements; */
+
+OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
+                                        sqlite3_stmt* hStmt,
+                                        int bBindNullValues )
+{
+    int rc;
+    sqlite3 *hDB = poDS->GetDB();
+
+/* -------------------------------------------------------------------- */
+/*      Bind the geometry                                               */
+/* -------------------------------------------------------------------- */
+    int nBindField = 1;
 
     if( osGeomColumn.size() != 0 &&
-        poGeom != NULL &&
         eGeomFormat != OSGF_FGF )
     {
+        OGRGeometry* poGeom = poFeature->GetGeometryRef();
+        if ( poGeom != NULL )
+        {
+            if ( eGeomFormat == OSGF_WKT )
+            {
+                char *pszWKT = NULL;
+                poGeom->exportToWkt( &pszWKT );
+                rc = sqlite3_bind_text( hStmt, nBindField++, pszWKT, -1, CPLFree );
+            }
+            else if( eGeomFormat == OSGF_WKB )
+            {
+                int nWKBLen = poGeom->WkbSize();
+                GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
 
-        if( bNeedComma )
+                poGeom->exportToWkb( wkbNDR, pabyWKB );
+                rc = sqlite3_bind_blob( hStmt, nBindField++, pabyWKB, nWKBLen, CPLFree );
+            }
+            else if ( eGeomFormat == OSGF_SpatiaLite )
+            {
+                int     nBLOBLen;
+                GByte   *pabySLBLOB;
+
+                ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR, bHasM,
+                                        bSpatialite2D, bUseComprGeom, &pabySLBLOB, &nBLOBLen );
+                rc = sqlite3_bind_blob( hStmt, nBindField++, pabySLBLOB,
+                                        nBLOBLen, CPLFree );
+            }
+            else
+            {
+                rc = SQLITE_OK;
+                CPLAssert(0);
+            }
+        }
+        else
         {
-            osCommand += ",";
-            osValues += ",";
+            if (bBindNullValues)
+                rc = sqlite3_bind_null( hStmt, nBindField++ );
+            else
+                rc = SQLITE_OK;
         }
 
-        osCommand += osGeomColumn;
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "sqlite3_bind_blob/text() failed:\n  %s",
+                      sqlite3_errmsg(hDB) );
+            return OGRERR_FAILURE;
+        }
+    }
 
-        osValues += "?";
+/* -------------------------------------------------------------------- */
+/*      Bind field values.                                              */
+/* -------------------------------------------------------------------- */
+    int iField;
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+    for( iField = 0; iField < nFieldCount; iField++ )
+    {
+        const char *pszRawValue;
+
+        if( !poFeature->IsFieldSet( iField ) )
+        {
+            if (bBindNullValues)
+                rc = sqlite3_bind_null( hStmt, nBindField++ );
+            else
+                rc = SQLITE_OK;
+        }
+        else
+        {
+            switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
+            {
+                case OFTInteger:
+                {
+                    int nFieldVal = poFeature->GetFieldAsInteger( iField );
+                    rc = sqlite3_bind_int(hStmt, nBindField++, nFieldVal);
+                    break;
+                }
+
+                case OFTReal:
+                {
+                    double dfFieldVal = poFeature->GetFieldAsDouble( iField );
+                    rc = sqlite3_bind_double(hStmt, nBindField++, dfFieldVal);
+                    break;
+                }
+
+                case OFTBinary:
+                {
+                    int nDataLength = 0;
+                    GByte* pabyData =
+                        poFeature->GetFieldAsBinary( iField, &nDataLength );
+                    rc = sqlite3_bind_blob(hStmt, nBindField++,
+                                        pabyData, nDataLength, SQLITE_TRANSIENT);
+                    break;
+                }
+
+                default:
+                {
+                    pszRawValue = poFeature->GetFieldAsString( iField );
+                    rc = sqlite3_bind_text(hStmt, nBindField++,
+                                        pszRawValue, -1, SQLITE_TRANSIENT);
+                    break;
+                }
+            }
+        }
+
+        if( rc != SQLITE_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "sqlite3_bind_() for column %s failed:\n  %s",
+                      poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
+                      sqlite3_errmsg(hDB) );
+            return OGRERR_FAILURE;
+        }
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                             SetFeature()                             */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::SetFeature( OGRFeature *poFeature )
+
+{
+    if( pszFIDColumn == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "SetFeature() without any FID column." );
+        return OGRERR_FAILURE;
+    }
+    
+    if( poFeature->GetFID() == OGRNullFID )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "SetFeature() with unset FID fails." );
+        return OGRERR_FAILURE;
+    }
+
+    if (bSpatialiteReadOnly || !poDS->GetUpdate())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't update feature on a read-only layer.");
+        return OGRERR_FAILURE;
+    }
+
+    sqlite3 *hDB = poDS->GetDB();
+    CPLString      osCommand;
+    int            bNeedComma = FALSE;
+
+    ResetReading();
+
+/* -------------------------------------------------------------------- */
+/*      Form the UPDATE command.                                        */
+/* -------------------------------------------------------------------- */
+    osCommand += CPLSPrintf( "UPDATE '%s' SET ", pszEscapedTableName );
+
+/* -------------------------------------------------------------------- */
+/*      Add geometry field name.                                        */
+/* -------------------------------------------------------------------- */
+    if( osGeomColumn.size() != 0 &&
+        eGeomFormat != OSGF_FGF )
+    {
+        osCommand += "\"";
+        osCommand += osGeomColumn;
+        osCommand += "\" = ?";
 
         bNeedComma = TRUE;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Add field values.                                               */
+/*      Add field names.                                                */
 /* -------------------------------------------------------------------- */
     int iField;
     int nFieldCount = poFeatureDefn->GetFieldCount();
 
     for( iField = 0; iField < nFieldCount; iField++ )
     {
-        if( !poFeature->IsFieldSet( iField ) )
-            continue;
-
         if( bNeedComma )
-        {
             osCommand += ",";
-            osValues += ",";
-        }
 
-        osCommand += "'";
+        osCommand += "\"";
         osCommand +=poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
-        osCommand += "'";
-
-        osValues += "?";
+        osCommand += "\" = ?";
 
         bNeedComma = TRUE;
     }
 
+    if (!bNeedComma)
+        return OGRERR_NONE;
+
 /* -------------------------------------------------------------------- */
 /*      Merge final command.                                            */
 /* -------------------------------------------------------------------- */
-    osCommand += ") VALUES (";
-    osCommand += osValues;
-    osCommand += ")";
+    osCommand += " WHERE \"";
+    osCommand += pszFIDColumn;
+    osCommand += CPLSPrintf("\" = %ld", poFeature->GetFID());
 
 /* -------------------------------------------------------------------- */
 /*      Prepare the statement.                                          */
 /* -------------------------------------------------------------------- */
     int rc;
-    sqlite3_stmt *hInsertStmt;
+    sqlite3_stmt *hUpdateStmt;
 
 #ifdef DEBUG
     CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
 #endif
 
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
+    rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "In CreateFeature(): sqlite3_prepare(%s):\n  %s", 
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "In SetFeature(): sqlite3_prepare(%s):\n  %s",
                   osCommand.c_str(), sqlite3_errmsg(hDB) );
 
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Bind the geometry                                               */
+/*      Bind values.                                                   */
 /* -------------------------------------------------------------------- */
-    int nBindField = 1;
+    OGRErr eErr = BindValues( poFeature, hUpdateStmt, TRUE );
+    if (eErr != OGRERR_NONE)
+    {
+        sqlite3_finalize( hUpdateStmt );
+        return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Execute the update.                                             */
+/* -------------------------------------------------------------------- */
+    rc = sqlite3_step( hUpdateStmt );
+
+    if( rc != SQLITE_OK && rc != SQLITE_DONE )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "sqlite3_step() failed:\n  %s",
+                  sqlite3_errmsg(hDB) );
+
+        sqlite3_finalize( hUpdateStmt );
+        return OGRERR_FAILURE;
+    }
+
+    sqlite3_finalize( hUpdateStmt );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           CreateFeature()                            */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
+
+{
+    sqlite3 *hDB = poDS->GetDB();
+    CPLString      osCommand;
+    CPLString      osValues;
+    int            bNeedComma = FALSE;
+
+    if (bSpatialiteReadOnly || !poDS->GetUpdate())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't create feature on a read-only layer.");
+        return OGRERR_FAILURE;
+    }
+
+    ResetReading();
+
+/* -------------------------------------------------------------------- */
+/*      Form the INSERT command.                                        */
+/* -------------------------------------------------------------------- */
+    osCommand += CPLSPrintf( "INSERT INTO '%s' (", pszEscapedTableName );
+
+/* -------------------------------------------------------------------- */
+/*      Add FID if we have a cleartext FID column.                      */
+/* -------------------------------------------------------------------- */
+    if( pszFIDColumn != NULL // && !EQUAL(pszFIDColumn,"OGC_FID") 
+        && poFeature->GetFID() != OGRNullFID )
+    {
+        osCommand += "\"";
+        osCommand += pszFIDColumn;
+        osCommand += "\"";
+
+        osValues += CPLSPrintf( "%ld", poFeature->GetFID() );
+        bNeedComma = TRUE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add geometry.                                                   */
+/* -------------------------------------------------------------------- */
+    OGRGeometry *poGeom = poFeature->GetGeometryRef();
 
     if( osGeomColumn.size() != 0 &&
         poGeom != NULL &&
         eGeomFormat != OSGF_FGF )
     {
-        if ( eGeomFormat == OSGF_WKT )
+
+        if( bNeedComma )
         {
-            char *pszWKT = NULL;
-            poGeom->exportToWkt( &pszWKT );
-            rc = sqlite3_bind_text( hInsertStmt, nBindField++, pszWKT, -1, CPLFree );
+            osCommand += ",";
+            osValues += ",";
         }
-        else if( eGeomFormat == OSGF_WKB )
-        {
-            int nWKBLen = poGeom->WkbSize();
-            GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
 
-            poGeom->exportToWkb( wkbNDR, pabyWKB );
-            rc = sqlite3_bind_blob( hInsertStmt, nBindField++, pabyWKB, nWKBLen, CPLFree );
-        }
-        else if ( eGeomFormat == OSGF_SpatiaLite )
-        {
-            int     nBLOBLen;
-            GByte   *pabySLBLOB;
+        osCommand += "\"";
+        osCommand += osGeomColumn;
+        osCommand += "\"";
 
-            ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR,
-                                      &pabySLBLOB, &nBLOBLen );
-            rc = sqlite3_bind_blob( hInsertStmt, nBindField++, pabySLBLOB, nBLOBLen, CPLFree );
-        }
-        else
-        {
-            CPLAssert(0);
-        }
+        osValues += "?";
 
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "sqlite3_bind_blob/text() failed:\n  %s", 
-                      sqlite3_errmsg(hDB) );
-            
-            sqlite3_finalize( hInsertStmt );
-            return OGRERR_FAILURE;
-        }
+        bNeedComma = TRUE;
     }
-    
+
 /* -------------------------------------------------------------------- */
-/*      Bind field values.                                              */
+/*      Add field values.                                               */
 /* -------------------------------------------------------------------- */
-    
+    int iField;
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+
     for( iField = 0; iField < nFieldCount; iField++ )
     {
-        const char *pszRawValue;
-
         if( !poFeature->IsFieldSet( iField ) )
             continue;
 
-        switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
+        if( bNeedComma )
         {
-            case OFTInteger:
-            {
-                int nFieldVal = poFeature->GetFieldAsInteger( iField );
-                rc = sqlite3_bind_int(hInsertStmt, nBindField++, nFieldVal);
-                break;
-            }
-            
-            case OFTReal:
-            {
-                double dfFieldVal = poFeature->GetFieldAsDouble( iField );
-                rc = sqlite3_bind_double(hInsertStmt, nBindField++, dfFieldVal);
-                break;
-            }
-            
-            case OFTBinary:
-            {
-                int nDataLength = 0;
-                GByte* pabyData =
-                    poFeature->GetFieldAsBinary( iField, &nDataLength );
-                rc = sqlite3_bind_blob(hInsertStmt, nBindField++,
-                                       pabyData, nDataLength, SQLITE_TRANSIENT);
-                break;
-            }
-            
-            default:
-            {
-                pszRawValue = poFeature->GetFieldAsString( iField );
-                rc = sqlite3_bind_text(hInsertStmt, nBindField++,
-                                       pszRawValue, -1, SQLITE_TRANSIENT);
-                break;
-            }
+            osCommand += ",";
+            osValues += ",";
         }
-        
+
+        osCommand += "\"";
+        osCommand +=poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
+        osCommand += "\"";
+
+        osValues += "?";
+
+        bNeedComma = TRUE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Merge final command.                                            */
+/* -------------------------------------------------------------------- */
+    osCommand += ") VALUES (";
+    osCommand += osValues;
+    osCommand += ")";
+
+/* -------------------------------------------------------------------- */
+/*      Prepare the statement.                                          */
+/* -------------------------------------------------------------------- */
+    int rc;
+
+    if (hInsertStmt == NULL ||
+        osCommand != osLastInsertStmt)
+    {
+    #ifdef DEBUG
+        CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
+    #endif
+
+        ClearInsertStmt();
+        osLastInsertStmt = osCommand;
+
+#ifdef HAVE_SQLITE3_PREPARE_V2
+        rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
+#else
+        rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
+#endif
         if( rc != SQLITE_OK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "sqlite3_bind_() for column %s failed:\n  %s", 
-                      poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
-                      sqlite3_errmsg(hDB) );
-            
-            sqlite3_finalize( hInsertStmt );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "In CreateFeature(): sqlite3_prepare(%s):\n  %s",
+                    osCommand.c_str(), sqlite3_errmsg(hDB) );
+
+            ClearInsertStmt();
             return OGRERR_FAILURE;
         }
     }
 
 /* -------------------------------------------------------------------- */
+/*      Bind values.                                                   */
+/* -------------------------------------------------------------------- */
+    OGRErr eErr = BindValues( poFeature, hInsertStmt, FALSE );
+    if (eErr != OGRERR_NONE)
+    {
+        sqlite3_reset( hInsertStmt );
+        return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Execute the insert.                                             */
 /* -------------------------------------------------------------------- */
     rc = sqlite3_step( hInsertStmt );
@@ -933,10 +1714,9 @@ OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
     if( rc != SQLITE_OK && rc != SQLITE_DONE )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
-                  "sqlite3_step() failed:\n  %s", 
-                  sqlite3_errmsg(hDB) );
-                  
-        sqlite3_finalize( hInsertStmt );
+                  "sqlite3_step() failed:\n  %s (%d)", 
+                  sqlite3_errmsg(hDB), rc );
+        sqlite3_reset( hInsertStmt );
         return OGRERR_FAILURE;
     }
 
@@ -946,11 +1726,56 @@ OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
     const sqlite_int64 nFID = sqlite3_last_insert_rowid( hDB );
     if(nFID > 0)
     {
-        poFeature->SetFID( nFID );
+        poFeature->SetFID( (long)nFID ); /* Possible truncation if nFID is 64bit */
     }
 
-    sqlite3_finalize( hInsertStmt );
+    sqlite3_reset( hInsertStmt );
 
     return OGRERR_NONE;
 }
 
+/************************************************************************/
+/*                           DeleteFeature()                            */
+/************************************************************************/
+
+OGRErr OGRSQLiteTableLayer::DeleteFeature( long nFID )
+
+{
+    CPLString      osSQL;
+    int            rc;
+    char          *pszErrMsg = NULL;
+
+    if( pszFIDColumn == NULL )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't delete feature on a layer without FID column.");
+        return OGRERR_FAILURE;
+    }
+
+    if (bSpatialiteReadOnly || !poDS->GetUpdate())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't delete feature on a read-only layer.");
+        return OGRERR_FAILURE;
+    }
+
+    ResetReading();
+
+    osSQL.Printf( "DELETE FROM '%s' WHERE \"%s\" = %ld",
+                  pszEscapedTableName,
+                  pszFIDColumn, nFID );
+
+    CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
+
+    rc = sqlite3_exec( poDS->GetDB(), osSQL, NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "In DeleteFeature(): sqlite3_exec(%s):\n  %s",
+                    osSQL.c_str(), pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
new file mode 100644
index 0000000..4299bc1
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
@@ -0,0 +1,371 @@
+/******************************************************************************
+ * $Id: ogrsqlitevfs.cpp 23346 2011-11-06 15:27:58Z 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>
+ *
+ * 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_sqlite.h"
+
+CPL_CVSID("$Id: ogrsqlitevfs.cpp 23346 2011-11-06 15:27:58Z rouault $");
+
+//#define DEBUG_IO 1
+
+#ifdef HAVE_SQLITE_VFS
+
+typedef struct
+{
+    const struct sqlite3_io_methods *pMethods;
+    VSILFILE                        *fp;
+    int                              bDeleteOnClose;
+    char                            *pszFilename;
+} OGRSQLiteFileStruct;
+
+static int OGRSQLiteIOClose(sqlite3_file* pFile)
+{
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteIOClose(%p (%s))", pMyFile->fp, pMyFile->pszFilename);
+#endif
+    VSIFCloseL(pMyFile->fp);
+    if (pMyFile->bDeleteOnClose)
+        VSIUnlink(pMyFile->pszFilename);
+    CPLFree(pMyFile->pszFilename);
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIORead(sqlite3_file* pFile, void* pBuffer, int iAmt, sqlite3_int64 iOfst)
+{
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteIORead(%p, %d, %d)", pMyFile->fp, iAmt, (int)iOfst);
+#endif
+    VSIFSeekL(pMyFile->fp, (vsi_l_offset) iOfst, SEEK_SET);
+    int nRead = (int)VSIFReadL(pBuffer, 1, iAmt, pMyFile->fp);
+    if (nRead < iAmt)
+    {
+        memset(((char*)pBuffer) + nRead, 0, iAmt - nRead);
+        return SQLITE_IOERR_SHORT_READ;
+    }
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOWrite(sqlite3_file* pFile, const void* pBuffer, int iAmt, sqlite3_int64 iOfst)
+{
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteIOWrite(%p, %d, %d)", pMyFile->fp, iAmt, (int)iOfst);
+#endif
+    VSIFSeekL(pMyFile->fp, (vsi_l_offset) iOfst, SEEK_SET);
+    int nWritten = (int)VSIFWriteL(pBuffer, 1, iAmt, pMyFile->fp);
+    if (nWritten < iAmt)
+    {
+        return SQLITE_IOERR_WRITE;
+    }
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOTruncate(sqlite3_file* pFile, sqlite3_int64 size)
+{
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteIOTruncate(%p)", pMyFile->fp);
+#endif
+    int nRet = VSIFTruncateL(pMyFile->fp, size);
+    return (nRet == 0) ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
+}
+
+static int OGRSQLiteIOSync(sqlite3_file* pFile, int flags)
+{
+#ifdef DEBUG_IO
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    CPLDebug("SQLITE", "OGRSQLiteIOSync(%p, %d)", pMyFile->fp, flags);
+#endif
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOFileSize(sqlite3_file* pFile, sqlite3_int64 *pSize)
+{
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteIOFileSize(%p)", pMyFile->fp);
+#endif
+    vsi_l_offset nCurOffset = VSIFTellL(pMyFile->fp);
+    VSIFSeekL(pMyFile->fp, 0, SEEK_END);
+    *pSize = VSIFTellL(pMyFile->fp);
+    VSIFSeekL(pMyFile->fp, nCurOffset, SEEK_SET);
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOLock(sqlite3_file* pFile, int flags)
+{
+#ifdef DEBUG_IO
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    CPLDebug("SQLITE", "OGRSQLiteIOLock(%p)", pMyFile->fp);
+#endif
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOUnlock(sqlite3_file* pFile, int flags)
+{
+#ifdef DEBUG_IO
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    CPLDebug("SQLITE", "OGRSQLiteIOUnlock(%p)", pMyFile->fp);
+#endif
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOCheckReservedLock(sqlite3_file* pFile, int *pResOut)
+{
+#ifdef DEBUG_IO
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    CPLDebug("SQLITE", "OGRSQLiteIOCheckReservedLock(%p)", pMyFile->fp);
+#endif
+    *pResOut = 0;
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOFileControl(sqlite3_file* pFile, int op, void *pArg)
+{
+#ifdef DEBUG_IO
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    CPLDebug("SQLITE", "OGRSQLiteIOFileControl(%p)", pMyFile->fp);
+#endif
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteIOSectorSize(sqlite3_file* pFile)
+{
+#ifdef DEBUG_IO
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    CPLDebug("SQLITE", "OGRSQLiteIOSectorSize(%p)", pMyFile->fp);
+#endif
+    return 0;
+}
+
+static int OGRSQLiteIODeviceCharacteristics(sqlite3_file* pFile)
+{
+#ifdef DEBUG_IO
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    CPLDebug("SQLITE", "OGRSQLiteIODeviceCharacteristics(%p)", pMyFile->fp);
+#endif
+    return 0;
+}
+
+static const sqlite3_io_methods OGRSQLiteIOMethods =
+{
+    1,
+    OGRSQLiteIOClose,
+    OGRSQLiteIORead,
+    OGRSQLiteIOWrite,
+    OGRSQLiteIOTruncate,
+    OGRSQLiteIOSync,
+    OGRSQLiteIOFileSize,
+    OGRSQLiteIOLock,
+    OGRSQLiteIOUnlock,
+    OGRSQLiteIOCheckReservedLock,
+    OGRSQLiteIOFileControl,
+    OGRSQLiteIOSectorSize,
+    OGRSQLiteIODeviceCharacteristics
+};
+
+static int OGRSQLiteVFSOpen(sqlite3_vfs* pVFS,
+                            const char *zName,
+                            sqlite3_file* pFile,
+                            int flags,
+                            int *pOutFlags)
+{
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteVFSOpen(%s, %d)", zName ? zName : "(null)", flags);
+#endif
+
+    if (zName == NULL)
+        //return SQLITE_IOERR;
+        zName = CPLSPrintf("/vsimem/sqlite/%p", pVFS);
+
+    OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
+    pMyFile->pMethods = NULL;
+    pMyFile->bDeleteOnClose = FALSE;
+    pMyFile->pszFilename = NULL;
+    if ( flags & SQLITE_OPEN_READONLY )
+        pMyFile->fp = VSIFOpenL(zName, "rb");
+    else if ( flags & SQLITE_OPEN_CREATE )
+        pMyFile->fp = VSIFOpenL(zName, "wb+");
+    else if ( flags & SQLITE_OPEN_READWRITE )
+        pMyFile->fp = VSIFOpenL(zName, "rb+");
+    else
+        pMyFile->fp = NULL;
+
+    if (pMyFile->fp == NULL)
+        return SQLITE_CANTOPEN;
+
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteVFSOpen() = %p", pMyFile->fp);
+#endif
+
+    pMyFile->pMethods = &OGRSQLiteIOMethods;
+    pMyFile->bDeleteOnClose = ( flags & SQLITE_OPEN_DELETEONCLOSE );
+    pMyFile->pszFilename = CPLStrdup(zName);
+
+    if (pOutFlags != NULL)
+        *pOutFlags = flags;
+
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteVFSDelete(sqlite3_vfs* pVFS, const char *zName, int syncDir)
+{
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteVFSDelete(%s)", zName);
+#endif
+    VSIUnlink(zName);
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteVFSAccess (sqlite3_vfs* pVFS, const char *zName, int flags, int *pResOut)
+{
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteVFSAccess(%s, %d)", zName, flags);
+#endif
+    VSIStatBufL sStatBufL;
+    int nRet;
+    if (flags == SQLITE_ACCESS_EXISTS)
+        nRet = VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG);
+    else if (flags == SQLITE_ACCESS_READ)
+    {
+        VSILFILE* fp = VSIFOpenL(zName, "rb");
+        nRet = fp ? 0 : -1;
+        if (fp)
+            VSIFCloseL(fp);
+    }
+    else if (flags == SQLITE_ACCESS_READWRITE)
+    {
+        VSILFILE* fp = VSIFOpenL(zName, "rb+");
+        nRet = fp ? 0 : -1;
+        if (fp)
+            VSIFCloseL(fp);
+    }
+    else
+        nRet = -1;
+    *pResOut = (nRet == 0);
+    return SQLITE_OK;
+}
+
+static int OGRSQLiteVFSFullPathname (sqlite3_vfs* pVFS, const char *zName, int nOut, char *zOut)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+#ifdef DEBUG_IO
+    CPLDebug("SQLITE", "OGRSQLiteVFSFullPathname(%s)", zName);
+#endif
+    if (zName[0] == '/')
+    {
+        strncpy(zOut, zName, nOut);
+        zOut[nOut-1] = '\0';
+        return SQLITE_OK;
+    }
+    return pUnderlyingVFS->xFullPathname(pUnderlyingVFS, zName, nOut, zOut);
+}
+
+static void* OGRSQLiteVFSDlOpen (sqlite3_vfs* pVFS, const char *zFilename)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSDlOpen(%s)", zFilename);
+    return pUnderlyingVFS->xDlOpen(pUnderlyingVFS, zFilename);
+}
+
+static void OGRSQLiteVFSDlError (sqlite3_vfs* pVFS, int nByte, char *zErrMsg)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSDlError()");
+    pUnderlyingVFS->xDlError(pUnderlyingVFS, nByte, zErrMsg);
+}
+
+static void (*OGRSQLiteVFSDlSym (sqlite3_vfs* pVFS,void* pHandle, const char *zSymbol))(void)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSDlSym(%s)", zSymbol);
+    return pUnderlyingVFS->xDlSym(pUnderlyingVFS, pHandle, zSymbol);
+}
+
+static void OGRSQLiteVFSDlClose (sqlite3_vfs* pVFS, void* pHandle)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSDlClose(%p)", pHandle);
+    pUnderlyingVFS->xDlClose(pUnderlyingVFS, pHandle);
+}
+
+static int OGRSQLiteVFSRandomness (sqlite3_vfs* pVFS, int nByte, char *zOut)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSRandomness()");
+    return pUnderlyingVFS->xRandomness(pUnderlyingVFS, nByte, zOut);
+}
+
+static int OGRSQLiteVFSSleep (sqlite3_vfs* pVFS, int microseconds)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSSleep()");
+    return pUnderlyingVFS->xSleep(pUnderlyingVFS, microseconds);
+}
+
+static int OGRSQLiteVFSCurrentTime (sqlite3_vfs* pVFS, double* p1)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSCurrentTime()");
+    return pUnderlyingVFS->xCurrentTime(pUnderlyingVFS, p1);
+}
+
+static int OGRSQLiteVFSGetLastError (sqlite3_vfs* pVFS, int p1, char *p2)
+{
+    sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
+    //CPLDebug("SQLITE", "OGRSQLiteVFSGetLastError()");
+    return pUnderlyingVFS->xGetLastError(pUnderlyingVFS, p1, p2);
+}
+
+sqlite3_vfs* OGRSQLiteCreateVFS()
+{
+    sqlite3_vfs* pDefaultVFS = sqlite3_vfs_find(NULL);
+    sqlite3_vfs* pMyVFS = (sqlite3_vfs*) CPLCalloc(1, sizeof(sqlite3_vfs));
+    pMyVFS->iVersion = 1;
+    pMyVFS->szOsFile = sizeof(OGRSQLiteFileStruct);
+    pMyVFS->mxPathname = pDefaultVFS->mxPathname;
+    pMyVFS->zName = "myvfs";
+    pMyVFS->pAppData = pDefaultVFS;
+    pMyVFS->xOpen = OGRSQLiteVFSOpen;
+    pMyVFS->xDelete = OGRSQLiteVFSDelete;
+    pMyVFS->xAccess = OGRSQLiteVFSAccess;
+    pMyVFS->xFullPathname = OGRSQLiteVFSFullPathname;
+    pMyVFS->xDlOpen = OGRSQLiteVFSDlOpen;
+    pMyVFS->xDlError = OGRSQLiteVFSDlError;
+    pMyVFS->xDlSym = OGRSQLiteVFSDlSym;
+    pMyVFS->xDlClose = OGRSQLiteVFSDlClose;
+    pMyVFS->xRandomness = OGRSQLiteVFSRandomness;
+    pMyVFS->xSleep = OGRSQLiteVFSSleep;
+    pMyVFS->xCurrentTime = OGRSQLiteVFSCurrentTime;
+    pMyVFS->xGetLastError = OGRSQLiteVFSGetLastError;
+    return pMyVFS;
+}
+
+#endif // HAVE_SQLITE_VFS
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
new file mode 100644
index 0000000..efb1d14
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
@@ -0,0 +1,459 @@
+/******************************************************************************
+ * $Id: ogrsqliteviewlayer.cpp 23015 2011-08-31 19:48:00Z 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>
+ *
+ * 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 "cpl_string.h"
+#include "ogr_sqlite.h"
+#include <string>
+
+CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 23015 2011-08-31 19:48:00Z rouault $");
+
+/************************************************************************/
+/*                        OGRSQLiteViewLayer()                         */
+/************************************************************************/
+
+OGRSQLiteViewLayer::OGRSQLiteViewLayer( OGRSQLiteDataSource *poDSIn )
+
+{
+    poDS = poDSIn;
+
+    iNextShapeId = 0;
+
+    nSRSId = -1;
+
+    poFeatureDefn = NULL;
+    pszEscapedTableName = NULL;
+    pszEscapedUnderlyingTableName = NULL;
+
+    bHasCheckedSpatialIndexTable = FALSE;
+}
+
+/************************************************************************/
+/*                        ~OGRSQLiteViewLayer()                        */
+/************************************************************************/
+
+OGRSQLiteViewLayer::~OGRSQLiteViewLayer()
+
+{
+    ClearStatement();
+    CPLFree(pszEscapedTableName);
+    CPLFree(pszEscapedUnderlyingTableName);
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+CPLErr OGRSQLiteViewLayer::Initialize( const char *pszViewName,
+                                       const char *pszViewGeometry,
+                                       const char *pszViewRowid,
+                                       const char *pszUnderlyingTableName,
+                                       const char *pszUnderlyingGeometryColumn,
+                                       int bSpatialiteLoaded)
+
+{
+    int rc;
+    sqlite3 *hDB = poDS->GetDB();
+
+    OGRSQLiteLayer* poUnderlyingLayer = (OGRSQLiteLayer*) poDS->GetLayerByName(pszUnderlyingTableName);
+    if (poUnderlyingLayer == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find underlying layer %s for view %s",
+                 pszUnderlyingTableName, pszViewName);
+        return CE_Failure;
+    }
+    if ( !poUnderlyingLayer->IsTableLayer() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Underlying layer %s for view %s is not a regular table",
+                 pszUnderlyingTableName, pszViewName);
+        return CE_Failure;
+    }
+
+    const char* pszRealUnderlyingGeometryColumn = poUnderlyingLayer->GetGeometryColumn();
+    if ( pszRealUnderlyingGeometryColumn == NULL ||
+         !EQUAL(pszRealUnderlyingGeometryColumn, pszUnderlyingGeometryColumn) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Underlying layer %s for view %s has not expected geometry column name (%s instead of %s)",
+                 pszUnderlyingTableName, pszViewName,
+                 pszRealUnderlyingGeometryColumn ? pszRealUnderlyingGeometryColumn : "(null)",
+                 pszUnderlyingGeometryColumn);
+        return CE_Failure;
+    }
+
+    osGeomColumn = pszViewGeometry;
+    eGeomFormat = OSGF_SpatiaLite;
+
+    CPLFree( pszFIDColumn );
+    pszFIDColumn = CPLStrdup( pszViewRowid );
+
+    osUnderlyingTableName = pszUnderlyingTableName;
+    osUnderlyingGeometryColumn = pszUnderlyingGeometryColumn;
+
+    poSRS = poUnderlyingLayer->GetSpatialRef();
+    if (poSRS)
+        poSRS->Reference();
+
+    this->bHasSpatialIndex = poUnderlyingLayer->HasSpatialIndex();
+    this->bSpatialiteLoaded = bSpatialiteLoaded;
+    //this->bHasM = bHasM;
+
+    pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszViewName));
+    pszEscapedUnderlyingTableName = CPLStrdup(OGRSQLiteEscape(pszUnderlyingTableName));
+
+    CPLErr eErr;
+    sqlite3_stmt *hColStmt = NULL;
+    const char *pszSQL;
+
+/* -------------------------------------------------------------------- */
+/*      Get the column definitions for this table.                      */
+/* -------------------------------------------------------------------- */
+    hColStmt = NULL;
+    pszSQL = CPLSPrintf( "SELECT %s, * FROM '%s' LIMIT 1", pszFIDColumn, 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.",
+                  pszViewName, 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;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect the rest of the fields.                                 */
+/* -------------------------------------------------------------------- */
+    eErr = BuildFeatureDefn( pszViewName, hColStmt );
+    sqlite3_finalize( hColStmt );
+
+    if( eErr != CE_None )
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      Set the geometry type if we know it.                            */
+/* -------------------------------------------------------------------- */
+    poFeatureDefn->SetGeomType( poUnderlyingLayer->GetGeomType() );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           ResetStatement()                           */
+/************************************************************************/
+
+OGRErr OGRSQLiteViewLayer::ResetStatement()
+
+{
+    int rc;
+    CPLString osSQL;
+
+    ClearStatement();
+
+    iNextShapeId = 0;
+
+    osSQL.Printf( "SELECT %s, * FROM '%s' %s",
+                  pszFIDColumn,
+                    pszEscapedTableName, 
+                    osWHERE.c_str() );
+
+    rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
+		          &hStmt, NULL );
+
+    if( rc == SQLITE_OK )
+    {
+	return OGRERR_NONE;
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
+                  osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
+        hStmt = NULL;
+        return OGRERR_FAILURE;
+    }
+}
+
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRSQLiteViewLayer::GetFeature( long nFeatureId )
+
+{
+/* -------------------------------------------------------------------- */
+/*      If we don't have an explicit FID column, just read through      */
+/*      the result set iteratively to find our target.                  */
+/* -------------------------------------------------------------------- */
+    if( pszFIDColumn == NULL )
+        return OGRSQLiteLayer::GetFeature( nFeatureId );
+
+/* -------------------------------------------------------------------- */
+/*      Setup explicit query statement to fetch the record we want.     */
+/* -------------------------------------------------------------------- */
+    CPLString osSQL;
+    int rc;
+
+    ClearStatement();
+
+    iNextShapeId = nFeatureId;
+
+    osSQL.Printf( "SELECT %s, * FROM '%s' WHERE \"%s\" = %d",
+                  pszFIDColumn,
+                  pszEscapedTableName, 
+                  pszFIDColumn, (int) nFeatureId );
+
+    CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
+
+    rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(), 
+                          &hStmt, NULL );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "In GetFeature(): sqlite3_prepare(%s):\n  %s", 
+                  osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
+
+        return NULL;
+    }
+/* -------------------------------------------------------------------- */
+/*      Get the feature if possible.                                    */
+/* -------------------------------------------------------------------- */
+    OGRFeature *poFeature = NULL;
+
+    poFeature = GetNextRawFeature();
+
+    ResetReading();
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRSQLiteViewLayer::SetAttributeFilter( const char *pszQuery )
+
+{
+    if( pszQuery == NULL )
+        osQuery = "";
+    else
+        osQuery = pszQuery;
+
+    BuildWhere();
+
+    ResetReading();
+
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRSQLiteViewLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
+
+{
+    if( InstallFilter( poGeomIn ) )
+    {
+        BuildWhere();
+
+        ResetReading();
+    }
+}
+
+/************************************************************************/
+/*                             BuildWhere()                             */
+/*                                                                      */
+/*      Build the WHERE statement appropriate to the current set of     */
+/*      criteria (spatial and attribute queries).                       */
+/************************************************************************/
+
+void OGRSQLiteViewLayer::BuildWhere()
+
+{
+    osWHERE = "";
+
+    if( m_poFilterGeom != NULL && bHasSpatialIndex )
+    {
+        OGREnvelope  sEnvelope;
+
+        m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        /* We first check that the spatial index table exists */
+        if (!bHasCheckedSpatialIndexTable)
+        {
+            bHasCheckedSpatialIndexTable = TRUE;
+            char **papszResult;
+            int nRowCount, nColCount;
+            char *pszErrMsg = NULL;
+
+            CPLString osSQL;
+            osSQL.Printf("SELECT name FROM sqlite_master "
+                        "WHERE name='idx_%s_%s'",
+                        pszEscapedUnderlyingTableName, osUnderlyingGeometryColumn.c_str());
+
+            int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
+                                        &papszResult, &nRowCount,
+                                        &nColCount, &pszErrMsg );
+
+            if( rc != SQLITE_OK )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Error: %s",
+                        pszErrMsg );
+                sqlite3_free( pszErrMsg );
+                bHasSpatialIndex = FALSE;
+            }
+            else
+            {
+                if (nRowCount != 1)
+                {
+                    bHasSpatialIndex = FALSE;
+                }
+
+                sqlite3_free_table(papszResult);
+            }
+        }
+
+        if (bHasSpatialIndex)
+        {
+            osWHERE.Printf("WHERE %s IN ( SELECT pkid FROM 'idx_%s_%s' WHERE "
+                           "xmax > %.12f AND xmin < %.12f AND ymax > %.12f AND ymin < %.12f) ",
+                            pszFIDColumn,
+                            pszEscapedUnderlyingTableName, osUnderlyingGeometryColumn.c_str(),
+                            sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
+                            sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
+        }
+        else
+        {
+            CPLDebug("SQLITE", "Count not find idx_%s_%s layer. Disabling spatial index",
+                     pszEscapedUnderlyingTableName, osUnderlyingGeometryColumn.c_str());
+        }
+
+    }
+
+    if( m_poFilterGeom != NULL && bSpatialiteLoaded && !bHasSpatialIndex )
+    {
+        OGREnvelope  sEnvelope;
+
+        m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        /* A bit inefficient but still faster than OGR filtering */
+        osWHERE.Printf("WHERE MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f)) ",
+                       osGeomColumn.c_str(),
+                       sEnvelope.MinX - 1e-11, sEnvelope.MinY - 1e-11,
+                       sEnvelope.MaxX + 1e-11, sEnvelope.MaxY + 1e-11);
+    }
+
+    if( strlen(osQuery) > 0 )
+    {
+        if( strlen(osWHERE) == 0 )
+        {
+            osWHERE.Printf( "WHERE %s ", osQuery.c_str()  );
+        }
+        else	
+        {
+            osWHERE += "AND ";
+            osWHERE += osQuery;
+        }
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSQLiteViewLayer::TestCapability( const char * pszCap )
+
+{
+    if (EQUAL(pszCap,OLCFastFeatureCount))
+        return m_poFilterGeom == NULL || osGeomColumn.size() == 0 ||
+               bHasSpatialIndex;
+
+    else if (EQUAL(pszCap,OLCFastSpatialFilter))
+        return bHasSpatialIndex;
+
+    else 
+        return OGRSQLiteLayer::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 OGRSQLiteViewLayer::GetFeatureCount( int bForce )
+
+{
+    if( !TestCapability(OLCFastFeatureCount) )
+        return OGRSQLiteLayer::GetFeatureCount( bForce );
+
+/* -------------------------------------------------------------------- */
+/*      Form count SQL.                                                 */
+/* -------------------------------------------------------------------- */
+    const char *pszSQL;
+
+    pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
+                          pszEscapedTableName, osWHERE.c_str() );
+
+/* -------------------------------------------------------------------- */
+/*      Execute.                                                        */
+/* -------------------------------------------------------------------- */
+    char **papszResult, *pszErrMsg;
+    int nRowCount, nColCount;
+    int nResult = -1;
+
+    if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult, 
+                           &nColCount, &nRowCount, &pszErrMsg ) != SQLITE_OK )
+        return -1;
+
+    if( nRowCount == 1 && nColCount == 1 )
+        nResult = atoi(papszResult[1]);
+
+    sqlite3_free_table( papszResult );
+
+    return nResult;
+}
diff --git a/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp b/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
index a3153a4..cc4d433 100644
--- a/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsuadatasource.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrsuadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUADataSource class
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsuadatasource.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrsuadatasource.cpp 23042 2011-09-04 15:07:22Z rouault $");
 
 /************************************************************************/
 /*                          OGRSUADataSource()                          */
@@ -97,15 +97,6 @@ int OGRSUADataSource::Open( const char * pszFilename, int bUpdateIn)
 
     pszName = CPLStrdup( pszFilename );
 
-/* -------------------------------------------------------------------- */
-/*      Determine what sort of object this is.                          */
-/* -------------------------------------------------------------------- */
-    VSIStatBufL sStatBuf;
-
-    if( VSIStatL( pszFilename, &sStatBuf ) != 0 ||
-        !VSI_ISREG(sStatBuf.st_mode) )
-        return FALSE;
-    
 // -------------------------------------------------------------------- 
 //      Does this appear to be a .sua file?
 // --------------------------------------------------------------------
diff --git a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
index 91cbd32..63325ee 100644
--- a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsualayer.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrsualayer.cpp 23066 2011-09-05 21:10:19Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUALayer class.
@@ -34,7 +34,7 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsualayer.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrsualayer.cpp 23066 2011-09-05 21:10:19Z rouault $");
 
 /************************************************************************/
 /*                            OGRSUALayer()                             */
@@ -348,6 +348,7 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
     poFeature->SetField(4, osBASE.c_str());
 
     OGRPolygon* poPoly = new OGRPolygon();
+    poPoly->assignSpatialReference(poSRS);
     oLR.closeRings();
     poPoly->addRing(&oLR);
     poFeature->SetGeometryDirectly(poPoly);
diff --git a/ogr/ogrsf_frmts/svg/GNUmakefile b/ogr/ogrsf_frmts/svg/GNUmakefile
new file mode 100644
index 0000000..1c4ba60
--- /dev/null
+++ b/ogr/ogrsf_frmts/svg/GNUmakefile
@@ -0,0 +1,19 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrsvgdriver.o ogrsvgdatasource.o ogrsvglayer.o
+
+ifeq ($(HAVE_EXPAT),yes)
+CPPFLAGS +=   -DHAVE_EXPAT
+endif
+
+CPPFLAGS	:=	-I.. -I../.. $(GDAL_INCLUDE) $(EXPAT_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_svg.h
+
diff --git a/ogr/ogrsf_frmts/svg/drv_svg.html b/ogr/ogrsf_frmts/svg/drv_svg.html
new file mode 100644
index 0000000..b8c642a
--- /dev/null
+++ b/ogr/ogrsf_frmts/svg/drv_svg.html
@@ -0,0 +1,34 @@
+<html>
+<head>
+<title>SVG - Scalable Vector Graphics</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>SVG - Scalable Vector Graphics</h1>
+
+(OGR >= 1.9.0)<p>
+
+OGR has support for SVG reading (if GDAL is built with <i>expat</i> library support).<p>
+
+Currently, it will only read SVG files that are the output from Cloudmade Vector Stream Server <p>
+
+All coordinates are relative to the Pseudo-mercator SRS (EPSG:3857).<p>
+
+The driver will return 3 layers :
+<ul>
+<li>points</li>
+<li>lines</li>
+<li>polygons</li>
+</ul>
+<p>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="http://www.w3.org/TR/SVG/">W3C SVG page</a><p>
+<li> <a href="http://developers.cloudmade.com/wiki/vector-stream-server/Documentation">Cloudmade vector documentation</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/svg/makefile.vc b/ogr/ogrsf_frmts/svg/makefile.vc
new file mode 100644
index 0000000..26b101a
--- /dev/null
+++ b/ogr/ogrsf_frmts/svg/makefile.vc
@@ -0,0 +1,18 @@
+
+OBJ	=	ogrsvgdriver.obj ogrsvgdatasource.obj ogrsvglayer.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+!IFDEF EXPAT_DIR
+EXTRAFLAGS =	-I.. -I..\.. $(EXPAT_INCLUDE) -DHAVE_EXPAT=1 
+!ELSE
+EXTRAFLAGS =	-I.. -I..\..
+!ENDIF
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
diff --git a/ogr/ogrsf_frmts/svg/ogr_svg.h b/ogr/ogrsf_frmts/svg/ogr_svg.h
new file mode 100644
index 0000000..569c035
--- /dev/null
+++ b/ogr/ogrsf_frmts/svg/ogr_svg.h
@@ -0,0 +1,185 @@
+/******************************************************************************
+ * $Id: ogr_svg.h 22110 2011-04-03 19:05:10Z 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
+ *
+ * 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_SVG_H_INCLUDED
+#define _OGR_SVG_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+#ifdef HAVE_EXPAT
+#include "ogr_expat.h"
+#endif
+
+class OGRSVGDataSource;
+
+typedef enum
+{
+    SVG_POINTS,
+    SVG_LINES,
+    SVG_POLYGONS,
+} SVGGeometryType;
+
+/************************************************************************/
+/*                             OGRSVGLayer                              */
+/************************************************************************/
+
+class OGRSVGLayer : public OGRLayer
+{
+    OGRFeatureDefn*    poFeatureDefn;
+    OGRSpatialReference *poSRS;
+    OGRSVGDataSource*  poDS;
+    CPLString          osLayerName;
+    
+    SVGGeometryType    svgGeomType;
+
+    int                nTotalFeatures;
+    int                nNextFID;
+    VSILFILE*          fpSVG; /* Large file API */
+
+#ifdef HAVE_EXPAT
+    XML_Parser         oParser;
+    XML_Parser         oSchemaParser;
+#endif
+    char*              pszSubElementValue;
+    int                nSubElementValueLen;
+    int                iCurrentField;
+
+    OGRFeature*        poFeature;
+    OGRFeature **      ppoFeatureTab;
+    int                nFeatureTabLength;
+    int                nFeatureTabIndex;
+
+    int                depthLevel;
+    int                interestingDepthLevel;
+    int                inInterestingElement;
+
+    int                bStopParsing;
+    int                nWithoutEventCounter;
+    int                nDataHandlerCounter;
+
+    OGRSVGLayer       *poCurLayer;
+
+  private:
+    void               LoadSchema();
+
+  public:
+                        OGRSVGLayer(const char *pszFilename,
+                                    const char* layerName,
+                                    SVGGeometryType svgGeomType,
+                                    OGRSVGDataSource* poDS);
+                        ~OGRSVGLayer();
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual const char*         GetName() { return osLayerName.c_str(); }
+    virtual OGRwkbGeometryType  GetGeomType();
+
+    virtual int                 GetFeatureCount( int bForce = TRUE );
+
+    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);
+    void                dataHandlerCbk(const char *data, int nLen);
+    
+    void                startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr);
+    void                endElementLoadSchemaCbk(const char *pszName);
+    void                dataHandlerLoadSchemaCbk(const char *data, int nLen);
+#endif
+};
+
+/************************************************************************/
+/*                           OGRSVGDataSource                           */
+/************************************************************************/
+
+typedef enum
+{
+    SVG_VALIDITY_UNKNOWN,
+    SVG_VALIDITY_INVALID,
+    SVG_VALIDITY_VALID
+} OGRSVGValidity;
+
+class OGRSVGDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRSVGLayer**       papoLayers;
+    int                 nLayers;
+
+    OGRSVGValidity      eValidity;
+    int                 bIsCloudmade;
+
+#ifdef HAVE_EXPAT
+    XML_Parser          oCurrentParser;
+    int                 nDataHandlerCounter;
+#endif
+
+  public:
+                        OGRSVGDataSource();
+                        ~OGRSVGDataSource();
+
+    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 * );
+
+    
+#ifdef HAVE_EXPAT
+    void                startElementValidateCbk(const char *pszName, const char **ppszAttr);
+    void                dataHandlerValidateCbk(const char *data, int nLen);
+#endif
+};
+
+/************************************************************************/
+/*                             OGRSVGDriver                             */
+/************************************************************************/
+
+class OGRSVGDriver : public OGRSFDriver
+{
+  public:
+                ~OGRSVGDriver();
+
+    const char*         GetName();
+    OGRDataSource*      Open( const char *, int );
+
+    virtual int                 TestCapability( const char * );
+};
+
+#endif /* ndef _OGR_SVG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
new file mode 100644
index 0000000..d675d4f
--- /dev/null
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
@@ -0,0 +1,278 @@
+/******************************************************************************
+ * $Id: ogrsvgdatasource.cpp 23557 2011-12-12 22:08:17Z 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
+ *
+ * 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_svg.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrsvgdatasource.cpp 23557 2011-12-12 22:08:17Z rouault $");
+
+/************************************************************************/
+/*                          OGRSVGDataSource()                          */
+/************************************************************************/
+
+OGRSVGDataSource::OGRSVGDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    bIsCloudmade = FALSE;
+
+    pszName = NULL;
+}
+
+/************************************************************************/
+/*                         ~OGRSVGDataSource()                          */
+/************************************************************************/
+
+OGRSVGDataSource::~OGRSVGDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+    CPLFree( pszName );
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRSVGDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+#ifdef HAVE_EXPAT
+
+/************************************************************************/
+/*                startElementValidateCbk()                             */
+/************************************************************************/
+
+void OGRSVGDataSource::startElementValidateCbk(const char *pszName,
+                                               const char **ppszAttr)
+{
+    if (eValidity == SVG_VALIDITY_UNKNOWN)
+    {
+        if (strcmp(pszName, "svg") == 0)
+        {
+            int i;
+            eValidity = SVG_VALIDITY_VALID;
+            for(i=0; ppszAttr[i] != NULL; i+= 2)
+            {
+                if (strcmp(ppszAttr[i], "xmlns:cm") == 0 &&
+                    strcmp(ppszAttr[i+1], "http://cloudmade.com/") == 0)
+                {
+                    bIsCloudmade = TRUE;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            eValidity = SVG_VALIDITY_INVALID;
+        }
+    }
+}
+
+
+/************************************************************************/
+/*                      dataHandlerValidateCbk()                        */
+/************************************************************************/
+
+void OGRSVGDataSource::dataHandlerValidateCbk(const char *data, int nLen)
+{
+    nDataHandlerCounter ++;
+    if (nDataHandlerCounter >= BUFSIZ)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File probably corrupted (million laugh pattern)");
+        XML_StopParser(oCurrentParser, XML_FALSE);
+    }
+}
+
+
+static void XMLCALL startElementValidateCbk(void *pUserData,
+                                            const char *pszName, const char **ppszAttr)
+{
+    OGRSVGDataSource* poDS = (OGRSVGDataSource*) pUserData;
+    poDS->startElementValidateCbk(pszName, ppszAttr);
+}
+
+static void XMLCALL dataHandlerValidateCbk(void *pUserData, const char *data, int nLen)
+{
+    OGRSVGDataSource* poDS = (OGRSVGDataSource*) pUserData;
+    poDS->dataHandlerValidateCbk(data, nLen);
+}
+#endif
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRSVGDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (bUpdateIn)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "OGR/SVG driver does not support opening a file in update mode");
+        return FALSE;
+    }
+#ifdef HAVE_EXPAT
+    pszName = CPLStrdup( pszFilename );
+
+/* -------------------------------------------------------------------- */
+/*      Try to open the file.                                           */
+/* -------------------------------------------------------------------- */
+    CPLString osFilename(pszFilename);
+    if (EQUAL(CPLGetExtension(pszFilename), "svgz") &&
+        strstr(pszFilename, "/vsigzip/") == NULL)
+    {
+        osFilename = CPLString("/vsigzip/") + pszFilename;
+        pszFilename = osFilename.c_str();
+    }
+
+    VSILFILE* fp = VSIFOpenL(pszFilename, "r");
+    if (fp == NULL)
+        return FALSE;
+    
+    eValidity = SVG_VALIDITY_UNKNOWN;
+
+    XML_Parser oParser = OGRCreateExpatXMLParser();
+    oCurrentParser = oParser;
+    XML_SetUserData(oParser, this);
+    XML_SetElementHandler(oParser, ::startElementValidateCbk, NULL);
+    XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
+    
+    char aBuf[BUFSIZ];
+    int nDone;
+    unsigned int nLen;
+    int nCount = 0;
+    
+    /* Begin to parse the file and look for the <svg> element */
+    /* It *MUST* be the first element of an XML file */
+    /* So once we have read the first element, we know if we can */
+    /* handle the file or not with that driver */
+    do
+    {
+        nDataHandlerCounter = 0;
+        nLen = (unsigned int) VSIFReadL( aBuf, 1, sizeof(aBuf), fp );
+        nDone = VSIFEofL(fp);
+        if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
+        {
+            if (nLen <= BUFSIZ-1)
+                aBuf[nLen] = 0;
+            else
+                aBuf[BUFSIZ-1] = 0;
+            if (strstr(aBuf, "<?xml") && strstr(aBuf, "<svg"))
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "XML parsing of SVG file failed : %s at line %d, column %d",
+                        XML_ErrorString(XML_GetErrorCode(oParser)),
+                        (int)XML_GetCurrentLineNumber(oParser),
+                        (int)XML_GetCurrentColumnNumber(oParser));
+            }
+            eValidity = SVG_VALIDITY_INVALID;
+            break;
+        }
+        if (eValidity == SVG_VALIDITY_INVALID)
+        {
+            break;
+        }
+        else if (eValidity == SVG_VALIDITY_VALID)
+        {
+            break;
+        }
+        else
+        {
+            /* After reading 50 * BUFSIZE bytes, and not finding whether the file */
+            /* is SVG or not, we give up and fail silently */
+            nCount ++;
+            if (nCount == 50)
+                break;
+        }
+    } while (!nDone && nLen > 0 );
+
+    XML_ParserFree(oParser);
+
+    VSIFCloseL(fp);
+
+    if (eValidity == SVG_VALIDITY_VALID)
+    {
+        if (bIsCloudmade)
+        {
+            nLayers = 3;
+            papoLayers =(OGRSVGLayer **) CPLRealloc(papoLayers,
+                                            nLayers * sizeof(OGRSVGLayer*));
+            papoLayers[0] = new OGRSVGLayer( pszFilename, "points", SVG_POINTS, this );
+            papoLayers[1] = new OGRSVGLayer( pszFilename, "lines", SVG_LINES, this );
+            papoLayers[2] = new OGRSVGLayer( pszFilename, "polygons", SVG_POLYGONS, this );
+        }
+        else
+        {
+            CPLDebug("SVG",
+                     "%s seems to be a SVG file, but not a Cloudmade vector one.",
+                     pszFilename);
+        }
+    }
+
+    return (nLayers > 0);
+#else
+    char aBuf[256];
+    VSILFILE* fp = VSIFOpenL(pszFilename, "r");
+    if (fp)
+    {
+        unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, 255, fp );
+        aBuf[nLen] = 0;
+        if (strstr(aBuf, "<?xml") && strstr(aBuf, "<svg") &&
+            strstr(aBuf, "http://cloudmade.com/"))
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                    "OGR/SVG driver has not been built with read support. "
+                    "Expat library required");
+        }
+        VSIFCloseL(fp);
+    }
+    return FALSE;
+#endif
+}
+
+/************************************************************************/
+/*                            TestCapability()                          */
+/************************************************************************/
+
+int OGRSVGDataSource::TestCapability( const char *pszCap )
+{
+    return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
new file mode 100644
index 0000000..7f62b43
--- /dev/null
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * $Id: ogrsvgdriver.cpp 22110 2011-04-03 19:05:10Z rouault $
+ *
+ * Project:  SVG Translator
+ * Purpose:  Implements OGRSVGDriver.
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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 "ogr_svg.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrsvgdriver.cpp 22110 2011-04-03 19:05:10Z rouault $");
+
+CPL_C_START
+void RegisterOGRSVG();
+CPL_C_END
+
+// g++ -g -Wall -fPIC ogr/ogrsf_frmts/svg/*.c* -shared -o ogr_SVG.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/svg -L. -lgdal -DHAVE_EXPAT
+
+/************************************************************************/
+/*                           ~OGRSVGDriver()                            */
+/************************************************************************/
+
+OGRSVGDriver::~OGRSVGDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRSVGDriver::GetName()
+
+{
+    return "SVG";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRSVGDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    if (bUpdate)
+    {
+        return NULL;
+    }
+
+    OGRSVGDataSource   *poDS = new OGRSVGDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                            TestCapability()                          */
+/************************************************************************/
+
+int OGRSVGDriver::TestCapability( const char *pszCap )
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRSVG()                           */
+/************************************************************************/
+
+void RegisterOGRSVG()
+
+{
+    if (! GDAL_CHECK_VERSION("OGR/SVG driver"))
+        return;
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRSVGDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
new file mode 100644
index 0000000..4c5f663
--- /dev/null
+++ b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
@@ -0,0 +1,851 @@
+/******************************************************************************
+ * $Id: ogrsvglayer.cpp 22111 2011-04-03 19:28:18Z 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
+ *
+ * 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_svg.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrsvglayer.cpp 22111 2011-04-03 19:28:18Z rouault $");
+
+/************************************************************************/
+/*                            OGRSVGLayer()                             */
+/************************************************************************/
+
+OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
+                          const char* pszLayerName,
+                          SVGGeometryType svgGeomType,
+                          OGRSVGDataSource* poDS)
+
+{
+    nNextFID = 0;
+
+    this->poDS = poDS;
+    this->svgGeomType = svgGeomType;
+    osLayerName = pszLayerName;
+
+    poFeatureDefn = NULL;
+
+    nTotalFeatures = 0;
+
+    ppoFeatureTab = NULL;
+    nFeatureTabIndex = 0;
+    nFeatureTabLength = 0;
+    pszSubElementValue = NULL;
+    nSubElementValueLen = 0;
+    bStopParsing = FALSE;
+
+    poSRS = new OGRSpatialReference("PROJCS[\"WGS 84 / Pseudo-Mercator\","
+    "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\"]],"
+    "UNIT[\"metre\",1,"
+    "    AUTHORITY[\"EPSG\",\"9001\"]],"
+    "PROJECTION[\"Mercator_1SP\"],"
+    "PARAMETER[\"central_meridian\",0],"
+    "PARAMETER[\"scale_factor\",1],"
+    "PARAMETER[\"false_easting\",0],"
+    "PARAMETER[\"false_northing\",0],"
+    "EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs\"],"
+    "AUTHORITY[\"EPSG\",\"3857\"],"
+    "AXIS[\"X\",EAST],"
+    "AXIS[\"Y\",NORTH]]");
+
+    poFeature = NULL;
+
+#ifdef HAVE_EXPAT
+    oParser = NULL;
+#endif
+
+    fpSVG = VSIFOpenL( pszFilename, "r" );
+    if( fpSVG == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszFilename);
+        return;
+    }
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                            ~OGRSVGLayer()                            */
+/************************************************************************/
+
+OGRSVGLayer::~OGRSVGLayer()
+
+{
+#ifdef HAVE_EXPAT
+    if (oParser)
+        XML_ParserFree(oParser);
+#endif
+    if (poFeatureDefn)
+        poFeatureDefn->Release();
+    
+    if( poSRS != NULL )
+        poSRS->Release();
+
+    CPLFree(pszSubElementValue);
+
+    int i;
+    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+        delete ppoFeatureTab[i];
+    CPLFree(ppoFeatureTab);
+
+    if (poFeature)
+        delete poFeature;
+
+    if (fpSVG)
+        VSIFCloseL( fpSVG );
+}
+
+#ifdef HAVE_EXPAT
+
+static void XMLCALL startElementCbk(void *pUserData,
+                                    const char *pszName, const char **ppszAttr)
+{
+    ((OGRSVGLayer*)pUserData)->startElementCbk(pszName, ppszAttr);
+}
+
+static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
+{
+    ((OGRSVGLayer*)pUserData)->endElementCbk(pszName);
+}
+
+static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
+{
+    ((OGRSVGLayer*)pUserData)->dataHandlerCbk(data, nLen);
+}
+
+#endif
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRSVGLayer::ResetReading()
+
+{
+    nNextFID = 0;
+    if (fpSVG)
+    {
+        VSIFSeekL( fpSVG, 0, SEEK_SET );
+#ifdef HAVE_EXPAT
+        if (oParser)
+            XML_ParserFree(oParser);
+
+        oParser = OGRCreateExpatXMLParser();
+        XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
+        XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
+        XML_SetUserData(oParser, this);
+#endif
+    }
+
+    CPLFree(pszSubElementValue);
+    pszSubElementValue = NULL;
+    nSubElementValueLen = 0;
+    iCurrentField = -1;
+
+    int i;
+    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+        delete ppoFeatureTab[i];
+    CPLFree(ppoFeatureTab);
+    nFeatureTabIndex = 0;
+    nFeatureTabLength = 0;
+    ppoFeatureTab = NULL;
+    if (poFeature)
+        delete poFeature;
+    poFeature = NULL;
+
+    depthLevel = 0;
+    interestingDepthLevel = 0;
+    inInterestingElement = FALSE;
+}
+
+#ifdef HAVE_EXPAT
+
+/************************************************************************/
+/*                         OGRSVGGetClass()                             */
+/************************************************************************/
+
+static const char* OGRSVGGetClass(const char **ppszAttr)
+{
+    const char** ppszIter = ppszAttr;
+    while(*ppszIter)
+    {
+        if (strcmp(ppszIter[0], "class") == 0)
+            return ppszIter[1];
+        ppszIter += 2;
+    }
+    return "";
+}
+
+/************************************************************************/
+/*                          OGRSVGParseD()                              */
+/************************************************************************/
+
+static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
+{
+    char szBuffer[32];
+    int iBuffer = 0;
+    const char* pszIter = pszD;
+    char ch;
+    int iNumber = 0;
+    double dfPrevNumber = 0;
+    int bRelativeLineto = FALSE;
+    double dfX = 0, dfY = 0;
+    int nPointCount = 0;
+    while(TRUE)
+    {
+        ch = *(pszIter ++);
+
+        if (ch == 'M' || ch == 'm')
+        {
+            if (nPointCount != 0)
+            {
+                CPLDebug("SVG", "Not ready to handle M/m not at the beginning");
+                return;
+            }
+        }
+        else if (ch == 'L')
+        {
+            bRelativeLineto = FALSE;
+        }
+        else if (ch == 'l')
+        {
+            if (nPointCount == 0)
+            {
+                CPLDebug("SVG", "Relative lineto at the beginning of the line");
+                return;
+            }
+            bRelativeLineto = TRUE;
+        }
+        else if (ch == 'z' || ch == 'Z')
+        {
+            poLS->closeRings();
+            return;
+        }
+        else if (ch == '+' || ch == '-' || ch == '.' ||
+                 (ch >= '0' && ch <= '9'))
+        {
+            if (iBuffer == 30)
+            {
+                CPLDebug("SVG", "Too big number");
+                return;
+            }
+            szBuffer[iBuffer ++] = ch;
+        }
+        else if (ch == ' ' || ch == 0)
+        {
+            if (iBuffer > 0)
+            {
+                szBuffer[iBuffer] = 0;
+                if (iNumber == 1)
+                {
+                    /* Cloudmade --> negate y */
+                    double dfNumber = -CPLAtof(szBuffer);
+
+                    if (bRelativeLineto)
+                    {
+                        dfX += dfPrevNumber;
+                        dfY += dfNumber;
+                    }
+                    else
+                    {
+                        dfX = dfPrevNumber;
+                        dfY = dfNumber;
+                    }
+                    poLS->addPoint(dfX, dfY);
+                    nPointCount ++;
+
+                    iNumber = 0;
+                }
+                else
+                {
+                    iNumber = 1;
+                    dfPrevNumber = CPLAtof(szBuffer);
+                }
+
+                iBuffer = 0;
+            }
+            if (ch == 0)
+                break;
+        }
+    }
+}
+
+/************************************************************************/
+/*                        startElementCbk()                            */
+/************************************************************************/
+
+void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
+{
+    int i;
+
+    if (bStopParsing) return;
+
+    nWithoutEventCounter = 0;
+
+    if (svgGeomType == SVG_POINTS &&
+        strcmp(pszName, "circle") == 0 &&
+        strcmp(OGRSVGGetClass(ppszAttr), "point") == 0)
+    {
+        int bHasFoundX = FALSE, bHasFoundY = FALSE;
+        double dfX = 0, dfY = 0;
+        for (i = 0; ppszAttr[i]; i += 2)
+        {
+            if (strcmp(ppszAttr[i], "cx") == 0)
+            {
+                bHasFoundX = TRUE;
+                dfX = CPLAtof(ppszAttr[i + 1]);
+            }
+            else if (strcmp(ppszAttr[i], "cy") == 0)
+            {
+                bHasFoundY = TRUE;
+                /* Cloudmade --> negate y */
+                dfY = - CPLAtof(ppszAttr[i + 1]);
+            }
+        }
+        if (bHasFoundX && bHasFoundY)
+        {
+            interestingDepthLevel = depthLevel;
+            inInterestingElement = TRUE;
+
+            if (poFeature)
+                delete poFeature;
+
+            poFeature = new OGRFeature( poFeatureDefn );
+
+            poFeature->SetFID( nNextFID++ );
+            OGRPoint* poPoint = new OGRPoint( dfX, dfY );
+            poPoint->assignSpatialReference(poSRS);
+            poFeature->SetGeometryDirectly( poPoint );
+        }
+    }
+    else if (svgGeomType == SVG_LINES &&
+             strcmp(pszName, "path") == 0 &&
+             strcmp(OGRSVGGetClass(ppszAttr), "line") == 0)
+    {
+        const char* pszD = NULL;
+        for (i = 0; ppszAttr[i]; i += 2)
+        {
+            if (strcmp(ppszAttr[i], "d") == 0)
+            {
+                pszD = ppszAttr[i + 1];
+                break;
+            }
+        }
+        if (pszD)
+        {
+            interestingDepthLevel = depthLevel;
+            inInterestingElement = TRUE;
+
+            if (poFeature)
+                delete poFeature;
+
+            poFeature = new OGRFeature( poFeatureDefn );
+
+            poFeature->SetFID( nNextFID++ );
+            OGRLineString* poLS = new OGRLineString();
+            OGRSVGParseD(poLS, pszD);
+            poLS->assignSpatialReference(poSRS);
+            poFeature->SetGeometryDirectly( poLS );
+        }
+    }
+    else if (svgGeomType == SVG_POLYGONS &&
+             strcmp(pszName, "path") == 0 &&
+             strcmp(OGRSVGGetClass(ppszAttr), "polygon") == 0)
+    {
+        const char* pszD = NULL;
+        for (i = 0; ppszAttr[i]; i += 2)
+        {
+            if (strcmp(ppszAttr[i], "d") == 0)
+            {
+                pszD = ppszAttr[i + 1];
+                break;
+            }
+        }
+        if (pszD)
+        {
+            interestingDepthLevel = depthLevel;
+            inInterestingElement = TRUE;
+
+            if (poFeature)
+                delete poFeature;
+
+            poFeature = new OGRFeature( poFeatureDefn );
+
+            poFeature->SetFID( nNextFID++ );
+            OGRPolygon* poPolygon = new OGRPolygon();
+            OGRLinearRing* poLS = new OGRLinearRing();
+            OGRSVGParseD(poLS, pszD);
+            poPolygon->addRingDirectly(poLS);
+            poPolygon->assignSpatialReference(poSRS);
+            poFeature->SetGeometryDirectly( poPolygon );
+        }
+    }
+    else if (inInterestingElement &&
+             depthLevel == interestingDepthLevel + 1 &&
+             strncmp(pszName, "cm:", 3) == 0)
+    {
+        iCurrentField = poFeatureDefn->GetFieldIndex(pszName + 3);
+    }
+
+    depthLevel++;
+}
+
+/************************************************************************/
+/*                           endElementCbk()                            */
+/************************************************************************/
+
+void OGRSVGLayer::endElementCbk(const char *pszName)
+{
+    if (bStopParsing) return;
+
+    nWithoutEventCounter = 0;
+
+    depthLevel--;
+
+    if (inInterestingElement)
+    {
+        if (depthLevel == interestingDepthLevel)
+        {
+            inInterestingElement = FALSE;
+
+            if( (m_poFilterGeom == NULL
+                    || FilterGeometry( poFeature->GetGeometryRef() ) )
+                && (m_poAttrQuery == NULL
+                    || m_poAttrQuery->Evaluate( poFeature )) )
+            {
+                ppoFeatureTab = (OGRFeature**)
+                        CPLRealloc(ppoFeatureTab,
+                                    sizeof(OGRFeature*) * (nFeatureTabLength + 1));
+                ppoFeatureTab[nFeatureTabLength] = poFeature;
+                nFeatureTabLength++;
+            }
+            else
+            {
+                delete poFeature;
+            }
+            poFeature = NULL;
+        }
+        else if (depthLevel == interestingDepthLevel + 1)
+        {
+            if (poFeature && iCurrentField >= 0 && nSubElementValueLen)
+            {
+                pszSubElementValue[nSubElementValueLen] = 0;
+                poFeature->SetField( iCurrentField, pszSubElementValue);
+            }
+
+            CPLFree(pszSubElementValue);
+            pszSubElementValue = NULL;
+            nSubElementValueLen = 0;
+            iCurrentField = -1;
+        }
+    }
+}
+
+/************************************************************************/
+/*                          dataHandlerCbk()                            */
+/************************************************************************/
+
+void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
+{
+    if (bStopParsing) return;
+
+    nDataHandlerCounter ++;
+    if (nDataHandlerCounter >= BUFSIZ)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File probably corrupted (million laugh pattern)");
+        XML_StopParser(oParser, XML_FALSE);
+        bStopParsing = TRUE;
+        return;
+    }
+
+    nWithoutEventCounter = 0;
+
+    if (iCurrentField >= 0)
+    {
+        char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue,
+                                           nSubElementValueLen + nLen + 1);
+        if (pszNewSubElementValue == NULL)
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+            XML_StopParser(oParser, XML_FALSE);
+            bStopParsing = TRUE;
+            return;
+        }
+        pszSubElementValue = pszNewSubElementValue;
+        memcpy(pszSubElementValue + nSubElementValueLen, data, nLen);
+        nSubElementValueLen += nLen;
+        if (nSubElementValueLen > 100000)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Too much data inside one element. File probably corrupted");
+            XML_StopParser(oParser, XML_FALSE);
+            bStopParsing = TRUE;
+        }
+    }
+}
+#endif
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRSVGLayer::GetNextFeature()
+{
+    GetLayerDefn();
+
+    if (fpSVG == NULL)
+        return NULL;
+
+    if (bStopParsing)
+        return NULL;
+
+#ifdef HAVE_EXPAT
+    if (nFeatureTabIndex < nFeatureTabLength)
+    {
+        return ppoFeatureTab[nFeatureTabIndex++];
+    }
+    
+    if (VSIFEofL(fpSVG))
+        return NULL;
+    
+    char aBuf[BUFSIZ];
+    
+    CPLFree(ppoFeatureTab);
+    ppoFeatureTab = NULL;
+    nFeatureTabLength = 0;
+    nFeatureTabIndex = 0;
+    nWithoutEventCounter = 0;
+    iCurrentField = -1;
+
+    int nDone;
+    do
+    {
+        nDataHandlerCounter = 0;
+        unsigned int nLen = (unsigned int)
+                    VSIFReadL( aBuf, 1, sizeof(aBuf), fpSVG );
+        nDone = VSIFEofL(fpSVG);
+        if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "XML parsing of SVG file failed : %s at line %d, column %d",
+                     XML_ErrorString(XML_GetErrorCode(oParser)),
+                     (int)XML_GetCurrentLineNumber(oParser),
+                     (int)XML_GetCurrentColumnNumber(oParser));
+            bStopParsing = TRUE;
+            break;
+        }
+        nWithoutEventCounter ++;
+    } while (!nDone && nFeatureTabLength == 0 && !bStopParsing &&
+             nWithoutEventCounter < 1000);
+
+    if (nWithoutEventCounter == 1000)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Too much data inside one element. File probably corrupted");
+        bStopParsing = TRUE;
+    }
+
+    return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
+#else
+    return NULL;
+#endif
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+
+OGRSpatialReference *OGRSVGLayer::GetSpatialRef()
+
+{
+    return poSRS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRSVGLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
+        return m_poAttrQuery == NULL && m_poFilterGeom == NULL &&
+               nTotalFeatures > 0;
+
+    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+
+    else
+        return FALSE;
+}
+
+
+/************************************************************************/
+/*                       LoadSchema()                         */
+/************************************************************************/
+
+#ifdef HAVE_EXPAT
+
+static void XMLCALL startElementLoadSchemaCbk(void *pUserData,
+                                              const char *pszName,
+                                              const char **ppszAttr)
+{
+    ((OGRSVGLayer*)pUserData)->startElementLoadSchemaCbk(pszName, ppszAttr);
+}
+
+static void XMLCALL endElementLoadSchemaCbk(void *pUserData, const char *pszName)
+{
+    ((OGRSVGLayer*)pUserData)->endElementLoadSchemaCbk(pszName);
+}
+
+static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData,
+                                             const char *data, int nLen)
+{
+    ((OGRSVGLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
+}
+
+
+/** This function parses the whole file to build the schema */
+void OGRSVGLayer::LoadSchema()
+{
+    CPLAssert(poFeatureDefn == NULL);
+
+    for(int i=0;i<poDS->GetLayerCount();i++)
+    {
+        OGRSVGLayer* poLayer = (OGRSVGLayer*)poDS->GetLayer(i);
+        poLayer->poFeatureDefn = new OGRFeatureDefn( poLayer->osLayerName );
+        poLayer->poFeatureDefn->Reference();
+        poLayer->poFeatureDefn->SetGeomType(poLayer->GetGeomType());
+    }
+
+    oSchemaParser = OGRCreateExpatXMLParser();
+    XML_SetElementHandler(oSchemaParser, ::startElementLoadSchemaCbk,
+                                         ::endElementLoadSchemaCbk);
+    XML_SetCharacterDataHandler(oSchemaParser, ::dataHandlerLoadSchemaCbk);
+    XML_SetUserData(oSchemaParser, this);
+
+    if (fpSVG == NULL)
+        return;
+
+    VSIFSeekL( fpSVG, 0, SEEK_SET );
+
+    inInterestingElement = FALSE;
+    depthLevel = 0;
+    nWithoutEventCounter = 0;
+    bStopParsing = FALSE;
+
+    char aBuf[BUFSIZ];
+    int nDone;
+    do
+    {
+        nDataHandlerCounter = 0;
+        unsigned int nLen =
+            (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpSVG );
+        nDone = VSIFEofL(fpSVG);
+        if (XML_Parse(oSchemaParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "XML parsing of SVG file failed : %s at line %d, column %d",
+                     XML_ErrorString(XML_GetErrorCode(oSchemaParser)),
+                     (int)XML_GetCurrentLineNumber(oSchemaParser),
+                     (int)XML_GetCurrentColumnNumber(oSchemaParser));
+            bStopParsing = TRUE;
+            break;
+        }
+        nWithoutEventCounter ++;
+    } while (!nDone && !bStopParsing && nWithoutEventCounter < 1000);
+
+    if (nWithoutEventCounter == 1000)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Too much data inside one element. File probably corrupted");
+        bStopParsing = TRUE;
+    }
+
+    XML_ParserFree(oSchemaParser);
+    oSchemaParser = NULL;
+
+    VSIFSeekL( fpSVG, 0, SEEK_SET );
+}
+
+
+/************************************************************************/
+/*                  startElementLoadSchemaCbk()                         */
+/************************************************************************/
+
+void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
+                                            const char **ppszAttr)
+{
+    if (bStopParsing) return;
+
+    nWithoutEventCounter = 0;
+
+    if (strcmp(pszName, "circle") == 0 &&
+        strcmp(OGRSVGGetClass(ppszAttr), "point") == 0)
+    {
+        poCurLayer = (OGRSVGLayer*)poDS->GetLayer(0);
+        poCurLayer->nTotalFeatures ++;
+        inInterestingElement = TRUE;
+        interestingDepthLevel = depthLevel;
+    }
+    else if (strcmp(pszName, "path") == 0 &&
+             strcmp(OGRSVGGetClass(ppszAttr), "line") == 0)
+    {
+        poCurLayer = (OGRSVGLayer*)poDS->GetLayer(1);
+        poCurLayer->nTotalFeatures ++;
+        inInterestingElement = TRUE;
+        interestingDepthLevel = depthLevel;
+    }
+    else if (strcmp(pszName, "path") == 0 &&
+             strcmp(OGRSVGGetClass(ppszAttr), "polygon") == 0)
+    {
+        poCurLayer = (OGRSVGLayer*)poDS->GetLayer(2);
+        poCurLayer->nTotalFeatures ++;
+        inInterestingElement = TRUE;
+        interestingDepthLevel = depthLevel;
+    }
+    else if (inInterestingElement)
+    {
+        if (depthLevel == interestingDepthLevel + 1 &&
+            strncmp(pszName, "cm:", 3) == 0)
+        {
+            pszName += 3;
+            if (poCurLayer->poFeatureDefn->GetFieldIndex(pszName) < 0)
+            {
+                OGRFieldDefn oFieldDefn(pszName, OFTString);
+                if (strcmp(pszName, "timestamp") == 0)
+                    oFieldDefn.SetType(OFTDateTime);
+                else if (strcmp(pszName, "way_area") == 0 ||
+                         strcmp(pszName, "area") == 0)
+                    oFieldDefn.SetType(OFTReal);
+                else if (strcmp(pszName, "z_order") == 0)
+                    oFieldDefn.SetType(OFTInteger);
+                poCurLayer->poFeatureDefn->AddFieldDefn(&oFieldDefn);
+            }
+        }
+    }
+
+    depthLevel++;
+}
+
+/************************************************************************/
+/*                   endElementLoadSchemaCbk()                           */
+/************************************************************************/
+
+void OGRSVGLayer::endElementLoadSchemaCbk(const char *pszName)
+{
+    if (bStopParsing) return;
+
+    nWithoutEventCounter = 0;
+
+    depthLevel--;
+
+    if (inInterestingElement &&
+        depthLevel == interestingDepthLevel)
+    {
+        inInterestingElement = FALSE;
+    }
+}
+
+/************************************************************************/
+/*                   dataHandlerLoadSchemaCbk()                         */
+/************************************************************************/
+
+void OGRSVGLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
+{
+    if (bStopParsing) return;
+
+    nDataHandlerCounter ++;
+    if (nDataHandlerCounter >= BUFSIZ)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File probably corrupted (million laugh pattern)");
+        XML_StopParser(oSchemaParser, XML_FALSE);
+        bStopParsing = TRUE;
+        return;
+    }
+
+    nWithoutEventCounter = 0;
+}
+#else
+void OGRSVGLayer::LoadSchema()
+{
+}
+#endif
+
+/************************************************************************/
+/*                          GetLayerDefn()                              */
+/************************************************************************/
+
+OGRFeatureDefn * OGRSVGLayer::GetLayerDefn()
+{
+    if (poFeatureDefn == NULL)
+    {
+        LoadSchema();
+    }
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                           GetGeomType()                              */
+/************************************************************************/
+
+OGRwkbGeometryType OGRSVGLayer::GetGeomType()
+{
+    if (svgGeomType == SVG_POINTS)
+        return wkbPoint;
+    else if (svgGeomType == SVG_LINES)
+        return wkbLineString;
+    else
+        return wkbPolygon;
+}
+
+/************************************************************************/
+/*                           GetGeomType()                              */
+/************************************************************************/
+
+int OGRSVGLayer::GetFeatureCount( int bForce )
+{
+    if (m_poAttrQuery != NULL || m_poFilterGeom != NULL)
+        return OGRLayer::GetFeatureCount(bForce);
+
+    GetLayerDefn();
+
+    return nTotalFeatures;
+}
diff --git a/ogr/ogrsf_frmts/tiger/ogr_tiger.h b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
index b5c7ab9..fbf0685 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 17224 2009-06-07 20:20:23Z rouault $
+ * $Id: ogr_tiger.h 23423 2011-11-26 18:40:30Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Main declarations for Tiger translator.
@@ -90,23 +90,23 @@ const char * TigerVersionString( TigerVersion );
 /*****************************************************************************/
 
 typedef struct TigerFieldInfo {
-  const char    *pszFieldName;  // name of the field
+  char          pszFieldName[11];  // name of the field
   char          cFmt;           // format of the field ('L' or 'R')
   char          cType;          // type of the field ('A' or 'N')
-  OGRFieldType  OGRtype;        // OFTType of the field (OFTInteger, OFTString, ...?)
-  int           nBeg;           // beginning column number for field
-  int           nEnd;           // ending column number for field
-  int           nLen;           // length of field
-
-  int           bDefine;        // whether to add this field to the FeatureDefn
-  int           bSet;           // whether to set this field in GetFeature()
-  int           bWrite;         // whether to write this field in CreateFeature()
+  char          OGRtype;        // OFTType of the field (OFTInteger, OFTString, ...?)
+  unsigned char nBeg;           // beginning column number for field
+  unsigned char nEnd;           // ending column number for field
+  unsigned char nLen;           // length of field
+
+  int           bDefine:1;        // whether to add this field to the FeatureDefn
+  int           bSet:1;           // whether to set this field in GetFeature()
+  int           bWrite:1;         // whether to write this field in CreateFeature()
 } TigerFieldInfo;
 
 typedef struct TigerRecordInfo {
-  TigerFieldInfo *pasFields;
-  int             nFieldCount;
-  int             nRecordLength;
+  const TigerFieldInfo *pasFields;
+  unsigned char        nFieldCount;
+  unsigned char        nRecordLength;
 } TigerRecordInfo;
 
 // OGR_TIGER_RECBUF_LEN should be a number that is larger than the
@@ -150,7 +150,8 @@ protected:
   TigerVersion        nVersion;
 
 public:
-                      TigerFileBase();
+                      TigerFileBase( const TigerRecordInfo *psRTInfoIn = NULL,
+                                     const char            *m_pszFileCodeIn = NULL );
   virtual            ~TigerFileBase();
 
   TigerVersion        GetVersion() { return nVersion; }
@@ -158,18 +159,13 @@ public:
 
   virtual const char *GetShortModule() { return pszShortModule; }
   virtual const char *GetModule() { return pszModule; }
-  virtual int         SetModule( const char * ) = 0;
   virtual int         SetWriteModule( const char *, int, OGRFeature * );
 
   virtual int         GetFeatureCount() { return nFeatures; }
-  virtual OGRFeature *GetFeature( int ) = 0;
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature )
-                                { return OGRERR_FAILURE; }
 
   OGRFeatureDefn     *GetFeatureDefn() { return poFeatureDefn; }
 
-  static CPLString    GetField( const char *, int, int );
+  static const char*  GetField( const char *, int, int );
   static void         SetField( OGRFeature *, const char *, const char *,
                                 int, int );
 
@@ -180,19 +176,26 @@ public:
   int                 WritePoint( char *pachRecord, int nStart,
                                   double dfX, double dfY );
 
+  virtual int         SetModule( const char * pszModule );
+  virtual OGRFeature *GetFeature( int nRecordId );
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+
  protected:
-  void                WriteFields(TigerRecordInfo *psRTInfo,
+  void                WriteFields(const TigerRecordInfo *psRTInfo,
                                   OGRFeature      *poFeature,
                                   char            *szRecord);
 
-  void                AddFieldDefns(TigerRecordInfo *psRTInfo,
+  void                AddFieldDefns(const TigerRecordInfo *psRTInfo,
                                     OGRFeatureDefn  *poFeatureDefn);
 
 
-  void                SetFields(TigerRecordInfo *psRTInfo,
+  void                SetFields(const TigerRecordInfo *psRTInfo,
                                 OGRFeature      *poFeature,
                                 char            *achRecord);
 
+
+  const TigerRecordInfo *psRTInfo;
+  const char            *m_pszFileCode;
 };
 
 /************************************************************************/
@@ -219,9 +222,9 @@ class TigerCompleteChain : public TigerFileBase
   OGRFeature         *GetFeature2002( int );
   void                AddFieldDefns2002();
 
-  TigerRecordInfo    *psRT1Info;
-  TigerRecordInfo    *psRT2Info;
-  TigerRecordInfo    *psRT3Info;
+  const TigerRecordInfo    *psRT1Info;
+  const TigerRecordInfo    *psRT2Info;
+  const TigerRecordInfo    *psRT3Info;
 
 public:
                       TigerCompleteChain( OGRTigerDataSource *,
@@ -243,15 +246,9 @@ public:
 
 class TigerAltName : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRT4Info;
-
  public:
                       TigerAltName( OGRTigerDataSource *,
                                           const char * );
-  virtual            ~TigerAltName();
-
-  virtual int         SetModule( const char * );
 
   virtual OGRFeature *GetFeature( int );
 
@@ -264,19 +261,9 @@ class TigerAltName : public TigerFileBase
 
 class TigerFeatureIds : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRT5Info;
-
  public:
                       TigerFeatureIds( OGRTigerDataSource *,
                                        const char * );
-  virtual            ~TigerFeatureIds();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -285,18 +272,8 @@ class TigerFeatureIds : public TigerFileBase
 
 class TigerZipCodes : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRT6Info;
-
 public:
                       TigerZipCodes( OGRTigerDataSource *, const char * );
-  virtual            ~TigerZipCodes();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -310,7 +287,9 @@ public:
 class TigerPoint : public TigerFileBase
 {
  protected:
-                      TigerPoint(int bRequireGeom);
+                      TigerPoint(int bRequireGeom,
+                                 const TigerRecordInfo *psRTInfoIn = NULL,
+                                 const char            *m_pszFileCodeIn = NULL);
 
                       // The boolean bRequireGeom indicates whether
                       // the layer requires each feature to actual
@@ -318,25 +297,19 @@ class TigerPoint : public TigerFileBase
                       // decide whether to report an error when a
                       // missing geom is detected.
 
-  virtual             ~TigerPoint();
-
  private:
  int                  bRequireGeom;
 
  public:
-  virtual int         SetModule( const char *,
-                                 const char *pszFileCode );
-
-  virtual OGRFeature *GetFeature( int              nRecordId,
-                                  TigerRecordInfo *psRTInfo,
+  virtual OGRFeature *GetFeature( int nFID) { return TigerFileBase::GetFeature(nFID); } /* to avoid -Woverloaded-virtual warnings */
+  OGRFeature *GetFeature( int              nRecordId,
                                   int nX0, int nX1,
                                   int nY0, int nY1 );
 
 
-  virtual OGRErr CreateFeature( OGRFeature      *poFeature,
-                                TigerRecordInfo *psRTInfo,
-                                int nIndex,
-                                const char *pszFileCode );
+  virtual OGRErr CreateFeature( OGRFeature      *poFeature) { return TigerFileBase::CreateFeature(poFeature); } /* to avoid -Woverloaded-virtual warnings */
+  OGRErr CreateFeature( OGRFeature      *poFeature,
+                                int nIndex );
 
 };
 
@@ -346,14 +319,8 @@ class TigerPoint : public TigerFileBase
 
 class TigerLandmarks : public TigerPoint
 {
- private:
-  TigerRecordInfo    *psRT7Info;
-
  public:
                       TigerLandmarks( OGRTigerDataSource *, const char * );
-  virtual            ~TigerLandmarks();
-
-  virtual int         SetModule( const char * );
 
   virtual OGRFeature *GetFeature( int );
 
@@ -366,18 +333,8 @@ class TigerLandmarks : public TigerPoint
 
 class TigerAreaLandmarks : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRT8Info;
-
 public:
                       TigerAreaLandmarks( OGRTigerDataSource *, const char * );
-  virtual            ~TigerAreaLandmarks();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -386,18 +343,8 @@ public:
 
 class TigerKeyFeatures : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRT9Info;
-
 public:
                       TigerKeyFeatures( OGRTigerDataSource *, const char * );
-  virtual            ~TigerKeyFeatures();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -407,8 +354,8 @@ public:
 class TigerPolygon : public TigerFileBase
 {
  private:
-  TigerRecordInfo    *psRTAInfo;
-  TigerRecordInfo    *psRTSInfo;
+  const TigerRecordInfo    *psRTAInfo;
+  const TigerRecordInfo    *psRTSInfo;
 
   FILE               *fpRTS;
   int                 bUsingRTS;
@@ -432,18 +379,8 @@ public:
 
 class TigerPolygonCorrections : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTBInfo;
-
 public:
                       TigerPolygonCorrections( OGRTigerDataSource *, const char * );
-  virtual            ~TigerPolygonCorrections();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -452,18 +389,8 @@ public:
 
 class TigerEntityNames : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTCInfo;
-
 public:
                       TigerEntityNames( OGRTigerDataSource *, const char * );
-  virtual            ~TigerEntityNames();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -472,18 +399,9 @@ public:
 
 class TigerPolygonEconomic : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTEInfo;
-
 public:
                       TigerPolygonEconomic( OGRTigerDataSource *, const char * );
-  virtual            ~TigerPolygonEconomic();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
 
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -492,18 +410,8 @@ public:
 
 class TigerIDHistory : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTHInfo;
-
 public:
                       TigerIDHistory( OGRTigerDataSource *, const char * );
-  virtual            ~TigerIDHistory();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -512,18 +420,8 @@ public:
 
 class TigerPolyChainLink : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTIInfo;
-
 public:
                       TigerPolyChainLink( OGRTigerDataSource *, const char * );
-  virtual            ~TigerPolyChainLink();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -532,18 +430,8 @@ public:
 
 class TigerSpatialMetadata : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTMInfo;
-
 public:
                       TigerSpatialMetadata( OGRTigerDataSource *, const char * );
-  virtual            ~TigerSpatialMetadata();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -552,14 +440,8 @@ public:
 
 class TigerPIP : public TigerPoint
 {
- private:
-  TigerRecordInfo    *psRTPInfo;
-
 public:
                       TigerPIP( OGRTigerDataSource *, const char * );
-  virtual            ~TigerPIP();
-
-  virtual int         SetModule( const char * );
 
   virtual OGRFeature *GetFeature( int );
 
@@ -572,18 +454,8 @@ public:
 
 class TigerTLIDRange : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTRInfo;
-
 public:
                       TigerTLIDRange( OGRTigerDataSource *, const char * );
-  virtual            ~TigerTLIDRange();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -592,18 +464,8 @@ public:
 
 class TigerZeroCellID : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTTInfo;
-
 public:
                       TigerZeroCellID( OGRTigerDataSource *, const char * );
-  virtual            ~TigerZeroCellID();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -612,14 +474,8 @@ public:
 
 class TigerOverUnder : public TigerPoint
 {
- private:
-  TigerRecordInfo    *psRTUInfo;
-
 public:
                       TigerOverUnder( OGRTigerDataSource *, const char * );
-  virtual            ~TigerOverUnder();
-
-  virtual int         SetModule( const char * );
 
   virtual OGRFeature *GetFeature( int );
 
@@ -632,18 +488,8 @@ public:
 
 class TigerZipPlus4 : public TigerFileBase
 {
- private:
-  TigerRecordInfo    *psRTZInfo;
-
  public:
                       TigerZipPlus4( OGRTigerDataSource *, const char * );
-  virtual            ~TigerZipPlus4();
-
-  virtual int         SetModule( const char * );
-
-  virtual OGRFeature *GetFeature( int );
-
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
index 8045239..8ab9d64 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrtigerdatasource.cpp 14288 2008-04-13 15:56:22Z rouault $
+ * $Id: ogrtigerdatasource.cpp 22622 2011-06-29 21:33:28Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerDataSource class
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: ogrtigerdatasource.cpp 14288 2008-04-13 15:56:22Z rouault $");
+CPL_CVSID("$Id: ogrtigerdatasource.cpp 22622 2011-06-29 21:33:28Z rouault $");
 
 /************************************************************************/
 /*                        TigerClassifyVersion()                        */
@@ -322,7 +322,7 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
         pszPath = CPLStrdup( CPLGetPath(pszFilename) );
 
         strncpy( szModule, CPLGetFilename(pszFilename), sizeof(szModule)-1 );
-        szModule[strlen(szModule)-1] = '\0';
+        szModule[sizeof(szModule)-1] = '\0';
 
         papszFileList = CSLAddString( papszFileList, szModule );
     }
diff --git a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
index 37fefb2..2589051 100644
--- a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigeraltname.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigeraltname.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerAltName, providing access to RT4 files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeraltname.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigeraltname.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "4"
 
-static TigerFieldInfo rt4_fields[] = {
+static const TigerFieldInfo rt4_fields[] = {
   // fieldname    fmt  type  OFTType         beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ',  ' ', OFTString,        0,   0,   8,       1,   0,     0 },
   { "TLID",       'R',  'N', OFTInteger,       6,  15,  10,       1,   1,     1 },
@@ -45,7 +45,7 @@ static TigerFieldInfo rt4_fields[] = {
   // to the FEAT array field here.
 };
 
-static TigerRecordInfo rt4_info =
+static const TigerRecordInfo rt4_info =
   {
     rt4_fields,
     sizeof(rt4_fields) / sizeof(TigerFieldInfo),
@@ -58,13 +58,11 @@ static TigerRecordInfo rt4_info =
 /************************************************************************/
 
 TigerAltName::TigerAltName( OGRTigerDataSource * poDSIn,
-                            const char * pszPrototypeModule )
+                            const char * pszPrototypeModule ) : TigerFileBase(&rt4_info, FILE_CODE)
 
 {
     OGRFieldDefn        oField("",OFTInteger);
 
-    psRT4Info = &rt4_info;
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "AltName" );
     poFeatureDefn->Reference();
@@ -74,31 +72,7 @@ TigerAltName::TigerAltName( OGRTigerDataSource * poDSIn,
     /*      Fields from type 4 record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRT4Info, poFeatureDefn );
-}
-
-/************************************************************************/
-/*                           ~TigerAltName()                            */
-/************************************************************************/
-
-TigerAltName::~TigerAltName()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerAltName::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
 
 /************************************************************************/
@@ -132,7 +106,7 @@ OGRFeature *TigerAltName::GetFeature( int nRecordId )
         return NULL;
     }
 
-    if( VSIFRead( achRecord, psRT4Info->nRecordLength, 1, fpPrimary ) != 1 )
+    if( VSIFRead( achRecord, psRTInfo->nRecordLength, 1, fpPrimary ) != 1 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read record %d of %s4",
@@ -148,7 +122,7 @@ OGRFeature *TigerAltName::GetFeature( int nRecordId )
     int         anFeatList[5];
     int         nFeatCount=0;
 
-    SetFields( psRT4Info, poFeature, achRecord );
+    SetFields( psRTInfo, poFeature, achRecord );
 
     for( int iFeat = 0; iFeat < 5; iFeat++ )
     {
@@ -176,12 +150,12 @@ OGRErr TigerAltName::CreateFeature( OGRFeature *poFeature )
     const int   *panValue;
     int         nValueCount = 0;
 
-    if( !SetWriteModule( FILE_CODE, psRT4Info->nRecordLength+2, poFeature ) )
+    if( !SetWriteModule( FILE_CODE, psRTInfo->nRecordLength+2, poFeature ) )
         return OGRERR_FAILURE;
 
-    memset( szRecord, ' ', psRT4Info->nRecordLength );
+    memset( szRecord, ' ', psRTInfo->nRecordLength );
 
-    WriteFields( psRT4Info, poFeature, szRecord );
+    WriteFields( psRTInfo, poFeature, szRecord );
 
     panValue = poFeature->GetFieldAsIntegerList( "FEAT", &nValueCount );
     for( int i = 0; i < nValueCount; i++ )
@@ -192,7 +166,7 @@ OGRErr TigerAltName::CreateFeature( OGRFeature *poFeature )
         strncpy( szRecord + 18 + 8 * i, szWork, 8 );
     }
 
-    WriteRecord( szRecord, psRT4Info->nRecordLength, FILE_CODE );
+    WriteRecord( szRecord, psRTInfo->nRecordLength, FILE_CODE );
 
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp b/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp
index f772c72..9b9fce5 100644
--- a/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerarealandmarks.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerarealandmarks.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerAreaLandmarks, providing access to .RT8 files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerarealandmarks.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerarealandmarks.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "8"
 
-static TigerFieldInfo rt8_fields[] = {
+static const TigerFieldInfo rt8_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       1,   1,     1 },
@@ -45,7 +45,7 @@ static TigerFieldInfo rt8_fields[] = {
   { "LAND",       'R', 'N', OFTInteger,   26,  35,  10,       1,   1,     1 }
 };
 
-static TigerRecordInfo rt8_info =
+static const TigerRecordInfo rt8_info =
   {
     rt8_fields,
     sizeof(rt8_fields) / sizeof(TigerFieldInfo),
@@ -57,116 +57,18 @@ static TigerRecordInfo rt8_info =
 /************************************************************************/
 
 TigerAreaLandmarks::TigerAreaLandmarks( OGRTigerDataSource * poDSIn,
-                                  const char * pszPrototypeModule )
+                                  const char * pszPrototypeModule ) : TigerFileBase(&rt8_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "AreaLandmarks" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRT8Info = &rt8_info;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from type 8 record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRT8Info, poFeatureDefn );
-
-}
-
-/************************************************************************/
-/*                        ~TigerAreaLandmarks()                         */
-/************************************************************************/
-
-TigerAreaLandmarks::~TigerAreaLandmarks()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerAreaLandmarks::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerAreaLandmarks::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %s8",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %s8",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRT8Info->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %s8",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Set fields.                                                     */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRT8Info, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerAreaLandmarks::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRT8Info->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRT8Info->nRecordLength );
-
-    WriteFields( psRT8Info, poFeature, szRecord);
-
-    WriteRecord( szRecord, psRT8Info->nRecordLength, FILE_CODE );
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 
-    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
index f5033d6..77f8d0c 100644
--- a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigercompletechain.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigercompletechain.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerCompleteChain, providing access to RT1 and
@@ -31,9 +31,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigercompletechain.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigercompletechain.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
-static TigerFieldInfo rt1_2002_fields[] = {
+static const TigerFieldInfo rt1_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "TLID",       'R', 'N', OFTInteger,    6,  15,  10,       1,   1,     1 },
@@ -76,14 +76,14 @@ static TigerFieldInfo rt1_2002_fields[] = {
   { "BLOCKL",     'L', 'N', OFTInteger,  183, 186,   4,       1,   1,     1 },
   { "BLOCKR",     'L', 'N', OFTInteger,  187, 190,   4,       1,   1,     1 }
 };
-static TigerRecordInfo rt1_2002_info =
+static const TigerRecordInfo rt1_2002_info =
   {
     rt1_2002_fields,
     sizeof(rt1_2002_fields) / sizeof(TigerFieldInfo),
     228
   };
 
-static TigerFieldInfo rt1_fields[] = {
+static const TigerFieldInfo rt1_fields[] = {
   // fieldname    fmt  type OFTType      beg  end   len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "TLID",       'R', 'N', OFTInteger,    6,  15,  10,       1,   1,     1 },
@@ -126,14 +126,14 @@ static TigerFieldInfo rt1_fields[] = {
   { "BLKL",       'L', 'N', OFTString,   183, 186,   4,       1,   1,     1 },
   { "BLKR",       'L', 'N', OFTString,   187, 190,   4,       1,   1,     1 }
 }; 
-static TigerRecordInfo rt1_info =
+static const TigerRecordInfo rt1_info =
   {
     rt1_fields,
     sizeof(rt1_fields) / sizeof(TigerFieldInfo),
     228
   };
 
-static TigerRecordInfo rt2_info =
+static const TigerRecordInfo rt2_info =
   {
     NULL,       // RT2 is handled specially in the code below; the only
     0,          // thing from this structure that is used is:
@@ -141,7 +141,7 @@ static TigerRecordInfo rt2_info =
   };
 
 
-static TigerFieldInfo rt3_2000_Redistricting_fields[] = {
+static const TigerFieldInfo rt3_2000_Redistricting_fields[] = {
   // fieldname    fmt  type OFTType       beg  end  len  bDefine bSet bWrite
   { "TLID",       'R', 'N', OFTInteger,     6,  15,  10,       0,   0,     1 },
   { "STATE90L",   'L', 'N', OFTInteger,    16,  17,   2,       1,   1,     1 },
@@ -170,14 +170,14 @@ static TigerFieldInfo rt3_2000_Redistricting_fields[] = {
   { "AITSL",      'L', 'N', OFTInteger,   102, 106,   5 ,      1,   1,     1 },
   { "AITSR",      'L', 'N', OFTInteger,   107, 111,   5,       1,   1,     1 }
 };
-static TigerRecordInfo rt3_2000_Redistricting_info  =
+static const TigerRecordInfo rt3_2000_Redistricting_info  =
   {
     rt3_2000_Redistricting_fields,
     sizeof(rt3_2000_Redistricting_fields) / sizeof(TigerFieldInfo),
     111
   };
 
-static TigerFieldInfo rt3_fields[] = {
+static const TigerFieldInfo rt3_fields[] = {
   // fieldname    fmt  type OFTType       beg  end  len  bDefine bSet bWrite
   { "TLID",       'R', 'N', OFTInteger,     6,  15,  10,       0,   0,     1 },
   { "STATE90L",   'L', 'N', OFTInteger,    16,  17,   2,       1,   1,     1 },
@@ -203,7 +203,7 @@ static TigerFieldInfo rt3_fields[] = {
   { "VTDR",       'L', 'A', OFTString,    108, 111,   4,       1,   1,     1 }
 
 };
-static TigerRecordInfo rt3_info =
+static const TigerRecordInfo rt3_info =
   {
     rt3_fields,
     sizeof(rt3_fields) / sizeof(TigerFieldInfo),
diff --git a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp b/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
index 10b4819..47ad77b 100644
--- a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerentitynames.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerentitynames.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerEntityNames, providing access to .RTC files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerentitynames.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerentitynames.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "C"
 
-static TigerFieldInfo rtC_2002_fields[] = {
+static const TigerFieldInfo rtC_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "STATE",      'L', 'N', OFTInteger,    6,   7,   2,       1,   1,     1 },
@@ -55,14 +55,14 @@ static TigerFieldInfo rtC_2002_fields[] = {
   { "RS_C2",      'L', 'N', OFTInteger,   55,  62,   8,       1,   1,     1 },
   { "NAME",       'L', 'A', OFTString,    63, 122,  60,       1,   1,     1 },
 };
-static TigerRecordInfo rtC_2002_info =
+static const TigerRecordInfo rtC_2002_info =
   {
     rtC_2002_fields,
     sizeof(rtC_2002_fields) / sizeof(TigerFieldInfo),
     122
   };
 
-static TigerFieldInfo rtC_2000_Redistricting_fields[] = {
+static const TigerFieldInfo rtC_2000_Redistricting_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "STATE",      'L', 'N', OFTInteger,    6,   7,   2,       1,   1,     1 },
@@ -81,14 +81,14 @@ static TigerFieldInfo rtC_2000_Redistricting_fields[] = {
   { "AITSCE",     'L', 'N', OFTInteger,   50,  52,   3,       1,   1,     1 },
   { "NAME",       'L', 'A', OFTString,    53, 112,  66,       1,   1,     1 }
 };
-static TigerRecordInfo rtC_2000_Redistricting_info =
+static const TigerRecordInfo rtC_2000_Redistricting_info =
   {
     rtC_2000_Redistricting_fields,
     sizeof(rtC_2000_Redistricting_fields) / sizeof(TigerFieldInfo),
     112
   };
 
-static TigerFieldInfo rtC_fields[] = {
+static const TigerFieldInfo rtC_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "STATE",      'L', 'N', OFTInteger,    6,   7,   2,       1,   1,     1 },
@@ -106,7 +106,7 @@ static TigerFieldInfo rtC_fields[] = {
   { "UA",         'L', 'N', OFTInteger,   43,  46,   4,       1,   1,     1 },
   { "NAME",       'L', 'A', OFTString,    47, 112,  66,       1,   1,     1 }
 };
-static TigerRecordInfo rtC_info =
+static const TigerRecordInfo rtC_info =
   {
     rtC_fields,
     sizeof(rtC_fields) / sizeof(TigerFieldInfo),
@@ -119,7 +119,7 @@ static TigerRecordInfo rtC_info =
 /************************************************************************/
 
 TigerEntityNames::TigerEntityNames( OGRTigerDataSource * poDSIn,
-                            const char * pszPrototypeModule )
+                            const char * pszPrototypeModule ) : TigerFileBase(NULL, FILE_CODE)
 
 {
     poDS = poDSIn;
@@ -128,108 +128,12 @@ TigerEntityNames::TigerEntityNames( OGRTigerDataSource * poDSIn,
     poFeatureDefn->SetGeomType( wkbPoint );
 
     if( poDS->GetVersion() >= TIGER_2002 ) {
-      psRTCInfo = &rtC_2002_info;
+      psRTInfo = &rtC_2002_info;
     } else if( poDS->GetVersion() >= TIGER_2000_Redistricting ) {
-      psRTCInfo = &rtC_2000_Redistricting_info;
+      psRTInfo = &rtC_2000_Redistricting_info;
     } else {
-      psRTCInfo = &rtC_info;
+      psRTInfo = &rtC_info;
     }
 
-    AddFieldDefns( psRTCInfo, poFeatureDefn );
-}
-
-/************************************************************************/
-/*                         ~TigerEntityNames()                          */
-/************************************************************************/
-
-TigerEntityNames::~TigerEntityNames()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerEntityNames::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, "C" ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerEntityNames::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sC",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Read the raw record data from the file.                         */
-    /* -------------------------------------------------------------------- */
-
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sC",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTCInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sC",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Set fields.                                                     */
-    /* -------------------------------------------------------------------- */
-
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTCInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerEntityNames::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTCInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTCInfo->nRecordLength );
-
-    WriteFields( psRTCInfo, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRTCInfo->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp b/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp
index e8f9a2c..faa8be6 100644
--- a/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerfeatureids.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerfeatureids.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerFeatureIds, providing access to .RT5 files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerfeatureids.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerfeatureids.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "5"
 
-static TigerFieldInfo rt5_2002_fields[] = {
+static const TigerFieldInfo rt5_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -44,14 +44,14 @@ static TigerFieldInfo rt5_2002_fields[] = {
   { "FETYPE",     'L', 'A', OFTString,    51,  54,   4,       1,   1,     1 },
   { "FEDIRS",     'L', 'A', OFTString,    55,  56,   2,       1,   1,     1 },
 };
-static TigerRecordInfo rt5_2002_info =
+static const TigerRecordInfo rt5_2002_info =
   {
     rt5_2002_fields,
     sizeof(rt5_2002_fields) / sizeof(TigerFieldInfo),
     56
   };
 
-static TigerFieldInfo rt5_fields[] = {
+static const TigerFieldInfo rt5_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     2,   6,   5,       1,   1,     1 },
@@ -64,7 +64,7 @@ static TigerFieldInfo rt5_fields[] = {
   { "FEDIRS",     'L', 'A', OFTString,    51,  52,   2,       1,   1,     1 }
 };
 
-static TigerRecordInfo rt5_info =
+static const TigerRecordInfo rt5_info =
   {
     rt5_fields,
     sizeof(rt5_fields) / sizeof(TigerFieldInfo),
@@ -76,111 +76,19 @@ static TigerRecordInfo rt5_info =
 /************************************************************************/
 
 TigerFeatureIds::TigerFeatureIds( OGRTigerDataSource * poDSIn,
-                                  const char * pszPrototypeModule )
+                                  const char * pszPrototypeModule ) : TigerFileBase(NULL, FILE_CODE)
 
 {
-  OGRFieldDefn        oField("",OFTInteger);
   poDS = poDSIn;
   poFeatureDefn = new OGRFeatureDefn( "FeatureIds" );
     poFeatureDefn->Reference();
   poFeatureDefn->SetGeomType( wkbNone );
 
   if (poDS->GetVersion() >= TIGER_2002) {
-    psRT5Info = &rt5_2002_info;
+    psRTInfo = &rt5_2002_info;
   } else {
-    psRT5Info = &rt5_info;
+    psRTInfo = &rt5_info;
   }
 
-  AddFieldDefns( psRT5Info, poFeatureDefn );
-}
-
-/************************************************************************/
-/*                        ~TigerFeatureIds()                         */
-/************************************************************************/
-
-TigerFeatureIds::~TigerFeatureIds()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerFeatureIds::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerFeatureIds::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %s5",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %s5",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRT5Info->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %s5",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRT5Info, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerFeatureIds::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRT5Info->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRT5Info->nRecordLength );
-
-    WriteFields( psRT5Info, poFeature, szRecord);
-
-    WriteRecord( szRecord, psRT5Info->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+  AddFieldDefns( psRTInfo, poFeatureDefn );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
index 0761bdf..79ad50e 100644
--- a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerfilebase.cpp 17225 2009-06-07 20:59:19Z rouault $
+ * $Id: tigerfilebase.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerBaseFile class, providing common services to all
@@ -33,13 +33,14 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: tigerfilebase.cpp 17225 2009-06-07 20:59:19Z rouault $");
+CPL_CVSID("$Id: tigerfilebase.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 /************************************************************************/
 /*                           TigerFileBase()                            */
 /************************************************************************/
 
-TigerFileBase::TigerFileBase()
+TigerFileBase::TigerFileBase( const TigerRecordInfo *psRTInfoIn,
+                              const char            *m_pszFileCodeIn )
 
 {
     pszShortModule = NULL;
@@ -49,6 +50,9 @@ TigerFileBase::TigerFileBase()
     nFeatures = 0;
     nVersionCode = 0;
     nVersion = TIGER_Unknown;
+
+    psRTInfo = psRTInfoIn;
+    m_pszFileCode = m_pszFileCodeIn;
 }
 
 /************************************************************************/
@@ -233,7 +237,7 @@ void TigerFileBase::EstablishFeatureCount()
 /*                              GetField()                              */
 /************************************************************************/
 
-CPLString TigerFileBase::GetField( const char * pachRawDataRecord,
+const char* TigerFileBase::GetField( const char * pachRawDataRecord,
                                      int nStartChar, int nEndChar )
 
 {
@@ -248,7 +252,7 @@ CPLString TigerFileBase::GetField( const char * pachRawDataRecord,
     while( nLength > 0 && aszField[nLength-1] == ' ' )
         aszField[--nLength] = '\0';
 
-    return aszField;
+    return CPLSPrintf("%s", aszField);
 }
 
 /************************************************************************/
@@ -304,6 +308,7 @@ int TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField,
     {
         strncpy( szValue, poFeature->GetFieldAsString( iField ), 
                  sizeof(szValue) - 1 );
+        szValue[sizeof(szValue) - 1] = 0;
         if( (int) strlen(szValue) < nEnd - nStart + 1 )
             memset( szValue + strlen(szValue), ' ', 
                     nEnd - nStart + 1 - strlen(szValue) );
@@ -440,11 +445,12 @@ int TigerFileBase::SetWriteModule( const char *pszExtension, int nRecLen,
 /* -------------------------------------------------------------------- */
 /*      Does this file already exist?                                   */
 /* -------------------------------------------------------------------- */
-    const char *pszFilename;
+    char *pszFilename;
 
     pszFilename = poDS->BuildFilename( szFullModule, pszExtension );
 
     fpPrimary = VSIFOpen( pszFilename, "ab" );
+    CPLFree(pszFilename);
     if( fpPrimary == NULL )
         return FALSE;
 
@@ -456,7 +462,7 @@ int TigerFileBase::SetWriteModule( const char *pszExtension, int nRecLen,
 /************************************************************************/
 /*                           AddFieldDefns()                            */
 /************************************************************************/
-void TigerFileBase::AddFieldDefns(TigerRecordInfo *psRTInfo,
+void TigerFileBase::AddFieldDefns(const TigerRecordInfo *psRTInfo,
                                   OGRFeatureDefn  *poFeatureDefn)
 {
     OGRFieldDefn        oField("",OFTInteger);
@@ -467,7 +473,7 @@ void TigerFileBase::AddFieldDefns(TigerRecordInfo *psRTInfo,
     
     for (i=0; i<psRTInfo->nFieldCount; ++i) {
         if (psRTInfo->pasFields[i].bDefine) {
-            OGRFieldType eFT = psRTInfo->pasFields[i].OGRtype;
+            OGRFieldType eFT = (OGRFieldType)psRTInfo->pasFields[i].OGRtype;
 
             if( bLFieldHack 
                 && psRTInfo->pasFields[i].cFmt == 'L' 
@@ -485,7 +491,7 @@ void TigerFileBase::AddFieldDefns(TigerRecordInfo *psRTInfo,
 /*                             SetFields()                              */
 /************************************************************************/
 
-void TigerFileBase::SetFields(TigerRecordInfo *psRTInfo,
+void TigerFileBase::SetFields(const TigerRecordInfo *psRTInfo,
                               OGRFeature      *poFeature,
                               char            *achRecord)
 {
@@ -504,7 +510,7 @@ void TigerFileBase::SetFields(TigerRecordInfo *psRTInfo,
 /************************************************************************/
 /*                             WriteField()                             */
 /************************************************************************/
-void TigerFileBase::WriteFields(TigerRecordInfo *psRTInfo,
+void TigerFileBase::WriteFields(const TigerRecordInfo *psRTInfo,
                                 OGRFeature      *poFeature,
                                 char            *szRecord)
 {
@@ -521,3 +527,99 @@ void TigerFileBase::WriteFields(TigerRecordInfo *psRTInfo,
     }
   }
 }
+
+
+
+/************************************************************************/
+/*                             SetModule()                              */
+/************************************************************************/
+
+int TigerFileBase::SetModule( const char * pszModule )
+
+{
+    if (m_pszFileCode == NULL)
+        return FALSE;
+
+    if( !OpenFile( pszModule, m_pszFileCode ) )
+        return FALSE;
+
+    EstablishFeatureCount();
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *TigerFileBase::GetFeature( int nRecordId )
+
+{
+    char        achRecord[OGR_TIGER_RECBUF_LEN];
+
+    if (psRTInfo == NULL)
+        return NULL;
+
+    if( nRecordId < 0 || nRecordId >= nFeatures )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Request for out-of-range feature %d of %s",
+                  nRecordId, pszModule );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the raw record data from the file.                         */
+/* -------------------------------------------------------------------- */
+    if( fpPrimary == NULL )
+        return NULL;
+
+    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to seek to %d of %s",
+                  nRecordId * nRecordLength, pszModule );
+        return NULL;
+    }
+
+    if( VSIFRead( achRecord, psRTInfo->nRecordLength, 1, fpPrimary ) != 1 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to read record %d of %s",
+                  nRecordId, pszModule );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set fields.                                                     */
+/* -------------------------------------------------------------------- */
+    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
+
+    SetFields( psRTInfo, poFeature, achRecord );
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           CreateFeature()                            */
+/************************************************************************/
+
+OGRErr TigerFileBase::CreateFeature( OGRFeature *poFeature )
+
+{
+    char        szRecord[OGR_TIGER_RECBUF_LEN];
+
+    if (psRTInfo == NULL)
+        return OGRERR_FAILURE;
+
+    if( !SetWriteModule( m_pszFileCode, psRTInfo->nRecordLength+2, poFeature ) )
+        return OGRERR_FAILURE;
+
+    memset( szRecord, ' ', psRTInfo->nRecordLength );
+
+    WriteFields( psRTInfo, poFeature, szRecord );
+
+    WriteRecord( szRecord, psRTInfo->nRecordLength, m_pszFileCode );
+
+    return OGRERR_NONE;
+}
diff --git a/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp b/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp
index f7131a6..b8f94ac 100644
--- a/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigeridhistory.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigeridhistory.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerIDHistory, providing access to .RTH files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeridhistory.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigeridhistory.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "H"
 
-static TigerFieldInfo rtH_fields[] = {
+static const TigerFieldInfo rtH_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       1,   1,     1 },
@@ -48,7 +48,7 @@ static TigerFieldInfo rtH_fields[] = {
   { "TLIDTO1",    'R', 'N', OFTInteger,   43,  52,  10,       1,   1,     1 },
   { "TLIDTO2",    'R', 'N', OFTInteger,   53,  62,  10,       1,   1,     1 }
 };
-static TigerRecordInfo rtH_info =
+static const TigerRecordInfo rtH_info =
   {
     rtH_fields,
     sizeof(rtH_fields) / sizeof(TigerFieldInfo),
@@ -60,115 +60,17 @@ static TigerRecordInfo rtH_info =
 /************************************************************************/
 
 TigerIDHistory::TigerIDHistory( OGRTigerDataSource * poDSIn,
-                            const char * pszPrototypeModule )
+                            const char * pszPrototypeModule ) : TigerFileBase(&rtH_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "IDHistory" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRTHInfo = &rtH_info;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from record type H                                       */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns(psRTHInfo, poFeatureDefn);
-}
-
-/************************************************************************/
-/*                          ~TigerIDHistory()                           */
-/************************************************************************/
-
-TigerIDHistory::~TigerIDHistory()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerIDHistory::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerIDHistory::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sH",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sH",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTHInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sH",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Set fields.                                                     */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTHInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerIDHistory::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTHInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTHInfo->nRecordLength );
-
-    WriteFields( psRTHInfo, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRTHInfo->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+    AddFieldDefns(psRTInfo, poFeatureDefn);
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp b/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp
index 8eb3446..88c1062 100644
--- a/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerkeyfeatures.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerkeyfeatures.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerKeyFeatures, providing access to .RT9 files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerkeyfeatures.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerkeyfeatures.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "9"
 
-static TigerFieldInfo rt9_fields[] = {
+static const TigerFieldInfo rt9_fields[] = {
   // fieldname    fmt  type  OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       1,   1,     1 },
@@ -51,7 +51,7 @@ static TigerFieldInfo rt9_fields[] = {
   { "FEAT",       'R', 'N', OFTInteger,   80,  87,   8,       1,   1,     1 }
 };
 
-static TigerRecordInfo rt9_info =
+static const TigerRecordInfo rt9_info =
   {
     rt9_fields,
     sizeof(rt9_fields) / sizeof(TigerFieldInfo),
@@ -63,118 +63,18 @@ static TigerRecordInfo rt9_info =
 /************************************************************************/
 
 TigerKeyFeatures::TigerKeyFeatures( OGRTigerDataSource * poDSIn,
-                                  const char * pszPrototypeModule )
+                                  const char * pszPrototypeModule ) : TigerFileBase(&rt9_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "KeyFeatures" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRT9Info = &rt9_info;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from type 9 record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRT9Info, poFeatureDefn );
-
-}
-
-/************************************************************************/
-/*                        ~TigerKeyFeatures()                         */
-/************************************************************************/
-
-TigerKeyFeatures::~TigerKeyFeatures()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerKeyFeatures::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerKeyFeatures::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %s9",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Read the raw record data from the file.                         */
-    /* -------------------------------------------------------------------- */
-
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %s9",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRT9Info->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %s9",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Set fields.                                                     */
-    /* -------------------------------------------------------------------- */
-
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRT9Info, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerKeyFeatures::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRT9Info->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRT9Info->nRecordLength );
-
-    WriteFields( psRT9Info, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRT9Info->nRecordLength, FILE_CODE );
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 
-    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp b/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
index 99eb8e2..900d7f6 100644
--- a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerlandmarks.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerlandmarks.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerLandmarks, providing access to .RT7 files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerlandmarks.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerlandmarks.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "7"
 
-static TigerFieldInfo rt7_2002_fields[] = {
+static const TigerFieldInfo rt7_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -46,14 +46,14 @@ static TigerFieldInfo rt7_2002_fields[] = {
   { "LALAT",      'R', 'N', OFTInteger,   65,  73,   9,       1,   1,     1 },
   { "FILLER",     'L', 'A', OFTString,    74,  74,   1,       1,   1,     1 },
 };
-static TigerRecordInfo rt7_2002_info =
+static const TigerRecordInfo rt7_2002_info =
   {
     rt7_2002_fields,
     sizeof(rt7_2002_fields) / sizeof(TigerFieldInfo),
     74
   };
 
-static TigerFieldInfo rt7_fields[] = {
+static const TigerFieldInfo rt7_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       1,   0,     1 },
@@ -64,7 +64,7 @@ static TigerFieldInfo rt7_fields[] = {
   { "CFCC",       'L', 'A', OFTString,    22,  24,   3,       1,   1,     1 },
   { "LANAME",     'L', 'A', OFTString,    25,  54,  30,       1,   1,     1 }
 };
-static TigerRecordInfo rt7_info =
+static const TigerRecordInfo rt7_info =
   {
     rt7_fields,
     sizeof(rt7_fields) / sizeof(TigerFieldInfo),
@@ -77,7 +77,7 @@ static TigerRecordInfo rt7_info =
 
 TigerLandmarks::TigerLandmarks( OGRTigerDataSource * poDSIn,
                                 const char * pszPrototypeModule )
-  : TigerPoint(FALSE)
+  : TigerPoint(FALSE, NULL, FILE_CODE)
 {
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "Landmarks" );
@@ -85,27 +85,17 @@ TigerLandmarks::TigerLandmarks( OGRTigerDataSource * poDSIn,
     poFeatureDefn->SetGeomType( wkbPoint );
 
     if (poDS->GetVersion() >= TIGER_2002) {
-        psRT7Info = &rt7_2002_info;
+        psRTInfo = &rt7_2002_info;
     } else {
-        psRT7Info = &rt7_info;
+        psRTInfo = &rt7_info;
     }
 
-    AddFieldDefns( psRT7Info, poFeatureDefn );
-}
-
-TigerLandmarks::~TigerLandmarks()
-{}
-
-
-int TigerLandmarks::SetModule( const char * pszModule )
-{
-  return TigerPoint::SetModule( pszModule, FILE_CODE );
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
 
 OGRFeature *TigerLandmarks::GetFeature( int nRecordId )
 {
   return TigerPoint::GetFeature( nRecordId,
-                                 psRT7Info,
                                  55, 64,
                                  65, 73 );
 }
@@ -113,7 +103,5 @@ OGRFeature *TigerLandmarks::GetFeature( int nRecordId )
 OGRErr TigerLandmarks::CreateFeature( OGRFeature *poFeature )
 {
   return TigerPoint::CreateFeature( poFeature, 
-                                    psRT7Info,
-                                    55,
-                                    FILE_CODE );
+                                    55 );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp b/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
index 603d79f..fc5fff4 100644
--- a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigeroverunder.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigeroverunder.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerOverUnder, providing access to .RTU files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeroverunder.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigeroverunder.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE       "U"
 
-static TigerFieldInfo rtU_fields[] = {
+static const TigerFieldInfo rtU_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -47,7 +47,7 @@ static TigerFieldInfo rtU_fields[] = {
   { "FRLONG",     'R', 'N', OFTInteger,   62,  71,  10,       1,   1,     1 },
   { "FRLAT",      'R', 'N', OFTInteger,   72,  80,   9,       1,   1,     1 },
 };
-static TigerRecordInfo rtU_info =
+static const TigerRecordInfo rtU_info =
   {
     rtU_fields,
     sizeof(rtU_fields) / sizeof(TigerFieldInfo),
@@ -60,35 +60,20 @@ static TigerRecordInfo rtU_info =
 /************************************************************************/
 
 TigerOverUnder::TigerOverUnder( OGRTigerDataSource * poDSIn,
-                              const char * pszPrototypeModule )
-  : TigerPoint(TRUE)
+                              const char * pszPrototypeModule ) : TigerPoint(TRUE, &rtU_info, FILE_CODE)
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "OverUnder" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRTUInfo = &rtU_info;
-
-    AddFieldDefns( psRTUInfo, poFeatureDefn );
-
-}
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 
-/************************************************************************/
-TigerOverUnder::~TigerOverUnder()
-{}
-
-int TigerOverUnder::SetModule( const char * pszModule )
-{
-  return TigerPoint::SetModule( pszModule, FILE_CODE );
 }
 
 OGRFeature *TigerOverUnder::GetFeature( int nRecordId )
 {
   return TigerPoint::GetFeature( nRecordId,
-                                 psRTUInfo,
                                  62, 71,
                                  72, 80 );
 }
@@ -96,7 +81,5 @@ OGRFeature *TigerOverUnder::GetFeature( int nRecordId )
 OGRErr TigerOverUnder::CreateFeature( OGRFeature *poFeature )
 {
   return TigerPoint::CreateFeature( poFeature, 
-                                    psRTUInfo,
-                                    62,
-                                    FILE_CODE );
+                                    62 );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpip.cpp b/ogr/ogrsf_frmts/tiger/tigerpip.cpp
index 57bf5a1..9286bb9 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpip.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpip.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpip.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerpip.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPIP, providing access to .RTP files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpip.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerpip.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "P"
 
-static TigerFieldInfo rtP_2002_fields[] = {
+static const TigerFieldInfo rtP_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -44,14 +44,14 @@ static TigerFieldInfo rtP_2002_fields[] = {
   { "POLYLAT",    'R', 'N', OFTInteger,   36,  44,   9,       1,   1,     1 },
   { "WATER",      'L', 'N', OFTInteger,   45,  45,   1,       1,   1,     1 },
 };
-static TigerRecordInfo rtP_2002_info =
+static const TigerRecordInfo rtP_2002_info =
   {
     rtP_2002_fields,
     sizeof(rtP_2002_fields) / sizeof(TigerFieldInfo),
     45
   };
 
-static TigerFieldInfo rtP_fields[] = {
+static const TigerFieldInfo rtP_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       1,   1,     1 },
@@ -60,7 +60,7 @@ static TigerFieldInfo rtP_fields[] = {
   { "CENID",      'L', 'A', OFTString,    11,  15,   5,       1,   1,     1 },
   { "POLYID",     'R', 'N', OFTInteger,   16,  25,  10,       1,   1,     1 }
 };
-static TigerRecordInfo rtP_info =
+static const TigerRecordInfo rtP_info =
   {
     rtP_fields,
     sizeof(rtP_fields) / sizeof(TigerFieldInfo),
@@ -74,7 +74,7 @@ static TigerRecordInfo rtP_info =
 
 TigerPIP::TigerPIP( OGRTigerDataSource * poDSIn,
                             const char * pszPrototypeModule ) 
-  : TigerPoint(TRUE)
+  : TigerPoint(TRUE, NULL, FILE_CODE)
 {
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "PIP" );
@@ -82,25 +82,16 @@ TigerPIP::TigerPIP( OGRTigerDataSource * poDSIn,
     poFeatureDefn->SetGeomType( wkbPoint );
 
     if (poDS->GetVersion() >= TIGER_2002) {
-        psRTPInfo = &rtP_2002_info;
+        psRTInfo = &rtP_2002_info;
     } else {
-        psRTPInfo = &rtP_info;
+        psRTInfo = &rtP_info;
     }
-    AddFieldDefns( psRTPInfo, poFeatureDefn );
-}
-
-TigerPIP::~TigerPIP()
-{}
-
-int TigerPIP::SetModule( const char * pszModule )
-{
-  return TigerPoint::SetModule( pszModule, FILE_CODE );
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
 
 OGRFeature *TigerPIP::GetFeature( int nRecordId )
 {
   return TigerPoint::GetFeature( nRecordId,
-                                 psRTPInfo,
                                  26, 35,
                                  36, 44 );
 }
@@ -108,8 +99,6 @@ OGRFeature *TigerPIP::GetFeature( int nRecordId )
 OGRErr TigerPIP::CreateFeature( OGRFeature *poFeature )
 {
   return TigerPoint::CreateFeature( poFeature, 
-                                    psRTPInfo,
-                                    26,
-                                    FILE_CODE );
+                                    26 );
 }
 
diff --git a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
index 8b5fa5e..3d0dd2b 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpoint.cpp 12745 2007-11-13 14:18:11Z dron $
+ * $Id: tigerpoint.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPoint class.
@@ -30,36 +30,21 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpoint.cpp 12745 2007-11-13 14:18:11Z dron $");
+CPL_CVSID("$Id: tigerpoint.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 /************************************************************************/
 /*                             TigerPoint()                             */
 /************************************************************************/
-TigerPoint::TigerPoint( int bRequireGeom )
+TigerPoint::TigerPoint( int bRequireGeom, const TigerRecordInfo *psRTInfoIn,
+                        const char            *m_pszFileCodeIn ) : TigerFileBase(psRTInfoIn, m_pszFileCodeIn)
 {
     this->bRequireGeom = bRequireGeom;
 }
 
-TigerPoint::~TigerPoint()
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-int TigerPoint::SetModule( const char * pszModule, const char *pszFileCode )
-{
-    if( !OpenFile( pszModule, pszFileCode ) )
-        return FALSE;
-    EstablishFeatureCount();
-    return TRUE;
-}
-
 /************************************************************************/
 /*                             GetFeature()                             */
 /************************************************************************/
 OGRFeature *TigerPoint::GetFeature( int nRecordId,
-                                    TigerRecordInfo *psRTInfo,
                                     int nX0, int nX1,
                                     int nY0, int nY1 )
 {
@@ -121,15 +106,13 @@ OGRFeature *TigerPoint::GetFeature( int nRecordId,
 /*                           CreateFeature()                            */
 /************************************************************************/
 OGRErr TigerPoint::CreateFeature( OGRFeature *poFeature, 
-                                  TigerRecordInfo *psRTInfo,
-                                  int pointIndex,
-                                  const char *pszFileCode)
+                                  int pointIndex)
 
 {
     char        szRecord[OGR_TIGER_RECBUF_LEN];
     OGRPoint    *poPoint = (OGRPoint *) poFeature->GetGeometryRef();
 
-    if( !SetWriteModule( pszFileCode, psRTInfo->nRecordLength+2, poFeature ) )
+    if( !SetWriteModule( m_pszFileCode, psRTInfo->nRecordLength+2, poFeature ) )
         return OGRERR_FAILURE;
 
     memset( szRecord, ' ', psRTInfo->nRecordLength );
@@ -146,7 +129,7 @@ OGRErr TigerPoint::CreateFeature( OGRFeature *poFeature,
         }
     }
 
-    WriteRecord( szRecord, psRTInfo->nRecordLength, pszFileCode );
+    WriteRecord( szRecord, psRTInfo->nRecordLength, m_pszFileCode );
 
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp b/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp
index 8904881..411eca9 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpolychainlink.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerpolychainlink.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolyChainLink, providing access to .RTI files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolychainlink.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerpolychainlink.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "I"
 
-static TigerFieldInfo rtI_2002_fields[] = {
+static const TigerFieldInfo rtI_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -51,14 +51,14 @@ static TigerFieldInfo rtI_2002_fields[] = {
   { "RS_I2",      'L', 'A', OFTString,   108, 117,  10,       1,   1,     1 },
   { "RS_I3",      'L', 'A', OFTString,   118, 127,  10,       1,   1,     1 },
 };
-static TigerRecordInfo rtI_2002_info =
+static const TigerRecordInfo rtI_2002_info =
   {
     rtI_2002_fields,
     sizeof(rtI_2002_fields) / sizeof(TigerFieldInfo),
     127
   };
 
-static TigerFieldInfo rtI_fields[] = {
+static const TigerFieldInfo rtI_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "TLID",       'R', 'N', OFTInteger,    6,  15,  10,       1,   1,     1 },
@@ -71,7 +71,7 @@ static TigerFieldInfo rtI_fields[] = {
   { "CENIDR",     'L', 'A', OFTString,    37,  41,   5,       1,   1,     1 },
   { "POLYIDR",    'R', 'N', OFTInteger,   42,  51,  10,       1,   1,     1 }
 };
-static TigerRecordInfo rtI_info =
+static const TigerRecordInfo rtI_info =
   {
     rtI_fields,
     sizeof(rtI_fields) / sizeof(TigerFieldInfo),
@@ -84,7 +84,7 @@ static TigerRecordInfo rtI_info =
 /************************************************************************/
 
 TigerPolyChainLink::TigerPolyChainLink( OGRTigerDataSource * poDSIn,
-                                  const char * pszPrototypeModule )
+                                  const char * pszPrototypeModule ) : TigerFileBase(NULL, FILE_CODE)
 
 {
     OGRFieldDefn        oField("",OFTInteger);
@@ -95,109 +95,14 @@ TigerPolyChainLink::TigerPolyChainLink( OGRTigerDataSource * poDSIn,
     poFeatureDefn->SetGeomType( wkbNone );
 
     if (poDS->GetVersion() >= TIGER_2002) {
-      psRTIInfo = &rtI_2002_info;
+      psRTInfo = &rtI_2002_info;
     } else {
-      psRTIInfo = &rtI_info;
+      psRTInfo = &rtI_info;
     }
 
     /* -------------------------------------------------------------------- */
     /*      Fields from type I record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRTIInfo, poFeatureDefn );
-}
-
-/************************************************************************/
-/*                        ~TigerPolyChainLink()                         */
-/************************************************************************/
-
-TigerPolyChainLink::~TigerPolyChainLink()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerPolyChainLink::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerPolyChainLink::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sI",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sI",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTIInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sI",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Set fields.                                                     */
-    /* -------------------------------------------------------------------- */
-
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTIInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerPolyChainLink::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTIInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTIInfo->nRecordLength );
-
-    WriteFields( psRTIInfo, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRTIInfo->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
index 0f09121..06a0536 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpolygon.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerpolygon.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygon, providing access to .RTA files.
@@ -30,9 +30,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygon.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerpolygon.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
-static TigerFieldInfo rtA_2002_fields[] = {
+static const TigerFieldInfo rtA_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -82,7 +82,7 @@ static TigerFieldInfo rtA_2002_fields[] = {
   { "RS_A18",     'L', 'A', OFTString,   194, 199,   6,       1,   1,     1 },
   { "RS_A19",     'L', 'A', OFTString,   200, 210,  11,       1,   1,     1 },
 };
-static TigerRecordInfo rtA_2002_info =
+static const TigerRecordInfo rtA_2002_info =
   {
     rtA_2002_fields,
     sizeof(rtA_2002_fields) / sizeof(TigerFieldInfo),
@@ -90,7 +90,7 @@ static TigerRecordInfo rtA_2002_info =
   };
 
 
-static TigerFieldInfo rtA_2003_fields[] = {
+static const TigerFieldInfo rtA_2003_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -142,7 +142,7 @@ static TigerFieldInfo rtA_2003_fields[] = {
   { "RS_A18",     'L', 'A', OFTString,   194, 199,   6,       1,   1,     1 },
   { "RS_A19",     'L', 'A', OFTString,   200, 210,  11,       1,   1,     1 },
 };
-static TigerRecordInfo rtA_2003_info =
+static const TigerRecordInfo rtA_2003_info =
   {
     rtA_2003_fields,
     sizeof(rtA_2003_fields) / sizeof(TigerFieldInfo),
@@ -150,7 +150,7 @@ static TigerRecordInfo rtA_2003_info =
   };
 
 
-static TigerFieldInfo rtA_2004_fields[] = {
+static const TigerFieldInfo rtA_2004_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -202,7 +202,7 @@ static TigerFieldInfo rtA_2004_fields[] = {
   { "RS_A18",     'L', 'A', OFTString,   194, 199,   6,       1,   1,     1 },
   { "RS_A19",     'L', 'A', OFTString,   200, 210,  11,       1,   1,     1 },
 };
-static TigerRecordInfo rtA_2004_info =
+static const TigerRecordInfo rtA_2004_info =
   {
     rtA_2004_fields,
     sizeof(rtA_2004_fields) / sizeof(TigerFieldInfo),
@@ -210,7 +210,7 @@ static TigerRecordInfo rtA_2004_info =
   };
 
 
-static TigerFieldInfo rtA_fields[] = {
+static const TigerFieldInfo rtA_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       1,   1,     1 },
@@ -237,7 +237,7 @@ static TigerFieldInfo rtA_fields[] = {
   { "AIR90",      'L', 'N', OFTInteger,   95,  98,   4,       1,   1,     1 }
 };
 
-static TigerRecordInfo rtA_info =
+static const TigerRecordInfo rtA_info =
   {
     rtA_fields,
     sizeof(rtA_fields) / sizeof(TigerFieldInfo),
@@ -245,7 +245,7 @@ static TigerRecordInfo rtA_info =
   };
 
 
-static TigerFieldInfo rtS_2002_fields[] = {
+static const TigerFieldInfo rtS_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       0,   0,     1 },
   { "CENID",      'L', 'A', OFTString,    11,  15,   5,       0,   0,     1 },
@@ -288,7 +288,7 @@ static TigerFieldInfo rtS_2002_fields[] = {
   { "SLDL",       'R', 'A', OFTString,   161, 163,   3,       1,   1,     1 },
   { "UGA",        'L', 'A', OFTString,   164, 168,   5,       1,   1,     1 },
 };
-static TigerRecordInfo rtS_2002_info =
+static const TigerRecordInfo rtS_2002_info =
   {
     rtS_2002_fields,
     sizeof(rtS_2002_fields) / sizeof(TigerFieldInfo),
@@ -296,7 +296,7 @@ static TigerRecordInfo rtS_2002_info =
   };
 
 
-static TigerFieldInfo rtS_2000_Redistricting_fields[] = {
+static const TigerFieldInfo rtS_2000_Redistricting_fields[] = {
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       0,   0,     1 },
   { "STATE",      'L', 'N', OFTInteger,    6,   7,   2,       0,   0,     1 },
   { "COUNTY",     'L', 'N', OFTInteger,    8,  10,   3,       0,   0,     1 },
@@ -333,14 +333,14 @@ static TigerFieldInfo rtS_2000_Redistricting_fields[] = {
 
 };
 
-static TigerRecordInfo rtS_2000_Redistricting_info =
+static const TigerRecordInfo rtS_2000_Redistricting_info =
   {
     rtS_2000_Redistricting_fields,
     sizeof(rtS_2000_Redistricting_fields) / sizeof(TigerFieldInfo),
     120
   };
 
-static TigerFieldInfo rtS_fields[] = {
+static const TigerFieldInfo rtS_fields[] = {
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       0,   0,     1 },
   { "STATE",      'L', 'N', OFTInteger,    6,   7,   2,       0,   0,     1 },
   { "COUNTY",     'L', 'N', OFTInteger,    8,  10,   3,       0,   0,     1 },
@@ -369,7 +369,7 @@ static TigerFieldInfo rtS_fields[] = {
   { "STHOUSE",    'L', 'A', OFTString,    91,  96,   6,       1,   1,     1 },
   { "VTD00",      'L', 'A', OFTString,    97, 102,   6,       1,   1,     1 }
 };
-static TigerRecordInfo rtS_info =
+static const TigerRecordInfo rtS_info =
   {
     rtS_fields,
     sizeof(rtS_fields) / sizeof(TigerFieldInfo),
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp
index a03834c..497a3e0 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpolygoncorrections.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerpolygoncorrections.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygonCorrections, providing access to .RTB files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygoncorrections.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerpolygoncorrections.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE       "B"
 
-static TigerFieldInfo rtB_fields[] = {
+static const TigerFieldInfo rtB_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -58,7 +58,7 @@ static TigerFieldInfo rtB_fields[] = {
   { "URCC",       'L', 'A', OFTString,    90,  90,   1,       1,   1,     1 },
   { "RS-B1",      'L', 'A', OFTString,    91,  98,  12,       1,   1,     1 },
 };
-static TigerRecordInfo rtB_info =
+static const TigerRecordInfo rtB_info =
   {
     rtB_fields,
     sizeof(rtB_fields) / sizeof(TigerFieldInfo),
@@ -70,7 +70,7 @@ static TigerRecordInfo rtB_info =
 /************************************************************************/
 
 TigerPolygonCorrections::TigerPolygonCorrections( OGRTigerDataSource * poDSIn,
-                              const char * pszPrototypeModule )
+                              const char * pszPrototypeModule ) : TigerFileBase(&rtB_info, FILE_CODE)
 
 {
     OGRFieldDefn        oField("",OFTInteger);
@@ -80,106 +80,9 @@ TigerPolygonCorrections::TigerPolygonCorrections( OGRTigerDataSource * poDSIn,
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRTBInfo = &rtB_info;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from type B record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRTBInfo, poFeatureDefn );
-}
-
-/************************************************************************/
-/*                           ~TigerPolygonCorrections()                           */
-/************************************************************************/
-
-TigerPolygonCorrections::~TigerPolygonCorrections()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerPolygonCorrections::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerPolygonCorrections::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sZ",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTBInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Set fields.                                                     */
-    /* -------------------------------------------------------------------- */
-
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTBInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerPolygonCorrections::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTBInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTBInfo->nRecordLength );
-
-    WriteFields( psRTBInfo, poFeature, szRecord);
-
-    WriteRecord( szRecord, psRTBInfo->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
index 74878cd..0a7789f 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerpolygoneconomic.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerpolygoneconomic.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygonEconomic, providing access to .RTE files.
@@ -30,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygoneconomic.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerpolygoneconomic.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE       "E"
 
@@ -55,7 +55,7 @@ static TigerFieldInfo rtE_fields[] = {
 };
 */
 
-static TigerFieldInfo rtE_fields[] = {
+static const TigerFieldInfo rtE_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -72,7 +72,7 @@ static TigerFieldInfo rtE_fields[] = {
   { "COMMREGEC",  'L', 'N', OFTInteger,   56,  56,   1,       1,   1,     1 },
   { "RS_E6",      'L', 'A', OFTString,    57,  73,  17,       1,   1,     1 }
 };
-static TigerRecordInfo rtE_info =
+static const TigerRecordInfo rtE_info =
   {
     rtE_fields,
     sizeof(rtE_fields) / sizeof(TigerFieldInfo),
@@ -84,115 +84,17 @@ static TigerRecordInfo rtE_info =
 /************************************************************************/
 
 TigerPolygonEconomic::TigerPolygonEconomic( OGRTigerDataSource * poDSIn,
-                              const char * pszPrototypeModule )
+                              const char * pszPrototypeModule ) : TigerFileBase(&rtE_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "PolygonEconomic" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRTEInfo = &rtE_info;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from type E record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRTEInfo, poFeatureDefn );
-}
-
-/************************************************************************/
-/*                           ~TigerPolygonEconomic()                           */
-/************************************************************************/
-
-TigerPolygonEconomic::~TigerPolygonEconomic()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerPolygonEconomic::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerPolygonEconomic::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sZ",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTEInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Set fields.                                                     */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTEInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerPolygonEconomic::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTEInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTEInfo->nRecordLength );
-
-    WriteFields( psRTEInfo, poFeature, szRecord);
-
-    WriteRecord( szRecord, psRTEInfo->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp b/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp
index 26e02fe..a3cec0c 100644
--- a/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerspatialmetadata.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerspatialmetadata.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerSpatialMetadata, providing access to .RTM files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerspatialmetadata.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerspatialmetadata.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "M"
 
-static TigerFieldInfo rtM_fields[] = {
+static const TigerFieldInfo rtM_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "TLID",       'R', 'N', OFTInteger,    6,  15,  10,       1,   1,     1 },
@@ -46,7 +46,7 @@ static TigerFieldInfo rtM_fields[] = {
   { "RS-M2",      'L', 'A', OFTString,    66,  67,   2,       1,   1,     1 },
   { "RS-M3",      'L', 'A', OFTString,    68,  90,  23,       1,   1,     1 }
 };
-static TigerRecordInfo rtM_info =
+static const TigerRecordInfo rtM_info =
   {
     rtM_fields,
     sizeof(rtM_fields) / sizeof(TigerFieldInfo),
@@ -58,115 +58,17 @@ static TigerRecordInfo rtM_info =
 /************************************************************************/
 
 TigerSpatialMetadata::TigerSpatialMetadata( OGRTigerDataSource * poDSIn,
-                            const char * pszPrototypeModule )
+                            const char * pszPrototypeModule ) : TigerFileBase(&rtM_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "SpatialMetadata" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRTMInfo = &rtM_info;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from record type H                                       */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns(psRTMInfo, poFeatureDefn);
-}
-
-/************************************************************************/
-/*                       ~TigerSpatialMetadata()                        */
-/************************************************************************/
-
-TigerSpatialMetadata::~TigerSpatialMetadata()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerSpatialMetadata::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerSpatialMetadata::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sH",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sH",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTMInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sM",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Set fields.                                                     */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTMInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerSpatialMetadata::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTMInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTMInfo->nRecordLength );
-
-    WriteFields( psRTMInfo, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRTMInfo->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+    AddFieldDefns(psRTInfo, poFeatureDefn);
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp b/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp
index c2fb9d6..58cd2ce 100644
--- a/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigertlidrange.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigertlidrange.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerTLIDRange, providing access to .RTR files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigertlidrange.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigertlidrange.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "R"
 
-static TigerFieldInfo rtR_2002_fields[] = {
+static const TigerFieldInfo rtR_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -47,14 +47,14 @@ static TigerFieldInfo rtR_2002_fields[] = {
   { "TZHIGHID",   'R', 'N', OFTInteger,   66,  75,  10,       1,   1,     1 },
   { "FILLER",     'L', 'A', OFTString,    76,  76,   1,       1,   1,     1 },
 };
-static TigerRecordInfo rtR_2002_info =
+static const TigerRecordInfo rtR_2002_info =
   {
     rtR_2002_fields,
     sizeof(rtR_2002_fields) / sizeof(TigerFieldInfo),
     76
   };
 
-static TigerFieldInfo rtR_fields[] = {
+static const TigerFieldInfo rtR_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       1,   1,     1 },
@@ -66,7 +66,7 @@ static TigerFieldInfo rtR_fields[] = {
   { "HIGHID",     'R', 'N', OFTInteger,   36,  45,  10,       1,   1,     1 }
 };
 
-static TigerRecordInfo rtR_info =
+static const TigerRecordInfo rtR_info =
   {
     rtR_fields,
     sizeof(rtR_fields) / sizeof(TigerFieldInfo),
@@ -78,121 +78,24 @@ static TigerRecordInfo rtR_info =
 /************************************************************************/
 
 TigerTLIDRange::TigerTLIDRange( OGRTigerDataSource * poDSIn,
-                            const char * pszPrototypeModule )
+                            const char * pszPrototypeModule ) : TigerFileBase(NULL, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "TLIDRange" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
     if (poDS->GetVersion() >= TIGER_2002) {
-      psRTRInfo = &rtR_2002_info;
+      psRTInfo = &rtR_2002_info;
     } else {
-      psRTRInfo = &rtR_info;
+      psRTInfo = &rtR_info;
     }
 
     /* -------------------------------------------------------------------- */
     /*      Fields from type R record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRTRInfo, poFeatureDefn );
-
-}
-
-/************************************************************************/
-/*                          ~TigerTLIDRange()                           */
-/************************************************************************/
-
-TigerTLIDRange::~TigerTLIDRange()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerTLIDRange::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerTLIDRange::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sR",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sR",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTRInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sR",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-    /* -------------------------------------------------------------------- */
-    /*      Set fields.                                                     */
-    /* -------------------------------------------------------------------- */
-
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTRInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerTLIDRange::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTRInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTRInfo->nRecordLength );
-
-    WriteFields( psRTRInfo, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRTRInfo->nRecordLength, FILE_CODE );
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 
-    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp b/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp
index 31c2b4d..63c6e6d 100644
--- a/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerzerocellid.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerzerocellid.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerZeroCellID, providing access to .RTT files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerzerocellid.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerzerocellid.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE       "T"
 
-static TigerFieldInfo rtT_fields[] = {
+static const TigerFieldInfo rtT_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       1,   1,     1 },
@@ -42,7 +42,7 @@ static TigerFieldInfo rtT_fields[] = {
   { "SOURCE",     'L', 'A', OFTString,    21,  30,  10,       1,   1,     1 },
   { "FTRP",       'L', 'A', OFTString,    31,  47,  17,       1,   1,     1 }
 };
-static TigerRecordInfo rtT_info =
+static const TigerRecordInfo rtT_info =
   {
     rtT_fields,
     sizeof(rtT_fields) / sizeof(TigerFieldInfo),
@@ -54,116 +54,18 @@ static TigerRecordInfo rtT_info =
 /************************************************************************/
 
 TigerZeroCellID::TigerZeroCellID( OGRTigerDataSource * poDSIn,
-                              const char * pszPrototypeModule )
+                              const char * pszPrototypeModule ) : TigerFileBase(&rtT_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "ZeroCellID" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRTTInfo = &rtT_info;
-
 /* -------------------------------------------------------------------- */
 /*      Fields from type T record.                                      */
 /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRTTInfo, poFeatureDefn );
-
-}
-
-/************************************************************************/
-/*                           ~TigerZeroCellID()                           */
-/************************************************************************/
-
-TigerZeroCellID::~TigerZeroCellID()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerZeroCellID::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerZeroCellID::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sZ",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTTInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Set fields.                                                     */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTTInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerZeroCellID::CreateFeature( OGRFeature *poFeature )
-
-{
-    char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTTInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTTInfo->nRecordLength );
-
-    WriteFields( psRTTInfo, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRTTInfo->nRecordLength, FILE_CODE );
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 
-    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp b/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp
index 46fa635..b1c5396 100644
--- a/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerzipcodes.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerzipcodes.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerZipCodes, providing access to .RT6 files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerzipcodes.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerzipcodes.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE "6"
 
-static TigerFieldInfo rt6_fields[] = {
+static const TigerFieldInfo rt6_fields[] = {
   // fieldname    fmt  type OFTType     beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,    0,   0,   8,       1,   0,     0 },
   { "TLID",       'R', 'N', OFTInteger,   6,  15,  10,       1,   1,     1 },
@@ -50,7 +50,7 @@ static TigerFieldInfo rt6_fields[] = {
   { "ZIPL",       'L', 'N', OFTInteger,  67,  71,   5,       1,   1,     1 },
   { "ZIPR",       'L', 'N', OFTInteger,  72,  76,   5,       1,   1,     1 }
 };
-static TigerRecordInfo rt6_info =
+static const TigerRecordInfo rt6_info =
   {
     rt6_fields,
     sizeof(rt6_fields) / sizeof(TigerFieldInfo),
@@ -62,116 +62,17 @@ static TigerRecordInfo rt6_info =
 /************************************************************************/
 
 TigerZipCodes::TigerZipCodes( OGRTigerDataSource * poDSIn,
-                                  const char * pszPrototypeModule )
+                                  const char * pszPrototypeModule ) : TigerFileBase(&rt6_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "ZipCodes" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRT6Info = &rt6_info;
-
-    /* -------------------------------------------------------------------- */
-    /*      Fields from type 5 record.                                      */
-    /* -------------------------------------------------------------------- */
-
-    AddFieldDefns( psRT6Info, poFeatureDefn );
-}
-
-/************************************************************************/
-/*                        ~TigerZipCodes()                         */
-/************************************************************************/
-
-TigerZipCodes::~TigerZipCodes()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerZipCodes::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, "6" ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerZipCodes::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %s6",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %s6",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRT6Info->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %s6",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
     /* -------------------------------------------------------------------- */
-    /*      Set fields.                                                     */
+    /*      Fields from type 6 record.                                      */
     /* -------------------------------------------------------------------- */
 
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRT6Info, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerZipCodes::CreateFeature( OGRFeature *poFeature )
-
-{
-  char  szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRT6Info->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRT6Info->nRecordLength );
-
-    WriteFields( psRT6Info, poFeature, szRecord);
-
-    WriteRecord( szRecord, psRT6Info->nRecordLength, FILE_CODE );
-
-    return OGRERR_NONE;
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp b/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp
index fd3eee3..d109f1f 100644
--- a/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tigerzipplus4.cpp 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: tigerzipplus4.cpp 22961 2011-08-20 17:09:59Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerZipPlus4, providing access to .RTZ files.
@@ -30,11 +30,11 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerzipplus4.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: tigerzipplus4.cpp 22961 2011-08-20 17:09:59Z rouault $");
 
 #define FILE_CODE       "Z"
 
-static TigerFieldInfo rtZ_fields[] = {
+static const TigerFieldInfo rtZ_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
   { "TLID",       'R', 'N', OFTInteger,    6,  15,  10,       1,   1,     1 },
@@ -42,7 +42,7 @@ static TigerFieldInfo rtZ_fields[] = {
   { "ZIP4L",      'L', 'N', OFTInteger,   19,  22,   4,       1,   1,     1 },
   { "ZIP4R",      'L', 'N', OFTInteger,   23,  26,   4,       1,   1,     1 }
 };
-static TigerRecordInfo rtZ_info =
+static const TigerRecordInfo rtZ_info =
   {
     rtZ_fields,
     sizeof(rtZ_fields) / sizeof(TigerFieldInfo),
@@ -54,116 +54,18 @@ static TigerRecordInfo rtZ_info =
 /************************************************************************/
 
 TigerZipPlus4::TigerZipPlus4( OGRTigerDataSource * poDSIn,
-                              const char * pszPrototypeModule )
+                              const char * pszPrototypeModule ) : TigerFileBase(&rtZ_info, FILE_CODE)
 
 {
-    OGRFieldDefn        oField("",OFTInteger);
-
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "ZipPlus4" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    psRTZInfo = &rtZ_info;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from type Z record.                                      */
     /* -------------------------------------------------------------------- */
 
-    AddFieldDefns( psRTZInfo, poFeatureDefn );
-
-}
-
-/************************************************************************/
-/*                           ~TigerZipPlus4()                           */
-/************************************************************************/
-
-TigerZipPlus4::~TigerZipPlus4()
-
-{
-}
-
-/************************************************************************/
-/*                             SetModule()                              */
-/************************************************************************/
-
-int TigerZipPlus4::SetModule( const char * pszModule )
-
-{
-    if( !OpenFile( pszModule, FILE_CODE ) )
-        return FALSE;
-
-    EstablishFeatureCount();
-    
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *TigerZipPlus4::GetFeature( int nRecordId )
-
-{
-    char        achRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( nRecordId < 0 || nRecordId >= nFeatures )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Request for out-of-range feature %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read the raw record data from the file.                         */
-/* -------------------------------------------------------------------- */
-    if( fpPrimary == NULL )
-        return NULL;
-
-    if( VSIFSeek( fpPrimary, nRecordId * nRecordLength, SEEK_SET ) != 0 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to %d of %sZ",
-                  nRecordId * nRecordLength, pszModule );
-        return NULL;
-    }
-
-    if( VSIFRead( achRecord, psRTZInfo->nRecordLength, 1, fpPrimary ) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read record %d of %sZ",
-                  nRecordId, pszModule );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Set fields.                                                     */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
-
-    SetFields( psRTZInfo, poFeature, achRecord );
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                           CreateFeature()                            */
-/************************************************************************/
-
-OGRErr TigerZipPlus4::CreateFeature( OGRFeature *poFeature )
-
-{
-  char        szRecord[OGR_TIGER_RECBUF_LEN];
-
-    if( !SetWriteModule( FILE_CODE, psRTZInfo->nRecordLength+2, poFeature ) )
-        return OGRERR_FAILURE;
-
-    memset( szRecord, ' ', psRTZInfo->nRecordLength );
-
-    WriteFields( psRTZInfo, poFeature, szRecord );
-
-    WriteRecord( szRecord, psRTZInfo->nRecordLength, FILE_CODE );
+    AddFieldDefns( psRTInfo, poFeatureDefn );
 
-    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/vfk/ogr_vfk.h b/ogr/ogrsf_frmts/vfk/ogr_vfk.h
index 1dac646..cb18344 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 18483 2010-01-08 23:59:26Z mloskot $
+ * $Id: ogr_vfk.h 23423 2011-11-26 18:40:30Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VFK driver.
@@ -100,7 +100,7 @@ private:
     IVFKReader    *poReader;
 
     /* private methods */
-    OGRVFKLayer   *CreateLayer(const VFKDataBlock *);
+    OGRVFKLayer   *CreateLayerFromBlock(const VFKDataBlock *);
 
 public:
     OGRVFKDataSource();
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
index f328aab..61414fb 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvfkdatasource.cpp 18529 2010-01-12 00:10:56Z mloskot $
+ * $Id: ogrvfkdatasource.cpp 23423 2011-11-26 18:40:30Z rouault $
  *
  * 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 18529 2010-01-12 00:10:56Z mloskot $");
+CPL_CVSID("$Id: ogrvfkdatasource.cpp 23423 2011-11-26 18:40:30Z rouault $");
 
 /*!
   \brief OGRVFKDataSource constructor
@@ -135,7 +135,7 @@ int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
     papoLayers = (OGRVFKLayer **) CPLCalloc(sizeof(OGRVFKLayer *), poReader->GetDataBlockCount());
     
     for (int iLayer = 0; iLayer < poReader->GetDataBlockCount(); iLayer++) {
-        papoLayers[iLayer] = CreateLayer(poReader->GetDataBlock(iLayer));
+        papoLayers[iLayer] = CreateLayerFromBlock(poReader->GetDataBlock(iLayer));
 	nLayers++;
     }
     
@@ -179,7 +179,7 @@ int OGRVFKDataSource::TestCapability(const char * pszCap)
   \return poiter to OGRVFKLayer instance
   \return NULL on error
 */
-OGRVFKLayer *OGRVFKDataSource::CreateLayer(const VFKDataBlock *poDataBlock)
+OGRVFKLayer *OGRVFKDataSource::CreateLayerFromBlock(const VFKDataBlock *poDataBlock)
 {
     OGRVFKLayer *poLayer;
 
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
index a8bd534..6984c27 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkdatablock.cpp 20142 2010-07-27 18:43:49Z rouault $
+ * $Id: vfkdatablock.cpp 22873 2011-08-06 20:33:55Z rouault $
  *
  * Project:  VFK Reader - Data block definition
  * Purpose:  Implements VFKDataBlock class.
@@ -890,7 +890,7 @@ long VFKDataBlock::LoadGeometry()
     end = clock();
     
     CPLDebug("OGR_VFK", "VFKDataBlock::LoadGeometry(): name=%s nfeatures=%ld sec=%ld",
-	     m_pszName, nfeatures, (end - start) / CLOCKS_PER_SEC);
+	     m_pszName, nfeatures, (long)((end - start) / CLOCKS_PER_SEC));
     
     return nfeatures;
 }
diff --git a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
index 9caeb9a..5ede9dd 100644
--- a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkfeature.cpp 19643 2010-05-08 21:56:18Z rouault $
+ * $Id: vfkfeature.cpp 21684 2011-02-11 22:14:01Z warmerdam $
  *
  * Project:  VFK Reader - Feature definition
  * Purpose:  Implements VFKFeature class.
@@ -237,7 +237,7 @@ bool VFKFeature::LoadGeometry()
         idxBp_Id = m_poDataBlock->GetPropertyIndex("BP_ID");
         idxPCB   = m_poDataBlock->GetPropertyIndex("PORADOVE_CISLO_BODU");
         if (idxId < 0 || idxBp_Id < 0 || idxPCB < 0)
-            return -1;
+            return false;
         
         poLine = this;
         while (TRUE)
diff --git a/ogr/ogrsf_frmts/vrt/ogr_vrt.h b/ogr/ogrsf_frmts/vrt/ogr_vrt.h
index ced7ff6..f47907e 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 20475 2010-08-28 12:45:57Z rouault $
+ * $Id: ogr_vrt.h 23575 2011-12-14 20:24:08Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VRT driver.
@@ -30,11 +30,14 @@
 #ifndef _OGR_VRT_H_INCLUDED
 #define _OGR_VRT_H_INCLUDED
 
-#include <vector>
 #include "ogrsf_frmts.h"
 #include "cpl_error.h"
 #include "cpl_minixml.h"
 
+#include <vector>
+#include <string>
+#include <set>
+
 typedef enum { 
     VGS_None,
     VGS_Direct,
@@ -48,9 +51,19 @@ typedef enum {
 /*                            OGRVRTLayer                                */
 /************************************************************************/
 
+class OGRVRTDataSource;
+
 class OGRVRTLayer : public OGRLayer
 {
   protected:
+    OGRVRTDataSource*   poDS;
+
+    int                 bHasFullInitialized;
+    CPLString           osName;
+    OGRwkbGeometryType  eGeomType;
+    CPLXMLNode         *psLTree;
+    CPLString           osVRTDirectory;
+
     OGRFeatureDefn      *poFeatureDefn;
 
     OGRDataSource       *poSrcDS;
@@ -72,7 +85,7 @@ class OGRVRTLayer : public OGRLayer
     int                 iStyleField; // -1 means pass through.
 
     // Geometry interpretation related.
-    OGRVRTGeometryStyle eGeometryType;
+    OGRVRTGeometryStyle eGeometryStyle;
     
     int                 iGeomField; 
 
@@ -94,14 +107,24 @@ class OGRVRTLayer : public OGRLayer
 
     int                 ResetSourceReading();
 
+    int                 FullInitialize();
+
   public:
-                        OGRVRTLayer();
+                        OGRVRTLayer(OGRVRTDataSource* poDSIn);
     virtual             ~OGRVRTLayer();
 
-    virtual int         Initialize( CPLXMLNode *psLTree, 
+    int                FastInitialize( CPLXMLNode *psLTree,
                                     const char *pszVRTDirectory,
                                     int bUpdate);
 
+    virtual const char  *GetName() { return osName.c_str(); }
+    virtual OGRwkbGeometryType GetGeomType();
+
+/* -------------------------------------------------------------------- */
+/*      Caution : all the below methods should care of calling          */
+/*      FullInitialize() if not already done                            */
+/* -------------------------------------------------------------------- */
+    
     virtual void        ResetReading();
     virtual OGRFeature *GetNextFeature();
 
@@ -109,7 +132,7 @@ class OGRVRTLayer : public OGRLayer
 
     virtual OGRErr      SetNextByIndex( long nIndex );
 
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *GetLayerDefn();
 
     virtual OGRSpatialReference *GetSpatialRef();
 
@@ -143,6 +166,12 @@ class OGRVRTDataSource : public OGRDataSource
     
     char               *pszName;
 
+    CPLXMLNode         *psTree;
+
+    int                 nCallLevel;
+
+    std::set<std::string> aosOtherDSNameSet;
+
   public:
                         OGRVRTDataSource();
                         ~OGRVRTDataSource();
@@ -155,6 +184,14 @@ class OGRVRTDataSource : public OGRDataSource
     OGRLayer            *GetLayer( int );
 
     int                 TestCapability( const char * );
+
+    /* Anti-recursion mechanism for standard Open */
+    void                SetCallLevel(int nCallLevelIn) { nCallLevel = nCallLevelIn; }
+    int                 GetCallLevel() { return nCallLevel; }
+
+    /* Anti-recursion mechanism for shared Open */
+    void                AddForbiddenNames(const char* pszOtherDSName);
+    int                 IsInForbiddenNames(const char* pszOtherDSName);
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
index d6d3187..6a2804b 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtdatasource.cpp 17506 2009-08-02 17:09:10Z rouault $
+ * $Id: ogrvrtdatasource.cpp 23575 2011-12-14 20:24:08Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDataSource class.
@@ -31,7 +31,8 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvrtdatasource.cpp 17506 2009-08-02 17:09:10Z rouault $");
+CPL_CVSID("$Id: ogrvrtdatasource.cpp 23575 2011-12-14 20:24:08Z rouault $");
+
 /************************************************************************/
 /*                          OGRVRTDataSource()                          */
 /************************************************************************/
@@ -42,6 +43,8 @@ OGRVRTDataSource::OGRVRTDataSource()
     pszName = NULL;
     papoLayers = NULL;
     nLayers = 0;
+    psTree = NULL;
+    nCallLevel = 0;
 }
 
 /************************************************************************/
@@ -59,6 +62,9 @@ OGRVRTDataSource::~OGRVRTDataSource()
         delete papoLayers[i];
     
     CPLFree( papoLayers );
+
+    if( psTree != NULL)
+        CPLDestroyXMLNode( psTree );
 }
 
 /************************************************************************/
@@ -71,6 +77,8 @@ int OGRVRTDataSource::Initialize( CPLXMLNode *psTree, const char *pszNewName,
 {
     CPLAssert( nLayers == 0 );
 
+    this->psTree = psTree;
+
 /* -------------------------------------------------------------------- */
 /*      Set name, and capture the directory path so we can use it       */
 /*      for relative datasources.                                       */
@@ -95,9 +103,9 @@ int OGRVRTDataSource::Initialize( CPLXMLNode *psTree, const char *pszNewName,
 /* -------------------------------------------------------------------- */
         OGRVRTLayer  *poLayer;
         
-        poLayer = new OGRVRTLayer();
+        poLayer = new OGRVRTLayer(this);
         
-        if( !poLayer->Initialize( psLTree, pszVRTDirectory, bUpdate ) )
+        if( !poLayer->FastInitialize( psLTree, pszVRTDirectory, bUpdate ) )
         {
             CPLFree( pszVRTDirectory );
             delete poLayer;
@@ -138,3 +146,21 @@ OGRLayer *OGRVRTDataSource::GetLayer( int iLayer )
     else
         return papoLayers[iLayer];
 }
+
+/************************************************************************/
+/*                         AddForbiddenNames()                          */
+/************************************************************************/
+
+void OGRVRTDataSource::AddForbiddenNames(const char* pszOtherDSName)
+{
+    aosOtherDSNameSet.insert(pszOtherDSName);
+}
+
+/************************************************************************/
+/*                         IsInForbiddenNames()                         */
+/************************************************************************/
+
+int OGRVRTDataSource::IsInForbiddenNames(const char* pszOtherDSName)
+{
+    return aosOtherDSNameSet.find(pszOtherDSName) != aosOtherDSNameSet.end();
+}
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
index 576fa02..a514bff 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtdriver.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: ogrvrtdriver.cpp 23575 2011-12-14 20:24:08Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDriver class.
@@ -30,7 +30,7 @@
 #include "ogr_vrt.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrvrtdriver.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: ogrvrtdriver.cpp 23575 2011-12-14 20:24:08Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRVRTDriver()                            */
@@ -83,11 +83,6 @@ OGRDataSource *OGRVRTDriver::Open( const char * pszFilename,
         VSILFILE *fp;
         char achHeader[18];
 
-        VSIStatBufL sStatBuf;
-        if (VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0 ||
-            VSI_ISDIR(sStatBuf.st_mode))
-            return FALSE;
-
         fp = VSIFOpenL( pszFilename, "rb" );
 
         if( fp == NULL )
@@ -105,13 +100,19 @@ OGRDataSource *OGRVRTDriver::Open( const char * pszFilename,
             return NULL;
         }
 
+        VSIStatBufL sStatBuf;
+        if ( VSIStatL( pszFilename, &sStatBuf ) != 0 ||
+             sStatBuf.st_size > 1024 * 1024 )
+        {
+            VSIFCloseL( fp );
+            return NULL;
+        }
+
 /* -------------------------------------------------------------------- */
 /*      It is the right file, now load the full XML definition.         */
 /* -------------------------------------------------------------------- */
-        int nLen;
+        int nLen = (int) sStatBuf.st_size;
 
-        VSIFSeekL( fp, 0, SEEK_END );
-        nLen = (int) VSIFTellL( fp );
         VSIFSeekL( fp, 0, SEEK_SET );
 
         pszXML = (char *) VSIMalloc(nLen+1);
@@ -144,15 +145,14 @@ OGRDataSource *OGRVRTDriver::Open( const char * pszFilename,
 /*      Create a virtual datasource configured based on this XML input. */
 /* -------------------------------------------------------------------- */
     poDS = new OGRVRTDataSource();
+    poDS->SetDriver(this);
+    /* psTree is owned by poDS */
     if( !poDS->Initialize( psTree, pszFilename, bUpdate ) )
     {
-        CPLDestroyXMLNode( psTree );
         delete poDS;
         return NULL;
     }
 
-    CPLDestroyXMLNode( psTree );
-
     return poDS;
 }
 
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
index c69b80b..9bf7765 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrvrtlayer.cpp 20827 2010-10-13 20:57:50Z rouault $
+ * $Id: ogrvrtlayer.cpp 23575 2011-12-14 20:24:08Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTLayer class.
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrvrtlayer.cpp 20827 2010-10-13 20:57:50Z rouault $");
+CPL_CVSID("$Id: ogrvrtlayer.cpp 23575 2011-12-14 20:24:08Z rouault $");
 
 typedef struct 
 {
@@ -58,9 +58,15 @@ static const OGRGeomTypeName asGeomTypeNames[] = { /* 25D versions are implicit
 /*                            OGRVRTLayer()                             */
 /************************************************************************/
 
-OGRVRTLayer::OGRVRTLayer()
+OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource* poDSIn)
 
 {
+    poDS = poDSIn;
+
+    bHasFullInitialized = FALSE;
+    eGeomType = wkbUnknown;
+    psLTree = NULL;
+
     poFeatureDefn = NULL;
     poSrcLayer = NULL;
     poSRS = NULL;
@@ -70,7 +76,7 @@ OGRVRTLayer::OGRVRTLayer()
     iFIDField = -1;
     iStyleField = -1;
 
-    eGeometryType = VGS_Direct;
+    eGeometryStyle = VGS_Direct;
     iGeomField = iGeomXField = iGeomYField = iGeomZField = -1;
 
     pszAttrFilter = NULL;
@@ -122,14 +128,17 @@ OGRVRTLayer::~OGRVRTLayer()
 }
 
 /************************************************************************/
-/*                             Initialize()                             */
+/*                         FastInitialize()                             */
 /************************************************************************/
 
-int OGRVRTLayer::Initialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
+int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
                              int bUpdate)
 
 {
-    
+    this->psLTree = psLTree;
+    this->bUpdate = bUpdate;
+    osVRTDirectory = pszVRTDirectory;
+
     if( !EQUAL(psLTree->pszValue,"OGRVRTLayer") )
         return FALSE;
 
@@ -145,7 +154,86 @@ int OGRVRTLayer::Initialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
         return FALSE;
     }
 
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    osName = pszLayerName;
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a fixed geometry type?  If so use it                 */
+/* -------------------------------------------------------------------- */
+     const char *pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
+     if( pszGType != NULL )
+     {
+         int iType;
+
+         for( iType = 0; asGeomTypeNames[iType].pszName != NULL; iType++ )
+         {
+             if( EQUALN(pszGType, asGeomTypeNames[iType].pszName,
+                        strlen(asGeomTypeNames[iType].pszName)) )
+             {
+                 eGeomType = asGeomTypeNames[iType].eType;
+
+                 if( strstr(pszGType,"25D") != NULL )
+                     eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
+                 break;
+             }
+         }
+
+         if( asGeomTypeNames[iType].pszName == NULL )
+         {
+             CPLError( CE_Failure, CPLE_AppDefined,
+                       "GeometryType %s not recognised.",
+                       pszGType );
+             return FALSE;
+         }
+     }
+
+/* -------------------------------------------------------------------- */
+/*      Apply a spatial reference system if provided                    */
+/* -------------------------------------------------------------------- */
+     const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
+     if( pszLayerSRS != NULL )
+     {
+         if( EQUAL(pszLayerSRS,"NULL") )
+             poSRS = NULL;
+         else
+         {
+             OGRSpatialReference oSRS;
+
+             if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE )
+             {
+                 CPLError( CE_Failure, CPLE_AppDefined,
+                           "Failed to import LayerSRS `%s'.", pszLayerSRS );
+                 return FALSE;
+             }
+             poSRS = oSRS.Clone();
+         }
+     }
+
+     return TRUE;
+}
+
+/************************************************************************/
+/*                         FullInitialize()                             */
+/************************************************************************/
+
+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;
+
+    if (bHasFullInitialized)
+        return TRUE;
+
+    bHasFullInitialized = TRUE;
+
+    poFeatureDefn = new OGRFeatureDefn( osName );
     poFeatureDefn->Reference();
 
 /* -------------------------------------------------------------------- */
@@ -158,15 +246,15 @@ int OGRVRTLayer::Initialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
     if( pszSrcDSName == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Missing SrcDataSource for layer %s.", pszLayerName );
-        return FALSE;
+                  "Missing SrcDataSource for layer %s.", osName.c_str() );
+        goto error;
     }
 
     if( CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcDataSource.relativetoVRT", 
                                        "0")) )
     {
         pszSrcDSName = CPLStrdup(
-            CPLProjectRelativeFilename( pszVRTDirectory, pszSrcDSName ) );
+            CPLProjectRelativeFilename( osVRTDirectory, pszSrcDSName ) );
     }
     else
     {
@@ -179,7 +267,7 @@ int OGRVRTLayer::Initialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
 /*      control our shared setting with an attribute on the             */
 /*      datasource element.                                             */
 /* -------------------------------------------------------------------- */
-    const char *pszSharedSetting = CPLGetXMLValue( psLTree, 
+    pszSharedSetting = CPLGetXMLValue( psLTree,
                                                    "SrcDataSource.shared",
                                                    NULL );
     if( pszSharedSetting == NULL )
@@ -204,13 +292,47 @@ try_again:
     if( EQUAL(pszSrcDSName,"@dummy@") )
     {
         OGRSFDriver *poMemDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("Memory");
-        poSrcDS = poMemDriver->CreateDataSource( "@dummy@" );
-        poSrcDS->CreateLayer( "@dummy@" );
+        if (poMemDriver != NULL)
+        {
+            poSrcDS = poMemDriver->CreateDataSource( "@dummy@" );
+            poSrcDS->CreateLayer( "@dummy@" );
+        }
     }
     else if( bSrcDSShared )
-        poSrcDS = poReg->OpenShared( pszSrcDSName, bUpdate, NULL );
+    {
+        if (poDS->IsInForbiddenNames(pszSrcDSName))
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cyclic VRT opening detected !");
+        }
+        else
+        {
+            poSrcDS = poReg->OpenShared( pszSrcDSName, bUpdate, NULL );
+            /* Is it a VRT datasource ? */
+            if (poSrcDS != NULL && poSrcDS->GetDriver() == poDS->GetDriver())
+            {
+                OGRVRTDataSource* poVRTSrcDS = (OGRVRTDataSource*)poSrcDS;
+                poVRTSrcDS->AddForbiddenNames(poDS->GetName());
+            }
+        }
+    }
     else
-        poSrcDS = poReg->Open( pszSrcDSName, bUpdate, NULL );
+    {
+        if (poDS->GetCallLevel() < 32)
+        {
+            poSrcDS = poReg->Open( pszSrcDSName, bUpdate, NULL );
+            /* Is it a VRT datasource ? */
+            if (poSrcDS != NULL && poSrcDS->GetDriver() == poDS->GetDriver())
+            {
+                OGRVRTDataSource* poVRTSrcDS = (OGRVRTDataSource*)poSrcDS;
+                poVRTSrcDS->SetCallLevel(poDS->GetCallLevel() + 1);
+            }
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Trying to open a VRT from a VRT from a VRT from ... [32 times] a VRT !");
+        }
+    }
 
     if( poSrcDS == NULL ) 
     {
@@ -227,7 +349,7 @@ try_again:
                       "Failed to open datasource `%s'.", 
                       pszSrcDSName );
         CPLFree( pszSrcDSName );
-        return FALSE;
+        goto error;
     }
 
     this->bUpdate = bUpdate;
@@ -235,7 +357,7 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Is this layer derived from an SQL query result?                 */
 /* -------------------------------------------------------------------- */
-    const char *pszSQL = CPLGetXMLValue( psLTree, "SrcSQL", NULL );
+    pszSQL = CPLGetXMLValue( psLTree, "SrcSQL", NULL );
 
     if( pszSQL != NULL )
     {
@@ -244,8 +366,8 @@ try_again:
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "SQL statement failed, or returned no layer result:\n%s",
-                      pszSQL );					      
-            return FALSE;
+                      pszSQL );
+            goto error;
         }
         bSrcLayerFromSQL = TRUE;
     }
@@ -256,7 +378,7 @@ try_again:
     if( poSrcLayer == NULL )
     {
         const char *pszSrcLayerName = CPLGetXMLValue( psLTree, "SrcLayer", 
-                                                      pszLayerName );
+                                                      osName );
         
         poSrcLayer = poSrcDS->GetLayerByName( pszSrcLayerName );
         if( poSrcLayer == NULL )
@@ -265,77 +387,30 @@ try_again:
                   "Failed to find layer '%s' on datasource '%s'.", 
                       pszSrcLayerName, pszSrcDSName );
             CPLFree( pszSrcDSName );
-            return FALSE;
+            goto error;
         }
     }
         
     CPLFree( pszSrcDSName );
 
 /* -------------------------------------------------------------------- */
-/*      Do we have a fixed geometry type?  If so use it, otherwise      */
-/*      derive from the source layer.                                   */
+/*      Do we have a fixed geometry type?  If not derive from the       */
+/*      source layer.                                                   */
 /* -------------------------------------------------------------------- */
-     const char *pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
-     
-     if( pszGType != NULL )
+     pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
+     if( pszGType == NULL )
      {
-         int iType;
-
-         for( iType = 0; asGeomTypeNames[iType].pszName != NULL; iType++ )
-         {
-             if( EQUALN(pszGType, asGeomTypeNames[iType].pszName, 
-                        strlen(asGeomTypeNames[iType].pszName)) )
-             {
-                 poFeatureDefn->SetGeomType( asGeomTypeNames[iType].eType );
-
-                 if( strstr(pszGType,"25D") != NULL )
-                     poFeatureDefn->SetGeomType( 
-                         (OGRwkbGeometryType)
-                         (poFeatureDefn->GetGeomType() | wkb25DBit) );
-                 break;
-             }
-         }
-
-         if( asGeomTypeNames[iType].pszName == NULL )
-         {
-             CPLError( CE_Failure, CPLE_AppDefined, 
-                       "GeometryType %s not recognised.", 
-                       pszGType );
-             return FALSE;
-         }
-     }
-
-     else
-     {
-         poFeatureDefn->SetGeomType(poSrcLayer->GetLayerDefn()->GetGeomType());
+         eGeomType = poSrcLayer->GetLayerDefn()->GetGeomType();
      }
+     poFeatureDefn->SetGeomType(eGeomType);
 
 /* -------------------------------------------------------------------- */
-/*      Apply a spatial reference system if provided, otherwise copy    */
-/*      from source.                                                    */
+/*      Copy spatial reference system from source if not provided       */
 /* -------------------------------------------------------------------- */
-     const char *pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
-
-     if( pszLayerSRS != NULL )
-     {
-         if( EQUAL(pszLayerSRS,"NULL") )
-             poSRS = NULL;
-         else
-         {
-             OGRSpatialReference oSRS;
-
-             if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE )
-             {
-                 CPLError( CE_Failure, CPLE_AppDefined, 
-                           "Failed to import LayerSRS `%s'.", pszLayerSRS );
-                 return FALSE;
-             }
-             poSRS = oSRS.Clone();
-         }
-     }
-
-     else
+     pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
+     if( pszLayerSRS == NULL )
      {
+         CPLAssert(poSRS == NULL);
          if( poSrcLayer->GetSpatialRef() != NULL )
              poSRS = poSrcLayer->GetSpatialRef()->Clone();
          else
@@ -345,23 +420,22 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Handle GeometryField.                                           */
 /* -------------------------------------------------------------------- */
-     const char *pszEncoding;
 
      pszEncoding = CPLGetXMLValue( psLTree,"GeometryField.encoding", "direct");
 
      if( EQUAL(pszEncoding,"Direct") )
-         eGeometryType = VGS_Direct;
+         eGeometryStyle = VGS_Direct;
      else if( EQUAL(pszEncoding,"None") )
-         eGeometryType = VGS_None;
+         eGeometryStyle = VGS_None;
      else if( EQUAL(pszEncoding,"WKT") )
-         eGeometryType = VGS_WKT;
+         eGeometryStyle = VGS_WKT;
      else if( EQUAL(pszEncoding,"WKB") )
-         eGeometryType = VGS_WKB;
+         eGeometryStyle = VGS_WKB;
      else if( EQUAL(pszEncoding,"Shape") )
-         eGeometryType = VGS_Shape;
+         eGeometryStyle = VGS_Shape;
      else if( EQUAL(pszEncoding,"PointFromColumns") )
      {
-         eGeometryType = VGS_PointFromColumns;
+         eGeometryStyle = VGS_PointFromColumns;
          bUseSpatialSubquery = 
              CSLTestBoolean(
                  CPLGetXMLValue(psLTree, 
@@ -379,19 +453,19 @@ try_again:
          {
              CPLError( CE_Failure, CPLE_AppDefined, 
                        "Unable to identify source X or Y field for PointFromColumns encoding." );
-             return FALSE;
+             goto error;
          }
      }
      else
      {
          CPLError( CE_Failure, CPLE_AppDefined, 
                    "encoding=\"%s\" not recognised.", pszEncoding );
-         return FALSE;
+         goto error;
      }
 
-     if( eGeometryType == VGS_WKT 
-         || eGeometryType == VGS_WKB 
-         || eGeometryType == VGS_Shape )
+     if( eGeometryStyle == VGS_WKT
+         || eGeometryStyle == VGS_WKB
+         || eGeometryStyle == VGS_Shape )
      {
          const char *pszFieldName = 
              CPLGetXMLValue( psLTree, "GeometryField.field", "missing" );
@@ -403,14 +477,14 @@ try_again:
              CPLError( CE_Failure, CPLE_AppDefined, 
                        "Unable to identify source field '%s' for geometry.",
                        pszFieldName );
-             return FALSE;
+             goto error;
          }
      }
 
 /* -------------------------------------------------------------------- */
 /*      Figure out what should be used as an FID.                       */
 /* -------------------------------------------------------------------- */
-     const char *pszFIDFieldName = CPLGetXMLValue( psLTree, "FID", NULL );
+     pszFIDFieldName = CPLGetXMLValue( psLTree, "FID", NULL );
 
      if( pszFIDFieldName != NULL )
      {
@@ -421,14 +495,14 @@ try_again:
              CPLError( CE_Failure, CPLE_AppDefined, 
                        "Unable to identify FID field '%s'.",
                        pszFIDFieldName );
-             return FALSE;
+             goto error;
          }
      }
 
 /* -------------------------------------------------------------------- */
 /*      Figure out what should be used as a Style                       */
 /* -------------------------------------------------------------------- */
-     const char *pszStyleFieldName = CPLGetXMLValue( psLTree, "Style", NULL );
+     pszStyleFieldName = CPLGetXMLValue( psLTree, "Style", NULL );
 
      if( pszStyleFieldName != NULL )
      {
@@ -439,14 +513,13 @@ try_again:
              CPLError( CE_Failure, CPLE_AppDefined, 
                        "Unable to identify Style field '%s'.",
                        pszStyleFieldName );
-             return FALSE;
+             goto error;
          }
      }
 
 /* ==================================================================== */
 /*      Search for schema definitions in the VRT.                       */
 /* ==================================================================== */
-     CPLXMLNode *psChild; 
      for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
      {
          if( psChild->eType == CXT_Element && EQUAL(psChild->pszValue,"Field") )
@@ -459,7 +532,7 @@ try_again:
              {
                  CPLError( CE_Failure, CPLE_AppDefined, 
                            "Unable to identify Field name." );
-                 return FALSE;
+                 goto error;
              }
 
              OGRFieldDefn oFieldDefn( pszName, OFTString );
@@ -488,7 +561,7 @@ try_again:
                      CPLError( CE_Failure, CPLE_AppDefined, 
                                "Unable to identify Field type '%s'.",
                                pszArg );
-                     return FALSE;
+                     goto error;
                  }
              }
 
@@ -524,7 +597,7 @@ try_again:
                      CPLError( CE_Failure, CPLE_AppDefined,
                                "Unable to find source field '%s'.",
                                pszArg );
-                     return FALSE;
+                     goto error;
                  }
              }
              
@@ -583,7 +656,7 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Do we have a SrcRegion?                                         */
 /* -------------------------------------------------------------------- */
-     const char *pszSrcRegion = CPLGetXMLValue( psLTree, "SrcRegion", NULL );
+     pszSrcRegion = CPLGetXMLValue( psLTree, "SrcRegion", NULL );
      if( pszSrcRegion != NULL )
      {
         OGRGeometryFactory::createFromWkt( (char**) &pszSrcRegion, NULL, &poSrcRegion );
@@ -599,6 +672,13 @@ try_again:
      }
 
      return TRUE;
+
+error:
+    if( poFeatureDefn )
+        poFeatureDefn->Release();
+    poFeatureDefn = new OGRFeatureDefn( osName );
+    poFeatureDefn->Reference();
+    return FALSE;
 }
 
 /************************************************************************/
@@ -625,7 +705,7 @@ int OGRVRTLayer::ResetSourceReading()
 /* -------------------------------------------------------------------- */
     char *pszFilter = NULL;
     if( (m_poFilterGeom || poSrcRegion) && bUseSpatialSubquery &&
-         eGeometryType == VGS_PointFromColumns )
+         eGeometryStyle == VGS_PointFromColumns )
     {
         const char *pszXField, *pszYField;
 
@@ -715,7 +795,7 @@ int OGRVRTLayer::ResetSourceReading()
 /*      Clear spatial filter (to be safe) for non direct geometries     */
 /*      and reset reading.            */
 /* -------------------------------------------------------------------- */
-    if (eGeometryType == VGS_Direct)
+    if (eGeometryStyle == VGS_Direct)
     {
         if (poSrcRegion == NULL)
             poSrcLayer->SetSpatialFilter( m_poFilterGeom );
@@ -752,6 +832,9 @@ int OGRVRTLayer::ResetSourceReading()
 OGRFeature *OGRVRTLayer::GetNextFeature()
 
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return NULL;
+
     if( bNeedReset )
     {
         if( !ResetSourceReading() )
@@ -772,7 +855,7 @@ OGRFeature *OGRVRTLayer::GetNextFeature()
         if( poFeature == NULL )
             return NULL;
 
-        if( (eGeometryType == VGS_Direct || m_poFilterGeom == NULL
+        if( (eGeometryStyle == VGS_Direct || m_poFilterGeom == NULL
             || FilterGeometry( poFeature->GetGeometryRef() ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
@@ -823,11 +906,11 @@ retry:
 /*      Handle the geometry.  Eventually there will be several more     */
 /*      supported options.                                              */
 /* -------------------------------------------------------------------- */
-    if( eGeometryType == VGS_None )
+    if( eGeometryStyle == VGS_None )
     {
         /* do nothing */
     }
-    else if( eGeometryType == VGS_WKT )
+    else if( eGeometryStyle == VGS_WKT )
     {
         char *pszWKT = (char *) poSrcFeat->GetFieldAsString( iGeomField );
         
@@ -843,7 +926,7 @@ retry:
             poDstFeat->SetGeometryDirectly( poGeom );
         }
     }
-    else if( eGeometryType == VGS_WKB )
+    else if( eGeometryStyle == VGS_WKB )
     {
         int nBytes;
         GByte *pabyWKB;
@@ -873,7 +956,7 @@ retry:
         if( bNeedFree )
             CPLFree( pabyWKB );
     }
-    else if( eGeometryType == VGS_Shape )
+    else if( eGeometryStyle == VGS_Shape )
     {
         int nBytes;
         GByte *pabyWKB;
@@ -902,11 +985,11 @@ retry:
         if( bNeedFree )
             CPLFree( pabyWKB );
     }
-    else if( eGeometryType == VGS_Direct )
+    else if( eGeometryStyle == VGS_Direct )
     {
         poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
     }
-    else if( eGeometryType == VGS_PointFromColumns )
+    else if( eGeometryStyle == VGS_PointFromColumns )
     {
         if( iGeomZField != -1 )
             poDstFeat->SetGeometryDirectly( 
@@ -923,7 +1006,7 @@ retry:
 
     /* In the non direct case, we need to check that the geometry intersects the source */
     /* region before an optionnal clipping */
-    if( bUseSrcRegion && eGeometryType != VGS_Direct && poSrcRegion != NULL )
+    if( bUseSrcRegion && eGeometryStyle != VGS_Direct && poSrcRegion != NULL )
     {
         OGRGeometry* poGeom = poDstFeat->GetGeometryRef();
         if (poGeom != NULL && !poGeom->Intersects(poSrcRegion))
@@ -963,6 +1046,9 @@ retry:
         OGRFieldDefn *poDstDefn = poFeatureDefn->GetFieldDefn( iVRTField );
         OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
 
+        if( !poSrcFeat->IsFieldSet( anSrcField[iVRTField] ) )
+            continue;
+
         if( abDirectCopy[iVRTField] 
             && poDstDefn->GetType() == poSrcDefn->GetType() )
         {
@@ -993,6 +1079,9 @@ retry:
 OGRFeature *OGRVRTLayer::GetFeature( long nFeatureId )
 
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return NULL;
+
     bNeedReset = TRUE;
 
 /* -------------------------------------------------------------------- */
@@ -1038,6 +1127,9 @@ OGRFeature *OGRVRTLayer::GetFeature( long nFeatureId )
 
 OGRErr OGRVRTLayer::SetNextByIndex( long nIndex )
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return OGRERR_FAILURE;
+
     if (TestCapability(OLCFastSetNextByIndex))
         return poSrcLayer->SetNextByIndex(nIndex);
 
@@ -1074,11 +1166,11 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
 /*      Handle the geometry.  Eventually there will be several more     */
 /*      supported options.                                              */
 /* -------------------------------------------------------------------- */
-    if( eGeometryType == VGS_None )
+    if( eGeometryStyle == VGS_None )
     {
         /* do nothing */
     }
-    else if( eGeometryType == VGS_WKT )
+    else if( eGeometryStyle == VGS_WKT )
     {
         OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
         if (poGeom != NULL)
@@ -1091,7 +1183,7 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
             CPLFree(pszWKT);
         }
     }
-    else if( eGeometryType == VGS_WKB )
+    else if( eGeometryStyle == VGS_WKB )
     {
         OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
         if (poGeom != NULL)
@@ -1114,15 +1206,15 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
             CPLFree(pabyData);
         }
     }
-    else if( eGeometryType == VGS_Shape )
+    else if( eGeometryStyle == VGS_Shape )
     {
         CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
     }
-    else if( eGeometryType == VGS_Direct )
+    else if( eGeometryStyle == VGS_Direct )
     {
         poSrcFeat->SetGeometry( poVRTFeature->GetGeometryRef() );
     }
-    else if( eGeometryType == VGS_PointFromColumns )
+    else if( eGeometryStyle == VGS_PointFromColumns )
     {
         OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
         if (poGeom != NULL)
@@ -1189,6 +1281,9 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
 
 OGRErr OGRVRTLayer::CreateFeature( OGRFeature* poVRTFeature )
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return OGRERR_FAILURE;
+
     if(!bUpdate)
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1220,6 +1315,9 @@ OGRErr OGRVRTLayer::CreateFeature( OGRFeature* poVRTFeature )
 
 OGRErr OGRVRTLayer::SetFeature( OGRFeature* poVRTFeature )
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return OGRERR_FAILURE;
+
     if(!bUpdate)
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1247,6 +1345,9 @@ OGRErr OGRVRTLayer::SetFeature( OGRFeature* poVRTFeature )
 OGRErr OGRVRTLayer::DeleteFeature( long nFID )
 
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return OGRERR_FAILURE;
+
     if(!bUpdate )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -1271,6 +1372,9 @@ OGRErr OGRVRTLayer::DeleteFeature( long nFID )
 OGRErr OGRVRTLayer::SetAttributeFilter( const char *pszNewQuery )
 
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return OGRERR_FAILURE;
+
     if( bAttrFilterPassThrough )
     {
         CPLFree( pszAttrFilter );
@@ -1296,19 +1400,22 @@ OGRErr OGRVRTLayer::SetAttributeFilter( const char *pszNewQuery )
 int OGRVRTLayer::TestCapability( const char * pszCap )
 
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return FALSE;
+
     if ( EQUAL(pszCap,OLCFastFeatureCount) ||
          EQUAL(pszCap,OLCFastSetNextByIndex) )
-        return (eGeometryType == VGS_Direct ||
+        return (eGeometryStyle == VGS_Direct ||
                (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
                m_poAttrQuery == NULL &&
                poSrcLayer->TestCapability(pszCap);
 
     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return eGeometryType == VGS_Direct && m_poAttrQuery == NULL &&
+        return eGeometryStyle == VGS_Direct && m_poAttrQuery == NULL &&
                poSrcLayer->TestCapability(pszCap);
 
     else if ( EQUAL(pszCap,OLCFastGetExtent) )
-        return eGeometryType == VGS_Direct &&
+        return eGeometryStyle == VGS_Direct &&
                m_poAttrQuery == NULL &&
                poSrcRegion == NULL &&
                poSrcLayer->TestCapability(pszCap);
@@ -1334,6 +1441,12 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
 OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
 
 {
+    if (CPLGetXMLValue( psLTree, "LayerSRS", NULL ) != NULL)
+        return poSRS;
+
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return NULL;
+
     return poSRS;
 }
 
@@ -1343,12 +1456,16 @@ OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
 
 OGRErr OGRVRTLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 {
-    if ( eGeometryType == VGS_Direct &&
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return OGRERR_FAILURE;
+
+    if ( eGeometryStyle == VGS_Direct &&
          m_poAttrQuery == NULL &&
          poSrcRegion == NULL )
     {
         if( bNeedReset )
             ResetSourceReading();
+
         return poSrcLayer->GetExtent(psExtent, bForce);
     }
 
@@ -1362,12 +1479,16 @@ OGRErr OGRVRTLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 int OGRVRTLayer::GetFeatureCount( int bForce )
 
 {
-    if ((eGeometryType == VGS_Direct ||
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return 0;
+
+    if ((eGeometryStyle == VGS_Direct ||
          (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
          m_poAttrQuery == NULL )
     {
         if( bNeedReset )
             ResetSourceReading();
+
         return poSrcLayer->GetFeatureCount( bForce );
     }
     else
@@ -1381,7 +1502,10 @@ int OGRVRTLayer::GetFeatureCount( int bForce )
 
 void OGRVRTLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 {
-    if (eGeometryType == VGS_Direct)
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return;
+
+    if (eGeometryStyle == VGS_Direct)
         bNeedReset = TRUE;
     OGRLayer::SetSpatialFilter(poGeomIn);
 }
@@ -1392,6 +1516,9 @@ void OGRVRTLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 
 OGRErr OGRVRTLayer::SyncToDisk()
 {
+    if (!bHasFullInitialized) FullInitialize();
+    if (!poSrcLayer) return OGRERR_FAILURE;
+
     return poSrcLayer->SyncToDisk();
 }
 
@@ -1727,3 +1854,26 @@ OGRErr OGRVRTLayer::createFromShapeBin( GByte *pabyShape, OGRGeometry **ppoGeom,
 
     return OGRERR_FAILURE;
 }
+
+/************************************************************************/
+/*                            GetLayerDefn()                            */
+/************************************************************************/
+
+OGRFeatureDefn *OGRVRTLayer::GetLayerDefn()
+{
+    if (!bHasFullInitialized) FullInitialize();
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                             GetGeomType()                            */
+/************************************************************************/
+
+OGRwkbGeometryType OGRVRTLayer::GetGeomType()
+{
+    if (CPLGetXMLValue( psLTree, "GeometryType", NULL ) != NULL)
+        return eGeomType;
+
+    return GetLayerDefn()->GetGeomType();
+}
diff --git a/ogr/ogrsf_frmts/wfs/GNUmakefile b/ogr/ogrsf_frmts/wfs/GNUmakefile
index 8c3bf90..b16106f 100644
--- a/ogr/ogrsf_frmts/wfs/GNUmakefile
+++ b/ogr/ogrsf_frmts/wfs/GNUmakefile
@@ -11,4 +11,4 @@ default:	$(O_OBJ:.o=.$(OBJ_EXT))
 clean:
 	rm -f *.o $(O_OBJ)
 
-$(O_OBJ):	ogr_wfs.h
\ No newline at end of file
+$(O_OBJ):	ogr_wfs.h ../gml/gmlreader.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/wfs/WFSServersList.txt b/ogr/ogrsf_frmts/wfs/WFSServersList.txt
index ddb0265..5581ff5 100644
--- a/ogr/ogrsf_frmts/wfs/WFSServersList.txt
+++ b/ogr/ogrsf_frmts/wfs/WFSServersList.txt
@@ -4,6 +4,10 @@ GeoServer:
 http://sigma.openplans.org/geoserver/ows
 http://demo.opengeo.org/geoserver/wfs (WFS-T with write permissions)
 http://giswebservices.massgis.state.ma.us/geoserver/wfs
+http://gem.demo.opengeo.org/geoserver/wfs
+http://geohub.jrc.ec.europa.eu/effis/ows
+http://v2.suite.opengeo.org/geoserver/ows
+http://data.wien.gv.at/daten/wfs  # layers with identical names within 2 different namespaces
 
 MapServer:
 http://www.bsc-eoc.org/cgi-bin/bsc_ows.asp (4.8.1)
@@ -13,19 +17,23 @@ http://devgeo.cciw.ca/cgi-bin/mapserv/carts
 http://map.ns.ec.gc.ca/MapServer/mapserv.exe?map=/mapserver/services/envdat/config.map (4.8.3)
 http://nsidc.org/cgi-bin/acap.pl
 http://sdmdataaccess.nrcs.usda.gov/Spatial/SDMNAD83Geographic.wfs
+http://demo.mapserver.org/cgi-bin/wfs?
 
 Deegree:
-http://www.nokis.org/deegree2/ogcwebservice
+http://www.nokis.org/deegree2/ogcwebservice (not responding, requires namespace to be passed)
+http://www.idee.es/IDEE-WFS/ogcwebservice (responding, requires namespace to be passed)
 http://demo.deegree.org/deegree-wfs/services
 http://testing.deegree.org/deegree-wfs/services (WFS-T, but permission denied)
 http://lkee-xplanung2.lat-lon.de/xplan-wfs/services (with complex schema that we cannot understand with the XSD parser)
 http://deegree3-testing.deegree.org/deegree-geosciml-demo/services (offline currently)
 http://deegree3-testing.deegree.org:80/deegree-inspire-node/services (GML 3.2.1 output only)
+http://deegree3-demo.deegree.org:80/deegree-utah-demo/services (schema has <complexType> inside <element>)
 http://inspire.kademo.nl/deegree-wfs/services
 
 TinyOWS:
 http://dev4.mapgears.com/cgi-bin/tinyows (old & buggy version)
 http://www.tinyows.org/cgi-bin/tinyows (WFS-T with write permissions)
+http://gis-lab.info/scripts/tinyows/tinyows.cgi
 
 CubeWerx:
 http://ceoware2.ccrs.nrcan.gc.ca/cubewerx/cwwfs/cubeserv.cgi?datastore=CEOWARE2
@@ -45,7 +53,7 @@ http://sentinel.ga.gov.au/wfsconnector/com.esri.wfs.Esrimap (works)
 http://sima.gencat.cat/wfsconnector/com.esri.wfs.Esrimap/SIMA_WFS (returns invalid XML in GetFeature)
 http://egisws01.nos.noaa.gov/wfsconnector/com.esri.wfs.Esrimap/nosdataexplorer_wfs (Mark invalid error in GetFeature)
 http://services.nationalmap.gov/ArcGIS/services/geonames/MapServer/WFSServer
-http://129.116.104.176/ArcGIS/services/Climate/CFSRMonthly/MapServer/WFSServer
+http://129.116.104.176/ArcGIS/services/Climate/CFSRMonthly/MapServer/WFSServer (offline)
 
 Microimages ?:
 http://publicatlas.microimages.com/tntgateway/tntgateway.cgi
@@ -56,7 +64,7 @@ http://webservices.ionicsoft.com/gazetteer/wfs/GNS_GAZ
 http://demo.ionicsoft.com/agiRSW/wfs/PYLONS
 
 Safe Software:
-http://142.176.62.103:8194/servlet/WFS_NS_NAMES
+http://142.176.62.103:8194/servlet/WFS_NS_NAMES (offline)
 
 ERDAS Apollo:
 http://apollo.erdas.com/erdas-apollo/vector/Cherokee
diff --git a/ogr/ogrsf_frmts/wfs/drv_wfs.html b/ogr/ogrsf_frmts/wfs/drv_wfs.html
index cd6081d..22e59ad 100644
--- a/ogr/ogrsf_frmts/wfs/drv_wfs.html
+++ b/ogr/ogrsf_frmts/wfs/drv_wfs.html
@@ -125,6 +125,24 @@ Currently, any other SQL command will be processed by the generic layer, meaning
 Server side spatial and attribute filtering must be done through the SetSpatialFilter() and SetAttributeFilter()
 interfaces.<p>
 
+<h2>Special layer : WFSLayerMetadata</h2>
+
+<p>(OGR >= 1.9.0)</p>
+
+<p>A "hidden" layer called "WFSLayerMetadata" is filled with records with metadata for each WFS layer.</p>
+
+<p>Each record contains a "layer_name", "title" and "abstract" field, from the document returned by GetCapabilities.</p>
+
+<p>That layer is returned through GetLayerByName("WFSLayerMetadata").</p>
+
+<h2>Special layer : WFSGetCapabilities</h2>
+
+<p>(OGR >= 1.9.0)</p>
+
+<p>A "hidden" layer called "WFSGetCapabilities" is filled with the raw XML result of the GetCapabilities request.</p>
+
+<p>That layer is returned through GetLayerByName("WFSGetCapabilities").</p>
+
 <h2>Examples</h2>
 
 <li>
@@ -153,6 +171,12 @@ Retrieving the features of gml:id "world.2" and "world.3" from the tows:world la
 ogrinfo "WFS:http://www.tinyows.org/cgi-bin/tinyows" tows:world -ro -al -where "gml_id='world.2' or gml_id='world.3'"
 </pre>
 
+<li>
+Display layer metadata (OGR >= 1.9.0):
+<pre>
+ogrinfo -ro -al "WFS:http://v2.suite.opengeo.org/geoserver/ows" WFSLayerMetadata
+</pre>
+
 <p>
 
 <h2>See Also</h2>
diff --git a/ogr/ogrsf_frmts/wfs/ogr_wfs.h b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
index c33abd1..196aa71 100644
--- a/ogr/ogrsf_frmts/wfs/ogr_wfs.h
+++ b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogr_wfs.h 21195 2010-12-04 22:04:16Z rouault $
+ * $Id: ogr_wfs.h 23164 2011-10-02 16:31:52Z rouault $
  *
  * Project:  WFS Translator
- * Purpose:  Definition of classes for OGR .sua driver.
+ * Purpose:  Definition of classes for OGR WFS driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
@@ -31,6 +31,7 @@
 #define _OGR_WFS_H_INCLUDED
 
 #include <vector>
+#include <set>
 
 #include "cpl_minixml.h"
 #include "ogrsf_frmts.h"
@@ -38,8 +39,6 @@
 #include "cpl_http.h"
 
 CPLXMLNode* WFSFindNode(CPLXMLNode* psXML, const char* pszRootName);
-CPLString WFS_FetchValueFromURL(const char* pszURL, const char* pszKey);
-CPLString WFS_AddKVToURL(const char* pszURL, const char* pszKey, const char* pszValue);
 CPLString WFS_TurnSQLFilterToOGCFilter( const char * pszFilter,
                                     int nVersion,
                                     int bPropertyIsNotEqualToSupported,
@@ -94,7 +93,6 @@ class OGRWFSLayer : public OGRLayer
     CPLString           osSQLWhere;
     CPLString           osWFSWhere;
 
-    const char         *GetShortName();
     CPLString           osTargetNamespace;
     CPLString           GetDescribeFeatureTypeURL(int bWithNS);
 
@@ -106,8 +104,6 @@ class OGRWFSLayer : public OGRLayer
 
     CPLString           GetPostHeader();
 
-    OGRFeatureDefn*     ParseSchema(CPLXMLNode* psSchema);
-
     int                 bUseFeatureIdAtLayerLevel;
 
     int                 bPagingActive;
@@ -115,6 +111,8 @@ class OGRWFSLayer : public OGRLayer
     int                 nFeatureRead;
     int                 nFeatureCountRequested;
 
+    OGRFeatureDefn*     BuildLayerDefnFromFeatureClass(GMLFeatureClass* poClass);
+
   public:
                         OGRWFSLayer(OGRWFSDataSource* poDS,
                                     OGRSpatialReference* poSRS,
@@ -156,11 +154,16 @@ class OGRWFSLayer : public OGRLayer
     virtual OGRErr      CommitTransaction();
     virtual OGRErr      RollbackTransaction();
 
-    OGRFeatureDefn*     BuildLayerDefn(CPLXMLNode* psSchema = NULL);
+    int                 HasLayerDefn() { return poFeatureDefn != NULL; }
+
+    OGRFeatureDefn*     ParseSchema(CPLXMLNode* psSchema);
+    OGRFeatureDefn*     BuildLayerDefn(OGRFeatureDefn* poSrcFDefn = NULL);
 
     OGRErr              DeleteFromFilter( CPLString osOGCFilter );
 
     const std::vector<CPLString>& GetLastInsertedFIDList() { return aosFIDList; }
+
+    const char         *GetShortName();
 };
 
 /************************************************************************/
@@ -186,6 +189,8 @@ class OGRWFSDataSource : public OGRDataSource
     int                 bPropertyIsNotEqualToSupported;
     int                 bUseFeatureId;
     int                 bGmlObjectIdNeedsGMLPrefix;
+    int                 bRequiresEnvelopeSpatialFilter;
+    int                 DetectRequiresEnvelopeSpatialFilter(CPLXMLNode* psRoot);
 
     int                 bTransactionSupport;
     char**              papszIdGenMethods;
@@ -206,6 +211,24 @@ class OGRWFSDataSource : public OGRDataSource
     int                 bPagingAllowed;
     int                 nPageSize;
 
+    int                 bIsGEOSERVER;
+
+    int                 bLoadMultipleLayerDefn;
+    std::set<CPLString> aoSetAlreadyTriedLayers;
+
+    CPLString           osLayerMetadataCSV;
+    CPLString           osLayerMetadataTmpFileName;
+    OGRDataSource      *poLayerMetadataDS;
+    OGRLayer           *poLayerMetadataLayer;
+
+    CPLString           osGetCapabilities;
+    OGRDataSource      *poLayerGetCapabilitiesDS;
+    OGRLayer           *poLayerGetCapabilitiesLayer;
+
+    int                 bKeepLayerNamePrefix;
+
+    CPLHTTPResult*      SendGetCapabilities(const char* pszBaseURL,
+                                            CPLString& osTypeName);
   public:
                         OGRWFSDataSource();
                         ~OGRWFSDataSource();
@@ -237,6 +260,7 @@ class OGRWFSDataSource : public OGRDataSource
     int                         HasMinOperators() { return bHasMinOperators; }
     int                         HasNullCheck() { return bHasNullCheck; }
     int                         UseFeatureId() { return bUseFeatureId; }
+    int                         RequiresEnvelopeSpatialFilter() { return bRequiresEnvelopeSpatialFilter; }
     void                        SetGmlObjectIdNeedsGMLPrefix() { bGmlObjectIdNeedsGMLPrefix = TRUE; }
     int                         DoesGmlObjectIdNeedGMLPrefix() { return bGmlObjectIdNeedsGMLPrefix; }
 
@@ -253,6 +277,11 @@ class OGRWFSDataSource : public OGRDataSource
     int                         GetPageSize() { return nPageSize; }
 
     const char*                 GetRequiredOutputFormat() { return (osRequiredOutputFormat.size() != 0) ? osRequiredOutputFormat.c_str() : NULL; }
+
+    void                        LoadMultipleLayerDefn(const char* pszLayerName,
+                                                      char* pszNS, char* pszNSVal);
+
+    int                         GetKeepLayerNamePrefix() { return bKeepLayerNamePrefix; }
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
index c5f70b6..842b457 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfsdatasource.cpp 21439 2011-01-08 14:54:41Z rouault $
+ * $Id: ogrwfsdatasource.cpp 23165 2011-10-02 17:27:02Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSDataSource class
@@ -27,14 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_wfs.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
+#include "ogr_api.h"
 #include "cpl_minixml.h"
 #include "cpl_http.h"
 #include "gmlutils.h"
+#include "parsexsd.h"
 
-CPL_CVSID("$Id: ogrwfsdatasource.cpp 21439 2011-01-08 14:54:41Z rouault $");
+CPL_CVSID("$Id: ogrwfsdatasource.cpp 23165 2011-10-02 17:27:02Z rouault $");
 
 
 /************************************************************************/
@@ -131,6 +132,7 @@ OGRWFSDataSource::OGRWFSDataSource()
     papszIdGenMethods = NULL;
     bUseFeatureId = FALSE; /* CubeWerx doesn't like GmlObjectId */
     bGmlObjectIdNeedsGMLPrefix = FALSE;
+    bRequiresEnvelopeSpatialFilter = FALSE;
 
     bRewriteFile = FALSE;
     psFileXML = NULL;
@@ -146,6 +148,18 @@ OGRWFSDataSource::OGRWFSDataSource()
         if (nPageSize <= 0)
             nPageSize = 100;
     }
+
+    bIsGEOSERVER = FALSE;
+
+    bLoadMultipleLayerDefn = CSLTestBoolean(CPLGetConfigOption("OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN", "TRUE"));
+
+    poLayerMetadataDS = NULL;
+    poLayerMetadataLayer = NULL;
+
+    poLayerGetCapabilitiesDS = NULL;
+    poLayerGetCapabilitiesLayer = NULL;
+
+    bKeepLayerNamePrefix = FALSE;
 }
 
 /************************************************************************/
@@ -168,6 +182,10 @@ OGRWFSDataSource::~OGRWFSDataSource()
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree( papoLayers );
+    if (osLayerMetadataTmpFileName.size() != 0)
+        VSIUnlink(osLayerMetadataTmpFileName);
+    delete poLayerMetadataDS;
+    delete poLayerGetCapabilitiesDS;
 
     CPLFree( pszName );
     CSLDestroy( papszIdGenMethods );
@@ -209,6 +227,47 @@ OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszName)
     int  i;
     int  bHasFoundLayerWithColon = FALSE;
 
+    if (EQUAL(pszName, "WFSLayerMetadata"))
+    {
+        if (osLayerMetadataTmpFileName.size() != 0)
+            return poLayerMetadataLayer;
+
+        osLayerMetadataTmpFileName = CPLSPrintf("/vsimem/tempwfs_%p/WFSLayerMetadata.csv", this);
+        osLayerMetadataCSV = "layer_name,title,abstract\n" + osLayerMetadataCSV;
+
+        VSIFCloseL(VSIFileFromMemBuffer(osLayerMetadataTmpFileName,
+                                        (GByte*) osLayerMetadataCSV.c_str(),
+                                        osLayerMetadataCSV.size(), FALSE));
+        poLayerMetadataDS = (OGRDataSource*) OGROpen(osLayerMetadataTmpFileName,
+                                                     FALSE, NULL);
+        if (poLayerMetadataDS)
+            poLayerMetadataLayer = poLayerMetadataDS->GetLayer(0);
+        return poLayerMetadataLayer;
+    }
+    else if (EQUAL(pszName, "WFSGetCapabilities"))
+    {
+        if (poLayerGetCapabilitiesLayer != NULL)
+            return poLayerGetCapabilitiesLayer;
+
+        OGRSFDriver* poMEMDrv = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("Memory");
+        if (poMEMDrv == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot load 'Memory' driver");
+            return NULL;
+        }
+
+        poLayerGetCapabilitiesDS = poMEMDrv->CreateDataSource("WFSGetCapabilities", NULL);
+        poLayerGetCapabilitiesLayer = poLayerGetCapabilitiesDS->CreateLayer("WFSGetCapabilities", NULL, wkbNone, NULL);
+        OGRFieldDefn oFDefn("content", OFTString);
+        poLayerGetCapabilitiesLayer->CreateField(&oFDefn);
+        OGRFeature* poFeature = new OGRFeature(poLayerGetCapabilitiesLayer->GetLayerDefn());
+        poFeature->SetField(0, osGetCapabilities);
+        poLayerGetCapabilitiesLayer->CreateFeature(poFeature);
+        delete poFeature;
+
+        return poLayerGetCapabilitiesLayer;
+    }
+
     /* first a case sensitive check */
     for( i = 0; i < nLayers; i++ )
     {
@@ -230,7 +289,7 @@ OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszName)
     }
 
     /* now try looking after the colon character */
-    if (bHasFoundLayerWithColon && strchr(pszName, ':') == NULL)
+    if (!bKeepLayerNamePrefix && bHasFoundLayerWithColon && strchr(pszName, ':') == NULL)
     {
         for( i = 0; i < nLayers; i++ )
         {
@@ -252,24 +311,10 @@ OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszName)
 const char* FindSubStringInsensitive(const char* pszStr,
                                      const char* pszSubStr)
 {
-    while(*pszStr)
-    {
-        const char* pszStrIter = pszStr;
-        const char* pszSubStrIter = pszSubStr;
-        while(*pszSubStrIter)
-        {
-            if (toupper((int)*pszStrIter) != toupper((int)*pszSubStrIter))
-            {
-                break;
-            }
-            pszStrIter ++;
-            pszSubStrIter ++;
-        }
-        if (*pszSubStrIter == 0)
-            return pszStrIter - (pszSubStrIter - pszSubStr);
-        pszStr ++;
-    }
-    return NULL;
+    size_t nSubStrPos = CPLString(pszStr).ifind(pszSubStr);
+    if (nSubStrPos == std::string::npos)
+        return NULL;
+    return pszStr + nSubStrPos;
 }
 
 /************************************************************************/
@@ -423,13 +468,56 @@ CPLString OGRWFSDataSource::DetectRequiredOutputFormat(CPLXMLNode* psRoot)
     return "";
 }
 
+
+/************************************************************************/
+/*                   DetectRequiresEnvelopeSpatialFilter()              */
+/************************************************************************/
+
+int OGRWFSDataSource::DetectRequiresEnvelopeSpatialFilter(CPLXMLNode* psRoot)
+{
+    /* This is a heuristic to detect Deegree 3 servers, such as */
+    /* http://deegree3-demo.deegree.org:80/deegree-utah-demo/services */
+    /* that are very GML3 strict, and don't like <gml:Box> in a <Filter><BBOX> */
+    /* request, but requires instead <gml:Envelope>, but some servers (such as MapServer) */
+    /* don't like <gml:Envelope> so we are obliged to detect the kind of server */
+
+    int nCount;
+    CPLXMLNode* psChild;
+
+    CPLXMLNode* psGeometryOperands =
+        CPLGetXMLNode(psRoot, "Filter_Capabilities.Spatial_Capabilities.GeometryOperands");
+    if (!psGeometryOperands)
+    {
+        return FALSE;
+    }
+
+    nCount = 0;
+    psChild = psGeometryOperands->psChild;
+    while(psChild)
+    {
+        nCount ++;
+        psChild = psChild->psNext;
+    }
+    /* Magic number... Might be fragile */
+    return (nCount == 19);
+}
+
 /************************************************************************/
 /*                       GetPostTransactionURL()                        */
 /************************************************************************/
 
 CPLString OGRWFSDataSource::GetPostTransactionURL()
 {
-    return osPostTransactionURL.size() ? osPostTransactionURL : osBaseURL;
+    if (osPostTransactionURL.size())
+        return osPostTransactionURL;
+
+    osPostTransactionURL = osBaseURL;
+    const char* pszPostTransactionURL = osPostTransactionURL.c_str();
+    const char* pszEsperluet = strchr(pszPostTransactionURL, '?');
+    if (pszEsperluet)
+        osPostTransactionURL.resize(pszEsperluet - pszPostTransactionURL);
+
+    return osPostTransactionURL;
 }
 
 /************************************************************************/
@@ -533,77 +621,6 @@ int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
 }
 
 /************************************************************************/
-/*                      WFS_FetchValueFromURL()                         */
-/************************************************************************/
-
-CPLString WFS_FetchValueFromURL(const char* pszURL, const char* pszKey)
-{
-    CPLString osKey(pszKey);
-    osKey += "=";
-    const char* pszExistingKey = FindSubStringInsensitive(pszURL, osKey);
-    if (pszExistingKey)
-    {
-        CPLString osValue(pszExistingKey + strlen(osKey));
-        const char* pszValue = osValue.c_str();
-        const char* pszSep = strchr(pszValue, '&');
-        if (pszSep)
-        {
-            osValue.resize(pszSep - pszValue);
-        }
-        return osValue;
-    }
-    return "";
-}
-
-/************************************************************************/
-/*                        WFS_AddKVToURL()                              */
-/************************************************************************/
-
-CPLString WFS_AddKVToURL(const char* pszURL, const char* pszKey, const char* pszValue)
-{
-    CPLString osURL(pszURL);
-    if (strchr(osURL, '?') == NULL)
-        osURL += "?";
-    pszURL = osURL.c_str();
-
-    CPLString osKey(pszKey);
-    osKey += "=";
-    const char* pszExistingKey = FindSubStringInsensitive(pszURL, osKey);
-    if (pszExistingKey)
-    {
-        CPLString osNewURL(osURL);
-        osNewURL.resize(pszExistingKey - pszURL);
-        if (pszValue)
-        {
-            if (osNewURL[osNewURL.size()-1] != '&' && osNewURL[osNewURL.size()-1] != '?')
-                osNewURL += '&';
-            osNewURL += osKey;
-            osNewURL += pszValue;
-        }
-        const char* pszNext = strchr(pszExistingKey, '&');
-        if (pszNext)
-        {
-            if (osNewURL[osNewURL.size()-1] == '&')
-                osNewURL += pszNext + 1;
-            else
-                osNewURL += pszNext;
-        }
-        return osNewURL;
-    }
-    else
-    {
-        if (pszValue)
-        {
-            if (osURL[osURL.size()-1] != '&' && osURL[osURL.size()-1] != '?')
-                osURL += '&';
-            osURL += osKey;
-            osURL += pszValue;
-        }
-        return osURL;
-    }
-}
-
-/************************************************************************/
 /*                      FindComparisonOperator()                        */
 /************************************************************************/
 
@@ -617,6 +634,12 @@ static int FindComparisonOperator(CPLXMLNode* psNode, const char* pszVal)
         {
             if (strcmp(CPLGetXMLValue(psChild, NULL, ""), pszVal) == 0)
                 return TRUE;
+
+            /* For WFS 2.0.0 */
+            const char* pszName = CPLGetXMLValue(psChild, "name", NULL);
+            if (pszName != NULL && strncmp(pszName, "PropertyIs", 10) == 0 &&
+                strcmp(pszName + 10, pszVal) == 0)
+                return TRUE;
         }
         psChild = psChild->psNext;
     }
@@ -630,25 +653,29 @@ static int FindComparisonOperator(CPLXMLNode* psNode, const char* pszVal)
 CPLXMLNode* OGRWFSDataSource::LoadFromFile( const char * pszFilename )
 {
     VSILFILE *fp;
-    char achHeader[18];
+    char achHeader[1024];
 
     VSIStatBufL sStatBuf;
     if (VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0 ||
         VSI_ISDIR(sStatBuf.st_mode))
-        return FALSE;
+        return NULL;
 
     fp = VSIFOpenL( pszFilename, "rb" );
 
     if( fp == NULL )
         return NULL;
 
-    if( VSIFReadL( achHeader, sizeof(achHeader), 1, fp ) != 1 )
+    int nRead;
+    if( (nRead = VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp )) == 0 )
     {
         VSIFCloseL( fp );
         return NULL;
     }
+    achHeader[nRead] = 0;
 
-    if( !EQUALN(achHeader,"<OGRWFSDataSource>",18) )
+    if( !EQUALN(achHeader,"<OGRWFSDataSource>",18) &&
+        strstr(achHeader,"<WFS_Capabilities") == NULL &&
+        strstr(achHeader,"<wfs:WFS_Capabilities") == NULL)
     {
         VSIFCloseL( fp );
         return NULL;
@@ -696,6 +723,50 @@ CPLXMLNode* OGRWFSDataSource::LoadFromFile( const char * pszFilename )
 }
 
 /************************************************************************/
+/*                          SendGetCapabilities()                       */
+/************************************************************************/
+
+CPLHTTPResult* OGRWFSDataSource::SendGetCapabilities(const char* pszBaseURL,
+                                                     CPLString& osTypeName)
+{
+    CPLString osURL(pszBaseURL);
+    osURL = CPLURLAddKVP(osURL, "SERVICE", "WFS");
+    osURL = CPLURLAddKVP(osURL, "REQUEST", "GetCapabilities");
+    osTypeName = CPLURLGetValue(osURL, "TYPENAME");
+    osURL = CPLURLAddKVP(osURL, "TYPENAME", NULL);
+    osURL = CPLURLAddKVP(osURL, "FILTER", NULL);
+    osURL = CPLURLAddKVP(osURL, "PROPERTYNAME", NULL);
+    osURL = CPLURLAddKVP(osURL, "MAXFEATURES", NULL);
+    osURL = CPLURLAddKVP(osURL, "OUTPUTFORMAT", NULL);
+
+    /* Don't accept WFS 2.0.0 for now, unless explicitely specified */
+    if (CPLURLGetValue(osURL, "ACCEPTVERSIONS").size() == 0 &&
+        CPLURLGetValue(osURL, "VERSION").size() == 0)
+        osURL = CPLURLAddKVP(osURL, "ACCEPTVERSIONS", "1.1.0,1.0.0");
+
+    CPLDebug("WFS", "%s", osURL.c_str());
+
+    CPLHTTPResult* psResult = HTTPFetch( osURL, NULL);
+    if (psResult == NULL)
+    {
+        return NULL;
+    }
+
+    if (strstr((const char*)psResult->pabyData,
+                                    "<ServiceExceptionReport") != NULL ||
+        strstr((const char*)psResult->pabyData,
+                                    "<ows:ExceptionReport") != NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Error returned by server : %s",
+                psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    return psResult;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -724,27 +795,13 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
             pszBaseURL += 4;
 
         osBaseURL = pszBaseURL;
-        const char* pszEsperluet = strchr(pszBaseURL, '?');
-        if (pszEsperluet)
-            osBaseURL.resize(pszEsperluet - pszBaseURL);
 
         if (strncmp(pszBaseURL, "http://", 7) != 0 &&
             strncmp(pszBaseURL, "https://", 8) != 0)
             return FALSE;
 
-        CPLString osURL(pszBaseURL);
-        osURL = WFS_AddKVToURL(osURL, "SERVICE", "WFS");
-        osURL = WFS_AddKVToURL(osURL, "REQUEST", "GetCapabilities");
-        osTypeName = WFS_FetchValueFromURL(osURL, "TYPENAME");
-        osURL = WFS_AddKVToURL(osURL, "TYPENAME", NULL);
-        osURL = WFS_AddKVToURL(osURL, "FILTER", NULL);
-        osURL = WFS_AddKVToURL(osURL, "PROPERTYNAME", NULL);
-        osURL = WFS_AddKVToURL(osURL, "MAXFEATURES", NULL);
-        osURL = WFS_AddKVToURL(osURL, "OUTPUTFORMAT", NULL);
-
-        CPLDebug("WFS", "%s", osURL.c_str());
-
-        CPLHTTPResult* psResult = HTTPFetch( osURL, NULL);
+        CPLHTTPResult* psResult = SendGetCapabilities(pszBaseURL,
+                                                      osTypeName);
         if (psResult == NULL)
         {
             return FALSE;
@@ -768,9 +825,18 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
             CPLHTTPDestroyResult(psResult);
             return FALSE;
         }
+        osGetCapabilities = (const char*) psResult->pabyData;
 
         CPLHTTPDestroyResult(psResult);
     }
+    else if ( WFSFindNode( psXML, "OGRWFSDataSource" ) == NULL &&
+              WFSFindNode( psXML, "WFS_Capabilities" ) != NULL )
+    {
+        /* This is directly the Capabilities document */
+        char* pszXML = CPLSerializeXMLTree(WFSFindNode( psXML, "WFS_Capabilities" ));
+        osGetCapabilities = pszXML;
+        CPLFree(pszXML);
+    }
     else
     {
         CPLXMLNode* psRoot = WFSFindNode( psXML, "OGRWFSDataSource" );
@@ -790,9 +856,10 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
             CPLDestroyXMLNode( psXML );
             return FALSE;
         }
+        osBaseURL = pszBaseURL;
 
 /* -------------------------------------------------------------------- */
-/*      Captureother parameters.                                        */
+/*      Capture other parameters.                                       */
 /* -------------------------------------------------------------------- */
         const char  *pszParm;
 
@@ -830,23 +897,13 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
                 nPageSize = 100;
         }
 
-        osTypeName = WFS_FetchValueFromURL(pszBaseURL, "TYPENAME");
+        osTypeName = CPLURLGetValue(pszBaseURL, "TYPENAME");
 
         psWFSCapabilities = WFSFindNode( psRoot, "WFS_Capabilities" );
         if (psWFSCapabilities == NULL)
         {
-            CPLString osURL(pszBaseURL);
-            osURL = WFS_AddKVToURL(osURL, "SERVICE", "WFS");
-            osURL = WFS_AddKVToURL(osURL, "REQUEST", "GetCapabilities");
-            osTypeName = WFS_FetchValueFromURL(osURL, "TYPENAME");
-            osURL = WFS_AddKVToURL(osURL, "TYPENAME", NULL);
-            osURL = WFS_AddKVToURL(osURL, "FILTER", NULL);
-            osURL = WFS_AddKVToURL(osURL, "PROPERTYNAME", NULL);
-            osURL = WFS_AddKVToURL(osURL, "MAXFEATURES", NULL);
-
-            CPLDebug("WFS", "%s", osURL.c_str());
-
-            CPLHTTPResult* psResult = HTTPFetch( osURL, NULL);
+            CPLHTTPResult* psResult = SendGetCapabilities(pszBaseURL,
+                                                          osTypeName);
             if (psResult == NULL)
             {
                 CPLDestroyXMLNode( psXML );
@@ -890,6 +947,14 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
         else
         {
             psFileXML = psXML;
+
+            /* To avoid to have nodes after WFSCapabilities */
+            CPLXMLNode* psAfterWFSCapabilities = psWFSCapabilities->psNext;
+            psWFSCapabilities->psNext = NULL;
+            char* pszXML = CPLSerializeXMLTree(psWFSCapabilities);
+            psWFSCapabilities->psNext = psAfterWFSCapabilities;
+            osGetCapabilities = pszXML;
+            CPLFree(pszXML);
         }
     }
 
@@ -912,6 +977,24 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
         return FALSE;
     }
 
+    if (pszBaseURL == NULL)
+    {
+        /* This is directly the Capabilities document */
+        pszBaseURL = CPLGetXMLValue( psWFSCapabilities, "OperationsMetadata.Operation.DCP.HTTP.Get.href", NULL );
+        if (pszBaseURL == NULL) /* WFS 1.0.0 variant */
+            pszBaseURL = CPLGetXMLValue( psWFSCapabilities, "Capability.Request.GetCapabilities.DCPType.HTTP.Get.onlineResource", NULL );
+
+        if (pszBaseURL == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Cannot find base URL");
+            CPLDestroyXMLNode( psStrippedXML );
+            return FALSE;
+        }
+
+        osBaseURL = pszBaseURL;
+    }
+
     if (osVersion.size() == 0)
         osVersion = CPLGetXMLValue(psWFSCapabilities, "version", "1.0.0");
     if (strcmp(osVersion.c_str(), "1.0.0") == 0)
@@ -920,12 +1003,36 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
     {
         /* Some servers happen to support RESULTTYPE=hits in 1.0.0, but there */
         /* is no way to advertisze this */
-        bGetFeatureSupportHits = DetectIfGetFeatureSupportHits(psWFSCapabilities);
+        if (atoi(osVersion) >= 2)
+            bGetFeatureSupportHits = TRUE;  /* WFS >= 2.0.0 supports hits */
+        else
+            bGetFeatureSupportHits = DetectIfGetFeatureSupportHits(psWFSCapabilities);
         osRequiredOutputFormat = DetectRequiredOutputFormat(psWFSCapabilities);
+        bRequiresEnvelopeSpatialFilter = DetectRequiresEnvelopeSpatialFilter(psWFSCapabilities);
     }
 
     DetectTransactionSupport(psWFSCapabilities);
 
+    /* Detect if server is GEOSERVER */
+    CPLXMLNode* psKeywords = CPLGetXMLNode(psWFSCapabilities, "ServiceIdentification.Keywords");
+    if (psKeywords)
+    {
+        CPLXMLNode* psKeyword = psKeywords->psChild;
+        for(;psKeyword != NULL;psKeyword=psKeyword->psNext)
+        {
+            if (psKeyword->eType == CXT_Element &&
+                psKeyword->pszValue != NULL &&
+                EQUAL(psKeyword->pszValue, "Keyword") &&
+                psKeyword->psChild != NULL &&
+                psKeyword->psChild->pszValue != NULL &&
+                EQUALN(psKeyword->psChild->pszValue, "GEOSERVER", 9))
+            {
+                bIsGEOSERVER = TRUE;
+                break;
+            }
+        }
+    }
+
     if (bUpdate && !bTransactionSupport)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -952,8 +1059,16 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
             {
                 bHasMinOperators &= FindComparisonOperator(psFilterCap, "LessThan");
                 bHasMinOperators &= FindComparisonOperator(psFilterCap, "GreaterThan");
-                bHasMinOperators &= FindComparisonOperator(psFilterCap, "LessThanEqualTo");
-                bHasMinOperators &= FindComparisonOperator(psFilterCap, "GreaterThanEqualTo");
+                if (atoi(osVersion) >= 2)
+                {
+                    bHasMinOperators &= FindComparisonOperator(psFilterCap, "LessThanOrEqualTo");
+                    bHasMinOperators &= FindComparisonOperator(psFilterCap, "GreaterThanOrEqualTo");
+                }
+                else
+                {
+                    bHasMinOperators &= FindComparisonOperator(psFilterCap, "LessThanEqualTo");
+                    bHasMinOperators &= FindComparisonOperator(psFilterCap, "GreaterThanEqualTo");
+                }
                 bHasMinOperators &= FindComparisonOperator(psFilterCap, "EqualTo");
                 bHasMinOperators &= FindComparisonOperator(psFilterCap, "NotEqualTo");
                 bHasMinOperators &= FindComparisonOperator(psFilterCap, "Like");
@@ -964,6 +1079,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
                                     CPLGetXMLNode(psFilterCap, "Like") != NULL;
             }
             bHasNullCheck = FindComparisonOperator(psFilterCap, "NullCheck") ||
+                            FindComparisonOperator(psFilterCap, "Null") || /* WFS 2.0.0 */
                             CPLGetXMLNode(psFilterCap, "NullCheck") != NULL;
         }
         else
@@ -983,6 +1099,33 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
     }
 
     CPLXMLNode* psChildIter;
+
+    /* Check if there are layer names whose identical except their prefix */
+    std::set<CPLString> aosSetLayerNames;
+    for(psChildIter = psChild->psChild;
+        psChildIter != NULL;
+        psChildIter = psChildIter->psNext)
+    {
+        if (psChildIter->eType == CXT_Element &&
+            strcmp(psChildIter->pszValue, "FeatureType") == 0)
+        {
+            const char* pszName = CPLGetXMLValue(psChildIter, "Name", NULL);
+            if (pszName != NULL)
+            {
+                const char* pszShortName = strchr(pszName, ':');
+                if (pszShortName)
+                    pszName = pszShortName + 1;
+                if (aosSetLayerNames.find(pszName) != aosSetLayerNames.end())
+                {
+                    bKeepLayerNamePrefix = TRUE;
+                    CPLDebug("WFS", "At least 2 layers have names that are only distinguishable by keeping the prefix");
+                    break;
+                }
+                aosSetLayerNames.insert(pszName);
+            }
+        }
+    }
+
     for(psChildIter = psChild->psChild;
         psChildIter != NULL;
         psChildIter = psChildIter->psNext)
@@ -1004,6 +1147,8 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
             }
 
             const char* pszName = CPLGetXMLValue(psChildIter, "Name", NULL);
+            const char* pszTitle = CPLGetXMLValue(psChildIter, "Title", NULL);
+            const char* pszAbstract = CPLGetXMLValue(psChildIter, "Abstract", NULL);
             if (pszName != NULL &&
                 (osTypeName.size() == 0 ||
                     strcmp(osTypeName.c_str(), pszName) == 0))
@@ -1012,12 +1157,14 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
                         CPLGetXMLValue(psChildIter, "DefaultSRS", NULL);
                 if (pszDefaultSRS == NULL)
                     pszDefaultSRS = CPLGetXMLValue(psChildIter, "SRS", NULL);
+                if (pszDefaultSRS == NULL)
+                    pszDefaultSRS = CPLGetXMLValue(psChildIter, "DefaultCRS", NULL); /* WFS 2.0.0 */
 
                 OGRSpatialReference* poSRS = NULL;
                 int bAxisOrderAlreadyInverted = FALSE;
 
                 /* If a SRSNAME parameter has been encoded in the URL, use it as the SRS */
-                CPLString osSRSName = WFS_FetchValueFromURL(pszBaseURL, "SRSNAME");
+                CPLString osSRSName = CPLURLGetValue(pszBaseURL, "SRSNAME");
                 if (osSRSName.size() != 0)
                 {
                     pszDefaultSRS = osSRSName.c_str();
@@ -1093,6 +1240,25 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
                     }
                 }
 
+                osLayerMetadataCSV += "\"";
+                osLayerMetadataCSV += pszName;
+                osLayerMetadataCSV += "\"";
+                osLayerMetadataCSV += ",";
+                if (pszTitle)
+                {
+                    osLayerMetadataCSV += "\"";
+                    osLayerMetadataCSV += pszTitle;
+                    osLayerMetadataCSV += "\"";
+                }
+                osLayerMetadataCSV += ",";
+                if (pszAbstract)
+                {
+                    osLayerMetadataCSV += "\"";
+                    osLayerMetadataCSV += pszAbstract;
+                    osLayerMetadataCSV += "\"";
+                }
+                osLayerMetadataCSV += "\n";
+
                 OGRWFSLayer* poLayer = new OGRWFSLayer(
                             this, poSRS, bAxisOrderAlreadyInverted,
                             pszBaseURL, pszName, pszNS, pszNSVal);
@@ -1102,7 +1268,14 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
                     char* pszProj4 = NULL;
                     if (poSRS->exportToProj4(&pszProj4) == OGRERR_NONE)
                     {
-                        if (strcmp(pszProj4, "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ") == 0)
+                        /* See http://trac.osgeo.org/gdal/ticket/4041 */
+                        /* For now, we restrict to GEOSERVER as apparently the order is always longitude,latitude */
+                        /* other servers might also qualify, so this should be relaxed */
+                        /* Also accept when <wfs:DefaultCRS>urn:ogc:def:crs:OGC:1.3:CRS84</wfs:DefaultCRS> */
+                        if ((bIsGEOSERVER &&
+                            (strcmp(pszProj4, "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ") == 0 ||
+                             strcmp(pszProj4, "+proj=longlat +datum=WGS84 +no_defs ") == 0)) ||
+                            strcmp(pszDefaultSRS, "urn:ogc:def:crs:OGC:1.3:CRS84") == 0)
                         {
                             poLayer->SetExtents(dfMinX, dfMinY, dfMaxX, dfMaxY);
                         }
@@ -1173,7 +1346,11 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
                         {
                             CPLXMLNode* psSchema = WFSFindNode( psIter->psChild, "schema" );
                             if (psSchema)
-                                poLayer->BuildLayerDefn(psSchema);
+                            {
+                                OGRFeatureDefn* poSrcFDefn = poLayer->ParseSchema(psSchema);
+                                if (poSrcFDefn)
+                                    poLayer->BuildLayerDefn(poSrcFDefn);
+                            }
                             break;
                         }
                         psIter = psIter->psNext;
@@ -1190,6 +1367,350 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn)
 }
 
 /************************************************************************/
+/*                       LoadMultipleLayerDefn()                        */
+/************************************************************************/
+
+/* TinyOWS doesn't support POST, but MapServer, GeoServer and Deegree do */
+#define USE_GET_FOR_DESCRIBE_FEATURE_TYPE 1
+
+void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
+                                             char* pszNS, char* pszNSVal)
+{
+    /*if (!bIsGEOSERVER)
+        return;*/
+
+    if (!bLoadMultipleLayerDefn)
+        return;
+
+    if (aoSetAlreadyTriedLayers.find(pszLayerName) != aoSetAlreadyTriedLayers.end())
+        return;
+
+    char* pszPrefix = CPLStrdup(pszLayerName);
+    char* pszColumn = strchr(pszPrefix, ':');
+    if (pszColumn)
+        *pszColumn = 0;
+    else
+        *pszPrefix = 0;
+
+#if USE_GET_FOR_DESCRIBE_FEATURE_TYPE == 1
+    CPLString osLayerToFetch(pszLayerName);
+#else
+    CPLString osTypeNameToPost;
+    osTypeNameToPost += "  <TypeName>";
+    osTypeNameToPost += pszLayerName;
+    osTypeNameToPost += "</TypeName>\n";
+#endif
+
+    int nLayersToFetch = 1;
+    aoSetAlreadyTriedLayers.insert(pszLayerName);
+
+    for(int i=0;i<nLayers;i++)
+    {
+        if (!papoLayers[i]->HasLayerDefn())
+        {
+            /* We must be careful to requests only layers with the same prefix/namespace */
+            const char* pszName = papoLayers[i]->GetName();
+            if ((pszPrefix[0] == 0 && strchr(pszName, ':') == NULL) ||
+                (pszPrefix[0] != 0 && strncmp(pszName, pszPrefix, strlen(pszPrefix)) == 0 &&
+                 pszName[strlen(pszPrefix)] == ':'))
+            {
+                if (aoSetAlreadyTriedLayers.find(pszName) != aoSetAlreadyTriedLayers.end())
+                    continue;
+                aoSetAlreadyTriedLayers.insert(pszName);
+
+#if USE_GET_FOR_DESCRIBE_FEATURE_TYPE == 1
+                if (nLayersToFetch > 0)
+                    osLayerToFetch += ",";
+                osLayerToFetch += papoLayers[i]->GetName();
+#else
+                osTypeNameToPost += "  <TypeName>";
+                osTypeNameToPost += pszName;
+                osTypeNameToPost += "</TypeName>\n";
+#endif
+                nLayersToFetch ++;
+
+                /* Avoid fetching to many layer definition at a time */
+                if (nLayersToFetch >= 50)
+                    break;
+            }
+        }
+    }
+
+    CPLFree(pszPrefix);
+    pszPrefix = NULL;
+
+#if USE_GET_FOR_DESCRIBE_FEATURE_TYPE == 1
+    CPLString osURL(osBaseURL);
+    osURL = CPLURLAddKVP(osURL, "SERVICE", "WFS");
+    osURL = CPLURLAddKVP(osURL, "VERSION", GetVersion());
+    osURL = CPLURLAddKVP(osURL, "REQUEST", "DescribeFeatureType");
+    osURL = CPLURLAddKVP(osURL, "TYPENAME", osLayerToFetch);
+    osURL = CPLURLAddKVP(osURL, "PROPERTYNAME", NULL);
+    osURL = CPLURLAddKVP(osURL, "MAXFEATURES", NULL);
+    osURL = CPLURLAddKVP(osURL, "FILTER", NULL);
+    osURL = CPLURLAddKVP(osURL, "OUTPUTFORMAT", GetRequiredOutputFormat());
+
+    if (pszNS && GetNeedNAMESPACE())
+    {
+        /* Older Deegree version require NAMESPACE */
+        /* This has been now corrected */
+        CPLString osValue("xmlns(");
+        osValue += pszNS;
+        osValue += "=";
+        osValue += pszNSVal;
+        osValue += ")";
+        osURL = CPLURLAddKVP(osURL, "NAMESPACE", osValue);
+    }
+
+    CPLHTTPResult* psResult = HTTPFetch( osURL, NULL);
+#else
+    CPLString osPost;
+    osPost += "<?xml version=\"1.0\"?>\n";
+    osPost += "<wfs:DescribeFeatureType xmlns:wfs=\"http://www.opengis.net/wfs\"\n";
+    osPost += "                 xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
+    osPost += "                 service=\"WFS\" version=\""; osPost += GetVersion(); osPost += "\"\n";
+    osPost += "                 xmlns:gml=\"http://www.opengis.net/gml\"\n";
+    osPost += "                 xmlns:ogc=\"http://www.opengis.net/ogc\"\n";
+    if (pszNS && pszNSVal)
+    {
+        osPost += "                 xmlns:";
+        osPost += pszNS;
+        osPost += "=\"";
+        osPost += pszNSVal;
+        osPost += "\"\n";
+    }
+    osPost += "                 xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/";
+    osPost += GetVersion();
+    osPost += "/wfs.xsd\"";
+    if (osRequiredOutputFormat.size())
+    {
+        osPost += "\n";
+        osPost += "                 outputFormat=\"";
+        osPost += osRequiredOutputFormat;
+        osPost += "\"";
+    }
+    osPost += ">\n";
+    osPost += osTypeNameToPost;
+    osPost += "</wfs:DescribeFeatureType>\n";
+
+    //CPLDebug("WFS", "%s", osPost.c_str());
+
+    char** papszOptions = NULL;
+    papszOptions = CSLAddNameValue(papszOptions, "POSTFIELDS", osPost.c_str());
+    papszOptions = CSLAddNameValue(papszOptions, "HEADERS",
+                                   "Content-Type: application/xml; charset=UTF-8");
+
+    CPLHTTPResult* psResult = HTTPFetch(GetPostTransactionURL(), papszOptions);
+    CSLDestroy(papszOptions);
+#endif
+
+    if (psResult == NULL)
+    {
+        bLoadMultipleLayerDefn = FALSE;
+        return;
+    }
+
+    if (strstr((const char*)psResult->pabyData, "<ServiceExceptionReport") != NULL)
+    {
+        if (IsOldDeegree((const char*)psResult->pabyData))
+        {
+            /* just silently forgive */
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Error returned by server : %s",
+                    psResult->pabyData);
+        }
+        CPLHTTPDestroyResult(psResult);
+        bLoadMultipleLayerDefn = FALSE;
+        return;
+    }
+
+    CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
+    if (psXML == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid XML content : %s",
+                psResult->pabyData);
+        CPLHTTPDestroyResult(psResult);
+        bLoadMultipleLayerDefn = FALSE;
+        return;
+    }
+    CPLHTTPDestroyResult(psResult);
+
+    CPLXMLNode* psSchema = WFSFindNode(psXML, "schema");
+    if (psSchema == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find <Schema>");
+        CPLDestroyXMLNode( psXML );
+        bLoadMultipleLayerDefn = FALSE;
+        return;
+    }
+
+    CPLString osTmpFileName;
+
+    osTmpFileName = CPLSPrintf("/vsimem/tempwfs_%p/file.xsd", this);
+    CPLSerializeXMLTreeToFile(psSchema, osTmpFileName);
+
+    std::vector<GMLFeatureClass*> aosClasses;
+    GMLParseXSD( osTmpFileName, aosClasses );
+
+    if ((int)aosClasses.size() == nLayersToFetch)
+    {
+        std::vector<GMLFeatureClass*>::const_iterator iter = aosClasses.begin();
+        std::vector<GMLFeatureClass*>::const_iterator eiter = aosClasses.end();
+        while (iter != eiter)
+        {
+            GMLFeatureClass* poClass = *iter;
+            iter ++;
+
+            OGRWFSLayer* poLayer;
+
+            if (bKeepLayerNamePrefix && pszNS != NULL && strchr(poClass->GetName(), ':') == NULL)
+            {
+                CPLString osWithPrefix(pszNS);
+                osWithPrefix += ":";
+                osWithPrefix += poClass->GetName();
+                poLayer = (OGRWFSLayer* )GetLayerByName(osWithPrefix);
+            }
+            else
+                poLayer = (OGRWFSLayer* )GetLayerByName(poClass->GetName());
+
+            if (poLayer)
+            {
+                if (!poLayer->HasLayerDefn())
+                {
+                    CPLXMLNode* psSchemaForLayer = CPLCloneXMLTree(psSchema);
+                    CPLStripXMLNamespace( psSchemaForLayer, NULL, TRUE );
+                    CPLXMLNode* psIter = psSchemaForLayer->psChild;
+                    int bHasAlreadyImportedGML = FALSE;
+                    int bFoundComplexType = FALSE;
+                    int bFoundElement = FALSE;
+                    while(psIter != NULL)
+                    {
+                        CPLXMLNode* psIterNext = psIter->psNext;
+                        if (psIter->eType == CXT_Element &&
+                            strcmp(psIter->pszValue,"complexType") == 0)
+                        {
+                            const char* pszName = CPLGetXMLValue(psIter, "name", "");
+                            CPLString osExpectedName(poLayer->GetShortName());
+                            osExpectedName += "Type";
+                            CPLString osExpectedName2(poLayer->GetShortName());
+                            osExpectedName2 += "_Type";
+                            if (strcmp(pszName, osExpectedName) == 0 ||
+                                strcmp(pszName, osExpectedName2) == 0 ||
+                                strcmp(pszName, poLayer->GetShortName()) == 0)
+                            {
+                                bFoundComplexType = TRUE;
+                            }
+                            else
+                            {
+                                CPLRemoveXMLChild( psSchemaForLayer, psIter );
+                                CPLDestroyXMLNode(psIter);
+                            }
+                        }
+                        else if (psIter->eType == CXT_Element &&
+                                strcmp(psIter->pszValue,"element") == 0)
+                        {
+                            const char* pszName = CPLGetXMLValue(psIter, "name", "");
+                            CPLString osExpectedName(poLayer->GetShortName());
+                            osExpectedName += "Type";
+                            CPLString osExpectedName2(poLayer->GetShortName());
+                            osExpectedName2 += "_Type";
+
+                            const char* pszType = CPLGetXMLValue(psIter, "type", "");
+                            CPLString osExpectedType(poLayer->GetName());
+                            osExpectedType += "Type";
+                            CPLString osExpectedType2(poLayer->GetName());
+                            osExpectedType2 += "_Type";
+                            if (strcmp(pszType, osExpectedType) == 0 ||
+                                strcmp(pszType, osExpectedType2) == 0 ||
+                                strcmp(pszType, poLayer->GetName()) == 0 ||
+                                (strchr(pszType, ':') &&
+                                 (strcmp(strchr(pszType, ':') + 1, osExpectedType) == 0 ||
+                                  strcmp(strchr(pszType, ':') + 1, osExpectedType2) == 0)))
+                            {
+                                bFoundElement = TRUE;
+                            }
+                            else if (*pszType == '\0' &&
+                                     CPLGetXMLNode(psIter, "complexType") != NULL &&
+                                     (strcmp(pszName, osExpectedName) == 0 ||
+                                      strcmp(pszName, osExpectedName2) == 0 ||
+                                      strcmp(pszName, poLayer->GetShortName()) == 0) )
+                            {
+                                bFoundElement = TRUE;
+                                bFoundComplexType = TRUE;
+                            }
+                            else
+                            {
+                                CPLRemoveXMLChild( psSchemaForLayer, psIter );
+                                CPLDestroyXMLNode(psIter);
+                            }
+                        }
+                        else if (psIter->eType == CXT_Element &&
+                                strcmp(psIter->pszValue,"import") == 0 &&
+                                strcmp(CPLGetXMLValue(psIter, "namespace", ""),
+                                        "http://www.opengis.net/gml") == 0)
+                        {
+                            if (bHasAlreadyImportedGML)
+                            {
+                                CPLRemoveXMLChild( psSchemaForLayer, psIter );
+                                CPLDestroyXMLNode(psIter);
+                            }
+                            else
+                                bHasAlreadyImportedGML = TRUE;
+                        }
+                        psIter = psIterNext;
+                    }
+
+                    if (bFoundComplexType && bFoundElement)
+                    {
+                        OGRFeatureDefn* poSrcFDefn = poLayer->ParseSchema(psSchemaForLayer);
+                        if (poSrcFDefn)
+                        {
+                            poLayer->BuildLayerDefn(poSrcFDefn);
+                            SaveLayerSchema(poLayer->GetName(), psSchemaForLayer);
+                        }
+                    }
+
+                    CPLDestroyXMLNode(psSchemaForLayer);
+                }
+                else
+                {
+                    CPLDebug("WFS", "Found several time schema for layer %s in server response. Shouldn't happen",
+                             poClass->GetName());
+                }
+            }
+            else
+            {
+                CPLDebug("WFS", "Cannot find layer %s. Shouldn't happen",
+                            poClass->GetName());
+            }
+            delete poClass;
+        }
+    }
+    else if (aosClasses.size() > 0)
+    {
+        std::vector<GMLFeatureClass*>::const_iterator iter = aosClasses.begin();
+        std::vector<GMLFeatureClass*>::const_iterator eiter = aosClasses.end();
+        while (iter != eiter)
+        {
+            GMLFeatureClass* poClass = *iter;
+            iter ++;
+            delete poClass;
+        }
+    }
+    else
+    {
+        CPLDebug("WFS", "Turn off loading of multiple layer definitions at a single time");
+        bLoadMultipleLayerDefn = FALSE;
+    }
+
+    VSIUnlink(osTmpFileName);
+
+    CPLDestroyXMLNode( psXML );
+}
+
+/************************************************************************/
 /*                         SaveLayerSchema()                            */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
index 47eabb0..b989c2f 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfsfilter.cpp 21042 2010-11-01 15:45:31Z rouault $
+ * $Id: ogrwfsfilter.cpp 23161 2011-10-02 15:14:07Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGR SQL into OGC Filter translation.
@@ -31,7 +31,7 @@
 
 #include "cpl_list.h"
 
-CPL_CVSID("$Id: ogrwfsfilter.cpp 21042 2010-11-01 15:45:31Z rouault $");
+CPL_CVSID("$Id: ogrwfsfilter.cpp 23161 2011-10-02 15:14:07Z rouault $");
 
 typedef enum
 {
@@ -213,7 +213,8 @@ static void WFS_ExprDump(FILE* fp, const Expr* expr)
 static int WFS_ExprDumpGmlObjectIdFilter(CPLString& osFilter,
                                          const Expr* expr,
                                          int bUseFeatureId,
-                                         int bGmlObjectIdNeedsGMLPrefix)
+                                         int bGmlObjectIdNeedsGMLPrefix,
+                                         int nVersion)
 {
     if (expr->eType == TOKEN_EQUAL &&
         expr->expr1->eType == TOKEN_VAR_NAME &&
@@ -222,6 +223,8 @@ static int WFS_ExprDumpGmlObjectIdFilter(CPLString& osFilter,
     {
         if (bUseFeatureId)
             osFilter += "<FeatureId fid=\"";
+        else if (nVersion >= 200)
+            osFilter += "<ResourceId rid=\"";
         else if (!bGmlObjectIdNeedsGMLPrefix)
             osFilter += "<GmlObjectId id=\"";
         else
@@ -240,9 +243,9 @@ static int WFS_ExprDumpGmlObjectIdFilter(CPLString& osFilter,
     else if (expr->eType == TOKEN_OR)
     {
         return WFS_ExprDumpGmlObjectIdFilter(osFilter, expr->expr1,
-                                             bUseFeatureId, bGmlObjectIdNeedsGMLPrefix) &&
+                                             bUseFeatureId, bGmlObjectIdNeedsGMLPrefix, nVersion) &&
                WFS_ExprDumpGmlObjectIdFilter(osFilter, expr->expr2,
-                                             bUseFeatureId, bGmlObjectIdNeedsGMLPrefix);
+                                             bUseFeatureId, bGmlObjectIdNeedsGMLPrefix, nVersion);
     }
     return FALSE;
 }
@@ -278,7 +281,10 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
                 EQUAL(expr->pszVal, "OGR_STYLE"))
                 return FALSE;
 
-            osFilter += "<PropertyName>";
+            if (psOptions->nVersion >= 200)
+                osFilter += "<ValueReference>";
+            else
+                osFilter += "<PropertyName>";
             if (expr->pszVal[0] == '\'' || expr->pszVal[0] == '"')
             {
                 CPLString osVal(expr->pszVal + 1);
@@ -287,7 +293,10 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
             }
             else
                 osFilter += expr->pszVal;
-            osFilter += "</PropertyName>";
+            if (psOptions->nVersion >= 200)
+                osFilter += "</ValueReference>";
+            else
+                osFilter += "</PropertyName>";
             break;
 
         case TOKEN_LITERAL:
@@ -808,7 +817,7 @@ CPLString WFS_TurnSQLFilterToOGCFilter( const char * pszFilter,
     /* If the filter is only made of querying one or several gml_id */
     /* (with OR operator), we turn this to <GmlObjectId> list */
     if (!WFS_ExprDumpGmlObjectIdFilter(osFilter, expr, bUseFeatureId,
-                                       bGmlObjectIdNeedsGMLPrefix))
+                                       bGmlObjectIdNeedsGMLPrefix, nVersion))
     {
         ExprDumpFilterOptions sOptions;
         sOptions.nVersion = nVersion;
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
index b467b26..1841ba7 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfslayer.cpp 21196 2010-12-04 22:24:32Z rouault $
+ * $Id: ogrwfslayer.cpp 23374 2011-11-13 18:20:08Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSLayer class.
@@ -27,16 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <vector>
-
+#include "cpl_port.h"
 #include "ogr_wfs.h"
-
 #include "ogr_api.h"
 #include "cpl_minixml.h"
 #include "cpl_http.h"
 #include "parsexsd.h"
 
-CPL_CVSID("$Id: ogrwfslayer.cpp 21196 2010-12-04 22:24:32Z rouault $");
+CPL_CVSID("$Id: ogrwfslayer.cpp 23374 2011-11-13 18:20:08Z rouault $");
 
 
 /************************************************************************/
@@ -161,14 +159,15 @@ OGRWFSLayer::~OGRWFSLayer()
 CPLString OGRWFSLayer::GetDescribeFeatureTypeURL(int bWithNS)
 {
     CPLString osURL(pszBaseURL);
-    osURL = WFS_AddKVToURL(osURL, "SERVICE", "WFS");
-    osURL = WFS_AddKVToURL(osURL, "VERSION", poDS->GetVersion());
-    osURL = WFS_AddKVToURL(osURL, "REQUEST", "DescribeFeatureType");
-    osURL = WFS_AddKVToURL(osURL, "TYPENAME", pszName);
-    osURL = WFS_AddKVToURL(osURL, "PROPERTYNAME", NULL);
-    osURL = WFS_AddKVToURL(osURL, "MAXFEATURES", NULL);
-    osURL = WFS_AddKVToURL(osURL, "FILTER", NULL);
-    osURL = WFS_AddKVToURL(osURL, "OUTPUTFORMAT", poDS->GetRequiredOutputFormat());
+    osURL = CPLURLAddKVP(osURL, "SERVICE", "WFS");
+    osURL = CPLURLAddKVP(osURL, "VERSION", poDS->GetVersion());
+    osURL = CPLURLAddKVP(osURL, "REQUEST", "DescribeFeatureType");
+    osURL = CPLURLAddKVP(osURL, "TYPENAME", pszName);
+    osURL = CPLURLAddKVP(osURL, "PROPERTYNAME", NULL);
+    osURL = CPLURLAddKVP(osURL, "MAXFEATURES", NULL);
+    osURL = CPLURLAddKVP(osURL, "COUNT", NULL);
+    osURL = CPLURLAddKVP(osURL, "FILTER", NULL);
+    osURL = CPLURLAddKVP(osURL, "OUTPUTFORMAT", poDS->GetRequiredOutputFormat());
 
     if (pszNS && poDS->GetNeedNAMESPACE())
     {
@@ -179,7 +178,7 @@ CPLString OGRWFSLayer::GetDescribeFeatureTypeURL(int bWithNS)
         osValue += "=";
         osValue += pszNSVal;
         osValue += ")";
-        osURL = WFS_AddKVToURL(osURL, "NAMESPACE", osValue);
+        osURL = CPLURLAddKVP(osURL, "NAMESPACE", osValue);
     }
 
     return osURL;
@@ -259,55 +258,7 @@ OGRFeatureDefn* OGRWFSLayer::ParseSchema(CPLXMLNode* psSchema)
 
     if (bHaveSchema && aosClasses.size() == 1)
     {
-        poGMLFeatureClass = aosClasses[0];
-
-        OGRFeatureDefn* poFDefn = new OGRFeatureDefn(poGMLFeatureClass->GetName());
-        poFDefn->SetGeomType( (OGRwkbGeometryType)poGMLFeatureClass->GetGeometryType() );
-
-    /* -------------------------------------------------------------------- */
-    /*      Added attributes (properties).                                  */
-    /* -------------------------------------------------------------------- */
-        OGRFieldDefn oField( "gml_id", OFTString );
-        poFDefn->AddFieldDefn( &oField );
-
-        for( int iField = 0; iField < poGMLFeatureClass->GetPropertyCount(); iField++ )
-        {
-            GMLPropertyDefn *poProperty = poGMLFeatureClass->GetProperty( iField );
-            OGRFieldType eFType;
-
-            if( poProperty->GetType() == GMLPT_Untyped )
-                eFType = OFTString;
-            else if( poProperty->GetType() == GMLPT_String )
-                eFType = OFTString;
-            else if( poProperty->GetType() == GMLPT_Integer )
-                eFType = OFTInteger;
-            else if( poProperty->GetType() == GMLPT_Real )
-                eFType = OFTReal;
-            else if( poProperty->GetType() == GMLPT_StringList )
-                eFType = OFTStringList;
-            else if( poProperty->GetType() == GMLPT_IntegerList )
-                eFType = OFTIntegerList;
-            else if( poProperty->GetType() == GMLPT_RealList )
-                eFType = OFTRealList;
-            else
-                eFType = OFTString;
-
-            OGRFieldDefn oField( poProperty->GetName(), eFType );
-            if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
-                oField.SetName(poProperty->GetName()+4);
-            if( poProperty->GetWidth() > 0 )
-                oField.SetWidth( poProperty->GetWidth() );
-            if( poProperty->GetPrecision() > 0 )
-                oField.SetPrecision( poProperty->GetPrecision() );
-
-            poFDefn->AddFieldDefn( &oField );
-        }
-
-        const char* pszGeometryColumnName = poGMLFeatureClass->GetGeometryElement();
-        if (pszGeometryColumnName)
-            osGeometryColumnName = pszGeometryColumnName;
-
-        return poFDefn;
+        return BuildLayerDefnFromFeatureClass(aosClasses[0]);
     }
     else if (bHaveSchema)
     {
@@ -325,6 +276,62 @@ OGRFeatureDefn* OGRWFSLayer::ParseSchema(CPLXMLNode* psSchema)
 
     return NULL;
 }
+/************************************************************************/
+/*                   BuildLayerDefnFromFeatureClass()                   */
+/************************************************************************/
+
+OGRFeatureDefn* OGRWFSLayer::BuildLayerDefnFromFeatureClass(GMLFeatureClass* poClass)
+{
+    this->poGMLFeatureClass = poClass;
+
+    OGRFeatureDefn* poFDefn = new OGRFeatureDefn(poDS->GetKeepLayerNamePrefix() ? pszName : poGMLFeatureClass->GetName());
+    poFDefn->SetGeomType( (OGRwkbGeometryType)poGMLFeatureClass->GetGeometryType() );
+
+/* -------------------------------------------------------------------- */
+/*      Added attributes (properties).                                  */
+/* -------------------------------------------------------------------- */
+    OGRFieldDefn oField( "gml_id", OFTString );
+    poFDefn->AddFieldDefn( &oField );
+
+    for( int iField = 0; iField < poGMLFeatureClass->GetPropertyCount(); iField++ )
+    {
+        GMLPropertyDefn *poProperty = poGMLFeatureClass->GetProperty( iField );
+        OGRFieldType eFType;
+
+        if( poProperty->GetType() == GMLPT_Untyped )
+            eFType = OFTString;
+        else if( poProperty->GetType() == GMLPT_String )
+            eFType = OFTString;
+        else if( poProperty->GetType() == GMLPT_Integer )
+            eFType = OFTInteger;
+        else if( poProperty->GetType() == GMLPT_Real )
+            eFType = OFTReal;
+        else if( poProperty->GetType() == GMLPT_StringList )
+            eFType = OFTStringList;
+        else if( poProperty->GetType() == GMLPT_IntegerList )
+            eFType = OFTIntegerList;
+        else if( poProperty->GetType() == GMLPT_RealList )
+            eFType = OFTRealList;
+        else
+            eFType = OFTString;
+
+        OGRFieldDefn oField( poProperty->GetName(), eFType );
+        if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
+            oField.SetName(poProperty->GetName()+4);
+        if( poProperty->GetWidth() > 0 )
+            oField.SetWidth( poProperty->GetWidth() );
+        if( poProperty->GetPrecision() > 0 )
+            oField.SetPrecision( poProperty->GetPrecision() );
+
+        poFDefn->AddFieldDefn( &oField );
+    }
+
+    const char* pszGeometryColumnName = poGMLFeatureClass->GetGeometryElement();
+    if (pszGeometryColumnName)
+        osGeometryColumnName = pszGeometryColumnName;
+
+    return poFDefn;
+}
 
 /************************************************************************/
 /*                       MakeGetFeatureURL()                            */
@@ -333,12 +340,12 @@ OGRFeatureDefn* OGRWFSLayer::ParseSchema(CPLXMLNode* psSchema)
 CPLString OGRWFSLayer::MakeGetFeatureURL(int nMaxFeatures, int bRequestHits)
 {
     CPLString osURL(pszBaseURL);
-    osURL = WFS_AddKVToURL(osURL, "SERVICE", "WFS");
-    osURL = WFS_AddKVToURL(osURL, "VERSION", poDS->GetVersion());
-    osURL = WFS_AddKVToURL(osURL, "REQUEST", "GetFeature");
-    osURL = WFS_AddKVToURL(osURL, "TYPENAME", pszName);
+    osURL = CPLURLAddKVP(osURL, "SERVICE", "WFS");
+    osURL = CPLURLAddKVP(osURL, "VERSION", poDS->GetVersion());
+    osURL = CPLURLAddKVP(osURL, "REQUEST", "GetFeature");
+    osURL = CPLURLAddKVP(osURL, "TYPENAME", pszName);
     if (poDS->GetRequiredOutputFormat())
-        osURL = WFS_AddKVToURL(osURL, "OUTPUTFORMAT", poDS->GetRequiredOutputFormat());
+        osURL = CPLURLAddKVP(osURL, "OUTPUTFORMAT", poDS->GetRequiredOutputFormat());
 
     if (poDS->IsPagingAllowed() && !bRequestHits)
     {
@@ -352,20 +359,22 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nMaxFeatures, int bRequestHits)
         }
         if (nFeatures >= poDS->GetPageSize())
         {
-            osURL = WFS_AddKVToURL(osURL, "STARTINDEX", CPLSPrintf("%d", nPagingStartIndex + 1));
+            osURL = CPLURLAddKVP(osURL, "STARTINDEX", CPLSPrintf("%d", nPagingStartIndex + 1));
             nMaxFeatures = poDS->GetPageSize();
             nFeatureCountRequested = nMaxFeatures;
             bPagingActive = TRUE;
         }
         else
         {
-            osURL = WFS_AddKVToURL(osURL, "STARTINDEX", NULL);
+            osURL = CPLURLAddKVP(osURL, "STARTINDEX", NULL);
         }
     }
 
     if (nMaxFeatures)
     {
-        osURL = WFS_AddKVToURL(osURL, "MAXFEATURES", CPLSPrintf("%d", nMaxFeatures));
+        osURL = CPLURLAddKVP(osURL,
+                             atoi(poDS->GetVersion()) >= 2 ? "COUNT" : "MAXFEATURES",
+                             CPLSPrintf("%d", nMaxFeatures));
     }
     if (pszNS && poDS->GetNeedNAMESPACE())
     {
@@ -376,7 +385,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nMaxFeatures, int bRequestHits)
         osValue += "=";
         osValue += pszNSVal;
         osValue += ")";
-        osURL = WFS_AddKVToURL(osURL, "NAMESPACE", osValue);
+        osURL = CPLURLAddKVP(osURL, "NAMESPACE", osValue);
     }
 
     delete poFetchedFilterGeom;
@@ -392,37 +401,67 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nMaxFeatures, int bRequestHits)
         poFetchedFilterGeom = m_poFilterGeom->clone();
 
         osGeomFilter = "<BBOX>";
-        osGeomFilter += "<PropertyName>";
+        if (atoi(poDS->GetVersion()) >= 2)
+            osGeomFilter += "<ValueReference>";
+        else
+            osGeomFilter += "<PropertyName>";
         if (pszNS)
         {
             osGeomFilter += pszNS;
             osGeomFilter += ":";
         }
         osGeomFilter += osGeometryColumnName;
-        osGeomFilter += "</PropertyName>";
-        osGeomFilter += "<gml:Box>";
-        osGeomFilter += "<gml:coordinates>";
-        if (bAxisOrderAlreadyInverted)
+        if (atoi(poDS->GetVersion()) >= 2)
+            osGeomFilter += "</ValueReference>";
+        else
+            osGeomFilter += "</PropertyName>";
+        if ( poDS->RequiresEnvelopeSpatialFilter() )
         {
-            /* We can go here in WFS 1.1 with geographic coordinate systems */
-            /* that are natively return in lat,long order, but as we have */
-            /* presented long,lat order to the user, we must switch back */
-            /* for the server... */
-            osGeomFilter += CPLSPrintf("%.16f,%.16f %.16f,%.16f", oEnvelope.MinY, oEnvelope.MinX, oEnvelope.MaxY, oEnvelope.MaxX);
+            osGeomFilter += "<Envelope xmlns=\"http://www.opengis.net/gml\">";
+            if (bAxisOrderAlreadyInverted)
+            {
+                /* We can go here in WFS 1.1 with geographic coordinate systems */
+                /* that are natively return in lat,long order, but as we have */
+                /* presented long,lat order to the user, we must switch back */
+                /* for the server... */
+                osGeomFilter += CPLSPrintf("<coord><X>%.16f</X><Y>%.16f</Y></coord><coord><X>%.16f</X><Y>%.16f</Y></coord>",
+                                        oEnvelope.MinY, oEnvelope.MinX, oEnvelope.MaxY, oEnvelope.MaxX);
+            }
+            else
+                osGeomFilter += CPLSPrintf("<coord><X>%.16f</X><Y>%.16f</Y></coord><coord><X>%.16f</X><Y>%.16f</Y></coord>",
+                                        oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
+            osGeomFilter += "</Envelope>";
         }
         else
-            osGeomFilter += CPLSPrintf("%.16f,%.16f %.16f,%.16f", oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
-        osGeomFilter += "</gml:coordinates>";
-        osGeomFilter += "</gml:Box>";
+        {
+            osGeomFilter += "<gml:Box>";
+            osGeomFilter += "<gml:coordinates>";
+            if (bAxisOrderAlreadyInverted)
+            {
+                /* We can go here in WFS 1.1 with geographic coordinate systems */
+                /* that are natively return in lat,long order, but as we have */
+                /* presented long,lat order to the user, we must switch back */
+                /* for the server... */
+                osGeomFilter += CPLSPrintf("%.16f,%.16f %.16f,%.16f", oEnvelope.MinY, oEnvelope.MinX, oEnvelope.MaxY, oEnvelope.MaxX);
+            }
+            else
+                osGeomFilter += CPLSPrintf("%.16f,%.16f %.16f,%.16f", oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
+            osGeomFilter += "</gml:coordinates>";
+            osGeomFilter += "</gml:Box>";
+        }
         osGeomFilter += "</BBOX>";
     }
 
     if (osGeomFilter.size() != 0 || osWFSWhere.size() != 0)
     {
-        CPLString osFilter = "<Filter ";
+        CPLString osFilter;
+        if (atoi(poDS->GetVersion()) >= 2)
+            osFilter = "<Filter xmlns=\"http://www.opengis.net/fes/2.0\"";
+        else
+            osFilter = "<Filter xmlns=\"http://www.opengis.net/ogc\"";
         if (pszNS)
         {
-            osFilter += "xmlns:";
+            osFilter += " xmlns:";
             osFilter += pszNS;
             osFilter += "=\"";
             osFilter += pszNSVal;
@@ -437,16 +476,17 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nMaxFeatures, int bRequestHits)
             osFilter += "</And>";
         osFilter += "</Filter>";
 
-        osURL = WFS_AddKVToURL(osURL, "FILTER", osFilter);
+        osURL = CPLURLAddKVP(osURL, "FILTER", osFilter);
     }
         
     if (bRequestHits)
     {
-        osURL = WFS_AddKVToURL(osURL, "RESULTTYPE", "hits");
+        osURL = CPLURLAddKVP(osURL, "RESULTTYPE", "hits");
     }
 
     /* If no PROPERTYNAME is specified, build one if there are ignored fields */
-    const char* pszPropertyName = WFS_FetchValueFromURL(osURL, "PROPERTYNAME");
+    CPLString osPropertyName = CPLURLGetValue(osURL, "PROPERTYNAME");
+    const char* pszPropertyName = osPropertyName.c_str();
     if (pszPropertyName[0] == 0 && poFeatureDefn != NULL)
     {
         int bHasIgnoredField = FALSE;
@@ -485,7 +525,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nMaxFeatures, int bRequestHits)
         if (bHasIgnoredField)
         {
             osPropertyName = "(" + osPropertyName + ")";
-            osURL = WFS_AddKVToURL(osURL, "PROPERTYNAME", osPropertyName);
+            osURL = CPLURLAddKVP(osURL, "PROPERTYNAME", osPropertyName);
         }
     }
 
@@ -592,7 +632,7 @@ OGRDataSource* OGRWFSLayer::FetchGetFeature(int nMaxFeatures)
     int bZIP = FALSE;
     int bGZIP = FALSE;
 
-    CPLString osOutputFormat = WFS_FetchValueFromURL(osURL, "OUTPUTFORMAT");
+    CPLString osOutputFormat = CPLURLGetValue(osURL, "OUTPUTFORMAT");
     const char* pszOutputFormat = osOutputFormat.c_str();
 
     if (FindSubStringInsensitive(pszContentType, "json") ||
@@ -782,6 +822,11 @@ OGRFeatureDefn * OGRWFSLayer::GetLayerDefn()
     if (poFeatureDefn)
         return poFeatureDefn;
 
+    poDS->LoadMultipleLayerDefn(GetName(), pszNS, pszNSVal);
+
+    if (poFeatureDefn)
+        return poFeatureDefn;
+
     return BuildLayerDefn();
 }
 
@@ -789,17 +834,14 @@ OGRFeatureDefn * OGRWFSLayer::GetLayerDefn()
 /*                          BuildLayerDefn()                            */
 /************************************************************************/
 
-OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(CPLXMLNode* psSchema)
+OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
 {
     poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
 
     OGRDataSource* poDS = NULL;
 
-    OGRFeatureDefn* poSrcFDefn = NULL;
-    if (psSchema)
-        poSrcFDefn = ParseSchema(psSchema);
-    else
+    if (poSrcFDefn == NULL)
         poSrcFDefn = DescribeFeatureType();
     if (poSrcFDefn == NULL)
     {
@@ -812,7 +854,8 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(CPLXMLNode* psSchema)
         bGotApproximateLayerDefn = TRUE;
     }
 
-    const char* pszPropertyName = WFS_FetchValueFromURL(pszBaseURL, "PROPERTYNAME");
+    CPLString osPropertyName = CPLURLGetValue(pszBaseURL, "PROPERTYNAME");
+    const char* pszPropertyName = osPropertyName.c_str();
 
     int i;
     poFeatureDefn->SetGeomType(poSrcFDefn->GetGeomType());
@@ -1045,7 +1088,8 @@ OGRErr OGRWFSLayer::SetAttributeFilter( const char * pszFilter )
     if (poDS->HasMinOperators() && pszFilter != NULL)
     {
         int bNeedsNullCheck = FALSE;
-        int nVersion = (strcmp(poDS->GetVersion(),"1.0.0") == 0) ? 100 : 110;
+        int nVersion = (strcmp(poDS->GetVersion(),"1.0.0") == 0) ? 100 :
+                       (atoi(poDS->GetVersion()) >= 2) ? 200 : 110;
         osWFSWhere = WFS_TurnSQLFilterToOGCFilter(pszFilter,
                                               nVersion,
                                               poDS->PropertyIsNotEqualToSupported(),
@@ -1129,7 +1173,7 @@ int OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
 {
     char* pabyData = NULL;
     CPLString osURL = MakeGetFeatureURL(0, TRUE);
-    osURL = WFS_AddKVToURL(osURL, "OUTPUTFORMAT", poDS->GetRequiredOutputFormat());
+    osURL = CPLURLAddKVP(osURL, "OUTPUTFORMAT", poDS->GetRequiredOutputFormat());
     CPLDebug("WFS", "%s", osURL.c_str());
 
     CPLHTTPResult* psResult = poDS->HTTPFetch( osURL, NULL);
@@ -1177,9 +1221,9 @@ int OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
         }
         VSIStatBufL sBuf;
         VSIStatL(osFileInZipTmpFileName.c_str(), &sBuf);
-        pabyData = (char*) CPLMalloc(sBuf.st_size + 1);
+        pabyData = (char*) CPLMalloc((size_t)(sBuf.st_size + 1));
         pabyData[sBuf.st_size] = 0;
-        VSIFReadL(pabyData, 1, sBuf.st_size, fp);
+        VSIFReadL(pabyData, 1, (size_t)sBuf.st_size, fp);
         VSIFCloseL(fp);
 
         CSLDestroy(papszDirContent);
@@ -1191,7 +1235,8 @@ int OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
         psResult->pabyData = NULL;
     }
 
-    if (strstr(pabyData, "<ServiceExceptionReport") != NULL)
+    if (strstr(pabyData, "<ServiceExceptionReport") != NULL ||
+        strstr(pabyData, "<ows:ExceptionReport") != NULL)
     {
         if (poDS->IsOldDeegree(pabyData))
         {
@@ -1228,6 +1273,8 @@ int OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
 
     const char* pszValue = CPLGetXMLValue(psRoot, "numberOfFeatures", NULL);
     if (pszValue == NULL)
+        pszValue = CPLGetXMLValue(psRoot, "numberMatched", NULL); /* WFS 2.0.0 */
+    if (pszValue == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find numberOfFeatures");
         CPLDestroyXMLNode( psXML );
@@ -1241,7 +1288,7 @@ int OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
     int nFeatures = atoi(pszValue);
     /* Hum, http://deegree3-testing.deegree.org:80/deegree-inspire-node/services?MAXFEATURES=10&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=ad:Address&OUTPUTFORMAT=text/xml;%20subtype=gml/3.2.1&RESULTTYPE=hits */
     /* returns more than MAXFEATURES features... So truncate to MAXFEATURES */
-    CPLString osMaxFeatures = WFS_FetchValueFromURL(osURL, "MAXFEATURES");
+    CPLString osMaxFeatures = CPLURLGetValue(osURL, atoi(poDS->GetVersion()) >= 2 ? "COUNT" : "MAXFEATURES");
     if (osMaxFeatures.size() != 0)
     {
         int nMaxFeatures = atoi(osMaxFeatures);
@@ -1422,7 +1469,15 @@ OGRErr OGRWFSLayer::CreateFeature( OGRFeature *poFeature )
             {
                 if (poGeom->getSpatialReference() == NULL)
                     poGeom->assignSpatialReference(poSRS);
-                char* pszGML = OGR_G_ExportToGML((OGRGeometryH)poGeom);
+                char* pszGML;
+                if (strcmp(poDS->GetVersion(), "1.1.0") == 0)
+                {
+                    char** papszOptions = CSLAddString(NULL, "FORMAT=GML3");
+                    pszGML = OGR_G_ExportToGMLEx((OGRGeometryH)poGeom, papszOptions);
+                    CSLDestroy(papszOptions);
+                }
+                else
+                    pszGML = OGR_G_ExportToGML((OGRGeometryH)poGeom);
                 osPost += "      <feature:"; osPost += osGeometryColumnName; osPost += ">";
                 osPost += pszGML;
                 osPost += "</feature:"; osPost += osGeometryColumnName; osPost += ">\n";
@@ -1656,7 +1711,15 @@ OGRErr OGRWFSLayer::SetFeature( OGRFeature *poFeature )
         {
             if (poGeom->getSpatialReference() == NULL)
                 poGeom->assignSpatialReference(poSRS);
-            char* pszGML = OGR_G_ExportToGML((OGRGeometryH)poGeom);
+            char* pszGML;
+            if (strcmp(poDS->GetVersion(), "1.1.0") == 0)
+            {
+                char** papszOptions = CSLAddString(NULL, "FORMAT=GML3");
+                pszGML = OGR_G_ExportToGMLEx((OGRGeometryH)poGeom, papszOptions);
+                CSLDestroy(papszOptions);
+            }
+            else
+                pszGML = OGR_G_ExportToGML((OGRGeometryH)poGeom);
             osPost += "      <wfs:Value>";
             osPost += pszGML;
             osPost += "</wfs:Value>\n";
@@ -1693,6 +1756,8 @@ OGRErr OGRWFSLayer::SetFeature( OGRFeature *poFeature )
     osPost += "    <ogc:Filter>\n";
     if (poDS->UseFeatureId() || bUseFeatureIdAtLayerLevel)
         osPost += "      <ogc:FeatureId fid=\"";
+    else if (atoi(poDS->GetVersion()) >= 2)
+        osPost += "      <ogc:ResourceId rid=\"";
     else
         osPost += "      <ogc:GmlObjectId gml:id=\"";
     osPost += poFeature->GetFieldAsString(0); osPost += "\"/>\n";
diff --git a/ogr/ogrsf_frmts/xls/GNUmakefile b/ogr/ogrsf_frmts/xls/GNUmakefile
new file mode 100644
index 0000000..8eb4fdc
--- /dev/null
+++ b/ogr/ogrsf_frmts/xls/GNUmakefile
@@ -0,0 +1,14 @@
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrxlsdriver.o ogrxlsdatasource.o ogrxlslayer.o
+
+CPPFLAGS	:=	-I.. -I../.. $(FREEXL_INCLUDE) $(GDAL_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_xls.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/xls/drv_xls.html b/ogr/ogrsf_frmts/xls/drv_xls.html
new file mode 100644
index 0000000..1a4f72b
--- /dev/null
+++ b/ogr/ogrsf_frmts/xls/drv_xls.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+<title>XLS - MS Excel format</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>XLS - MS Excel format</h1>
+
+(GDAL/OGR >= 1.9.0)<p>
+
+This driver reads spreadsheets in MS Excel format. GDAL/OGR must be built against the FreeXL library (GPL/LPL/MPL licenced),
+and the driver has the same restrictions as the FreeXL library itself as far as which and how Excel files are supported.
+(At the time of writing - with FreeXL 1.0.0a -, it means in particular that formulas are not supported.)<p>
+
+Each sheet is presented as a OGR layer. No geometry support is available directly (but you may use the OGR VRT capabilities for that).<p>
+
+<h3>Configuration options</h3>
+
+<ul>
+<li>OGR_XLS_HEADERS = FORCE / DISABLE / AUTO : By default, the driver will read the first lines of each sheet to detect if the
+first line might be the name of columns. If set to FORCE, the driver will consider the first line will be taken as the header line.
+If set to DISABLE, it will be considered as the first feature. Otherwise auto-dection will occur.</li>
+<li>OGR_XLS_FIELD_TYPES = STRING / AUTO : By default, the driver will try to detect the data type of fields. If set to STRING,
+all fields will be of String type.</li>
+</ul>
+
+<h3>See Also</h3>
+
+<ul>
+<li> <a href="https://www.gaia-gis.it/fossil/freexl/index">Homepage of the FreeXL library</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/xls/makefile.vc b/ogr/ogrsf_frmts/xls/makefile.vc
new file mode 100644
index 0000000..cb0229f
--- /dev/null
+++ b/ogr/ogrsf_frmts/xls/makefile.vc
@@ -0,0 +1,15 @@
+
+OBJ	=	ogrxlsdriver.obj ogrxlsdatasource.obj ogrxlslayer.obj
+EXTRAFLAGS =	-I.. -I..\.. $(FREEXL_CFLAGS)
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.obj *.pdb
+
+
+
diff --git a/ogr/ogrsf_frmts/xls/ogr_xls.h b/ogr/ogrsf_frmts/xls/ogr_xls.h
new file mode 100644
index 0000000..80ec83e
--- /dev/null
+++ b/ogr/ogrsf_frmts/xls/ogr_xls.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ * $Id: ogr_xls.h 23695 2012-01-03 22:04:16Z 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>
+ *
+ * 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_XLS_H_INCLUDED
+#define _OGR_XLS_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+/************************************************************************/
+/*                             OGRXLSLayer                              */
+/************************************************************************/
+
+class OGRXLSDataSource;
+
+class OGRXLSLayer : public OGRLayer
+{
+    OGRXLSDataSource*  poDS;
+    OGRFeatureDefn*    poFeatureDefn;
+
+    char              *pszName;
+    int                iSheet;
+    int                bFirstLineIsHeaders;
+    int                nRows;
+    unsigned short     nCols;
+
+    int                nNextFID;
+
+    OGRFeature *       GetNextRawFeature();
+
+    void               DetectHeaderLine(const void* xlshandle);
+    void               DetectColumnTypes(const void* xlshandle,
+                                         int* paeFieldTypes);
+
+  public:
+                        OGRXLSLayer(OGRXLSDataSource* poDSIn,
+                                    const char* pszSheetname,
+                                    int iSheetIn,
+                                    int nRowsIn,
+                                    unsigned short nColsIn);
+                        ~OGRXLSLayer();
+
+
+    virtual void                ResetReading();
+    virtual OGRFeature *        GetNextFeature();
+
+    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual int                 GetFeatureCount( int bForce = TRUE );
+
+    virtual const char         *GetName() { return pszName; }
+    virtual OGRwkbGeometryType  GetGeomType() { return wkbNone; }
+
+    virtual int                 TestCapability( const char * );
+
+    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
+
+};
+
+/************************************************************************/
+/*                           OGRXLSDataSource                           */
+/************************************************************************/
+
+class OGRXLSDataSource : public OGRDataSource
+{
+    char*               pszName;
+
+    OGRLayer**          papoLayers;
+    int                 nLayers;
+
+    const void*         xlshandle;
+
+  public:
+                        OGRXLSDataSource();
+                        ~OGRXLSDataSource();
+
+    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 * );
+
+    const void                 *GetXLSHandle();
+};
+
+/************************************************************************/
+/*                             OGRXLSDriver                             */
+/************************************************************************/
+
+class OGRXLSDriver : public OGRSFDriver
+{
+  public:
+                ~OGRXLSDriver();
+
+    virtual const char*         GetName();
+    virtual OGRDataSource*      Open( const char *, int );
+    virtual int                 TestCapability( const char * );
+};
+
+
+#endif /* ndef _OGR_XLS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
new file mode 100644
index 0000000..eb6a516
--- /dev/null
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
@@ -0,0 +1,159 @@
+/******************************************************************************
+ * $Id: ogrxlsdatasource.cpp 23476 2011-12-05 22:57:06Z 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>
+ *
+ * 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 <freexl.h>
+
+#include "ogr_xls.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogrxlsdatasource.cpp 23476 2011-12-05 22:57:06Z rouault $");
+
+/************************************************************************/
+/*                          OGRXLSDataSource()                          */
+/************************************************************************/
+
+OGRXLSDataSource::OGRXLSDataSource()
+
+{
+    papoLayers = NULL;
+    nLayers = 0;
+
+    pszName = NULL;
+
+    xlshandle = NULL;
+}
+
+/************************************************************************/
+/*                         ~OGRXLSDataSource()                          */
+/************************************************************************/
+
+OGRXLSDataSource::~OGRXLSDataSource()
+
+{
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    CPLFree( pszName );
+
+    if (xlshandle)
+        freexl_close(xlshandle);
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRXLSDataSource::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRXLSDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRXLSDataSource::Open( const char * pszFilename, int bUpdateIn)
+
+{
+    if (bUpdateIn)
+    {
+        return FALSE;
+    }
+
+    pszName = CPLStrdup( pszFilename );
+
+// -------------------------------------------------------------------- 
+//      Does this appear to be a .xls file?
+// --------------------------------------------------------------------
+
+    /* Open only for getting info. To get cell values, we have to use freexl_open */
+    if (freexl_open_info (pszFilename, &xlshandle) != FREEXL_OK)
+        return FALSE;
+
+    unsigned int nSheets = 0;
+    if (freexl_get_info (xlshandle, FREEXL_BIFF_SHEET_COUNT, &nSheets) != FREEXL_OK)
+        return FALSE;
+
+    for(int i=0; i<(int)nSheets; i++)
+    {
+        freexl_select_active_worksheet(xlshandle, i);
+
+        const char* pszSheetname = NULL;
+        if (freexl_get_worksheet_name(xlshandle, i, &pszSheetname) != FREEXL_OK)
+            return FALSE;
+
+        unsigned int nRows = 0;
+        unsigned short nCols = 0;
+        if (freexl_worksheet_dimensions(xlshandle, &nRows, &nCols) != FREEXL_OK)
+            return FALSE;
+
+        /* Skip empty sheets */
+        if (nRows == 0)
+            continue;
+
+        papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
+        papoLayers[nLayers ++] = new OGRXLSLayer(this, pszSheetname, i, (int)nRows, nCols);
+    }
+
+    freexl_close(xlshandle);
+    xlshandle = NULL;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           GetXLSHandle()                             */
+/************************************************************************/
+
+const void* OGRXLSDataSource::GetXLSHandle()
+{
+    if (xlshandle)
+        return xlshandle;
+
+    if (freexl_open (pszName, &xlshandle) != FREEXL_OK)
+        return NULL;
+
+    return xlshandle;
+}
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
new file mode 100644
index 0000000..fe21385
--- /dev/null
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
@@ -0,0 +1,101 @@
+/******************************************************************************
+ * $Id: ogrxlsdriver.cpp 23381 2011-11-17 21:55:45Z 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>
+ *
+ * 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_xls.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrxlsdriver.cpp 23381 2011-11-17 21:55:45Z rouault $");
+
+/************************************************************************/
+/*                           ~OGRXLSDriver()                            */
+/************************************************************************/
+
+OGRXLSDriver::~OGRXLSDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRXLSDriver::GetName()
+
+{
+    return "XLS";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRXLSDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    if (bUpdate)
+    {
+        return NULL;
+    }
+
+    if (!EQUAL(CPLGetExtension(pszFilename), "XLS"))
+    {
+        return NULL;
+    }
+
+    OGRXLSDataSource   *poDS = new OGRXLSDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRXLSDriver::TestCapability( const char * pszCap )
+
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRXLS()                           */
+/************************************************************************/
+
+void RegisterOGRXLS()
+
+{
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRXLSDriver );
+}
+
diff --git a/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
new file mode 100644
index 0000000..448f388
--- /dev/null
+++ b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
@@ -0,0 +1,374 @@
+/******************************************************************************
+ * $Id: ogrxlslayer.cpp 23695 2012-01-03 22:04:16Z 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>
+ *
+ * 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 <freexl.h>
+
+#include "ogr_xls.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogrxlslayer.cpp 23695 2012-01-03 22:04:16Z rouault $");
+
+/************************************************************************/
+/*                            OGRXLSLayer()                             */
+/************************************************************************/
+
+OGRXLSLayer::OGRXLSLayer( OGRXLSDataSource* poDSIn,
+                          const char* pszSheetname,
+                          int iSheetIn,
+                          int nRowsIn,
+                          unsigned short nColsIn )
+
+{
+    poDS = poDSIn;
+    iSheet = iSheetIn;
+    nNextFID = 0;
+    bFirstLineIsHeaders = FALSE;
+    poFeatureDefn = NULL;
+    pszName = CPLStrdup(pszSheetname);
+    nRows = nRowsIn;
+    nCols = nColsIn;
+}
+
+/************************************************************************/
+/*                            ~OGRXLSLayer()                            */
+/************************************************************************/
+
+OGRXLSLayer::~OGRXLSLayer()
+
+{
+    CPLFree(pszName);
+    if (poFeatureDefn)
+        poFeatureDefn->Release();
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRXLSLayer::ResetReading()
+
+{
+    if (poFeatureDefn != NULL)
+    {
+        nNextFID = bFirstLineIsHeaders ? 1 : 0;
+    }
+}
+
+/************************************************************************/
+/*                          DetectHeaderLine()                          */
+/************************************************************************/
+
+void OGRXLSLayer::DetectHeaderLine(const void* xlshandle)
+
+{
+    unsigned short i;
+    FreeXL_CellValue sCellValue;
+    int nCountTextOnSecondLine = 0;
+    for(i = 0; i < nCols && nRows >= 2; i ++)
+    {
+        if (freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK)
+        {
+            if (sCellValue.type != FREEXL_CELL_TEXT &&
+                sCellValue.type != FREEXL_CELL_SST_TEXT)
+            {
+                /* If the values in the first line are not text, then it is */
+                /* not a header line */
+                break;
+            }
+        }
+        if (freexl_get_cell_value(xlshandle, 1, i, &sCellValue) == FREEXL_OK)
+        {
+            if (sCellValue.type == FREEXL_CELL_TEXT ||
+                sCellValue.type == FREEXL_CELL_SST_TEXT)
+            {
+                /* If there are only text values on the second line, then we cannot */
+                /* know if it is a header line or just a regular line */
+                nCountTextOnSecondLine ++;
+            }
+        }
+    }
+
+    const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
+    if (EQUAL(pszXLSHeaders, "FORCE"))
+        bFirstLineIsHeaders = TRUE;
+    else if (EQUAL(pszXLSHeaders, "DISABLE"))
+        bFirstLineIsHeaders = FALSE;
+    else if (i == nCols && nCountTextOnSecondLine != nCols)
+        bFirstLineIsHeaders = TRUE;
+}
+
+/************************************************************************/
+/*                         DetectColumnTypes()                          */
+/************************************************************************/
+
+void OGRXLSLayer::DetectColumnTypes(const void* xlshandle,
+                                    int* paeFieldTypes)
+
+{
+    int j;
+    unsigned short i;
+    FreeXL_CellValue sCellValue;
+    for(j = bFirstLineIsHeaders ? 1 : 0; j < nRows; j ++)
+    {
+        for(i = 0; i < nCols; i ++)
+        {
+            if (freexl_get_cell_value(xlshandle, j, i, &sCellValue) == FREEXL_OK)
+            {
+                OGRFieldType eType = (OGRFieldType) paeFieldTypes[i];
+                switch (sCellValue.type)
+                {
+                    case FREEXL_CELL_INT:
+                        eType = OFTInteger;
+                        break;
+                    case FREEXL_CELL_DOUBLE:
+                        eType = OFTReal;
+                        break;
+                    case FREEXL_CELL_TEXT:
+                    case FREEXL_CELL_SST_TEXT:
+                        eType = OFTString;
+                        break;
+                    case FREEXL_CELL_DATE:
+                        eType = OFTDate;
+                        break;
+                    case FREEXL_CELL_DATETIME:
+                        eType = OFTDateTime;
+                        break;
+                    case FREEXL_CELL_TIME:
+                        eType = OFTTime;
+                        break;
+                    case FREEXL_CELL_NULL:
+                        break;
+                    default:
+                        break;
+                }
+
+                if (paeFieldTypes[i] < 0)
+                {
+                    paeFieldTypes[i] = (int) eType;
+                }
+                else if ((int)eType != paeFieldTypes[i])
+                {
+                    if ((paeFieldTypes[i] == OFTDate ||
+                         paeFieldTypes[i] == OFTTime ||
+                         paeFieldTypes[i] == OFTDateTime) &&
+                        (eType == OFTDate || eType == OFTTime || eType == OFTDateTime))
+                        paeFieldTypes[i] = OFTDateTime;
+                    else if (paeFieldTypes[i] == OFTReal && eType == OFTInteger)
+                        /* nothing */ ;
+                    else if (paeFieldTypes[i] == OFTInteger && eType == OFTReal)
+                        paeFieldTypes[i] = OFTReal;
+                    else
+                        paeFieldTypes[i] = OFTString;
+                }
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                            GetLayerDefn()                            */
+/************************************************************************/
+
+OGRFeatureDefn * OGRXLSLayer::GetLayerDefn()
+{
+    if (poFeatureDefn)
+        return poFeatureDefn;
+
+    poFeatureDefn = new OGRFeatureDefn( pszName );
+    poFeatureDefn->Reference();
+    poFeatureDefn->SetGeomType( wkbNone );
+
+    const void* xlshandle = poDS->GetXLSHandle();
+    if (xlshandle == NULL)
+        return poFeatureDefn;
+
+    freexl_select_active_worksheet(xlshandle, iSheet);
+
+    if (nRows > 0)
+    {
+        unsigned short i;
+        FreeXL_CellValue sCellValue;
+
+        DetectHeaderLine(xlshandle);
+
+        int* paeFieldTypes = (int* )
+                            CPLMalloc(nCols * sizeof(int));
+        for(i = 0; i < nCols; i ++)
+        {
+            paeFieldTypes[i] = -1;
+        }
+
+        const char* pszXLSFieldTypes =
+                        CPLGetConfigOption("OGR_XLS_FIELD_TYPES", "");
+        if (!EQUAL(pszXLSFieldTypes, "STRING"))
+            DetectColumnTypes(xlshandle, paeFieldTypes);
+
+        for(i = 0; i < nCols; i ++)
+        {
+            OGRFieldType eType = (OGRFieldType) paeFieldTypes[i];
+            if (paeFieldTypes[i] < 0)
+                eType = OFTString;
+            if (bFirstLineIsHeaders &&
+                freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK &&
+                (sCellValue.type == FREEXL_CELL_TEXT ||
+                 sCellValue.type == FREEXL_CELL_SST_TEXT))
+            {
+                OGRFieldDefn oField(sCellValue.value.text_value, eType);
+                poFeatureDefn->AddFieldDefn(&oField);
+            }
+            else
+            {
+                OGRFieldDefn oField(CPLSPrintf("Field%d", i+1),  eType);
+                poFeatureDefn->AddFieldDefn(&oField);
+            }
+        }
+
+        CPLFree(paeFieldTypes);
+
+    }
+
+    ResetReading();
+
+    return poFeatureDefn;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+int OGRXLSLayer::GetFeatureCount( int bForce )
+{
+    if  ( m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */ )
+    {
+        const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
+        if(EQUAL(pszXLSHeaders, "DISABLE"))
+            return nRows;
+
+        GetLayerDefn();
+        return bFirstLineIsHeaders ? nRows - 1 : nRows;
+    }
+
+    return OGRLayer::GetFeatureCount(bForce);
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRXLSLayer::GetNextFeature()
+{
+    GetLayerDefn();
+
+    OGRFeature  *poFeature;
+
+    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 *OGRXLSLayer::GetNextRawFeature()
+{
+    if (nNextFID == nRows)
+        return NULL;
+
+    const void* xlshandle = poDS->GetXLSHandle();
+    if (xlshandle == NULL)
+        return NULL;
+
+    freexl_select_active_worksheet(xlshandle, iSheet);
+
+    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+
+    FreeXL_CellValue sCellValue;
+    for(unsigned short i=0;i<(unsigned short )poFeatureDefn->GetFieldCount(); i++)
+    {
+        if (freexl_get_cell_value(xlshandle, nNextFID, i, &sCellValue) == FREEXL_OK)
+        {
+            switch (sCellValue.type)
+            {
+                case FREEXL_CELL_INT:
+                    poFeature->SetField(i, sCellValue.value.int_value);
+                    break;
+                case FREEXL_CELL_DOUBLE:
+                    poFeature->SetField(i, sCellValue.value.double_value);
+                    break;
+                case FREEXL_CELL_TEXT:
+                case FREEXL_CELL_SST_TEXT:
+                    poFeature->SetField(i, sCellValue.value.text_value);
+                    break;
+                case FREEXL_CELL_DATE:
+                case FREEXL_CELL_DATETIME:
+                case FREEXL_CELL_TIME:
+                    poFeature->SetField(i, sCellValue.value.text_value);
+                    break;
+                case FREEXL_CELL_NULL:
+                    break;
+                default:
+                    CPLDebug("XLS", "Unknown cell type = %d", sCellValue.type);
+                    break;
+            }
+        }
+    }
+
+    poFeature->SetFID(nNextFID ++);
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRXLSLayer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
+        return m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */;
+
+    return FALSE;
+}
+
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
index 9c1186a..1d2d542 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
@@ -30,7 +30,7 @@
 #include "ogr_xplane_apt_reader.h"
 #include "ogr_xplane_geo_utils.h"
 
-CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 21298 2010-12-20 10:58:34Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 22627 2011-07-01 19:36:15Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAptFileReader                       */
@@ -147,7 +147,7 @@ OGRXPlaneReader* OGRXPlaneAptReader::CloneForLayer(OGRXPlaneLayer* poLayer)
     if (pszFilename)
     {
         poReader->pszFilename = CPLStrdup(pszFilename);
-        poReader->fp = VSIFOpen( pszFilename, "rt" );
+        poReader->fp = VSIFOpenL( pszFilename, "rb" );
     }
 
     return poReader;
@@ -198,7 +198,7 @@ void OGRXPlaneAptReader::Read()
         CPLAssert(papszTokens == NULL);
     }
 
-    while(bResumeLine || (pszLine = CPLReadLine(fp)) != NULL)
+    while(bResumeLine || (pszLine = CPLReadLineL(fp)) != NULL)
     {
         int nType;
         if (!bResumeLine)
@@ -389,7 +389,7 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
     double adfDisplacedThresholdLength[2];
     double adfStopwayLength[2];
     const char* pszRwyNum;
-    int aeVisualApproachLightingCode[2], aeRunwayLightingCode[2], aeApproachLightingCode[2];
+    int /*aeVisualApproachLightingCode[2], */ aeRunwayLightingCode[2], aeApproachLightingCode[2];
     int eSurfaceCode, eShoulderCode, eMarkings;
     double dfSmoothness;
     double adfVisualGlidePathAngle[2];
@@ -412,13 +412,20 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
     dfWidth *= FEET_TO_METER;
     if (strlen(papszTokens[9]) == 6)
     {
-        aeVisualApproachLightingCode[0] = papszTokens[9][0] - '0';
+        /*aeVisualApproachLightingCode[0] = papszTokens[9][0] - '0'; */
         aeRunwayLightingCode[0] = papszTokens[9][1] - '0';
         aeApproachLightingCode[0] = papszTokens[9][2] - '0';
-        aeVisualApproachLightingCode[1] = papszTokens[9][3] - '0';
+        /* aeVisualApproachLightingCode[1] = papszTokens[9][3] - '0'; */
         aeRunwayLightingCode[1] = papszTokens[9][4] - '0';
         aeApproachLightingCode[1] = papszTokens[9][5] - '0';
     }
+    else
+    {
+        aeRunwayLightingCode[0] = 0;
+        aeApproachLightingCode[0] = 0;
+        aeRunwayLightingCode[1] = 0;
+        aeApproachLightingCode[1] = 0;
+    }
     eSurfaceCode = atoi(papszTokens[10]);
     eShoulderCode = atoi(papszTokens[11]);
     eMarkings = atoi(papszTokens[12]);
@@ -429,6 +436,13 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
         adfVisualGlidePathAngle[0] = atoi(papszTokens[15]) / 100.;
         if (strchr(papszTokens[15], '.') != NULL)
             adfVisualGlidePathAngle[1] = atoi(strchr(papszTokens[15], '.') + 1) / 100.;
+        else
+            adfVisualGlidePathAngle[1] = 0;
+    }
+    else
+    {
+        adfVisualGlidePathAngle[0] = 0;
+        adfVisualGlidePathAngle[1] = 0;
     }
 
     if (strcmp(pszRwyNum, "xxx") == 000)
@@ -1027,7 +1041,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
 
     *ppoGeom = NULL;
 
-    while((pszLine = CPLReadLine(fp)) != NULL)
+    while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         int nType = -1;
         papszTokens = CSLTokenizeString(pszLine);
@@ -1354,7 +1368,7 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
 
     OGRLineString lineString;
 
-    while((pszLine = CPLReadLine(fp)) != NULL)
+    while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         int nType = -1;
         papszTokens = CSLTokenizeString(pszLine);
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
index e898edd..7f301c2 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_awy_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 18548 2010-01-14 22:01:35Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAwyFileReader                       */
@@ -80,7 +80,7 @@ OGRXPlaneReader* OGRXPlaneAwyReader::CloneForLayer(OGRXPlaneLayer* poLayer)
     if (pszFilename)
     {
         poReader->pszFilename = CPLStrdup(pszFilename);
-        poReader->fp = VSIFOpen( pszFilename, "rt" );
+        poReader->fp = VSIFOpenL( pszFilename, "rt" );
     }
 
     return poReader;
@@ -104,7 +104,7 @@ int OGRXPlaneAwyReader::IsRecognizedVersion( const char* pszVersionString)
 void OGRXPlaneAwyReader::Read()
 {
     const char* pszLine;
-    while((pszLine = CPLReadLine(fp)) != NULL)
+    while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         papszTokens = CSLTokenizeString(pszLine);
         nTokens = CSLCount(papszTokens);
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
index 3024001..c474c79 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_fix_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 18548 2010-01-14 22:01:35Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateFixFileReader                       */
@@ -76,7 +76,7 @@ OGRXPlaneReader* OGRXPlaneFixReader::CloneForLayer(OGRXPlaneLayer* poLayer)
     if (pszFilename)
     {
         poReader->pszFilename = CPLStrdup(pszFilename);
-        poReader->fp = VSIFOpen( pszFilename, "rt" );
+        poReader->fp = VSIFOpenL( pszFilename, "rt" );
     }
 
     return poReader;
@@ -98,7 +98,7 @@ int OGRXPlaneFixReader::IsRecognizedVersion( const char* pszVersionString)
 void OGRXPlaneFixReader::Read()
 {
     const char* pszLine;
-    while((pszLine = CPLReadLine(fp)) != NULL)
+    while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         papszTokens = CSLTokenizeString(pszLine);
         nTokens = CSLCount(papszTokens);
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
index 471c1be..962ec57 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
@@ -29,7 +29,7 @@
 
 #include "ogr_xplane_nav_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 18548 2010-01-14 22:01:35Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateNavFileReader                       */
@@ -100,7 +100,7 @@ OGRXPlaneReader* OGRXPlaneNavReader::CloneForLayer(OGRXPlaneLayer* poLayer)
     if (pszFilename)
     {
         poReader->pszFilename = CPLStrdup(pszFilename);
-        poReader->fp = VSIFOpen( pszFilename, "rt" );
+        poReader->fp = VSIFOpenL( pszFilename, "rb" );
     }
 
     return poReader;
@@ -123,7 +123,7 @@ int OGRXPlaneNavReader::IsRecognizedVersion( const char* pszVersionString)
 void OGRXPlaneNavReader::Read()
 {
     const char* pszLine;
-    while((pszLine = CPLReadLine(fp)) != NULL)
+    while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         int nType;
         papszTokens = CSLTokenizeString(pszLine);
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
index b5627a7..c414522 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane_reader.cpp 18548 2010-01-14 22:01:35Z rouault $
+ * $Id: ogr_xplane_reader.cpp 21634 2011-02-06 14:45:00Z rouault $
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Definition of classes for OGR X-Plane aeronautical data driver.
@@ -27,9 +27,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_vsi_virtual.h"
+
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_reader.cpp 18548 2010-01-14 22:01:35Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
 
 /***********************************************************************/
 /*                       OGRXPlaneReader()                             */
@@ -59,7 +61,7 @@ OGRXPlaneReader::~OGRXPlaneReader()
     papszTokens = NULL;
 
     if (fp != NULL)
-        VSIFClose(fp);
+        VSIFCloseL(fp);
     fp = NULL;
 }
 
@@ -69,23 +71,25 @@ OGRXPlaneReader::~OGRXPlaneReader()
 
 int OGRXPlaneReader::StartParsing( const char * pszFilename )
 {
-    fp = VSIFOpen( pszFilename, "rt" );
+    fp = VSIFOpenL( pszFilename, "rb" );
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine = CPLReadLine(fp);
+    fp = (VSILFILE*) VSICreateBufferedReaderHandle ( (VSIVirtualHandle*) fp );
+
+    const char* pszLine = CPLReadLineL(fp);
     if (!pszLine || (strcmp(pszLine, "I") != 0 &&
                      strcmp(pszLine, "A") != 0))
     {
-        VSIFClose(fp);
+        VSIFCloseL(fp);
         fp = NULL;
         return FALSE;
     }
 
-    pszLine = CPLReadLine(fp);
+    pszLine = CPLReadLineL(fp);
     if (!pszLine || IsRecognizedVersion(pszLine) == FALSE)
     {
-        VSIFClose(fp);
+        VSIFCloseL(fp);
         fp = NULL;
         return FALSE;
     }
@@ -109,9 +113,9 @@ void OGRXPlaneReader::Rewind()
 {
     if (fp != NULL)
     {
-        VSIRewind(fp);
-        CPLReadLine(fp);
-        CPLReadLine(fp);
+        VSIRewindL(fp);
+        CPLReadLineL(fp);
+        CPLReadLineL(fp);
 
         nLineNumber = 2;
 
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
index ed8faa9..d94785c 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
@@ -53,7 +53,7 @@ class OGRXPlaneReader
         int             nLineNumber;
         char**          papszTokens;
         int             nTokens;
-        FILE*           fp;
+        VSILFILE*       fp;
         char*           pszFilename;
         int             bEOF;
         OGRXPlaneLayer* poInterestLayer;
diff --git a/ogr/ogrspatialreference.cpp b/ogr/ogrspatialreference.cpp
index db05d77..6813137 100644
--- a/ogr/ogrspatialreference.cpp
+++ b/ogr/ogrspatialreference.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrspatialreference.cpp 21435 2011-01-08 10:41:11Z rouault $
+ * $Id: ogrspatialreference.cpp 22974 2011-08-24 18:37:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSpatialReference class.
@@ -33,7 +33,7 @@
 #include "cpl_http.h"
 #include "cpl_atomic_ops.h"
 
-CPL_CVSID("$Id: ogrspatialreference.cpp 21435 2011-01-08 10:41:11Z rouault $");
+CPL_CVSID("$Id: ogrspatialreference.cpp 22974 2011-08-24 18:37:09Z rouault $");
 
 // The current opinion is that WKT longitudes like central meridian
 // should be relative to greenwich, not the prime meridian in use. 
@@ -45,7 +45,7 @@ CPL_CVSID("$Id: ogrspatialreference.cpp 21435 2011-01-08 10:41:11Z rouault $");
 /*                           OGRPrintDouble()                           */
 /************************************************************************/
 
-static void OGRPrintDouble( char * pszStrBuf, double dfValue )
+void OGRPrintDouble( char * pszStrBuf, double dfValue )
 
 {
     sprintf( pszStrBuf, "%.16g", dfValue );
@@ -428,7 +428,10 @@ OGR_SRSNode *OGRSpatialReference::GetAttrNode( const char * pszNodePath )
     papszPathTokens = CSLTokenizeStringComplex(pszNodePath, "|", TRUE, FALSE);
 
     if( CSLCount( papszPathTokens ) < 1 )
+    {
+        CSLDestroy(papszPathTokens);
         return NULL;
+    }
 
     poNode = GetRoot();
     for( int i = 0; poNode != NULL && papszPathTokens[i] != NULL; i++ )
@@ -701,7 +704,27 @@ OGRErr OGRSpatialReference::importFromWkt( char ** ppszInput )
 
     poRoot = new OGR_SRSNode();
 
-    return poRoot->importFromWkt( ppszInput );
+    OGRErr eErr = poRoot->importFromWkt( ppszInput ); 
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      The following seems to try and detect and unconsumed            */
+/*      VERTCS[] coordinate system definition (ESRI style) and to       */
+/*      import and attach it to the existing root.  Likely we will      */
+/*      need to extend this somewhat to bring it into an acceptable     */
+/*      OGRSpatialReference organization at some point.                 */
+/* -------------------------------------------------------------------- */
+    if (strlen(*ppszInput) > 0 && strstr(*ppszInput, "VERTCS"))
+    {
+        if(((*ppszInput)[0]) == ',')
+            (*ppszInput)++;
+        OGR_SRSNode *poNewChild = new OGR_SRSNode();
+        poRoot->AddChild( poNewChild );
+        return poNewChild->importFromWkt( ppszInput );
+    }
+
+    return eErr;
 }
 
 /************************************************************************/
@@ -1060,6 +1083,7 @@ OGRErr OSRSetLinearUnitsAndUpdateParameters( OGRSpatialReferenceH hSRS,
     return ((OGRSpatialReference *) hSRS)->
         SetLinearUnitsAndUpdateParameters( pszUnits, dfInMeters );
 }
+
 /************************************************************************/
 /*                           SetLinearUnits()                           */
 /************************************************************************/
@@ -1068,7 +1092,7 @@ OGRErr OSRSetLinearUnitsAndUpdateParameters( OGRSpatialReferenceH hSRS,
  * \brief Set the linear units for the projection.
  *
  * This method creates a UNIT subnode with the specified values as a
- * child of the PROJCS or LOCAL_CS node. 
+ * child of the PROJCS, GEOCCS or LOCAL_CS node. 
  *
  * This method does the same as the C function OSRSetLinearUnits(). 
  *
@@ -1087,17 +1111,79 @@ OGRErr OGRSpatialReference::SetLinearUnits( const char * pszUnitsName,
                                             double dfInMeters )
 
 {
+    return SetTargetLinearUnits( NULL, pszUnitsName, dfInMeters );
+}
+
+/************************************************************************/
+/*                         OSRSetLinearUnits()                          */
+/************************************************************************/
+
+/**
+ * \brief Set the linear units for the projection.
+ *
+ * This function is the same as OGRSpatialReference::SetLinearUnits()
+ */
+OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS, 
+                          const char * pszUnits, double dfInMeters )
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRSetLinearUnits", CE_Failure );
+
+    return ((OGRSpatialReference *) hSRS)->SetLinearUnits( pszUnits, 
+                                                           dfInMeters );
+}
+
+/************************************************************************/
+/*                        SetTargetLinearUnits()                        */
+/************************************************************************/
+
+/**
+ * \brief Set the linear units for the projection.
+ *
+ * This method creates a UNIT subnode with the specified values as a
+ * child of the target node. 
+ *
+ * This method does the same as the C function OSRSetTargetLinearUnits(). 
+ *
+ * @param pszTargetKey the keyword to set the linear units for.  ie. "PROJCS" or "VERT_CS"
+ *
+ * @param pszUnitsName the units name to be used.  Some preferred units
+ * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT 
+ * and SRS_UL_US_FOOT. 
+ *
+ * @param dfInMeters the value to multiple by a length in the indicated
+ * units to transform to meters.  Some standard conversion factors can
+ * be found in ogr_srs_api.h. 
+ *
+ * @return OGRERR_NONE on success.
+ *
+ * @since OGR 1.9.0
+ */
+
+OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
+                                                  const char * pszUnitsName,
+                                                  double dfInMeters )
+
+{
     OGR_SRSNode *poCS;
     OGR_SRSNode *poUnits;
     char        szValue[128];
 
     bNormInfoSet = FALSE;
 
-    poCS = GetAttrNode( "PROJCS" );
-    if( poCS == NULL )
-        poCS = GetAttrNode( "VERT_CS" );
-    if( poCS == NULL )
-        poCS = GetAttrNode( "LOCAL_CS" );
+    if( pszTargetKey == NULL )
+    {
+        poCS = GetAttrNode( "PROJCS" );
+
+        if( poCS == NULL )
+            poCS = GetAttrNode( "LOCAL_CS" );
+        if( poCS == NULL )
+            poCS = GetAttrNode( "GEOCCS" );
+        if( poCS == NULL && IsVertical() )
+            poCS = GetAttrNode( "VERT_CS" );
+    }
+    else
+        poCS = GetAttrNode( pszTargetKey );
 
     if( poCS == NULL )
         return OGRERR_FAILURE;
@@ -1134,18 +1220,21 @@ OGRErr OGRSpatialReference::SetLinearUnits( const char * pszUnitsName,
 /************************************************************************/
 
 /**
- * \brief Set the linear units for the projection.
+ * \brief Set the linear units for the target node.
  *
- * This function is the same as OGRSpatialReference::SetLinearUnits()
+ * This function is the same as OGRSpatialReference::SetTargetLinearUnits()
+ *
+ * @since OGR 1.9.0
  */
-OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS, 
-                          const char * pszUnits, double dfInMeters )
+OGRErr OSRSetTargetLinearUnits( OGRSpatialReferenceH hSRS, 
+                                const char *pszTargetKey,
+                                const char * pszUnits, double dfInMeters )
 
 {
-    VALIDATE_POINTER1( hSRS, "OSRSetLinearUnits", CE_Failure );
+    VALIDATE_POINTER1( hSRS, "OSRSetTargetLinearUnits", CE_Failure );
 
-    return ((OGRSpatialReference *) hSRS)->SetLinearUnits( pszUnits, 
-                                                           dfInMeters );
+    return ((OGRSpatialReference *) hSRS)->
+        SetTargetLinearUnits( pszTargetKey, pszUnits, dfInMeters );
 }
 
 /************************************************************************/
@@ -1156,8 +1245,8 @@ OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS,
  * \brief Fetch linear projection units. 
  *
  * If no units are available, a value of "Meters" and 1.0 will be assumed.
- * This method only checks directly under the PROJCS or LOCAL_CS node for 
- * units.
+ * This method only checks directly under the PROJCS, GEOCCS or LOCAL_CS node 
+ * for units.
  *
  * This method does the same thing as the C function OSRGetLinearUnits()/
  *
@@ -1173,10 +1262,68 @@ OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS,
 double OGRSpatialReference::GetLinearUnits( char ** ppszName ) const
 
 {
-    const OGR_SRSNode *poCS = GetAttrNode( "PROJCS" );
+    return GetTargetLinearUnits( NULL, ppszName );
+}
 
-    if( poCS == NULL )
-        poCS = GetAttrNode( "LOCAL_CS" );
+/************************************************************************/
+/*                         OSRGetLinearUnits()                          */
+/************************************************************************/
+
+/**
+ * \brief Fetch linear projection units. 
+ *
+ * This function is the same as OGRSpatialReference::GetLinearUnits()
+ */
+double OSRGetLinearUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
+    
+{
+    VALIDATE_POINTER1( hSRS, "OSRGetLinearUnits", 0 );
+
+    return ((OGRSpatialReference *) hSRS)->GetLinearUnits( ppszName );
+}
+
+/************************************************************************/
+/*                        GetTargetLinearUnits()                        */
+/************************************************************************/
+
+/**
+ * \brief Fetch linear units for target. 
+ *
+ * If no units are available, a value of "Meters" and 1.0 will be assumed.
+ *
+ * This method does the same thing as the C function OSRGetTargetLinearUnits()/
+ *
+ * @param pszTargetKey the key to look on. ie. "PROJCS" or "VERT_CS".
+ * @param ppszName a pointer to be updated with the pointer to the 
+ * units name.  The returned value remains internal to the OGRSpatialReference
+ * and shouldn't be freed, or modified.  It may be invalidated on the next
+ * OGRSpatialReference call. 
+ *
+ * @return the value to multiply by linear distances to transform them to 
+ * meters.
+ *
+ * @since OGR 1.9.0
+ */
+
+double OGRSpatialReference::GetTargetLinearUnits( const char *pszTargetKey,
+                                                  char ** ppszName ) const
+
+{
+    const OGR_SRSNode *poCS;
+
+    if( pszTargetKey == NULL )
+    {
+        poCS = GetAttrNode( "PROJCS" );
+
+        if( poCS == NULL )
+            poCS = GetAttrNode( "LOCAL_CS" );
+        if( poCS == NULL )
+            poCS = GetAttrNode( "GEOCCS" );
+        if( poCS == NULL && IsVertical() )
+            poCS = GetAttrNode( "VERT_CS" );
+    }
+    else
+        poCS = GetAttrNode( pszTargetKey );
 
     if( ppszName != NULL )
         *ppszName = (char*) "unknown";
@@ -1202,20 +1349,25 @@ double OGRSpatialReference::GetLinearUnits( char ** ppszName ) const
 }
 
 /************************************************************************/
-/*                         OSRGetLinearUnits()                          */
+/*                      OSRGetTargetLinearUnits()                       */
 /************************************************************************/
 
 /**
  * \brief Fetch linear projection units. 
  *
- * This function is the same as OGRSpatialReference::GetLinearUnits()
+ * This function is the same as OGRSpatialReference::GetTargetLinearUnits()
+ *
+ * @since OGR 1.9.0
  */
-double OSRGetLinearUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
+double OSRGetTargetLinearUnits( OGRSpatialReferenceH hSRS, 
+                                const char *pszTargetKey, 
+                                char ** ppszName )
     
 {
-    VALIDATE_POINTER1( hSRS, "OSRGetLinearUnits", 0 );
+    VALIDATE_POINTER1( hSRS, "OSRGetTargetLinearUnits", 0 );
 
-    return ((OGRSpatialReference *) hSRS)->GetLinearUnits( ppszName );
+    return ((OGRSpatialReference *) hSRS)->GetTargetLinearUnits( pszTargetKey,
+                                                                 ppszName );
 }
 
 /************************************************************************/
@@ -1338,18 +1490,35 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
     bNormInfoSet = FALSE;
 
 /* -------------------------------------------------------------------- */
+/*      For a geocentric coordinate system we want to set the datum     */
+/*      and ellipsoid based on the GEOGCS.  Create the GEOGCS in a      */
+/*      temporary srs and use the copy method which has special         */
+/*      handling for GEOCCS.                                            */
+/* -------------------------------------------------------------------- */
+    if( IsGeocentric() )
+    {
+        OGRSpatialReference oGCS;
+
+        oGCS.SetGeogCS( pszGeogName, pszDatumName, pszSpheroidName,
+                        dfSemiMajor, dfInvFlattening, 
+                        pszPMName, dfPMOffset, 
+                        pszAngularUnits, dfConvertToRadians );
+        return CopyGeogCSFrom( &oGCS );
+    }        
+
+/* -------------------------------------------------------------------- */
 /*      Do we already have a GEOGCS?  If so, blow it away so it can     */
 /*      be properly replaced.                                           */
 /* -------------------------------------------------------------------- */
     if( GetAttrNode( "GEOGCS" ) != NULL )
     {
-        OGR_SRSNode *poPROJCS;
+        OGR_SRSNode *poCS;
 
         if( EQUAL(GetRoot()->GetValue(),"GEOGCS") )
             Clear();
-        else if( (poPROJCS = GetAttrNode( "PROJCS" )) != NULL
-                 && poPROJCS->FindChild( "GEOGCS" ) != -1 )
-            poPROJCS->DestroyChild( poPROJCS->FindChild( "GEOGCS" ) );
+        else if( (poCS = GetAttrNode( "PROJCS" )) != NULL
+                 && poCS->FindChild( "GEOGCS" ) != -1 )
+            poCS->DestroyChild( poCS->FindChild( "GEOGCS" ) );
         else
             return OGRERR_FAILURE;
     }
@@ -1538,16 +1707,16 @@ OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
 /* -------------------------------------------------------------------- */
     char        *pszWKT = NULL;
 
-    if( EQUAL(pszName, "WGS84") || EQUAL(pszName,"CRS84") )
+    if( EQUAL(pszName, "WGS84") || EQUAL(pszName,"CRS84") || EQUAL(pszName,"CRS:84") )
         pszWKT = (char* ) SRS_WKT_WGS84;
 
     else if( EQUAL(pszName, "WGS72") )
         pszWKT = (char* ) "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\"]]";
 
-    else if( EQUAL(pszName, "NAD27") || EQUAL(pszName, "CRS27") )
+    else if( EQUAL(pszName, "NAD27") || EQUAL(pszName, "CRS27") || EQUAL(pszName,"CRS:27") )
         pszWKT = (char* ) "GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\",6378206.4,294.978698213898,AUTHORITY[\"EPSG\",\"7008\"]],AUTHORITY[\"EPSG\",\"6267\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4267\"]]";
         
-    else if( EQUAL(pszName, "NAD83") || EQUAL(pszName,"CRS83") )
+    else if( EQUAL(pszName, "NAD83") || EQUAL(pszName,"CRS83") || EQUAL(pszName,"CRS:83") )
         pszWKT = (char* ) "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4269\"]]";
 
     else
@@ -1609,6 +1778,30 @@ OGRErr OGRSpatialReference::CopyGeogCSFrom(
     bNormInfoSet = FALSE;
 
 /* -------------------------------------------------------------------- */
+/*      Handle geocentric coordinate systems specially.  We just        */
+/*      want to copy the DATUM and PRIMEM nodes.                        */
+/* -------------------------------------------------------------------- */
+    if( IsGeocentric() )
+    {
+        if( GetRoot()->FindChild( "DATUM" ) != -1 )
+            GetRoot()->DestroyChild( GetRoot()->FindChild( "DATUM" ) );
+        if( GetRoot()->FindChild( "PRIMEM" ) != -1 )
+            GetRoot()->DestroyChild( GetRoot()->FindChild( "PRIMEM" ) );
+
+        const OGR_SRSNode *poDatum = poSrcSRS->GetAttrNode( "DATUM" );
+        const OGR_SRSNode *poPrimeM = poSrcSRS->GetAttrNode( "PRIMEM" );
+
+        if( poDatum == NULL || poPrimeM == NULL )
+            return OGRERR_FAILURE;
+        
+        poRoot->InsertChild( poDatum->Clone(), 1 );
+        poRoot->InsertChild( poPrimeM->Clone(), 2 );
+
+        return OGRERR_NONE;
+        
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Do we already have a GEOGCS?  If so, blow it away so it can     */
 /*      be properly replaced.                                           */
 /* -------------------------------------------------------------------- */
@@ -1686,6 +1879,7 @@ OGRErr OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS,
  * WGS84 or WGS72. 
  * <li> WKT (directly or in a file) in ESRI format should be prefixed with
  * ESRI:: to trigger an automatic morphFromESRI().
+ * <li> "IGNF:xxx" - "+init=IGNF:xxx" passed on to importFromProj4().
  * </ol>
  *
  * It is expected that this method will be extended in the future to support
@@ -1723,7 +1917,9 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
 /* -------------------------------------------------------------------- */
     if( EQUALN(pszDefinition,"PROJCS",6)
         || EQUALN(pszDefinition,"GEOGCS",6)
-        || EQUALN(pszDefinition,"COMPD_CS",6)
+        || EQUALN(pszDefinition,"COMPD_CS",8)
+        || EQUALN(pszDefinition,"GEOCCS",6)
+        || EQUALN(pszDefinition,"VERT_CS",7)
         || EQUALN(pszDefinition,"LOCAL_CS",8) )
     {
         err = importFromWkt( (char **) &pszDefinition );
@@ -1773,8 +1969,10 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
             return eStatus;
     }
 
-    if( EQUALN(pszDefinition,"urn:ogc:def:crs:",16) 
+    if( EQUALN(pszDefinition,"urn:ogc:def:crs:",16)
+        || EQUALN(pszDefinition,"urn:ogc:def:crs,crs:",20)
         || EQUALN(pszDefinition,"urn:x-ogc:def:crs:",18)
+        || EQUALN(pszDefinition,"urn:opengis:crs:",16)
         || EQUALN(pszDefinition,"urn:opengis:def:crs:",20))
         return importFromURN( pszDefinition );
 
@@ -1784,6 +1982,9 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
     if( EQUALN(pszDefinition,"OGC:",4) )  // WMS/WCS OGC codes like OGC:CRS84
         return SetWellKnownGeogCS( pszDefinition+4 );
 
+    if( EQUALN(pszDefinition,"CRS:",4) )
+        return SetWellKnownGeogCS( pszDefinition );
+
     if( EQUALN(pszDefinition,"DICT:",5) 
         && strstr(pszDefinition,",") )
     {
@@ -1814,6 +2015,17 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
              || strstr(pszDefinition,"+init") != NULL )
         return importFromProj4( pszDefinition );
 
+    if( EQUALN(pszDefinition,"IGNF:", 5) )
+    {
+        char* pszProj4Str = (char*) CPLMalloc(6 + strlen(pszDefinition) + 1);
+        strcpy(pszProj4Str, "+init=");
+        strcat(pszProj4Str, pszDefinition);
+        err = importFromProj4( pszProj4Str );
+        CPLFree(pszProj4Str);
+
+        return err;
+    }
+
     if( EQUALN(pszDefinition,"http://",7) )
     {
         return importFromUrl (pszDefinition);
@@ -2008,6 +2220,78 @@ OGRErr OSRImportFromUrl( OGRSpatialReferenceH hSRS, const char *pszUrl )
 }
 
 /************************************************************************/
+/*                         importFromURNPart()                          */
+/************************************************************************/
+OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
+                                              const char* pszCode,
+                                              const char* pszURN)
+{
+
+/* -------------------------------------------------------------------- */
+/*      Is this an EPSG code? Note that we import it with EPSG          */
+/*      preferred axis ordering for geographic coordinate systems!      */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszAuthority,"EPSG:",5) )
+        return importFromEPSGA( atoi(pszCode) );
+
+/* -------------------------------------------------------------------- */
+/*      Is this an IAU code?  Lets try for the IAU2000 dictionary.      */
+/* -------------------------------------------------------------------- */
+    if( EQUALN(pszAuthority,"IAU",3) )
+        return importFromDict( "IAU2000.wkt", pszCode );
+
+/* -------------------------------------------------------------------- */
+/*      Is this an OGC code?                                            */
+/* -------------------------------------------------------------------- */
+    if( !EQUALN(pszAuthority,"OGC:",4) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "URN %s has unrecognised authority.",
+                  pszURN );
+        return OGRERR_FAILURE;
+    }
+
+    if( EQUALN(pszCode,"CRS84",5) )
+        return SetWellKnownGeogCS( pszCode );
+    else if( EQUALN(pszCode,"CRS83",5) )
+        return SetWellKnownGeogCS( pszCode );
+    else if( EQUALN(pszCode,"CRS27",5) )
+        return SetWellKnownGeogCS( pszCode );
+
+/* -------------------------------------------------------------------- */
+/*      Handle auto codes.  We need to convert from format              */
+/*      AUTO42001:99:8888 to format AUTO:42001,99,8888.                 */
+/* -------------------------------------------------------------------- */
+    else if( EQUALN(pszCode,"AUTO",4) )
+    {
+        char szWMSAuto[100];
+        int i;
+
+        if( strlen(pszCode) > sizeof(szWMSAuto)-2 )
+            return OGRERR_FAILURE;
+
+        strcpy( szWMSAuto, "AUTO:" );
+        strcpy( szWMSAuto + 5, pszCode + 4 );
+        for( i = 5; szWMSAuto[i] != '\0'; i++ )
+        {
+            if( szWMSAuto[i] == ':' )
+                szWMSAuto[i] = ',';
+        }
+
+        return importFromWMSAUTO( szWMSAuto );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Not a recognise OGC item.                                       */
+/* -------------------------------------------------------------------- */
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "URN %s value not supported.",
+              pszURN );
+
+    return OGRERR_FAILURE;
+}
+
+/************************************************************************/
 /*                           importFromURN()                            */
 /*                                                                      */
 /*      See OGC recommendation paper 06-023r1 or later for details.     */
@@ -2036,8 +2320,12 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 
     if( EQUALN(pszURN,"urn:ogc:def:crs:",16) )
         pszCur = pszURN + 16;
+    else if( EQUALN(pszURN,"urn:ogc:def:crs,crs:",20) )
+        pszCur = pszURN + 20;
     else if( EQUALN(pszURN,"urn:x-ogc:def:crs:",18) )
         pszCur = pszURN + 18;
+    else if( EQUALN(pszURN,"urn:opengis:crs:",16) )
+        pszCur = pszURN + 16;
     else if( EQUALN(pszURN,"urn:opengis:def:crs:",20) )
         pszCur = pszURN + 20;
     else
@@ -2059,7 +2347,7 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 /* -------------------------------------------------------------------- */
 /*      Find code (ignoring version) out of string like:                */
 /*                                                                      */
-/*      authority:[version]:code                                          */
+/*      authority:[version]:code                                        */
 /* -------------------------------------------------------------------- */
     const char *pszAuthority = pszCur;
 
@@ -2083,68 +2371,77 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 
     const char *pszCode = pszCur;
 
-/* -------------------------------------------------------------------- */
-/*      Is this an EPSG code? Note that we import it with EPSG          */
-/*      preferred axis ordering for geographic coordinate systems!      */
-/* -------------------------------------------------------------------- */
-    if( EQUALN(pszAuthority,"EPSG:",5) )
-        return importFromEPSGA( atoi(pszCode) );
+    const char* pszComma = strchr(pszCur, ',');
+    if (pszComma == NULL)
+        return importFromURNPart(pszAuthority, pszCode, pszURN);
 
-/* -------------------------------------------------------------------- */
-/*      Is this an IAU code?  Lets try for the IAU2000 dictionary.      */
-/* -------------------------------------------------------------------- */
-    if( EQUALN(pszAuthority,"IAU",3) )
-        return importFromDict( "IAU2000.wkt", pszCode );
 
-/* -------------------------------------------------------------------- */
-/*      Is this an OGC code?                                            */
-/* -------------------------------------------------------------------- */
-    if( !EQUALN(pszAuthority,"OGC:",4) )
+    /* There's a second part with the vertical SRS */
+    pszCur = pszComma + 1;
+    if (strncmp(pszCur, "crs:", 4) != 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "URN %s has unrecognised authority.", 
-                  pszURN );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "URN %s not a supported format.", pszURN );
         return OGRERR_FAILURE;
     }
 
-    if( EQUALN(pszCode,"CRS84",5) )
-        return SetWellKnownGeogCS( pszCode );
-    else if( EQUALN(pszCode,"CRS83",5) )
-        return SetWellKnownGeogCS( pszCode );
-    else if( EQUALN(pszCode,"CRS27",5) )
-        return SetWellKnownGeogCS( pszCode );
+    pszCur += 4;
 
-/* -------------------------------------------------------------------- */
-/*      Handle auto codes.  We need to convert from format              */
-/*      AUTO42001:99:8888 to format AUTO:42001,99,8888.                 */
-/* -------------------------------------------------------------------- */
-    else if( EQUALN(pszCode,"AUTO",4) )
+    char* pszFirstCode = CPLStrdup(pszCode);
+    pszFirstCode[pszComma - pszCode] = '\0';
+    OGRErr eStatus = importFromURNPart(pszAuthority, pszFirstCode, pszURN);
+    CPLFree(pszFirstCode);
+
+    // Do we want to turn this into a compound definition
+    // with a vertical datum?
+    if( eStatus == OGRERR_NONE )
     {
-        char szWMSAuto[100];
-        int i;
+        OGRSpatialReference oVertSRS;
+
+    /* -------------------------------------------------------------------- */
+    /*      Find code (ignoring version) out of string like:                */
+    /*                                                                      */
+    /*      authority:[version]:code                                        */
+    /* -------------------------------------------------------------------- */
+        pszAuthority = pszCur;
+
+        // skip authority
+        while( *pszCur != ':' && *pszCur )
+            pszCur++;
+        if( *pszCur == ':' )
+            pszCur++;
+
+        // skip version
+        pszBeforeVersion = pszCur;
+        while( *pszCur != ':' && *pszCur )
+            pszCur++;
+        if( *pszCur == ':' )
+            pszCur++;
+        else
+            pszCur = pszBeforeVersion;
 
-        if( strlen(pszCode) > sizeof(szWMSAuto)-2 )
-            return OGRERR_FAILURE;
+        pszCode = pszCur;
 
-        strcpy( szWMSAuto, "AUTO:" );
-        strcpy( szWMSAuto + 5, pszCode + 4 );
-        for( i = 5; szWMSAuto[i] != '\0'; i++ )
+        eStatus = oVertSRS.importFromURNPart(pszAuthority, pszCode, pszURN);
+        if( eStatus == OGRERR_NONE )
         {
-            if( szWMSAuto[i] == ':' )
-                szWMSAuto[i] = ',';
-        }
+            OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
 
-        return importFromWMSAUTO( szWMSAuto );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Not a recognise OGC item.                                       */
-/* -------------------------------------------------------------------- */
-    CPLError( CE_Failure, CPLE_AppDefined, 
-              "URN %s value not supported.", 
-              pszURN );
+            Clear();
 
-    return OGRERR_FAILURE;
+            CPLString osName = poHorizSRS->GetChild(0)->GetValue();
+            osName += " + ";
+            osName += oVertSRS.GetRoot()->GetValue();
+
+            SetNode( "COMPD_CS", osName );
+            GetRoot()->AddChild( poHorizSRS );
+            GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
+        }
+
+        return eStatus;
+    }
+    else
+        return eStatus;
 }
 
 /************************************************************************/
@@ -2450,7 +2747,7 @@ double OSRGetSemiMinor( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
  *
  * This method is the same as the C function OSRSetLocalCS(). 
  *
- * This method is will ensure a LOCAL_CS node is created as the root, 
+ * This method will ensure a LOCAL_CS node is created as the root,
  * and set the provided name on it.  It must be used before SetLinearUnits().
  *
  * @param pszName the user visible name to assign.  Not used as a key.
@@ -2496,6 +2793,284 @@ OGRErr OSRSetLocalCS( OGRSpatialReferenceH hSRS, const char * pszName )
 }
 
 /************************************************************************/
+/*                             SetGeocCS()                              */
+/************************************************************************/
+
+/**
+ * \brief Set the user visible GEOCCS name.
+ *
+ * This method is the same as the C function OSRSetGeocCS(). 
+
+ * This method will ensure a GEOCCS node is created as the root,
+ * and set the provided name on it.  If used on a GEOGCS coordinate system, 
+ * the DATUM and PRIMEM nodes from the GEOGCS will be tarnsferred over to 
+ * the GEOGCS. 
+ *
+ * @param pszName the user visible name to assign.  Not used as a key.
+ * 
+ * @return OGRERR_NONE on success.
+ *
+ * @since OGR 1.9.0
+ */
+
+OGRErr OGRSpatialReference::SetGeocCS( const char * pszName )
+
+{
+    OGR_SRSNode *poGeogCS = NULL;
+    OGR_SRSNode *poGeocCS = GetAttrNode( "GEOCCS" );
+
+    if( poRoot != NULL && EQUAL(poRoot->GetValue(),"GEOGCS") )
+    {
+        poGeogCS = poRoot;
+        poRoot = NULL;
+    }
+
+    if( poGeocCS == NULL && GetRoot() != NULL )
+    {
+        CPLDebug( "OGR", 
+                  "OGRSpatialReference::SetGeocCS(%s) failed.\n"
+               "It appears an incompatible root node (%s) already exists.\n",
+                  pszName, GetRoot()->GetValue() );
+        return OGRERR_FAILURE;
+    }
+
+    SetNode( "GEOCCS", pszName );
+
+    if( poGeogCS != NULL )
+    {
+        OGR_SRSNode *poDatum = poGeogCS->GetNode( "DATUM" );
+        OGR_SRSNode *poPRIMEM = poGeogCS->GetNode( "PRIMEM" );
+        if ( poDatum != NULL && poPRIMEM != NULL )
+        {
+            poRoot->InsertChild( poDatum->Clone(), 1 );
+            poRoot->InsertChild( poPRIMEM->Clone(), 2 );
+        }
+        delete poGeogCS;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            OSRSetGeocCS()                            */
+/************************************************************************/
+
+/**
+ * \brief Set the user visible PROJCS name.
+ *
+ * This function is the same as OGRSpatialReference::SetGeocCS()
+ *
+ * @since OGR 1.9.0
+ */
+OGRErr OSRSetGeocCS( OGRSpatialReferenceH hSRS, const char * pszName )
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRSetGeocCS", CE_Failure );
+
+    return ((OGRSpatialReference *) hSRS)->SetGeocCS( pszName );
+}
+
+/************************************************************************/
+/*                             SetVertCS()                              */
+/************************************************************************/
+
+/**
+ * \brief Set the user visible VERT_CS name.
+ *
+ * This method is the same as the C function OSRSetVertCS(). 
+
+ * This method will ensure a VERT_CS node is created if needed.  If the
+ * existing coordinate system is GEOGCS or PROJCS rooted, then it will be
+ * turned into a COMPD_CS.
+ *
+ * @param pszVertCSName the user visible name of the vertical coordinate
+ * system. Not used as a key.
+ *  
+ * @param pszVertDatumName the user visible name of the vertical datum.  It
+ * is helpful if this matches the EPSG name.
+ * 
+ * @param nVertDatumType the OGC vertical datum type, usually 2005. 
+ * 
+ * @return OGRERR_NONE on success.
+ *
+ * @since OGR 1.9.0
+ */
+
+OGRErr OGRSpatialReference::SetVertCS( const char * pszVertCSName,
+                                       const char * pszVertDatumName,
+                                       int nVertDatumType )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Handle the case where we want to make a compound coordinate     */
+/*      system.                                                         */
+/* -------------------------------------------------------------------- */
+    if( IsProjected() || IsGeographic() )
+    {
+        OGR_SRSNode *poNewRoot = new OGR_SRSNode( "COMPD_CS" );
+        poNewRoot->AddChild( poRoot );
+        poRoot = poNewRoot;
+    }
+
+    else if( GetAttrNode( "VERT_CS" ) == NULL )
+        Clear();
+
+/* -------------------------------------------------------------------- */
+/*      If we already have a VERT_CS, wipe and recreate the root        */
+/*      otherwise create the VERT_CS now.                               */
+/* -------------------------------------------------------------------- */
+    OGR_SRSNode *poVertCS = GetAttrNode( "VERT_CS" );
+    
+    if( poVertCS != NULL )
+    {
+        poVertCS->ClearChildren();
+    }
+    else
+    {
+        poVertCS = new OGR_SRSNode( "VERT_CS" );
+        if( poRoot != NULL && EQUAL(poRoot->GetValue(),"COMPD_CS") )
+        {
+            poRoot->AddChild( poVertCS );
+        }
+        else
+            SetRoot( poVertCS );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set the name, datumname, and type.                              */
+/* -------------------------------------------------------------------- */
+    OGR_SRSNode *poVertDatum;
+
+    poVertCS->AddChild( new OGR_SRSNode( pszVertCSName ) );
+    
+    poVertDatum = new OGR_SRSNode( "VERT_DATUM" );
+    poVertCS->AddChild( poVertDatum );
+        
+    poVertDatum->AddChild( new OGR_SRSNode( pszVertDatumName ) );
+
+    CPLString osVertDatumType;
+    osVertDatumType.Printf( "%d", nVertDatumType );
+    poVertDatum->AddChild( new OGR_SRSNode( osVertDatumType ) );
+
+    // add default axis node.
+    OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
+
+    poAxis->AddChild( new OGR_SRSNode( "Up" ) );
+    poAxis->AddChild( new OGR_SRSNode( "UP" ) );
+
+    poVertCS->AddChild( poAxis );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            OSRSetVertCS()                            */
+/************************************************************************/
+
+/**
+ * \brief Setup the vertical coordinate system.
+ *
+ * This function is the same as OGRSpatialReference::SetVertCS()
+ *
+ * @since OGR 1.9.0
+ */
+OGRErr OSRSetVertCS( OGRSpatialReferenceH hSRS,
+                     const char * pszVertCSName,
+                     const char * pszVertDatumName,
+                     int nVertDatumType )
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRSetVertCS", CE_Failure );
+
+    return ((OGRSpatialReference *) hSRS)->SetVertCS( pszVertCSName,
+                                                      pszVertDatumName,
+                                                      nVertDatumType );
+}
+
+/************************************************************************/
+/*                           SetCompoundCS()                            */
+/************************************************************************/
+
+/**
+ * \brief Setup a compound coordinate system.
+ *
+ * This method is the same as the C function OSRSetCompoundCS(). 
+
+ * This method is replace the current SRS with a COMPD_CS coordinate system
+ * consisting of the passed in horizontal and vertical coordinate systems.
+ *
+ * @param pszName the name of the compound coordinate system. 
+ * 
+ * @param poHorizSRS the horizontal SRS (PROJCS or GEOGCS).
+ *  
+ * @param poVertSRS the vertical SRS (VERT_CS).
+ * 
+ * @return OGRERR_NONE on success.
+ */
+
+OGRErr 
+OGRSpatialReference::SetCompoundCS( const char *pszName,
+                                    const OGRSpatialReference *poHorizSRS,
+                                    const OGRSpatialReference *poVertSRS )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Verify these are legal horizontal and vertical coordinate       */
+/*      systems.                                                        */
+/* -------------------------------------------------------------------- */
+    if( !poVertSRS->IsVertical() ) 
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "SetCompoundCS() fails, vertical component is not VERT_CS." );
+        return OGRERR_FAILURE;
+    }
+    if( !poHorizSRS->IsProjected() 
+        && !poHorizSRS->IsGeographic() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "SetCompoundCS() fails, horizontal component is not PROJCS or GEOGCS." );
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Replace with compound srs.                                      */
+/* -------------------------------------------------------------------- */
+    Clear();
+
+    poRoot = new OGR_SRSNode( "COMPD_CS" );
+    poRoot->AddChild( new OGR_SRSNode( pszName ) );
+    poRoot->AddChild( poHorizSRS->GetRoot()->Clone() );
+    poRoot->AddChild( poVertSRS->GetRoot()->Clone() );
+    
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          OSRSetCompoundCS()                          */
+/************************************************************************/
+
+/**
+ * \brief Setup a compound coordinate system.
+ *
+ * This function is the same as OGRSpatialReference::SetCompoundCS()
+ */
+OGRErr OSRSetCompoundCS( OGRSpatialReferenceH hSRS,
+                         const char *pszName,
+                         OGRSpatialReferenceH hHorizSRS,
+                         OGRSpatialReferenceH hVertSRS )
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRSetCompoundCS", CE_Failure );
+    VALIDATE_POINTER1( hHorizSRS, "OSRSetCompoundCS", CE_Failure );
+    VALIDATE_POINTER1( hVertSRS, "OSRSetCompoundCS", CE_Failure );
+
+    return ((OGRSpatialReference *) hSRS)->
+        SetCompoundCS( pszName,
+                       (OGRSpatialReference *) hHorizSRS,
+                       (OGRSpatialReference *) hVertSRS );
+}
+
+/************************************************************************/
 /*                             SetProjCS()                              */
 /************************************************************************/
 
@@ -2504,7 +3079,7 @@ OGRErr OSRSetLocalCS( OGRSpatialReferenceH hSRS, const char * pszName )
  *
  * This method is the same as the C function OSRSetProjCS(). 
  *
- * This method is will ensure a PROJCS node is created as the root, 
+ * This method will ensure a PROJCS node is created as the root,
  * and set the provided name on it.  If used on a GEOGCS coordinate system, 
  * the GEOGCS node will be demoted to be a child of the new PROJCS root.
  *
@@ -3656,6 +4231,30 @@ OGRErr OSRSetGH( OGRSpatialReferenceH hSRS,
 }
 
 /************************************************************************/
+/*                              SetIGH()                                */
+/************************************************************************/
+
+OGRErr OGRSpatialReference::SetIGH()
+
+{
+    SetProjection( SRS_PT_IGH );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                              OSRSetIGH()                             */
+/************************************************************************/
+
+OGRErr OSRSetIGH( OGRSpatialReferenceH hSRS )
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRSetIGH", CE_Failure );
+
+    return ((OGRSpatialReference *) hSRS)->SetIGH();
+}
+
+/************************************************************************/
 /*                              SetGEOS()                               */
 /************************************************************************/
 
@@ -5085,6 +5684,8 @@ const char *OSRGetAuthorityName( OGRSpatialReferenceH hSRS,
  * portion remains (normally PROJCS, GEOGCS or LOCAL_CS). 
  *
  * If this is not a compound coordinate system then nothing is changed.
+ *
+ * @since OGR 1.8.0
  */
 
 OGRErr OGRSpatialReference::StripVertical()
@@ -5170,6 +5771,44 @@ OGRErr OSRStripCTParms( OGRSpatialReferenceH hSRS )
 }
 
 /************************************************************************/
+/*                             IsCompound()                             */
+/************************************************************************/
+
+/**
+ * \brief Check if coordinate system is compound.
+ *
+ * This method is the same as the C function OSRIsCompound().
+ *
+ * @return TRUE if this is rooted with a COMPD_CS node.
+ */
+
+int OGRSpatialReference::IsCompound() const
+
+{
+    if( poRoot == NULL )
+        return FALSE;
+
+    return EQUAL(poRoot->GetValue(),"COMPD_CS");
+}
+
+/************************************************************************/
+/*                           OSRIsCompound()                            */
+/************************************************************************/
+
+/** 
+ * \brief Check if the coordinate system is compound.
+ *
+ * This function is the same as OGRSpatialReference::IsCompound().
+ */
+int OSRIsCompound( OGRSpatialReferenceH hSRS ) 
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRIsCompound", 0 );
+
+    return ((OGRSpatialReference *) hSRS)->IsCompound();
+}
+
+/************************************************************************/
 /*                            IsProjected()                             */
 /************************************************************************/
 
@@ -5213,6 +5852,51 @@ int OSRIsProjected( OGRSpatialReferenceH hSRS )
 }
 
 /************************************************************************/
+/*                            IsGeocentric()                            */
+/************************************************************************/
+
+/**
+ * \brief Check if geocentric coordinate system.
+ *
+ * This method is the same as the C function OSRIsGeocentric().
+ *
+ * @return TRUE if this contains a GEOCCS node indicating a it is a 
+ * geocentric coordinate system.
+ *
+ * @since OGR 1.9.0
+ */
+
+int OGRSpatialReference::IsGeocentric() const
+
+{
+    if( poRoot == NULL )
+        return FALSE;
+
+    if( EQUAL(poRoot->GetValue(),"GEOCCS") )
+        return TRUE;
+    else 
+        return FALSE;
+}
+
+/************************************************************************/
+/*                           OSRIsGeocentric()                          */
+/************************************************************************/
+/** 
+ * \brief Check if geocentric coordinate system.
+ *
+ * This function is the same as OGRSpatialReference::IsGeocentric().
+ *
+ * @since OGR 1.9.0
+ */
+int OSRIsGeocentric( OGRSpatialReferenceH hSRS ) 
+
+{
+    VALIDATE_POINTER1( hSRS, "OSRIsGeocentric", 0 );
+
+    return ((OGRSpatialReference *) hSRS)->IsGeocentric();
+}
+
+/************************************************************************/
 /*                            IsGeographic()                            */
 /************************************************************************/
 
@@ -5304,7 +5988,9 @@ int OSRIsLocal( OGRSpatialReferenceH hSRS )
  * This method is the same as the C function OSRIsVertical().
  *
  * @return TRUE if this contains a VERT_CS node indicating a it is a 
- * vertical coordinate system. 
+ * vertical coordinate system.
+ *
+ * @since OGR 1.8.0
  */
 
 int OGRSpatialReference::IsVertical() const
@@ -5328,6 +6014,8 @@ int OGRSpatialReference::IsVertical() const
  * \brief Check if vertical coordinate system.
  *
  * This function is the same as OGRSpatialReference::IsVertical().
+ *
+ * @since OGR 1.8.0
  */
 int OSRIsVertical( OGRSpatialReferenceH hSRS ) 
 
@@ -5352,6 +6040,35 @@ OGRSpatialReference *OGRSpatialReference::CloneGeogCS() const
     const OGR_SRSNode *poGeogCS;
     OGRSpatialReference * poNewSRS;
 
+/* -------------------------------------------------------------------- */
+/*      We have to reconstruct the GEOGCS node for geocentric           */
+/*      coordinate systems.                                             */
+/* -------------------------------------------------------------------- */
+    if( IsGeocentric() )
+    {
+        const OGR_SRSNode *poDatum = GetAttrNode( "DATUM" );
+        const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
+        OGR_SRSNode *poGeogCS;
+        
+        if( poDatum == NULL || poPRIMEM == NULL )
+            return NULL;
+        
+        poGeogCS = new OGR_SRSNode( "GEOGCS" );
+        poGeogCS->AddChild( new OGR_SRSNode( "unnamed" ) );
+        poGeogCS->AddChild( poDatum->Clone() );
+        poGeogCS->AddChild( poPRIMEM->Clone() );
+
+        poNewSRS = new OGRSpatialReference();
+        poNewSRS->SetRoot( poGeogCS );
+
+        poNewSRS->SetAngularUnits( "degree", CPLAtof(SRS_UA_DEGREE_CONV) );
+
+        return poNewSRS;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      For all others we just search the tree, and duplicate.          */
+/* -------------------------------------------------------------------- */
     poGeogCS = GetAttrNode( "GEOGCS" );
     if( poGeogCS == NULL )
         return NULL;
@@ -5969,14 +6686,17 @@ OGRErr OGRSpatialReference::Fixup()
 
 {
 /* -------------------------------------------------------------------- */
-/*      Ensure linear units defaulted to METER if missing for PROJCS    */
-/*      or LOCAL_CS.                                                    */
+/*      Ensure linear units defaulted to METER if missing for PROJCS,   */
+/*      GEOCCS or LOCAL_CS.                                             */
 /* -------------------------------------------------------------------- */
     const OGR_SRSNode *poCS = GetAttrNode( "PROJCS" );
 
     if( poCS == NULL )
         poCS = GetAttrNode( "LOCAL_CS" );
 
+    if( poCS == NULL )
+        poCS = GetAttrNode( "GEOCCS" );
+
     if( poCS != NULL && poCS->FindChild( "UNIT" ) == -1 )
         SetLinearUnits( SRS_UL_METER, 1.0 );
 
@@ -6232,6 +6952,12 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
             *peOrientation = OAO_South;
         else if( EQUAL(pszOrientation,"WEST") )
             *peOrientation = OAO_West;
+        else if( EQUAL(pszOrientation,"UP") )
+            *peOrientation = OAO_Up;
+        else if( EQUAL(pszOrientation,"DOWN") )
+            *peOrientation = OAO_Down;
+        else if( EQUAL(pszOrientation,"OTHER") )
+            *peOrientation = OAO_Other;
         else
         {
             CPLDebug( "OSR", "Unrecognised orientation value '%s'.",
@@ -6284,6 +7010,12 @@ const char *OSRAxisEnumToName( OGRAxisOrientation eOrientation )
         return "SOUTH";
     if( eOrientation == OAO_West )
         return "WEST";
+    if( eOrientation == OAO_Up )
+        return "UP";
+    if( eOrientation == OAO_Down )
+        return "DOWN";
+    if( eOrientation == OAO_Other )
+        return "OTHER";
 
     return "UNKNOWN";
 }
diff --git a/ogr/ogrutils.cpp b/ogr/ogrutils.cpp
index 4d5ea09..d1af883 100644
--- a/ogr/ogrutils.cpp
+++ b/ogr/ogrutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrutils.cpp 20483 2010-08-29 18:42:23Z rouault $
+ * $Id: ogrutils.cpp 23584 2011-12-17 09:43:03Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility functions for OGR classes, including some related to
@@ -37,7 +37,7 @@
 # include "ogrsf_frmts.h"
 #endif /* OGR_ENABLED */
 
-CPL_CVSID("$Id: ogrutils.cpp 20483 2010-08-29 18:42:23Z rouault $");
+CPL_CVSID("$Id: ogrutils.cpp 23584 2011-12-17 09:43:03Z rouault $");
 
 /************************************************************************/
 /*                        OGRFormatDouble()                             */
@@ -388,9 +388,11 @@ const char * OGRWktReadPoints( const char * pszInput,
             }
 
             (*ppadfZ)[*pnPointsRead] = CPLAtof(szDelim);
-            
+
             pszInput = OGRWktReadToken( pszInput, szDelim );
         }
+        else if ( *ppadfZ != NULL )
+            (*ppadfZ)[*pnPointsRead] = 0.0;
         
         (*pnPointsRead)++;
 
@@ -476,10 +478,14 @@ void OGRFree( void * pMemory )
  * options for all OGR commandline utilities.  It takes care of the following
  * commandline options:
  *  
+ *  --version: report version of GDAL in use. 
+ *  --license: report GDAL license info.
  *  --formats: report all format drivers configured.
  *  --optfile filename: expand an option file into the argument list. 
  *  --config key value: set system configuration option. 
  *  --debug [on/off/value]: set debug level.
+ *  --pause: Pause for user input (allows time to attach debugger)
+ *  --locale [locale]: Install a locale using setlocale() (debugging)
  *  --help-general: report detailed help on general options. 
  *
  * The argument array is replaced "in place" and should be freed with 
@@ -713,10 +719,8 @@ int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--pause") )
         {
-            char szLine[81];
-
-            printf( "Hit <ENTER> to continue.\n" );
-            fgets( szLine, sizeof(szLine), stdin );
+            printf( "Hit <ENTER> to Continue.\n" );
+            CPLReadLine( stdin );
         }
 
 /* -------------------------------------------------------------------- */
@@ -733,6 +737,8 @@ int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
             printf( "  --optfile filename: expand an option file into the argument list.\n" );
             printf( "  --config key value: set system configuration option.\n" );
             printf( "  --debug [on/off/value]: set debug level.\n" );
+            printf( "  --pause: wait for user input, time to attach debugger\n" );
+            printf( "  --locale [locale]: install locale for debugging (ie. en_US.UTF-8)\n" );
             printf( "  --help-general: report detailed help on general options.\n" );
             CSLDestroy( papszReturn );
             return 0;
@@ -1271,6 +1277,7 @@ double OGRCallAtofOnShortString(const char* pszStr)
     while(*p == '+'  ||
           *p == '-'  ||
           (*p >= '0' && *p <= '9') ||
+          *p == '.'  ||
           (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D'))
     {
         szTemp[nCounter++] = *(p++);
@@ -1350,3 +1357,38 @@ double OGRFastAtof(const char* pszStr)
         }
     }
 }
+
+/**
+ * Check that panPermutation is a permutation of [0,nSize-1].
+ * @param panPermutation an array of nSize elements.
+ * @param nSize size of the array.
+ * @return OGRERR_NONE if panPermutation is a permutation of [0,nSize-1].
+ * @since OGR 1.9.0
+ */
+OGRErr OGRCheckPermutation(int* panPermutation, int nSize)
+{
+    OGRErr eErr = OGRERR_NONE;
+    int* panCheck = (int*)CPLCalloc(nSize, sizeof(int));
+    int i;
+    for(i=0;i<nSize;i++)
+    {
+        if (panPermutation[i] < 0 || panPermutation[i] >= nSize)
+        {
+            CPLError(CE_Failure, CPLE_IllegalArg,
+                     "Bad value for element %d", i);
+            eErr = OGRERR_FAILURE;
+            break;
+        }
+        if (panCheck[panPermutation[i]] != 0)
+        {
+            CPLError(CE_Failure, CPLE_IllegalArg,
+                     "Array is not a permutation of [0,%d]",
+                     nSize - 1);
+            eErr = OGRERR_FAILURE;
+            break;
+        }
+        panCheck[panPermutation[i]] = 1;
+    }
+    CPLFree(panCheck);
+    return eErr;
+}
diff --git a/ogr/swq.cpp b/ogr/swq.cpp
index 1b1540e..3cf7070 100644
--- a/ogr/swq.cpp
+++ b/ogr/swq.cpp
@@ -178,6 +178,8 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
             nReturn = SWQT_LIKE;
         else if( EQUAL(osToken,"ILIKE") )
             nReturn = SWQT_LIKE;
+        else if( EQUAL(osToken,"ESCAPE") )
+            nReturn = SWQT_ESCAPE;
         else if( EQUAL(osToken,"NULL") )
             nReturn = SWQT_NULL;
         else if( EQUAL(osToken,"IS") )
@@ -263,7 +265,7 @@ swq_select_summarize( swq_select *select_info,
 /*      Create the summary information if this is the first row         */
 /*      being processed.                                                */
 /* -------------------------------------------------------------------- */
-    if( select_info->column_summary == NULL )
+    if( select_info->column_summary == NULL && value != NULL )
     {
         int i;
 
@@ -292,7 +294,13 @@ swq_select_summarize( swq_select *select_info,
            data structure to achieve any sort of efficiency. */
         for( i = 0; i < summary->count; i++ )
         {
-            if( strcmp(value,summary->distinct_list[i]) == 0 )
+            if( value == NULL )
+            {
+                if (summary->distinct_list[i] == NULL)
+                    break;
+            }
+            else if( summary->distinct_list[i] != NULL &&
+                     strcmp(value,summary->distinct_list[i]) == 0 )
                 break;
         }
         
@@ -305,7 +313,7 @@ swq_select_summarize( swq_select *select_info,
             memcpy( summary->distinct_list, old_list, 
                     sizeof(char *) * summary->count );
             summary->distinct_list[(summary->count)++] = 
-                CPLStrdup( value );
+                (value != NULL) ? CPLStrdup( value ) : NULL;
 
             CPLFree(old_list);
         }
@@ -367,8 +375,15 @@ static int FORCE_CDECL swq_compare_int( const void *item1, const void *item2 )
 {
     int  v1, v2;
 
-    v1 = atoi(*((const char **) item1));
-    v2 = atoi(*((const char **) item2));
+    const char* pszStr1 = *((const char **) item1);
+    const char* pszStr2 = *((const char **) item2);
+    if (pszStr1 == NULL)
+        return (pszStr2 == NULL) ? 0 : -1;
+    else if (pszStr2 == NULL)
+        return 1;
+
+    v1 = atoi(pszStr1);
+    v2 = atoi(pszStr2);
 
     if( v1 < v2 )
         return -1;
@@ -382,8 +397,15 @@ static int FORCE_CDECL swq_compare_real( const void *item1, const void *item2 )
 {
     double  v1, v2;
 
-    v1 = CPLAtof(*((const char **) item1));
-    v2 = CPLAtof(*((const char **) item2));
+    const char* pszStr1 = *((const char **) item1);
+    const char* pszStr2 = *((const char **) item2);
+    if (pszStr1 == NULL)
+        return (pszStr2 == NULL) ? 0 : -1;
+    else if (pszStr2 == NULL)
+        return 1;
+
+    v1 = CPLAtof(pszStr1);
+    v2 = CPLAtof(pszStr2);
 
     if( v1 < v2 )
         return -1;
@@ -395,7 +417,14 @@ static int FORCE_CDECL swq_compare_real( const void *item1, const void *item2 )
 
 static int FORCE_CDECL swq_compare_string( const void *item1, const void *item2 )
 {
-    return strcmp( *((const char **) item1), *((const char **) item2) );
+    const char* pszStr1 = *((const char **) item1);
+    const char* pszStr2 = *((const char **) item2);
+    if (pszStr1 == NULL)
+        return (pszStr2 == NULL) ? 0 : -1;
+    else if (pszStr2 == NULL)
+        return 1;
+
+    return strcmp( pszStr1, pszStr2 );
 }
 
 /************************************************************************/
@@ -609,3 +638,42 @@ CPLErr swq_expr_compile2( const char *where_clause,
         return CE_Failure;
     }
 }
+
+/************************************************************************/
+/*                        swq_is_reserved_keyword()                     */
+/************************************************************************/
+
+static const char* apszSQLReservedKeywords[] = {
+    "OR",
+    "AND",
+    "NOT",
+    "LIKE",
+    "IS",
+    "NULL",
+    "IN",
+    "BETWEEN",
+    "CAST",
+    "DISTINCT",
+    "ESCAPE",
+    "SELECT",
+    "LEFT",
+    "JOIN",
+    "WHERE",
+    "ON",
+    "ORDER",
+    "BY",
+    "FROM",
+    "AS",
+    "ASC",
+    "DESC"
+};
+
+int swq_is_reserved_keyword(const char* pszStr)
+{
+    for(int i = 0; i < (int)(sizeof(apszSQLReservedKeywords)/sizeof(char*)); i++)
+    {
+        if (EQUAL(pszStr, apszSQLReservedKeywords[i]))
+            return TRUE;
+    }
+    return FALSE;
+}
diff --git a/ogr/swq.h b/ogr/swq.h
index 333e309..e4252b9 100644
--- a/ogr/swq.h
+++ b/ogr/swq.h
@@ -91,7 +91,7 @@ typedef swq_expr_node *(*swq_op_evaluator)(swq_expr_node *op,
 typedef swq_field_type (*swq_op_checker)( swq_expr_node *op );
 
 class swq_expr_node {
-    static void   Quote( CPLString & );
+    static void   Quote( CPLString &, char chQuote = '\'' );
 public:
     swq_expr_node();
 
@@ -103,7 +103,7 @@ public:
     ~swq_expr_node();
 
     void           Initialize();
-    char          *Unparse( swq_field_list * );
+    char          *Unparse( swq_field_list *, char chColumnQuote );
     void           Dump( FILE *fp, int depth );
     swq_field_type Check( swq_field_list * );
     swq_expr_node* Evaluate( swq_field_fetcher pfnFetcher, 
@@ -248,7 +248,7 @@ typedef struct {
 typedef struct {
     int         count;
     
-    char        **distinct_list;
+    char        **distinct_list; /* items of the list can be NULL */
     double      sum;
     double      min;
     double      max;
@@ -323,4 +323,6 @@ const char *swq_select_summarize( swq_select *select_info,
                                   int dest_column, 
                                   const char *value );
 
+int swq_is_reserved_keyword(const char* pszStr);
+
 #endif /* def _SWQ_H_INCLUDED_ */
diff --git a/ogr/swq_expr_node.cpp b/ogr/swq_expr_node.cpp
index 2443753..fa3d392 100644
--- a/ogr/swq_expr_node.cpp
+++ b/ogr/swq_expr_node.cpp
@@ -77,7 +77,8 @@ swq_expr_node::swq_expr_node( const char *pszValueIn )
     Initialize();
 
     field_type = SWQ_STRING;
-    string_value = CPLStrdup(pszValueIn);
+    string_value = CPLStrdup( pszValueIn ? pszValueIn : "" );
+    is_null = pszValueIn == NULL;
 }
 
 /************************************************************************/
@@ -302,22 +303,25 @@ void swq_expr_node::Dump( FILE * fp, int depth )
 /*      Add quoting necessary to unparse a string.                      */
 /************************************************************************/
 
-void swq_expr_node::Quote( CPLString &osTarget )
+void swq_expr_node::Quote( CPLString &osTarget, char chQuote )
 
 {
     CPLString osNew;
     int i;
 
-    osNew = "'";
+    osNew += chQuote;
 
     for( i = 0; i < (int) osTarget.size(); i++ )
     {
-        if( osTarget[i] == '\'' )
-            osNew += "''";
+        if( osTarget[i] == chQuote )
+        {
+            osNew += chQuote;
+            osNew += chQuote;
+        }
         else
             osNew += osTarget[i];
     }
-    osNew += "'";
+    osNew += chQuote;
 
     osTarget = osNew;
 }
@@ -326,7 +330,7 @@ void swq_expr_node::Quote( CPLString &osTarget )
 /*                              Unparse()                               */
 /************************************************************************/
 
-char *swq_expr_node::Unparse( swq_field_list *field_list )
+char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
 
 {
     CPLString osExpr;
@@ -336,6 +340,9 @@ char *swq_expr_node::Unparse( swq_field_list *field_list )
 /* -------------------------------------------------------------------- */
     if( eNodeType == SNT_CONSTANT )
     {
+        if (is_null)
+            return CPLStrdup("NULL");
+
         if( field_type == SWQ_INTEGER || field_type == SWQ_BOOLEAN )
             osExpr.Printf( "%d", int_value );
         else if( field_type == SWQ_FLOAT )
@@ -363,8 +370,24 @@ char *swq_expr_node::Unparse( swq_field_list *field_list )
         else if( field_index != -1 )
             osExpr.Printf( "%s", field_list->names[field_index] );
 
-        Quote( osExpr );
 
+        for( int i = 0; i < (int) osExpr.size(); i++ )
+        {
+            char ch = osExpr[i];
+            if (!(isalnum((int)ch) || ch == '_'))
+            {
+                Quote( osExpr, chColumnQuote );
+                return CPLStrdup(osExpr.c_str());
+            }
+        }
+
+        if (swq_is_reserved_keyword(osExpr))
+        {
+            Quote( osExpr, chColumnQuote );
+            return CPLStrdup(osExpr.c_str());
+        }
+
+        /* The string is just alphanum and not a reserved SQL keyword, no needs to quote and escape */
         return CPLStrdup(osExpr.c_str());
     }
 
@@ -375,7 +398,7 @@ char *swq_expr_node::Unparse( swq_field_list *field_list )
     int i;
 
     for( i = 0; i < nSubExprCount; i++ )
-        apszSubExpr.push_back( papoSubExpr[i]->Unparse(field_list) );
+        apszSubExpr.push_back( papoSubExpr[i]->Unparse(field_list, chColumnQuote) );
 
 /* -------------------------------------------------------------------- */
 /*      Put things together in a fashion depending on the operator.     */
@@ -406,11 +429,34 @@ char *swq_expr_node::Unparse( swq_field_list *field_list )
       case SWQ_MULTIPLY:
       case SWQ_DIVIDE:
       case SWQ_MODULUS:
-        CPLAssert( nSubExprCount == 2 );
-        osExpr.Printf( "(%s) %s (%s)", 
-                       apszSubExpr[0],
-                       poOp->osName.c_str(),
-                       apszSubExpr[1] );
+        CPLAssert( nSubExprCount >= 2 );
+        if (papoSubExpr[0]->eNodeType == SNT_COLUMN ||
+            papoSubExpr[0]->eNodeType == SNT_CONSTANT)
+        {
+            osExpr += apszSubExpr[0];
+        }
+        else
+        {
+            osExpr += "(";
+            osExpr += apszSubExpr[0];
+            osExpr += ")";
+        }
+        osExpr += " ";
+        osExpr += poOp->osName;
+        osExpr += " ";
+        if (papoSubExpr[1]->eNodeType == SNT_COLUMN ||
+            papoSubExpr[1]->eNodeType == SNT_CONSTANT)
+        {
+            osExpr += apszSubExpr[1];
+        }
+        else
+        {
+            osExpr += "(";
+            osExpr += apszSubExpr[1];
+            osExpr += ")";
+        }
+        if( nOperation == SWQ_LIKE && nSubExprCount == 3 )
+            osExpr += CPLSPrintf( " ESCAPE (%s)", apszSubExpr[2] );
         break;
 
       case SWQ_NOT:
@@ -495,6 +541,8 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
         else
             poRetNode->string_value = NULL;
 
+        poRetNode->is_null = is_null;
+
         return poRetNode;
     }
 
diff --git a/ogr/swq_op_general.cpp b/ogr/swq_op_general.cpp
index 38f9a9a..d1901de 100644
--- a/ogr/swq_op_general.cpp
+++ b/ogr/swq_op_general.cpp
@@ -37,7 +37,7 @@
 /*      Does input match pattern?                                       */
 /************************************************************************/
 
-int swq_test_like( const char *input, const char *pattern )
+int swq_test_like( const char *input, const char *pattern, char chEscape )
 
 {
     if( input == NULL || pattern == NULL )
@@ -48,6 +48,20 @@ int swq_test_like( const char *input, const char *pattern )
         if( *pattern == '\0' )
             return 0;
 
+        else if( *pattern == chEscape )
+        {
+            pattern++;
+            if( *pattern == '\0' )
+                return 0;
+            if( tolower(*pattern) != tolower(*input) )
+                return 0;
+            else
+            {
+                input++;
+                pattern++;
+            }
+        }
+
         else if( *pattern == '_' )
         {
             input++;
@@ -63,7 +77,7 @@ int swq_test_like( const char *input, const char *pattern )
             /* try eating varying amounts of the input till we get a positive*/
             for( eat = 0; input[eat] != '\0'; eat++ )
             {
-                if( swq_test_like(input+eat,pattern+1) )
+                if( swq_test_like(input+eat,pattern+1, chEscape) )
                     return 1;
             }
 
@@ -407,9 +421,15 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
             break;
 
           case SWQ_LIKE:
+          {
+            char chEscape = '\0';
+            if( node->nSubExprCount == 3 )
+                chEscape = sub_node_values[2]->string_value[0];
             poRet->int_value = swq_test_like(sub_node_values[0]->string_value,
-                                             sub_node_values[1]->string_value);
+                                             sub_node_values[1]->string_value,
+                                             chEscape);
             break;
+          }
 
           case SWQ_ISNULL:
             poRet->int_value = sub_node_values[0]->is_null;
@@ -425,6 +445,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                   osResult += sub_node_values[i]->string_value;
               
               poRet->string_value = CPLStrdup(osResult);
+              poRet->is_null = sub_node_values[0]->is_null;
               break;
           }
             
@@ -450,7 +471,23 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                   nSize = 0;
 
               int nSrcStrLen = (int)strlen(pszSrcStr);
-              if( nOffset < 0 || nSize < 0 || nOffset > nSrcStrLen )
+
+
+              /* In SQL, the first character is at offset 1 */
+              /* And 0 is considered as 1 */
+              if (nOffset > 0)
+                  nOffset --;
+              /* Some implementations allow negative offsets, to start */
+              /* from the end of the string */
+              else if( nOffset < 0 )
+              {
+                  if( nSrcStrLen + nOffset >= 0 )
+                      nOffset = nSrcStrLen + nOffset;
+                  else
+                      nOffset = 0;
+              }
+
+              if( nSize < 0 || nOffset > nSrcStrLen )
               {
                   nOffset = 0;
                   nSize = 0;
@@ -463,6 +500,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                   osResult.resize( nSize );
               
               poRet->string_value = CPLStrdup(osResult);
+              poRet->is_null = sub_node_values[0]->is_null;
               break;
           }
 
@@ -561,6 +599,67 @@ static void SWQAutoPromoteStringToDateTime( swq_expr_node *poNode )
 }
 
 /************************************************************************/
+/*                    SWQAutoConvertStringToNumeric()                   */
+/*                                                                      */
+/*      Convert string constants to integer or float constants          */
+/*      when there is a mix of arguments of type numeric and string     */
+/************************************************************************/
+
+static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
+
+{
+    if( poNode->nSubExprCount < 2 )
+        return;
+
+    swq_field_type eArgType = poNode->papoSubExpr[0]->field_type;
+    int i;
+
+    for( i = 1; i < poNode->nSubExprCount; i++ )
+    {
+        swq_expr_node *poSubNode = poNode->papoSubExpr[i];
+
+        /* identify the mixture of the argument type */
+        if( (eArgType == SWQ_STRING
+            && (poSubNode->field_type == SWQ_INTEGER
+               || poSubNode->field_type == SWQ_FLOAT)) ||
+            (eArgType == SWQ_INTEGER
+            && poSubNode->field_type == SWQ_STRING) )
+        {
+            eArgType = SWQ_FLOAT;
+            break;
+        }
+    }
+    
+    for( i = 0; i < poNode->nSubExprCount; i++ )
+    {
+        swq_expr_node *poSubNode = poNode->papoSubExpr[i];
+
+        if( eArgType == SWQ_FLOAT
+            && poSubNode->field_type == SWQ_STRING )
+        {
+            if( poSubNode->eNodeType == SNT_CONSTANT )
+            {
+                /* apply the string to numeric conversion */
+                char* endPtr = NULL;
+                poSubNode->float_value = CPLStrtod(poSubNode->string_value, &endPtr);
+                if ( !(endPtr == NULL || *endPtr == '\0') )
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                             "Conversion failed when converting the string value '%s' to data type float.",
+                             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;
+            }
+        }
+    }
+}
+
+/************************************************************************/
 /*                         SWQGeneralChecker()                          */
 /*                                                                      */
 /*      Check the general purpose functions have appropriate types,     */
@@ -592,6 +691,7 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode )
       case SWQ_IN:
       case SWQ_BETWEEN:
         eRetType = SWQ_BOOLEAN;
+        SWQAutoConvertStringToNumeric( poNode );
         SWQAutoPromoteIntegerToFloat( poNode );
         SWQAutoPromoteStringToDateTime( poNode );
         eArgType = poNode->papoSubExpr[0]->field_type;
@@ -732,6 +832,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
         case SWQ_INTEGER:
         {
             poRetNode = new swq_expr_node( 0 );
+            poRetNode->is_null = poSrcNode->is_null;
 
             switch( poSrcNode->field_type )
             {
@@ -754,6 +855,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
         case SWQ_FLOAT:
         {
             poRetNode = new swq_expr_node( 0.0 );
+            poRetNode->is_null = poSrcNode->is_null;
 
             switch( poSrcNode->field_type )
             {
@@ -804,6 +906,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
             }
 
             poRetNode = new swq_expr_node( osRet.c_str() );
+            poRetNode->is_null = poSrcNode->is_null;
         }
     }
 
diff --git a/ogr/swq_op_registrar.cpp b/ogr/swq_op_registrar.cpp
index 110dd9e..2ac1ac1 100644
--- a/ogr/swq_op_registrar.cpp
+++ b/ogr/swq_op_registrar.cpp
@@ -178,14 +178,19 @@ void swq_op_registrar::Initialize()
 void swq_op_registrar::DeInitialize()
 
 {
-    CPLMutexHolderD( &hOperationsMutex );
-
-    if( papoOperations == NULL)
-        return;
-
-    for( unsigned int i=0; i < papoOperations->size(); i++ )
-        delete (*papoOperations)[i];
+    {
+        CPLMutexHolderD( &hOperationsMutex );
+        
+        if( papoOperations != NULL)
+        {
+            for( unsigned int i=0; i < papoOperations->size(); i++ )
+                delete (*papoOperations)[i];
+            
+            delete papoOperations;
+            papoOperations = NULL;
+        }
+    }
 
-    delete papoOperations;
-    papoOperations = NULL;
+    CPLDestroyMutex( hOperationsMutex );
+    hOperationsMutex = NULL;
 }
diff --git a/ogr/swq_parser.cpp b/ogr/swq_parser.cpp
index c582674..e8e601c 100644
--- a/ogr/swq_parser.cpp
+++ b/ogr/swq_parser.cpp
@@ -114,6 +114,13 @@
 
 #define YYSTYPE  swq_expr_node*
 
+/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */ 
+/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */ 
+/* increase YYINITDEPTH instead, but this will consume memory. */ 
+/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */ 
+/* 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, 
@@ -155,29 +162,30 @@ static void swqerror( swq_parse_context *context, const char *msg )
      SWQT_IDENTIFIER = 260,
      SWQT_IN = 261,
      SWQT_LIKE = 262,
-     SWQT_BETWEEN = 263,
-     SWQT_NULL = 264,
-     SWQT_IS = 265,
-     SWQT_SELECT = 266,
-     SWQT_LEFT = 267,
-     SWQT_JOIN = 268,
-     SWQT_WHERE = 269,
-     SWQT_ON = 270,
-     SWQT_ORDER = 271,
-     SWQT_BY = 272,
-     SWQT_FROM = 273,
-     SWQT_AS = 274,
-     SWQT_ASC = 275,
-     SWQT_DESC = 276,
-     SWQT_DISTINCT = 277,
-     SWQT_CAST = 278,
-     SWQT_LOGICAL_START = 279,
-     SWQT_VALUE_START = 280,
-     SWQT_SELECT_START = 281,
-     SWQT_NOT = 282,
-     SWQT_OR = 283,
-     SWQT_AND = 284,
-     SWQT_UMINUS = 285
+     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_LOGICAL_START = 280,
+     SWQT_VALUE_START = 281,
+     SWQT_SELECT_START = 282,
+     SWQT_NOT = 283,
+     SWQT_OR = 284,
+     SWQT_AND = 285,
+     SWQT_UMINUS = 286
    };
 #endif
 
@@ -195,7 +203,7 @@ typedef int YYSTYPE;
 
 
 /* Line 264 of yacc.c  */
-#line 199 "swq_parser.cpp"
+#line 200 "swq_parser.cpp"
 
 #ifdef short
 # undef short
@@ -408,22 +416,22 @@ union yyalloc
 #endif
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  19
+#define YYFINAL  20
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   256
+#define YYLAST   301
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  44
+#define YYNTOKENS  45
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  17
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  76
+#define YYNRULES  79
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  171
+#define YYNSTATES  176
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   285
+#define YYMAXUTOK   286
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -434,10 +442,10 @@ 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,    41,     2,     2,     2,    34,     2,     2,
-      36,    37,    32,    30,    42,    31,    43,    33,     2,     2,
+       2,     2,     2,    42,     2,     2,     2,    35,     2,     2,
+      37,    38,    33,    31,    43,    32,    44,    34,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      39,    38,    40,     2,     2,     2,     2,     2,     2,     2,
+      40,    39,    41,     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,
@@ -459,7 +467,7 @@ 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,    35
+      25,    26,    27,    28,    29,    30,    36
 };
 
 #if YYDEBUG
@@ -469,61 +477,63 @@ 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,   108,   113,   117,   119,   121,
-     125,   127,   129,   131,   135,   138,   142,   146,   150,   154,
-     158,   163,   170,   172,   177,   184,   192,   194,   198,   201,
-     204,   206,   211,   215,   217,   221,   226,   233,   239,   247,
-     248,   251,   252,   260,   269,   270,   274,   278,   280,   282,
-     285,   288,   290,   292,   294,   297,   301
+      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,   207,
+     209,   213,   216,   219,   221,   226,   230,   232,   236,   241,
+     248,   254,   262,   263,   266,   267,   275,   284,   285,   289,
+     293,   295,   297,   300,   303,   305,   307,   309,   312,   316
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      45,     0,    -1,    24,    46,    -1,    25,    49,    -1,    26,
-      51,    -1,    46,    29,    46,    -1,    46,    28,    46,    -1,
-      27,    46,    -1,    36,    46,    37,    -1,    49,    38,    49,
-      -1,    49,    39,    40,    49,    -1,    49,    41,    38,    49,
-      -1,    49,    39,    49,    -1,    49,    40,    49,    -1,    49,
-      39,    38,    49,    -1,    49,    38,    39,    49,    -1,    49,
-      38,    40,    49,    -1,    49,    40,    38,    49,    -1,    49,
-       7,    49,    -1,    49,    27,     7,    49,    -1,    49,     6,
-      36,    47,    37,    -1,    49,    27,     6,    36,    47,    37,
-      -1,    49,     8,    49,    29,    49,    -1,    49,    27,     8,
-      49,    29,    49,    -1,    49,    10,     9,    -1,    49,    10,
-      27,     9,    -1,    49,    42,    47,    -1,    49,    -1,     5,
-      -1,     5,    43,     5,    -1,     3,    -1,     4,    -1,    48,
-      -1,    36,    49,    37,    -1,    31,    49,    -1,    49,    30,
-      49,    -1,    49,    31,    49,    -1,    49,    32,    49,    -1,
-      49,    33,    49,    -1,    49,    34,    49,    -1,     5,    36,
-      47,    37,    -1,    23,    36,    49,    19,    50,    37,    -1,
-       5,    -1,     5,    36,     3,    37,    -1,     5,    36,     3,
-      42,     3,    37,    -1,    11,    52,    18,    60,    55,    54,
-      56,    -1,    53,    -1,    53,    42,    52,    -1,    22,    48,
-      -1,    22,     4,    -1,    49,    -1,    22,    48,    19,    59,
-      -1,    49,    19,    59,    -1,    32,    -1,     5,    43,    32,
-      -1,     5,    36,    32,    37,    -1,     5,    36,    32,    37,
-      19,    59,    -1,     5,    36,    22,    48,    37,    -1,     5,
-      36,    22,    48,    37,    19,    59,    -1,    -1,    14,    46,
-      -1,    -1,    13,    60,    15,    48,    38,    48,    55,    -1,
-      12,    13,    60,    15,    48,    38,    48,    55,    -1,    -1,
-      16,    17,    57,    -1,    58,    42,    57,    -1,    58,    -1,
-      48,    -1,    48,    20,    -1,    48,    21,    -1,     5,    -1,
-       4,    -1,    59,    -1,    59,     5,    -1,     4,    43,    59,
-      -1,     4,    43,    59,     5,    -1
+      46,     0,    -1,    25,    47,    -1,    26,    50,    -1,    27,
+      52,    -1,    47,    30,    47,    -1,    47,    29,    47,    -1,
+      28,    47,    -1,    37,    47,    38,    -1,    50,    39,    50,
+      -1,    50,    40,    41,    50,    -1,    50,    42,    39,    50,
+      -1,    50,    40,    50,    -1,    50,    41,    50,    -1,    50,
+      40,    39,    50,    -1,    50,    39,    40,    50,    -1,    50,
+      39,    41,    50,    -1,    50,    41,    39,    50,    -1,    50,
+       7,    50,    -1,    50,    28,     7,    50,    -1,    50,     7,
+      50,     8,    50,    -1,    50,    28,     7,    50,     8,    50,
+      -1,    50,     6,    37,    48,    38,    -1,    50,    28,     6,
+      37,    48,    38,    -1,    50,     9,    50,    30,    50,    -1,
+      50,    28,     9,    50,    30,    50,    -1,    50,    11,    10,
+      -1,    50,    11,    28,    10,    -1,    50,    43,    48,    -1,
+      50,    -1,     5,    -1,     5,    44,     5,    -1,     3,    -1,
+       4,    -1,    49,    -1,    37,    50,    38,    -1,    10,    -1,
+      32,    50,    -1,    50,    31,    50,    -1,    50,    32,    50,
+      -1,    50,    33,    50,    -1,    50,    34,    50,    -1,    50,
+      35,    50,    -1,     5,    37,    48,    38,    -1,    24,    37,
+      50,    20,    51,    38,    -1,     5,    -1,     5,    37,     3,
+      38,    -1,     5,    37,     3,    43,     3,    38,    -1,    12,
+      53,    19,    61,    56,    55,    57,    -1,    54,    -1,    54,
+      43,    53,    -1,    23,    49,    -1,    23,     4,    -1,    50,
+      -1,    23,    49,    20,    60,    -1,    50,    20,    60,    -1,
+      33,    -1,     5,    44,    33,    -1,     5,    37,    33,    38,
+      -1,     5,    37,    33,    38,    20,    60,    -1,     5,    37,
+      23,    49,    38,    -1,     5,    37,    23,    49,    38,    20,
+      60,    -1,    -1,    15,    47,    -1,    -1,    14,    61,    16,
+      49,    39,    49,    56,    -1,    13,    14,    61,    16,    49,
+      39,    49,    56,    -1,    -1,    17,    18,    58,    -1,    59,
+      43,    58,    -1,    59,    -1,    49,    -1,    49,    21,    -1,
+      49,    22,    -1,     5,    -1,     4,    -1,    60,    -1,    60,
+       5,    -1,     4,    44,    60,    -1,     4,    44,    60,     5,
+      -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    94,    94,    99,   104,   110,   118,   126,   133,   138,
-     146,   154,   162,   170,   178,   186,   194,   202,   210,   218,
-     231,   240,   255,   264,   278,   285,   299,   305,   312,   319,
-     335,   340,   344,   349,   354,   370,   377,   384,   391,   398,
-     405,   429,   437,   443,   450,   459,   465,   466,   469,   478,
-     487,   496,   508,   519,   533,   555,   585,   619,   643,   671,
-     672,   677,   678,   687,   697,   698,   701,   702,   705,   711,
-     717,   725,   729,   735,   745,   756,   767
+       0,    95,    95,   100,   105,   111,   119,   127,   134,   139,
+     147,   155,   163,   171,   179,   187,   195,   203,   211,   219,
+     232,   241,   255,   264,   279,   288,   302,   309,   323,   329,
+     336,   343,   359,   364,   368,   373,   378,   383,   399,   406,
+     413,   420,   427,   434,   458,   466,   472,   479,   488,   494,
+     495,   498,   507,   516,   525,   537,   548,   562,   584,   614,
+     648,   672,   700,   701,   706,   707,   716,   726,   727,   730,
+     731,   734,   740,   746,   754,   758,   764,   774,   785,   796
 };
 #endif
 
@@ -533,17 +543,17 @@ static const yytype_uint16 yyrline[] =
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "SWQT_NUMBER", "SWQT_STRING",
-  "SWQT_IDENTIFIER", "SWQT_IN", "SWQT_LIKE", "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_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_field_list", "column_spec",
-  "opt_where", "opt_joins", "opt_order_by", "sort_spec_list", "sort_spec",
-  "string_or_identifier", "table_def", 0
+  "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_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_field_list",
+  "column_spec", "opt_where", "opt_joins", "opt_order_by",
+  "sort_spec_list", "sort_spec", "string_or_identifier", "table_def", 0
 };
 #endif
 
@@ -555,22 +565,22 @@ 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,
-      43,    45,    42,    47,    37,   285,    40,    41,    61,    60,
-      62,    33,    44,    46
+     285,    43,    45,    42,    47,    37,   286,    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,    44,    45,    45,    45,    46,    46,    46,    46,    46,
-      46,    46,    46,    46,    46,    46,    46,    46,    46,    46,
-      46,    46,    46,    46,    46,    46,    47,    47,    48,    48,
-      49,    49,    49,    49,    49,    49,    49,    49,    49,    49,
-      49,    49,    50,    50,    50,    51,    52,    52,    53,    53,
-      53,    53,    53,    53,    53,    53,    53,    53,    53,    54,
-      54,    55,    55,    55,    56,    56,    57,    57,    58,    58,
-      58,    59,    59,    60,    60,    60,    60
+       0,    45,    46,    46,    46,    47,    47,    47,    47,    47,
+      47,    47,    47,    47,    47,    47,    47,    47,    47,    47,
+      47,    47,    47,    47,    47,    47,    47,    47,    48,    48,
+      49,    49,    50,    50,    50,    50,    50,    50,    50,    50,
+      50,    50,    50,    50,    50,    51,    51,    51,    52,    53,
+      53,    54,    54,    54,    54,    54,    54,    54,    54,    54,
+      54,    54,    55,    55,    56,    56,    56,    57,    57,    58,
+      58,    59,    59,    59,    60,    60,    61,    61,    61,    61
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -578,12 +588,12 @@ 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,     3,     4,     3,     1,     1,     3,
-       1,     1,     1,     3,     2,     3,     3,     3,     3,     3,
-       4,     6,     1,     4,     6,     7,     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
+       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,     7,     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
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -591,63 +601,63 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     0,     0,    30,    31,    28,     0,     0,
-       0,     0,     2,    32,     0,     0,     3,     0,     4,     1,
-       0,     0,     0,     7,    34,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    32,    33,    30,    36,     0,
+       0,     0,     0,     2,    34,     0,     0,     3,     0,     4,
+       1,     0,     0,     0,     7,    37,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    28,     0,    53,    50,     0,    46,
-       0,    27,    29,     0,     8,    33,     6,     5,     0,    18,
-       0,    24,     0,     0,     0,     0,    35,    36,    37,    38,
-      39,     0,     0,     9,     0,     0,    12,     0,    13,     0,
-       0,     0,    49,    28,    48,     0,     0,     0,    40,     0,
-       0,     0,     0,    25,     0,    19,     0,    15,    16,    14,
-      10,    17,    11,     0,     0,    54,     0,    72,    71,    52,
-      72,    73,    61,    47,    26,    42,     0,    20,    22,     0,
-       0,     0,    55,    51,     0,    74,     0,     0,    59,     0,
-      41,    21,    23,    57,     0,    75,     0,     0,     0,    64,
-       0,     0,    56,    76,     0,     0,    60,     0,    45,    43,
-       0,    58,     0,     0,     0,     0,     0,     0,    68,    65,
-      67,    44,     0,    61,    69,    70,     0,    61,    62,    66,
-      63
+       0,     0,     0,     0,     0,    30,     0,    56,    53,     0,
+      49,     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,    52,    30,    51,     0,     0,     0,    43,
+       0,     0,     0,     0,     0,    27,     0,    19,     0,    15,
+      16,    14,    10,    17,    11,     0,     0,    57,     0,    75,
+      74,    55,    75,    76,    64,    50,    28,    45,     0,    22,
+      20,    24,     0,     0,     0,     0,    58,    54,     0,    77,
+       0,     0,    62,     0,    44,    23,    21,    25,    60,     0,
+      78,     0,     0,     0,    67,     0,     0,    59,    79,     0,
+       0,    63,     0,    48,    46,     0,    61,     0,     0,     0,
+       0,     0,     0,    71,    68,    70,    47,     0,    64,    72,
+      73,     0,    64,    65,    69,    66
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     4,    12,    50,    13,    14,   116,    18,    48,    49,
-     139,   128,   148,   159,   160,   111,   112
+      -1,     4,    13,    51,    14,    15,   118,    19,    49,    50,
+     144,   132,   153,   164,   165,   113,   114
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -111
+#define YYPACT_NINF -125
 static const yytype_int16 yypact[] =
 {
-      90,   177,   188,    37,    24,  -111,  -111,    13,    14,   177,
-     188,   177,     9,  -111,   135,   188,   -21,   167,  -111,  -111,
-     188,    57,   188,     9,  -111,   -23,   120,   177,   177,    35,
-     188,   188,    -6,   113,   188,   188,   188,   188,   188,    50,
-     100,    29,    40,   206,    15,    70,  -111,   195,    65,    49,
-      56,   153,  -111,   201,  -111,  -111,    69,  -111,   188,   -21,
-     215,  -111,    93,    64,   188,   188,   101,   101,  -111,  -111,
-    -111,   188,   188,   -21,   188,   188,   -21,   188,   -21,   188,
-     174,    -1,  -111,    66,    92,    83,    91,   167,  -111,   188,
-     107,    80,   188,  -111,   188,   -21,   221,   -21,   -21,   -21,
-     -21,   -21,   -21,   119,    95,  -111,    83,  -111,  -111,  -111,
-      96,   132,    94,  -111,  -111,   108,   109,  -111,   -21,   118,
-     188,   126,   137,  -111,    83,  -111,   151,    91,   180,   185,
-    -111,  -111,   -21,   182,    83,   197,    91,   192,   177,   193,
-     -14,    83,  -111,  -111,   200,   119,     9,   199,  -111,  -111,
-     209,  -111,   119,   179,   119,   181,   183,   119,   128,  -111,
-     214,  -111,   119,    94,  -111,  -111,   119,    94,  -111,  -111,
-    -111
+      93,   196,   212,    43,    26,  -125,  -125,    -6,  -125,    -9,
+     196,   212,   196,   -17,  -125,   138,   212,   266,     0,  -125,
+    -125,   212,    52,   212,   -17,  -125,    18,   123,   196,   196,
+      27,   212,   212,     1,   101,   212,   212,   212,   212,   212,
+      49,    99,   171,    28,   246,    14,    70,  -125,   206,    53,
+      35,    45,   233,  -125,   240,  -125,  -125,    61,  -125,   212,
+     219,   255,  -125,    89,    56,   212,   212,   108,   108,  -125,
+    -125,  -125,   212,   212,   266,   212,   212,   266,   212,   266,
+     212,   181,    16,  -125,    57,    86,    83,    91,     0,  -125,
+     212,   106,    75,   212,   212,  -125,   212,   224,   261,   266,
+     266,   266,   266,   266,   266,   116,    97,  -125,    83,  -125,
+    -125,  -125,    95,   132,   102,  -125,  -125,   109,   110,  -125,
+     266,   266,   112,   212,   212,   114,   133,  -125,    83,  -125,
+     145,    91,   152,   157,  -125,  -125,   266,   266,   148,    83,
+     177,    91,   167,   196,   170,   -29,    83,  -125,  -125,   172,
+     116,   -17,   174,  -125,  -125,   186,  -125,   116,   151,   116,
+     155,   158,   116,   103,  -125,   153,  -125,   116,   102,  -125,
+    -125,   116,   102,  -125,  -125,  -125
 };
 
 /* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
+static const yytype_int8 yypgoto[] =
 {
-    -111,  -111,    -9,   -28,   -44,     5,  -111,  -111,   136,  -111,
-    -111,   -95,  -111,    75,  -111,   -77,  -110
+    -125,  -125,   -10,   -25,   -45,     4,  -125,  -125,   119,  -125,
+    -125,  -106,  -125,    23,  -125,   -78,  -124
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -657,86 +667,96 @@ static const yytype_int16 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      23,    84,    25,    61,    52,    27,    28,    16,   109,    34,
-      35,    36,    37,    38,    54,    24,    26,   137,    56,    57,
-      43,    62,    47,   149,    19,    51,   144,    53,   150,   123,
-      91,   105,     5,     6,     7,    59,    60,    27,    28,    66,
-      67,    68,    69,    70,    73,    76,    78,   135,    17,    20,
-      22,    80,     8,     5,     6,     7,    21,   142,    81,   121,
-      10,   114,    52,    51,   151,    15,   119,    77,   168,    95,
-      96,    58,   170,     8,    82,    83,    97,    98,    79,    99,
-     100,    10,   101,    86,   102,    51,    15,   107,   108,    71,
-      72,    87,    47,    88,    51,   110,   108,   118,    28,    51,
-      94,   153,    93,     5,     6,     7,   126,   127,   156,    21,
-     158,   106,   115,   163,     1,     2,     3,   117,   167,    63,
-      64,    65,   158,     8,    83,   132,    29,    30,    31,   146,
-      32,    10,   122,    36,    37,    38,    15,   125,    74,   124,
-      75,    29,    30,    31,   129,    32,   130,    33,   164,   165,
-      34,    35,    36,    37,    38,   131,   134,    55,    39,    40,
-      41,    42,    33,   133,   136,    34,    35,    36,    37,    38,
-       5,     6,    44,    39,    40,    41,    42,     5,     6,     7,
-       5,     6,     7,    34,    35,    36,    37,    38,   140,    45,
-       8,     5,     6,     7,   138,    89,   103,     8,    10,    46,
-       8,   141,   143,    15,     9,    10,   104,   145,    10,   147,
-      15,     8,   155,    11,    85,   152,   154,   157,   161,    10,
-      90,   162,     0,   113,    15,    34,    35,    36,    37,    38,
-       0,    34,    35,    36,    37,    38,    34,    35,    36,    37,
-      38,   169,     0,    55,    92,    34,    35,    36,    37,    38,
-     120,    34,    35,    36,    37,    38,   166
+      24,    85,    26,     5,     6,    45,    17,   142,   111,   154,
+       8,    62,    28,    29,   155,    25,    27,   149,    57,    58,
+      44,    53,    48,    46,     9,    52,    20,    54,    23,    63,
+     127,    21,    11,    47,    92,    60,    61,    16,    22,    67,
+      68,    69,    70,    71,    74,    77,    79,    28,    29,   107,
+     140,    81,     5,     6,     7,    18,    55,    53,    82,     8,
+     125,   147,   173,    52,    59,   116,   175,    80,   156,    97,
+      98,   122,    87,     9,    83,    84,    99,   100,    88,   101,
+     102,    11,   103,    89,   104,    52,    16,   109,   110,    72,
+      73,    29,    48,    96,    52,   112,   110,   120,   121,    95,
+      52,    22,     5,     6,     7,   158,   108,    64,    65,     8,
+      66,   117,   161,   119,   163,   130,   131,   168,     1,     2,
+       3,    84,   172,     9,   169,   170,   163,   136,   137,    30,
+      31,    11,    32,   151,    33,   126,    16,   129,    75,   128,
+      76,    37,    38,    39,    30,    31,   133,    32,   134,    33,
+     135,    34,   138,   139,    35,    36,    37,    38,    39,   141,
+     145,    56,    40,    41,    42,    43,    34,   143,   146,    35,
+      36,    37,    38,    39,     5,     6,     7,    40,    41,    42,
+      43,     8,   148,   150,     5,     6,     7,   152,   157,   160,
+     162,     8,   159,   166,   174,     9,   171,   167,     0,     5,
+       6,     7,     0,    11,   105,     9,     8,   115,    16,     0,
+      78,     0,     0,    11,   106,     5,     6,     7,    16,     0,
+       9,     0,     8,     0,    10,     0,    86,    93,    11,     0,
+       0,     0,   123,    12,     0,     0,     9,    35,    36,    37,
+      38,    39,     0,     0,    11,     0,     0,     0,     0,    16,
+      35,    36,    37,    38,    39,    35,    36,    37,    38,    39,
+      91,     0,     0,     0,    35,    36,    37,    38,    39,     0,
+       0,    35,    36,    37,    38,    39,    90,    35,    36,    37,
+      38,    39,     0,     0,    56,    94,    35,    36,    37,    38,
+      39,   124,    35,    36,    37,    38,    39,    35,    36,    37,
+      38,    39
 };
 
 static const yytype_int16 yycheck[] =
 {
-       9,    45,    11,     9,     5,    28,    29,     2,    85,    30,
-      31,    32,    33,    34,    37,    10,    11,   127,    27,    28,
-      15,    27,    17,    37,     0,    20,   136,    22,    42,   106,
-      58,    32,     3,     4,     5,    30,    31,    28,    29,    34,
-      35,    36,    37,    38,    39,    40,    41,   124,    11,    36,
-      36,    36,    23,     3,     4,     5,    43,   134,    43,   103,
-      31,    89,     5,    58,   141,    36,    94,    38,   163,    64,
-      65,    36,   167,    23,     4,     5,    71,    72,    38,    74,
-      75,    31,    77,    18,    79,    80,    36,     4,     5,    39,
-      40,    42,    87,    37,    89,     4,     5,    92,    29,    94,
-      36,   145,     9,     3,     4,     5,    12,    13,   152,    43,
-     154,    19,     5,   157,    24,    25,    26,    37,   162,     6,
-       7,     8,   166,    23,     5,   120,     6,     7,     8,   138,
-      10,    31,    37,    32,    33,    34,    36,     5,    38,    43,
-      40,     6,     7,     8,    36,    10,    37,    27,    20,    21,
-      30,    31,    32,    33,    34,    37,    19,    37,    38,    39,
-      40,    41,    27,    37,    13,    30,    31,    32,    33,    34,
-       3,     4,     5,    38,    39,    40,    41,     3,     4,     5,
-       3,     4,     5,    30,    31,    32,    33,    34,     3,    22,
-      23,     3,     4,     5,    14,    42,    22,    23,    31,    32,
-      23,    19,     5,    36,    27,    31,    32,    15,    31,    16,
-      36,    23,     3,    36,    19,    15,    17,    38,    37,    31,
-      19,    38,    -1,    87,    36,    30,    31,    32,    33,    34,
-      -1,    30,    31,    32,    33,    34,    30,    31,    32,    33,
-      34,   166,    -1,    37,    29,    30,    31,    32,    33,    34,
-      29,    30,    31,    32,    33,    34,    42
+      10,    46,    12,     3,     4,     5,     2,   131,    86,    38,
+      10,    10,    29,    30,    43,    11,    12,   141,    28,    29,
+      16,     5,    18,    23,    24,    21,     0,    23,    37,    28,
+     108,    37,    32,    33,    59,    31,    32,    37,    44,    35,
+      36,    37,    38,    39,    40,    41,    42,    29,    30,    33,
+     128,    37,     3,     4,     5,    12,    38,     5,    44,    10,
+     105,   139,   168,    59,    37,    90,   172,    39,   146,    65,
+      66,    96,    19,    24,     4,     5,    72,    73,    43,    75,
+      76,    32,    78,    38,    80,    81,    37,     4,     5,    40,
+      41,    30,    88,    37,    90,     4,     5,    93,    94,    10,
+      96,    44,     3,     4,     5,   150,    20,     6,     7,    10,
+       9,     5,   157,    38,   159,    13,    14,   162,    25,    26,
+      27,     5,   167,    24,    21,    22,   171,   123,   124,     6,
+       7,    32,     9,   143,    11,    38,    37,     5,    39,    44,
+      41,    33,    34,    35,     6,     7,    37,     9,    38,    11,
+      38,    28,    38,    20,    31,    32,    33,    34,    35,    14,
+       3,    38,    39,    40,    41,    42,    28,    15,    20,    31,
+      32,    33,    34,    35,     3,     4,     5,    39,    40,    41,
+      42,    10,     5,    16,     3,     4,     5,    17,    16,     3,
+      39,    10,    18,    38,   171,    24,    43,    39,    -1,     3,
+       4,     5,    -1,    32,    23,    24,    10,    88,    37,    -1,
+      39,    -1,    -1,    32,    33,     3,     4,     5,    37,    -1,
+      24,    -1,    10,    -1,    28,    -1,    20,     8,    32,    -1,
+      -1,    -1,     8,    37,    -1,    -1,    24,    31,    32,    33,
+      34,    35,    -1,    -1,    32,    -1,    -1,    -1,    -1,    37,
+      31,    32,    33,    34,    35,    31,    32,    33,    34,    35,
+      20,    -1,    -1,    -1,    31,    32,    33,    34,    35,    -1,
+      -1,    31,    32,    33,    34,    35,    43,    31,    32,    33,
+      34,    35,    -1,    -1,    38,    30,    31,    32,    33,    34,
+      35,    30,    31,    32,    33,    34,    35,    31,    32,    33,
+      34,    35
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    24,    25,    26,    45,     3,     4,     5,    23,    27,
-      31,    36,    46,    48,    49,    36,    49,    11,    51,     0,
-      36,    43,    36,    46,    49,    46,    49,    28,    29,     6,
-       7,     8,    10,    27,    30,    31,    32,    33,    34,    38,
-      39,    40,    41,    49,     5,    22,    32,    49,    52,    53,
-      47,    49,     5,    49,    37,    37,    46,    46,    36,    49,
-      49,     9,    27,     6,     7,     8,    49,    49,    49,    49,
-      49,    39,    40,    49,    38,    40,    49,    38,    49,    38,
-      36,    43,     4,     5,    48,    19,    18,    42,    37,    42,
-      19,    47,    29,     9,    36,    49,    49,    49,    49,    49,
-      49,    49,    49,    22,    32,    32,    19,     4,     5,    59,
-       4,    59,    60,    52,    47,     5,    50,    37,    49,    47,
-      29,    48,    37,    59,    43,     5,    12,    13,    55,    36,
-      37,    37,    49,    37,    19,    59,    13,    60,    14,    54,
-       3,    19,    59,     5,    60,    15,    46,    16,    56,    37,
-      42,    59,    15,    48,    17,     3,    48,    38,    48,    57,
-      58,    37,    38,    48,    20,    21,    42,    48,    55,    57,
-      55
+       0,    25,    26,    27,    46,     3,     4,     5,    10,    24,
+      28,    32,    37,    47,    49,    50,    37,    50,    12,    52,
+       0,    37,    44,    37,    47,    50,    47,    50,    29,    30,
+       6,     7,     9,    11,    28,    31,    32,    33,    34,    35,
+      39,    40,    41,    42,    50,     5,    23,    33,    50,    53,
+      54,    48,    50,     5,    50,    38,    38,    47,    47,    37,
+      50,    50,    10,    28,     6,     7,     9,    50,    50,    50,
+      50,    50,    40,    41,    50,    39,    41,    50,    39,    50,
+      39,    37,    44,     4,     5,    49,    20,    19,    43,    38,
+      43,    20,    48,     8,    30,    10,    37,    50,    50,    50,
+      50,    50,    50,    50,    50,    23,    33,    33,    20,     4,
+       5,    60,     4,    60,    61,    53,    48,     5,    51,    38,
+      50,    50,    48,     8,    30,    49,    38,    60,    44,     5,
+      13,    14,    56,    37,    38,    38,    50,    50,    38,    20,
+      60,    14,    61,    15,    55,     3,    20,    60,     5,    61,
+      16,    47,    17,    57,    38,    43,    60,    16,    49,    18,
+       3,    49,    39,    49,    58,    59,    38,    39,    49,    21,
+      22,    43,    49,    56,    58,    56
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1256,92 +1276,92 @@ yydestruct (yymsg, yytype, yyvaluep, context)
       case 3: /* "SWQT_NUMBER" */
 
 /* Line 1000 of yacc.c  */
-#line 88 "swq_parser.y"
+#line 89 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1264 "swq_parser.cpp"
+#line 1277 "swq_parser.cpp"
 	break;
       case 4: /* "SWQT_STRING" */
 
 /* Line 1000 of yacc.c  */
-#line 88 "swq_parser.y"
+#line 89 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1273 "swq_parser.cpp"
+#line 1286 "swq_parser.cpp"
 	break;
       case 5: /* "SWQT_IDENTIFIER" */
 
 /* Line 1000 of yacc.c  */
-#line 88 "swq_parser.y"
+#line 89 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1282 "swq_parser.cpp"
+#line 1295 "swq_parser.cpp"
 	break;
-      case 46: /* "logical_expr" */
+      case 47: /* "logical_expr" */
 
 /* Line 1000 of yacc.c  */
-#line 89 "swq_parser.y"
+#line 90 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1291 "swq_parser.cpp"
+#line 1304 "swq_parser.cpp"
 	break;
-      case 47: /* "value_expr_list" */
+      case 48: /* "value_expr_list" */
 
 /* Line 1000 of yacc.c  */
-#line 89 "swq_parser.y"
+#line 90 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1300 "swq_parser.cpp"
+#line 1313 "swq_parser.cpp"
 	break;
-      case 48: /* "field_value" */
+      case 49: /* "field_value" */
 
 /* Line 1000 of yacc.c  */
-#line 89 "swq_parser.y"
+#line 90 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1309 "swq_parser.cpp"
+#line 1322 "swq_parser.cpp"
 	break;
-      case 49: /* "value_expr" */
+      case 50: /* "value_expr" */
 
 /* Line 1000 of yacc.c  */
-#line 89 "swq_parser.y"
+#line 90 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1318 "swq_parser.cpp"
+#line 1331 "swq_parser.cpp"
 	break;
-      case 50: /* "type_def" */
+      case 51: /* "type_def" */
 
 /* Line 1000 of yacc.c  */
-#line 89 "swq_parser.y"
+#line 90 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1327 "swq_parser.cpp"
+#line 1340 "swq_parser.cpp"
 	break;
-      case 59: /* "string_or_identifier" */
+      case 60: /* "string_or_identifier" */
 
 /* Line 1000 of yacc.c  */
-#line 89 "swq_parser.y"
+#line 90 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1336 "swq_parser.cpp"
+#line 1349 "swq_parser.cpp"
 	break;
-      case 60: /* "table_def" */
+      case 61: /* "table_def" */
 
 /* Line 1000 of yacc.c  */
-#line 89 "swq_parser.y"
+#line 90 "swq_parser.y"
 	{ delete (*yyvaluep); };
 
 /* Line 1000 of yacc.c  */
-#line 1345 "swq_parser.cpp"
+#line 1358 "swq_parser.cpp"
 	break;
 
       default:
@@ -1645,7 +1665,7 @@ yyreduce:
         case 2:
 
 /* Line 1455 of yacc.c  */
-#line 95 "swq_parser.y"
+#line 96 "swq_parser.y"
     {
 			context->poRoot = (yyvsp[(2) - (2)]);
 		;}
@@ -1654,7 +1674,7 @@ yyreduce:
   case 3:
 
 /* Line 1455 of yacc.c  */
-#line 100 "swq_parser.y"
+#line 101 "swq_parser.y"
     {
 			context->poRoot = (yyvsp[(2) - (2)]);
 		;}
@@ -1663,7 +1683,7 @@ yyreduce:
   case 4:
 
 /* Line 1455 of yacc.c  */
-#line 105 "swq_parser.y"
+#line 106 "swq_parser.y"
     {
 			context->poRoot = (yyvsp[(2) - (2)]);
 		;}
@@ -1672,7 +1692,7 @@ yyreduce:
   case 5:
 
 /* Line 1455 of yacc.c  */
-#line 111 "swq_parser.y"
+#line 112 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_AND );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1684,7 +1704,7 @@ yyreduce:
   case 6:
 
 /* Line 1455 of yacc.c  */
-#line 119 "swq_parser.y"
+#line 120 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_OR );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1696,7 +1716,7 @@ yyreduce:
   case 7:
 
 /* Line 1455 of yacc.c  */
-#line 127 "swq_parser.y"
+#line 128 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_NOT );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1707,7 +1727,7 @@ yyreduce:
   case 8:
 
 /* Line 1455 of yacc.c  */
-#line 134 "swq_parser.y"
+#line 135 "swq_parser.y"
     {
 			(yyval) = (yyvsp[(2) - (3)]);
 		     ;}
@@ -1716,7 +1736,7 @@ yyreduce:
   case 9:
 
 /* Line 1455 of yacc.c  */
-#line 139 "swq_parser.y"
+#line 140 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_EQ );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1728,7 +1748,7 @@ yyreduce:
   case 10:
 
 /* Line 1455 of yacc.c  */
-#line 147 "swq_parser.y"
+#line 148 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_NE );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1740,7 +1760,7 @@ yyreduce:
   case 11:
 
 /* Line 1455 of yacc.c  */
-#line 155 "swq_parser.y"
+#line 156 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_NE );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1752,7 +1772,7 @@ yyreduce:
   case 12:
 
 /* Line 1455 of yacc.c  */
-#line 163 "swq_parser.y"
+#line 164 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_LT );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1764,7 +1784,7 @@ yyreduce:
   case 13:
 
 /* Line 1455 of yacc.c  */
-#line 171 "swq_parser.y"
+#line 172 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_GT );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1776,7 +1796,7 @@ yyreduce:
   case 14:
 
 /* Line 1455 of yacc.c  */
-#line 179 "swq_parser.y"
+#line 180 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_LE );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1788,7 +1808,7 @@ yyreduce:
   case 15:
 
 /* Line 1455 of yacc.c  */
-#line 187 "swq_parser.y"
+#line 188 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_LE );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1800,7 +1820,7 @@ yyreduce:
   case 16:
 
 /* Line 1455 of yacc.c  */
-#line 195 "swq_parser.y"
+#line 196 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_LE );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1812,7 +1832,7 @@ yyreduce:
   case 17:
 
 /* Line 1455 of yacc.c  */
-#line 203 "swq_parser.y"
+#line 204 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_GE );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1824,7 +1844,7 @@ yyreduce:
   case 18:
 
 /* Line 1455 of yacc.c  */
-#line 211 "swq_parser.y"
+#line 212 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_LIKE );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1836,7 +1856,7 @@ yyreduce:
   case 19:
 
 /* Line 1455 of yacc.c  */
-#line 219 "swq_parser.y"
+#line 220 "swq_parser.y"
     {
 		        swq_expr_node *like;
 			like = new swq_expr_node( SWQ_LIKE );
@@ -1853,7 +1873,38 @@ yyreduce:
   case 20:
 
 /* Line 1455 of yacc.c  */
-#line 232 "swq_parser.y"
+#line 233 "swq_parser.y"
+    {
+            (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)]) );
+       ;}
+    break;
+
+  case 21:
+
+/* Line 1455 of yacc.c  */
+#line 242 "swq_parser.y"
+    {
+                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)]) );
+
+            (yyval) = new swq_expr_node( SWQ_NOT );
+            (yyval)->field_type = SWQ_BOOLEAN;
+            (yyval)->PushSubExpression( like );
+      ;}
+    break;
+
+  case 22:
+
+/* Line 1455 of yacc.c  */
+#line 256 "swq_parser.y"
     {
 			(yyval) = (yyvsp[(4) - (5)]);
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1863,10 +1914,10 @@ yyreduce:
 		     ;}
     break;
 
-  case 21:
+  case 23:
 
 /* Line 1455 of yacc.c  */
-#line 241 "swq_parser.y"
+#line 265 "swq_parser.y"
     {
 		        swq_expr_node *in;
 
@@ -1882,10 +1933,10 @@ yyreduce:
 		     ;}
     break;
 
-  case 22:
+  case 24:
 
 /* Line 1455 of yacc.c  */
-#line 256 "swq_parser.y"
+#line 280 "swq_parser.y"
     {
             (yyval) = new swq_expr_node( SWQ_BETWEEN );
             (yyval)->field_type = SWQ_BOOLEAN;
@@ -1895,10 +1946,10 @@ yyreduce:
              ;}
     break;
 
-  case 23:
+  case 25:
 
 /* Line 1455 of yacc.c  */
-#line 265 "swq_parser.y"
+#line 289 "swq_parser.y"
     {
             swq_expr_node *between;
             between = new swq_expr_node( SWQ_BETWEEN );
@@ -1913,10 +1964,10 @@ yyreduce:
              ;}
     break;
 
-  case 24:
+  case 26:
 
 /* Line 1455 of yacc.c  */
-#line 279 "swq_parser.y"
+#line 303 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_ISNULL );
 			(yyval)->field_type = SWQ_BOOLEAN;
@@ -1924,10 +1975,10 @@ yyreduce:
 		     ;}
     break;
 
-  case 25:
+  case 27:
 
 /* Line 1455 of yacc.c  */
-#line 286 "swq_parser.y"
+#line 310 "swq_parser.y"
     {
 		        swq_expr_node *isnull;
 
@@ -1941,45 +1992,45 @@ yyreduce:
 		     ;}
     break;
 
-  case 26:
+  case 28:
 
 /* Line 1455 of yacc.c  */
-#line 300 "swq_parser.y"
+#line 324 "swq_parser.y"
     {
 			(yyval) = (yyvsp[(3) - (3)]);
 			(yyvsp[(3) - (3)])->PushSubExpression( (yyvsp[(1) - (3)]) );
 		;}
     break;
 
-  case 27:
+  case 29:
 
 /* Line 1455 of yacc.c  */
-#line 306 "swq_parser.y"
+#line 330 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_UNKNOWN ); /* list */
 			(yyval)->PushSubExpression( (yyvsp[(1) - (1)]) );
 		;}
     break;
 
-  case 28:
+  case 30:
 
 /* Line 1455 of yacc.c  */
-#line 313 "swq_parser.y"
+#line 337 "swq_parser.y"
     {
 		        (yyval) = (yyvsp[(1) - (1)]);  // validation deferred.
 			(yyval)->eNodeType = SNT_COLUMN;
-			(yyval)->field_index = -1; 
+			(yyval)->field_index = (yyval)->table_index = -1;
 		;}
     break;
 
-  case 29:
+  case 31:
 
 /* Line 1455 of yacc.c  */
-#line 320 "swq_parser.y"
+#line 344 "swq_parser.y"
     {
 		        (yyval) = (yyvsp[(1) - (3)]);  // validation deferred.
 			(yyval)->eNodeType = SNT_COLUMN;
-			(yyval)->field_index = -1; 
+			(yyval)->field_index = (yyval)->table_index = -1;
 			(yyval)->string_value = (char *) 
                             CPLRealloc( (yyval)->string_value, 
                                         strlen((yyval)->string_value) 
@@ -1991,46 +2042,55 @@ yyreduce:
 		;}
     break;
 
-  case 30:
+  case 32:
 
 /* Line 1455 of yacc.c  */
-#line 336 "swq_parser.y"
+#line 360 "swq_parser.y"
     {
 			(yyval) = (yyvsp[(1) - (1)]);
 		;}
     break;
 
-  case 31:
+  case 33:
 
 /* Line 1455 of yacc.c  */
-#line 341 "swq_parser.y"
+#line 365 "swq_parser.y"
     {
 			(yyval) = (yyvsp[(1) - (1)]);
 		;}
     break;
 
-  case 32:
+  case 34:
 
 /* Line 1455 of yacc.c  */
-#line 345 "swq_parser.y"
+#line 369 "swq_parser.y"
     {
 			(yyval) = (yyvsp[(1) - (1)]);
 		;}
     break;
 
-  case 33:
+  case 35:
 
 /* Line 1455 of yacc.c  */
-#line 350 "swq_parser.y"
+#line 374 "swq_parser.y"
     {
 			(yyval) = (yyvsp[(2) - (3)]);
 		;}
     break;
 
-  case 34:
+  case 36:
 
 /* Line 1455 of yacc.c  */
-#line 355 "swq_parser.y"
+#line 379 "swq_parser.y"
+    {
+            (yyval) = new swq_expr_node((const char*)NULL);
+        ;}
+    break;
+
+  case 37:
+
+/* Line 1455 of yacc.c  */
+#line 384 "swq_parser.y"
     {
             if ((yyvsp[(2) - (2)])->eNodeType == SNT_CONSTANT)
             {
@@ -2047,10 +2107,10 @@ yyreduce:
         ;}
     break;
 
-  case 35:
+  case 38:
 
 /* Line 1455 of yacc.c  */
-#line 371 "swq_parser.y"
+#line 400 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_ADD );
 			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
@@ -2058,10 +2118,10 @@ yyreduce:
 		;}
     break;
 
-  case 36:
+  case 39:
 
 /* Line 1455 of yacc.c  */
-#line 378 "swq_parser.y"
+#line 407 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_SUBTRACT );
 			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
@@ -2069,10 +2129,10 @@ yyreduce:
 		;}
     break;
 
-  case 37:
+  case 40:
 
 /* Line 1455 of yacc.c  */
-#line 385 "swq_parser.y"
+#line 414 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_MULTIPLY );
 			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
@@ -2080,10 +2140,10 @@ yyreduce:
 		;}
     break;
 
-  case 38:
+  case 41:
 
 /* Line 1455 of yacc.c  */
-#line 392 "swq_parser.y"
+#line 421 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_DIVIDE );
 			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
@@ -2091,10 +2151,10 @@ yyreduce:
 		;}
     break;
 
-  case 39:
+  case 42:
 
 /* Line 1455 of yacc.c  */
-#line 399 "swq_parser.y"
+#line 428 "swq_parser.y"
     {
 			(yyval) = new swq_expr_node( SWQ_MODULUS );
 			(yyval)->PushSubExpression( (yyvsp[(1) - (3)]) );
@@ -2102,10 +2162,10 @@ yyreduce:
 		;}
     break;
 
-  case 40:
+  case 43:
 
 /* Line 1455 of yacc.c  */
-#line 406 "swq_parser.y"
+#line 435 "swq_parser.y"
     {
 		    const swq_operation *poOp = 
                       swq_op_registrar::GetOperator( (yyvsp[(1) - (4)])->string_value );
@@ -2130,10 +2190,10 @@ yyreduce:
 		;}
     break;
 
-  case 41:
+  case 44:
 
 /* Line 1455 of yacc.c  */
-#line 430 "swq_parser.y"
+#line 459 "swq_parser.y"
     {
 		    (yyval) = (yyvsp[(5) - (6)]);
 		    (yyval)->PushSubExpression( (yyvsp[(3) - (6)]) );
@@ -2141,20 +2201,20 @@ yyreduce:
 		;}
     break;
 
-  case 42:
+  case 45:
 
 /* Line 1455 of yacc.c  */
-#line 438 "swq_parser.y"
+#line 467 "swq_parser.y"
     {
 	    (yyval) = new swq_expr_node( SWQ_CAST );
 	    (yyval)->PushSubExpression( (yyvsp[(1) - (1)]) );
 	;}
     break;
 
-  case 43:
+  case 46:
 
 /* Line 1455 of yacc.c  */
-#line 444 "swq_parser.y"
+#line 473 "swq_parser.y"
     {
 	    (yyval) = new swq_expr_node( SWQ_CAST );
 	    (yyval)->PushSubExpression( (yyvsp[(3) - (4)]) );
@@ -2162,10 +2222,10 @@ yyreduce:
 	;}
     break;
 
-  case 44:
+  case 47:
 
 /* Line 1455 of yacc.c  */
-#line 451 "swq_parser.y"
+#line 480 "swq_parser.y"
     {
 	    (yyval) = new swq_expr_node( SWQ_CAST );
 	    (yyval)->PushSubExpression( (yyvsp[(5) - (6)]) );
@@ -2174,19 +2234,19 @@ yyreduce:
 	;}
     break;
 
-  case 45:
+  case 48:
 
 /* Line 1455 of yacc.c  */
-#line 460 "swq_parser.y"
+#line 489 "swq_parser.y"
     {
 	    delete (yyvsp[(4) - (7)]);
 	;}
     break;
 
-  case 48:
+  case 51:
 
 /* Line 1455 of yacc.c  */
-#line 470 "swq_parser.y"
+#line 499 "swq_parser.y"
     {
 		if( !context->poSelect->PushField( (yyvsp[(2) - (2)]), NULL, TRUE ) )
         {
@@ -2196,10 +2256,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 49:
+  case 52:
 
 /* Line 1455 of yacc.c  */
-#line 479 "swq_parser.y"
+#line 508 "swq_parser.y"
     {
         if( !context->poSelect->PushField( (yyvsp[(2) - (2)]), NULL, TRUE ) )
         {
@@ -2209,10 +2269,10 @@ yyreduce:
         ;}
     break;
 
-  case 50:
+  case 53:
 
 /* Line 1455 of yacc.c  */
-#line 488 "swq_parser.y"
+#line 517 "swq_parser.y"
     {
 		if( !context->poSelect->PushField( (yyvsp[(1) - (1)]) ) )
         {
@@ -2222,10 +2282,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 51:
+  case 54:
 
 /* Line 1455 of yacc.c  */
-#line 497 "swq_parser.y"
+#line 526 "swq_parser.y"
     {
 		if( !context->poSelect->PushField( (yyvsp[(2) - (4)]), (yyvsp[(4) - (4)])->string_value, TRUE ))
         {
@@ -2238,10 +2298,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 52:
+  case 55:
 
 /* Line 1455 of yacc.c  */
-#line 509 "swq_parser.y"
+#line 538 "swq_parser.y"
     {
 		if( !context->poSelect->PushField( (yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])->string_value ) )
         {
@@ -2253,10 +2313,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 53:
+  case 56:
 
 /* Line 1455 of yacc.c  */
-#line 520 "swq_parser.y"
+#line 549 "swq_parser.y"
     {
 	        swq_expr_node *poNode = new swq_expr_node();
 		poNode->eNodeType = SNT_COLUMN;
@@ -2271,10 +2331,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 54:
+  case 57:
 
 /* Line 1455 of yacc.c  */
-#line 534 "swq_parser.y"
+#line 563 "swq_parser.y"
     {
                 CPLString osQualifiedField;
 
@@ -2297,10 +2357,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 55:
+  case 58:
 
 /* Line 1455 of yacc.c  */
-#line 556 "swq_parser.y"
+#line 585 "swq_parser.y"
     {
 	        // special case for COUNT(*), confirm it.
 		if( !EQUAL((yyvsp[(1) - (4)])->string_value,"COUNT") )
@@ -2331,10 +2391,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 56:
+  case 59:
 
 /* Line 1455 of yacc.c  */
-#line 586 "swq_parser.y"
+#line 615 "swq_parser.y"
     {
 	        // special case for COUNT(*), confirm it.
 		if( !EQUAL((yyvsp[(1) - (6)])->string_value,"COUNT") )
@@ -2369,10 +2429,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 57:
+  case 60:
 
 /* Line 1455 of yacc.c  */
-#line 620 "swq_parser.y"
+#line 649 "swq_parser.y"
     {
 	        // special case for COUNT(DISTINCT x), confirm it.
 		if( !EQUAL((yyvsp[(1) - (5)])->string_value,"COUNT") )
@@ -2397,10 +2457,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 58:
+  case 61:
 
 /* Line 1455 of yacc.c  */
-#line 644 "swq_parser.y"
+#line 673 "swq_parser.y"
     {
 	        // special case for COUNT(DISTINCT x), confirm it.
 		if( !EQUAL((yyvsp[(1) - (7)])->string_value,"COUNT") )
@@ -2429,19 +2489,19 @@ yyreduce:
 	    ;}
     break;
 
-  case 60:
+  case 63:
 
 /* Line 1455 of yacc.c  */
-#line 673 "swq_parser.y"
+#line 702 "swq_parser.y"
     {	     
 	    	 context->poSelect->where_expr = (yyvsp[(2) - (2)]);
 	    ;}
     break;
 
-  case 62:
+  case 65:
 
 /* Line 1455 of yacc.c  */
-#line 679 "swq_parser.y"
+#line 708 "swq_parser.y"
     {
 	        context->poSelect->PushJoin( (yyvsp[(2) - (7)])->int_value, 
 					     (yyvsp[(4) - (7)])->string_value, 
@@ -2452,10 +2512,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 63:
+  case 66:
 
 /* Line 1455 of yacc.c  */
-#line 688 "swq_parser.y"
+#line 717 "swq_parser.y"
     {
 	        context->poSelect->PushJoin( (yyvsp[(3) - (8)])->int_value, 
 					     (yyvsp[(5) - (8)])->string_value, 
@@ -2466,10 +2526,10 @@ yyreduce:
 	    ;}
     break;
 
-  case 68:
+  case 71:
 
 /* Line 1455 of yacc.c  */
-#line 706 "swq_parser.y"
+#line 735 "swq_parser.y"
     {
                 context->poSelect->PushOrderBy( (yyvsp[(1) - (1)])->string_value, TRUE );
                 delete (yyvsp[(1) - (1)]);
@@ -2477,10 +2537,10 @@ yyreduce:
             ;}
     break;
 
-  case 69:
+  case 72:
 
 /* Line 1455 of yacc.c  */
-#line 712 "swq_parser.y"
+#line 741 "swq_parser.y"
     {
                 context->poSelect->PushOrderBy( (yyvsp[(1) - (2)])->string_value, TRUE );
                 delete (yyvsp[(1) - (2)]);
@@ -2488,10 +2548,10 @@ yyreduce:
             ;}
     break;
 
-  case 70:
+  case 73:
 
 /* Line 1455 of yacc.c  */
-#line 718 "swq_parser.y"
+#line 747 "swq_parser.y"
     {
                 context->poSelect->PushOrderBy( (yyvsp[(1) - (2)])->string_value, FALSE );
                 delete (yyvsp[(1) - (2)]);
@@ -2499,28 +2559,28 @@ yyreduce:
             ;}
     break;
 
-  case 71:
+  case 74:
 
 /* Line 1455 of yacc.c  */
-#line 726 "swq_parser.y"
+#line 755 "swq_parser.y"
     {
             (yyval) = (yyvsp[(1) - (1)]);
         ;}
     break;
 
-  case 72:
+  case 75:
 
 /* Line 1455 of yacc.c  */
-#line 730 "swq_parser.y"
+#line 759 "swq_parser.y"
     {
             (yyval) = (yyvsp[(1) - (1)]);
         ;}
     break;
 
-  case 73:
+  case 76:
 
 /* Line 1455 of yacc.c  */
-#line 736 "swq_parser.y"
+#line 765 "swq_parser.y"
     {
 	    int iTable;
 	    iTable =context->poSelect->PushTableDef( NULL, (yyvsp[(1) - (1)])->string_value, 
@@ -2531,10 +2591,10 @@ yyreduce:
 	;}
     break;
 
-  case 74:
+  case 77:
 
 /* Line 1455 of yacc.c  */
-#line 746 "swq_parser.y"
+#line 775 "swq_parser.y"
     {
 	    int iTable;
 	    iTable = context->poSelect->PushTableDef( NULL, (yyvsp[(1) - (2)])->string_value, 
@@ -2546,10 +2606,10 @@ yyreduce:
 	;}
     break;
 
-  case 75:
+  case 78:
 
 /* Line 1455 of yacc.c  */
-#line 757 "swq_parser.y"
+#line 786 "swq_parser.y"
     {
 	    int iTable;
 	    iTable = context->poSelect->PushTableDef( (yyvsp[(1) - (3)])->string_value, 
@@ -2561,10 +2621,10 @@ yyreduce:
 	;}
     break;
 
-  case 76:
+  case 79:
 
 /* Line 1455 of yacc.c  */
-#line 768 "swq_parser.y"
+#line 797 "swq_parser.y"
     {
 	    int iTable;
 	    iTable = context->poSelect->PushTableDef( (yyvsp[(1) - (4)])->string_value, 
@@ -2581,7 +2641,7 @@ yyreduce:
 
 
 /* Line 1455 of yacc.c  */
-#line 2585 "swq_parser.cpp"
+#line 2638 "swq_parser.cpp"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
diff --git a/ogr/swq_parser.hpp b/ogr/swq_parser.hpp
index 46a20c2..3992f67 100644
--- a/ogr/swq_parser.hpp
+++ b/ogr/swq_parser.hpp
@@ -44,29 +44,30 @@
      SWQT_IDENTIFIER = 260,
      SWQT_IN = 261,
      SWQT_LIKE = 262,
-     SWQT_BETWEEN = 263,
-     SWQT_NULL = 264,
-     SWQT_IS = 265,
-     SWQT_SELECT = 266,
-     SWQT_LEFT = 267,
-     SWQT_JOIN = 268,
-     SWQT_WHERE = 269,
-     SWQT_ON = 270,
-     SWQT_ORDER = 271,
-     SWQT_BY = 272,
-     SWQT_FROM = 273,
-     SWQT_AS = 274,
-     SWQT_ASC = 275,
-     SWQT_DESC = 276,
-     SWQT_DISTINCT = 277,
-     SWQT_CAST = 278,
-     SWQT_LOGICAL_START = 279,
-     SWQT_VALUE_START = 280,
-     SWQT_SELECT_START = 281,
-     SWQT_NOT = 282,
-     SWQT_OR = 283,
-     SWQT_AND = 284,
-     SWQT_UMINUS = 285
+     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_LOGICAL_START = 280,
+     SWQT_VALUE_START = 281,
+     SWQT_SELECT_START = 282,
+     SWQT_NOT = 283,
+     SWQT_OR = 284,
+     SWQT_AND = 285,
+     SWQT_UMINUS = 286
    };
 #endif
 
diff --git a/ogr/swq_parser.y b/ogr/swq_parser.y
index 7d49c20..4535066 100644
--- a/ogr/swq_parser.y
+++ b/ogr/swq_parser.y
@@ -35,6 +35,13 @@
 
 #define YYSTYPE  swq_expr_node*
 
+/* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */ 
+/* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */ 
+/* increase YYINITDEPTH instead, but this will consume memory. */ 
+/* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */ 
+/* 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, 
@@ -54,6 +61,7 @@ static void swqerror( swq_parse_context *context, const char *msg )
 %token SWQT_IDENTIFIER
 %token SWQT_IN
 %token SWQT_LIKE
+%token SWQT_ESCAPE
 %token SWQT_BETWEEN
 %token SWQT_NULL
 %token SWQT_IS
@@ -228,6 +236,29 @@ logical_expr:
 			$$->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;
+            like = new swq_expr_node( SWQ_LIKE );
+            like->field_type = SWQ_BOOLEAN;
+            like->PushSubExpression( $1 );
+            like->PushSubExpression( $4 );
+            like->PushSubExpression( $6 );
+
+            $$ = new swq_expr_node( SWQ_NOT );
+            $$->field_type = SWQ_BOOLEAN;
+            $$->PushSubExpression( like );
+      }
+
 	| value_expr SWQT_IN '(' value_expr_list ')'
 	             {
 			$$ = $4;
@@ -313,14 +344,14 @@ field_value:
 		{
 		        $$ = $1;  // validation deferred.
 			$$->eNodeType = SNT_COLUMN;
-			$$->field_index = -1; 
+			$$->field_index = $$->table_index = -1;
 		}
 
 	| SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
 		{
 		        $$ = $1;  // validation deferred.
 			$$->eNodeType = SNT_COLUMN;
-			$$->field_index = -1; 
+			$$->field_index = $$->table_index = -1;
 			$$->string_value = (char *) 
                             CPLRealloc( $$->string_value, 
                                         strlen($$->string_value) 
@@ -351,6 +382,11 @@ value_expr:
 			$$ = $2;
 		}
 
+    | SWQT_NULL
+        {
+            $$ = new swq_expr_node((const char*)NULL);
+        }
+
     | '-' value_expr %prec SWQT_UMINUS
         {
             if ($2->eNodeType == SNT_CONSTANT)
diff --git a/port/GNUmakefile b/port/GNUmakefile
index bc0f120..b1ff249 100644
--- a/port/GNUmakefile
+++ b/port/GNUmakefile
@@ -16,15 +16,16 @@ endif
 
 CPPFLAGS	:= $(CPPFLAGS)	$(CURL_INC) $(XTRA_OPT)
 
-OBJ =	cpl_conv.o cpl_error.o cpl_string.o cplgetsymbol.o \
+OBJ =	cpl_conv.o cpl_error.o cpl_string.o cplgetsymbol.o cplstringlist.o \
 	cpl_strtod.o cpl_path.o cpl_csv.o cpl_findfile.o cpl_minixml.o \
 	cpl_multiproc.o cpl_list.o cpl_getexecpath.o cplstring.o \
 	cpl_vsil_win32.o cpl_vsisimple.o cpl_vsil.o cpl_vsi_mem.o \
 	cpl_vsil_unix_stdio_64.o cpl_http.o cpl_hash_set.o cplkeywordparser.o \
-	cpl_recode_stub.o cpl_quad_tree.o cpl_atomic_ops.o cpl_vsil_subfile.o cpl_time.o \
+	cpl_recode.o cpl_recode_iconv.o cpl_recode_stub.o cpl_quad_tree.o cpl_atomic_ops.o \
+	cpl_vsil_subfile.o cpl_time.o \
 	cpl_vsil_stdout.o cpl_vsil_sparsefile.o cpl_vsil_abstract_archive.o cpl_vsil_tar.o \
 	cpl_vsil_stdin.o cpl_vsil_buffered_reader.o cpl_base64.o \
-	cpl_vsil_curl.o
+	cpl_vsil_curl.o cpl_vsil_cache.o
 
 ifeq ($(ODBC_SETTING),yes)
 OBJ	:= 	$(OBJ) cpl_odbc.o
@@ -43,8 +44,10 @@ endif
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
+$(OBJ): cpl_vsi_virtual.h
+
 clean:
-	$(RM) *.o $(LIB)
+	$(RM) *.o $(O_OBJ)
 
 install:
 	for f in *.h ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; done
diff --git a/port/cpl_base64.cpp b/port/cpl_base64.cpp
index 47e36c9..de82465 100644
--- a/port/cpl_base64.cpp
+++ b/port/cpl_base64.cpp
@@ -1,14 +1,18 @@
 /******************************************************************************
- * $Id: cpl_base64.cpp 20794 2010-10-08 16:58:27Z warmerdam $
+ * $Id: cpl_base64.cpp 21954 2011-03-13 18:18:20Z warmerdam $
  *
- * Project:  MapServer
- * Purpose:  Decoding Base64 strings
+ * Project:  Common Portability Library
+ * Purpose:  Encoding/Decoding Base64 strings
  * Author:   Paul Ramsey <pramsey at cleverelephant.ca>
  *           Dave Blasby <dblasby at gmail.com>
+ *           René Nyffenegger
  *
  ******************************************************************************
  * Copyright (c) 2008 Paul Ramsey
  * Copyright (c) 2002 Refractions Research
+ * Copyright (C) 2004-2008 René Nyffenegger
+ *
+ * (see also part way down the file for license terms for René's code)
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,9 +33,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_base64.h"
 #include "cpl_string.h"
 
+CPL_CVSID("$Id: cpl_base64.cpp 21954 2011-03-13 18:18:20Z warmerdam $");
+
 /* Derived from MapServer's mappostgis.c */
 
 /*
@@ -71,10 +76,13 @@ static const unsigned char CPLBase64DecodeChar[256] = {
     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64
     };
 
-/*
-** Decode base64 string "pszBase64" (null terminated) in place
-** Returns length of decoded array or 0 on failure.
-*/
+/************************************************************************/
+/*                       CPLBase64DecodeInPlace()                       */
+/*                                                                      */
+/*      Decode base64 string "pszBase64" (null terminated) in place     */
+/*      Returns length of decoded array or 0 on failure.                */
+/************************************************************************/
+
 int CPLBase64DecodeInPlace(GByte* pszBase64)
 {
     if (pszBase64 && *pszBase64) {
@@ -132,3 +140,96 @@ int CPLBase64DecodeInPlace(GByte* pszBase64)
     }
     return 0;
 }
+
+/*
+ * This function was extracted from the base64 cpp utility published by
+ * René Nyffenegger. The code was modified into a form suitable for use in
+ * CPL.  The original code can be found at 
+ * http://www.adp-gmbh.ch/cpp/common/base64.html.
+ *
+ * The following is the original notice of this function.
+ *
+ * base64.cpp and base64.h
+ *
+ *  Copyright (C) 2004-2008 René Nyffenegger
+ *
+ *  This source code is provided 'as-is', without any express or implied
+ *  warranty. In no event will the author be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, subject to the following restrictions:
+ *
+ *  1. The origin of this source code must not be misrepresented; you must not
+ *     claim that you wrote the original source code. If you use this source code
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *
+ *  2. Altered source versions must be plainly marked as such, and must not be
+ *     misrepresented as being the original source code.
+ *
+ *  3. This notice may not be removed or altered from any source distribution.
+ *
+ *  René Nyffenegger rene.nyffenegger at adp-gmbh.ch
+*/
+
+/************************************************************************/
+/*                          CPLBase64Encode()                           */
+/************************************************************************/
+
+char *CPLBase64Encode( int nDataLen, const GByte *pabyBytesToEncode )
+
+{
+    static const std::string base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+    int           i = 0;
+    int           j = 0;
+    std::string   result("");
+    unsigned char charArray3[3];
+    unsigned char charArray4[4];
+
+    while( nDataLen-- )
+    {
+        charArray3[i++] = *(pabyBytesToEncode++);
+
+        if( i == 3 )
+        {
+            charArray4[0] = (charArray3[0] & 0xfc) >> 2;
+            charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
+            charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
+            charArray4[3] = charArray3[2] & 0x3f;
+
+            for( i = 0; i < 4; i++ )
+            {
+                result += base64Chars[charArray4[i]];
+            }
+
+            i = 0;
+        }
+    }
+
+    if( i )
+    {
+        for( j = i; j < 3; j++ )
+        {
+            charArray3[j] = '\0';
+        }
+
+        charArray4[0] = (charArray3[0]  & 0xfc) >> 2;
+        charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
+        charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
+        charArray4[3] = charArray3[2] & 0x3f;
+
+        for ( j = 0; j < (i + 1); j++ )
+        {
+            result += base64Chars[charArray4[j]];
+        }
+
+        while( i++ < 3 )
+            result += '=';
+    }
+
+    return (CPLStrdup(result.c_str()));
+}
+
diff --git a/port/cpl_config.h.in b/port/cpl_config.h.in
index bfa9685..34671d7 100644
--- a/port/cpl_config.h.in
+++ b/port/cpl_config.h.in
@@ -46,6 +46,9 @@
 /* Define to 1 if you have the `getcwd' function. */
 #undef HAVE_GETCWD
 
+/* Define if you have the iconv() function and it works. */
+#undef HAVE_ICONV
+
 /* Define as 0 or 1 according to the floating point format suported by the
    machine */
 #undef HAVE_IEEEFP
@@ -134,6 +137,12 @@
 /* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
 #undef HOST_FILLORDER
 
+/* Define as const if the declaration of iconv() needs const. */
+#undef ICONV_CONST
+
+/* For .cpp files, define as const if the declaration of iconv() needs const. */
+#undef ICONV_CPP_CONST
+
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #undef LT_OBJDIR
@@ -168,6 +177,9 @@
 /* Define to name of 64bit fopen function */
 #undef VSI_FOPEN64
 
+/* Define to name of 64bit ftruncate function */
+#undef VSI_FTRUNCATE64
+
 /* Define to name of 64bit fseek func */
 #undef VSI_FSEEK64
 
@@ -189,3 +201,8 @@
 /* Define to 1 if your processor stores words with the most significant byte
    first (like Motorola and SPARC, unlike Intel and VAX). */
 #undef WORDS_BIGENDIAN
+
+/* Use this file to override settings in instances where you're doing FAT compiles
+   on Apple.  It is currently off by default because it doesn't seem to work with 
+   newish ( XCode >= 3/28/11) XCodes */
+/* #include "cpl_config_extras.h" */
diff --git a/port/cpl_config_extras.h b/port/cpl_config_extras.h
index c5ddb71..654f2fc 100644
--- a/port/cpl_config_extras.h
+++ b/port/cpl_config_extras.h
@@ -1,4 +1,7 @@
 
+#ifndef INCLUDED_CPL_CONFIG_EXTRAS
+#define INCLUDED_CPL_CONFIG_EXTRAS
+
 #if defined(__APPLE__)
 
 #ifdef __BIG_ENDIAN__
@@ -26,7 +29,12 @@
   #undef WORDS_BIGENDIAN
 #endif
 
+#undef VSI_STAT64
+#undef VSI_STAT64_T
+
 #define VSI_STAT64 stat
 #define VSI_STAT64_T stat
 
-#endif
+#endif // APPLE
+
+#endif //INCLUDED_CPL_CONFIG_EXTRAS
diff --git a/port/cpl_conv.cpp b/port/cpl_conv.cpp
index 4175a83..3db2ee7 100644
--- a/port/cpl_conv.cpp
+++ b/port/cpl_conv.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_conv.cpp 21474 2011-01-13 00:09:06Z warmerdam $
+ * $Id: cpl_conv.cpp 23504 2011-12-09 20:43:50Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions.
@@ -34,7 +34,7 @@
 #include "cpl_vsi.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: cpl_conv.cpp 21474 2011-01-13 00:09:06Z warmerdam $");
+CPL_CVSID("$Id: cpl_conv.cpp 23504 2011-12-09 20:43:50Z rouault $");
 
 #if defined(WIN32CE)
 #  include "cpl_wince.h"
@@ -77,14 +77,8 @@ void *CPLCalloc( size_t nCount, size_t nSize )
     if( nSize * nCount == 0 )
         return NULL;
     
-    pReturn = VSICalloc( nCount, nSize );
-    if( pReturn == NULL )
-    {
-        CPLError( CE_Fatal, CPLE_OutOfMemory,
-                  "CPLCalloc(): Out of memory allocating %ld bytes.\n",
-                  (long) (nSize * nCount) );
-    }
-
+    pReturn = CPLMalloc( nCount * nSize );
+    memset( pReturn, 0, nCount * nSize );
     return pReturn;
 }
 
@@ -117,7 +111,7 @@ void *CPLMalloc( size_t nSize )
     if( nSize == 0 )
         return NULL;
 
-    if( nSize < 0 )
+    if( long(nSize) < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "CPLMalloc(%ld): Silly size requested.\n",
@@ -128,9 +122,19 @@ void *CPLMalloc( size_t nSize )
     pReturn = VSIMalloc( nSize );
     if( pReturn == NULL )
     {
-        CPLError( CE_Fatal, CPLE_OutOfMemory,
-                  "CPLMalloc(): Out of memory allocating %ld bytes.\n",
-                  (long) nSize );
+        if( nSize > 0 && nSize < 2000 )
+        {
+            char szSmallMsg[60];
+
+            sprintf( szSmallMsg, 
+                     "CPLMalloc(): Out of memory allocating %ld bytes.", 
+                     (long) nSize );
+            CPLEmergencyError( szSmallMsg ); 
+        }
+        else
+            CPLError( CE_Fatal, CPLE_OutOfMemory,
+                      "CPLMalloc(): Out of memory allocating %ld bytes.\n",
+                      (long) nSize );
     }
 
     return pReturn;
@@ -171,7 +175,7 @@ void * CPLRealloc( void * pData, size_t nNewSize )
         return NULL;
     }
 
-    if( nNewSize < 0 )
+    if( long(nNewSize) < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "CPLRealloc(%ld): Silly size requested.\n",
@@ -186,9 +190,19 @@ void * CPLRealloc( void * pData, size_t nNewSize )
     
     if( pReturn == NULL )
     {
-        CPLError( CE_Fatal, CPLE_OutOfMemory,
-                  "CPLRealloc(): Out of memory allocating %ld bytes.\n",
-                  (long)nNewSize );
+        if( nNewSize > 0 && nNewSize < 2000 )
+        {
+            char szSmallMsg[60];
+
+            sprintf( szSmallMsg, 
+                     "CPLRealloc(): Out of memory allocating %ld bytes.", 
+                     (long) nNewSize );
+            CPLEmergencyError( szSmallMsg ); 
+        }
+        else
+            CPLError( CE_Fatal, CPLE_OutOfMemory,
+                      "CPLRealloc(): Out of memory allocating %ld bytes.\n",
+                      (long) nNewSize );
     }
 
     return pReturn;
@@ -224,8 +238,7 @@ char *CPLStrdup( const char * pszString )
     if( pszString == NULL )
         pszString = "";
 
-    pszReturn = VSIStrdup( pszString );
-        
+    pszReturn = (char *) CPLMalloc(strlen(pszString)+1);
     if( pszReturn == NULL )
     {
         CPLError( CE_Fatal, CPLE_OutOfMemory,
@@ -233,7 +246,8 @@ char *CPLStrdup( const char * pszString )
                   (long) strlen(pszString) );
         
     }
-    
+
+    strcpy( pszReturn, pszString );
     return( pszReturn );
 }
 
@@ -394,6 +408,9 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 /*      Fetch readline buffer, and ensure it is the desired size,       */
 /*      reallocating if needed.  Manages TLS (thread local storage)     */
 /*      issues for the buffer.                                          */
+/*      We use a special trick to track the actual size of the buffer   */
+/*      The first 4 bytes are reserved to store it as a int, hence the  */
+/*      -4 / +4 hacks with the size and pointer.                        */
 /************************************************************************/
 static char *CPLReadLineBuffer( int nRequiredSize )
 
@@ -427,15 +444,26 @@ static char *CPLReadLineBuffer( int nRequiredSize )
 /* -------------------------------------------------------------------- */
 /*      If it is too small, grow it bigger.                             */
 /* -------------------------------------------------------------------- */
-    if( (int) *pnAlloc < nRequiredSize+1 )
+    if( ((int) *pnAlloc) -1 < nRequiredSize )
     {
         int nNewSize = nRequiredSize + 4 + 500;
+        if (nNewSize <= 0)
+        {
+            VSIFree( pnAlloc );
+            CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                      "CPLReadLineBuffer(): Trying to allocate more than 2 GB." );
+            return NULL;
+        }
 
         GUInt32* pnAllocNew = (GUInt32 *) VSIRealloc(pnAlloc,nNewSize);
         if( pnAllocNew == NULL )
         {
             VSIFree( pnAlloc );
             CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
+            CPLError( CE_Failure, CPLE_OutOfMemory,
+                      "CPLReadLineBuffer(): Out of memory allocating %ld bytes.",
+                      (long) nNewSize );
             return NULL;
         }
         pnAlloc = pnAllocNew;
@@ -591,7 +619,17 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Read a chunk from the input file.                               */
 /* -------------------------------------------------------------------- */
+        if ( nBufLength > INT_MAX - nChunkSize - 1 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Too big line : more than 2 billion characters!." );
+            CPLReadLineBuffer( -1 );
+            return NULL;
+        }
+
         pszRLBuffer = CPLReadLineBuffer( nBufLength + nChunkSize + 1 );
+        if( pszRLBuffer == NULL )
+            return NULL;
 
         if( nChunkBytesRead == nChunkBytesConsumed + 1 )
         {
@@ -1391,6 +1429,69 @@ void CPLVerifyConfiguration()
                   "CPLVerifyConfiguration(): byte order set wrong.\n" );
 }
 
+/* Uncomment to get list of options that have been fetched and set */
+//#define DEBUG_CONFIG_OPTIONS
+
+#ifdef DEBUG_CONFIG_OPTIONS
+
+#include <set>
+#include "cpl_multiproc.h"
+
+static void* hRegisterConfigurationOptionMutex = 0;
+static std::set<CPLString>* paoGetKeys = NULL;
+static std::set<CPLString>* paoSetKeys = NULL;
+
+/************************************************************************/
+/*                      CPLShowAccessedOptions()                        */
+/************************************************************************/
+
+static void CPLShowAccessedOptions()
+{
+    std::set<CPLString>::iterator aoIter;
+
+    printf("Configuration options accessed in reading : "),
+    aoIter = paoGetKeys->begin();
+    while(aoIter != paoGetKeys->end())
+    {
+        printf("%s, ", (*aoIter).c_str());
+        aoIter ++;
+    }
+    printf("\n");
+
+    printf("Configuration options accessed in writing : "),
+    aoIter = paoSetKeys->begin();
+    while(aoIter != paoSetKeys->end())
+    {
+        printf("%s, ", (*aoIter).c_str());
+        aoIter ++;
+    }
+    printf("\n");
+
+    delete paoGetKeys;
+    delete paoSetKeys;
+    paoGetKeys = paoSetKeys = NULL;
+}
+
+/************************************************************************/
+/*                       CPLAccessConfigOption()                        */
+/************************************************************************/
+
+static void CPLAccessConfigOption(const char* pszKey, int bGet)
+{
+    CPLMutexHolderD(&hRegisterConfigurationOptionMutex);
+    if (paoGetKeys == NULL)
+    {
+        paoGetKeys = new std::set<CPLString>;
+        paoSetKeys = new std::set<CPLString>;
+        atexit(CPLShowAccessedOptions);
+    }
+    if (bGet)
+        paoGetKeys->insert(pszKey);
+    else
+        paoSetKeys->insert(pszKey);
+}
+#endif
+
 /************************************************************************/
 /*                         CPLGetConfigOption()                         */
 /************************************************************************/
@@ -1412,6 +1513,10 @@ const char * CPL_STDCALL
 CPLGetConfigOption( const char *pszKey, const char *pszDefault )
 
 {
+#ifdef DEBUG_CONFIG_OPTIONS
+    CPLAccessConfigOption(pszKey, TRUE);
+#endif
+
     const char *pszResult = NULL;
 
     char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
@@ -1458,7 +1563,7 @@ CPLGetConfigOption( const char *pszKey, const char *pszDefault )
   * ogrinfo --config CPL_DEBUG ON ~/data/test/point.shp
   *
   * @param pszKey the key of the option
-  * @param pszValue the value of the option
+  * @param pszValue the value of the option, or NULL to clear a setting.
   * 
   * @see http://trac.osgeo.org/gdal/wiki/ConfigOptions
   */
@@ -1466,6 +1571,9 @@ void CPL_STDCALL
 CPLSetConfigOption( const char *pszKey, const char *pszValue )
 
 {
+#ifdef DEBUG_CONFIG_OPTIONS
+    CPLAccessConfigOption(pszKey, FALSE);
+#endif
     CPLMutexHolderD( &hConfigMutex );
 
     papszConfigOptions = (volatile char **) 
@@ -1487,13 +1595,17 @@ CPLSetConfigOption( const char *pszKey, const char *pszValue )
   * that applies on all threads.
   *
   * @param pszKey the key of the option
-  * @param pszValue the value of the option
+  * @param pszValue the value of the option, or NULL to clear a setting.
   */
 
 void CPL_STDCALL 
 CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
 
 {
+#ifdef DEBUG_CONFIG_OPTIONS
+    CPLAccessConfigOption(pszKey, FALSE);
+#endif
+
     char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
 
     papszTLConfigOptions = 
@@ -1509,17 +1621,21 @@ CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
 void CPL_STDCALL CPLFreeConfig()
 
 {
-    CPLMutexHolderD( &hConfigMutex );
-
-    CSLDestroy( (char **) papszConfigOptions);
-    papszConfigOptions = NULL;
-
-    char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
-    if( papszTLConfigOptions != NULL )
     {
-        CSLDestroy( papszTLConfigOptions );
-        CPLSetTLS( CTLS_CONFIGOPTIONS, NULL, FALSE );
+        CPLMutexHolderD( &hConfigMutex );
+
+        CSLDestroy( (char **) papszConfigOptions);
+        papszConfigOptions = NULL;
+        
+        char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
+        if( papszTLConfigOptions != NULL )
+        {
+            CSLDestroy( papszTLConfigOptions );
+            CPLSetTLS( CTLS_CONFIGOPTIONS, NULL, FALSE );
+        }
     }
+    CPLDestroyMutex( hConfigMutex );
+    hConfigMutex = NULL;
 }
 
 /************************************************************************/
@@ -1805,7 +1921,7 @@ void CPL_DLL CPLStringToComplex( const char *pszString,
     while( *pszString == ' ' )
         pszString++;
 
-    *pdfReal = atof(pszString);
+    *pdfReal = CPLAtof(pszString);
     *pdfImag = 0.0;
 
     for( i = 0; pszString[i] != '\0' && pszString[i] != ' ' && i < 100; i++ )
@@ -1820,7 +1936,7 @@ void CPL_DLL CPLStringToComplex( const char *pszString,
 
     if( iPlus > -1 && iImagEnd > -1 && iPlus < iImagEnd )
     {
-        *pdfImag = atof(pszString + iPlus);
+        *pdfImag = CPLAtof(pszString + iPlus);
     }
 
     return;
@@ -2171,7 +2287,7 @@ int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
 /* -------------------------------------------------------------------- */
     do { 
         nBytesRead = VSIFReadL( pabyBuffer, 1, nBufferSize, fpOld );
-        if( nBytesRead < 0 )
+        if( long(nBytesRead) < 0 )
             nRet = -1;
 
         if( nRet == 0
@@ -2223,7 +2339,10 @@ int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
 CPLLocaleC::CPLLocaleC() : pszOldLocale(CPLStrdup(setlocale(LC_NUMERIC,NULL)))
 
 {
-    if( setlocale(LC_NUMERIC,"C") == NULL )
+    if( CSLTestBoolean(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC","NO"))
+        || EQUAL(pszOldLocale,"C")
+        || EQUAL(pszOldLocale,"POSIX")
+        || setlocale(LC_NUMERIC,"C") == NULL )
     {
         CPLFree( pszOldLocale );
         pszOldLocale = NULL;
diff --git a/port/cpl_conv.h b/port/cpl_conv.h
index 0ab31da..d1eeec6 100644
--- a/port/cpl_conv.h
+++ b/port/cpl_conv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_conv.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl_conv.h 23431 2011-11-27 15:02:24Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions declarations.
@@ -50,7 +50,7 @@ CPL_C_START
 void CPL_DLL CPLVerifyConfiguration(void);
 
 const char CPL_DLL * CPL_STDCALL
-CPLGetConfigOption( const char *, const char * );
+CPLGetConfigOption( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL CPL_STDCALL CPLSetConfigOption( const char *, const char * );
 void CPL_DLL CPL_STDCALL CPLSetThreadLocalConfigOption( const char *pszKey, 
                                                         const char *pszValue );
@@ -60,10 +60,10 @@ void CPL_DLL CPL_STDCALL CPLFreeConfig(void);
 /*      Safe malloc() API.  Thin cover over VSI functions with fatal    */
 /*      error reporting if memory allocation fails.                     */
 /* -------------------------------------------------------------------- */
-void CPL_DLL *CPLMalloc( size_t );
-void CPL_DLL *CPLCalloc( size_t, size_t );
-void CPL_DLL *CPLRealloc( void *, size_t );
-char CPL_DLL *CPLStrdup( const char * );
+void CPL_DLL *CPLMalloc( size_t ) CPL_WARN_UNUSED_RESULT;
+void CPL_DLL *CPLCalloc( size_t, size_t ) CPL_WARN_UNUSED_RESULT;
+void CPL_DLL *CPLRealloc( void *, size_t ) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL *CPLStrdup( const char * ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL *CPLStrlwr( char *);
 
 #define CPLFree VSIFree
@@ -229,7 +229,7 @@ CPL_C_END
 
 #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
 
-class CPLLocaleC
+class CPL_DLL CPLLocaleC
 {
 public:
     CPLLocaleC();
diff --git a/port/cpl_error.cpp b/port/cpl_error.cpp
index e0874bf..fea28c8 100644
--- a/port/cpl_error.cpp
+++ b/port/cpl_error.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_error.cpp 19588 2010-04-30 19:56:38Z rouault $
+ * $Id: cpl_error.cpp 23348 2011-11-06 16:22:05Z rouault $
  *
  * Name:     cpl_error.cpp
  * Project:  CPL - Common Portability Library
@@ -40,9 +40,10 @@
  
 #define TIMESTAMP_DEBUG
 
-CPL_CVSID("$Id: cpl_error.cpp 19588 2010-04-30 19:56:38Z rouault $");
+CPL_CVSID("$Id: cpl_error.cpp 23348 2011-11-06 16:22:05Z rouault $");
 
 static void *hErrorMutex = NULL;
+static void *pErrorHandlerUserData = NULL; 
 static CPLErrorHandler pfnErrorHandler = CPLDefaultErrorHandler;
 
 #if !defined(HAVE_VSNPRINTF)
@@ -54,6 +55,7 @@ static CPLErrorHandler pfnErrorHandler = CPLDefaultErrorHandler;
 typedef struct errHandler
 {
     struct errHandler   *psNext;
+    void                *pUserData;
     CPLErrorHandler     pfnHandler;
 } CPLErrorHandlerNode;
 
@@ -88,6 +90,28 @@ static CPLErrorContext *CPLGetErrorContext()
     return psCtx;
 }
 
+/************************************************************************/
+/*                         CPLGetErrorHandlerUserData()                 */
+/************************************************************************/
+
+/**
+ * Fetch the user data for the error context
+ *
+ * Fetches the user data for the current error context.  You can 
+ * set the user data for the error context when you add your handler by 
+ * issuing CPLSetErrorHandlerEx() and CPLPushErrorHandlerEx().  Note that 
+ * user data is primarily intended for providing context within error handlers
+ * themselves, but they could potentially be abused in other useful ways with the usual 
+ * caveat emptor understanding.
+ *
+ * @return the user data pointer for the error context
+ */
+
+void* CPL_STDCALL CPLGetErrorHandlerUserData(void)
+{
+    CPLErrorContext *psCtx = CPLGetErrorContext();
+    return (void*) psCtx->psHandlerStack ? psCtx->psHandlerStack->pUserData : pErrorHandlerUserData;
+}
 
 /**********************************************************************
  *                          CPLError()
@@ -238,6 +262,54 @@ void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
 }
 
 /************************************************************************/
+/*                         CPLEmergencyError()                          */
+/************************************************************************/
+
+/**
+ * Fatal error when things are bad. 
+ *
+ * This function should be called in an emergency situation where
+ * it is unlikely that a regular error report would work.  This would 
+ * include in the case of heap exhaustion for even small allocations, 
+ * or any failure in the process of reporting an error (such as TLS 
+ * allocations). 
+ *
+ * This function should never return.  After the error message has been
+ * reported as best possible, the application will abort() similarly to how
+ * CPLError() aborts on CE_Fatal class errors.
+ *
+ * @param pszMessage the error message to report.
+ */
+
+void CPLEmergencyError( const char *pszMessage )
+{
+    CPLErrorContext *psCtx = NULL;
+    static int bInEmergencyError = FALSE;
+
+    if( !bInEmergencyError )
+    {
+        bInEmergencyError = TRUE;
+        psCtx = (CPLErrorContext *) CPLGetTLS( CTLS_ERRORCONTEXT );
+    }
+
+    if( psCtx != NULL && psCtx->psHandlerStack != NULL )
+    {
+        psCtx->psHandlerStack->pfnHandler( CE_Fatal, CPLE_AppDefined, 
+                                           pszMessage );
+    }
+    else if( pfnErrorHandler != NULL )
+    {
+        pfnErrorHandler( CE_Fatal, CPLE_AppDefined, pszMessage );
+    }
+    else
+    {
+        fprintf( stderr, "FATAL: %s\n", pszMessage );
+    }
+
+    abort();
+}
+
+/************************************************************************/
 /*                              CPLDebug()                              */
 /************************************************************************/
 
@@ -605,7 +677,54 @@ void CPLTurnFailureIntoWarning(int bOn )
 }
 
 /**********************************************************************
- *                          CPLSetErrorHandler()
+ *                          CPLSetErrorHandlerEx()                    *
+ **********************************************************************/
+
+/**
+ * Install custom error handle with user's data. This method is 
+ * essentially CPLSetErrorHandler with an added pointer to pUserData.  
+ * The pUserData is not returned in the CPLErrorHandler, however, and 
+ * must be fetched via CPLGetLastErrorUserData
+ *
+ * @param pfnErrorHandlerNew new error handler function.
+ * @param pUserData User data to carry along with the error context.
+ * @return returns the previously installed error handler.
+ */ 
+
+CPLErrorHandler CPL_STDCALL 
+CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, 
+                      void* pUserData )
+{
+    CPLErrorHandler     pfnOldHandler = pfnErrorHandler;
+    CPLErrorContext *psCtx = CPLGetErrorContext();
+
+    if( psCtx->psHandlerStack != NULL )
+    {
+        CPLDebug( "CPL", 
+                  "CPLSetErrorHandler() called with an error handler on\n"
+                  "the local stack.  New error handler will not be used immediately.\n" );
+    }
+
+
+    {
+        CPLMutexHolderD( &hErrorMutex );
+
+        pfnOldHandler = pfnErrorHandler;
+        
+        if( pfnErrorHandler == NULL )
+            pfnErrorHandler = CPLDefaultErrorHandler;
+        else
+            pfnErrorHandler = pfnErrorHandlerNew;
+            
+        pErrorHandlerUserData = pUserData;
+    }
+
+    return pfnOldHandler;
+}
+
+
+/**********************************************************************
+ *                          CPLSetErrorHandler()                      *
  **********************************************************************/
 
 /**
@@ -646,33 +765,10 @@ void CPLTurnFailureIntoWarning(int bOn )
  * @param pfnErrorHandlerNew new error handler function.
  * @return returns the previously installed error handler.
  */ 
-
 CPLErrorHandler CPL_STDCALL 
 CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
 {
-    CPLErrorHandler     pfnOldHandler = pfnErrorHandler;
-    CPLErrorContext *psCtx = CPLGetErrorContext();
-
-    if( psCtx->psHandlerStack != NULL )
-    {
-        CPLDebug( "CPL", 
-                  "CPLSetErrorHandler() called with an error handler on\n"
-                  "the local stack.  New error handler will not be used immediately.\n" );
-    }
-
-
-    {
-        CPLMutexHolderD( &hErrorMutex );
-
-        pfnOldHandler = pfnErrorHandler;
-        
-        if( pfnErrorHandler == NULL )
-            pfnErrorHandler = CPLDefaultErrorHandler;
-        else
-            pfnErrorHandler = pfnErrorHandlerNew;
-    }
-
-    return pfnOldHandler;
+    return CPLSetErrorHandlerEx(pfnErrorHandlerNew, NULL);
 }
 
 /************************************************************************/
@@ -683,7 +779,7 @@ CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
  * Push a new CPLError handler.
  *
  * This pushes a new error handler on the thread-local error handler
- * stack.  This handler will be used untill removed with CPLPopErrorHandler().
+ * stack.  This handler will be used until removed with CPLPopErrorHandler().
  *
  * The CPLSetErrorHandler() docs have further information on how 
  * CPLError handlers work.
@@ -694,13 +790,38 @@ CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
 void CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
 
 {
+    CPLPushErrorHandlerEx(pfnErrorHandlerNew, NULL);
+}
+
+
+/************************************************************************/
+/*                        CPLPushErrorHandlerEx()                       */
+/************************************************************************/
+
+/**
+ * Push a new CPLError handler with user data on the error context.
+ *
+ * This pushes a new error handler on the thread-local error handler
+ * stack.  This handler will be used until removed with CPLPopErrorHandler(). 
+ * Obtain the user data back by using CPLGetErrorContext().
+ *
+ * The CPLSetErrorHandler() docs have further information on how 
+ * CPLError handlers work.
+ *
+ * @param pfnErrorHandlerNew new error handler function.
+ * @param pUserData User data to put on the error context. 
+ */
+void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, 
+                                        void* pUserData )
+
+{
     CPLErrorContext *psCtx = CPLGetErrorContext();
     CPLErrorHandlerNode         *psNode;
 
     psNode = (CPLErrorHandlerNode *) VSIMalloc(sizeof(CPLErrorHandlerNode));
     psNode->psNext = psCtx->psHandlerStack;
     psNode->pfnHandler = pfnErrorHandlerNew;
-
+    psNode->pUserData = pUserData;
     psCtx->psHandlerStack = psNode;
 }
 
diff --git a/port/cpl_error.h b/port/cpl_error.h
index 35d8b77..d741ca8 100644
--- a/port/cpl_error.h
+++ b/port/cpl_error.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_error.h 19588 2010-04-30 19:56:38Z rouault $
+ * $Id: cpl_error.h 23286 2011-10-28 20:59:59Z hobu $
  *
  * Name:     cpl_error.h
  * Project:  CPL - Common Portability Library
@@ -56,10 +56,12 @@ typedef enum
 
 void CPL_DLL CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (3, 4);
 void CPL_DLL CPLErrorV(CPLErr, int, const char *, va_list );
+void CPL_DLL CPLEmergencyError( const char * );
 void CPL_DLL CPL_STDCALL CPLErrorReset( void );
 int CPL_DLL CPL_STDCALL CPLGetLastErrorNo( void );
 CPLErr CPL_DLL CPL_STDCALL CPLGetLastErrorType( void );
 const char CPL_DLL * CPL_STDCALL CPLGetLastErrorMsg( void );
+void* CPL_STDCALL CPLGetErrorHandlerUserData(void);
 
 typedef void (CPL_STDCALL *CPLErrorHandler)(CPLErr, int, const char*);
 
@@ -69,7 +71,9 @@ void CPL_DLL CPL_STDCALL CPLQuietErrorHandler( CPLErr, int, const char * );
 void CPLTurnFailureIntoWarning(int bOn );
 
 CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandler(CPLErrorHandler);
+CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandlerEx(CPLErrorHandler, void*);
 void CPL_DLL CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler );
+void CPL_DLL CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler, void* );
 void CPL_DLL CPL_STDCALL CPLPopErrorHandler(void);
 
 void CPL_DLL CPL_STDCALL CPLDebug( const char *, const char *, ... )  CPL_PRINT_FUNC_FORMAT (2, 3);
diff --git a/port/cpl_getexecpath.cpp b/port/cpl_getexecpath.cpp
index dde261c..e182b58 100644
--- a/port/cpl_getexecpath.cpp
+++ b/port/cpl_getexecpath.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_getexecpath.cpp 20703 2010-09-26 19:54:15Z warmerdam $
+ * $Id: cpl_getexecpath.cpp 21915 2011-03-08 21:58:16Z warmerdam $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLGetExecPath().
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_getexecpath.cpp 20703 2010-09-26 19:54:15Z warmerdam $");
+CPL_CVSID("$Id: cpl_getexecpath.cpp 21915 2011-03-08 21:58:16Z warmerdam $");
 
 #if defined(WIN32) || defined(WIN32CE)
 
@@ -125,7 +125,7 @@ int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
  *
  * The path to the executable currently running is returned.  This path
  * includes the name of the executable.   Currently this only works on 
- * win32 platform.  The returned path is UTF-8 encoded.
+ * win32 and linux platforms.  The returned path is UTF-8 encoded.
  *
  * @param pszPathBuf the buffer into which the path is placed.
  * @param nMaxLength the buffer size, MAX_PATH+1 is suggested.
diff --git a/port/cpl_http.cpp b/port/cpl_http.cpp
index a695069..6e16acc 100644
--- a/port/cpl_http.cpp
+++ b/port/cpl_http.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_http.cpp 21442 2011-01-09 12:23:19Z rouault $
+ * $Id: cpl_http.cpp 22588 2011-06-25 20:11:07Z rouault $
  *
  * Project:  libcurl based HTTP client
  * Purpose:  libcurl based HTTP client
@@ -42,7 +42,7 @@
 
 #endif
 
-CPL_CVSID("$Id: cpl_http.cpp 21442 2011-01-09 12:23:19Z rouault $");
+CPL_CVSID("$Id: cpl_http.cpp 22588 2011-06-25 20:11:07Z rouault $");
 
 // list of named persistent http sessions 
 
@@ -126,22 +126,24 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  * <li>TIMEOUT=val, where val is in seconds</li>
  * <li>HEADERS=val, where val is an extra header to use when getting a web page.
  *                  For example "Accept: application/x-ogcwkt"
- * <li>HTTPAUTH=[BASIC/NTLM/ANY] to specify an authentication scheme to use.
+ * <li>HTTPAUTH=[BASIC/NTLM/GSSNEGOTIATE/ANY] to specify an authentication scheme to use.
  * <li>USERPWD=userid:password to specify a user and password for authentication
  * <li>POSTFIELDS=val, where val is a nul-terminated string to be passed to the server
  *                     with a POST request.
  * <li>PROXY=val, to make requests go through a proxy server, where val is of the
  *                form proxy.server.com:port_number
- * <li>PROXYUSERPWD=val, where val is of the form username:password 
+ * <li>PROXYUSERPWD=val, where val is of the form username:password
+ * <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 and PROXYUSERPWD
- * values are searched in the configuration options named GDAL_HTTP_PROXY and GDAL_HTTP_PROXYUSERPWD,
- * as proxy configuration belongs to networking setup and makes more sense at the configuration
- * option level than at the connection level.
+ * Alternatively, if not defined in the papszOptions arguments, the PROXY and 
+ * PROXYUSERPWD values are searched in the configuration options named 
+ * GDAL_HTTP_PROXY and GDAL_HTTP_PROXYUSERPWD, 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
+ * @return a CPLHTTPResult* structure that must be freed by 
+ * CPLHTTPDestroyResult(), or NULL if libcurl support is disabled
  */
 CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
@@ -167,6 +169,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
     CURL *http_handle = NULL;
 
     const char *pszPersistent = CSLFetchNameValue( papszOptions, "PERSISTENT" );
+    const char *pszClosePersistent = CSLFetchNameValue( papszOptions, "CLOSE_PERSISTENT" );
     if (pszPersistent)
     {
         CPLString osSessionName = pszPersistent;
@@ -181,6 +184,30 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
         http_handle = oSessionMap[osSessionName];
     }
+/* -------------------------------------------------------------------- */
+/*      Are we requested to close a persistent named session?          */
+/* -------------------------------------------------------------------- */
+    else if (pszClosePersistent)
+    {
+        CPLString osSessionName = pszClosePersistent;
+        CPLMutexHolder oHolder( &hSessionMapMutex );
+
+        std::map<CPLString,CURL*>::iterator oIter = oSessionMap.find( osSessionName );
+        if( oIter != oSessionMap.end() )
+        {
+            curl_easy_cleanup(oIter->second);
+            oSessionMap.erase(oIter);
+            CPLDebug( "HTTP", "Ended persistent session named '%s'.",
+                      osSessionName.c_str() );
+        }
+        else
+        {
+            CPLDebug( "HTTP", "Could not find persistent session named '%s'.",
+                      osSessionName.c_str() );
+        }
+
+        return NULL;
+    }
     else
         http_handle = curl_easy_init();
 
@@ -191,12 +218,28 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
     CPLHTTPResult *psResult;
     struct curl_slist *headers=NULL; 
 
-    CPLDebug( "HTTP", "Fetch(%s)", pszURL );
+    const char* pszArobase = strchr(pszURL, '@');
+    const char* pszSlash = strchr(pszURL, '/');
+    const char* pszColon = (pszSlash) ? strchr(pszSlash, ':') : NULL;
+    if (pszArobase != NULL && pszColon != NULL && pszArobase - pszColon > 0)
+    {
+        /* http://user:password@www.example.com */
+        char* pszSanitizedURL = CPLStrdup(pszURL);
+        pszSanitizedURL[pszColon-pszURL] = 0;
+        CPLDebug( "HTTP", "Fetch(%s:#password#%s)", pszSanitizedURL, pszArobase );
+        CPLFree(pszSanitizedURL);
+    }
+    else
+    {
+        CPLDebug( "HTTP", "Fetch(%s)", pszURL );
+    }
 
     psResult = (CPLHTTPResult *) CPLCalloc(1,sizeof(CPLHTTPResult));
 
     curl_easy_setopt(http_handle, CURLOPT_URL, pszURL );
 
+    if (CSLTestBoolean(CPLGetConfigOption("CPL_CURL_VERBOSE", "NO")))
+        curl_easy_setopt(http_handle, CURLOPT_VERBOSE, 1);
 
     const char *pszHttpVersion = CSLFetchNameValue( papszOptions, "HTTP_VERSION");
     if( pszHttpVersion && strcmp(pszHttpVersion, "1.0") == 0 )
@@ -215,6 +258,10 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_NTLM );
     else if( EQUAL(pszHttpAuth,"ANY") )
         curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
+#ifdef CURLAUTH_GSSNEGOTIATE
+    else if( EQUAL(pszHttpAuth,"NEGOTIATE") )
+        curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE );
+#endif
     else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
@@ -252,12 +299,18 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
     /* Set POST mode */
     const char* pszPost = CSLFetchNameValue( papszOptions, "POSTFIELDS" );
-    if( pszPost != NULL && CSLTestBoolean(pszPost) )
+    if( pszPost != NULL )
     {
         curl_easy_setopt(http_handle, CURLOPT_POST, 1 );
         curl_easy_setopt(http_handle, CURLOPT_POSTFIELDS, pszPost );
     }
 
+    const char* pszCustomRequest = CSLFetchNameValue( papszOptions, "CUSTOMREQUEST" );
+    if( pszCustomRequest != NULL )
+    {
+        curl_easy_setopt(http_handle, CURLOPT_CUSTOMREQUEST, pszCustomRequest );
+    }
+
     /* Enable following redirections.  Requires libcurl 7.10.1 at least */
     curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1 );
     curl_easy_setopt(http_handle, CURLOPT_MAXREDIRS, 10 );
@@ -275,7 +328,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         headers = curl_slist_append(headers, pszHeaders);
         curl_easy_setopt(http_handle, CURLOPT_HTTPHEADER, headers);
     }
-                         
+
     /* NOSIGNAL should be set to true for timeout to work in multithread
      * environments on Unix, requires libcurl 7.10 or more recent.
      * (this force avoiding the use of sgnal handlers)
@@ -302,8 +355,12 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         bSupportGZip = strstr(curl_version(), "zlib/") != NULL;
         bHasCheckVersion = TRUE;
     }
-    if (bSupportGZip)
+    int bGZipRequested = FALSE;
+    if (bSupportGZip && CSLTestBoolean(CPLGetConfigOption("CPL_CURL_GZIP", "YES")))
+    {
+        bGZipRequested = TRUE;
         curl_easy_setopt(http_handle, CURLOPT_ENCODING, "gzip");
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Execute the request, waiting for results.                       */
@@ -326,9 +383,38 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /* -------------------------------------------------------------------- */
     if( strlen(szCurlErrBuf) > 0 )
     {
-        psResult->pszErrBuf = CPLStrdup(szCurlErrBuf);
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "%s", szCurlErrBuf );
+        int bSkipError = FALSE;
+
+        /* Some servers such as http://115.113.193.14/cgi-bin/world/qgis_mapserv.fcgi?VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities */
+        /* invalidly return Content-Length as the uncompressed size, with makes curl to wait for more data */
+        /* and time-out finally. If we got the expected data size, then we don't emit an error */
+        /* but turn off GZip requests */
+        if (bGZipRequested &&
+            strstr(szCurlErrBuf, "transfer closed with") &&
+            strstr(szCurlErrBuf, "bytes remaining to read"))
+        {
+            const char* pszContentLength =
+                CSLFetchNameValue(psResult->papszHeaders, "Content-Length");
+            if (pszContentLength && psResult->nDataLen != 0 &&
+                atoi(pszContentLength) == psResult->nDataLen)
+            {
+                const char* pszCurlGZIPOption = CPLGetConfigOption("CPL_CURL_GZIP", NULL);
+                if (pszCurlGZIPOption == NULL)
+                {
+                    CPLSetConfigOption("CPL_CURL_GZIP", "NO");
+                    CPLDebug("HTTP", "Disabling CPL_CURL_GZIP, because %s doesn't support it properly",
+                             pszURL);
+                }
+                psResult->nStatus = 0;
+                bSkipError = TRUE;
+            }
+        }
+        if (!bSkipError)
+        {
+            psResult->pszErrBuf = CPLStrdup(szCurlErrBuf);
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "%s", szCurlErrBuf );
+        }
     }
     else
     {
@@ -339,6 +425,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         if (response_code >= 400 && response_code < 600)
         {
             psResult->pszErrBuf = CPLStrdup(CPLSPrintf("HTTP error code : %d", (int)response_code));
+            CPLError( CE_Failure, CPLE_AppDefined, "%s", psResult->pszErrBuf );
         }
     }
 
diff --git a/port/cpl_minixml.cpp b/port/cpl_minixml.cpp
index 59e7abb..8a67fb7 100644
--- a/port/cpl_minixml.cpp
+++ b/port/cpl_minixml.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_minixml.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl_minixml.cpp 22178 2011-04-16 20:07:53Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of MiniXML Parser and handling.
@@ -44,7 +44,7 @@
 #include "cpl_string.h"
 #include <ctype.h>
 
-CPL_CVSID("$Id: cpl_minixml.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: cpl_minixml.cpp 22178 2011-04-16 20:07:53Z rouault $");
 
 typedef enum {
     TNone,
@@ -252,9 +252,11 @@ static XMLTokenType ReadToken( ParseContext *psContext )
                 do
                 {
                     chNext = ReadChar( psContext );
+                    if (chNext == ']')
+                        break;
                     AddToToken( psContext, chNext );
                 }
-                while( chNext != ']' && chNext != '\0'
+                while( chNext != '\0'
                     && !EQUALN(psContext->pszInput+psContext->nInputOffset,"]>", 2) );
                     
                 if (chNext == '\0')
@@ -266,11 +268,14 @@ static XMLTokenType ReadToken( ParseContext *psContext )
                     break;
                 }
 
-                chNext = ReadChar( psContext );
-                AddToToken( psContext, chNext );
+                if (chNext != ']')
+                {
+                    chNext = ReadChar( psContext );
+                    AddToToken( psContext, chNext );
 
-                // Skip ">" character, will be consumed below
-                chNext = ReadChar( psContext );
+                    // Skip ">" character, will be consumed below
+                    chNext = ReadChar( psContext );
+                }
             }
 
 
@@ -654,6 +659,20 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                 }
                 else
                 {
+                    if (strcmp(sContext.pszToken+1,
+                         sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue) != 0)
+                    {
+                        /* TODO: at some point we could just error out like any other */
+                        /* sane XML parser would do */
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                                "Line %d: <%.500s> matches <%.500s>, but the case isn't the same. "
+                                "Going on, but this is invalid XML that might be rejected in "
+                                "future versions.",
+                                sContext.nInputLine,
+                                sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue,
+                                sContext.pszToken );
+                    }
+
                     if( ReadToken(&sContext) != TClose )
                     {
                         CPLError( CE_Failure, CPLE_AppDefined, 
@@ -688,8 +707,17 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                 break;
             }
 
-            if( ReadToken(&sContext) != TString 
-                && sContext.eTokenType != TToken )
+            if( ReadToken(&sContext) == TToken )
+            {
+                /* TODO: at some point we could just error out like any other */
+                /* sane XML parser would do */
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "Line %d: Attribute value should be single or double quoted. "
+                          "Going on, but this is invalid XML that might be rejected in "
+                          "future versions.",
+                          sContext.nInputLine );
+            }
+            else if( sContext.eTokenType != TString )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, 
                           "Line %d: Didn't find expected attribute value.",
@@ -807,7 +835,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /* -------------------------------------------------------------------- */
 /*      Did we pop all the way out of our stack?                        */
 /* -------------------------------------------------------------------- */
-    if( CPLGetLastErrorType() == CE_None && sContext.nStackSize != 0 )
+    if( CPLGetLastErrorType() != CE_Failure && sContext.nStackSize != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Parse error at EOF, not all elements have been closed,\n"
@@ -822,7 +850,7 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
     if( sContext.papsStack != NULL )
         CPLFree( sContext.papsStack );
 
-    if( CPLGetLastErrorType() != CE_None )
+    if( CPLGetLastErrorType() == CE_Failure )
     {
         CPLDestroyXMLNode( sContext.psFirstNode );
         sContext.psFirstNode = NULL;
diff --git a/port/cpl_minizip_unzip.cpp b/port/cpl_minizip_unzip.cpp
index 541b89e..4e92234 100644
--- a/port/cpl_minizip_unzip.cpp
+++ b/port/cpl_minizip_unzip.cpp
@@ -1512,7 +1512,7 @@ extern int ZEXPORT cpl_unzReadCurrentFile  (unzFile file, voidp buf, unsigned le
         return UNZ_PARAMERROR;
 
 
-    if ((pfile_in_zip_read_info->read_buffer == NULL))
+    if (pfile_in_zip_read_info->read_buffer == NULL)
         return UNZ_END_OF_LIST_OF_FILE;
     if (len==0)
         return 0;
diff --git a/port/cpl_minizip_zip.cpp b/port/cpl_minizip_zip.cpp
index 37b3398..4296cf2 100644
--- a/port/cpl_minizip_zip.cpp
+++ b/port/cpl_minizip_zip.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_minizip_zip.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: cpl_minizip_zip.cpp 23425 2011-11-26 19:14:25Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -746,9 +746,9 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
     zi->ci.flag = 0;
     if ((level==8) || (level==9))
       zi->ci.flag |= 2;
-    if ((level==2))
+    if (level==2)
       zi->ci.flag |= 4;
-    if ((level==1))
+    if (level==1)
       zi->ci.flag |= 6;
     if (password != NULL)
       zi->ci.flag |= 1;
diff --git a/port/cpl_multiproc.cpp b/port/cpl_multiproc.cpp
index c3ff744..a819f5e 100644
--- a/port/cpl_multiproc.cpp
+++ b/port/cpl_multiproc.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_multiproc.cpp 21055 2010-11-03 11:36:59Z dron $
+ * $Id: cpl_multiproc.cpp 22648 2011-07-05 23:14:50Z warmerdam $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL Multi-Threading, and process handling portability functions.
@@ -40,7 +40,7 @@
 #  include <wce_time.h>
 #endif
 
-CPL_CVSID("$Id: cpl_multiproc.cpp 21055 2010-11-03 11:36:59Z dron $");
+CPL_CVSID("$Id: cpl_multiproc.cpp 22648 2011-07-05 23:14:50Z warmerdam $");
 
 #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
 #  define MUTEX_NONE
@@ -449,6 +449,9 @@ void CPLCleanupTLS()
   /* ==================================================================== */
   /************************************************************************/
 
+/* InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x403 */
+#define _WIN32_WINNT 0x0500
+
 #include <windows.h>
 
 /* windows.h header must be included above following lines. */
@@ -457,7 +460,6 @@ void CPLCleanupTLS()
 #  define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
 #endif
 
-
 /************************************************************************/
 /*                        CPLGetThreadingModel()                        */
 /************************************************************************/
@@ -475,11 +477,26 @@ const char *CPLGetThreadingModel()
 void *CPLCreateMutex()
 
 {
+#ifdef USE_WIN32_MUTEX
     HANDLE hMutex;
 
     hMutex = CreateMutex( NULL, TRUE, NULL );
 
     return (void *) hMutex;
+#else
+    CRITICAL_SECTION *pcs;
+
+	/* Do not use CPLMalloc() since its debugging infrastructure */
+	/* can call the CPL*Mutex functions... */
+    pcs = (CRITICAL_SECTION *)malloc(sizeof(*pcs));
+    if( pcs )
+    {
+      InitializeCriticalSectionAndSpinCount(pcs, 4000);
+      EnterCriticalSection(pcs);
+    }
+
+    return (void *) pcs;
+#endif
 }
 
 /************************************************************************/
@@ -489,12 +506,25 @@ void *CPLCreateMutex()
 int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
 
 {
+#ifdef USE_WIN32_MUTEX
     HANDLE hMutex = (HANDLE) hMutexIn;
     DWORD  hr;
 
     hr = WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
     
     return hr != WAIT_TIMEOUT;
+#else
+    CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
+    BOOL ret;
+
+    while( (ret = TryEnterCriticalSection(pcs)) == 0 && dfWaitInSeconds > 0.0 )
+    {
+        CPLSleep( MIN(dfWaitInSeconds,0.125) );
+        dfWaitInSeconds -= 0.125;
+    }
+    
+    return ret;
+#endif
 }
 
 /************************************************************************/
@@ -504,9 +534,15 @@ int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
 void CPLReleaseMutex( void *hMutexIn )
 
 {
+#ifdef USE_WIN32_MUTEX
     HANDLE hMutex = (HANDLE) hMutexIn;
 
     ReleaseMutex( hMutex );
+#else
+    CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
+
+    LeaveCriticalSection(pcs);
+#endif
 }
 
 /************************************************************************/
@@ -516,9 +552,16 @@ void CPLReleaseMutex( void *hMutexIn )
 void CPLDestroyMutex( void *hMutexIn )
 
 {
+#ifdef USE_WIN32_MUTEX
     HANDLE hMutex = (HANDLE) hMutexIn;
 
     CloseHandle( hMutex );
+#else
+    CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
+
+    DeleteCriticalSection( pcs );
+    free( pcs );
+#endif
 }
 
 /************************************************************************/
diff --git a/port/cpl_path.cpp b/port/cpl_path.cpp
index bfec5cc..c7ac45d 100644
--- a/port/cpl_path.cpp
+++ b/port/cpl_path.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_path.cpp 21584 2011-01-27 02:36:37Z warmerdam $
+ * $Id: cpl_path.cpp 21583 2011-01-27 02:35:12Z warmerdam $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Portable filename/path parsing, and forming ala "Glob API".
@@ -31,7 +31,7 @@
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: cpl_path.cpp 21584 2011-01-27 02:36:37Z warmerdam $");
+CPL_CVSID("$Id: cpl_path.cpp 21583 2011-01-27 02:35:12Z warmerdam $");
 
 
 /* should be size of larged possible filename */
diff --git a/port/cpl_port.h b/port/cpl_port.h
index dc714dd..9df4925 100644
--- a/port/cpl_port.h
+++ b/port/cpl_port.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_port.h 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: cpl_port.h 23431 2011-11-27 15:02:24Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -31,11 +31,6 @@
 #ifndef CPL_BASE_H_INCLUDED
 #define CPL_BASE_H_INCLUDED
 
-/* Remove annoying warnings Microsoft Visual C++ */
-#if defined(_MSC_VER)
-#  pragma warning(disable:4251 4275 4786 4127 4100)
-#endif
-
 /**
  * \file cpl_port.h
  *
@@ -102,6 +97,31 @@
 #endif
 
 /* ==================================================================== */
+/*      If iconv() is available use extended recoding module.           */
+/*      Stub implementation is always compiled in, because it works     */
+/*      faster than iconv() for encodings it supports.                  */
+/* ==================================================================== */
+
+#if defined(HAVE_ICONV)
+#  define CPL_RECODE_ICONV
+#endif
+
+#define CPL_RECODE_STUB
+
+/* ==================================================================== */
+/*      MinGW stuff                                                     */
+/* ==================================================================== */
+
+/* We need __MSVCRT_VERSION__ >= 0x0601 to have "struct __stat64" */
+/* Latest versions of mingw32 define it, but with older ones, */
+/* we need to define it manually */
+#if defined(__MINGW32__)
+#ifndef __MSVCRT_VERSION__
+#define __MSVCRT_VERSION__ 0x0601
+#endif
+#endif
+
+/* ==================================================================== */
 /*      Standard include files.                                         */
 /* ==================================================================== */
 
@@ -298,14 +318,19 @@ typedef unsigned long    GUIntBig;
 #  define CPLIsEqual(x,y) (fabs((x) - (y)) < 0.0000000000001)
 #endif
 
+/* -------------------------------------------------------------------- */
+/*      Provide macros for case insensitive string comparisons.         */
+/* -------------------------------------------------------------------- */
 #ifndef EQUAL
-#if defined(WIN32) || defined(WIN32CE)
-#  define EQUALN(a,b,n)           (strnicmp(a,b,n)==0)
-#  define EQUAL(a,b)              (stricmp(a,b)==0)
-#else
-#  define EQUALN(a,b,n)           (strncasecmp(a,b,n)==0)
-#  define EQUAL(a,b)              (strcasecmp(a,b)==0)
-#endif
+#  if defined(WIN32) || defined(WIN32CE)
+#    define STRCASECMP(a,b)         (stricmp(a,b))
+#    define STRNCASECMP(a,b,n)      (strnicmp(a,b,n))
+#  else
+#    define STRCASECMP(a,b)         (strcasecmp(a,b))
+#    define STRNCASECMP(a,b,n)      (strncasecmp(a,b,n))
+#  endif
+#  define EQUALN(a,b,n)           (STRNCASECMP(a,b,n)==0)
+#  define EQUAL(a,b)              (STRCASECMP(a,b)==0)
 #endif
 
 #ifdef macos_pre10
@@ -314,8 +339,8 @@ int strncasecmp(char * str1, char * str2, int len);
 char * strdup (char *instr);
 #endif
 
-#ifndef CPL_THREADLOCAL 
-#  define CPL_THREADLOCAL 
+#ifndef CPL_THREADLOCAL
+#  define CPL_THREADLOCAL
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -504,4 +529,11 @@ static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
 #define CPL_PRINT_FUNC_FORMAT( format_idx, arg_idx )
 #endif
 
+#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
+#define CPL_WARN_UNUSED_RESULT                        __attribute__((warn_unused_result))
+#else
+#define CPL_WARN_UNUSED_RESULT
+#endif
+
+
 #endif /* ndef CPL_BASE_H_INCLUDED */
diff --git a/port/cpl_recode.cpp b/port/cpl_recode.cpp
new file mode 100644
index 0000000..935ed1f
--- /dev/null
+++ b/port/cpl_recode.cpp
@@ -0,0 +1,324 @@
+/**********************************************************************
+ * $Id: cpl_recode.cpp 22600 2011-06-28 13:36:36Z warmerdam $
+ *
+ * Name:     cpl_recode.cpp
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Character set recoding and char/wchar_t conversions.
+ * Author:   Andrey Kiselev, dron at ak4719.spb.edu
+ *
+ **********************************************************************
+ * Copyright (c) 2011, Andrey Kiselev <dron at ak4719.spb.edu>
+ * Copyright (c) 2008, Frank Warmerdam
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **********************************************************************/
+
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: cpl_recode.cpp 22600 2011-06-28 13:36:36Z warmerdam $");
+
+#ifdef CPL_RECODE_ICONV
+extern char *CPLRecodeIconv( const char *, const char *, const char * );
+extern char *CPLRecodeFromWCharIconv( const wchar_t *,
+                                      const char *, const char * );
+extern wchar_t *CPLRecodeToWCharIconv( const char *,
+                                       const char *, const char * );
+#endif /* CPL_RECODE_ICONV */
+
+extern char *CPLRecodeStub( const char *, const char *, const char * );
+extern char *CPLRecodeFromWCharStub( const wchar_t *,
+                                     const char *, const char * );
+extern wchar_t *CPLRecodeToWCharStub( const char *,
+                                      const char *, const char * );
+extern int CPLIsUTF8Stub( const char *, int );
+
+/************************************************************************/
+/*                             CPLRecode()                              */
+/************************************************************************/
+
+/**
+ * Convert a string from a source encoding to a destination encoding.
+ *
+ * The only guaranteed supported encodings are CPL_ENC_UTF8, CPL_ENC_ASCII
+ * and CPL_ENC_ISO8859_1. Currently, the following conversions are supported :
+ * <ul>
+ *  <li>CPL_ENC_ASCII -> CPL_ENC_UTF8 or CPL_ENC_ISO8859_1 (no conversion in fact)</li>
+ *  <li>CPL_ENC_ISO8859_1 -> CPL_ENC_UTF8</li>
+ *  <li>CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1</li>
+ * </ul>
+ *
+ * If an error occurs an error may, or may not be posted with CPLError(). 
+ *
+ * @param pszSource a NULL terminated string.
+ * @param pszSrcEncoding the source encoding.
+ * @param pszDstEncoding the destination encoding.
+ *
+ * @return a NULL terminated string which should be freed with CPLFree().
+ *
+ * @since GDAL 1.6.0
+ */
+
+char CPL_DLL *CPLRecode( const char *pszSource,
+                         const char *pszSrcEncoding,
+                         const char *pszDstEncoding )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Handle a few common short cuts.                                 */
+/* -------------------------------------------------------------------- */
+    if ( EQUAL(pszSrcEncoding, pszDstEncoding) )
+        return CPLStrdup(pszSource);
+
+    if ( EQUAL(pszSrcEncoding, CPL_ENC_ASCII) 
+        && ( EQUAL(pszDstEncoding, CPL_ENC_UTF8) 
+             || EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
+        return CPLStrdup(pszSource);
+
+#ifdef CPL_RECODE_ICONV
+/* -------------------------------------------------------------------- */
+/*      CPL_ENC_ISO8859_1 -> CPL_ENC_UTF8                               */
+/*      and CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1 conversions are hadled    */
+/*      very well by the stub implementation which is faster than the   */
+/*      iconv() route. Use a stub for these two ones and iconv()        */
+/*      everything else.                                                */
+/* -------------------------------------------------------------------- */
+    if ( ( EQUAL(pszSrcEncoding, CPL_ENC_ISO8859_1)
+           && EQUAL(pszDstEncoding, CPL_ENC_UTF8) )
+         || ( EQUAL(pszSrcEncoding, CPL_ENC_UTF8)
+              && EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
+    {
+        return CPLRecodeStub( pszSource, pszSrcEncoding, pszDstEncoding );
+    }
+    else
+    {
+        return CPLRecodeIconv( pszSource, pszSrcEncoding, pszDstEncoding );
+    }
+#else /* CPL_RECODE_STUB */
+    return CPLRecodeStub( pszSource, pszSrcEncoding, pszDstEncoding );
+#endif /* CPL_RECODE_ICONV */
+}
+
+/************************************************************************/
+/*                         CPLRecodeFromWChar()                         */
+/************************************************************************/
+
+/**
+ * Convert wchar_t string to UTF-8. 
+ *
+ * Convert a wchar_t string into a multibyte utf-8 string.  The only
+ * guaranteed supported source encoding is CPL_ENC_UCS2, and the only
+ * guaranteed supported destination encodings are CPL_ENC_UTF8, CPL_ENC_ASCII
+ * and CPL_ENC_ISO8859_1.  In some cases (ie. using iconv()) other encodings 
+ * may also be supported.
+ *
+ * Note that the wchar_t type varies in size on different systems. On
+ * win32 it is normally 2 bytes, and on unix 4 bytes.
+ *
+ * If an error occurs an error may, or may not be posted with CPLError(). 
+ *
+ * @param pwszSource the source wchar_t string, terminated with a 0 wchar_t.
+ * @param pszSrcEncoding the source encoding, typically CPL_ENC_UCS2.
+ * @param pszDstEncoding the destination encoding, typically CPL_ENC_UTF8.
+ *
+ * @return a zero terminated multi-byte string which should be freed with 
+ * CPLFree(), or NULL if an error occurs. 
+ *
+ * @since GDAL 1.6.0
+ */
+
+char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
+                                  const char *pszSrcEncoding,
+                                  const char *pszDstEncoding )
+
+{
+#ifdef CPL_RECODE_ICONV
+/* -------------------------------------------------------------------- */
+/*      Conversions from CPL_ENC_UCS2                                   */
+/*      to CPL_ENC_UTF8, CPL_ENC_ISO8859_1 and CPL_ENC_ASCII are well   */
+/*      handled by the stub implementation.                             */
+/* -------------------------------------------------------------------- */
+    if ( (EQUAL(pszSrcEncoding, CPL_ENC_UCS2) || EQUAL(pszSrcEncoding, "WCHAR_T"))
+         && ( EQUAL(pszDstEncoding, CPL_ENC_UTF8)
+              || EQUAL(pszDstEncoding, CPL_ENC_ASCII)
+              || EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
+    {
+        return CPLRecodeFromWCharStub( pwszSource,
+                                       pszSrcEncoding, pszDstEncoding );
+    }
+    else
+    {
+        return CPLRecodeFromWCharIconv( pwszSource,
+                                        pszSrcEncoding, pszDstEncoding );
+    }
+#else /* CPL_RECODE_STUB */
+    return CPLRecodeFromWCharStub( pwszSource,
+                                   pszSrcEncoding, pszDstEncoding );
+#endif /* CPL_RECODE_ICONV */
+}
+
+/************************************************************************/
+/*                          CPLRecodeToWChar()                          */
+/************************************************************************/
+
+/**
+ * Convert UTF-8 string to a wchar_t string.
+ *
+ * Convert a 8bit, multi-byte per character input string into a wide
+ * character (wchar_t) string.  The only guaranteed supported source encodings
+ * are CPL_ENC_UTF8, CPL_ENC_ASCII and CPL_ENC_ISO8869_1 (LATIN1).  The only
+ * guaranteed supported destination encoding is CPL_ENC_UCS2.  Other source
+ * and destination encodings may be supported depending on the underlying
+ * implementation. 
+ *
+ * Note that the wchar_t type varies in size on different systems. On
+ * win32 it is normally 2 bytes, and on unix 4 bytes.
+ *
+ * If an error occurs an error may, or may not be posted with CPLError(). 
+ *
+ * @param pszSource input multi-byte character string.
+ * @param pszSrcEncoding source encoding, typically CPL_ENC_UTF8.
+ * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2. 
+ *
+ * @return the zero terminated wchar_t string (to be freed with CPLFree()) or
+ * NULL on error.
+ *
+ * @since GDAL 1.6.0
+ */
+
+wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
+                                   const char *pszSrcEncoding,
+                                   const char *pszDstEncoding )
+
+{
+#ifdef CPL_RECODE_ICONV
+/* -------------------------------------------------------------------- */
+/*      Conversions to CPL_ENC_UCS2                                     */
+/*      from CPL_ENC_UTF8, CPL_ENC_ISO8859_1 and CPL_ENC_ASCII are well */
+/*      handled by the stub implementation.                             */
+/* -------------------------------------------------------------------- */
+    if ( (EQUAL(pszDstEncoding, CPL_ENC_UCS2) || EQUAL(pszDstEncoding, "WCHAR_T"))
+         && ( EQUAL(pszSrcEncoding, CPL_ENC_UTF8)
+              || EQUAL(pszSrcEncoding, CPL_ENC_ASCII)
+              || EQUAL(pszSrcEncoding, CPL_ENC_ISO8859_1) ) )
+    {
+        return CPLRecodeToWCharStub( pszSource,
+                                     pszSrcEncoding, pszDstEncoding );
+    }
+    else
+    {
+        return CPLRecodeToWCharIconv( pszSource,
+                                      pszSrcEncoding, pszDstEncoding );
+    }
+#else /* CPL_RECODE_STUB */
+    return CPLRecodeToWCharStub( pszSource, pszSrcEncoding, pszDstEncoding );
+#endif /* CPL_RECODE_ICONV */
+}
+
+/************************************************************************/
+/*                                 CPLIsUTF8()                          */
+/************************************************************************/
+
+/**
+ * Test if a string is encoded as UTF-8.
+ *
+ * @param pabyData input string to test
+ * @param nLen length of the input string, or -1 if the function must compute
+ *             the string length. In which case it must be null terminated.
+ * @return TRUE if the string is encoded as UTF-8. FALSE otherwise
+ *
+ * @since GDAL 1.7.0
+ */
+int CPLIsUTF8(const char* pabyData, int nLen)
+{
+    return CPLIsUTF8Stub( pabyData, nLen );
+}
+
+/************************************************************************/
+/*                          CPLForceToASCII()                           */
+/************************************************************************/
+
+/**
+ * Return a new string that is made only of ASCII characters. If non-ASCII
+ * characters are found in the input string, they will be replaced by the
+ * provided replacement character.
+ *
+ * @param pabyData input string to test
+ * @param nLen length of the input string, or -1 if the function must compute
+ *             the string length. In which case it must be null terminated.
+ * @param chReplacementChar character which will be used when the input stream
+ *                          contains a non ASCII character. Must be valid ASCII !
+ *
+ * @return a new string that must be freed with CPLFree().
+ *
+ * @since GDAL 1.7.0
+ */
+char CPL_DLL *CPLForceToASCII(const char* pabyData, int nLen, char chReplacementChar)
+{
+    if (nLen < 0)
+        nLen = strlen(pabyData);
+    char* pszOutputString = (char*)CPLMalloc(nLen + 1);
+    int i;
+    for(i=0;i<nLen;i++)
+    {
+        if (((unsigned char*)pabyData)[i] > 127)
+            pszOutputString[i] = chReplacementChar;
+        else
+            pszOutputString[i] = pabyData[i];
+    }
+    pszOutputString[i] = '\0';
+    return pszOutputString;
+}
+
+/************************************************************************/
+/*                        CPLEncodingCharSize()                         */
+/************************************************************************/
+
+/**
+ * Return bytes per character for encoding.
+ *
+ * This function returns the size in bytes of the smallest character
+ * in this encoding.  For fixed width encodings (ASCII, UCS-2, UCS-4) this
+ * is straight forward.  For encodings like UTF8 and UTF16 which represent
+ * some characters as a sequence of atomic character sizes the function
+ * still returns the atomic character size (1 for UTF8, 2 for UTF16). 
+ *
+ * This function will return the correct value for well known encodings
+ * with corresponding CPL_ENC_ values.  It may not return the correct value
+ * for other encodings even if they are supported by the underlying iconv 
+ * or windows transliteration services.  Hopefully it will improve over time.
+ *
+ * @param pszEncoding the name of the encoding.
+ *
+ * @return the size of a minimal character in bytes or -1 if the size is 
+ * unknown. 
+ */
+
+int CPLEncodingCharSize( const char *pszEncoding )
+
+{
+    if( EQUAL(pszEncoding,CPL_ENC_UTF8) )
+        return 1;
+    else if( EQUAL(pszEncoding,CPL_ENC_UTF16) )
+        return 2;
+    else if( EQUAL(pszEncoding,CPL_ENC_UCS2) )
+        return 2;
+    else if( EQUAL(pszEncoding,CPL_ENC_UCS4) )
+        return 4;
+    else if( EQUAL(pszEncoding,CPL_ENC_ASCII) )
+        return 1;
+    else if( EQUALN(pszEncoding,"ISO-8859-",9) )
+        return 1;
+    else
+        return -1;
+}
+
diff --git a/port/cpl_recode_iconv.cpp b/port/cpl_recode_iconv.cpp
new file mode 100644
index 0000000..ec7118c
--- /dev/null
+++ b/port/cpl_recode_iconv.cpp
@@ -0,0 +1,323 @@
+/**********************************************************************
+ * $Id: cpl_recode_iconv.cpp 23653 2011-12-29 14:27:11Z rouault $
+ *
+ * Name:     cpl_recode_iconv.cpp
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Character set recoding and char/wchar_t conversions implemented
+ *           using the iconv() functionality.
+ * Author:   Andrey Kiselev, dron at ak4719.spb.edu
+ *
+ **********************************************************************
+ * Copyright (c) 2011, Andrey Kiselev <dron at ak4719.spb.edu>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **********************************************************************/
+
+#include "cpl_port.h"
+
+CPL_CVSID("$Id: cpl_recode_iconv.cpp 23653 2011-12-29 14:27:11Z rouault $");
+
+#ifdef CPL_RECODE_ICONV
+
+#include <iconv.h>
+#include "cpl_string.h"
+
+#ifndef ICONV_CPP_CONST
+#define ICONV_CPP_CONST ICONV_CONST
+#endif
+
+#define CPL_RECODE_DSTBUF_SIZE 32768
+
+/************************************************************************/
+/*                          CPLRecodeIconv()                            */
+/************************************************************************/
+
+/**
+ * Convert a string from a source encoding to a destination encoding
+ * using the iconv() function.
+ *
+ * If an error occurs an error may, or may not be posted with CPLError(). 
+ *
+ * @param pszSource a NULL terminated string.
+ * @param pszSrcEncoding the source encoding.
+ * @param pszDstEncoding the destination encoding.
+ *
+ * @return a NULL terminated string which should be freed with CPLFree().
+ */
+
+char *CPLRecodeIconv( const char *pszSource, 
+                      const char *pszSrcEncoding, 
+                      const char *pszDstEncoding )
+
+{
+    iconv_t sConv;
+
+    sConv = iconv_open( pszDstEncoding, pszSrcEncoding );
+
+    if ( sConv == (iconv_t)-1 )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined, 
+                  "Recode from %s to %s failed with the error: \"%s\".", 
+                  pszSrcEncoding, pszDstEncoding, strerror(errno) );
+
+        return CPLStrdup(pszSource);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      XXX: There is a portability issue: iconv() function could be    */
+/*      declared differently on different platforms. The second         */
+/*      argument could be declared as char** (as POSIX defines) or      */
+/*      as a const char**. Handle it with the ICONV_CPP_CONST macro here.   */
+/* -------------------------------------------------------------------- */
+    ICONV_CPP_CONST char *pszSrcBuf = (ICONV_CPP_CONST char *)pszSource;
+    size_t  nSrcLen = strlen( pszSource );
+    size_t  nDstCurLen = MAX(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
+    size_t  nDstLen = nDstCurLen;
+    char    *pszDestination = (char *)CPLCalloc( nDstCurLen, sizeof(char) );
+    char    *pszDstBuf = pszDestination;
+
+    while ( nSrcLen > 0 )
+    {
+        size_t  nConverted =
+            iconv( sConv, &pszSrcBuf, &nSrcLen, &pszDstBuf, &nDstLen );
+
+        if ( nConverted == (size_t)-1 )
+        {
+            if ( errno == EILSEQ )
+            {
+                // Skip the invalid sequence in the input string.
+                static int bHasWarned = FALSE;
+                if (!bHasWarned)
+                {
+                    bHasWarned = TRUE;
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "One or several characters couldn't be converted correctly from %s to %s.\n"
+                            "This warning will not be emitted anymore",
+                             pszSrcEncoding, pszDstEncoding);
+                }
+                nSrcLen--, pszSrcBuf++;
+                continue;
+            }
+
+            else if ( errno == E2BIG )
+            {
+                // We are running out of the output buffer.
+                // Dynamically increase the buffer size.
+                size_t nTmp = nDstCurLen;
+                nDstCurLen *= 2;
+                pszDestination =
+                    (char *)CPLRealloc( pszDestination, nDstCurLen );
+                pszDstBuf = pszDestination + nTmp - nDstLen;
+                nDstLen += nDstCurLen - nTmp;
+                continue;
+            }
+
+            else
+                break;
+        }
+    }
+
+    pszDestination[nDstCurLen - nDstLen] = '\0';
+
+    iconv_close( sConv );
+
+    return pszDestination;
+}
+
+/************************************************************************/
+/*                      CPLRecodeFromWCharIconv()                       */
+/************************************************************************/
+
+/**
+ * Convert wchar_t string to UTF-8. 
+ *
+ * Convert a wchar_t string into a multibyte utf-8 string
+ * using the iconv() function.
+ *
+ * Note that the wchar_t type varies in size on different systems. On
+ * win32 it is normally 2 bytes, and on unix 4 bytes.
+ *
+ * If an error occurs an error may, or may not be posted with CPLError(). 
+ *
+ * @param pwszSource the source wchar_t string, terminated with a 0 wchar_t.
+ * @param pszSrcEncoding the source encoding, typically CPL_ENC_UCS2.
+ * @param pszDstEncoding the destination encoding, typically CPL_ENC_UTF8.
+ *
+ * @return a zero terminated multi-byte string which should be freed with 
+ * CPLFree(), or NULL if an error occurs. 
+ */
+
+char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource, 
+                               const char *pszSrcEncoding, 
+                               const char *pszDstEncoding )
+
+{
+/* -------------------------------------------------------------------- */
+/*      What is the source length.                                      */
+/* -------------------------------------------------------------------- */
+    size_t  nSrcLen = 0;
+
+    while ( pwszSource[nSrcLen] != 0 )
+        nSrcLen++;
+
+/* -------------------------------------------------------------------- */
+/*      iconv() does not support wchar_t so we need to repack the       */
+/*      characters according to the width of a character in the         */
+/*      source encoding.  For instance if wchar_t is 4 bytes but our    */
+/*      source is UTF16 then we need to pack down into 2 byte           */
+/*      characters before passing to iconv().                           */
+/* -------------------------------------------------------------------- */
+    int nTargetCharWidth = CPLEncodingCharSize( pszSrcEncoding );
+
+    if( nTargetCharWidth < 1 )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Recode from %s with CPLRecodeFromWChar() failed because"
+                  " the width of characters in the encoding are not known.",
+                  pszSrcEncoding );
+        return CPLStrdup("");
+    }
+
+    GByte *pszIconvSrcBuf = (GByte*) CPLCalloc((nSrcLen+1),nTargetCharWidth);
+    unsigned int iSrc;
+
+    for( iSrc = 0; iSrc <= nSrcLen; iSrc++ )
+    {
+        if( nTargetCharWidth == 1 )
+            pszIconvSrcBuf[iSrc] = (GByte) pwszSource[iSrc];
+        else if( nTargetCharWidth == 2 )
+            ((short *)pszIconvSrcBuf)[iSrc] = (short) pwszSource[iSrc];
+        else if( nTargetCharWidth == 4 )
+            ((GInt32 *)pszIconvSrcBuf)[iSrc] = pwszSource[iSrc];
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the iconv() translation object.                          */
+/* -------------------------------------------------------------------- */
+    iconv_t sConv;
+
+    sConv = iconv_open( pszDstEncoding, pszSrcEncoding );
+
+    if ( sConv == (iconv_t)-1 )
+    {
+        CPLFree( pszIconvSrcBuf );
+        CPLError( CE_Warning, CPLE_AppDefined, 
+                  "Recode from %s to %s failed with the error: \"%s\".", 
+                  pszSrcEncoding, pszDstEncoding, strerror(errno) );
+
+        return CPLStrdup( "" );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      XXX: There is a portability issue: iconv() function could be    */
+/*      declared differently on different platforms. The second         */
+/*      argument could be declared as char** (as POSIX defines) or      */
+/*      as a const char**. Handle it with the ICONV_CPP_CONST macro here.   */
+/* -------------------------------------------------------------------- */
+    ICONV_CPP_CONST char *pszSrcBuf = (ICONV_CPP_CONST char *) pszIconvSrcBuf;
+
+    /* iconv expects a number of bytes, not characters */
+    nSrcLen *= sizeof(wchar_t);
+
+/* -------------------------------------------------------------------- */
+/*      Allocate destination buffer.                                    */
+/* -------------------------------------------------------------------- */
+    size_t  nDstCurLen = MAX(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
+    size_t  nDstLen = nDstCurLen;
+    char    *pszDestination = (char *)CPLCalloc( nDstCurLen, sizeof(char) );
+    char    *pszDstBuf = pszDestination;
+
+    while ( nSrcLen > 0 )
+    {
+        size_t  nConverted =
+            iconv( sConv, &pszSrcBuf, &nSrcLen, &pszDstBuf, &nDstLen );
+
+        if ( nConverted == (size_t)-1 )
+        {
+            if ( errno == EILSEQ )
+            {
+                // Skip the invalid sequence in the input string.
+                nSrcLen--;
+                pszSrcBuf += sizeof(wchar_t);
+                static int bHasWarned = FALSE;
+                if (!bHasWarned)
+                {
+                    bHasWarned = TRUE;
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "One or several characters couldn't be converted correctly from %s to %s.\n"
+                            "This warning will not be emitted anymore",
+                             pszSrcEncoding, pszDstEncoding);
+                }
+                continue;
+            }
+
+            else if ( errno == E2BIG )
+            {
+                // We are running out of the output buffer.
+                // Dynamically increase the buffer size.
+                size_t nTmp = nDstCurLen;
+                nDstCurLen *= 2;
+                pszDestination =
+                    (char *)CPLRealloc( pszDestination, nDstCurLen );
+                pszDstBuf = pszDestination + nTmp - nDstLen;
+                nDstLen += nDstCurLen - nTmp;
+                continue;
+            }
+
+            else
+                break;
+        }
+    }
+
+    pszDestination[nDstCurLen - nDstLen] = '\0';
+
+    iconv_close( sConv );
+
+    CPLFree( pszIconvSrcBuf );
+
+    return pszDestination;
+}
+
+/************************************************************************/
+/*                        CPLRecodeToWCharIconv()                       */
+/************************************************************************/
+
+/**
+ * Convert UTF-8 string to a wchar_t string.
+ *
+ * Convert a 8bit, multi-byte per character input string into a wide
+ * character (wchar_t) string using the iconv() function.
+ *
+ * Note that the wchar_t type varies in size on different systems. On
+ * win32 it is normally 2 bytes, and on unix 4 bytes.
+ *
+ * If an error occurs an error may, or may not be posted with CPLError(). 
+ *
+ * @param pszSource input multi-byte character string.
+ * @param pszSrcEncoding source encoding, typically CPL_ENC_UTF8.
+ * @param pszDstEncoding destination encoding, typically CPL_ENC_UCS2. 
+ *
+ * @return the zero terminated wchar_t string (to be freed with CPLFree()) or
+ * NULL on error.
+ */
+
+wchar_t *CPLRecodeToWCharIconv( const char *pszSource,
+                                const char *pszSrcEncoding, 
+                                const char *pszDstEncoding )
+
+{
+    return (wchar_t *)CPLRecodeIconv( pszSource,
+                                      pszSrcEncoding, pszDstEncoding);
+}
+
+#endif /* CPL_RECODE_ICONV */
diff --git a/port/cpl_recode_stub.cpp b/port/cpl_recode_stub.cpp
index 0073936..c37a392 100644
--- a/port/cpl_recode_stub.cpp
+++ b/port/cpl_recode_stub.cpp
@@ -1,9 +1,11 @@
 /**********************************************************************
- * $Id: cpl_recode_stub.cpp 17405 2009-07-17 06:13:24Z chaitanya $
+ * $Id: cpl_recode_stub.cpp 23024 2011-09-02 19:45:20Z rouault $
  *
- * Name:     cpl_recode.cpp
+ * Name:     cpl_recode_stub.cpp
  * Project:  CPL - Common Portability Library
- * Purpose:  Character set recoding and char/wchar_t conversions.
+ * Purpose:  Character set recoding and char/wchar_t conversions, stub
+ *           implementation to be used if iconv() functionality is not
+ *           available.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  * The bulk of this code is derived from the utf.c module from FLTK. It
@@ -29,9 +31,7 @@
 
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_recode_stub.cpp 17405 2009-07-17 06:13:24Z chaitanya $");
-
-#define CPL_RECODE_STUB
+CPL_CVSID("$Id: cpl_recode_stub.cpp 23024 2011-09-02 19:45:20Z rouault $");
 
 #ifdef CPL_RECODE_STUB 
 
@@ -60,7 +60,7 @@ static int utf8bytes(unsigned ucs);
 /************************************************************************/
 
 /************************************************************************/
-/*                             CPLRecode()                              */
+/*                           CPLRecodeStub()                            */
 /************************************************************************/
 
 /**
@@ -76,32 +76,19 @@ static int utf8bytes(unsigned ucs);
  *
  * If an error occurs an error may, or may not be posted with CPLError(). 
  *
- * @param pszSource a NUL terminated string.
+ * @param pszSource a NULL terminated string.
  * @param pszSrcEncoding the source encoding.
  * @param pszDstEncoding the destination encoding.
  *
- * @return a NUL terminated string which should be freed with CPLFree().
- *
- * @since GDAL 1.6.0
+ * @return a NULL terminated string which should be freed with CPLFree().
  */
 
-char CPL_DLL *CPLRecode( const char *pszSource, 
-                         const char *pszSrcEncoding, 
-                         const char *pszDstEncoding )
+char *CPLRecodeStub( const char *pszSource, 
+                     const char *pszSrcEncoding, 
+                     const char *pszDstEncoding )
 
 {
 /* -------------------------------------------------------------------- */
-/*      Handle a few common short cuts.                                 */
-/* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,pszDstEncoding) == 0 )
-        return CPLStrdup(pszSource);
-
-    if( strcmp(pszSrcEncoding,CPL_ENC_ASCII) == 0 
-        && (strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 
-            || strcmp(pszDstEncoding,CPL_ENC_ISO8859_1) == 0) )
-        return CPLStrdup(pszSource);
-
-/* -------------------------------------------------------------------- */
 /*      If the source or destination is current locale(), we change     */
 /*      it to ISO8859-1 since our stub implementation does not          */
 /*      attempt to address locales properly.                            */
@@ -207,7 +194,7 @@ char CPL_DLL *CPLRecode( const char *pszSource,
 }
 
 /************************************************************************/
-/*                         CPLRecodeFromWChar()                         */
+/*                       CPLRecodeFromWCharStub()                       */
 /************************************************************************/
 
 /**
@@ -230,27 +217,26 @@ char CPL_DLL *CPLRecode( const char *pszSource,
  *
  * @return a zero terminated multi-byte string which should be freed with 
  * CPLFree(), or NULL if an error occurs. 
- *
- * @since GDAL 1.6.0
  */
 
-char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource, 
-                                  const char *pszSrcEncoding, 
-                                  const char *pszDstEncoding )
+char *CPLRecodeFromWCharStub( const wchar_t *pwszSource, 
+                              const char *pszSrcEncoding, 
+                              const char *pszDstEncoding )
 
 {
 /* -------------------------------------------------------------------- */
 /*      We try to avoid changes of character set.  We are just          */
 /*      providing for unicode to unicode.                               */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) != 0
+    if( strcmp(pszSrcEncoding,"WCHAR_T") != 0 &&
+        strcmp(pszSrcEncoding,CPL_ENC_UTF8) != 0
         && strcmp(pszSrcEncoding,CPL_ENC_UTF16) != 0
         && strcmp(pszSrcEncoding,CPL_ENC_UCS2) != 0
         && strcmp(pszSrcEncoding,CPL_ENC_UCS4) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Stub recoding implementation does not support\n"
-                  "CPLRecodeFromWChar(...,%s,%s)", 
+                  "CPLRecodeFromWCharStub(...,%s,%s)", 
                   pszSrcEncoding, pszDstEncoding );
         return NULL;
     }
@@ -272,6 +258,12 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
     nDstBufSize = nSrcLen * 4 + 1;
     pszResult = (char *) CPLMalloc(nDstBufSize); // nearly worst case.
 
+    if (nSrcLen == 0)
+    {
+        pszResult[0] = '\0';
+        return pszResult;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Convert, and confirm we had enough space.                       */
 /* -------------------------------------------------------------------- */
@@ -289,7 +281,7 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
         return pszResult;
 
     char *pszFinalResult = 
-        CPLRecode( pszResult, CPL_ENC_UTF8, pszDstEncoding );
+        CPLRecodeStub( pszResult, CPL_ENC_UTF8, pszDstEncoding );
 
     CPLFree( pszResult );
     
@@ -297,7 +289,7 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
 }
 
 /************************************************************************/
-/*                          CPLRecodeToWChar()                          */
+/*                        CPLRecodeToWCharStub()                        */
 /************************************************************************/
 
 /**
@@ -325,9 +317,9 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
  * @since GDAL 1.6.0
  */
 
-wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
-                                   const char *pszSrcEncoding, 
-                                   const char *pszDstEncoding )
+wchar_t *CPLRecodeToWCharStub( const char *pszSource,
+                               const char *pszSrcEncoding, 
+                               const char *pszDstEncoding )
 
 {
     char *pszUTF8Source = (char *) pszSource;
@@ -335,7 +327,7 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
     if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) != 0 
         && strcmp(pszSrcEncoding,CPL_ENC_ASCII) != 0 )
     {
-        pszUTF8Source = CPLRecode( pszSource, pszSrcEncoding, CPL_ENC_UTF8 );
+        pszUTF8Source = CPLRecodeStub( pszSource, pszSrcEncoding, CPL_ENC_UTF8 );
         if( pszUTF8Source == NULL )
             return NULL;
     }
@@ -344,13 +336,14 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
 /*      We try to avoid changes of character set.  We are just          */
 /*      providing for unicode to unicode.                               */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszDstEncoding,CPL_ENC_UCS2) != 0
+    if( strcmp(pszDstEncoding,"WCHAR_T") != 0
+        && strcmp(pszDstEncoding,CPL_ENC_UCS2) != 0
         && strcmp(pszDstEncoding,CPL_ENC_UCS4) != 0 
         && strcmp(pszDstEncoding,CPL_ENC_UTF16) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Stub recoding implementation does not support\n"
-                  "CPLRecodeToWChar(...,%s,%s)", 
+                  "CPLRecodeToWCharStub(...,%s,%s)", 
                   pszSrcEncoding, pszDstEncoding );
         return NULL;
     }
@@ -384,7 +377,7 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
  *
  * @since GDAL 1.7.0
  */
-int CPLIsUTF8(const char* pabyData, int nLen)
+int CPLIsUTF8Stub(const char* pabyData, int nLen)
 {
     if (nLen < 0)
         nLen = strlen(pabyData);
@@ -392,43 +385,6 @@ int CPLIsUTF8(const char* pabyData, int nLen)
 }
 
 /************************************************************************/
-/*                          CPLForceToASCII()                           */
-/************************************************************************/
-
-/**
- * Return a new string that is made only of ASCII characters. If non-ASCII
- * characters are found in the input string, they will be replaced by the
- * provided replacement character.
- *
- * @param pabyData input string to test
- * @param nLen length of the input string, or -1 if the function must compute
- *             the string length. In which case it must be null terminated.
- * @param chReplacementChar character which will be used when the input stream
- *                          contains a non ASCII character. Must be valid ASCII !
- *
- * @return a new string that must be freed with CPLFree().
- *
- * @since GDAL 1.7.0
- */
-char CPL_DLL *CPLForceToASCII(const char* pabyData, int nLen, char chReplacementChar)
-{
-    if (nLen < 0)
-        nLen = strlen(pabyData);
-    char* pszOutputString = (char*)CPLMalloc(nLen + 1);
-    int i;
-    for(i=0;i<nLen;i++)
-    {
-        if (((unsigned char*)pabyData)[i] > 127)
-            pszOutputString[i] = chReplacementChar;
-        else
-            pszOutputString[i] = pabyData[i];
-    }
-    pszOutputString[i] = '\0';
-    return pszOutputString;
-}
-
-
-/************************************************************************/
 /* ==================================================================== */
 /*	UTF.C code from FLTK with some modifications.                   */
 /* ==================================================================== */
@@ -856,7 +812,18 @@ static unsigned utf8toa(const char* src, unsigned srclen,
       int len; unsigned ucs = utf8decode(p,e,&len);
       p += len;
       if (ucs < 0x100) dst[count] = (char)ucs;
-      else dst[count] = '?';
+      else
+      {
+          static int bHasWarned = FALSE;
+          if (!bHasWarned)
+          {
+              bHasWarned = TRUE;
+              CPLError(CE_Warning, CPLE_AppDefined,
+                       "One or several characters couldn't be converted correctly from UTF-8 to ISO-8859-1.\n"
+                       "This warning will not be emitted anymore");
+          }
+          dst[count] = '?';
+      }
     }
     if (++count >= dstlen) {dst[count-1] = 0; break;}
   }
diff --git a/port/cpl_string.cpp b/port/cpl_string.cpp
index 351f3d5..9e89343 100644
--- a/port/cpl_string.cpp
+++ b/port/cpl_string.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_string.cpp 21449 2011-01-09 21:58:17Z warmerdam $
+ * $Id: cpl_string.cpp 23407 2011-11-21 19:35:16Z rouault $
  *
  * Name:     cpl_string.cpp
  * Project:  CPL - Common Portability Library
@@ -54,7 +54,7 @@
 #  include <wce_string.h>
 #endif
 
-CPL_CVSID("$Id: cpl_string.cpp 21449 2011-01-09 21:58:17Z warmerdam $");
+CPL_CVSID("$Id: cpl_string.cpp 23407 2011-11-21 19:35:16Z rouault $");
 
 /*=====================================================================
                     StringList manipulation functions.
@@ -338,10 +338,13 @@ char **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols, char** papszO
     }
     else
     {
-        /* Unable to open file */
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "CSLLoad2(\"%s\") failed: unable to open output file.",
-                  pszFname );
+        if (CSLFetchBoolean(papszOptions, "EMIT_ERROR_IF_CANNOT_OPEN_FILE", TRUE))
+        {
+            /* Unable to open file */
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "CSLLoad2(\"%s\") failed: unable to open file.",
+                    pszFname );
+        }
     }
 
     return papszStrList;
@@ -788,8 +791,7 @@ char ** CSLTokenizeString2( const char * pszString,
 {
     if( pszString == NULL )
         return (char **) CPLCalloc(sizeof(char *),1);
-    char        **papszRetList = NULL;
-    int         nRetMax = 0, nRetLen = 0;
+    CPLStringList oRetList;
     char        *pszToken;
     int         nTokenMax, nTokenLen;
     int         bHonourStrings = (nCSLTFlags & CSLT_HONOURSTRINGS);
@@ -897,43 +899,29 @@ char ** CSLTokenizeString2( const char * pszString,
          * Add the token.
          */
         if( pszToken[0] != '\0' || bAllowEmptyTokens )
-        {
-            if( nRetLen >= nRetMax - 1 )
-            {
-                nRetMax = nRetMax * 2 + 10;
-                papszRetList = (char **) 
-                    CPLRealloc(papszRetList, sizeof(char*) * nRetMax );
-            }
-
-            papszRetList[nRetLen++] = CPLStrdup( pszToken );
-            papszRetList[nRetLen] = NULL;
-        }
+            oRetList.AddString( pszToken );
     }
 
     /*
      * If the last token was empty, then we need to capture
      * it now, as the loop would skip it.
      */
-    if( *pszString == '\0' && bAllowEmptyTokens && nRetLen > 0 
+    if( *pszString == '\0' && bAllowEmptyTokens && oRetList.Count() > 0 
         && strchr(pszDelimiters,*(pszString-1)) != NULL )
     {
-        if( nRetLen >= nRetMax - 1 )
-        {
-            nRetMax = nRetMax * 2 + 10;
-            papszRetList = (char **) 
-                CPLRealloc(papszRetList, sizeof(char*) * nRetMax );
-        }
-
-        papszRetList[nRetLen++] = CPLStrdup("");
-        papszRetList[nRetLen] = NULL;
+        oRetList.AddString( "" );
     }
 
-    if( papszRetList == NULL )
-        papszRetList = (char **) CPLCalloc(sizeof(char *),1);
-
     CPLFree( pszToken );
 
-    return papszRetList;
+    if( oRetList.List() == NULL )
+    {
+        // 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) );
+    }
+
+    return oRetList.StealList();
 }
 
 /**********************************************************************
@@ -1027,7 +1015,7 @@ int CPLVASPrintf( char **buf, const char *fmt, va_list ap )
     osWork.vPrintf( fmt, ap );
 
     if( buf )
-        *buf = strdup(osWork.c_str());
+        *buf = CPLStrdup(osWork.c_str());
 
     return strlen(osWork);
 }
@@ -1458,8 +1446,8 @@ void CSLSetNameValueSeparator( char ** papszList, const char *pszSeparator )
  * The backslash, quote, '\\0' and newline characters are all escaped in 
  * the usual C style. 
  *
- * CPLES_XML(1): This scheme converts the '<', '<' and '&' characters into
- * their XML/HTML equivelent (>, < and &) making a string safe
+ * CPLES_XML(1): This scheme converts the '<', '>', '"' and '&' characters into
+ * their XML/HTML equivelent (<, >, " and &) making a string safe
  * to embed as CDATA within an XML element.  The '\\0' is not escaped and 
  * should not be included in the input.
  *
@@ -1539,13 +1527,13 @@ char *CPLEscapeString( const char *pszInput, int nLength,
             if( (pszInput[iIn] >= 'a' && pszInput[iIn] <= 'z')
                 || (pszInput[iIn] >= 'A' && pszInput[iIn] <= 'Z')
                 || (pszInput[iIn] >= '0' && pszInput[iIn] <= '9')
-                || pszInput[iIn] == '_' )
+                || pszInput[iIn] == '_' || pszInput[iIn] == '.' )
             {
                 pszOutput[iOut++] = pszInput[iIn];
             }
             else
             {
-                sprintf( pszOutput+iOut, "%%%02X", pszInput[iIn] );
+                sprintf( pszOutput+iOut, "%%%02X", ((unsigned char*)pszInput)[iIn] );
                 iOut += 3;
             }
         }
@@ -1588,6 +1576,14 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 pszOutput[iOut++] = 't';
                 pszOutput[iOut++] = ';';
             }
+            else if( ((GByte*)pszInput)[iIn] < 0x20 
+                     && pszInput[iIn] != 0x9
+                     && pszInput[iIn] != 0xA 
+                     && pszInput[iIn] != 0xD ) 
+            {
+                // These control characters are unrepresentable in XML format, 
+                // so we just drop them.  #4117
+            }
             else
                 pszOutput[iOut++] = pszInput[iIn];
         }
@@ -1683,14 +1679,19 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
     char *pszOutput;
     int iOut=0, iIn;
 
-    pszOutput = (char *) CPLMalloc(strlen(pszInput)+1);
+    pszOutput = (char *) CPLMalloc(4 * strlen(pszInput)+1);
     pszOutput[0] = '\0';
 
     if( nScheme == CPLES_XML )
     {
-        for( iIn = 0; pszInput[iIn] != '\0'; iIn++ )
+        char ch;
+        for( iIn = 0; (ch = pszInput[iIn]) != '\0'; iIn++ )
         {
-            if( EQUALN(pszInput+iIn,"<",4) )
+            if( ch != '&' )
+            {
+                pszOutput[iOut++] = ch;
+            }
+            else if( EQUALN(pszInput+iIn,"<",4) )
             {
                 pszOutput[iOut++] = '<';
                 iIn += 3;
@@ -1705,14 +1706,73 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
                 pszOutput[iOut++] = '&';
                 iIn += 4;
             }
+            else if( EQUALN(pszInput+iIn,"'",6) )
+            {
+                pszOutput[iOut++] = '\'';
+                iIn += 5;
+            }
             else if( EQUALN(pszInput+iIn,""",6) )
             {
                 pszOutput[iOut++] = '"';
                 iIn += 5;
             }
+            else if( EQUALN(pszInput+iIn,"&#x",3) )
+            {
+                wchar_t anVal[2] = {0 , 0};
+                iIn += 3;
+
+                while(TRUE)
+                {
+                    ch = pszInput[iIn ++];
+                    if (ch >= 'a' && ch <= 'f')
+                        anVal[0] = anVal[0] * 16 + ch - 'a' + 10;
+                    else if (ch >= 'A' && ch <= 'A')
+                        anVal[0] = anVal[0] * 16 + ch - 'A' + 10;
+                    else if (ch >= '0' && ch <= '9')
+                        anVal[0] = anVal[0] * 16 + ch - '0';
+                    else
+                        break;
+                }
+                if (ch != ';')
+                    break;
+                iIn --;
+
+                char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
+                int nLen = strlen(pszUTF8);
+                memcpy(pszOutput + iOut, pszUTF8, nLen);
+                CPLFree(pszUTF8);
+                iOut += nLen;
+            }
+            else if( EQUALN(pszInput+iIn,"&#",2) )
+            {
+                char ch;
+                wchar_t anVal[2] = {0 , 0};
+                iIn += 2;
+
+                while(TRUE)
+                {
+                    ch = pszInput[iIn ++];
+                    if (ch >= '0' && ch <= '9')
+                        anVal[0] = anVal[0] * 10 + ch - '0';
+                    else
+                        break;
+                }
+                if (ch != ';')
+                    break;
+                iIn --;
+
+                char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
+                int nLen = strlen(pszUTF8);
+                memcpy(pszOutput + iOut, pszUTF8, nLen);
+                CPLFree(pszUTF8);
+                iOut += nLen;
+            }
             else
             {
-                pszOutput[iOut++] = pszInput[iIn];
+                /* illegal escape sequence */
+                CPLDebug( "CPL",
+                          "Error unescaping CPLES_XML text, '&' character followed by unhandled escape sequence." );
+                break;
             }
         }
     }
@@ -1908,6 +1968,10 @@ GByte *CPLHexToBinary( const char *pszHex, int *pnBytes )
  * a real, an integer or a string
  * Leading and trailing spaces are skipped in the analysis.
  *
+ * Note: in the context of this function, integer must be understood in a
+ * broad sense. It does not mean that the value can fit into a 32 bit integer
+ * for example. It might be larger.
+ *
  * @param pszValue the string to analyze
  *
  * @return returns the type of the value contained in the string.
diff --git a/port/cpl_string.h b/port/cpl_string.h
index 751fc4b..1c9ce1b 100644
--- a/port/cpl_string.h
+++ b/port/cpl_string.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_string.h 21815 2011-02-23 22:56:54Z warmerdam $
+ * $Id: cpl_string.h 23431 2011-11-27 15:02:24Z rouault $
  *
  * Name:     cpl_string.h
  * Project:  CPL - Common Portability Library
@@ -49,26 +49,30 @@
  * name/value pairs.  The actual data is formatted with each string having
  * the format "<name>:<value>" (though "=" is also an acceptable separator). 
  * A number of the functions in the file operate on name/value style
- * string lists (such as CSLSetNameValue(), and CSLFetchNameValue()). 
+ * string lists (such as CSLSetNameValue(), and CSLFetchNameValue()).
+ *
+ * To some extent the CPLStringList C++ class can be used to abstract
+ * managing string lists a bit but still be able to return them from C
+ * functions.
  *
  */
 
 CPL_C_START
 
-char CPL_DLL **CSLAddString(char **papszStrList, const char *pszNewString);
+char CPL_DLL **CSLAddString(char **papszStrList, const char *pszNewString) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CSLCount(char **papszStrList);
 const char CPL_DLL *CSLGetField( char **, int );
 void CPL_DLL CPL_STDCALL CSLDestroy(char **papszStrList);
-char CPL_DLL **CSLDuplicate(char **papszStrList);
-char CPL_DLL **CSLMerge( char **papszOrig, char **papszOverride );
+char CPL_DLL **CSLDuplicate(char **papszStrList) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLMerge( char **papszOrig, char **papszOverride ) CPL_WARN_UNUSED_RESULT;
 
-char CPL_DLL **CSLTokenizeString(const char *pszString );
+char CPL_DLL **CSLTokenizeString(const char *pszString ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL **CSLTokenizeStringComplex(const char *pszString,
                                    const char *pszDelimiter,
-                                   int bHonourStrings, int bAllowEmptyTokens );
+                                   int bHonourStrings, int bAllowEmptyTokens ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL **CSLTokenizeString2( const char *pszString, 
                                    const char *pszDelimeter, 
-                                   int nCSLTFlags );
+                                   int nCSLTFlags ) CPL_WARN_UNUSED_RESULT;
 
 #define CSLT_HONOURSTRINGS      0x0001
 #define CSLT_ALLOWEMPTYTOKENS   0x0002
@@ -78,16 +82,16 @@ char CPL_DLL **CSLTokenizeString2( const char *pszString,
 #define CSLT_STRIPENDSPACES     0x0020
 
 int CPL_DLL CSLPrint(char **papszStrList, FILE *fpOut);
-char CPL_DLL **CSLLoad(const char *pszFname);
-char CPL_DLL **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols, char** papszOptions);
+char CPL_DLL **CSLLoad(const char *pszFname) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols, char** papszOptions) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CSLSave(char **papszStrList, const char *pszFname);
 
 char CPL_DLL **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo, 
-                         char **papszNewLines);
+                         char **papszNewLines) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL **CSLInsertString(char **papszStrList, int nInsertAtLineNo, 
-                               const char *pszNewLine);
+                               const char *pszNewLine) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
-                         int nNumToRemove, char ***ppapszRetStrings);
+                         int nNumToRemove, char ***ppapszRetStrings) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CSLFindString( char **, const char * );
 int CPL_DLL CSLPartialFindString( char **papszHaystack, 
 	const char * pszNeedle );
@@ -97,7 +101,7 @@ int CPL_DLL CSLFetchBoolean( char **papszStrList, const char *pszKey,
                              int bDefault );
 
 const char CPL_DLL *CPLSPrintf(const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(1, 2);
-char CPL_DLL **CSLAppendPrintf(char **papszStrList, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3);
+char CPL_DLL **CSLAppendPrintf(char **papszStrList, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPLVASPrintf(char **buf, const char *fmt, va_list args );
 
 const char CPL_DLL *
@@ -111,10 +115,10 @@ char CPL_DLL **
       CSLFetchNameValueMultiple(char **papszStrList, const char *pszName);
 char CPL_DLL **
       CSLAddNameValue(char **papszStrList, 
-                      const char *pszName, const char *pszValue);
+                      const char *pszName, const char *pszValue) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL **
       CSLSetNameValue(char **papszStrList, 
-                      const char *pszName, const char *pszValue);
+                      const char *pszName, const char *pszValue) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL CSLSetNameValueSeparator( char ** papszStrList, 
                                        const char *pszSeparator );
 
@@ -125,12 +129,15 @@ void CPL_DLL CSLSetNameValueSeparator( char ** papszStrList,
 #define CPLES_CSV               4
 
 char CPL_DLL *CPLEscapeString( const char *pszString, int nLength, 
-                               int nScheme );
+                               int nScheme ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL *CPLUnescapeString( const char *pszString, int *pnLength,
-                                 int nScheme );
+                                 int nScheme ) CPL_WARN_UNUSED_RESULT;
+
+char CPL_DLL *CPLBinaryToHex( int nBytes, const GByte *pabyData ) CPL_WARN_UNUSED_RESULT;
+GByte CPL_DLL *CPLHexToBinary( const char *pszHex, int *pnBytes ) CPL_WARN_UNUSED_RESULT;
 
-char CPL_DLL *CPLBinaryToHex( int nBytes, const GByte *pabyData );
-GByte CPL_DLL *CPLHexToBinary( const char *pszHex, int *pnBytes );
+char CPL_DLL *CPLBase64Encode( int nBytes, const GByte *pabyData ) CPL_WARN_UNUSED_RESULT;
+int CPL_DLL CPLBase64DecodeInPlace(GByte* pszBase64);
 
 typedef enum
 {
@@ -156,17 +163,18 @@ size_t CPL_DLL CPLStrnlen (const char *pszStr, size_t nMaxLen);
 #define CPL_ENC_ASCII      "ASCII"
 #define CPL_ENC_ISO8859_1  "ISO-8859-1"
 
+int CPL_DLL  CPLEncodingCharSize( const char *pszEncoding );
 char CPL_DLL *CPLRecode( const char *pszSource, 
                          const char *pszSrcEncoding, 
-                         const char *pszDstEncoding );
+                         const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource, 
                                   const char *pszSrcEncoding, 
-                                  const char *pszDstEncoding );
+                                  const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
 wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
                                    const char *pszSrcEncoding, 
-                                   const char *pszDstEncoding );
+                                   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);
+char CPL_DLL *CPLForceToASCII(const char* pabyData, int nLen, char chReplacementChar) CPL_WARN_UNUSED_RESULT;
 
 CPL_C_END
 
@@ -210,9 +218,7 @@ CPL_C_END
 #  pragma warning(disable:4251 4275 4786)
 #endif
 
-
-
-
+//! Convenient string class based on std::string.
 class CPL_DLL CPLString : public gdal_std_string
 {
 public:
@@ -256,7 +262,84 @@ public:
     /* case insensitive find alternates */
     size_t    ifind( const std::string & str, size_t pos = 0 ) const;
     size_t    ifind( const char * s, size_t pos = 0 ) const;
+    CPLString &toupper( void );
+    CPLString &tolower( void );
+};
+
+/* -------------------------------------------------------------------- */
+/*      URL processing functions, here since they depend on CPLString.  */
+/* -------------------------------------------------------------------- */
+CPLString CPL_DLL CPLURLGetValue(const char* pszURL, const char* pszKey);
+CPLString CPL_DLL CPLURLAddKVP(const char* pszURL, const char* pszKey,
+                               const char* pszValue);
+
+/************************************************************************/
+/*                            CPLStringList                             */
+/************************************************************************/
+
+//! String list class designed around our use of C "char**" string lists.
+class CPL_DLL CPLStringList
+{
+    char **papszList;
+    mutable int nCount;
+    mutable int nAllocation;
+    int    bOwnList;
+    int    bIsSorted;
+
+    void   Initialize();
+    void   MakeOurOwnCopy();
+    void   EnsureAllocation( int nMaxLength );
+    int    FindSortedInsertionPoint( const char *pszLine );
+    
+  public:
+    CPLStringList();
+    CPLStringList( char **papszList, int bTakeOwnership=TRUE );
+    CPLStringList( const CPLStringList& oOther );
+    ~CPLStringList();
 
+    CPLStringList &Clear();
+
+    int    size() const { return Count(); }
+    int    Count() const;
+
+    CPLStringList &AddString( const char *pszNewString );
+    CPLStringList &AddStringDirectly( char *pszNewString );
+
+    CPLStringList &InsertString( int nInsertAtLineNo, const char *pszNewLine )
+    { return InsertStringDirectly( nInsertAtLineNo, CPLStrdup(pszNewLine) ); }
+    CPLStringList &InsertStringDirectly( int nInsertAtLineNo, char *pszNewLine);
+    
+//    CPLStringList &InsertStrings( int nInsertAtLineNo, char **papszNewLines );
+//    CPLStringList &RemoveStrings( int nFirstLineToDelete, int nNumToRemove=1 );
+    
+    int    FindString( const char *pszTarget ) const
+    { return CSLFindString( papszList, pszTarget ); }
+    int    PartialFindString( const char *pszNeedle ) const
+    { return CSLPartialFindString( papszList, pszNeedle ); }
+
+    int    FindName( const char *pszName ) const;
+    int    FetchBoolean( const char *pszKey, int bDefault ) const;
+    const char *FetchNameValue( const char *pszKey ) const;
+    const char *FetchNameValueDef( const char *pszKey, const char *pszDefault ) const;
+    CPLStringList &AddNameValue( const char *pszKey, const char *pszValue );
+    CPLStringList &SetNameValue( const char *pszKey, const char *pszValue );
+
+    CPLStringList &Assign( char **papszList, int bTakeOwnership=TRUE );
+    CPLStringList &operator=(char **papszListIn) { return Assign( papszListIn, TRUE ); }
+    CPLStringList &operator=(const CPLStringList& oOther);
+
+    char * operator[](int i);
+    char * operator[](size_t i) { return (*this)[(int)i]; }
+    const char * operator[](int i) const;
+    const char * operator[](size_t i) const { return (*this)[(int)i]; }
+
+    char **List() { return papszList; }
+    char **StealList();
+
+    CPLStringList &Sort();
+    int    IsSorted() const { return bIsSorted; }
+
+    operator char**(void) { return List(); }
 };
 
 #endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */
diff --git a/port/cpl_strtod.cpp b/port/cpl_strtod.cpp
index 95ec11b..fcc3c25 100644
--- a/port/cpl_strtod.cpp
+++ b/port/cpl_strtod.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_strtod.cpp 19692 2010-05-13 17:16:55Z rouault $
+ * $Id: cpl_strtod.cpp 23556 2011-12-12 21:49:34Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Functions to convert ASCII string to floating point number.
@@ -33,7 +33,7 @@
 
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: cpl_strtod.cpp 19692 2010-05-13 17:16:55Z rouault $");
+CPL_CVSID("$Id: cpl_strtod.cpp 23556 2011-12-12 21:49:34Z rouault $");
 
 // XXX: with GCC 2.95 strtof() function is only available when in c99 mode.
 // Fix it here not touching the compiler options.
@@ -167,12 +167,12 @@ double CPLAtofM( const char *nptr )
 }
 
 /************************************************************************/
-/*                          CPLStrtodDelim()                            */
+/*                      CPLReplacePointByLocalePoint()                  */
 /************************************************************************/
 
-static void CPLReplacePointByLocalePoint(char* pszNumber, char point)
+static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
 {
-#if defined(WIN32CE)
+#if defined(WIN32CE) || defined(__ANDROID__)
     static char byPoint = 0;
     if (byPoint == 0)
     {
@@ -182,16 +182,12 @@ static void CPLReplacePointByLocalePoint(char* pszNumber, char point)
     }
     if (point != byPoint)
     {
-        int     i = 0;
-
-        while ( pszNumber[i] )
+        const char* pszPoint = strchr(pszNumber, point);
+        if (pszPoint)
         {
-            if ( pszNumber[i] == point )
-            {
-                pszNumber[i] = byPoint;
-                break;
-            }
-            i++;
+            char* pszNew = CPLStrdup(pszNumber);
+            pszNew[pszPoint - pszNumber] = byPoint;
+            return pszNew;
         }
     }
 #else
@@ -200,25 +196,26 @@ static void CPLReplacePointByLocalePoint(char* pszNumber, char point)
          && poLconv->decimal_point
          && strlen(poLconv->decimal_point) > 0 )
     {
-        int     i = 0;
         char    byPoint = poLconv->decimal_point[0];
 
         if (point != byPoint)
         {
-            while ( pszNumber[i] )
+            const char* pszPoint = strchr(pszNumber, point);
+            if (pszPoint)
             {
-                if ( pszNumber[i] == point )
-                {
-                    pszNumber[i] = byPoint;
-                    break;
-                }
-                i++;
+                char* pszNew = CPLStrdup(pszNumber);
+                pszNew[pszPoint - pszNumber] = byPoint;
+                return pszNew;
             }
         }
     }
 #endif
+    return (char*) pszNumber;
 }
 
+/************************************************************************/
+/*                          CPLStrtodDelim()                            */
+/************************************************************************/
 
 /**
  * Converts ASCII string to floating point number using specified delimiter.
@@ -249,11 +246,10 @@ double CPLStrtodDelim(const char *nptr, char **endptr, char point)
 /*  with the one, taken from locale settings and use standard strtod()  */
 /*  on that buffer.                                                     */
 /* -------------------------------------------------------------------- */
-    char        *pszNumber = CPLStrdup( nptr );
     double      dfValue;
     int         nError;
 
-    CPLReplacePointByLocalePoint(pszNumber, point);
+    char*       pszNumber = CPLReplacePointByLocalePoint(nptr, point);
 
     dfValue = strtod( pszNumber, endptr );
     nError = errno;
@@ -261,7 +257,8 @@ double CPLStrtodDelim(const char *nptr, char **endptr, char point)
     if ( endptr )
         *endptr = (char *)nptr + (*endptr - pszNumber);
 
-    CPLFree( pszNumber );
+    if (pszNumber != (char*) nptr)
+        CPLFree( pszNumber );
 
     errno = nError;
     return dfValue;
@@ -324,11 +321,10 @@ float CPLStrtofDelim(const char *nptr, char **endptr, char point)
 /*  on that buffer.                                                     */
 /* -------------------------------------------------------------------- */
 
-    char        *pszNumber = CPLStrdup( nptr );
     double      dfValue;
     int         nError;
 
-    CPLReplacePointByLocalePoint(pszNumber, point);
+    char*       pszNumber = CPLReplacePointByLocalePoint(nptr, point);
 
     dfValue = strtof( pszNumber, endptr );
     nError = errno;
@@ -336,7 +332,8 @@ float CPLStrtofDelim(const char *nptr, char **endptr, char point)
     if ( endptr )
         *endptr = (char *)nptr + (*endptr - pszNumber);
 
-    CPLFree( pszNumber );
+    if (pszNumber != (char*) nptr)
+        CPLFree( pszNumber );
 
     errno = nError;
     return dfValue;
diff --git a/port/cpl_vsi.h b/port/cpl_vsi.h
index 7b7625e..361d059 100644
--- a/port/cpl_vsi.h
+++ b/port/cpl_vsi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi.h 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl_vsi.h 23467 2011-12-04 22:56:00Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -78,7 +78,7 @@ CPL_C_START
 /*      API.                                                            */
 /* ==================================================================== */
 
-FILE CPL_DLL *  VSIFOpen( const char *, const char * );
+FILE CPL_DLL *  VSIFOpen( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFClose( FILE * );
 int CPL_DLL     VSIFSeek( FILE *, long, int );
 long CPL_DLL    VSIFTell( FILE * );
@@ -135,14 +135,16 @@ typedef struct _VSILFILE VSILFILE;
 typedef FILE VSILFILE;
 #endif
 
-VSILFILE CPL_DLL *  VSIFOpenL( const char *, const char * );
+VSILFILE CPL_DLL *  VSIFOpenL( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFCloseL( VSILFILE * );
 int CPL_DLL     VSIFSeekL( VSILFILE *, vsi_l_offset, int );
 vsi_l_offset CPL_DLL VSIFTellL( VSILFILE * );
 void CPL_DLL    VSIRewindL( VSILFILE * );
 size_t CPL_DLL  VSIFReadL( void *, size_t, size_t, VSILFILE * );
+int CPL_DLL     VSIFReadMultiRangeL( int nRanges, void ** ppData, const vsi_l_offset* panOffsets, const size_t* panSizes, VSILFILE * );
 size_t CPL_DLL  VSIFWriteL( const void *, size_t, size_t, VSILFILE * );
 int CPL_DLL     VSIFEofL( VSILFILE * );
+int CPL_DLL     VSIFTruncateL( VSILFILE *, vsi_l_offset );
 int CPL_DLL     VSIFFlushL( VSILFILE * );
 int CPL_DLL     VSIFPrintfL( VSILFILE *, const char *, ... ) CPL_PRINT_FUNC_FORMAT(2, 3);
 int CPL_DLL     VSIFPutcL( int, VSILFILE * );
@@ -167,11 +169,11 @@ int CPL_DLL     VSIIsCaseSensitiveFS( const char * pszFilename );
 /*      Memory allocation                                               */
 /* ==================================================================== */
 
-void CPL_DLL   *VSICalloc( size_t, size_t );
-void CPL_DLL   *VSIMalloc( size_t );
+void CPL_DLL   *VSICalloc( size_t, size_t ) CPL_WARN_UNUSED_RESULT;
+void CPL_DLL   *VSIMalloc( size_t ) CPL_WARN_UNUSED_RESULT;
 void CPL_DLL    VSIFree( void * );
-void CPL_DLL   *VSIRealloc( void *, size_t );
-char CPL_DLL   *VSIStrdup( const char * );
+void CPL_DLL   *VSIRealloc( void *, size_t ) CPL_WARN_UNUSED_RESULT;
+char CPL_DLL   *VSIStrdup( const char * ) CPL_WARN_UNUSED_RESULT;
 
 /**
  VSIMalloc2 allocates (nSize1 * nSize2) bytes.
@@ -180,7 +182,7 @@ char CPL_DLL   *VSIStrdup( const char * );
  If nSize1 == 0 || nSize2 == 0, a NULL pointer will also be returned.
  CPLFree() or VSIFree() can be used to free memory allocated by this function.
 */
-void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 );
+void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 ) CPL_WARN_UNUSED_RESULT;
 
 /**
  VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.
@@ -189,7 +191,7 @@ void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 );
  If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.
  CPLFree() or VSIFree() can be used to free memory allocated by this function.
 */
-void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 );
+void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 ) CPL_WARN_UNUSED_RESULT;
 
 
 /* ==================================================================== */
diff --git a/port/cpl_vsi_mem.cpp b/port/cpl_vsi_mem.cpp
index 104f390..68cbf9b 100644
--- a/port/cpl_vsi_mem.cpp
+++ b/port/cpl_vsi_mem.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi_mem.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: cpl_vsi_mem.cpp 23596 2011-12-18 23:20:12Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of Memory Buffer virtual IO functions.
@@ -42,7 +42,7 @@
 #endif
 
 
-CPL_CVSID("$Id: cpl_vsi_mem.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: cpl_vsi_mem.cpp 23596 2011-12-18 23:20:12Z rouault $");
 
 /*
 ** Notes on Multithreading:
@@ -90,6 +90,8 @@ public:
     vsi_l_offset  nLength;
     vsi_l_offset  nAllocLength;
 
+    int           bEOF;
+
                   VSIMemFile();
     virtual       ~VSIMemFile();
 
@@ -108,6 +110,7 @@ class VSIMemHandle : public VSIVirtualHandle
     VSIMemFile    *poFile;
     vsi_l_offset  nOffset;
     int           bUpdate;
+    int           bEOF;
 
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
     virtual vsi_l_offset Tell();
@@ -115,6 +118,7 @@ class VSIMemHandle : public VSIVirtualHandle
     virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
     virtual int       Eof();
     virtual int       Close();
+    virtual int       Truncate( vsi_l_offset nNewSize );
 };
 
 /************************************************************************/
@@ -163,6 +167,7 @@ VSIMemFile::VSIMemFile()
     pabyData = NULL;
     nLength = 0;
     nAllocLength = 0;
+    bEOF = FALSE;
 }
 
 /************************************************************************/
@@ -264,12 +269,8 @@ int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence )
         return -1;
     }
 
-    if( this->nOffset < 0 )
-    {
-        this->nOffset = 0;
-        return -1;
-    }
-    
+    bEOF = FALSE;
+
     if( this->nOffset > poFile->nLength )
     {
         if( !bUpdate ) // Read-only files cannot be extended by seek.
@@ -315,8 +316,15 @@ size_t VSIMemHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 
     if( nBytesToRead + nOffset > poFile->nLength )
     {
+        if (poFile->nLength < nOffset)
+        {
+            bEOF = TRUE;
+            return 0;
+        }
+
         nBytesToRead = (size_t)(poFile->nLength - nOffset);
         nCount = nBytesToRead / nSize;
+        bEOF = TRUE;
     }
 
     memcpy( pBuffer, poFile->pabyData + nOffset, (size_t)nBytesToRead );
@@ -360,7 +368,25 @@ size_t VSIMemHandle::Write( const void * pBuffer, size_t nSize, size_t nCount )
 int VSIMemHandle::Eof()
 
 {
-    return nOffset == poFile->nLength;
+    return bEOF;
+}
+
+/************************************************************************/
+/*                             Truncate()                               */
+/************************************************************************/
+
+int VSIMemHandle::Truncate( vsi_l_offset nNewSize )
+{
+    if( !bUpdate )
+    {
+        errno = EACCES;
+        return -1;
+    }
+
+    if (poFile->SetLength( nNewSize ))
+        return 0;
+    else
+        return -1;
 }
 
 /************************************************************************/
@@ -453,6 +479,7 @@ VSIMemFilesystemHandler::Open( const char *pszFilename,
 
     poHandle->poFile = poFile;
     poHandle->nOffset = 0;
+    poHandle->bEOF = FALSE;
     if( strstr(pszAccess,"w") || strstr(pszAccess,"+") 
         || strstr(pszAccess,"a") )
         poHandle->bUpdate = TRUE;
diff --git a/port/cpl_vsi_virtual.h b/port/cpl_vsi_virtual.h
index 5cc5941..009b003 100644
--- a/port/cpl_vsi_virtual.h
+++ b/port/cpl_vsi_virtual.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi_virtual.h 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: cpl_vsi_virtual.h 23467 2011-12-04 22:56:00Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Declarations for classes related to the virtual filesystem.
@@ -55,10 +55,12 @@ class CPL_DLL VSIVirtualHandle {
     virtual int       Seek( vsi_l_offset nOffset, int nWhence ) = 0;
     virtual vsi_l_offset Tell() = 0;
     virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb ) = 0;
+    virtual int       ReadMultiRange( int nRanges, void ** ppData, const vsi_l_offset* panOffsets, const size_t* panSizes );
     virtual size_t    Write( const void *pBuffer, size_t nSize,size_t nMemb)=0;
     virtual int       Eof() = 0;
     virtual int       Flush() {return 0;}
     virtual int       Close() = 0;
+    virtual int       Truncate( vsi_l_offset nNewSize ) { return -1; }
     virtual           ~VSIVirtualHandle() { }
 };
 
@@ -185,5 +187,6 @@ public:
 };
 
 VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle);
+VSIVirtualHandle* VSICreateCachedFile( VSIVirtualHandle* poBaseHandle );
 
 #endif /* ndef CPL_VSI_VIRTUAL_H_INCLUDED */
diff --git a/port/cpl_vsil.cpp b/port/cpl_vsil.cpp
index bdc0927..96af694 100644
--- a/port/cpl_vsil.cpp
+++ b/port/cpl_vsil.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl_vsil.cpp 23506 2011-12-10 13:43:59Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation VSI*L File API and other file system access
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include <string>
 
-CPL_CVSID("$Id: cpl_vsil.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: cpl_vsil.cpp 23506 2011-12-10 13:43:59Z rouault $");
 
 /************************************************************************/
 /*                             VSIReadDir()                             */
@@ -326,9 +326,13 @@ int VSIIsCaseSensitiveFS( const char * pszFilename )
  * than 2GB) should be supported.  Binary access is always implied and
  * the "b" does not need to be included in the pszAccess string.
  *
- * Note that the "VSILFILE *" returned since GDAL 1.8.0 by this function is *NOT* a
- * standard C library FILE *, and cannot be used with any functions other
- * than the "VSI*L" family of functions.  They aren't "real" FILE objects.
+ * Note that the "VSILFILE *" returned since GDAL 1.8.0 by this function is 
+ * *NOT* a standard C library FILE *, and cannot be used with any functions 
+ * other than the "VSI*L" family of functions.  They aren't "real" FILE objects.
+ *
+ * On windows it is possible to define the configuration option 
+ * GDAL_FILE_IS_UTF8 to have pszFilename treated as being in the local
+ * encoding instead of UTF-8, retoring the pre-1.8.0 behavior of VSIFOpenL().
  *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
@@ -514,6 +518,43 @@ size_t VSIFReadL( void * pBuffer, size_t nSize, size_t nCount, VSILFILE * fp )
     return poFileHandle->Read( pBuffer, nSize, nCount );
 }
 
+
+/************************************************************************/
+/*                       VSIFReadMultiRangeL()                          */
+/************************************************************************/
+
+/**
+ * \brief Read several ranges of bytes from file.
+ *
+ * Reads nRanges objects of panSizes[i] bytes from the indicated file at the
+ * offset panOffsets[i] into the buffer ppData[i].
+ *
+ * Ranges must be sorted in ascending start offset, and must not overlap each
+ * other.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory or /vsicurl/.
+ *
+ * @param nRanges number of ranges to read.
+ * @param ppData array of nRanges buffer into which the data should be read
+ *               (ppData[i] must be at list panSizes[i] bytes).
+ * @param panOffsets array of nRanges offsets at which the data should be read.
+ * @param panSizes array of nRanges sizes of objects to read (in bytes).
+ * @param fp file handle opened with VSIFOpenL().
+ *
+ * @return 0 in case of success, -1 otherwise.
+ * @since GDAL 1.9.0
+ */
+
+int VSIFReadMultiRangeL( int nRanges, void ** ppData,
+                         const vsi_l_offset* panOffsets,
+                         const size_t* panSizes, VSILFILE * fp )
+{
+    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
+
+    return poFileHandle->ReadMultiRange( nRanges, ppData, panOffsets, panSizes );
+}
+
 /************************************************************************/
 /*                             VSIFWriteL()                             */
 /************************************************************************/
@@ -553,8 +594,9 @@ size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *f
 /**
  * \brief Test for end of file.
  *
- * Returns TRUE (non-zero) if the file read/write offset is currently at the
- * end of the file. 
+ * Returns TRUE (non-zero) if an end-of-file condition occured during the
+ * previous read operation. The end-of-file flag is cleared by a successfull
+ * VSIFSeekL() call.
  *
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
@@ -575,6 +617,33 @@ int VSIFEofL( VSILFILE * fp )
 }
 
 /************************************************************************/
+/*                            VSIFTruncateL()                           */
+/************************************************************************/
+
+/**
+ * \brief Truncate/expand the file to the specified size
+
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX ftruncate() call.
+ *
+ * @param fp file handle opened with VSIFOpenL().
+ * @param nNewSize new size in bytes.
+ *
+ * @return 0 on success
+ * @since GDAL 1.9.0
+ */
+
+int VSIFTruncateL( VSILFILE * fp, vsi_l_offset nNewSize )
+
+{
+    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
+
+    return poFileHandle->Truncate(nNewSize);
+}
+
+/************************************************************************/
 /*                            VSIFPrintfL()                             */
 /************************************************************************/
 
@@ -754,3 +823,34 @@ void VSICleanupFileManager()
         poManager = NULL;
     }
 }
+
+/************************************************************************/
+/*                           ReadMultiRange()                           */
+/************************************************************************/
+
+int VSIVirtualHandle::ReadMultiRange( int nRanges, void ** ppData,
+                                      const vsi_l_offset* panOffsets,
+                                      const size_t* panSizes )
+{
+    int nRet = 0;
+    vsi_l_offset nCurOffset = Tell();
+    for(int i=0;i<nRanges;i++)
+    {
+        if (Seek(panOffsets[i], SEEK_SET) < 0)
+        {
+            nRet = -1;
+            break;
+        }
+
+        size_t nRead = Read(ppData[i], 1, panSizes[i]);
+        if (panSizes[i] != nRead)
+        {
+            nRet = -1;
+            break;
+        }
+    }
+
+    Seek(nCurOffset, SEEK_SET);
+
+    return nRet;
+}
diff --git a/port/cpl_vsil_abstract_archive.cpp b/port/cpl_vsil_abstract_archive.cpp
index c897cd7..3c6b962 100644
--- a/port/cpl_vsil_abstract_archive.cpp
+++ b/port/cpl_vsil_abstract_archive.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_abstract_archive.cpp 20958 2010-10-25 19:24:01Z rouault $
+ * $Id: cpl_vsil_abstract_archive.cpp 22980 2011-08-25 22:29:12Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for archive files.
@@ -35,7 +35,7 @@
 
 #define ENABLE_DEBUG 0
 
-CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 20958 2010-10-25 19:24:01Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 22980 2011-08-25 22:29:12Z rouault $");
 
 /************************************************************************/
 /*                    ~VSIArchiveEntryFileOffset()                      */
@@ -130,6 +130,14 @@ const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
         CPLString osFileName = poReader->GetFileName();
         const char* fileName = osFileName.c_str();
 
+        /* Remove ./ pattern at the beginning of a filename */
+        if (fileName[0] == '.' && fileName[1] == '/')
+        {
+            fileName += 2;
+            if (fileName[0] == '\0')
+                continue;
+        }
+
         char* pszStrippedFileName = CPLStrdup(fileName);
         int bIsDir = strlen(fileName) > 0 &&
                       (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\');
diff --git a/port/cpl_vsil_buffered_reader.cpp b/port/cpl_vsil_buffered_reader.cpp
index 88d8f3f..506813a 100644
--- a/port/cpl_vsil_buffered_reader.cpp
+++ b/port/cpl_vsil_buffered_reader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_buffered_reader.cpp 21358 2010-12-31 17:28:26Z rouault $
+ * $Id: cpl_vsil_buffered_reader.cpp 22109 2011-04-03 18:39:59Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of buffered reader IO functions.
@@ -37,7 +37,7 @@
 
 #define MAX_BUFFER_SIZE 65536
 
-CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 21358 2010-12-31 17:28:26Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 22109 2011-04-03 18:39:59Z rouault $");
 
 class VSIBufferedReaderHandle : public VSIVirtualHandle
 {
@@ -47,6 +47,7 @@ class VSIBufferedReaderHandle : public VSIVirtualHandle
     int               nBufferSize;
     GUIntBig          nCurOffset;
     int               bNeedBaseHandleSeek;
+    int               bEOF;
 
   public:
 
@@ -82,6 +83,7 @@ VSIBufferedReaderHandle::VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle)
     nBufferSize = 0;
     nCurOffset = 0;
     bNeedBaseHandleSeek = FALSE;
+    bEOF = FALSE;
 }
 
 /************************************************************************/
@@ -100,6 +102,7 @@ VSIBufferedReaderHandle::~VSIBufferedReaderHandle()
 int VSIBufferedReaderHandle::Seek( vsi_l_offset nOffset, int nWhence )
 {
     //CPLDebug( "BUFFERED", "Seek(%d,%d)", (int)nOffset, (int)nWhence);
+    bEOF = FALSE;
     if (nWhence == SEEK_CUR)
         nCurOffset += nOffset;
     else if (nWhence == SEEK_END)
@@ -162,6 +165,8 @@ size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb
             //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize);
             //CPLAssert(poBaseHandle->Tell() == nCurOffset);
 
+            bEOF = poBaseHandle->Eof();
+
             return nRead / nSize;
         }
         else
@@ -185,6 +190,8 @@ size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb
         //CPLAssert(poBaseHandle->Tell() == nBufferOffset + nBufferSize);
         //CPLAssert(poBaseHandle->Tell() == nCurOffset);
 
+        bEOF = poBaseHandle->Eof();
+
         return nReadInFile / nSize;
     }
 
@@ -208,7 +215,7 @@ size_t VSIBufferedReaderHandle::Write( const void *pBuffer, size_t nSize, size_t
 
 int VSIBufferedReaderHandle::Eof()
 {
-    return poBaseHandle->Eof();
+    return bEOF;
 }
 
 /************************************************************************/
diff --git a/port/cpl_vsil_cache.cpp b/port/cpl_vsil_cache.cpp
new file mode 100644
index 0000000..fbb4528
--- /dev/null
+++ b/port/cpl_vsil_cache.cpp
@@ -0,0 +1,474 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  VSI Virtual File System
+ * Purpose:  Implementation of caching IO layer.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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 "cpl_vsi_virtual.h"
+
+CPL_CVSID("$Id$");
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             VSICacheChunk                            */
+/* ==================================================================== */
+/************************************************************************/
+
+#define CHUNK_SIZE  32768
+
+class VSICacheChunk
+{
+public:
+    VSICacheChunk() { 
+        poLRUPrev = poLRUNext = NULL;
+        nDataFilled = 0;
+        bDirty = FALSE;
+    }
+
+    int            bDirty;
+    size_t         iBlock;
+
+    VSICacheChunk *poLRUPrev;
+    VSICacheChunk *poLRUNext;
+
+    vsi_l_offset   nDataFilled;
+    GByte          abyData[CHUNK_SIZE];
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             VSICachedFile                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class VSICachedFile : public VSIVirtualHandle
+{ 
+  public:
+    VSICachedFile( VSIVirtualHandle * );
+    ~VSICachedFile() { Close(); }
+
+    void          FlushLRU();
+    int           LoadBlocks( size_t nStartBlock, size_t nBlockCount, 
+                              void *pBuffer, size_t nBufferSize );
+    void          Demote( VSICacheChunk * );
+
+    VSIVirtualHandle *poBase;
+    
+    vsi_l_offset  nOffset;
+    vsi_l_offset  nFileSize;
+
+    GUIntBig      nCacheUsed;
+    GUIntBig      nCacheMax;
+
+    VSICacheChunk *poLRUStart;
+    VSICacheChunk *poLRUEnd;
+
+    std::vector<VSICacheChunk*> apoCache;
+
+    int            bEOF;
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
+    virtual vsi_l_offset Tell();
+    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
+    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
+    virtual int       Eof();
+    virtual int       Flush();
+    virtual int       Close();
+};
+
+/************************************************************************/
+/*                           VSICachedFile()                            */
+/************************************************************************/
+
+VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle )
+
+{
+    poBase = poBaseHandle;
+
+    nCacheUsed = 0;
+    nCacheMax = CPLScanUIntBig( 
+        CPLGetConfigOption( "VSI_CACHE_SIZE", "25000000" ), 40 );
+
+    poLRUStart = NULL;
+    poLRUEnd = NULL;
+
+    poBase->Seek( 0, SEEK_END );
+    nFileSize = poBase->Tell();
+
+    nOffset = 0;
+    bEOF = FALSE;
+}
+
+/************************************************************************/
+/*                               Close()                                */
+/************************************************************************/
+
+int VSICachedFile::Close()
+
+{
+    size_t i;
+    for( i = 0; i < apoCache.size(); i++ )
+        delete apoCache[i];
+
+    apoCache.resize( 0 );
+
+    poLRUStart = NULL;
+    poLRUEnd = NULL;
+
+    nCacheUsed = 0;
+
+    if( poBase )
+    {
+        poBase->Close();
+        delete poBase;
+        poBase = NULL;
+    }
+
+    return 0;
+}
+
+/************************************************************************/
+/*                                Seek()                                */
+/************************************************************************/
+
+int VSICachedFile::Seek( vsi_l_offset nReqOffset, int nWhence )
+
+{
+    bEOF = FALSE;
+
+    if( nWhence == SEEK_SET )
+    {
+        // use offset directly.
+    }
+
+    else if( nWhence == SEEK_CUR )
+    {
+        nReqOffset += nOffset;
+    }
+
+    else if( nWhence == SEEK_END )
+    {
+        nReqOffset += nFileSize;
+    }
+
+    nOffset = nReqOffset;
+
+    return 0;
+}
+
+/************************************************************************/
+/*                                Tell()                                */
+/************************************************************************/
+
+vsi_l_offset VSICachedFile::Tell()
+
+{
+    return nOffset;
+}
+
+/************************************************************************/
+/*                              FlushLRU()                              */
+/************************************************************************/
+
+void VSICachedFile::FlushLRU()
+
+{
+    CPLAssert( poLRUStart != NULL );
+
+    VSICacheChunk *poBlock = poLRUStart;
+
+    CPLAssert( nCacheUsed >= poBlock->nDataFilled );
+
+    nCacheUsed -= poBlock->nDataFilled;
+    
+    poLRUStart = poBlock->poLRUNext;
+    if( poLRUEnd == poBlock )
+        poLRUEnd = NULL;
+
+    if( poBlock->poLRUNext != NULL )
+        poBlock->poLRUNext->poLRUPrev = NULL;
+
+    CPLAssert( !poBlock->bDirty );
+
+    apoCache[poBlock->iBlock] = NULL;
+
+    delete poBlock;
+}
+
+/************************************************************************/
+/*                               Demote()                               */
+/*                                                                      */
+/*      Demote the indicated block to the end of the LRU list.          */
+/*      Potentially integrate the link into the list if it is not       */
+/*      already there.                                                  */
+/************************************************************************/
+
+void VSICachedFile::Demote( VSICacheChunk *poBlock )
+
+{
+    // already at end?
+    if( poLRUEnd == poBlock )
+        return;
+    
+    if( poLRUStart == poBlock )
+        poLRUStart = poBlock->poLRUNext;
+
+    if( poBlock->poLRUPrev != NULL )
+        poBlock->poLRUPrev->poLRUNext = poBlock->poLRUNext;
+
+    if( poBlock->poLRUNext != NULL )
+        poBlock->poLRUNext->poLRUPrev = poBlock->poLRUPrev;
+
+    poBlock->poLRUNext = NULL;
+    poBlock->poLRUPrev = NULL;
+
+    if( poLRUEnd != NULL )
+        poLRUEnd->poLRUNext = poBlock;
+    poLRUEnd = poBlock;
+    
+    if( poLRUStart == NULL )
+        poLRUStart = poBlock;
+}
+
+/************************************************************************/
+/*                             LoadBlocks()                             */
+/*                                                                      */
+/*      Load the desired set of blocks.  Use pBuffer as a temporary     */
+/*      buffer if it would be helpful.                                  */
+/************************************************************************/
+
+int VSICachedFile::LoadBlocks( size_t nStartBlock, size_t nBlockCount,
+                               void *pBuffer, size_t nBufferSize )
+
+{
+    if( nBlockCount == 0 )
+        return 1;
+
+    if( apoCache.size() < nStartBlock + nBlockCount )
+        apoCache.resize( nStartBlock + nBlockCount );
+
+/* -------------------------------------------------------------------- */
+/*      When we want to load only one block, we can directly load it    */
+/*      into the target buffer with no concern about intermediaries.    */
+/* -------------------------------------------------------------------- */
+    if( nBlockCount == 1 )
+    {
+        poBase->Seek( nStartBlock * CHUNK_SIZE, SEEK_SET );
+
+        apoCache[nStartBlock] = new VSICacheChunk();
+
+        VSICacheChunk *poBlock = apoCache[nStartBlock];
+
+        poBlock->iBlock = nStartBlock;
+        poBlock->nDataFilled = poBase->Read( poBlock->abyData, 1, CHUNK_SIZE );
+        nCacheUsed += poBlock->nDataFilled;
+
+        // Merges into the LRU list. 
+        Demote( poBlock );
+
+        return 1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If the buffer is quite large but not quite large enough to      */
+/*      hold all the blocks we will take the pain of splitting the      */
+/*      io request in two in order to avoid allocating a large          */
+/*      temporary buffer.                                               */
+/* -------------------------------------------------------------------- */
+    if( nBufferSize > CHUNK_SIZE * 20 
+        && nBufferSize < nBlockCount * CHUNK_SIZE )
+    {
+        if( !LoadBlocks( nStartBlock, 2, pBuffer, nBufferSize ) )
+            return 0;
+
+        return LoadBlocks( nStartBlock+2, nBlockCount-2, pBuffer, nBufferSize );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we need to allocate our own buffer?                          */
+/* -------------------------------------------------------------------- */
+    GByte *pabyWorkBuffer = (GByte *) pBuffer;
+
+    if( nBufferSize < CHUNK_SIZE * nBlockCount )
+        pabyWorkBuffer = (GByte *) CPLMalloc(CHUNK_SIZE * nBlockCount);
+
+/* -------------------------------------------------------------------- */
+/*      Read the whole request into the working buffer.                 */
+/* -------------------------------------------------------------------- */
+    if( poBase->Seek( nStartBlock * CHUNK_SIZE, SEEK_SET ) != 0 )
+        return 0;
+
+    size_t nDataRead = poBase->Read( pabyWorkBuffer, 1, nBlockCount*CHUNK_SIZE);
+
+    if( nBlockCount * CHUNK_SIZE > nDataRead + CHUNK_SIZE - 1 )
+        nBlockCount = (nDataRead + CHUNK_SIZE - 1) / CHUNK_SIZE;
+
+    for( size_t i = 0; i < nBlockCount; i++ )
+    {
+        VSICacheChunk *poBlock = new VSICacheChunk();
+
+        poBlock->iBlock = nStartBlock + i;
+
+        CPLAssert( apoCache[i+nStartBlock] == NULL );
+
+        apoCache[i + nStartBlock] = poBlock;
+
+        if( nDataRead >= (i+1) * CHUNK_SIZE )
+            poBlock->nDataFilled = CHUNK_SIZE;
+        else
+            poBlock->nDataFilled = nDataRead - i*CHUNK_SIZE;
+
+        memcpy( poBlock->abyData, pabyWorkBuffer + i*CHUNK_SIZE,
+                (size_t) poBlock->nDataFilled );
+
+        nCacheUsed += poBlock->nDataFilled;
+
+        // Merges into the LRU list. 
+        Demote( poBlock );
+    }
+
+    if( pabyWorkBuffer != pBuffer )
+        CPLFree( pabyWorkBuffer );
+
+    return 1;
+}
+
+/************************************************************************/
+/*                                Read()                                */
+/************************************************************************/
+
+size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
+
+{
+    if( nOffset >= nFileSize )
+    {
+        bEOF = TRUE;
+        return 0;
+    }
+
+/* ==================================================================== */
+/*      Make sure the cache is loaded for the whole request region.     */
+/* ==================================================================== */
+    size_t nStartBlock = (size_t) (nOffset / CHUNK_SIZE);
+    size_t nEndBlock = (size_t) ((nOffset + nSize * nCount - 1) / CHUNK_SIZE);
+    
+    for( size_t iBlock = nStartBlock; iBlock <= nEndBlock; iBlock++ )
+    {
+        if( apoCache.size() <= iBlock || apoCache[iBlock] == NULL )
+        {
+            size_t nBlocksToLoad = 1;
+            while( iBlock + nBlocksToLoad <= nEndBlock
+                   && (apoCache.size() <= iBlock+nBlocksToLoad 
+                       || apoCache[iBlock+nBlocksToLoad] == NULL) )
+                nBlocksToLoad++;
+
+            LoadBlocks( iBlock, nBlocksToLoad, pBuffer, nSize * nCount );
+        }
+    }
+    
+/* ==================================================================== */
+/*      Copy data into the target buffer to the extent possible.        */
+/* ==================================================================== */
+    size_t nAmountCopied = 0;
+
+    while( nAmountCopied < nSize * nCount )
+    {
+        size_t iBlock = (size_t) ((nOffset + nAmountCopied) / CHUNK_SIZE);
+        size_t nThisCopy;
+        VSICacheChunk *poBlock = apoCache[iBlock];
+
+        nThisCopy = (size_t)
+            ((iBlock * CHUNK_SIZE + poBlock->nDataFilled) 
+             - nAmountCopied - nOffset);
+        
+        if( nThisCopy > nSize * nCount - nAmountCopied )
+            nThisCopy = nSize * nCount - nAmountCopied;
+
+        if( nThisCopy == 0 )
+            break;
+
+        memcpy( ((GByte *) pBuffer) + nAmountCopied,
+                poBlock->abyData 
+                + (nOffset + nAmountCopied) - iBlock * CHUNK_SIZE, 
+                nThisCopy );
+
+        nAmountCopied += nThisCopy;
+    }
+    
+    nOffset += nAmountCopied;
+
+/* -------------------------------------------------------------------- */
+/*      Ensure the cache is reduced to our limit.                       */
+/* -------------------------------------------------------------------- */
+    while( nCacheUsed > nCacheMax )
+        FlushLRU();
+
+    size_t nRet = nAmountCopied / nSize;
+    if (nRet != nCount)
+        bEOF = TRUE;
+    return nRet;
+}
+
+/************************************************************************/
+/*                               Write()                                */
+/************************************************************************/
+
+size_t VSICachedFile::Write( const void * pBuffer, size_t nSize, size_t nCount )
+
+{
+    return 0;
+}
+
+/************************************************************************/
+/*                                Eof()                                 */
+/************************************************************************/
+
+int VSICachedFile::Eof()
+
+{
+    return bEOF;
+}
+
+/************************************************************************/
+/*                               Flush()                                */
+/************************************************************************/
+
+int VSICachedFile::Flush()
+
+{
+    return 0;
+}
+
+/************************************************************************/
+/*                        VSICreateCachedFile()                         */
+/************************************************************************/
+
+VSIVirtualHandle *
+VSICreateCachedFile( VSIVirtualHandle *poBaseHandle )
+
+{
+    return new VSICachedFile( poBaseHandle );
+}
diff --git a/port/cpl_vsil_curl.cpp b/port/cpl_vsil_curl.cpp
index 7391902..90a80b0 100644
--- a/port/cpl_vsil_curl.cpp
+++ b/port/cpl_vsil_curl.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl_vsil_curl.cpp 23506 2011-12-10 13:43:59Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files
@@ -31,8 +31,9 @@
 #include "cpl_string.h"
 #include "cpl_multiproc.h"
 #include "cpl_hash_set.h"
+#include "cpl_time.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl.cpp 23506 2011-12-10 13:43:59Z rouault $");
 
 #ifndef HAVE_CURL
 
@@ -66,6 +67,7 @@ typedef struct
     int             bHastComputedFileSize;
     vsi_l_offset    fileSize;
     int             bIsDirectory;
+    time_t          mTime;
 } CachedFileProp;
 
 typedef struct
@@ -88,7 +90,12 @@ static const char* VSICurlGetCacheFileName()
     return "gdal_vsicurl_cache.bin";
 }
 
-static int CSLFindStringSensitive( char ** papszList, const char * pszTarget )
+/************************************************************************/
+/*          VSICurlFindStringSensitiveExceptEscapeSequences()           */
+/************************************************************************/
+
+static int VSICurlFindStringSensitiveExceptEscapeSequences( char ** papszList,
+                                                            const char * pszTarget )
 
 {
     int         i;
@@ -98,7 +105,33 @@ static int CSLFindStringSensitive( char ** papszList, const char * pszTarget )
 
     for( i = 0; papszList[i] != NULL; i++ )
     {
-        if( strcmp(papszList[i],pszTarget) == 0 )
+        const char* pszIter1 = papszList[i];
+        const char* pszIter2 = pszTarget;
+        char ch1, ch2;
+        /* The comparison is case-sensitive, escape for escaped */
+        /* sequences where letters of the hexadecimal sequence */
+        /* can be uppercase or lowercase depending on the quoting algorithm */
+        while(TRUE)
+        {
+            ch1 = *pszIter1;
+            ch2 = *pszIter2;
+            if (ch1 == '\0' || ch2 == '\0')
+                break;
+            if (ch1 == '%' && ch2 == '%' &&
+                pszIter1[1] != '\0' && pszIter1[2] != '\0' &&
+                pszIter2[1] != '\0' && pszIter2[2] != '\0')
+            {
+                if (!EQUALN(pszIter1+1, pszIter2+1, 2))
+                    break;
+                pszIter1 += 2;
+                pszIter2 += 2;
+            }
+            if (ch1 != ch2)
+                break;
+            pszIter1 ++;
+            pszIter2 ++;
+        }
+        if (ch1 == ch2 && ch1 == '\0')
             return i;
     }
 
@@ -106,9 +139,35 @@ static int CSLFindStringSensitive( char ** papszList, const char * pszTarget )
 }
 
 /************************************************************************/
+/*                      VSICurlIsFileInList()                           */
+/************************************************************************/
+
+static int VSICurlIsFileInList( char ** papszList, const char * pszTarget )
+{
+    int nRet = VSICurlFindStringSensitiveExceptEscapeSequences(papszList, pszTarget);
+    if (nRet >= 0)
+        return nRet;
+
+    /* If we didn't find anything, try to URL-escape the target filename */
+    char* pszEscaped = CPLEscapeString(pszTarget, -1, CPLES_URL);
+    if (strcmp(pszTarget, pszEscaped) != 0)
+    {
+        nRet = VSICurlFindStringSensitiveExceptEscapeSequences(papszList, pszEscaped);
+    }
+    CPLFree(pszEscaped);
+    return nRet;
+}
+
+/************************************************************************/
 /*                     VSICurlFilesystemHandler                         */
 /************************************************************************/
 
+typedef struct
+{
+    CPLString       osURL;
+    CURL           *hCurlHandle;
+} CachedConnection;
+
 
 class VSICurlFilesystemHandler : public VSIFilesystemHandler 
 {
@@ -117,11 +176,19 @@ class VSICurlFilesystemHandler : public VSIFilesystemHandler
     CachedRegion  **papsRegions;
     int             nRegions;
 
-    std::map<unsigned long, CachedFileProp*>   cacheFileSize;
+    std::map<CPLString, CachedFileProp*>   cacheFileSize;
     std::map<CPLString, CachedDirList*>        cacheDirList;
 
     int             bUseCacheDisk;
 
+    /* Per-thread Curl connection cache */
+    std::map<GIntBig, CachedConnection*> mapConnections;
+
+    char** GetFileList(const char *pszFilename, int* pbGotFileList);
+
+    char**              ParseHTMLFileList(const char* pszFilename,
+                                          char* pszData,
+                                          int* pbGotFileList);
 public:
     VSICurlFilesystemHandler();
     ~VSICurlFilesystemHandler();
@@ -150,6 +217,8 @@ public:
     void                AddRegionToCacheDisk(CachedRegion* psRegion);
     const CachedRegion* GetRegionFromCacheDisk(const char*     pszURL,
                                                vsi_l_offset nFileOffsetStart);
+
+    CURL               *GetCurlHandleFor(CPLString osURL);
 };
 
 /************************************************************************/
@@ -169,8 +238,7 @@ class VSICurlHandle : public VSIVirtualHandle
     int             bHastComputedFileSize;
     ExistStatus     eExists;
     int             bIsDirectory;
-    
-    CURL*           hCurlHandle;
+    time_t          mTime;
 
     vsi_l_offset    lastDownloadedOffset;
     int             nBlocksToDownload;
@@ -186,14 +254,18 @@ class VSICurlHandle : public VSIVirtualHandle
     virtual int          Seek( vsi_l_offset nOffset, int nWhence );
     virtual vsi_l_offset Tell();
     virtual size_t       Read( void *pBuffer, size_t nSize, size_t nMemb );
+    virtual int          ReadMultiRange( int nRanges, void ** ppData,
+                                         const vsi_l_offset* panOffsets, const size_t* panSizes );
     virtual size_t       Write( const void *pBuffer, size_t nSize, size_t nMemb );
     virtual int          Eof();
     virtual int          Flush();
     virtual int          Close();
 
+    int                  IsKnownFileSize() const { return bHastComputedFileSize; }
     vsi_l_offset         GetFileSize();
     int                  Exists();
-    int                  IsDirectory() { return bIsDirectory; }
+    int                  IsDirectory() const { return bIsDirectory; }
+    time_t               GetMTime() const { return mTime; }
 };
 
 /************************************************************************/
@@ -206,20 +278,13 @@ VSICurlHandle::VSICurlHandle(VSICurlFilesystemHandler* poFS, const char* pszURL)
     this->pszURL = CPLStrdup(pszURL);
 
     curOffset = 0;
-    fileSize = 0;
-    bHastComputedFileSize = FALSE;
-    eExists = EXIST_UNKNOWN;
-    bIsDirectory = FALSE;
-    hCurlHandle = NULL;
 
     CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-    if (cachedFileProp)
-    {
-        eExists = cachedFileProp->eExists;
-        fileSize = cachedFileProp->fileSize;
-        bHastComputedFileSize = cachedFileProp->bHastComputedFileSize;
-        bIsDirectory = cachedFileProp->bIsDirectory;
-    }
+    eExists = cachedFileProp->eExists;
+    fileSize = cachedFileProp->fileSize;
+    bHastComputedFileSize = cachedFileProp->bHastComputedFileSize;
+    bIsDirectory = cachedFileProp->bIsDirectory;
+    mTime = cachedFileProp->mTime;
 
     lastDownloadedOffset = -1;
     nBlocksToDownload = 1;
@@ -233,8 +298,6 @@ VSICurlHandle::VSICurlHandle(VSICurlFilesystemHandler* poFS, const char* pszURL)
 VSICurlHandle::~VSICurlHandle()
 {
     CPLFree(pszURL);
-    if (hCurlHandle)
-        curl_easy_cleanup(hCurlHandle );
 }
 
 
@@ -247,18 +310,16 @@ int VSICurlHandle::Seek( vsi_l_offset nOffset, int nWhence )
     if (nWhence == SEEK_SET)
     {
         curOffset = nOffset;
-        bEOF = FALSE;
     }
     else if (nWhence == SEEK_CUR)
     {
         curOffset = curOffset + nOffset;
-        bEOF = FALSE;
     }
     else
     {
         curOffset = GetFileSize() + nOffset;
-        bEOF = TRUE;
     }
+    bEOF = FALSE;
     return 0;
 }
 
@@ -306,6 +367,19 @@ static void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL)
     curl_easy_setopt(hCurlHandle, CURLOPT_NOSIGNAL, 1);
 #endif
 
+    curl_easy_setopt(hCurlHandle, CURLOPT_NOBODY, 0);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 1); 
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADER, 0);
+
+/* 7.16.4 */
+#if LIBCURL_VERSION_NUM <= 0x071004
+    curl_easy_setopt(hCurlHandle, CURLOPT_FTPLISTONLY, 0);
+#elif LIBCURL_VERSION_NUM > 0x071004
+    curl_easy_setopt(hCurlHandle, CURLOPT_DIRLISTONLY, 0);
+#endif
+
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
 }
 
 
@@ -313,6 +387,15 @@ typedef struct
 {
     char*           pBuffer;
     size_t          nSize;
+    int             bIsHTTP;
+    int             bIsInHeader;
+    int             bMultiRange;
+    vsi_l_offset    nStartOffset;
+    vsi_l_offset    nEndOffset;
+    int             nHTTPCode;
+    vsi_l_offset    nContentLength;
+    int             bFoundContentRange;
+    int             bError;
 } WriteFuncStruct;
 
 /************************************************************************/
@@ -323,6 +406,15 @@ static void VSICURLInitWriteFuncStruct(WriteFuncStruct* psStruct)
 {
     psStruct->pBuffer = NULL;
     psStruct->nSize = 0;
+    psStruct->bIsHTTP = FALSE;
+    psStruct->bIsInHeader = TRUE;
+    psStruct->bMultiRange = FALSE;
+    psStruct->nStartOffset = 0;
+    psStruct->nEndOffset = 0;
+    psStruct->nHTTPCode = 0;
+    psStruct->nContentLength = 0;
+    psStruct->bFoundContentRange = FALSE;
+    psStruct->bError = FALSE;
 }
 
 /************************************************************************/
@@ -334,12 +426,51 @@ static int VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void
     WriteFuncStruct* psStruct = (WriteFuncStruct*) req;
     size_t nSize = count * nmemb;
 
-    char* pNewBuffer = (char*) VSIRealloc(psStruct->pBuffer, psStruct->nSize + nSize + 1);
+    char* pNewBuffer = (char*) VSIRealloc(psStruct->pBuffer,
+                                          psStruct->nSize + nSize + 1);
     if (pNewBuffer)
     {
         psStruct->pBuffer = pNewBuffer;
         memcpy(psStruct->pBuffer + psStruct->nSize, buffer, nSize);
         psStruct->pBuffer[psStruct->nSize + nSize] = '\0';
+        if (psStruct->bIsHTTP && psStruct->bIsInHeader)
+        {
+            char* pszLine = psStruct->pBuffer + psStruct->nSize;
+            if (EQUALN(pszLine, "HTTP/1.0 ", 9) ||
+                EQUALN(pszLine, "HTTP/1.1 ", 9))
+                psStruct->nHTTPCode = atoi(pszLine + 9);
+            else if (EQUALN(pszLine, "Content-Length: ", 16))
+                psStruct->nContentLength = CPLScanUIntBig(pszLine + 16,
+                                                          strlen(pszLine + 16));
+            else if (EQUALN(pszLine, "Content-Range: ", 15))
+                psStruct->bFoundContentRange = TRUE;
+
+            /*if (nSize > 2 && pszLine[nSize - 2] == '\r' &&
+                pszLine[nSize - 1] == '\n')
+            {
+                pszLine[nSize - 2] = 0;
+                CPLDebug("VSICURL", "%s", pszLine);
+                pszLine[nSize - 2] = '\r';
+            }*/
+
+            if (pszLine[0] == '\r' || pszLine[0] == '\n')
+            {
+                psStruct->bIsInHeader = FALSE;
+
+                /* Detect servers that don't support range downloading */
+                if (psStruct->nHTTPCode == 200 &&
+                    !psStruct->bMultiRange &&
+                    !psStruct->bFoundContentRange &&
+                    (psStruct->nStartOffset != 0 || psStruct->nContentLength > 10 *
+                        (psStruct->nEndOffset - psStruct->nStartOffset + 1)))
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Range downloading not supported by this server !");
+                    psStruct->bError = TRUE;
+                    return 0;
+                }
+            }
+        }
         psStruct->nSize += nSize;
         return nmemb;
     }
@@ -363,20 +494,78 @@ vsi_l_offset VSICurlHandle::GetFileSize()
 
     bHastComputedFileSize = TRUE;
 
-    CURL* hCurlHandle = curl_easy_init();
+    /* Consider that only the files whose extension ends up with one that is */
+    /* listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server */
+    /* This can speeds up dramatically open experience, in case the server */
+    /* cannot return a file list */
+    /* For example : */
+    /* gdalinfo --config CPL_VSIL_CURL_ALLOWED_EXTENSIONS ".tif" /vsicurl/http://igskmncngs506.cr.usgs.gov/gmted/Global_tiles_GMTED/075darcsec/bln/W030/30N030W_20101117_gmted_bln075.tif */
+    const char* pszAllowedExtensions =
+        CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", NULL);
+    if (pszAllowedExtensions)
+    {
+        char** papszExtensions = CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
+        int nURLLen = strlen(pszURL);
+        int bFound = FALSE;
+        for(int i=0;papszExtensions[i] != NULL;i++)
+        {
+            int nExtensionLen = strlen(papszExtensions[i]);
+            if (nURLLen > nExtensionLen &&
+                EQUAL(pszURL + nURLLen - nExtensionLen, papszExtensions[i]))
+            {
+                bFound = TRUE;
+                break;
+            }
+        }
+
+        if (!bFound)
+        {
+            eExists = EXIST_NO;
+            fileSize = 0;
+
+            CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+            cachedFileProp->bHastComputedFileSize = TRUE;
+            cachedFileProp->fileSize = fileSize;
+            cachedFileProp->eExists = eExists;
+
+            CSLDestroy(papszExtensions);
+
+            return 0;
+        }
+
+        CSLDestroy(papszExtensions);
+    }
+
+#if LIBCURL_VERSION_NUM < 0x070B00
+    /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
+    /* previously set, so we have to reinit the connection handle */
+    poFS->GetCurlHandleFor("");
+#endif
+    CURL* hCurlHandle = poFS->GetCurlHandleFor(pszURL);
 
     VSICurlSetOptions(hCurlHandle, pszURL);
     curl_easy_setopt(hCurlHandle, CURLOPT_NOBODY, 1);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 0); 
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADER, 1);
 
+    /* We need that otherwise OSGEO4W's libcurl issue a dummy range request */
+    /* when doing a HEAD when recycling connections */
+    curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
+
     /* Bug with older curl versions (<=7.16.4) and FTP. See http://curl.haxx.se/mail/lib-2007-08/0312.html */
     VSICURLInitWriteFuncStruct(&sWriteFuncData);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
 
+    char szCurlErrBuf[CURL_ERROR_SIZE+1];
+    szCurlErrBuf[0] = '\0';
+    curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
+
     double dfSize = 0;
     curl_easy_perform(hCurlHandle);
 
+    eExists = EXIST_UNKNOWN;
+
     if (strncmp(pszURL, "ftp", 3) == 0)
     {
         if (sWriteFuncData.pBuffer != NULL &&
@@ -442,8 +631,6 @@ vsi_l_offset VSICurlHandle::GetFileSize()
     cachedFileProp->eExists = eExists;
     cachedFileProp->bIsDirectory = bIsDirectory;
 
-    curl_easy_cleanup(hCurlHandle );
-
     return fileSize;
 }
 
@@ -480,11 +667,8 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
     if (cachedFileProp->eExists == EXIST_NO)
         return FALSE;
 
-    if ( hCurlHandle == NULL)
-    {
-        hCurlHandle = curl_easy_init();
-        VSICurlSetOptions(hCurlHandle, pszURL);
-    }
+    CURL* hCurlHandle = poFS->GetCurlHandleFor(pszURL);
+    VSICurlSetOptions(hCurlHandle, pszURL);
 
     VSICURLInitWriteFuncStruct(&sWriteFuncData);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
@@ -493,6 +677,9 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
+    sWriteFuncHeaderData.bIsHTTP = strncmp(pszURL, "http", 4) == 0;
+    sWriteFuncHeaderData.nStartOffset = startOffset;
+    sWriteFuncHeaderData.nEndOffset = startOffset + nBlocks * DOWNLOAD_CHUNCK_SIZE - 1;
 
     char rangeStr[512];
     sprintf(rangeStr, CPL_FRMT_GUIB "-" CPL_FRMT_GUIB, startOffset, startOffset + nBlocks * DOWNLOAD_CHUNCK_SIZE - 1);
@@ -502,6 +689,10 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
 
     curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, rangeStr);
 
+    char szCurlErrBuf[CURL_ERROR_SIZE+1];
+    szCurlErrBuf[0] = '\0';
+    curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
+
     curl_easy_perform(hCurlHandle);
 
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, NULL);
@@ -515,12 +706,27 @@ int VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks)
     char *content_type = 0;
     curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_TYPE, &content_type);
 
-    if (response_code != 200 && response_code != 206 &&
-        response_code != 226 && response_code != 426)
+    if (ENABLE_DEBUG)
+        CPLDebug("VSICURL", "Got reponse_code=%ld", response_code);
+
+    if ((response_code != 200 && response_code != 206 &&
+         response_code != 225 && response_code != 226 && response_code != 426) || sWriteFuncHeaderData.bError)
     {
-        bHastComputedFileSize = cachedFileProp->bHastComputedFileSize = TRUE;
-        cachedFileProp->fileSize = 0;
-        cachedFileProp->eExists = EXIST_NO;
+        if (response_code >= 400 && szCurlErrBuf[0] != '\0')
+        {
+            if (strcmp(szCurlErrBuf, "Couldn't use REST") == 0)
+                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s, %s",
+                         (int)response_code, szCurlErrBuf,
+                         "Range downloading not supported by this server !");
+            else
+                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s", (int)response_code, szCurlErrBuf);
+        }
+        if (!bHastComputedFileSize && startOffset == 0)
+        {
+            cachedFileProp->bHastComputedFileSize = bHastComputedFileSize = TRUE;
+            cachedFileProp->fileSize = fileSize = 0;
+            cachedFileProp->eExists = eExists = EXIST_NO;
+        }
         CPLFree(sWriteFuncData.pBuffer);
         CPLFree(sWriteFuncHeaderData.pBuffer);
         return FALSE;
@@ -678,7 +884,7 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
             bEOF = TRUE;
             return 0;
         }
-        int nToCopy = MIN(nBufferRequestSize, psRegion->nSize - (iterOffset - psRegion->nFileOffsetStart));
+        int nToCopy = (int) MIN(nBufferRequestSize, psRegion->nSize - (iterOffset - psRegion->nFileOffsetStart));
         memcpy(pBuffer, psRegion->pData + iterOffset - psRegion->nFileOffsetStart,
                 nToCopy);
         pBuffer = (char*) pBuffer + nToCopy;
@@ -690,7 +896,7 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
         }
     }
 
-    size_t ret = (iterOffset - curOffset) / nSize;
+    size_t ret = (size_t) ((iterOffset - curOffset) / nSize);
     if (ret != nMemb)
         bEOF = TRUE;
 
@@ -699,6 +905,344 @@ size_t VSICurlHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
     return ret;
 }
 
+
+/************************************************************************/
+/*                           ReadMultiRange()                           */
+/************************************************************************/
+
+int VSICurlHandle::ReadMultiRange( int nRanges, void ** ppData,
+                                   const vsi_l_offset* panOffsets,
+                                   const size_t* panSizes )
+{
+    WriteFuncStruct sWriteFuncData;
+    WriteFuncStruct sWriteFuncHeaderData;
+
+    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+    if (cachedFileProp->eExists == EXIST_NO)
+        return -1;
+
+    CPLString osRanges, osFirstRange, osLastRange;
+    int i;
+    int nMergedRanges = 0;
+    vsi_l_offset nTotalReqSize = 0;
+    for(i=0;i<nRanges;i++)
+    {
+        CPLString osCurRange;
+        if (i != 0)
+            osRanges.append(",");
+        osCurRange = CPLSPrintf(CPL_FRMT_GUIB "-", panOffsets[i]);
+        while (i + 1 < nRanges && panOffsets[i] + panSizes[i] == panOffsets[i+1])
+        {
+            nTotalReqSize += panSizes[i];
+            i ++;
+        }
+        nTotalReqSize += panSizes[i];
+        osCurRange.append(CPLSPrintf(CPL_FRMT_GUIB, panOffsets[i] + panSizes[i]-1));
+        nMergedRanges ++;
+
+        osRanges += osCurRange;
+
+        if (nMergedRanges == 1)
+            osFirstRange = osCurRange;
+        osLastRange = osCurRange;
+    }
+
+    const char* pszMaxRanges = CPLGetConfigOption("CPL_VSIL_CURL_MAX_RANGES", "250");
+    int nMaxRanges = atoi(pszMaxRanges);
+    if (nMaxRanges <= 0)
+        nMaxRanges = 250;
+    if (nMergedRanges > nMaxRanges)
+    {
+        int nHalf = nRanges / 2;
+        int nRet = ReadMultiRange(nHalf, ppData, panOffsets, panSizes);
+        if (nRet != 0)
+            return nRet;
+        return ReadMultiRange(nRanges - nHalf, ppData + nHalf, panOffsets + nHalf, panSizes + nHalf);
+    }
+
+    CURL* hCurlHandle = poFS->GetCurlHandleFor(pszURL);
+    VSICurlSetOptions(hCurlHandle, pszURL);
+
+    VSICURLInitWriteFuncStruct(&sWriteFuncData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+    VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
+    sWriteFuncHeaderData.bIsHTTP = strncmp(pszURL, "http", 4) == 0;
+    sWriteFuncHeaderData.bMultiRange = nMergedRanges > 1;
+    if (nMergedRanges == 1)
+    {
+        sWriteFuncHeaderData.nStartOffset = panOffsets[0];
+        sWriteFuncHeaderData.nEndOffset = panOffsets[0] + nTotalReqSize-1;
+    }
+
+    if (ENABLE_DEBUG)
+    {
+        if (nMergedRanges == 1)
+            CPLDebug("VSICURL", "Downloading %s (%s)...", osRanges.c_str(), pszURL);
+        else
+            CPLDebug("VSICURL", "Downloading %s, ..., %s (" CPL_FRMT_GUIB " bytes, %s)...",
+                     osFirstRange.c_str(), osLastRange.c_str(), (GUIntBig)nTotalReqSize, pszURL);
+    }
+
+    curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, osRanges.c_str());
+
+    char szCurlErrBuf[CURL_ERROR_SIZE+1];
+    szCurlErrBuf[0] = '\0';
+    curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
+
+    curl_easy_perform(hCurlHandle);
+
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
+
+    long response_code = 0;
+    curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+
+    char *content_type = 0;
+    curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_TYPE, &content_type);
+
+    if ((response_code != 200 && response_code != 206 &&
+         response_code != 225 && response_code != 226 && response_code != 426) || sWriteFuncHeaderData.bError)
+    {
+        if (response_code >= 400 && szCurlErrBuf[0] != '\0')
+        {
+            if (strcmp(szCurlErrBuf, "Couldn't use REST") == 0)
+                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s, %s",
+                         (int)response_code, szCurlErrBuf,
+                         "Range downloading not supported by this server !");
+            else
+                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s", (int)response_code, szCurlErrBuf);
+        }
+        /*
+        if (!bHastComputedFileSize && startOffset == 0)
+        {
+            cachedFileProp->bHastComputedFileSize = bHastComputedFileSize = TRUE;
+            cachedFileProp->fileSize = fileSize = 0;
+            cachedFileProp->eExists = eExists = EXIST_NO;
+        }
+        */
+        CPLFree(sWriteFuncData.pBuffer);
+        CPLFree(sWriteFuncHeaderData.pBuffer);
+        return -1;
+    }
+
+    char* pBuffer = sWriteFuncData.pBuffer;
+    int nSize = sWriteFuncData.nSize;
+
+    int nRet = -1;
+    char* pszBoundary;
+    CPLString osBoundary;
+    char *pszNext;
+    int iRange = 0;
+    int iPart = 0;
+    char* pszEOL;
+
+/* -------------------------------------------------------------------- */
+/*      No multipart if a single range has been requested               */
+/* -------------------------------------------------------------------- */
+
+    if (nMergedRanges == 1)
+    {
+        int nAccSize = 0;
+        if ((vsi_l_offset)nSize < nTotalReqSize)
+            goto end;
+
+        for(i=0;i<nRanges;i++)
+        {
+            memcpy(ppData[i], pBuffer + nAccSize, panSizes[i]);
+            nAccSize += panSizes[i];
+        }
+
+        nRet = 0;
+        goto end;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Extract boundary name                                           */
+/* -------------------------------------------------------------------- */
+
+    pszBoundary = strstr(sWriteFuncHeaderData.pBuffer,
+                         "Content-Type: multipart/byteranges; boundary=");
+    if( pszBoundary == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Could not find '%s'",
+                  "Content-Type: multipart/byteranges; boundary=" );
+        goto end;
+    }
+    
+    pszBoundary += strlen( "Content-Type: multipart/byteranges; boundary=" );
+
+    pszEOL = strchr(pszBoundary, '\r');
+    if (pszEOL)
+        *pszEOL = 0;
+    pszEOL = strchr(pszBoundary, '\n');
+    if (pszEOL)
+        *pszEOL = 0;
+
+    /* Remove optional double-quote character around boundary name */
+    if (pszBoundary[0] == '"')
+    {
+        pszBoundary ++;
+        char* pszLastDoubleQuote = strrchr(pszBoundary, '"');
+        if (pszLastDoubleQuote)
+            *pszLastDoubleQuote = 0;
+    }
+
+    osBoundary = "--";
+    osBoundary += pszBoundary;
+
+/* -------------------------------------------------------------------- */
+/*      Find the start of the first chunk.                              */
+/* -------------------------------------------------------------------- */
+    pszNext = strstr(pBuffer,osBoundary.c_str());
+    if( pszNext == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "No parts found." );
+        goto end;
+    }
+
+    pszNext += strlen(osBoundary);
+    while( *pszNext != '\n' && *pszNext != '\r' && *pszNext != '\0' )
+        pszNext++;
+    if( *pszNext == '\r' )
+        pszNext++;
+    if( *pszNext == '\n' )
+        pszNext++;
+
+/* -------------------------------------------------------------------- */
+/*      Loop over parts...                                              */
+/* -------------------------------------------------------------------- */
+    while( iPart < nRanges )
+    {
+/* -------------------------------------------------------------------- */
+/*      Collect headers.                                                */
+/* -------------------------------------------------------------------- */
+        int bExpectedRange = FALSE;
+
+        while( *pszNext != '\n' && *pszNext != '\r' && *pszNext != '\0' )
+        {
+            char *pszEOL = strstr(pszNext,"\n");
+
+            if( pszEOL == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Error while parsing multipart content (at line %d)", __LINE__);
+                goto end;
+            }
+
+            *pszEOL = '\0';
+            int bRestoreAntislashR = FALSE;
+            if (pszEOL - pszNext > 1 && pszEOL[-1] == '\r')
+            {
+                bRestoreAntislashR = TRUE;
+                pszEOL[-1] = '\0';
+            }
+
+            if (EQUALN(pszNext, "Content-Range: bytes ", strlen("Content-Range: bytes ")))
+            {
+                bExpectedRange = TRUE; /* FIXME */
+            }
+
+            if (bRestoreAntislashR)
+                pszEOL[-1] = '\r';
+            *pszEOL = '\n';
+
+            pszNext = pszEOL + 1;
+        }
+
+        if (!bExpectedRange)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Error while parsing multipart content (at line %d)", __LINE__);
+            goto end;
+        }
+
+        if( *pszNext == '\r' )
+            pszNext++;
+        if( *pszNext == '\n' )
+            pszNext++;
+
+/* -------------------------------------------------------------------- */
+/*      Work out the data block size.                                   */
+/* -------------------------------------------------------------------- */
+        size_t nBytesAvail = nSize - (pszNext - pBuffer);
+
+        while(TRUE)
+        {
+            if (nBytesAvail < panSizes[iRange])
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                            "Error while parsing multipart content (at line %d)", __LINE__);
+                goto end;
+            }
+
+            memcpy(ppData[iRange], pszNext, panSizes[iRange]);
+            pszNext += panSizes[iRange];
+            nBytesAvail -= panSizes[iRange];
+            if( iRange + 1 < nRanges &&
+                panOffsets[iRange] + panSizes[iRange] == panOffsets[iRange + 1] )
+            {
+                iRange++;
+            }
+            else
+                break;
+        }
+
+        iPart ++;
+        iRange ++;
+
+        while( nBytesAvail > 0
+               && (*pszNext != '-'
+                   || strncmp(pszNext,osBoundary,strlen(osBoundary)) != 0) )
+        {
+            pszNext++;
+            nBytesAvail--;
+        }
+
+        if( nBytesAvail == 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Error while parsing multipart content (at line %d)", __LINE__);
+            goto end;
+        }
+
+        pszNext += strlen(osBoundary);
+        if( strncmp(pszNext,"--",2) == 0 )
+        {
+            /* End of multipart */
+            break;
+        }
+
+        if( *pszNext == '\r' )
+            pszNext++;
+        if( *pszNext == '\n' )
+            pszNext++;
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Error while parsing multipart content (at line %d)", __LINE__);
+            goto end;
+        }
+    }
+
+    if (iPart == nMergedRanges)
+        nRet = 0;
+    else
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Got only %d parts, where %d were expected", iPart, nMergedRanges);
+
+end:
+    CPLFree(sWriteFuncData.pBuffer);
+    CPLFree(sWriteFuncHeaderData.pBuffer);
+
+    return nRet;
+}
+
 /************************************************************************/
 /*                               Write()                                */
 /************************************************************************/
@@ -765,7 +1309,7 @@ VSICurlFilesystemHandler::~VSICurlFilesystemHandler()
     }
     CPLFree(papsRegions);
 
-    std::map<unsigned long, CachedFileProp*>::const_iterator iterCacheFileSize;
+    std::map<CPLString, CachedFileProp*>::const_iterator iterCacheFileSize;
 
     for( iterCacheFileSize = cacheFileSize.begin(); iterCacheFileSize != cacheFileSize.end(); iterCacheFileSize++ )
     {
@@ -780,11 +1324,65 @@ VSICurlFilesystemHandler::~VSICurlFilesystemHandler()
         CPLFree(iterCacheDirList->second);
     }
 
+    std::map<GIntBig, CachedConnection*>::const_iterator iterConnections;
+    for( iterConnections = mapConnections.begin(); iterConnections != mapConnections.end(); iterConnections++ )
+    {
+        curl_easy_cleanup(iterConnections->second->hCurlHandle);
+        delete iterConnections->second;
+    }
+
     if( hMutex != NULL )
         CPLDestroyMutex( hMutex );
     hMutex = NULL;
 }
 
+/************************************************************************/
+/*                      GetCurlHandleFor()                              */
+/************************************************************************/
+
+CURL* VSICurlFilesystemHandler::GetCurlHandleFor(CPLString osURL)
+{
+    CPLMutexHolder oHolder( &hMutex );
+
+    std::map<GIntBig, CachedConnection*>::const_iterator iterConnections;
+
+    iterConnections = mapConnections.find(CPLGetPID());
+    if (iterConnections == mapConnections.end())
+    {
+        CURL* hCurlHandle = curl_easy_init();
+        CachedConnection* psCachedConnection = new CachedConnection;
+        psCachedConnection->osURL = osURL;
+        psCachedConnection->hCurlHandle = hCurlHandle;
+        mapConnections[CPLGetPID()] = psCachedConnection;
+        return hCurlHandle;
+    }
+    else
+    {
+        CachedConnection* psCachedConnection = iterConnections->second;
+        if (osURL == psCachedConnection->osURL)
+            return psCachedConnection->hCurlHandle;
+
+        const char* pszURL = osURL.c_str();
+        const char* pszEndOfServ = strchr(pszURL, '.');
+        if (pszEndOfServ != NULL)
+            pszEndOfServ = strchr(pszEndOfServ, '/');
+        if (pszEndOfServ == NULL)
+            pszURL = pszURL + strlen(pszURL);
+        int bReinitConnection = strncmp(psCachedConnection->osURL,
+                                        pszURL, pszEndOfServ-pszURL) != 0;
+
+        if (bReinitConnection)
+        {
+            if (psCachedConnection->hCurlHandle)
+                curl_easy_cleanup(psCachedConnection->hCurlHandle);
+            psCachedConnection->hCurlHandle = curl_easy_init();
+        }
+        psCachedConnection->osURL = osURL;
+
+        return psCachedConnection->hCurlHandle;
+    }
+}
+
 
 /************************************************************************/
 /*                   GetRegionFromCacheDisk()                           */
@@ -967,8 +1565,7 @@ CachedFileProp*  VSICurlFilesystemHandler::GetCachedFileProp(const char* pszURL)
 {
     CPLMutexHolder oHolder( &hMutex );
 
-    unsigned long   pszURLHash = CPLHashSetHashStr(pszURL);
-    CachedFileProp* cachedFileProp = cacheFileSize[pszURLHash];
+    CachedFileProp* cachedFileProp = cacheFileSize[pszURL];
     if (cachedFileProp == NULL)
     {
         cachedFileProp = (CachedFileProp*) CPLMalloc(sizeof(CachedFileProp));
@@ -976,7 +1573,7 @@ CachedFileProp*  VSICurlFilesystemHandler::GetCachedFileProp(const char* pszURL)
         cachedFileProp->bHastComputedFileSize = FALSE;
         cachedFileProp->fileSize = 0;
         cachedFileProp->bIsDirectory = FALSE;
-        cacheFileSize[pszURLHash] = cachedFileProp;
+        cacheFileSize[pszURL] = cachedFileProp;
     }
 
     return cachedFileProp;
@@ -997,13 +1594,18 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
         return NULL;
     }
 
+    const char* pszOptionVal =
+        CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
+    int bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
+                       CSLTestBoolean(pszOptionVal);
+
     CPLString osFilename(pszFilename);
+    int bGotFileList = TRUE;
     if (strchr(CPLGetFilename(osFilename), '.') != NULL &&
-        strncmp(CPLGetExtension(osFilename), "zip", 3) != 0)
+        strncmp(CPLGetExtension(osFilename), "zip", 3) != 0 && !bSkipReadDir)
     {
-        int bGotFileList;
         char** papszFileList = ReadDir(CPLGetDirname(osFilename), &bGotFileList);
-        int bFound = (CSLFindStringSensitive(papszFileList, CPLGetFilename(osFilename)) != -1);
+        int bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
         CSLDestroy(papszFileList);
         if (bGotFileList && !bFound)
         {
@@ -1011,27 +1613,221 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
         }
     }
 
-    return new VSICurlHandle( this, osFilename + strlen("/vsicurl/"));
+    VSICurlHandle* poHandle = new VSICurlHandle( this, osFilename + strlen("/vsicurl/"));
+    if (!bGotFileList)
+    {
+        /* If we didn't get a filelist, check that the file really exists */
+        if (!poHandle->Exists())
+        {
+            delete poHandle;
+            poHandle = NULL;
+        }
+    }
+    return poHandle;
 }
 
-static char** VSICurlParseHTMLFileList(const char* pszFilename,
+/************************************************************************/
+/*                        VSICurlParserFindEOL()                        */
+/*                                                                      */
+/*      Small helper function for VSICurlPaseHTMLFileList() to find     */
+/*      the end of a line in the directory listing.  Either a <br>      */
+/*      or newline.                                                     */
+/************************************************************************/
+
+static char *VSICurlParserFindEOL( char *pszData )
+
+{
+    while( *pszData != '\0' && *pszData != '\n' && !EQUALN(pszData,"<br>",4) )
+        pszData++;
+
+    if( *pszData == '\0' )
+        return NULL;
+    else 
+        return pszData;
+}
+
+
+/************************************************************************/
+/*                   VSICurlParseHTMLDateTimeFileSize()                 */
+/************************************************************************/
+
+static const char* const apszMonths[] = { "January", "February", "March",
+                                          "April", "May", "June", "July",
+                                          "August", "September", "October",
+                                          "November", "December" };
+
+static int VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
+                                            struct tm& brokendowntime,
+                                            GUIntBig& nFileSize,
+                                            GIntBig& mTime)
+{
+    int iMonth;
+    for(iMonth=0;iMonth<12;iMonth++)
+    {
+        char szMonth[32];
+        szMonth[0] = '-';
+        memcpy(szMonth + 1, apszMonths[iMonth], 3);
+        szMonth[4] = '-';
+        szMonth[5] = '\0';
+        const char* pszMonthFound = strstr(pszStr, szMonth);
+        if (pszMonthFound)
+        {
+            /* Format of Apache, like in http://download.osgeo.org/gdal/data/gtiff/ */
+            /* "17-May-2010 12:26" */
+            if (pszMonthFound - pszStr > 2 && strlen(pszMonthFound) > 15 &&
+                pszMonthFound[-2 + 11] == ' ' && pszMonthFound[-2 + 14] == ':')
+            {
+                pszMonthFound -= 2;
+                int nDay = atoi(pszMonthFound);
+                int nYear = atoi(pszMonthFound + 7);
+                int nHour = atoi(pszMonthFound + 12);
+                int nMin = atoi(pszMonthFound + 15);
+                if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
+                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
+                {
+                    brokendowntime.tm_year = nYear - 1900;
+                    brokendowntime.tm_mon = iMonth;
+                    brokendowntime.tm_mday = nDay;
+                    brokendowntime.tm_hour = nHour;
+                    brokendowntime.tm_min = nMin;
+                    mTime = CPLYMDHMSToUnixTime(&brokendowntime);
+
+                    return TRUE;
+                }
+            }
+            return FALSE;
+        }
+
+        /* Microsoft IIS */
+        szMonth[0] = ' ';
+        strcpy(szMonth + 1, apszMonths[iMonth]);
+        strcat(szMonth, " ");
+        pszMonthFound = strstr(pszStr, szMonth);
+        if (pszMonthFound)
+        {
+            int nLenMonth = strlen(apszMonths[iMonth]);
+            if (pszMonthFound - pszStr > 2 &&
+                pszMonthFound[-1] != ',' &&
+                pszMonthFound[-2] != ' ' &&
+                (int)strlen(pszMonthFound-2) > 2 + 1 + nLenMonth + 1 + 4 + 1 + 5 + 1 + 4)
+            {
+                /* Format of http://ortho.linz.govt.nz/tifs/1994_95/ */
+                /* "        Friday, 21 April 2006 12:05 p.m.     48062343 m35a_fy_94_95.tif" */
+                pszMonthFound -= 2;
+                    int nDay = atoi(pszMonthFound);
+                int nCurOffset = 2 + 1 + nLenMonth + 1;
+                int nYear = atoi(pszMonthFound + nCurOffset);
+                nCurOffset += 4 + 1;
+                int nHour = atoi(pszMonthFound + nCurOffset);
+                if (nHour < 10)
+                    nCurOffset += 1 + 1;
+                else
+                    nCurOffset += 2 + 1;
+                int nMin = atoi(pszMonthFound + nCurOffset);
+                nCurOffset += 2 + 1;
+                if (strncmp(pszMonthFound + nCurOffset, "p.m.", 4) == 0)
+                    nHour += 12;
+                else if (strncmp(pszMonthFound + nCurOffset, "a.m.", 4) != 0)
+                    nHour = -1;
+                nCurOffset += 4;
+
+                const char* pszFilesize = pszMonthFound + nCurOffset;
+                while(*pszFilesize == ' ')
+                    pszFilesize ++;
+                if (*pszFilesize >= '1' && *pszFilesize <= '9')
+                    nFileSize = CPLScanUIntBig(pszFilesize, strlen(pszFilesize));
+
+                if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
+                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
+                {
+                    brokendowntime.tm_year = nYear - 1900;
+                    brokendowntime.tm_mon = iMonth;
+                    brokendowntime.tm_mday = nDay;
+                    brokendowntime.tm_hour = nHour;
+                    brokendowntime.tm_min = nMin;
+                    mTime = CPLYMDHMSToUnixTime(&brokendowntime);
+
+                    return TRUE;
+                }
+                nFileSize = 0;
+            }
+            else if (pszMonthFound - pszStr > 1 &&
+                        pszMonthFound[-1] == ',' &&
+                        (int)strlen(pszMonthFound) > 1 + nLenMonth + 1 + 2 + 1 + 1 + 4 + 1 + 5 + 1 + 2)
+            {
+                /* Format of http://publicfiles.dep.state.fl.us/dear/BWR_GIS/2007NWFLULC/ */
+                /* "        Sunday, June 20, 2010  6:46 PM    233170905 NWF2007LULCForSDE.zip" */
+                pszMonthFound += 1;
+                int nCurOffset = nLenMonth + 1;
+                int nDay = atoi(pszMonthFound + nCurOffset);
+                nCurOffset += 2 + 1 + 1;
+                int nYear = atoi(pszMonthFound + nCurOffset);
+                nCurOffset += 4 + 1;
+                int nHour = atoi(pszMonthFound + nCurOffset);
+                nCurOffset += 2 + 1;
+                int nMin = atoi(pszMonthFound + nCurOffset);
+                nCurOffset += 2 + 1;
+                if (strncmp(pszMonthFound + nCurOffset, "PM", 2) == 0)
+                    nHour += 12;
+                else if (strncmp(pszMonthFound + nCurOffset, "AM", 2) != 0)
+                    nHour = -1;
+                nCurOffset += 2;
+
+                const char* pszFilesize = pszMonthFound + nCurOffset;
+                while(*pszFilesize == ' ')
+                    pszFilesize ++;
+                if (*pszFilesize >= '1' && *pszFilesize <= '9')
+                    nFileSize = CPLScanUIntBig(pszFilesize, strlen(pszFilesize));
+
+                if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
+                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
+                {
+                    brokendowntime.tm_year = nYear - 1900;
+                    brokendowntime.tm_mon = iMonth;
+                    brokendowntime.tm_mday = nDay;
+                    brokendowntime.tm_hour = nHour;
+                    brokendowntime.tm_min = nMin;
+                    mTime = CPLYMDHMSToUnixTime(&brokendowntime);
+
+                    return TRUE;
+                }
+                nFileSize = 0;
+            }
+            return FALSE;
+        }
+    }
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          ParseHTMLFileList()                         */
+/*                                                                      */
+/*      Parse a file list document and return all the components.       */
+/************************************************************************/
+
+char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
                                        char* pszData,
                                        int* pbGotFileList)
 {
-    char** papszFileList = NULL;
-    char* iter = pszData;
+    CPLStringList oFileList;
+    char* pszLine = pszData;
     char* c;
     int nCount = 0;
     int bIsHTMLDirList = FALSE;
     CPLString osExpectedString;
     CPLString osExpectedString2;
     CPLString osExpectedString3;
+    CPLString osExpectedString4;
+    CPLString osExpectedString_unescaped;
     
     *pbGotFileList = FALSE;
 
     const char* pszDir;
     if (EQUALN(pszFilename, "/vsicurl/http://", strlen("/vsicurl/http://")))
         pszDir = strchr(pszFilename + strlen("/vsicurl/http://"), '/');
+    else if (EQUALN(pszFilename, "/vsicurl/https://", strlen("/vsicurl/https://")))
+        pszDir = strchr(pszFilename + strlen("/vsicurl/https://"), '/');
     else
         pszDir = strchr(pszFilename + strlen("/vsicurl/ftp://"), '/');
     if (pszDir == NULL)
@@ -1048,27 +1844,62 @@ static char** VSICurlParseHTMLFileList(const char* pszFilename,
     osExpectedString3 = "FTP Listing of ";
     osExpectedString3 += pszDir;
     osExpectedString3 += "/";
-    while( (c = strstr(iter, "<br>")) != NULL ||
-           (c = strchr(iter, '\n')) != NULL )
+    /* Apache 1.3.33 */
+    osExpectedString4 = "<TITLE>Index of ";
+    osExpectedString4 += pszDir;
+    osExpectedString4 += "</TITLE>";
+
+    /* The listing of http://dds.cr.usgs.gov/srtm/SRTM_image_sample/picture%20examples/ */
+    /* has "<title>Index of /srtm/SRTM_image_sample/picture examples</title>" so we must */
+    /* try unescaped %20 also */
+    /* Similar with http://datalib.usask.ca/gis/Data/Central_America_goodbutdoweown%3f/ */
+    if (strchr(pszDir, '%'))
+    {
+        char* pszUnescapedDir = CPLUnescapeString(pszDir, NULL, CPLES_URL);
+        osExpectedString_unescaped = "<title>Index of ";
+        osExpectedString_unescaped += pszUnescapedDir;
+        osExpectedString_unescaped += "</title>";
+        CPLFree(pszUnescapedDir);
+    }
+
+    int nCountTable = 0;
+    
+    while( (c = VSICurlParserFindEOL( pszLine )) != NULL )
     {
         *c = 0;
-        if (strstr(iter, osExpectedString.c_str()) ||
-            strstr(iter, osExpectedString2.c_str()) ||
-            strstr(iter, osExpectedString3.c_str()))
+
+        /* To avoid false positive on pages such as http://www.ngs.noaa.gov/PC_PROD/USGG2009BETA */
+        /* This is a heuristics, but normal HTML listing of files have not more than one table */
+        if (strstr(pszLine, "<table"))
+        {
+            nCountTable ++;
+            if (nCountTable == 2)
+            {
+                *pbGotFileList = FALSE;
+                return NULL;
+            }
+        }
+
+        if (!bIsHTMLDirList &&
+            (strstr(pszLine, osExpectedString.c_str()) ||
+             strstr(pszLine, osExpectedString2.c_str()) ||
+             strstr(pszLine, osExpectedString3.c_str()) ||
+             strstr(pszLine, osExpectedString4.c_str()) ||
+             (osExpectedString_unescaped.size() != 0 && strstr(pszLine, osExpectedString_unescaped.c_str()))))
         {
             bIsHTMLDirList = TRUE;
             *pbGotFileList = TRUE;
         }
         /* Subversion HTTP listing */
         /* or Microsoft-IIS/6.0 listing (e.g. http://ortho.linz.govt.nz/tifs/2005_06/) */
-        else if (strstr(iter, "<title>"))
+        else if (!bIsHTMLDirList && strstr(pszLine, "<title>"))
         {
             /* Detect something like : <html><head><title>gdal - Revision 20739: /trunk/autotest/gcore/data</title></head> */
             /* The annoying thing is that what is after ': ' is a subpart of what is after http://server/ */
-            char* pszSubDir = strstr(iter, ": ");
+            char* pszSubDir = strstr(pszLine, ": ");
             if (pszSubDir == NULL)
                 /* or <title>ortho.linz.govt.nz - /tifs/2005_06/</title> */
-                pszSubDir = strstr(iter, "- ");
+                pszSubDir = strstr(pszLine, "- ");
             if (pszSubDir)
             {
                 pszSubDir += 2;
@@ -1088,134 +1919,406 @@ static char** VSICurlParseHTMLFileList(const char* pszFilename,
             }
         }
         else if (bIsHTMLDirList &&
-                 (strstr(iter, "<a href=\"") != NULL || strstr(iter, "<A HREF=\"") != NULL) &&
-                 strstr(iter, "<a href=\"http://") == NULL && /* exclude absolute links, like to subversion home */
-                 strstr(iter, "Parent Directory") == NULL /* exclude parent directory */)
+                 (strstr(pszLine, "<a href=\"") != NULL || strstr(pszLine, "<A HREF=\"") != NULL) &&
+                 strstr(pszLine, "<a href=\"http://") == NULL && /* exclude absolute links, like to subversion home */
+                 strstr(pszLine, "Parent Directory") == NULL /* exclude parent directory */)
         {
-            char *beginFilename = strstr(iter, "<a href=\"");
+            char *beginFilename = strstr(pszLine, "<a href=\"");
             if (beginFilename == NULL)
-                beginFilename = strstr(iter, "<A HREF=\"");
+                beginFilename = strstr(pszLine, "<A HREF=\"");
             beginFilename += strlen("<a href=\"");
             char *endQuote = strchr(beginFilename, '"');
-            if (endQuote && strncmp(beginFilename, "?C=", 3) != 0)
+            if (endQuote && strncmp(beginFilename, "?C=", 3) != 0 && strncmp(beginFilename, "?N=", 3) != 0)
             {
+                struct tm brokendowntime;
+                memset(&brokendowntime, 0, sizeof(brokendowntime));
+                GUIntBig nFileSize = 0;
+                GIntBig mTime = 0;
+
+                VSICurlParseHTMLDateTimeFileSize(pszLine,
+                                                 brokendowntime,
+                                                 nFileSize,
+                                                 mTime);
+
                 *endQuote = '\0';
-                
+
                 /* Remove trailing slash, that are returned for directories by */
                 /* Apache */
+                int bIsDirectory = FALSE;
                 if (endQuote[-1] == '/')
+                {
+                    bIsDirectory = TRUE;
                     endQuote[-1] = 0;
+                }
                 
                 /* shttpd links include slashes from the root directory. Skip them */
                 while(strchr(beginFilename, '/'))
                     beginFilename = strchr(beginFilename, '/') + 1;
-                papszFileList = CSLAddString(papszFileList, beginFilename);
-                if (ENABLE_DEBUG)
-                    CPLDebug("VSICURL", "File[%d] = %s", nCount, beginFilename);
-                nCount ++;
+
+                if (strcmp(beginFilename, ".") != 0 &&
+                    strcmp(beginFilename, "..") != 0)
+                {
+                    CPLString osCachedFilename =
+                        CPLSPrintf("%s/%s", pszFilename + strlen("/vsicurl/"), beginFilename);
+                    CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                    cachedFileProp->eExists = EXIST_YES;
+                    cachedFileProp->bIsDirectory = bIsDirectory;
+                    cachedFileProp->mTime = mTime;
+                    cachedFileProp->bHastComputedFileSize = nFileSize > 0;
+                    cachedFileProp->fileSize = nFileSize;
+
+                    oFileList.AddString( beginFilename );
+                    if (ENABLE_DEBUG)
+                        CPLDebug("VSICURL", "File[%d] = %s, is_dir = %d, size = " CPL_FRMT_GUIB ", time = %04d/%02d/%02d %02d:%02d:%02d",
+                                nCount, beginFilename, bIsDirectory, nFileSize,
+                                brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1, brokendowntime.tm_mday,
+                                brokendowntime.tm_hour, brokendowntime.tm_min, brokendowntime.tm_sec);
+                    nCount ++;
+                }
             }
         }
-        iter = c + 1;
+        pszLine = c + 1;
     }
-    
-    return papszFileList;
+
+    return oFileList.StealList();
 }
 
-static char** VSICurlGetFileList(const char *pszFilename, int* pbGotFileList)
+
+/************************************************************************/
+/*                         VSICurlGetToken()                            */
+/************************************************************************/
+
+static char* VSICurlGetToken(char* pszCurPtr, char** ppszNextToken)
 {
-    if (ENABLE_DEBUG)
-        CPLDebug("VSICURL", "GetFileList(%s)" , pszFilename);
+    if (pszCurPtr == NULL)
+        return NULL;
 
-    *pbGotFileList = FALSE;
+    while((*pszCurPtr) == ' ')
+        pszCurPtr ++;
+    if (*pszCurPtr == '\0')
+        return NULL;
 
-    if (strncmp(pszFilename, "/vsicurl/ftp", strlen("/vsicurl/ftp")) == 0)
+    char* pszToken = pszCurPtr;
+    while((*pszCurPtr) != ' ' && (*pszCurPtr) != '\0')
+        pszCurPtr ++;
+    if (*pszCurPtr == '\0')
+        *ppszNextToken = NULL;
+    else
     {
-        WriteFuncStruct sWriteFuncData;
+        *pszCurPtr = '\0';
+        pszCurPtr ++;
+        while((*pszCurPtr) == ' ')
+            pszCurPtr ++;
+        *ppszNextToken = pszCurPtr;
+    }
 
-        CURL* hCurlHandle = curl_easy_init();
+    return pszToken;
+}
 
-        CPLString osFilename(pszFilename + strlen("/vsicurl/"));
-        osFilename += '/';
+/************************************************************************/
+/*                    VSICurlParseFullFTPLine()                         */
+/************************************************************************/
 
-        VSICurlSetOptions(hCurlHandle, osFilename.c_str());
+/* Parse lines like the following ones :
+-rw-r--r--    1 10003    100           430 Jul 04  2008 COPYING
+lrwxrwxrwx    1 ftp      ftp            28 Jun 14 14:13 MPlayer -> mirrors/mplayerhq.hu/MPlayer
+-rw-r--r--    1 ftp      ftp      725614592 May 13 20:13 Fedora-15-x86_64-Live-KDE.iso
+drwxr-xr-x  280 1003  1003  6656 Aug 26 04:17 gnu
+*/
 
-/* 7.16.4 */
-#if LIBCURL_VERSION_NUM <= 0x071004
-        curl_easy_setopt(hCurlHandle, CURLOPT_FTPLISTONLY, 1);
-#elif LIBCURL_VERSION_NUM > 0x071004
-        curl_easy_setopt(hCurlHandle, CURLOPT_DIRLISTONLY, 1);
-#endif
-        VSICURLInitWriteFuncStruct(&sWriteFuncData);
-        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+static int VSICurlParseFullFTPLine(char* pszLine,
+                                   char*& pszFilename,
+                                   int& bSizeValid,
+                                   GUIntBig& nSize,
+                                   int& bIsDirectory,
+                                   GIntBig& nUnixTime)
+{
+    char* pszNextToken = pszLine;
+    char* pszPermissions = VSICurlGetToken(pszNextToken, &pszNextToken);
+    if (pszPermissions == NULL || strlen(pszPermissions) != 10)
+        return FALSE;
+    bIsDirectory = (pszPermissions[0] == 'd');
 
-        curl_easy_perform(hCurlHandle);
+    int i;
+    for(i = 0; i < 3; i++)
+    {
+        if (VSICurlGetToken(pszNextToken, &pszNextToken) == NULL)
+            return FALSE;
+    }
 
-        curl_easy_cleanup(hCurlHandle);
+    char* pszSize = VSICurlGetToken(pszNextToken, &pszNextToken);
+    if (pszSize == NULL)
+        return FALSE;
 
-        if (sWriteFuncData.pBuffer == NULL)
-            return NULL;
+    if (pszPermissions[0] == '-')
+    {
+        /* Regular file */
+        bSizeValid = TRUE;
+        nSize = CPLScanUIntBig(pszSize, strlen(pszSize));
+    }
 
-        char** papszFileList = NULL;
-        char* iter = sWriteFuncData.pBuffer;
-        char* c;
-        int nCount = 0;
-        
-        if (EQUALN(iter, "<!DOCTYPE HTML", strlen("<!DOCTYPE HTML")) ||
-            EQUALN(iter, "<HTML>", 6))
+    struct tm brokendowntime;
+    memset(&brokendowntime, 0, sizeof(brokendowntime));
+    int bBrokenDownTimeValid = TRUE;
+
+    char* pszMonth = VSICurlGetToken(pszNextToken, &pszNextToken);
+    if (pszMonth == NULL || strlen(pszMonth) != 3)
+        return FALSE;
+
+    for(i = 0; i < 12; i++)
+    {
+        if (EQUALN(pszMonth, apszMonths[i], 3))
+            break;
+    }
+    if (i < 12)
+        brokendowntime.tm_mon = i;
+    else
+        bBrokenDownTimeValid = FALSE;
+
+    char* pszDay = VSICurlGetToken(pszNextToken, &pszNextToken);
+    if (pszDay == NULL || (strlen(pszDay) != 1 && strlen(pszDay) != 2))
+        return FALSE;
+    int nDay = atoi(pszDay);
+    if (nDay >= 1 && nDay <= 31)
+        brokendowntime.tm_mday = nDay;
+    else
+        bBrokenDownTimeValid = FALSE;
+
+    char* pszHourOrYear = VSICurlGetToken(pszNextToken, &pszNextToken);
+    if (pszHourOrYear == NULL || (strlen(pszHourOrYear) != 4 && strlen(pszHourOrYear) != 5))
+        return FALSE;
+    if (strlen(pszHourOrYear) == 4)
+    {
+        brokendowntime.tm_year = atoi(pszHourOrYear) - 1900;
+    }
+    else
+    {
+        time_t sTime;
+        time(&sTime);
+        struct tm currentBrokendowntime;
+        CPLUnixTimeToYMDHMS((GIntBig)sTime, &currentBrokendowntime);
+        brokendowntime.tm_year = currentBrokendowntime.tm_year;
+        brokendowntime.tm_hour = atoi(pszHourOrYear);
+        brokendowntime.tm_min = atoi(pszHourOrYear + 3);
+    }
+
+    if (bBrokenDownTimeValid)
+        nUnixTime = CPLYMDHMSToUnixTime(&brokendowntime);
+    else
+        nUnixTime = 0;
+
+    if (pszNextToken == NULL)
+        return FALSE;
+
+    pszFilename = pszNextToken;
+
+    char* pszCurPtr = pszFilename;
+    while( *pszCurPtr != '\0')
+    {
+        /* In case of a link, stop before the pointed part of the link */
+        if (pszPermissions[0] == 'l' && strncmp(pszCurPtr, " -> ", 4) == 0)
         {
-            papszFileList = VSICurlParseHTMLFileList(pszFilename,
-                                             sWriteFuncData.pBuffer,
-                                             pbGotFileList);
+            break;
         }
-        else
+        pszCurPtr ++;
+    }
+    *pszCurPtr = '\0';
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          GetFileList()                               */
+/************************************************************************/
+
+char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname, int* pbGotFileList)
+{
+    if (ENABLE_DEBUG)
+        CPLDebug("VSICURL", "GetFileList(%s)" , pszDirname);
+
+    *pbGotFileList = FALSE;
+
+    if (strncmp(pszDirname, "/vsicurl/ftp", strlen("/vsicurl/ftp")) == 0)
+    {
+        WriteFuncStruct sWriteFuncData;
+        sWriteFuncData.pBuffer = NULL;
+
+        CPLString osDirname(pszDirname + strlen("/vsicurl/"));
+        osDirname += '/';
+
+        char** papszFileList = NULL;
+
+        for(int iTry=0;iTry<2;iTry++)
         {
-            *pbGotFileList = TRUE;
-            
-            while( (c = strchr(iter, '\n')) != NULL)
+            CURL* hCurlHandle = GetCurlHandleFor(osDirname);
+            VSICurlSetOptions(hCurlHandle, osDirname.c_str());
+
+            /* On the first pass, we want to try fetching all the possible */
+            /* informations (filename, file/directory, size). If that */
+            /* does not work, then try again with CURLOPT_DIRLISTONLY set */
+            if (iTry == 1)
             {
-                *c = 0;
-                if (c - iter > 0 && c[-1] == '\r')
-                    c[-1] = 0;
-                papszFileList = CSLAddString(papszFileList, iter);
-                if (ENABLE_DEBUG)
-                    CPLDebug("VSICURL", "File[%d] = %s", nCount, iter);
-                iter = c + 1;
-                nCount ++;
+        /* 7.16.4 */
+        #if LIBCURL_VERSION_NUM <= 0x071004
+                curl_easy_setopt(hCurlHandle, CURLOPT_FTPLISTONLY, 1);
+        #elif LIBCURL_VERSION_NUM > 0x071004
+                curl_easy_setopt(hCurlHandle, CURLOPT_DIRLISTONLY, 1);
+        #endif
             }
+
+            VSICURLInitWriteFuncStruct(&sWriteFuncData);
+            curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+            curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+
+            char szCurlErrBuf[CURL_ERROR_SIZE+1];
+            szCurlErrBuf[0] = '\0';
+            curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
+
+            curl_easy_perform(hCurlHandle);
+
+            if (sWriteFuncData.pBuffer == NULL)
+                return NULL;
+
+            char* pszLine = sWriteFuncData.pBuffer;
+            char* c;
+            int nCount = 0;
+
+            if (EQUALN(pszLine, "<!DOCTYPE HTML", strlen("<!DOCTYPE HTML")) ||
+                EQUALN(pszLine, "<HTML>", 6))
+            {
+                papszFileList = ParseHTMLFileList(pszDirname,
+                                                  sWriteFuncData.pBuffer,
+                                                  pbGotFileList);
+                break;
+            }
+            else if (iTry == 0)
+            {
+                CPLStringList oFileList;
+                *pbGotFileList = TRUE;
+
+                while( (c = strchr(pszLine, '\n')) != NULL)
+                {
+                    *c = 0;
+                    if (c - pszLine > 0 && c[-1] == '\r')
+                        c[-1] = 0;
+
+                    char* pszFilename = NULL;
+                    int bSizeValid = FALSE;
+                    GUIntBig nFileSize = 0;
+                    int bIsDirectory = FALSE;
+                    GIntBig mUnixTime = 0;
+                    if (!VSICurlParseFullFTPLine(pszLine, pszFilename,
+                                                 bSizeValid, nFileSize,
+                                                 bIsDirectory, mUnixTime))
+                        break;
+
+                    if (strcmp(pszFilename, ".") != 0 &&
+                        strcmp(pszFilename, "..") != 0)
+                    {
+                        CPLString osCachedFilename =
+                            CPLSPrintf("%s/%s", pszDirname + strlen("/vsicurl/"), pszFilename);
+                        CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                        cachedFileProp->eExists = EXIST_YES;
+                        cachedFileProp->bHastComputedFileSize = bSizeValid;
+                        cachedFileProp->fileSize = nFileSize;
+                        cachedFileProp->bIsDirectory = bIsDirectory;
+                        cachedFileProp->mTime = mUnixTime;
+
+                        oFileList.AddString(pszFilename);
+                        if (ENABLE_DEBUG)
+                        {
+                            struct tm brokendowntime;
+                            CPLUnixTimeToYMDHMS(mUnixTime, &brokendowntime);
+                            CPLDebug("VSICURL", "File[%d] = %s, is_dir = %d, size = " CPL_FRMT_GUIB ", time = %04d/%02d/%02d %02d:%02d:%02d",
+                                    nCount, pszFilename, bIsDirectory, nFileSize,
+                                    brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1, brokendowntime.tm_mday,
+                                    brokendowntime.tm_hour, brokendowntime.tm_min, brokendowntime.tm_sec);
+                        }
+
+                        nCount ++;
+                    }
+
+                    pszLine = c + 1;
+                }
+
+                if (c == NULL)
+                {
+                    papszFileList = oFileList.StealList();
+                    break;
+                }
+            }
+            else
+            {
+                CPLStringList oFileList;
+                *pbGotFileList = TRUE;
+
+                while( (c = strchr(pszLine, '\n')) != NULL)
+                {
+                    *c = 0;
+                    if (c - pszLine > 0 && c[-1] == '\r')
+                        c[-1] = 0;
+
+                    if (strcmp(pszLine, ".") != 0 &&
+                        strcmp(pszLine, "..") != 0)
+                    {
+                        oFileList.AddString(pszLine);
+                        if (ENABLE_DEBUG)
+                            CPLDebug("VSICURL", "File[%d] = %s", nCount, pszLine);
+                        nCount ++;
+                    }
+
+                    pszLine = c + 1;
+                }
+
+                papszFileList = oFileList.StealList();
+            }
+
+            CPLFree(sWriteFuncData.pBuffer);
+            sWriteFuncData.pBuffer = NULL;
         }
 
         CPLFree(sWriteFuncData.pBuffer);
+
         return papszFileList;
     }
 
     /* Try to recognize HTML pages that list the content of a directory */
     /* Currently this supports what Apache and shttpd can return */
-    else if (strncmp(pszFilename, "/vsicurl/http://", strlen("/vsicurl/http://")) == 0)
+    else if (strncmp(pszDirname, "/vsicurl/http://", strlen("/vsicurl/http://")) == 0 ||
+             strncmp(pszDirname, "/vsicurl/https://", strlen("/vsicurl/https://")) == 0)
     {
         WriteFuncStruct sWriteFuncData;
 
-        CURL* hCurlHandle = curl_easy_init();
+        CPLString osDirname(pszDirname + strlen("/vsicurl/"));
+        osDirname += '/';
 
-        CPLString osFilename(pszFilename + strlen("/vsicurl/"));
-        osFilename += '/';
+    #if LIBCURL_VERSION_NUM < 0x070B00
+        /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
+        /* previously set, so we have to reinit the connection handle */
+        GetCurlHandleFor("");
+    #endif
 
-        VSICurlSetOptions(hCurlHandle, osFilename.c_str());
+        CURL* hCurlHandle = GetCurlHandleFor(osDirname);
+        VSICurlSetOptions(hCurlHandle, osDirname.c_str());
+
+        curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
 
         VSICURLInitWriteFuncStruct(&sWriteFuncData);
         curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
         curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
 
-        curl_easy_perform(hCurlHandle);
+        char szCurlErrBuf[CURL_ERROR_SIZE+1];
+        szCurlErrBuf[0] = '\0';
+        curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-        curl_easy_cleanup(hCurlHandle);
+        curl_easy_perform(hCurlHandle);
 
         if (sWriteFuncData.pBuffer == NULL)
             return NULL;
             
-        char** papszFileList = VSICurlParseHTMLFileList(pszFilename,
-                                                        sWriteFuncData.pBuffer,
-                                                        pbGotFileList);
+        char** papszFileList = ParseHTMLFileList(pszDirname,
+                                                 sWriteFuncData.pBuffer,
+                                                 pbGotFileList);
 
         CPLFree(sWriteFuncData.pBuffer);
         return papszFileList;
@@ -1235,9 +2338,14 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
     
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
+    const char* pszOptionVal =
+        CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
+    int bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
+                       CSLTestBoolean(pszOptionVal);
+
     /* Does it look like a FTP directory ? */
     if (strncmp(osFilename, "/vsicurl/ftp", strlen("/vsicurl/ftp")) == 0 &&
-        pszFilename[strlen(osFilename) - 1] == '/')
+        pszFilename[strlen(osFilename) - 1] == '/' && !bSkipReadDir)
     {
         char** papszFileList = ReadDir(osFilename);
         if (papszFileList)
@@ -1252,34 +2360,29 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
         return -1;
     }
     else if (strchr(CPLGetFilename(osFilename), '.') != NULL &&
-             strncmp(CPLGetExtension(osFilename), "zip", 3) != 0)
+             strncmp(CPLGetExtension(osFilename), "zip", 3) != 0 &&
+             !bSkipReadDir)
     {
         int bGotFileList;
         char** papszFileList = ReadDir(CPLGetDirname(osFilename), &bGotFileList);
-        int bFound = (CSLFindStringSensitive(papszFileList, CPLGetFilename(osFilename)) != -1);
+        int bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
         CSLDestroy(papszFileList);
         if (bGotFileList && !bFound)
         {
             return -1;
         }
-        if (bGotFileList && bFound && (nFlags & VSI_STAT_SIZE_FLAG) == 0)
-        {
-            pStatBuf->st_mode = S_IFREG;
-            pStatBuf->st_size = 0;
-            return 0;
-        }
     }
 
     VSICurlHandle oHandle( this, osFilename + strlen("/vsicurl/"));
 
-    pStatBuf->st_mode = S_IFREG;
-    pStatBuf->st_size = (nFlags & VSI_STAT_SIZE_FLAG) ? oHandle.GetFileSize() : 0;
+    if ( oHandle.IsKnownFileSize() ||
+         ((nFlags & VSI_STAT_SIZE_FLAG) && !oHandle.IsDirectory() &&
+           CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE", "YES"))) )
+        pStatBuf->st_size = oHandle.GetFileSize();
 
     int nRet = (oHandle.Exists()) ? 0 : -1;
-    if (nRet == 0 && oHandle.IsDirectory())
-    {
-        pStatBuf->st_mode = S_IFDIR;
-    }
+    pStatBuf->st_mtime = oHandle.GetMTime();
+    pStatBuf->st_mode = oHandle.IsDirectory() ? S_IFDIR : S_IFREG;
     return nRet;
 }
 
@@ -1342,11 +2445,20 @@ char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname, int* pbGotFile
 
     CPLMutexHolder oHolder( &hMutex );
 
+    /* If we know the file exists and is not a directory, then don't try to list its content */
+    CachedFileProp* cachedFileProp = GetCachedFileProp(osDirname.c_str() + strlen("/vsicurl/"));
+    if (cachedFileProp->eExists == EXIST_YES && !cachedFileProp->bIsDirectory)
+    {
+        if (pbGotFileList)
+            *pbGotFileList = TRUE;
+        return NULL;
+    }
+
     CachedDirList* psCachedDirList = cacheDirList[osDirname];
     if (psCachedDirList == NULL)
     {
         psCachedDirList = (CachedDirList*) CPLMalloc(sizeof(CachedDirList));
-        psCachedDirList->papszFileList = VSICurlGetFileList(osDirname, &psCachedDirList->bGotFileList);
+        psCachedDirList->papszFileList = GetFileList(osDirname, &psCachedDirList->bGotFileList);
         cacheDirList[osDirname] = psCachedDirList;
     }
 
@@ -1369,6 +2481,37 @@ char** VSICurlFilesystemHandler::ReadDir( const char *pszDirname )
 /*                   VSIInstallCurlFileHandler()                        */
 /************************************************************************/
 
+/**
+ * \brief Install /vsicurl/ HTTP/FTP file system handler (requires libcurl)
+ *
+ * A special file handler is installed that allows reading on-the-fly of files
+ * available through HTTP/FTP web protocols, without downloading the entire file.
+ *
+ * Recognized filenames are of the form /vsicurl/http://path/to/remote/ressource or
+ * /vsicurl/ftp://path/to/remote/ressource where path/to/remote/ressource is the
+ * URL of a remote ressource.
+ *
+ * Partial downloads (requires the HTTP server to support random reading) are done
+ * with a 16 KB granularity by default. If the driver detects sequential reading
+ * it will progressively increase the chunk size up to 2 MB to improve download
+ * performance.
+ *
+ * The GDAL_HTTP_PROXY and GDAL_HTTP_PROXYUSERPWD configuration options can be
+ * used to define a proxy server. The syntax to use is the one of Curl CURLOPT_PROXY
+ * and CURLOPT_PROXYUSERPWD options.
+ *
+ * VSIStatL() will return the size in st_size member and file
+ * nature- file or directory - in st_mode member (the later only reliable with FTP
+ * resources for now).
+ *
+ * VSIReadDir() should be able to parse the HTML directory listing returned by the
+ * most popular web servers, such as Apache or Microsoft IIS.
+ *
+ * This special file handler can be combined with other virtual filesystems handlers,
+ * such as /vsizip. For example, /vsizip//vsicurl/path/to/remote/file.zip/path/inside/zip
+ *
+ * @since GDAL 1.8.0
+ */
 void VSIInstallCurlFileHandler(void)
 {
     VSIFileManager::InstallHandler( "/vsicurl/", new VSICurlFilesystemHandler );
diff --git a/port/cpl_vsil_gzip.cpp b/port/cpl_vsil_gzip.cpp
index 46f21e7..93f2a82 100644
--- a/port/cpl_vsil_gzip.cpp
+++ b/port/cpl_vsil_gzip.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_gzip.cpp 21502 2011-01-15 15:28:54Z rouault $
+ * $Id: cpl_vsil_gzip.cpp 23588 2011-12-17 13:36:47Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for gz/zip files (.gz and .zip).
@@ -84,7 +84,7 @@
 #include "cpl_minizip_unzip.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: cpl_vsil_gzip.cpp 21502 2011-01-15 15:28:54Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_gzip.cpp 23588 2011-12-17 13:36:47Z rouault $");
 
 #define Z_BUFSIZE 65536  /* original size is 16384 */
 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
@@ -187,6 +187,7 @@ class VSIGZipFilesystemHandler : public VSIFilesystemHandler
 {
     void* hMutex;
     VSIGZipHandle* poHandleLastGZipFile;
+    int            bInSaveInfo;
 
 public:
     VSIGZipFilesystemHandler();
@@ -530,7 +531,7 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
         stream.next_in = inbuf;
         if (whence == SEEK_CUR)
         {
-            if (out + offset < 0 || out + offset > compressed_size)
+            if (out + offset > compressed_size)
             {
                 CPL_VSIL_GZ_RETURN_MINUS_ONE();
                 return -1L;
@@ -540,7 +541,7 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
         }
         else if (whence == SEEK_SET)
         {
-            if (offset < 0 || offset > compressed_size)
+            if (offset > compressed_size)
             {
                 CPL_VSIL_GZ_RETURN_MINUS_ONE();
                 return -1L;
@@ -613,10 +614,6 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
     if (whence == SEEK_CUR) {
         offset += out;
     }
-    if (offset < 0) {
-        CPL_VSIL_GZ_RETURN_MINUS_ONE();
-        return -1L;
-    }
 
     /* For a negative seek, rewind and use positive seek */
     if (offset >= out) {
@@ -799,7 +796,7 @@ size_t VSIGZipHandle::Read( void *buf, size_t nSize, size_t nMemb )
         {
             vsi_l_offset uncompressed_pos = VSIFTellL((VSILFILE*)poBaseHandle);
             GZipSnapshot* snapshot = &snapshots[(uncompressed_pos - startOff) / snapshot_byte_interval];
-            if (uncompressed_pos >= 0 && snapshot->uncompressed_pos == 0)
+            if (snapshot->uncompressed_pos == 0)
             {
                 snapshot->crc = crc32 (crc, pStart, (uInt) (stream.next_out - pStart));
                 if (ENABLE_DEBUG)
@@ -1219,6 +1216,7 @@ VSIGZipFilesystemHandler::VSIGZipFilesystemHandler()
     hMutex = NULL;
 
     poHandleLastGZipFile = NULL;
+    bInSaveInfo = FALSE;
 }
 
 /************************************************************************/
@@ -1242,6 +1240,10 @@ VSIGZipFilesystemHandler::~VSIGZipFilesystemHandler()
 void VSIGZipFilesystemHandler::SaveInfo(  VSIGZipHandle* poHandle )
 {
     CPLMutexHolder oHolder(&hMutex);
+
+    if (bInSaveInfo)
+        return;
+    bInSaveInfo = TRUE;
     
     CPLAssert(poHandle->GetBaseFileName() != NULL);
 
@@ -1250,17 +1252,23 @@ void VSIGZipFilesystemHandler::SaveInfo(  VSIGZipHandle* poHandle )
     {
         if (poHandle->GetLastReadOffset() > poHandleLastGZipFile->GetLastReadOffset())
         {
-            delete poHandleLastGZipFile;
+            VSIGZipHandle* poTmp = poHandleLastGZipFile;
+            poHandleLastGZipFile = NULL;
+            delete poTmp;
             poHandleLastGZipFile = poHandle->Duplicate();
             poHandleLastGZipFile->CloseBaseHandle();
         }
     }
     else
     {
-        delete poHandleLastGZipFile;
+        VSIGZipHandle* poTmp = poHandleLastGZipFile;
+        poHandleLastGZipFile = NULL;
+        delete poTmp;
         poHandleLastGZipFile = poHandle->Duplicate();
         poHandleLastGZipFile->CloseBaseHandle();
     }
+
+    bInSaveInfo = FALSE;
 }
 
 /************************************************************************/
@@ -1511,6 +1519,7 @@ char** VSIGZipFilesystemHandler::ReadDir( const char *pszDirname )
  *
  * Additional documentation is to be found at http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
  *
+ * @since GDAL 1.6.0
  */
 
 void VSIInstallGZipFileHandler(void)
@@ -1610,7 +1619,7 @@ void VSIZipReader::SetInfo()
     brokendowntime.tm_hour = file_info.tmu_date.tm_hour;
     brokendowntime.tm_mday = file_info.tmu_date.tm_mday;
     brokendowntime.tm_mon = file_info.tmu_date.tm_mon;
-    brokendowntime.tm_year = file_info.tmu_date.tm_year;
+    brokendowntime.tm_year = file_info.tmu_date.tm_year - 1900; /* the minizip conventions differs from the Unix one */
     nModifiedTime = CPLYMDHMSToUnixTime(&brokendowntime);
 
     cpl_unzGetFilePos(unzF, &this->file_pos);
@@ -1849,13 +1858,17 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
 
     delete poReader;
 
-    return new VSIGZipHandle(poVirtualHandle,
+    VSIGZipHandle* poGZIPHandle = new VSIGZipHandle(poVirtualHandle,
                              NULL,
                              pos,
                              file_info.compressed_size,
                              file_info.uncompressed_size,
                              file_info.crc,
                              file_info.compression_method == 0);
+    /* Wrap the VSIGZipHandle inside a buffered reader that will */
+    /* improve dramatically performance when doing small backward */
+    /* seeks */
+    return VSICreateBufferedReaderHandle(poGZIPHandle);
 }
 
 /************************************************************************/
@@ -1976,8 +1989,6 @@ VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite( const char *pszFilename
     std::map<CPLString,VSIArchiveContent*>::iterator iter = oFileList.find(osZipFilename);
     if (iter != oFileList.end())
     {
-        oFileList.erase(iter);
-
         VSIArchiveContent* content = iter->second;
         int i;
         for(i=0;i<content->nEntries;i++)
@@ -1987,6 +1998,8 @@ VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite( const char *pszFilename
         }
         CPLFree(content->entries);
         delete content;
+
+        oFileList.erase(iter);
     }
 
     VSIZipWriteHandle* poZIPHandle;
@@ -2219,12 +2232,36 @@ void  VSIZipWriteHandle::StartNewFile(VSIZipWriteHandle* poSubFile)
 /**
  * \brief Install ZIP file system handler. 
  *
- * A special file handler is installed that allows reading on-the-fly in ZIP (.zip) archives.
- * All portions of the file system underneath the base
- * path "/vsizip/" will be handled by this driver.
+ * A special file handler is installed that allows reading on-the-fly in ZIP
+ * (.zip) archives.
+ *
+ * All portions of the file system underneath the base path "/vsizip/" will be
+ * handled by this driver.
+ *
+ * The syntax to open a file inside a zip file is /vsizip/path/to/the/file.zip/path/inside/the/zip/file
+ * were path/to/the/file.zip is relative or absolute and path/inside/the/zip/file
+ * is the relative path to the file inside the archive.
+ * 
+ * If the path is absolute, it should begin with a / on a Unix-like OS (or C:\ on Windows),
+ * so the line looks like /vsizip//home/gdal/...
+ * For example gdalinfo /vsizip/myarchive.zip/subdir1/file1.tif
+ *
+ * Syntaxic sugar : if the .zip file contains only one file located at its root,
+ * just mentionning "/vsizip/path/to/the/file.zip" will work
+ *
+ * VSIStatL() will return the uncompressed size in st_size member and file
+ * nature- file or directory - in st_mode member.
+ *
+ * Directory listing is available through VSIReadDir().
+ *
+ * Since GDAL 1.8.0, write capabilities are available. They allow creating
+ * a new zip file and adding new files to an already existing (or just created)
+ * zip file. Read and write operations cannot be interleaved : the new zip must
+ * be closed before being re-opened for read.
  *
  * Additional documentation is to be found at http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
  *
+ * @since GDAL 1.6.0
  */
 
 void VSIInstallZipFileHandler(void)
diff --git a/port/cpl_vsil_stdin.cpp b/port/cpl_vsil_stdin.cpp
index 3bf8248..b9090f1 100644
--- a/port/cpl_vsil_stdin.cpp
+++ b/port/cpl_vsil_stdin.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdin.cpp 20794 2010-10-08 16:58:27Z warmerdam $
+ * $Id: cpl_vsil_stdin.cpp 21689 2011-02-12 12:18:14Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdin
@@ -38,7 +38,7 @@
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdin.cpp 20794 2010-10-08 16:58:27Z warmerdam $");
+CPL_CVSID("$Id: cpl_vsil_stdin.cpp 21689 2011-02-12 12:18:14Z rouault $");
 
 /* We buffer the first 1MB of standard input to enable drivers */
 /* to autodetect data. In the first MB, backward and forward seeking */
@@ -357,9 +357,20 @@ int VSIStdinFilesystemHandler::Stat( const char * pszFilename,
 }
 
 /************************************************************************/
-/*                       VSIInstallStdinHandler()                      */
+/*                       VSIInstallStdinHandler()                       */
 /************************************************************************/
 
+/**
+ * \brief Install /vsistdin/ file system handler
+ *
+ * A special file handler is installed that allows reading from the standard
+ * input steam.
+ *
+ * The file operations available are of course limited to Read() and
+ * forward Seek() (full seek in the first MB of a file).
+ *
+ * @since GDAL 1.8.0
+ */
 void VSIInstallStdinHandler()
 
 {
diff --git a/port/cpl_vsil_stdout.cpp b/port/cpl_vsil_stdout.cpp
index 7f06951..58e1e49 100644
--- a/port/cpl_vsil_stdout.cpp
+++ b/port/cpl_vsil_stdout.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdout.cpp 20794 2010-10-08 16:58:27Z warmerdam $
+ * $Id: cpl_vsil_stdout.cpp 21906 2011-03-06 16:41:27Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdout
@@ -37,7 +37,7 @@
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdout.cpp 20794 2010-10-08 16:58:27Z warmerdam $");
+CPL_CVSID("$Id: cpl_vsil_stdout.cpp 21906 2011-03-06 16:41:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -189,12 +189,197 @@ int VSIStdoutFilesystemHandler::Stat( const char * pszFilename,
     return -1;
 }
 
+
+
+/************************************************************************/
+/* ==================================================================== */
+/*                   VSIStdoutRedirectFilesystemHandler                 */
+/* ==================================================================== */
+/************************************************************************/
+
+class VSIStdoutRedirectFilesystemHandler : public VSIFilesystemHandler
+{
+public:
+    virtual VSIVirtualHandle *Open( const char *pszFilename,
+                                    const char *pszAccess);
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        VSIStdoutRedirectHandle                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class VSIStdoutRedirectHandle : public VSIVirtualHandle
+{
+    VSIVirtualHandle* poHandle;
+  public:
+                      VSIStdoutRedirectHandle(VSIVirtualHandle* poHandle);
+                     ~VSIStdoutRedirectHandle();
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
+    virtual vsi_l_offset Tell();
+    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
+    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
+    virtual int       Eof();
+    virtual int       Flush();
+    virtual int       Close();
+};
+
+/************************************************************************/
+/*                        VSIStdoutRedirectHandle()                    */
+/************************************************************************/
+
+VSIStdoutRedirectHandle::VSIStdoutRedirectHandle(VSIVirtualHandle* poHandle)
+{
+    this->poHandle = poHandle;
+}
+
+/************************************************************************/
+/*                        ~VSIStdoutRedirectHandle()                    */
+/************************************************************************/
+
+VSIStdoutRedirectHandle::~VSIStdoutRedirectHandle()
+{
+    delete poHandle;
+}
+
+/************************************************************************/
+/*                                Seek()                                */
+/************************************************************************/
+
+int VSIStdoutRedirectHandle::Seek( vsi_l_offset nOffset, int nWhence )
+
+{
+    CPLError(CE_Failure, CPLE_NotSupported, "Seek() unsupported on /vsistdout_redirect");
+    return -1;
+}
+
+/************************************************************************/
+/*                                Tell()                                */
+/************************************************************************/
+
+vsi_l_offset VSIStdoutRedirectHandle::Tell()
+{
+    return poHandle->Tell();
+}
+
+/************************************************************************/
+/*                               Flush()                                */
+/************************************************************************/
+
+int VSIStdoutRedirectHandle::Flush()
+
+{
+    return poHandle->Flush();
+}
+
+/************************************************************************/
+/*                                Read()                                */
+/************************************************************************/
+
+size_t VSIStdoutRedirectHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
+
+{
+    CPLError(CE_Failure, CPLE_NotSupported, "Read() unsupported on /vsistdout_redirect");
+    return 0;
+}
+
+/************************************************************************/
+/*                               Write()                                */
+/************************************************************************/
+
+size_t VSIStdoutRedirectHandle::Write( const void * pBuffer, size_t nSize,
+                                  size_t nCount )
+
+{
+    return poHandle->Write(pBuffer, nSize, nCount);
+}
+
+/************************************************************************/
+/*                                Eof()                                 */
+/************************************************************************/
+
+int VSIStdoutRedirectHandle::Eof()
+
+{
+    return poHandle->Eof();
+}
+
+/************************************************************************/
+/*                               Close()                                */
+/************************************************************************/
+
+int VSIStdoutRedirectHandle::Close()
+
+{
+    return poHandle->Close();
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                 VSIStdoutRedirectFilesystemHandler                   */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+VSIVirtualHandle *
+VSIStdoutRedirectFilesystemHandler::Open( const char *pszFilename,
+                                          const char *pszAccess )
+
+{
+    if ( strchr(pszAccess, 'r') != NULL ||
+         strchr(pszAccess, '+') != NULL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Read or update mode not supported on /vsistdout_redirect");
+        return NULL;
+    }
+
+    VSIVirtualHandle* poHandle = (VSIVirtualHandle* )VSIFOpenL(
+            pszFilename + strlen("/vsistdout_redirect/"), pszAccess);
+    if (poHandle == NULL)
+        return NULL;
+
+    return new VSIStdoutRedirectHandle(poHandle);
+}
+
+/************************************************************************/
+/*                                Stat()                                */
+/************************************************************************/
+
+int VSIStdoutRedirectFilesystemHandler::Stat( const char * pszFilename,
+                                      VSIStatBufL * pStatBuf,
+                                      int nFlags )
+
+{
+    memset( pStatBuf, 0, sizeof(VSIStatBufL) );
+
+    return -1;
+}
+
 /************************************************************************/
 /*                       VSIInstallStdoutHandler()                      */
 /************************************************************************/
 
+/**
+ * \brief Install /vsistdout/ file system handler
+ *
+ * A special file handler is installed that allows writing to the standard
+ * output stream.
+ *
+ * The file operations available are of course limited to Write().
+ *
+ * @since GDAL 1.8.0
+ */
+
 void VSIInstallStdoutHandler()
 
 {
     VSIFileManager::InstallHandler( "/vsistdout/", new VSIStdoutFilesystemHandler );
+    VSIFileManager::InstallHandler( "/vsistdout_redirect/", new VSIStdoutRedirectFilesystemHandler );
 }
diff --git a/port/cpl_vsil_subfile.cpp b/port/cpl_vsil_subfile.cpp
index d93ddc9..f4736fe 100644
--- a/port/cpl_vsil_subfile.cpp
+++ b/port/cpl_vsil_subfile.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_subfile.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl_vsil_subfile.cpp 21533 2011-01-19 18:13:08Z warmerdam $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of subfile virtual IO functions.
@@ -36,7 +36,7 @@
 #  include <wce_errno.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_subfile.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_subfile.cpp 21533 2011-01-19 18:13:08Z warmerdam $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,7 +50,6 @@ class VSISubFileHandle : public VSIVirtualHandle
     VSILFILE     *fp;
     vsi_l_offset  nSubregionOffset;
     vsi_l_offset  nSubregionSize;
-    int           bUpdate;
 
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
     virtual vsi_l_offset Tell();
@@ -307,6 +306,13 @@ VSISubFileFilesystemHandler::Open( const char *pszFilename,
     }
 
 /* -------------------------------------------------------------------- */
+/*      We can't open the containing file with "w" access, so if tht    */
+/*      is requested use "r+" instead to update in place.               */
+/* -------------------------------------------------------------------- */
+    if( pszAccess[0] == 'w' )
+        pszAccess = "r+";
+
+/* -------------------------------------------------------------------- */
 /*      Open the underlying file.                                       */
 /* -------------------------------------------------------------------- */
     VSILFILE *fp = VSIFOpenL( osSubFilePath, pszAccess );
diff --git a/port/cpl_vsil_tar.cpp b/port/cpl_vsil_tar.cpp
index 454a7b0..a978d8b 100644
--- a/port/cpl_vsil_tar.cpp
+++ b/port/cpl_vsil_tar.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_tar.cpp 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl_vsil_tar.cpp 21781 2011-02-21 21:57:41Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for tar files (.tar).
@@ -29,7 +29,7 @@
 
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_tar.cpp 20996 2010-10-28 18:38:15Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_tar.cpp 21781 2011-02-21 21:57:41Z rouault $");
 
 
 /************************************************************************/
@@ -129,8 +129,8 @@ int VSITarReader::GotoNextFile()
         abyHeader[107] != '\0' ||
         abyHeader[115] != '\0' ||
         abyHeader[123] != '\0' ||
-        abyHeader[135] != '\0' ||
-        abyHeader[147] != '\0' ||
+        (abyHeader[135] != '\0' && abyHeader[135] != ' ') ||
+        (abyHeader[147] != '\0' && abyHeader[147] != ' ') ||
         abyHeader[154] != '\0' ||
         abyHeader[155] != ' ')
         return FALSE;
@@ -295,14 +295,32 @@ VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
 /*                    VSIInstallTarFileHandler()                        */
 /************************************************************************/
 
-
 /**
- * \brief Install TAR file system handler. 
+ * \brief Install /vsitar/ file system handler.
+ *
+ * A special file handler is installed that allows reading on-the-fly in TAR
+ * (regular .tar, or compressed .tar.gz/.tgz) archives.
+ *
+ * All portions of the file system underneath the base path "/vsitar/" will be
+ * handled by this driver.
+ *
+ * The syntax to open a file inside a zip file is /vsitar/path/to/the/file.tar/path/inside/the/tar/file
+ * were path/to/the/file.tar is relative or absolute and path/inside/the/tar/file
+ * is the relative path to the file inside the archive.
+ *
+ * If the path is absolute, it should begin with a / on a Unix-like OS (or C:\ on Windows),
+ * so the line looks like /vsitar//home/gdal/...
+ * For example gdalinfo /vsitar/myarchive.tar/subdir1/file1.tif
+ *
+ * Syntaxic sugar : if the tar archive contains only one file located at its root,
+ * just mentionning "/vsitar/path/to/the/file.tar" will work
+ *
+ * VSIStatL() will return the uncompressed size in st_size member and file
+ * nature- file or directory - in st_mode member.
  *
- * A special file handler is installed that allows reading on-the-fly in TAR (.tar, .tar.gz/.tgz) archives.
- * All portions of the file system underneath the base
- * path "/vsitar/" will be handled by this driver.
+ * Directory listing is available through VSIReadDir().
  *
+ * @since GDAL 1.8.0
  */
 
 void VSIInstallTarFileHandler(void)
diff --git a/port/cpl_vsil_unix_stdio_64.cpp b/port/cpl_vsil_unix_stdio_64.cpp
index 36f2036..64bd6f0 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 20774 2010-10-05 20:41:05Z rouault $
+ * $Id: cpl_vsil_unix_stdio_64.cpp 23506 2011-12-10 13:43:59Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Unix platforms with fseek64()
@@ -48,7 +48,7 @@
 #include <dirent.h>
 #include <errno.h>
 
-CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 20774 2010-10-05 20:41:05Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 23506 2011-12-10 13:43:59Z rouault $");
 
 #if defined(UNIX_STDIO_64)
 
@@ -67,6 +67,9 @@ CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 20774 2010-10-05 20:41:05Z rouault $"
 #ifndef VSI_STAT64_T
 #define VSI_STAT64_T stat64
 #endif
+#ifndef VSI_FTRUNCATE64
+#define VSI_FTRUNCATE64 ftruncate64
+#endif
 
 #else /* not UNIX_STDIO_64 */
 
@@ -85,6 +88,9 @@ CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 20774 2010-10-05 20:41:05Z rouault $"
 #ifndef VSI_STAT64_T
 #define VSI_STAT64_T stat
 #endif
+#ifndef VSI_FTRUNCATE64
+#define VSI_FTRUNCATE64 ftruncate
+#endif
 
 #endif /* ndef UNIX_STDIO_64 */
 
@@ -129,6 +135,7 @@ class VSIUnixStdioHandle : public VSIVirtualHandle
     virtual int       Eof();
     virtual int       Flush();
     virtual int       Close();
+    virtual int       Truncate( vsi_l_offset nNewSize );
 };
 
 /************************************************************************/
@@ -155,9 +162,6 @@ int VSIUnixStdioHandle::Seek( vsi_l_offset nOffset, int nWhence )
     if( nWhence == SEEK_SET && nOffset == this->nOffset )
         return 0;
 
-    if( nWhence == SEEK_END && nOffset == 0 && bAtEOF )
-        return 0;
-
     int     nResult = VSI_FSEEK64( fp, nOffset, nWhence );
     int     nError = errno;
 
@@ -191,22 +195,20 @@ int VSIUnixStdioHandle::Seek( vsi_l_offset nOffset, int nWhence )
         if( nWhence == SEEK_SET )
         {
             this->nOffset = nOffset;
-            bAtEOF = FALSE;
         }
         else if( nWhence == SEEK_END )
         {
             this->nOffset = VSI_FTELL64( fp );
-            bAtEOF = TRUE;
         }
         else if( nWhence == SEEK_CUR )
         {
             this->nOffset += nOffset;
-            bAtEOF = FALSE;
         }
     }
         
     bLastOpWrite = FALSE;
     bLastOpRead = FALSE;
+    bAtEOF = FALSE;
 
     errno = nError;
     return nResult;
@@ -277,6 +279,9 @@ size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
     nOffset += nSize * nResult;
     bLastOpWrite = FALSE;
     bLastOpRead = TRUE;
+
+    if (nResult != nCount)
+        bAtEOF = feof(fp);
     
     return nResult;
 }
@@ -327,9 +332,6 @@ size_t VSIUnixStdioHandle::Write( const void * pBuffer, size_t nSize,
 int VSIUnixStdioHandle::Eof()
 
 {
-    if( !bAtEOF )
-        bAtEOF = feof(fp);
-
     if( bAtEOF )
         return 1;
     else
@@ -337,6 +339,18 @@ int VSIUnixStdioHandle::Eof()
 }
 
 /************************************************************************/
+/*                             Truncate()                               */
+/************************************************************************/
+
+int VSIUnixStdioHandle::Truncate( vsi_l_offset nNewSize )
+{
+    fflush(fp);
+    int nRet = VSI_FTRUNCATE64(fileno(fp), nNewSize);
+    return nRet;
+}
+
+
+/************************************************************************/
 /* ==================================================================== */
 /*                       VSIUnixStdioFilesystemHandler                  */
 /* ==================================================================== */
@@ -372,7 +386,20 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
     poHandle->bAtEOF = FALSE;
 
     errno = nError;
-    return poHandle;
+
+/* -------------------------------------------------------------------- */
+/*      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"))
+        && CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
+    {
+        return VSICreateCachedFile( poHandle );
+    }
+    else
+    {
+        return poHandle;
+    }
 }
 
 /************************************************************************/
@@ -438,36 +465,18 @@ char **VSIUnixStdioFilesystemHandler::ReadDir( const char *pszPath )
 {
     DIR           *hDir;
     struct dirent *psDirEntry;
-    char          **papszDir = NULL;
+    CPLStringList  oDir;
 
     if (strlen(pszPath) == 0)
         pszPath = ".";
 
     if ( (hDir = opendir(pszPath)) != NULL )
     {
-        /* In case of really big number of files in the directory, CSLAddString */
-        /* can be slow (see #2158). We then directly build the list. */
-        int nItems=0;
-        int nAllocatedItems=0;
+        // we want to avoid returning NULL for an empty list.
+        oDir.Assign( (char**) CPLCalloc(2,sizeof(char*)) );
+
         while( (psDirEntry = readdir(hDir)) != NULL )
-        {
-            if (nItems == 0)
-            {
-                papszDir = (char**) CPLCalloc(2,sizeof(char*));
-                nAllocatedItems = 1;
-            }
-            else if (nItems >= nAllocatedItems)
-            {
-                nAllocatedItems = nAllocatedItems * 2;
-                papszDir = (char**)CPLRealloc(papszDir, 
-                                              (nAllocatedItems+2)*sizeof(char*));
-            }
-
-            papszDir[nItems] = CPLStrdup(psDirEntry->d_name);
-            papszDir[nItems+1] = NULL;
-
-            nItems++;
-        }
+            oDir.AddString( psDirEntry->d_name );
 
         closedir( hDir );
     }
@@ -478,7 +487,7 @@ char **VSIUnixStdioFilesystemHandler::ReadDir( const char *pszPath )
          */
     }
 
-    return papszDir;
+    return oDir.StealList();
 }
 
 /************************************************************************/
diff --git a/port/cpl_vsil_win32.cpp b/port/cpl_vsil_win32.cpp
index 8bd6ff2..e6af68a 100644
--- a/port/cpl_vsil_win32.cpp
+++ b/port/cpl_vsil_win32.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_win32.cpp 21167 2010-11-24 15:19:51Z warmerdam $
+ * $Id: cpl_vsil_win32.cpp 23506 2011-12-10 13:43:59Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Win32.
@@ -29,7 +29,7 @@
 
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_win32.cpp 21167 2010-11-24 15:19:51Z warmerdam $");
+CPL_CVSID("$Id: cpl_vsil_win32.cpp 23506 2011-12-10 13:43:59Z rouault $");
 
 #if defined(WIN32)
 
@@ -83,6 +83,7 @@ class VSIWin32Handle : public VSIVirtualHandle
 {
   public:
     HANDLE       hFile;
+    int          bEOF;
 
     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
     virtual vsi_l_offset Tell();
@@ -91,6 +92,7 @@ class VSIWin32Handle : public VSIVirtualHandle
     virtual int       Eof();
     virtual int       Flush();
     virtual int       Close();
+    virtual int       Truncate( vsi_l_offset nNewSize );
 };
 
 /************************************************************************/
@@ -199,6 +201,8 @@ int VSIWin32Handle::Seek( vsi_l_offset nOffset, int nWhence )
     GUInt32       nMoveLow;
     LARGE_INTEGER li;
 
+    bEOF = FALSE;
+
     switch(nWhence)
     {
         case SEEK_CUR:
@@ -291,6 +295,9 @@ size_t VSIWin32Handle::Read( void * pBuffer, size_t nSize, size_t nCount )
     else
         nResult = dwSizeRead / nSize;
 
+    if( nResult != nCount )
+        bEOF = TRUE;
+
     return nResult;
 }
 
@@ -325,14 +332,24 @@ size_t VSIWin32Handle::Write( const void *pBuffer, size_t nSize, size_t nCount)
 int VSIWin32Handle::Eof()
 
 {
-    vsi_l_offset       nCur, nEnd;
+    return bEOF;
+}
+
+/************************************************************************/
+/*                             Truncate()                               */
+/************************************************************************/
 
-    nCur = Tell();
-    Seek( 0, SEEK_END );
-    nEnd = Tell();
+int VSIWin32Handle::Truncate( vsi_l_offset nNewSize )
+{
+    vsi_l_offset nCur = Tell();
+    Seek( nNewSize, SEEK_SET );
+    BOOL bRes = SetEndOfFile( hFile );
     Seek( nCur, SEEK_SET );
 
-    return (nCur == nEnd);
+    if (bRes)
+        return 0;
+    else
+        return -1;
 }
 
 /************************************************************************/
@@ -352,7 +369,9 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
     DWORD dwDesiredAccess, dwCreationDisposition, dwFlagsAndAttributes;
     HANDLE hFile;
 
-    if( strchr(pszAccess, '+') != NULL || strchr(pszAccess, 'w') != 0 )
+    if( strchr(pszAccess, '+') != NULL ||
+        strchr(pszAccess, 'w') != 0 ||
+        strchr(pszAccess, 'a') != 0 )
         dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
     else
         dwDesiredAccess = GENERIC_READ;
@@ -404,12 +423,29 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
         errno = ErrnoFromGetLastError();
         return NULL;
     }
+
+/* -------------------------------------------------------------------- */
+/*      Create a VSI file handle.                                       */
+/* -------------------------------------------------------------------- */
+    VSIWin32Handle *poHandle = new VSIWin32Handle;
+    
+    poHandle->hFile = hFile;
+    poHandle->bEOF = FALSE;
+    
+    if (strchr(pszAccess, 'a') != 0)
+        poHandle->Seek(0, SEEK_END);
+    
+/* -------------------------------------------------------------------- */
+/*      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"))
+        && CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
+    {
+        return VSICreateCachedFile( poHandle );
+    }
     else
     {
-        VSIWin32Handle *poHandle = new VSIWin32Handle;
-        
-        poHandle->hFile = hFile;
-        
         return poHandle;
     }
 }
@@ -569,7 +605,8 @@ char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
     {
         struct _wfinddata_t c_file;
         intptr_t hFile;
-        char    *pszFileSpec, **papszDir = NULL;
+        char    *pszFileSpec;
+        CPLStringList oDir;
         
         if (strlen(pszPath) == 0)
             pszPath = ".";
@@ -580,29 +617,10 @@ char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
         
         if ( (hFile = _wfindfirst( pwszFileSpec, &c_file )) != -1L )
         {
-            /* In case of really big number of files in the directory, CSLAddString */
-            /* can be slow (see #2158). We then directly build the list. */
-            int nItems=0;
-            int nAllocatedItems=0;
             do
             {
-                if (nItems == 0)
-                {
-                    papszDir = (char**) CPLCalloc(2,sizeof(char*));
-                    nAllocatedItems = 1;
-                }
-                else if (nItems >= nAllocatedItems)
-                {
-                    nAllocatedItems = nAllocatedItems * 2;
-                    papszDir = (char**)CPLRealloc(papszDir, 
-                                                  (nAllocatedItems+2)*sizeof(char*));
-                }
-                
-                papszDir[nItems] =
-                    CPLRecodeFromWChar(c_file.name,CPL_ENC_UCS2,CPL_ENC_UTF8);
-                papszDir[nItems+1] = NULL;
-                
-                nItems++;
+                oDir.AddStringDirectly(
+                    CPLRecodeFromWChar(c_file.name,CPL_ENC_UCS2,CPL_ENC_UTF8));
             } while( _wfindnext( hFile, &c_file ) == 0 );
             
             _findclose( hFile );
@@ -617,14 +635,15 @@ char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
         CPLFree(pszFileSpec);
         CPLFree(pwszFileSpec);
 
-        return papszDir;
+        return oDir.StealList();
     }
     else
 #endif
     {
         struct _finddata_t c_file;
         intptr_t hFile;
-        char    *pszFileSpec, **papszDir = NULL;
+        char    *pszFileSpec;
+        CPLStringList oDir;
         
         if (strlen(pszPath) == 0)
             pszPath = ".";
@@ -633,28 +652,9 @@ char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
         
         if ( (hFile = _findfirst( pszFileSpec, &c_file )) != -1L )
         {
-            /* In case of really big number of files in the directory, CSLAddString */
-            /* can be slow (see #2158). We then directly build the list. */
-            int nItems=0;
-            int nAllocatedItems=0;
             do
             {
-                if (nItems == 0)
-                {
-                    papszDir = (char**) CPLCalloc(2,sizeof(char*));
-                    nAllocatedItems = 1;
-                }
-                else if (nItems >= nAllocatedItems)
-                {
-                    nAllocatedItems = nAllocatedItems * 2;
-                    papszDir = (char**)CPLRealloc(papszDir, 
-                                                  (nAllocatedItems+2)*sizeof(char*));
-                }
-                
-                papszDir[nItems] = CPLStrdup(c_file.name);
-                papszDir[nItems+1] = NULL;
-                
-                nItems++;
+                oDir.AddString(c_file.name);
             } while( _findnext( hFile, &c_file ) == 0 );
             
             _findclose( hFile );
@@ -667,8 +667,8 @@ char **VSIWin32FilesystemHandler::ReadDir( const char *pszPath )
         }
 
         CPLFree(pszFileSpec);
-
-        return papszDir;
+        
+        return oDir.StealList();
     }
 }
 
diff --git a/port/cpl_vsisimple.cpp b/port/cpl_vsisimple.cpp
index 72ece7e..7a8beb9 100644
--- a/port/cpl_vsisimple.cpp
+++ b/port/cpl_vsisimple.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsisimple.cpp 20666 2010-09-21 23:13:27Z warmerdam $
+ * $Id: cpl_vsisimple.cpp 23604 2011-12-19 22:49:08Z rouault $
  *
  * Project:  Common Portability Library 
  * Purpose:  Simple implementation of POSIX VSI functions.
@@ -52,7 +52,7 @@
 /* DEBUG_VSIMALLOC must also be defined */
 //#define DEBUG_VSIMALLOC_VERBOSE
 
-CPL_CVSID("$Id: cpl_vsisimple.cpp 20666 2010-09-21 23:13:27Z warmerdam $");
+CPL_CVSID("$Id: cpl_vsisimple.cpp 23604 2011-12-19 22:49:08Z rouault $");
 
 /* for stat() */
 
@@ -330,6 +330,9 @@ static GUIntBig nVSIFrees = 0;
 
 void VSIShowMemStats()
 {
+    char* pszShowMemStats = getenv("CPL_SHOW_MEM_STATS");
+    if (pszShowMemStats == NULL || pszShowMemStats[0] == '\0' )
+        return;
     printf("Current VSI memory usage        : " CPL_FRMT_GUIB " bytes\n",
             (GUIntBig)nCurrentTotalAllocs);
     printf("Maximum VSI memory usage        : " CPL_FRMT_GUIB " bytes\n",
@@ -347,6 +350,11 @@ void VSIShowMemStats()
 }
 #endif
 
+#ifdef DEBUG_VSIMALLOC
+static GIntBig nMaxPeakAllocSize = -1;
+static GIntBig nMaxCumulAllocSize = -1;
+#endif
+
 /************************************************************************/
 /*                             VSICalloc()                              */
 /************************************************************************/
@@ -362,19 +370,45 @@ void *VSICalloc( size_t nCount, size_t nSize )
                 (int)nCount, (int)nSize);
         return NULL;
     }
-    void* ptr = VSIMalloc(nCount * nSize);
-    if (ptr == NULL)
+    if (nMaxPeakAllocSize < 0)
+    {
+        char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
+        nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
+        char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
+        nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
+    }
+    if (nMaxPeakAllocSize > 0 && (GIntBig)nMul > nMaxPeakAllocSize)
         return NULL;
-
-    memset(ptr, 0, nCount * nSize);
 #ifdef DEBUG_VSIMALLOC_STATS
+    if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nMul > nMaxCumulAllocSize)
+        return NULL;
+#endif
+    char* ptr = (char*) calloc(1, 2 * sizeof(void*) + nMul);
+    if (ptr == NULL)
+        return NULL;
+    ptr[0] = 'V';
+    ptr[1] = 'S';
+    ptr[2] = 'I';
+    ptr[3] = 'M';
+    memcpy(ptr + sizeof(void*), &nMul, sizeof(void*));
+#if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
     {
         CPLMutexHolderD(&hMemStatMutex);
+#ifdef DEBUG_VSIMALLOC_VERBOSE
+        fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p\n",
+                (void*)CPLGetPID(), (int)nCount, (int)nSize, ptr + 2 * sizeof(void*));
+#endif
+#ifdef DEBUG_VSIMALLOC_STATS
         nVSICallocs ++;
-        nVSIMallocs --;
+        if (nMaxTotalAllocs == 0)
+            atexit(VSIShowMemStats);
+        nCurrentTotalAllocs += nMul;
+        if (nCurrentTotalAllocs > nMaxTotalAllocs)
+            nMaxTotalAllocs = nCurrentTotalAllocs;
+#endif
     }
 #endif
-    return ptr;
+    return ptr + 2 * sizeof(void*);
 #else
     return( calloc( nCount, nSize ) );
 #endif
@@ -388,6 +422,19 @@ void *VSIMalloc( size_t nSize )
 
 {
 #ifdef DEBUG_VSIMALLOC
+    if (nMaxPeakAllocSize < 0)
+    {
+        char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
+        nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
+        char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
+        nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
+    }
+    if (nMaxPeakAllocSize > 0 && (GIntBig)nSize > nMaxPeakAllocSize)
+        return NULL;
+#ifdef DEBUG_VSIMALLOC_STATS
+    if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nSize > nMaxCumulAllocSize)
+        return NULL;
+#endif
     char* ptr = (char*) malloc(2 * sizeof(void*) + nSize);
     if (ptr == NULL)
         return NULL;
@@ -450,9 +497,22 @@ void * VSIRealloc( void * pData, size_t nNewSize )
     memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
 #endif
 
-    ptr = (char*) realloc(ptr, nNewSize + 2 * sizeof(void*));
-    if (ptr == NULL)
+    if (nMaxPeakAllocSize < 0)
+    {
+        char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
+        nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
+    }
+    if (nMaxPeakAllocSize > 0 && (GIntBig)nNewSize > nMaxPeakAllocSize)
+        return NULL;
+#ifdef DEBUG_VSIMALLOC_STATS
+    if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nNewSize - (GIntBig)nOldSize > nMaxCumulAllocSize)
+        return NULL;
+#endif
+
+    void* newptr = realloc(ptr, nNewSize + 2 * sizeof(void*));
+    if (newptr == NULL)
         return NULL;
+    ptr = (char*) newptr;
     memcpy(ptr + sizeof(void*), &nNewSize, sizeof(void*));
 
 #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
diff --git a/port/cplstring.cpp b/port/cplstring.cpp
index 66144a4..8043183 100644
--- a/port/cplstring.cpp
+++ b/port/cplstring.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplstring.cpp 21815 2011-02-23 22:56:54Z warmerdam $
+ * $Id: cplstring.cpp 23406 2011-11-21 19:29:41Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  CPLString implementation.
@@ -30,7 +30,7 @@
 #include "cpl_string.h"
 #include <string>
 
-CPL_CVSID("$Id: cplstring.cpp 21815 2011-02-23 22:56:54Z warmerdam $");
+CPL_CVSID("$Id: cplstring.cpp 23406 2011-11-21 19:29:41Z rouault $");
 
 /*
  * The CPLString class is derived from std::string, so the vast majority 
@@ -238,7 +238,12 @@ CPLString &CPLString::Recode( const char *pszSrcEncoding,
 /************************************************************************/
 
 /** 
- * Case insensitive find() alternative. 
+ * Case insensitive find() alternative.
+ *
+ * @param str substring to find.
+ * @param pos offset in the string at which the search starts.
+ * @return the position of substring in the string or std::string::npos if not found.
+ * @since GDAL 1.9.0
  */
 
 size_t CPLString::ifind( const std::string & str, size_t pos ) const
@@ -247,11 +252,20 @@ size_t CPLString::ifind( const std::string & str, size_t pos ) const
     return ifind( str.c_str(), pos );
 }
 
+/**
+ * Case insensitive find() alternative.
+ *
+ * @param s substring to find.
+ * @param nPos offset in the string at which the search starts.
+ * @return the position of the substring in the string or std::string::npos if not found.
+ * @since GDAL 1.9.0
+ */
+
 size_t CPLString::ifind( const char *s, size_t nPos ) const
 
 {
     const char *pszHaystack = c_str();
-    char chFirst = (char) tolower( s[0] );
+    char chFirst = (char) ::tolower( s[0] );
     int nTargetLen = strlen(s);
 
     if( nPos > size() )
@@ -261,7 +275,7 @@ size_t CPLString::ifind( const char *s, size_t nPos ) const
 
     while( *pszHaystack != '\0' )
     {
-        if( chFirst == tolower(*pszHaystack) )
+        if( chFirst == ::tolower(*pszHaystack) )
         {
             if( EQUALN(pszHaystack,s,nTargetLen) )
                 return nPos;
@@ -273,3 +287,131 @@ size_t CPLString::ifind( const char *s, size_t nPos ) const
 
     return std::string::npos;
 }
+
+/************************************************************************/
+/*                              toupper()                               */
+/************************************************************************/
+
+/**
+ * Convert to upper case in place.
+ */
+
+CPLString &CPLString::toupper()
+
+{
+    size_t i;
+
+    for( i = 0; i < size(); i++ )
+        (*this)[i] = (char) ::toupper( (*this)[i] );
+
+    return *this;
+}
+
+/************************************************************************/
+/*                              tolower()                               */
+/************************************************************************/
+
+/**
+ * Convert to lower case in place.
+ */
+
+CPLString &CPLString::tolower()
+
+{
+    size_t i;
+
+    for( i = 0; i < size(); i++ )
+        (*this)[i] = (char) ::tolower( (*this)[i] );
+
+    return *this;
+}
+
+/************************************************************************/
+/*                         CPLURLGetValue()                             */
+/************************************************************************/
+
+/**
+ * Return the value matching a key from a key=value pair in a URL.
+ *
+ * @param pszURL the URL.
+ * @param pszKey the key to find.
+ * @return the value of empty string if not found.
+ * @since GDAL 1.9.0
+ */
+CPLString CPLURLGetValue(const char* pszURL, const char* pszKey)
+{
+    CPLString osKey(pszKey);
+    osKey += "=";
+    size_t nKeyPos = CPLString(pszURL).ifind(osKey);
+    if (nKeyPos != std::string::npos && nKeyPos > 0 &&
+        (pszURL[nKeyPos-1] == '?' || pszURL[nKeyPos-1] == '&'))
+    {
+        CPLString osValue(pszURL + nKeyPos + strlen(osKey));
+        const char* pszValue = osValue.c_str();
+        const char* pszSep = strchr(pszValue, '&');
+        if (pszSep)
+        {
+            osValue.resize(pszSep - pszValue);
+        }
+        return osValue;
+    }
+    return "";
+}
+
+/************************************************************************/
+/*                          CPLURLAddKVP()                              */
+/************************************************************************/
+
+/**
+ * Return a new URL with a new key=value pair.
+ *
+ * @param pszURL the URL.
+ * @param pszKey the key to find.
+ * @param pszValue the value of the key (may be NULL to unset an existing KVP).
+ * @return the modified URL.
+ * @since GDAL 1.9.0
+ */
+CPLString CPLURLAddKVP(const char* pszURL, const char* pszKey,
+                       const char* pszValue)
+{
+    CPLString osURL(pszURL);
+    if (strchr(osURL, '?') == NULL)
+        osURL += "?";
+    pszURL = osURL.c_str();
+
+    CPLString osKey(pszKey);
+    osKey += "=";
+    size_t nKeyPos = osURL.ifind(osKey);
+    if (nKeyPos != std::string::npos && nKeyPos > 0 &&
+        (pszURL[nKeyPos-1] == '?' || pszURL[nKeyPos-1] == '&'))
+    {
+        CPLString osNewURL(osURL);
+        osNewURL.resize(nKeyPos);
+        if (pszValue)
+        {
+            osNewURL += osKey;
+            osNewURL += pszValue;
+        }
+        const char* pszNext = strchr(pszURL + nKeyPos, '&');
+        if (pszNext)
+        {
+            if (osNewURL[osNewURL.size()-1] == '&'
+                || osNewURL[osNewURL.size()-1] == '?' )
+                osNewURL += pszNext + 1;
+            else
+                osNewURL += pszNext;
+        }
+        return osNewURL;
+    }
+    else
+    {
+        if (pszValue)
+        {
+            if (osURL[osURL.size()-1] != '&' && osURL[osURL.size()-1] != '?')
+                osURL += '&';
+            osURL += osKey;
+            osURL += pszValue;
+        }
+        return osURL;
+    }
+}
diff --git a/port/cplstringlist.cpp b/port/cplstringlist.cpp
new file mode 100755
index 0000000..cf07b1a
--- /dev/null
+++ b/port/cplstringlist.cpp
@@ -0,0 +1,738 @@
+/******************************************************************************
+ * $Id: cplstringlist.cpp 23043 2011-09-04 15:28:19Z rouault $
+ *
+ * Project:  GDAL 
+ * Purpose:  CPLStringList implementation.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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 "cpl_string.h"
+#include <string>
+
+CPL_CVSID("$Id: cplstringlist.cpp 23043 2011-09-04 15:28:19Z rouault $");
+
+/************************************************************************/
+/*                           CPLStringList()                            */
+/************************************************************************/
+
+CPLStringList::CPLStringList()
+
+{
+    Initialize();
+}
+
+/************************************************************************/
+/*                           CPLStringList()                            */
+/************************************************************************/
+
+/**
+ * CPLStringList constructor.
+ *
+ * @param papszListIn the NULL terminated list of strings to consume.
+ * @param bTakeOwnership TRUE if the CPLStringList should take ownership
+ * of the list of strings which implies responsibility to free them.
+ */
+
+CPLStringList::CPLStringList( char **papszListIn, int bTakeOwnership )
+
+{
+    Initialize();
+    Assign( papszListIn, bTakeOwnership );
+}
+
+/************************************************************************/
+/*                           CPLStringList()                            */
+/************************************************************************/
+
+//! Copy constructor
+CPLStringList::CPLStringList( const CPLStringList &oOther )
+
+{
+    Initialize();
+    Assign( oOther.papszList, FALSE );
+
+    // We don't want to just retain a reference to the others list
+    // as we don't want to make assumptions about it's lifetime that
+    // might surprise the client developer.
+    MakeOurOwnCopy();
+    bIsSorted = oOther.bIsSorted;
+}
+
+/************************************************************************/
+/*                             operator=()                              */
+/************************************************************************/
+
+CPLStringList &CPLStringList::operator=(const CPLStringList& oOther)
+{
+    if (this != &oOther)
+    {
+        Assign( oOther.papszList, FALSE );
+
+        // We don't want to just retain a reference to the others list
+        // as we don't want to make assumptions about it's lifetime that
+        // might surprise the client developer.
+        MakeOurOwnCopy();
+        bIsSorted = oOther.bIsSorted;
+    }
+    
+    return *this;
+}
+
+/************************************************************************/
+/*                             Initialize()                             */
+/************************************************************************/
+
+void CPLStringList::Initialize()
+
+{
+    papszList = NULL;
+    nCount = 0;
+    nAllocation = 0;
+    bOwnList = FALSE;
+    bIsSorted = FALSE;
+}
+
+/************************************************************************/
+/*                           ~CPLStringList()                           */
+/************************************************************************/
+
+CPLStringList::~CPLStringList()
+
+{
+    Clear();
+}
+
+/************************************************************************/
+/*                               Clear()                                */
+/************************************************************************/
+
+/**
+ * Clear the string list. 
+ */
+CPLStringList &CPLStringList::Clear()
+
+{
+    if( bOwnList )
+    {
+        CSLDestroy( papszList );
+        papszList = NULL;
+
+        bOwnList = FALSE;
+        nAllocation = 0;
+        nCount = 0;
+    }
+    
+    return *this;
+}
+
+/************************************************************************/
+/*                               Assign()                               */
+/************************************************************************/
+
+/**
+ * Assign a list of strings. 
+ *
+ * 
+ * @param papszListIn the NULL terminated list of strings to consume.
+ * @param bTakeOwnership TRUE if the CPLStringList should take ownership
+ * of the list of strings which implies responsibility to free them.
+ *
+ * @return a reference to the CPLStringList on which it was invoked.
+ */
+
+CPLStringList &CPLStringList::Assign( char **papszListIn, int bTakeOwnership )
+
+{
+    Clear();
+
+    papszList = papszListIn;
+    bOwnList = bTakeOwnership;
+
+    if( papszList == NULL || *papszList == NULL )
+        nCount = 0;
+    else
+        nCount = -1;      // unknown
+
+    nAllocation = 0;  
+    bIsSorted = FALSE;
+
+    return *this;
+}
+
+/************************************************************************/
+/*                               Count()                                */
+/************************************************************************/
+
+/**
+ * @return count of strings in the list, zero if empty.
+ */
+
+int CPLStringList::Count() const
+
+{
+    if( nCount == -1 )
+    {
+        if( papszList == NULL )
+        {
+            nCount = nAllocation = 0;
+        }
+        else
+        {
+            nCount = CSLCount( papszList );
+            nAllocation = MAX(nCount+1,nAllocation);
+        }
+    }
+    
+    return nCount;
+}
+
+/************************************************************************/
+/*                           MakeOurOwnCopy()                           */
+/*                                                                      */
+/*      If we don't own the list, a copy is made which we own.          */
+/*      Necessary if we are going to modify the list.                   */
+/************************************************************************/
+
+void CPLStringList::MakeOurOwnCopy()
+
+{
+    if( bOwnList )
+        return;
+
+    if( papszList == NULL )
+        return;
+
+    Count();
+    bOwnList = TRUE;
+    papszList = CSLDuplicate( papszList );
+    nAllocation = nCount+1;
+}
+
+/************************************************************************/
+/*                          EnsureAllocation()                          */
+/*                                                                      */
+/*      Ensure we have enough room allocated for at least the           */
+/*      requested number of strings (so nAllocation will be at least    */
+/*      one more than the target)                                       */
+/************************************************************************/
+
+void CPLStringList::EnsureAllocation( int nMaxList )
+
+{
+    if( !bOwnList )
+        MakeOurOwnCopy();
+
+    if( nAllocation <= nMaxList )
+    {
+        nAllocation = MAX(nAllocation*2 + 20,nMaxList+1);
+		if( papszList == NULL )
+		{
+			papszList = (char **) CPLCalloc(nAllocation,sizeof(char*));
+			bOwnList = TRUE;
+			nCount = 0;
+		}
+		else
+			papszList = (char **) CPLRealloc(papszList, nAllocation*sizeof(char*));
+    }
+}
+
+/************************************************************************/
+/*                         AddStringDirectly()                          */
+/************************************************************************/
+
+/**
+ * Add a string to the list.
+ *
+ * This method is similar to AddString(), but ownership of the
+ * pszNewString is transferred to the CPLStringList class.
+ *
+ * @param pszNewString the string to add to the list. 
+ */
+
+CPLStringList &CPLStringList::AddStringDirectly( char *pszNewString )
+
+{
+    if( nCount == -1 )
+        Count();
+
+    EnsureAllocation( nCount+1 );
+
+    papszList[nCount++] = pszNewString;
+    papszList[nCount] = NULL;
+
+    bIsSorted = FALSE;
+
+    return *this;
+}
+
+/************************************************************************/
+/*                             AddString()                              */
+/************************************************************************/
+
+/**
+ * Add a string to the list.
+ *
+ * A copy of the passed in string is made and inserted in the list.
+ *
+ * @param pszNewString the string to add to the list. 
+ */
+
+CPLStringList &CPLStringList::AddString( const char *pszNewString )
+
+{
+    return AddStringDirectly( CPLStrdup( pszNewString ) );
+}
+
+/************************************************************************/
+/*                            AddNameValue()                            */
+/************************************************************************/
+
+/**
+ * A a name=value entry to the list.
+ *
+ * A key=value string is prepared and appended to the list.  There is no
+ * check for other values for the same key in the list.
+ *
+ * @param pszKey the key name to add.
+ * @param pszValue the key value to add.
+ */
+
+CPLStringList &CPLStringList::AddNameValue( const char  *pszKey, 
+                                            const char *pszValue )
+
+{
+    if (pszKey == NULL || pszValue==NULL)
+        return *this;
+
+    MakeOurOwnCopy();
+
+/* -------------------------------------------------------------------- */
+/*      Format the line.                                                */
+/* -------------------------------------------------------------------- */
+    char *pszLine;
+    pszLine = (char *) CPLMalloc(strlen(pszKey)+strlen(pszValue)+2);
+    sprintf( pszLine, "%s=%s", pszKey, pszValue );
+
+/* -------------------------------------------------------------------- */
+/*      If we don't need to keep the sort order things are pretty       */
+/*      straight forward.                                               */
+/* -------------------------------------------------------------------- */
+    if( !IsSorted() )
+        return AddStringDirectly( pszLine );
+
+/* -------------------------------------------------------------------- */
+/*      Find the proper insertion point.                                */
+/* -------------------------------------------------------------------- */
+    CPLAssert( IsSorted() );
+    int iKey = FindSortedInsertionPoint( pszLine );
+    InsertStringDirectly( iKey, pszLine );
+    bIsSorted = TRUE; // we have actually preserved sort order.
+
+    return *this;
+}
+
+/************************************************************************/
+/*                            SetNameValue()                            */
+/************************************************************************/
+
+/**
+ * Set name=value entry in the list. 
+ *
+ * Similar to AddNameValue(), except if there is already a value for
+ * the key in the list it is replaced instead of adding a new entry to
+ * the list.  If pszValue is NULL any existing key entry is removed.
+ * 
+ * @param pszKey the key name to add.
+ * @param pszValue the key value to add.
+ */
+
+CPLStringList &CPLStringList::SetNameValue( const char *pszKey, 
+                                            const char *pszValue )
+
+{
+    int iKey = FindName( pszKey );
+
+    if( iKey == -1 )
+        return AddNameValue( pszKey, pszValue );
+
+    Count();
+    MakeOurOwnCopy();
+
+    CPLFree( papszList[iKey] );
+    if( pszValue == NULL ) // delete entry
+    {
+
+        // shift everything down by one.
+        do 
+        {
+            papszList[iKey] = papszList[iKey+1];
+        } 
+        while( papszList[iKey++] != NULL );
+
+        nCount--;
+    }
+    else
+    {
+        char *pszLine;
+        pszLine = (char *) CPLMalloc(strlen(pszKey)+strlen(pszValue)+2);
+        sprintf( pszLine, "%s=%s", pszKey, pszValue );
+
+        papszList[iKey] = pszLine;
+    }
+
+    return *this;
+}
+
+/************************************************************************/
+/*                              operator[]                              */
+/************************************************************************/
+
+/**
+ * Fetch entry "i".
+ *
+ * Fetches the requested item in the list.  Note that the returned string
+ * remains owned by the CPLStringList.  If "i" is out of range NULL is
+ * returned.
+ *
+ * @param i the index of the list item to return.
+ * @return selected entry in the list.  
+ */
+char *CPLStringList::operator[]( int i )
+
+{
+    if( nCount == -1 )
+        Count();
+    
+    if( i < 0 || i >= nCount )
+        return NULL;
+    else
+        return papszList[i];
+}
+
+const char *CPLStringList::operator[]( int i ) const
+
+{
+    if( nCount == -1 )
+        Count();
+    
+    if( i < 0 || i >= nCount )
+        return NULL;
+    else
+        return papszList[i];
+}
+
+/************************************************************************/
+/*                             StealList()                              */
+/************************************************************************/
+
+/**
+ * Seize ownership of underlying string array.
+ *
+ * This method is simmilar to List(), except that the returned list is
+ * now owned by the caller and the CPLStringList is emptied.  
+ *
+ * @return the C style string list. 
+ */
+char **CPLStringList::StealList()
+
+{
+    char **papszRetList = papszList;
+
+    bOwnList = FALSE;
+    papszList = NULL;
+    nCount = 0;
+    nAllocation = 0;
+    
+    return papszRetList;
+}
+
+/************************************************************************/
+/*                            llCompareStr()                            */
+/*                                                                      */
+/*      Note this is case insensitive!  This is because we normally     */
+/*      treat key value keywords as case insensitive.                   */
+/************************************************************************/
+static int llCompareStr(const void *a, const void *b)
+{
+	return STRCASECMP((*(const char **)a),(*(const char **)b));
+}
+
+/************************************************************************/
+/*                                Sort()                                */
+/************************************************************************/
+
+/**
+ * Sort the entries in the list and mark list sorted.
+ *
+ * Note that once put into "sorted" mode, the CPLStringList will attempt to
+ * keep things in sorted order through calls to AddString(), 
+ * AddStringDirectly(), AddNameValue(), SetNameValue(). Complete list
+ * assignments (via Assign() and operator= will clear the sorting state.
+ * When in sorted order FindName(), FetchNameValue() and FetchNameValueDef()
+ * will do a binary search to find the key, substantially improve lookup
+ * performance in large lists.
+ */
+
+CPLStringList &CPLStringList::Sort()
+
+{
+    Count();
+    MakeOurOwnCopy();
+
+    qsort( papszList, nCount, sizeof(char*), llCompareStr );
+    bIsSorted = TRUE;
+    
+    return *this;
+}
+
+/************************************************************************/
+/*                              FindName()                              */
+/************************************************************************/
+
+/**
+ * Get index of given name/value keyword.
+ * 
+ * Note that this search is for a line in the form name=value or name:value. 
+ * Use FindString() or PartialFindString() for searches not based on name=value
+ * pairs. 
+ *
+ * @param pszKey the name to search for.  
+ *
+ * @return the string list index of this name, or -1 on failure.
+ */
+
+int CPLStringList::FindName( const char *pszKey ) const
+
+{
+    if( !IsSorted() )
+        return CSLFindName( papszList, pszKey );
+
+    // If we are sorted, we can do an optimized binary search. 
+    int iStart=0, iEnd=nCount-1;
+    int nKeyLen = strlen(pszKey);
+
+    while( iStart <= iEnd )
+    {
+        int iMiddle = (iEnd+iStart)/2;
+        const char *pszMiddle = papszList[iMiddle];
+
+        if (EQUALN(pszMiddle, pszKey, nKeyLen)
+            && (pszMiddle[nKeyLen] == '=' || pszMiddle[nKeyLen] == ':') )
+            return iMiddle;
+
+        if( STRCASECMP(pszKey,pszMiddle) < 0 )
+            iEnd = iMiddle-1;
+        else
+            iStart = iMiddle+1;
+    }
+
+    return -1;
+}
+
+/************************************************************************/
+/*                            FetchBoolean()                            */
+/************************************************************************/
+/**
+ *
+ * Check for boolean key value.
+ *
+ * In a CPLStringList of "Name=Value" pairs, look to see if there is a key
+ * with the given name, and if it can be interpreted as being TRUE.  If
+ * the key appears without any "=Value" portion it will be considered true. 
+ * If the value is NO, FALSE or 0 it will be considered FALSE otherwise
+ * if the key appears in the list it will be considered TRUE.  If the key
+ * doesn't appear at all, the indicated default value will be returned. 
+ * 
+ * @param pszKey the key value to look for (case insensitive).
+ * @param bDefault the value to return if the key isn't found at all. 
+ * 
+ * @return TRUE or FALSE 
+ */
+
+int CPLStringList::FetchBoolean( const char *pszKey, int bDefault ) const
+
+{
+    const char *pszValue = FetchNameValue( pszKey );
+
+    if( pszValue == NULL )
+        return bDefault;
+    else
+        return CSLTestBoolean( pszValue );
+}
+
+/************************************************************************/
+/*                           FetchNameValue()                           */
+/************************************************************************/
+
+/**
+ * Fetch value associated with this key name.
+ *
+ * If this list sorted, a fast binary search is done, otherwise a linear
+ * scan is done.  Name lookup is case insensitive. 
+ * 
+ * @param pszName the key name to search for.
+ * 
+ * @return the corresponding value or NULL if not found.  The returned string 
+ * should not be modified and points into internal object state that may 
+ * change on future calls. 
+ */
+
+const char *CPLStringList::FetchNameValue( const char *pszName ) const
+
+{
+    int iKey = FindName( pszName );
+
+    if( iKey == -1 )
+        return NULL;
+
+    CPLAssert( papszList[iKey][strlen(pszName)] == '='
+               || papszList[iKey][strlen(pszName)] == ':' );
+
+    return papszList[iKey] + strlen(pszName)+1;
+}
+
+/************************************************************************/
+/*                         FetchNameValueDef()                          */
+/************************************************************************/
+
+/**
+ * Fetch value associated with this key name.
+ *
+ * If this list sorted, a fast binary search is done, otherwise a linear
+ * scan is done.  Name lookup is case insensitive. 
+ * 
+ * @param pszName the key name to search for.
+ * @param pszDefault the default value returned if the named entry isn't found.
+ * 
+ * @return the corresponding value or the passed default if not found. 
+ */
+
+const char *CPLStringList::FetchNameValueDef( const char *pszName,
+                                              const char *pszDefault ) const
+
+{
+    const char *pszValue = FetchNameValue( pszName );
+    if( pszValue == NULL )
+        return pszDefault;
+    else
+        return pszValue;
+}
+
+/************************************************************************/
+/*                            InsertString()                            */
+/************************************************************************/
+
+/**
+ * \fn CPLStringList *CPLStringList::InsertString( int nInsertAtLineNo,
+ *                                                 const char *pszNewLine );
+ *
+ * \brief Insert into the list at identified location.
+ *
+ * This method will insert a string into the list at the identified
+ * location.  The insertion point must be within or at the end of the list.
+ * The following entries are pushed down to make space.
+ *
+ * @param nInsertAtLineNo the line to insert at, zero to insert at front.
+ * @param pszNewLine to the line to insert.  This string will be copied.
+ */
+
+
+/************************************************************************/
+/*                        InsertStringDirectly()                        */
+/************************************************************************/
+
+/**
+ * Insert into the list at identified location.
+ *
+ * This method will insert a string into the list at the identified
+ * location.  The insertion point must be within or at the end of the list.
+ * The following entries are pushed down to make space.
+ *
+ * @param nInsertAtLineNo the line to insert at, zero to insert at front.
+ * @param pszNewLine to the line to insert, the ownership of this string
+ * will be taken over the by the object.  It must have been allocated on the
+ * heap.
+ */
+
+CPLStringList &CPLStringList::InsertStringDirectly( int nInsertAtLineNo, 
+                                                    char *pszNewLine )
+
+{
+    if( nCount == -1 )
+        Count();
+
+    EnsureAllocation( nCount+1 );
+
+    if( nInsertAtLineNo < 0 || nInsertAtLineNo > nCount )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "CPLStringList::InsertString() requested beyond list end." );
+        return *this;
+    }
+
+    bIsSorted = FALSE;
+
+    for( int i = nCount; i > nInsertAtLineNo; i-- )
+        papszList[i] = papszList[i-1];
+
+    papszList[nInsertAtLineNo] = pszNewLine;
+    papszList[++nCount] = NULL;
+
+    return *this;
+}
+
+/************************************************************************/
+/*                      FindSortedInsertionPoint()                      */
+/*                                                                      */
+/*      Find the location at which the indicated line should be         */
+/*      inserted in order to keep things in sorted order.               */
+/************************************************************************/
+
+int CPLStringList::FindSortedInsertionPoint( const char *pszLine )
+
+{
+    CPLAssert( IsSorted() );
+    
+    int iStart=0, iEnd=nCount-1;
+
+    while( iStart <= iEnd )
+    {
+        int iMiddle = (iEnd+iStart)/2;
+        const char *pszMiddle = papszList[iMiddle];
+
+        if( STRCASECMP(pszLine,pszMiddle) < 0 )
+            iEnd = iMiddle-1;
+        else
+            iStart = iMiddle+1;
+    }
+
+    iEnd++;
+    CPLAssert( iEnd >= 0 && iEnd <= nCount );
+    CPLAssert( iEnd == 0 
+               || STRCASECMP(pszLine,papszList[iEnd-1]) >= 0 );
+    CPLAssert( iEnd == nCount
+               || STRCASECMP(pszLine,papszList[iEnd]) <= 0 );
+    
+    return iEnd;
+}
diff --git a/port/makefile.vc b/port/makefile.vc
index d05d090..967c9a9 100644
--- a/port/makefile.vc
+++ b/port/makefile.vc
@@ -6,6 +6,7 @@ OBJ	=	cpl_conv.obj \
 		cpl_error.obj \
 		cpl_string.obj \
 		cplstring.obj \
+		cplstringlist.obj \
 		cpl_strtod.obj \
 		cpl_vsisimple.obj \
 		cplgetsymbol.obj \
@@ -22,6 +23,8 @@ OBJ	=	cpl_conv.obj \
                 cpl_http.obj \
                 cpl_hash_set.obj \
                 cplkeywordparser.obj \
+		cpl_recode.obj \
+		cpl_recode_iconv.obj \
 		cpl_recode_stub.obj \
 		cpl_quad_tree.obj \
 		cpl_vsil_gzip.obj \
@@ -38,6 +41,7 @@ OBJ	=	cpl_conv.obj \
 		cpl_vsil_curl.obj \
 		cpl_vsil_stdin.obj \
 		cpl_vsil_buffered_reader.obj \
+		cpl_vsil_cache.obj \
 		cpl_base64.obj \
 		$(ODBC_OBJ)
 
@@ -49,6 +53,10 @@ GDAL_ROOT = ..
 
 EXTRAFLAGS	= 	 -I..\frmts\zlib -DHAVE_LIBZ
 
+!IFDEF LIBICONV_INCLUDE
+EXTRAFLAGS =	$(EXTRAFLAGS) -DHAVE_ICONV $(LIBICONV_CFLAGS) $(LIBICONV_INCLUDE)
+!ENDIF
+
 !IFDEF CURL_INC
 EXTRAFLAGS =	$(EXTRAFLAGS) -DHAVE_CURL $(CURL_CFLAGS) $(CURL_INC)
 !ENDIF
diff --git a/swig/csharp/const/GdalConst.cs b/swig/csharp/const/GdalConst.cs
index c956e6f..5b5e8bc 100644
--- a/swig/csharp/const/GdalConst.cs
+++ b/swig/csharp/const/GdalConst.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/const/GdalConstPINVOKE.cs b/swig/csharp/const/GdalConstPINVOKE.cs
index c977791..bbcbd55 100644
--- a/swig/csharp/const/GdalConstPINVOKE.cs
+++ b/swig/csharp/const/GdalConstPINVOKE.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/const/gdalconst_wrap.c b/swig/csharp/const/gdalconst_wrap.c
index 7257736..d8cf6a6 100644
--- a/swig/csharp/const/gdalconst_wrap.c
+++ b/swig/csharp/const/gdalconst_wrap.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -177,7 +177,7 @@ static SWIG_CSharpException_t SWIG_csharp_exceptions[] = {
 static SWIG_CSharpExceptionArgument_t SWIG_csharp_exceptions_argument[] = {
   { SWIG_CSharpArgumentException, NULL },
   { SWIG_CSharpArgumentNullException, NULL },
-  { SWIG_CSharpArgumentOutOfRangeException, NULL },
+  { SWIG_CSharpArgumentOutOfRangeException, NULL }
 };
 
 static void SWIGUNUSED SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg) {
diff --git a/swig/csharp/gdal/Access.cs b/swig/csharp/gdal/Access.cs
index f25db8d..7a81445 100644
--- a/swig/csharp/gdal/Access.cs
+++ b/swig/csharp/gdal/Access.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/AsyncReader.cs b/swig/csharp/gdal/AsyncReader.cs
index c230b55..27da36c 100644
--- a/swig/csharp/gdal/AsyncReader.cs
+++ b/swig/csharp/gdal/AsyncReader.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/AsyncStatusType.cs b/swig/csharp/gdal/AsyncStatusType.cs
index 0a31fc1..e3a80e0 100644
--- a/swig/csharp/gdal/AsyncStatusType.cs
+++ b/swig/csharp/gdal/AsyncStatusType.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/Band.cs b/swig/csharp/gdal/Band.cs
index 20f118c..840d5e2 100644
--- a/swig/csharp/gdal/Band.cs
+++ b/swig/csharp/gdal/Band.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -47,11 +47,13 @@ public class Band : MajorObject {
 
   public override void Dispose() {
     lock(this) {
-      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
-        swigCMemOwn = false;
-        throw new MethodAccessException("C++ destructor does not have public access");
+      if (swigCPtr.Handle != IntPtr.Zero) {
+        if (swigCMemOwn) {
+          swigCMemOwn = false;
+          throw new MethodAccessException("C++ destructor does not have public access");
+        }
+        swigCPtr = new HandleRef(null, IntPtr.Zero);
       }
-      swigCPtr = new HandleRef(null, IntPtr.Zero);
       GC.SuppressFinalize(this);
       base.Dispose();
     }
@@ -462,6 +464,33 @@ public class Band : MajorObject {
     return ret;
   }
 
+  public string[] GetCategoryNames() {
+        /* %typemap(csout) char**options */
+        IntPtr cPtr = GdalPINVOKE.Band_GetCategoryNames(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 (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+        return ret;
+}
+
+  public CPLErr SetCategoryNames(string[] papszCategoryNames) {
+    CPLErr ret = (CPLErr)GdalPINVOKE.Band_SetCategoryNames(swigCPtr, (papszCategoryNames != null)? new GdalPINVOKE.StringListMarshal(papszCategoryNames)._ar : null);
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public CPLErr ReadRaster(int xOff, int yOff, int xSize, int ySize, IntPtr buffer, int buf_xSize, int buf_ySize, DataType buf_type, int pixelSpace, int lineSpace) {
     CPLErr ret = (CPLErr)GdalPINVOKE.Band_ReadRaster(swigCPtr, xOff, yOff, xSize, ySize, buffer, buf_xSize, buf_ySize, (int)buf_type, pixelSpace, lineSpace);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/gdal/CPLErr.cs b/swig/csharp/gdal/CPLErr.cs
index 1fb6804..98beaac 100644
--- a/swig/csharp/gdal/CPLErr.cs
+++ b/swig/csharp/gdal/CPLErr.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/ColorEntry.cs b/swig/csharp/gdal/ColorEntry.cs
index 7c9f113..e798d1a 100644
--- a/swig/csharp/gdal/ColorEntry.cs
+++ b/swig/csharp/gdal/ColorEntry.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/ColorInterp.cs b/swig/csharp/gdal/ColorInterp.cs
index f1af75b..21541ca 100644
--- a/swig/csharp/gdal/ColorInterp.cs
+++ b/swig/csharp/gdal/ColorInterp.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/ColorTable.cs b/swig/csharp/gdal/ColorTable.cs
index 8c5816a..757f2ba 100644
--- a/swig/csharp/gdal/ColorTable.cs
+++ b/swig/csharp/gdal/ColorTable.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/DataType.cs b/swig/csharp/gdal/DataType.cs
index 05e764b..0b3ff2b 100644
--- a/swig/csharp/gdal/DataType.cs
+++ b/swig/csharp/gdal/DataType.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/Dataset.cs b/swig/csharp/gdal/Dataset.cs
index 559996e..0217f63 100644
--- a/swig/csharp/gdal/Dataset.cs
+++ b/swig/csharp/gdal/Dataset.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -51,11 +51,13 @@ public class Dataset : MajorObject {
 
   public override void Dispose() {
     lock(this) {
-      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
-        swigCMemOwn = false;
-        GdalPINVOKE.delete_Dataset(swigCPtr);
+      if (swigCPtr.Handle != IntPtr.Zero) {
+        if (swigCMemOwn) {
+          swigCMemOwn = false;
+          GdalPINVOKE.delete_Dataset(swigCPtr);
+        }
+        swigCPtr = new HandleRef(null, IntPtr.Zero);
       }
-      swigCPtr = new HandleRef(null, IntPtr.Zero);
       GC.SuppressFinalize(this);
       base.Dispose();
     }
diff --git a/swig/csharp/gdal/Driver.cs b/swig/csharp/gdal/Driver.cs
index 9879ab8..a5efaf1 100644
--- a/swig/csharp/gdal/Driver.cs
+++ b/swig/csharp/gdal/Driver.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -47,11 +47,13 @@ public class Driver : MajorObject {
 
   public override void Dispose() {
     lock(this) {
-      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
-        swigCMemOwn = false;
-        throw new MethodAccessException("C++ destructor does not have public access");
+      if (swigCPtr.Handle != IntPtr.Zero) {
+        if (swigCMemOwn) {
+          swigCMemOwn = false;
+          throw new MethodAccessException("C++ destructor does not have public access");
+        }
+        swigCPtr = new HandleRef(null, IntPtr.Zero);
       }
-      swigCPtr = new HandleRef(null, IntPtr.Zero);
       GC.SuppressFinalize(this);
       base.Dispose();
     }
diff --git a/swig/csharp/gdal/GCP.cs b/swig/csharp/gdal/GCP.cs
index db7d116..b9b1780 100644
--- a/swig/csharp/gdal/GCP.cs
+++ b/swig/csharp/gdal/GCP.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/Gdal.cs b/swig/csharp/gdal/Gdal.cs
index 047944c..b32d3c9 100644
--- a/swig/csharp/gdal/Gdal.cs
+++ b/swig/csharp/gdal/Gdal.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -103,8 +103,8 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
-  public static CPLErr GetLastErrorType() {
-    CPLErr ret = (CPLErr)GdalPINVOKE.GetLastErrorType();
+  public static int GetLastErrorType() {
+    int ret = GdalPINVOKE.GetLastErrorType();
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -187,8 +187,8 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
   }
 
-  public static int Unlink(string pszFilename) {
-    int ret = GdalPINVOKE.Unlink(pszFilename);
+  public static int Unlink(string utf8_path) {
+    int ret = GdalPINVOKE.Unlink(System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(utf8_path)));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -241,6 +241,12 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static int VSIFTruncateL(SWIGTYPE_p_void arg0, int arg1) {
+    int ret = GdalPINVOKE.VSIFTruncateL(SWIGTYPE_p_void.getCPtr(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));
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/gdal/GdalPINVOKE.cs b/swig/csharp/gdal/GdalPINVOKE.cs
index 00b1c7a..686a48c 100644
--- a/swig/csharp/gdal/GdalPINVOKE.cs
+++ b/swig/csharp/gdal/GdalPINVOKE.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -303,6 +303,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFTellL")]
   public static extern int VSIFTellL(HandleRef jarg1);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFTruncateL")]
+  public static extern int VSIFTruncateL(HandleRef jarg1, int jarg2);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFWriteL")]
   public static extern int VSIFWriteL(string jarg1, int jarg2, int jarg3, HandleRef jarg4);
 
@@ -804,6 +807,12 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_Band_HasArbitraryOverviews")]
   public static extern bool Band_HasArbitraryOverviews(HandleRef jarg1);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_Band_GetCategoryNames")]
+  public static extern IntPtr Band_GetCategoryNames(HandleRef jarg1);
+
+  [DllImport("gdal_wrap", EntryPoint="CSharp_Band_SetCategoryNames")]
+  public static extern int Band_SetCategoryNames(HandleRef jarg1, IntPtr[] jarg2);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_Band_ReadRaster")]
   public static extern int Band_ReadRaster(HandleRef jarg1, int jarg2, int jarg3, int jarg4, int jarg5, IntPtr jarg6, int jarg7, int jarg8, int jarg9, int jarg10, int jarg11);
 
diff --git a/swig/csharp/gdal/MajorObject.cs b/swig/csharp/gdal/MajorObject.cs
index 3e59019..b875237 100644
--- a/swig/csharp/gdal/MajorObject.cs
+++ b/swig/csharp/gdal/MajorObject.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/PaletteInterp.cs b/swig/csharp/gdal/PaletteInterp.cs
index 280966b..8d9b3e3 100644
--- a/swig/csharp/gdal/PaletteInterp.cs
+++ b/swig/csharp/gdal/PaletteInterp.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/RATFieldType.cs b/swig/csharp/gdal/RATFieldType.cs
index d62a87e..36900b1 100644
--- a/swig/csharp/gdal/RATFieldType.cs
+++ b/swig/csharp/gdal/RATFieldType.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/RATFieldUsage.cs b/swig/csharp/gdal/RATFieldUsage.cs
index 00770ab..5ecb45f 100644
--- a/swig/csharp/gdal/RATFieldUsage.cs
+++ b/swig/csharp/gdal/RATFieldUsage.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/RWFlag.cs b/swig/csharp/gdal/RWFlag.cs
index 82bbf89..c826433 100644
--- a/swig/csharp/gdal/RWFlag.cs
+++ b/swig/csharp/gdal/RWFlag.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/RasterAttributeTable.cs b/swig/csharp/gdal/RasterAttributeTable.cs
index 7ba57c1..60c14d7 100644
--- a/swig/csharp/gdal/RasterAttributeTable.cs
+++ b/swig/csharp/gdal/RasterAttributeTable.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/ResampleAlg.cs b/swig/csharp/gdal/ResampleAlg.cs
index 61bbedf..1c55440 100644
--- a/swig/csharp/gdal/ResampleAlg.cs
+++ b/swig/csharp/gdal/ResampleAlg.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/SWIGTYPE_p_double.cs b/swig/csharp/gdal/SWIGTYPE_p_double.cs
index 007d68a..4ac07f8 100644
--- a/swig/csharp/gdal/SWIGTYPE_p_double.cs
+++ b/swig/csharp/gdal/SWIGTYPE_p_double.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/SWIGTYPE_p_int.cs b/swig/csharp/gdal/SWIGTYPE_p_int.cs
index 22cddec..d1014f4 100644
--- a/swig/csharp/gdal/SWIGTYPE_p_int.cs
+++ b/swig/csharp/gdal/SWIGTYPE_p_int.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/SWIGTYPE_p_p_GDALRasterBandShadow.cs b/swig/csharp/gdal/SWIGTYPE_p_p_GDALRasterBandShadow.cs
index c64d429..bee8294 100644
--- a/swig/csharp/gdal/SWIGTYPE_p_p_GDALRasterBandShadow.cs
+++ b/swig/csharp/gdal/SWIGTYPE_p_p_GDALRasterBandShadow.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/SWIGTYPE_p_p_int.cs b/swig/csharp/gdal/SWIGTYPE_p_p_int.cs
index e38bce1..99747b1 100644
--- a/swig/csharp/gdal/SWIGTYPE_p_p_int.cs
+++ b/swig/csharp/gdal/SWIGTYPE_p_p_int.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/SWIGTYPE_p_void.cs b/swig/csharp/gdal/SWIGTYPE_p_void.cs
index 9404f6f..a13e591 100644
--- a/swig/csharp/gdal/SWIGTYPE_p_void.cs
+++ b/swig/csharp/gdal/SWIGTYPE_p_void.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/Transformer.cs b/swig/csharp/gdal/Transformer.cs
index b52cb0d..092c24c 100644
--- a/swig/csharp/gdal/Transformer.cs
+++ b/swig/csharp/gdal/Transformer.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/XMLNode.cs b/swig/csharp/gdal/XMLNode.cs
index 23ac7d7..07e7e74 100644
--- a/swig/csharp/gdal/XMLNode.cs
+++ b/swig/csharp/gdal/XMLNode.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/XMLNodeType.cs b/swig/csharp/gdal/XMLNodeType.cs
index 63a2fe8..98b2a1e 100644
--- a/swig/csharp/gdal/XMLNodeType.cs
+++ b/swig/csharp/gdal/XMLNodeType.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/gdal/gdal_wrap.cpp b/swig/csharp/gdal/gdal_wrap.cpp
index ce1ca70..a01d3f1 100644
--- a/swig/csharp/gdal/gdal_wrap.cpp
+++ b/swig/csharp/gdal/gdal_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -201,7 +201,7 @@ static SWIG_CSharpException_t SWIG_csharp_exceptions[] = {
 static SWIG_CSharpExceptionArgument_t SWIG_csharp_exceptions_argument[] = {
   { SWIG_CSharpArgumentException, NULL },
   { SWIG_CSharpArgumentNullException, NULL },
-  { SWIG_CSharpArgumentOutOfRangeException, NULL },
+  { SWIG_CSharpArgumentOutOfRangeException, NULL }
 };
 
 static void SWIGUNUSED SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg) {
@@ -1143,6 +1143,12 @@ SWIGINTERN CPLErr GDALRasterBandShadow_SetDefaultHistogram(GDALRasterBandShadow
 SWIGINTERN bool GDALRasterBandShadow_HasArbitraryOverviews(GDALRasterBandShadow *self){
       return (GDALHasArbitraryOverviews( self ) != 0) ? true : false;
   }
+SWIGINTERN char **GDALRasterBandShadow_GetCategoryNames(GDALRasterBandShadow *self){
+    return GDALGetRasterCategoryNames( self );
+  }
+SWIGINTERN CPLErr GDALRasterBandShadow_SetCategoryNames(GDALRasterBandShadow *self,char **papszCategoryNames){
+    return GDALSetRasterCategoryNames( self, papszCategoryNames );
+  }
 SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster(GDALRasterBandShadow *self,int xOff,int yOff,int xSize,int ySize,void *buffer,int buf_xSize,int buf_ySize,GDALDataType buf_type,int pixelSpace,int lineSpace){
        return GDALRasterIO( self, GF_Read, xOff, yOff, xSize, ySize, 
 		        buffer, buf_xSize, buf_ySize, buf_type, pixelSpace, lineSpace );
@@ -1925,26 +1931,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_GetLastErrorNo() {
   int result;
   
   {
-    CPLErrorReset();
-    result = (int)CPLGetLastErrorNo();
-    CPLErr eclass = CPLGetLastErrorType();
-    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
-      
-      
-      
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    result = CPLGetLastErrorNo();
   }
   jresult = result; 
   return jresult;
@@ -1953,29 +1940,10 @@ SWIGEXPORT int SWIGSTDCALL CSharp_GetLastErrorNo() {
 
 SWIGEXPORT int SWIGSTDCALL CSharp_GetLastErrorType() {
   int jresult ;
-  CPLErr result;
+  int result;
   
   {
-    CPLErrorReset();
-    result = (CPLErr)CPLGetLastErrorType();
-    CPLErr eclass = CPLGetLastErrorType();
-    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
-      
-      
-      
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    result = CPLGetLastErrorType();
   }
   jresult = result; 
   return jresult;
@@ -1987,26 +1955,7 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_GetLastErrorMsg() {
   char *result = 0 ;
   
   {
-    CPLErrorReset();
-    result = (char *)CPLGetLastErrorMsg();
-    CPLErr eclass = CPLGetLastErrorType();
-    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
-      
-      
-      
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    result = (char*)CPLGetLastErrorMsg();
   }
   jresult = SWIG_csharp_string_callback((const char *)result); 
   return jresult;
@@ -2366,13 +2315,6 @@ 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();
@@ -2667,6 +2609,41 @@ SWIGEXPORT long SWIGSTDCALL CSharp_VSIFTellL(void * jarg1) {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_VSIFTruncateL(void * jarg1, long jarg2) {
+  int jresult ;
+  VSILFILE *arg1 = (VSILFILE *) 0 ;
+  long arg2 ;
+  int result;
+  
+  arg1 = (VSILFILE *)jarg1; 
+  arg2 = (long)jarg2; 
+  {
+    CPLErrorReset();
+    result = (int)VSIFTruncateL(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_VSIFWriteL(char * jarg1, int jarg2, int jarg3, void * jarg4) {
   int jresult ;
   char *arg1 = (char *) 0 ;
@@ -3358,6 +3335,13 @@ SWIGEXPORT void SWIGSTDCALL CSharp_MajorObject_SetDescription(void * jarg1, char
   arg1 = (GDALMajorObjectShadow *)jarg1; 
   arg2 = (char *)jarg2; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -8500,6 +8484,74 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Band_HasArbitraryOverviews(void * jar
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_Band_GetCategoryNames(void * jarg1) {
+  void * jresult ;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  char **result = 0 ;
+  
+  arg1 = (GDALRasterBandShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (char **)GDALRasterBandShadow_GetCategoryNames(arg1);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_Band_SetCategoryNames(void * jarg1, void * jarg2) {
+  int jresult ;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  CPLErr result;
+  
+  arg1 = (GDALRasterBandShadow *)jarg1; 
+  arg2 = (char **)jarg2; 
+  {
+    CPLErrorReset();
+    result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(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_Band_ReadRaster(void * jarg1, int jarg2, int jarg3, int jarg4, int jarg5, void * jarg6, int jarg7, int jarg8, int jarg9, int jarg10, int jarg11) {
   int jresult ;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
diff --git a/swig/csharp/ogr/CoordinateTransformation.cs b/swig/csharp/ogr/CoordinateTransformation.cs
index 571aa1b..fda7867 100644
--- a/swig/csharp/ogr/CoordinateTransformation.cs
+++ b/swig/csharp/ogr/CoordinateTransformation.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/DataSource.cs b/swig/csharp/ogr/DataSource.cs
index 227bc4a..fbc1ad6 100644
--- a/swig/csharp/ogr/DataSource.cs
+++ b/swig/csharp/ogr/DataSource.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -113,6 +113,12 @@ public class DataSource : IDisposable {
     return ret;
   }
 
+  public int SyncToDisk() {
+    int ret = OgrPINVOKE.DataSource_SyncToDisk(swigCPtr);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public Layer CreateLayer(string name, OSGeo.OSR.SpatialReference srs, wkbGeometryType geom_type, string[] options) {
     IntPtr cPtr = OgrPINVOKE.DataSource_CreateLayer(swigCPtr, name, OSGeo.OSR.SpatialReference.getCPtr(srs), (int)geom_type, (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null);
     Layer ret = (cPtr == IntPtr.Zero) ? null : new Layer(cPtr, false, ThisOwn_false());
diff --git a/swig/csharp/ogr/Driver.cs b/swig/csharp/ogr/Driver.cs
index 44a61fe..68d7f98 100644
--- a/swig/csharp/ogr/Driver.cs
+++ b/swig/csharp/ogr/Driver.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/Envelope.cs b/swig/csharp/ogr/Envelope.cs
index 3714e75..b08dc5f 100644
--- a/swig/csharp/ogr/Envelope.cs
+++ b/swig/csharp/ogr/Envelope.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/Envelope3D.cs b/swig/csharp/ogr/Envelope3D.cs
new file mode 100644
index 0000000..dd09264
--- /dev/null
+++ b/swig/csharp/ogr/Envelope3D.cs
@@ -0,0 +1,149 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.40
+ *
+ * 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 Envelope3D : IDisposable {
+  private HandleRef swigCPtr;
+  protected bool swigCMemOwn;
+  protected object swigParentRef;
+  
+  protected static object ThisOwn_true() { return null; }
+  protected object ThisOwn_false() { return this; }
+
+  public Envelope3D(IntPtr cPtr, bool cMemoryOwn, object parent) {
+    swigCMemOwn = cMemoryOwn;
+    swigParentRef = parent;
+    swigCPtr = new HandleRef(this, cPtr);
+  }
+
+  public static HandleRef getCPtr(Envelope3D obj) {
+    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
+  }
+  public static HandleRef getCPtrAndDisown(Envelope3D 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(Envelope3D obj, object parent) {
+    if (obj != null)
+    {
+      obj.swigParentRef = parent;
+      return obj.swigCPtr;
+    }
+    else
+    {
+      return new HandleRef(null, IntPtr.Zero);
+    }
+  }
+
+  ~Envelope3D() {
+    Dispose();
+  }
+
+  public virtual void Dispose() {
+  lock(this) {
+      if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) {
+        swigCMemOwn = false;
+        OgrPINVOKE.delete_Envelope3D(swigCPtr);
+      }
+      swigCPtr = new HandleRef(null, IntPtr.Zero);
+      swigParentRef = null;
+      GC.SuppressFinalize(this);
+    }
+  }
+
+  public double MinX {
+    set {
+      OgrPINVOKE.Envelope3D_MinX_set(swigCPtr, value);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    } 
+    get {
+      double ret = OgrPINVOKE.Envelope3D_MinX_get(swigCPtr);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+      return ret;
+    } 
+  }
+
+  public double MaxX {
+    set {
+      OgrPINVOKE.Envelope3D_MaxX_set(swigCPtr, value);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    } 
+    get {
+      double ret = OgrPINVOKE.Envelope3D_MaxX_get(swigCPtr);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+      return ret;
+    } 
+  }
+
+  public double MinY {
+    set {
+      OgrPINVOKE.Envelope3D_MinY_set(swigCPtr, value);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    } 
+    get {
+      double ret = OgrPINVOKE.Envelope3D_MinY_get(swigCPtr);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+      return ret;
+    } 
+  }
+
+  public double MaxY {
+    set {
+      OgrPINVOKE.Envelope3D_MaxY_set(swigCPtr, value);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    } 
+    get {
+      double ret = OgrPINVOKE.Envelope3D_MaxY_get(swigCPtr);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+      return ret;
+    } 
+  }
+
+  public double MinZ {
+    set {
+      OgrPINVOKE.Envelope3D_MinZ_set(swigCPtr, value);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    } 
+    get {
+      double ret = OgrPINVOKE.Envelope3D_MinZ_get(swigCPtr);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+      return ret;
+    } 
+  }
+
+  public double MaxZ {
+    set {
+      OgrPINVOKE.Envelope3D_MaxZ_set(swigCPtr, value);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    } 
+    get {
+      double ret = OgrPINVOKE.Envelope3D_MaxZ_get(swigCPtr);
+      if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+      return ret;
+    } 
+  }
+
+  public Envelope3D() : this(OgrPINVOKE.new_Envelope3D(), true, null) {
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+}
+
+}
diff --git a/swig/csharp/ogr/Feature.cs b/swig/csharp/ogr/Feature.cs
index cbbd161..dc73ea2 100644
--- a/swig/csharp/ogr/Feature.cs
+++ b/swig/csharp/ogr/Feature.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/FeatureDefn.cs b/swig/csharp/ogr/FeatureDefn.cs
index 99f6a48..b578556 100644
--- a/swig/csharp/ogr/FeatureDefn.cs
+++ b/swig/csharp/ogr/FeatureDefn.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/FieldDefn.cs b/swig/csharp/ogr/FieldDefn.cs
index 5ecc2aa..eb68705 100644
--- a/swig/csharp/ogr/FieldDefn.cs
+++ b/swig/csharp/ogr/FieldDefn.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/FieldType.cs b/swig/csharp/ogr/FieldType.cs
index 0b87940..67efa18 100644
--- a/swig/csharp/ogr/FieldType.cs
+++ b/swig/csharp/ogr/FieldType.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/Geometry.cs b/swig/csharp/ogr/Geometry.cs
index 0ba6535..a03ecec 100644
--- a/swig/csharp/ogr/Geometry.cs
+++ b/swig/csharp/ogr/Geometry.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -140,8 +140,8 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     return ret;
   }
 
-  public string ExportToJson() {
-    string ret = OgrPINVOKE.Geometry_ExportToJson(swigCPtr);
+  public string ExportToJson(string[] options) {
+    string ret = OgrPINVOKE.Geometry_ExportToJson(swigCPtr, (options != null)? new OgrPINVOKE.StringListMarshal(options)._ar : null);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
@@ -269,6 +269,13 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     return ret;
   }
 
+  public Geometry SimplifyPreserveTopology(double tolerance) {
+    IntPtr cPtr = OgrPINVOKE.Geometry_SimplifyPreserveTopology(swigCPtr, tolerance);
+    Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, true, ThisOwn_true());
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public Geometry Boundary() {
     IntPtr cPtr = OgrPINVOKE.Geometry_Boundary(swigCPtr);
     Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, true, ThisOwn_true());
@@ -478,6 +485,11 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public void GetEnvelope3D(Envelope3D env) {
+    OgrPINVOKE.Geometry_GetEnvelope3D(swigCPtr, Envelope3D.getCPtr(env));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public Geometry Centroid() {
     IntPtr cPtr = OgrPINVOKE.Geometry_Centroid(swigCPtr);
     Geometry ret = (cPtr == IntPtr.Zero) ? null : new Geometry(cPtr, true, ThisOwn_true());
diff --git a/swig/csharp/ogr/Justification.cs b/swig/csharp/ogr/Justification.cs
index 61e98e5..cbe1395 100644
--- a/swig/csharp/ogr/Justification.cs
+++ b/swig/csharp/ogr/Justification.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/Layer.cs b/swig/csharp/ogr/Layer.cs
index 698a321..7149990 100644
--- a/swig/csharp/ogr/Layer.cs
+++ b/swig/csharp/ogr/Layer.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -197,6 +197,30 @@ public class Layer : IDisposable {
     return ret;
   }
 
+  public int DeleteField(int iField) {
+    int ret = OgrPINVOKE.Layer_DeleteField(swigCPtr, iField);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int ReorderField(int iOldFieldPos, int iNewFieldPos) {
+    int ret = OgrPINVOKE.Layer_ReorderField(swigCPtr, iOldFieldPos, iNewFieldPos);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int ReorderFields(int nList, int[] pList) {
+    int ret = OgrPINVOKE.Layer_ReorderFields(swigCPtr, nList, pList);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int AlterFieldDefn(int iField, FieldDefn field_def, int nFlags) {
+    int ret = OgrPINVOKE.Layer_AlterFieldDefn(swigCPtr, iField, FieldDefn.getCPtr(field_def), nFlags);
+    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();
diff --git a/swig/csharp/ogr/Ogr.cs b/swig/csharp/ogr/Ogr.cs
index c325427..09849b7 100644
--- a/swig/csharp/ogr/Ogr.cs
+++ b/swig/csharp/ogr/Ogr.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -208,6 +208,9 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public static readonly string OLCFastFeatureCount = OgrPINVOKE.OLCFastFeatureCount_get();
   public static readonly string OLCFastGetExtent = OgrPINVOKE.OLCFastGetExtent_get();
   public static readonly string OLCCreateField = OgrPINVOKE.OLCCreateField_get();
+  public static readonly string OLCDeleteField = OgrPINVOKE.OLCDeleteField_get();
+  public static readonly string OLCReorderFields = OgrPINVOKE.OLCReorderFields_get();
+  public static readonly string OLCAlterFieldDefn = OgrPINVOKE.OLCAlterFieldDefn_get();
   public static readonly string OLCTransactions = OgrPINVOKE.OLCTransactions_get();
   public static readonly string OLCDeleteFeature = OgrPINVOKE.OLCDeleteFeature_get();
   public static readonly string OLCFastSetNextByIndex = OgrPINVOKE.OLCFastSetNextByIndex_get();
diff --git a/swig/csharp/ogr/OgrPINVOKE.cs b/swig/csharp/ogr/OgrPINVOKE.cs
index 676c4c0..3472fb1 100644
--- a/swig/csharp/ogr/OgrPINVOKE.cs
+++ b/swig/csharp/ogr/OgrPINVOKE.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -222,6 +222,15 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_OLCCreateField_get")]
   public static extern string OLCCreateField_get();
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_OLCDeleteField_get")]
+  public static extern string OLCDeleteField_get();
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_OLCReorderFields_get")]
+  public static extern string OLCReorderFields_get();
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_OLCAlterFieldDefn_get")]
+  public static extern string OLCAlterFieldDefn_get();
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_OLCTransactions_get")]
   public static extern string OLCTransactions_get();
 
@@ -327,6 +336,48 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_delete_Envelope")]
   public static extern void delete_Envelope(HandleRef jarg1);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MinX_set")]
+  public static extern void Envelope3D_MinX_set(HandleRef jarg1, double jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MinX_get")]
+  public static extern double Envelope3D_MinX_get(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MaxX_set")]
+  public static extern void Envelope3D_MaxX_set(HandleRef jarg1, double jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MaxX_get")]
+  public static extern double Envelope3D_MaxX_get(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MinY_set")]
+  public static extern void Envelope3D_MinY_set(HandleRef jarg1, double jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MinY_get")]
+  public static extern double Envelope3D_MinY_get(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MaxY_set")]
+  public static extern void Envelope3D_MaxY_set(HandleRef jarg1, double jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MaxY_get")]
+  public static extern double Envelope3D_MaxY_get(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MinZ_set")]
+  public static extern void Envelope3D_MinZ_set(HandleRef jarg1, double jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MinZ_get")]
+  public static extern double Envelope3D_MinZ_get(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MaxZ_set")]
+  public static extern void Envelope3D_MaxZ_set(HandleRef jarg1, double jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Envelope3D_MaxZ_get")]
+  public static extern double Envelope3D_MaxZ_get(HandleRef jarg1);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_new_Envelope3D")]
+  public static extern IntPtr new_Envelope3D();
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_delete_Envelope3D")]
+  public static extern void delete_Envelope3D(HandleRef jarg1);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Driver_name_get")]
   public static extern string Driver_name_get(HandleRef jarg1);
 
@@ -378,6 +429,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_DataSource_DeleteLayer")]
   public static extern int DataSource_DeleteLayer(HandleRef jarg1, int jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_DataSource_SyncToDisk")]
+  public static extern int DataSource_SyncToDisk(HandleRef jarg1);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_DataSource_CreateLayer")]
   public static extern IntPtr DataSource_CreateLayer(HandleRef jarg1, string jarg2, HandleRef jarg3, int jarg4, IntPtr[] jarg5);
 
@@ -465,6 +519,18 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_CreateField")]
   public static extern int Layer_CreateField(HandleRef jarg1, HandleRef jarg2, int jarg3);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_DeleteField")]
+  public static extern int Layer_DeleteField(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_ReorderField")]
+  public static extern int Layer_ReorderField(HandleRef jarg1, int jarg2, int jarg3);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Layer_ReorderFields")]
+  public static extern int Layer_ReorderFields(HandleRef jarg1, int jarg2, int[] jarg3);
+
+  [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_StartTransaction")]
   public static extern int Layer_StartTransaction(HandleRef jarg1);
 
@@ -763,7 +829,7 @@ class OgrPINVOKE {
   public static extern string Geometry_ExportToKML(HandleRef jarg1, string jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_ExportToJson")]
-  public static extern string Geometry_ExportToJson(HandleRef jarg1);
+  public static extern string Geometry_ExportToJson(HandleRef jarg1, IntPtr[] jarg2);
 
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_AddPoint")]
   public static extern void Geometry_AddPoint(HandleRef jarg1, double jarg2, double jarg3, double jarg4);
@@ -828,6 +894,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Simplify")]
   public static extern IntPtr Geometry_Simplify(HandleRef jarg1, double jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_SimplifyPreserveTopology")]
+  public static extern IntPtr Geometry_SimplifyPreserveTopology(HandleRef jarg1, double jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Boundary")]
   public static extern IntPtr Geometry_Boundary(HandleRef jarg1);
 
@@ -930,6 +999,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetEnvelope")]
   public static extern void Geometry_GetEnvelope(HandleRef jarg1, HandleRef jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_GetEnvelope3D")]
+  public static extern void Geometry_GetEnvelope3D(HandleRef jarg1, HandleRef jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Centroid")]
   public static extern IntPtr Geometry_Centroid(HandleRef jarg1);
 
diff --git a/swig/csharp/ogr/Osr.cs b/swig/csharp/ogr/Osr.cs
index b7dc28c..ccade7a 100644
--- a/swig/csharp/ogr/Osr.cs
+++ b/swig/csharp/ogr/Osr.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -117,6 +117,7 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public const string SRS_PT_GAUSSSCHREIBERTMERCATOR = "Gauss_Schreiber_Transverse_Mercator";
   public const string SRS_PT_GEOSTATIONARY_SATELLITE = "Geostationary_Satellite";
   public const string SRS_PT_GOODE_HOMOLOSINE = "Goode_Homolosine";
+  public const string SRS_PT_IGH = "Interrupted_Goode_Homolosine";
   public const string SRS_PT_GNOMONIC = "Gnomonic";
   public const string SRS_PT_HOTINE_OBLIQUE_MERCATOR = "Hotine_Oblique_Mercator";
   public const string SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN = "Hotine_Oblique_Mercator_Two_Point_Natural_Origin";
@@ -199,6 +200,8 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public const string SRS_UL_CHAIN_CONV = "20.116684023368047";
   public const string SRS_UL_ROD = "Rod";
   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_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 a84aceb..d1df5da 100644
--- a/swig/csharp/ogr/OsrPINVOKE.cs
+++ b/swig/csharp/ogr/OsrPINVOKE.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -246,15 +246,27 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsSameGeogCS")]
   public static extern int SpatialReference_IsSameGeogCS(HandleRef jarg1, HandleRef jarg2);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsSameVertCS")]
+  public static extern int SpatialReference_IsSameVertCS(HandleRef jarg1, HandleRef jarg2);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsGeographic")]
   public static extern int SpatialReference_IsGeographic(HandleRef jarg1);
 
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsProjected")]
   public static extern int SpatialReference_IsProjected(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsCompound")]
+  public static extern int SpatialReference_IsCompound(HandleRef jarg1);
+
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsGeocentric")]
+  public static extern int SpatialReference_IsGeocentric(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsLocal")]
   public static extern int SpatialReference_IsLocal(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsVertical")]
+  public static extern int SpatialReference_IsVertical(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_EPSGTreatsAsLatLong")]
   public static extern int SpatialReference_EPSGTreatsAsLatLong(HandleRef jarg1);
 
@@ -273,6 +285,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_GetAngularUnits")]
   public static extern double SpatialReference_GetAngularUnits(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetTargetLinearUnits")]
+  public static extern int SpatialReference_SetTargetLinearUnits(HandleRef jarg1, string jarg2, string jarg3, double jarg4);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetLinearUnits")]
   public static extern int SpatialReference_SetLinearUnits(HandleRef jarg1, string jarg2, double jarg3);
 
@@ -366,6 +381,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetGH")]
   public static extern int SpatialReference_SetGH(HandleRef jarg1, double jarg2, double jarg3, double jarg4);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetIGH")]
+  public static extern int SpatialReference_SetIGH(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetGEOS")]
   public static extern int SpatialReference_SetGEOS(HandleRef jarg1, double jarg2, double jarg3, double jarg4, double jarg5);
 
@@ -468,6 +486,15 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetProjCS")]
   public static extern int SpatialReference_SetProjCS(HandleRef jarg1, string jarg2);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetGeocCS")]
+  public static extern int SpatialReference_SetGeocCS(HandleRef jarg1, string jarg2);
+
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetVertCS")]
+  public static extern int SpatialReference_SetVertCS(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
+
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetCompoundCS")]
+  public static extern int SpatialReference_SetCompoundCS(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_ImportFromWkt")]
   public static extern int SpatialReference_ImportFromWkt(HandleRef jarg1, ref string jarg2);
 
diff --git a/swig/csharp/ogr/SpatialReference.cs b/swig/csharp/ogr/SpatialReference.cs
index 6343312..0fec51f 100644
--- a/swig/csharp/ogr/SpatialReference.cs
+++ b/swig/csharp/ogr/SpatialReference.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -90,6 +90,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int IsSameVertCS(SpatialReference rhs) {
+    int ret = OsrPINVOKE.SpatialReference_IsSameVertCS(swigCPtr, SpatialReference.getCPtr(rhs));
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int IsGeographic() {
     int ret = OsrPINVOKE.SpatialReference_IsGeographic(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -102,12 +108,30 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int IsCompound() {
+    int ret = OsrPINVOKE.SpatialReference_IsCompound(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int IsGeocentric() {
+    int ret = OsrPINVOKE.SpatialReference_IsGeocentric(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int IsLocal() {
     int ret = OsrPINVOKE.SpatialReference_IsLocal(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
+  public int IsVertical() {
+    int ret = OsrPINVOKE.SpatialReference_IsVertical(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int EPSGTreatsAsLatLong() {
     int ret = OsrPINVOKE.SpatialReference_EPSGTreatsAsLatLong(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -144,6 +168,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int SetTargetLinearUnits(string target, string name, double to_meters) {
+    int ret = OsrPINVOKE.SpatialReference_SetTargetLinearUnits(swigCPtr, target, name, to_meters);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int SetLinearUnits(string name, double to_meters) {
     int ret = OsrPINVOKE.SpatialReference_SetLinearUnits(swigCPtr, name, to_meters);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -330,6 +360,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int SetIGH() {
+    int ret = OsrPINVOKE.SpatialReference_SetIGH(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int SetGEOS(double cm, double satelliteheight, double fe, double fn) {
     int ret = OsrPINVOKE.SpatialReference_SetGEOS(swigCPtr, cm, satelliteheight, fe, fn);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -534,6 +570,24 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int SetGeocCS(string name) {
+    int ret = OsrPINVOKE.SpatialReference_SetGeocCS(swigCPtr, name);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SetVertCS(string VertCSName, string VertDatumName, int VertDatumType) {
+    int ret = OsrPINVOKE.SpatialReference_SetVertCS(swigCPtr, VertCSName, VertDatumName, VertDatumType);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SetCompoundCS(string name, SpatialReference horizcs, SpatialReference vertcs) {
+    int ret = OsrPINVOKE.SpatialReference_SetCompoundCS(swigCPtr, name, SpatialReference.getCPtr(horizcs), SpatialReference.getCPtr(vertcs));
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int ImportFromWkt(ref string ppszInput) {
     int ret = OsrPINVOKE.SpatialReference_ImportFromWkt(swigCPtr, ref ppszInput);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/ogr/ogr_wrap.cpp b/swig/csharp/ogr/ogr_wrap.cpp
index 2373213..6737e98 100644
--- a/swig/csharp/ogr/ogr_wrap.cpp
+++ b/swig/csharp/ogr/ogr_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -201,7 +201,7 @@ static SWIG_CSharpException_t SWIG_csharp_exceptions[] = {
 static SWIG_CSharpExceptionArgument_t SWIG_csharp_exceptions_argument[] = {
   { SWIG_CSharpArgumentException, NULL },
   { SWIG_CSharpArgumentNullException, NULL },
-  { SWIG_CSharpArgumentOutOfRangeException, NULL },
+  { SWIG_CSharpArgumentOutOfRangeException, NULL }
 };
 
 static void SWIGUNUSED SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg) {
@@ -406,6 +406,14 @@ SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_CopyDataSource(OGRDriverShadow *
   }
 SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_Open(OGRDriverShadow *self,char const *utf8_path,int update=0){
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*) OGR_Dr_Open(self, utf8_path, update);
+    if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
+    {
+        CPLDebug( "SWIG",
+          "OGR_Dr_Open() succeeded, but an error is posted, so we destroy"
+          " the datasource and fail at swig level." );
+        OGRReleaseDataSource(ds);
+        ds = NULL;
+    }
     return ds;
   }
 SWIGINTERN int OGRDriverShadow_DeleteDataSource(OGRDriverShadow *self,char const *utf8_path){
@@ -468,6 +476,9 @@ OGRErrMessages( int rc ) {
   }
 }
 
+SWIGINTERN OGRErr OGRDataSourceShadow_SyncToDisk(OGRDataSourceShadow *self){
+    return OGR_DS_SyncToDisk(self);
+  }
 SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_CreateLayer(OGRDataSourceShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
     OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_CreateLayer( self,
 								  name,
@@ -571,6 +582,25 @@ SWIGINTERN bool OGRLayerShadow_TestCapability(OGRLayerShadow *self,char const *c
 SWIGINTERN OGRErr OGRLayerShadow_CreateField(OGRLayerShadow *self,OGRFieldDefnShadow *field_def,int approx_ok=1){
     return OGR_L_CreateField(self, field_def, approx_ok);
   }
+SWIGINTERN OGRErr OGRLayerShadow_DeleteField(OGRLayerShadow *self,int iField){
+    return OGR_L_DeleteField(self, iField);
+  }
+SWIGINTERN OGRErr OGRLayerShadow_ReorderField(OGRLayerShadow *self,int iOldFieldPos,int iNewFieldPos){
+    return OGR_L_ReorderField(self, iOldFieldPos, iNewFieldPos);
+  }
+SWIGINTERN OGRErr OGRLayerShadow_ReorderFields(OGRLayerShadow *self,int nList,int *pList){
+    if (nList != OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)))
+    {
+      CPLError(CE_Failure, CPLE_IllegalArg,
+               "List should have %d elements",
+               OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)));
+      return 6;
+    }
+    return OGR_L_ReorderFields(self, pList);
+  }
+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_StartTransaction(OGRLayerShadow *self){
     return OGR_L_StartTransaction(self);
   }
@@ -919,7 +949,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 
   OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
                                       reference,
                                       &geom,
@@ -935,7 +965,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 
   OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
                                       OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkt(val,
                                       reference,
                                       &geom);
@@ -979,7 +1009,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
     return NULL;
   }
 
-  return hPolygon;
+  return (OGRGeometryShadow* )hPolygon;
   }
 
 
@@ -989,7 +1019,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
         double dfStartAngle, double dfEndAngle,
         double dfMaxAngleStepSizeDegrees ) {
   
-  return OGR_G_ApproximateArcAngles( 
+  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
              dfCenterX, dfCenterY, dfZ, 
              dfPrimaryRadius, dfSecondaryAxis, dfRotation,
              dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
@@ -999,28 +1029,28 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 OGRGeometryShadow* ForceToPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiPoint( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiLineString( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
 }
 
 SWIGINTERN void delete_OGRGeometryShadow(OGRGeometryShadow *self){
@@ -1057,8 +1087,8 @@ SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToGML__SWIG_1(OGRGeometr
 SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToKML(OGRGeometryShadow *self,char const *altitude_mode=NULL){
     return (retStringAndCPLFree *) OGR_G_ExportToKML(self, altitude_mode);
   }
-SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow *self){
-    return (retStringAndCPLFree *) OGR_G_ExportToJson(self);
+SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow *self,char **options=0){
+    return (retStringAndCPLFree *) OGR_G_ExportToJsonEx(self, options);
   }
 SWIGINTERN void OGRGeometryShadow_AddPoint(OGRGeometryShadow *self,double x,double y,double z=0){
     OGR_G_AddPoint( self, x, y, z );
@@ -1125,6 +1155,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_GetGeometryRef(OGRGeometryShadow
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Simplify(OGRGeometryShadow *self,double tolerance){
     return (OGRGeometryShadow*) OGR_G_Simplify(self, tolerance);
   }
+SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SimplifyPreserveTopology(OGRGeometryShadow *self,double tolerance){
+    return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Boundary(OGRGeometryShadow *self){
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
   }
@@ -1230,6 +1263,9 @@ SWIGINTERN void OGRGeometryShadow_Segmentize(OGRGeometryShadow *self,double dfMa
 SWIGINTERN void OGRGeometryShadow_GetEnvelope(OGRGeometryShadow *self,OGREnvelope *env){
     OGR_G_GetEnvelope(self, env);
   }
+SWIGINTERN void OGRGeometryShadow_GetEnvelope3D(OGRGeometryShadow *self,OGREnvelope3D *env){
+    OGR_G_GetEnvelope3D(self, env);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Centroid(OGRGeometryShadow *self){
     OGRGeometryShadow *pt = (OGRGeometryShadow*) OGR_G_CreateGeometry( wkbPoint );
     OGR_G_Centroid( self, pt );
@@ -1441,6 +1477,36 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_OLCCreateField_get() {
 }
 
 
+SWIGEXPORT char * SWIGSTDCALL CSharp_OLCDeleteField_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *) "DeleteField";
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_OLCReorderFields_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *) "ReorderFields";
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_OLCAlterFieldDefn_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *) "AlterFieldDefn";
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_OLCTransactions_get() {
   char * jresult ;
   char *result = 0 ;
@@ -1788,6 +1854,198 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_Envelope(void * jarg1) {
 }
 
 
+SWIGEXPORT void SWIGSTDCALL CSharp_Envelope3D_MinX_set(void * jarg1, double jarg2) {
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double arg2 ;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  arg2 = (double)jarg2; 
+  if (arg1) (arg1)->MinX = arg2;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Envelope3D_MinX_get(void * jarg1) {
+  double jresult ;
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double result;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  result = (double) ((arg1)->MinX);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Envelope3D_MaxX_set(void * jarg1, double jarg2) {
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double arg2 ;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  arg2 = (double)jarg2; 
+  if (arg1) (arg1)->MaxX = arg2;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Envelope3D_MaxX_get(void * jarg1) {
+  double jresult ;
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double result;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  result = (double) ((arg1)->MaxX);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Envelope3D_MinY_set(void * jarg1, double jarg2) {
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double arg2 ;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  arg2 = (double)jarg2; 
+  if (arg1) (arg1)->MinY = arg2;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Envelope3D_MinY_get(void * jarg1) {
+  double jresult ;
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double result;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  result = (double) ((arg1)->MinY);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Envelope3D_MaxY_set(void * jarg1, double jarg2) {
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double arg2 ;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  arg2 = (double)jarg2; 
+  if (arg1) (arg1)->MaxY = arg2;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Envelope3D_MaxY_get(void * jarg1) {
+  double jresult ;
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double result;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  result = (double) ((arg1)->MaxY);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Envelope3D_MinZ_set(void * jarg1, double jarg2) {
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double arg2 ;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  arg2 = (double)jarg2; 
+  if (arg1) (arg1)->MinZ = arg2;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Envelope3D_MinZ_get(void * jarg1) {
+  double jresult ;
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double result;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  result = (double) ((arg1)->MinZ);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Envelope3D_MaxZ_set(void * jarg1, double jarg2) {
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double arg2 ;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  arg2 = (double)jarg2; 
+  if (arg1) (arg1)->MaxZ = arg2;
+}
+
+
+SWIGEXPORT double SWIGSTDCALL CSharp_Envelope3D_MaxZ_get(void * jarg1) {
+  double jresult ;
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  double result;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  result = (double) ((arg1)->MaxZ);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void * SWIGSTDCALL CSharp_new_Envelope3D() {
+  void * jresult ;
+  OGREnvelope3D *result = 0 ;
+  
+  {
+    CPLErrorReset();
+    result = (OGREnvelope3D *)new OGREnvelope3D();
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_delete_Envelope3D(void * jarg1) {
+  OGREnvelope3D *arg1 = (OGREnvelope3D *) 0 ;
+  
+  arg1 = (OGREnvelope3D *)jarg1; 
+  {
+    CPLErrorReset();
+    delete arg1;
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_Driver_name_get(void * jarg1) {
   char * jresult ;
   OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
@@ -2371,6 +2629,46 @@ SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_DeleteLayer(void * jarg1, int jarg2
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_DataSource_SyncToDisk(void * jarg1) {
+  int jresult ;
+  OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRDataSourceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+    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_DataSource_CreateLayer(void * jarg1, char * jarg2, void * jarg3, int jarg4, void * jarg5) {
   void * jresult ;
   OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
@@ -3486,6 +3784,192 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Layer_CreateField(void * jarg1, void * jarg2,
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_Layer_DeleteField(void * jarg1, int jarg2) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_DeleteField(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_Layer_ReorderField(void * jarg1, int jarg2, int jarg3) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (int)jarg3; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_ReorderField(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_Layer_ReorderFields(void * jarg1, int jarg2, void * jarg3) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    /* %typemap(in) (int inout[ANY]) */
+    arg3 = (int *)jarg3;
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_ReorderFields(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_Layer_AlterFieldDefn(void * jarg1, int jarg2, void * jarg3, int jarg4) {
+  int jresult ;
+  OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 ;
+  OGRFieldDefnShadow *arg3 = (OGRFieldDefnShadow *) 0 ;
+  int arg4 ;
+  OGRErr result;
+  
+  arg1 = (OGRLayerShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  arg3 = (OGRFieldDefnShadow *)jarg3; 
+  arg4 = (int)jarg4; 
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+    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_StartTransaction(void * jarg1) {
   int jresult ;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
@@ -7131,15 +7615,17 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_Geometry_ExportToKML(void * jarg1, char * j
 }
 
 
-SWIGEXPORT char * SWIGSTDCALL CSharp_Geometry_ExportToJson(void * jarg1) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_Geometry_ExportToJson(void * jarg1, void * jarg2) {
   char * jresult ;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
   retStringAndCPLFree *result = 0 ;
   
   arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (char **)jarg2; 
   {
     CPLErrorReset();
-    result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1);
+    result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -7924,6 +8410,41 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_Geometry_Simplify(void * jarg1, double jarg
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_Geometry_SimplifyPreserveTopology(void * jarg1, double jarg2) {
+  void * jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double arg2 ;
+  OGRGeometryShadow *result = 0 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (double)jarg2; 
+  {
+    CPLErrorReset();
+    result = (OGRGeometryShadow *)OGRGeometryShadow_SimplifyPreserveTopology(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_Geometry_Boundary(void * jarg1) {
   void * jresult ;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -9208,6 +9729,37 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_GetEnvelope(void * jarg1, void * jar
 }
 
 
+SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_GetEnvelope3D(void * jarg1, void * jarg2) {
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  OGREnvelope3D *arg2 = (OGREnvelope3D *) 0 ;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (OGREnvelope3D *)jarg2; 
+  {
+    CPLErrorReset();
+    OGRGeometryShadow_GetEnvelope3D(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT void * SWIGSTDCALL CSharp_Geometry_Centroid(void * jarg1) {
   void * jresult ;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
diff --git a/swig/csharp/ogr/osr_wrap.cpp b/swig/csharp/ogr/osr_wrap.cpp
index 5bb109c..96969ef 100644
--- a/swig/csharp/ogr/osr_wrap.cpp
+++ b/swig/csharp/ogr/osr_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -201,7 +201,7 @@ static SWIG_CSharpException_t SWIG_csharp_exceptions[] = {
 static SWIG_CSharpExceptionArgument_t SWIG_csharp_exceptions_argument[] = {
   { SWIG_CSharpArgumentException, NULL },
   { SWIG_CSharpArgumentNullException, NULL },
-  { SWIG_CSharpArgumentOutOfRangeException, NULL },
+  { SWIG_CSharpArgumentOutOfRangeException, NULL }
 };
 
 static void SWIGUNUSED SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg) {
@@ -442,15 +442,27 @@ SWIGINTERN int OSRSpatialReferenceShadow_IsSame(OSRSpatialReferenceShadow *self,
 SWIGINTERN int OSRSpatialReferenceShadow_IsSameGeogCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
     return OSRIsSameGeogCS( self, rhs );
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsSameVertCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
+    return OSRIsSameVertCS( self, rhs );
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsGeographic(OSRSpatialReferenceShadow *self){
     return OSRIsGeographic(self);
   }
 SWIGINTERN int OSRSpatialReferenceShadow_IsProjected(OSRSpatialReferenceShadow *self){
     return OSRIsProjected(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsCompound(OSRSpatialReferenceShadow *self){
+    return OSRIsCompound(self);
+  }
+SWIGINTERN int OSRSpatialReferenceShadow_IsGeocentric(OSRSpatialReferenceShadow *self){
+    return OSRIsGeocentric(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsLocal(OSRSpatialReferenceShadow *self){
     return OSRIsLocal(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *self){
+    return OSRIsVertical(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
@@ -470,6 +482,9 @@ SWIGINTERN double OSRSpatialReferenceShadow_GetAngularUnits(OSRSpatialReferenceS
     // Return code ignored.
     return OSRGetAngularUnits( self, 0 );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target,char const *name,double to_meters){
+    return OSRSetTargetLinearUnits( self, target, name, to_meters );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnits( self, name, to_meters );
   }
@@ -594,6 +609,9 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGS(OSRSpatialReferenceShadow *sel
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGH(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
     return OSRSetGH( self, cm, fe, fn );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetIGH(OSRSpatialReferenceShadow *self){
+    return OSRSetIGH( self );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *self,double cm,double satelliteheight,double fe,double fn){
     return OSRSetGEOS( self, cm, satelliteheight,
                        fe, fn );
@@ -723,6 +741,15 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeogCS(OSRSpatialReferenceShadow
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
     return OSRSetProjCS( self, name );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeocCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
+    return OSRSetGeocCS( self, name );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVertCS(OSRSpatialReferenceShadow *self,char const *VertCSName="unnamed",char const *VertDatumName="unnamed",int VertDatumType=0){
+    return OSRSetVertCS( self, VertCSName, VertDatumName, VertDatumType );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCompoundCS(OSRSpatialReferenceShadow *self,char const *name,OSRSpatialReferenceShadow *horizcs,OSRSpatialReferenceShadow *vertcs){
+    return OSRSetCompoundCS( self, name, horizcs, vertcs );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromWkt(OSRSpatialReferenceShadow *self,char **ppszInput){
     return OSRImportFromWkt( self, ppszInput );
   }
@@ -809,15 +836,21 @@ SWIGINTERN void delete_OSRCoordinateTransformationShadow(OSRCoordinateTransforma
     OCTDestroyCoordinateTransformation( self );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_0(OSRCoordinateTransformationShadow *self,double inout[3]){
+    if (self == NULL)
+        return;
     OCTTransform( self, 1, &inout[0], &inout[1], &inout[2] );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_1(OSRCoordinateTransformationShadow *self,double argout[3],double x,double y,double z=0.0){
+    if (self == NULL)
+        return;
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
     OCTTransform( self, 1, &argout[0], &argout[1], &argout[2] );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoints(OSRCoordinateTransformationShadow *self,int nCount,double *x,double *y,double *z){
+    if (self == NULL)
+        return;
     OCTTransform( self, nCount, x, y, z );
   }
 
@@ -1301,6 +1334,48 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsSameGeogCS(void * jarg1, vo
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsSameVertCS(void * jarg1, void * jarg2) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (OSRSpatialReferenceShadow *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsSameVertCS(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_SpatialReference_IsGeographic(void * jarg1) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -1367,6 +1442,72 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsProjected(void * jarg1) {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsCompound(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsCompound(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_IsGeocentric(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsGeocentric(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_IsLocal(void * jarg1) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -1400,6 +1541,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsLocal(void * jarg1) {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsVertical(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsVertical(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_EPSGTreatsAsLatLong(void * jarg1) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -1658,6 +1832,59 @@ SWIGEXPORT double SWIGSTDCALL CSharp_SpatialReference_GetAngularUnits(void * jar
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetTargetLinearUnits(void * jarg1, char * jarg2, char * jarg3, double jarg4) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  double arg4 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (double)jarg4; 
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetTargetLinearUnits(arg1,(char const *)arg2,(char const *)arg3,arg4);
+    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_SpatialReference_SetLinearUnits(void * jarg1, char * jarg2, double jarg3) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -3020,6 +3247,46 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetGH(void * jarg1, double ja
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetIGH(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetIGH(arg1);
+    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_SpatialReference_SetGEOS(void * jarg1, double jarg2, double jarg3, double jarg4, double jarg5) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -4701,6 +4968,168 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetProjCS(void * jarg1, char
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetGeocCS(void * jarg1, char * jarg2) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) "unnamed" ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetGeocCS(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_SpatialReference_SetVertCS(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) "unnamed" ;
+  char *arg3 = (char *) "unnamed" ;
+  int arg4 = (int) 0 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (int)jarg4; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetVertCS(arg1,(char const *)arg2,(char const *)arg3,arg4);
+    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_SpatialReference_SetCompoundCS(void * jarg1, char * jarg2, void * jarg3, void * jarg4) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg4 = (OSRSpatialReferenceShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (OSRSpatialReferenceShadow *)jarg3; 
+  arg4 = (OSRSpatialReferenceShadow *)jarg4; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg4) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetCompoundCS(arg1,(char const *)arg2,arg3,arg4);
+    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_SpatialReference_ImportFromWkt(void * jarg1, void * jarg2) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -4800,6 +5229,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_ImportFromUrl(void * jarg1, c
   arg1 = (OSRSpatialReferenceShadow *)jarg1; 
   arg2 = (char *)jarg2; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromUrl(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -5114,6 +5550,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_ImportFromERM(void * jarg1, c
   arg3 = (char *)jarg3; 
   arg4 = (char *)jarg4; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromERM(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
     CPLErr eclass = CPLGetLastErrorType();
diff --git a/swig/csharp/ogr/wkbByteOrder.cs b/swig/csharp/ogr/wkbByteOrder.cs
index 2ee0cb6..6f47302 100644
--- a/swig/csharp/ogr/wkbByteOrder.cs
+++ b/swig/csharp/ogr/wkbByteOrder.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/ogr/wkbGeometryType.cs b/swig/csharp/ogr/wkbGeometryType.cs
index 9b1086e..a54c736 100644
--- a/swig/csharp/ogr/wkbGeometryType.cs
+++ b/swig/csharp/ogr/wkbGeometryType.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/osr/CoordinateTransformation.cs b/swig/csharp/osr/CoordinateTransformation.cs
index 6c86dff..eed58d6 100644
--- a/swig/csharp/osr/CoordinateTransformation.cs
+++ b/swig/csharp/osr/CoordinateTransformation.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
diff --git a/swig/csharp/osr/Osr.cs b/swig/csharp/osr/Osr.cs
index 77f115d..0810071 100644
--- a/swig/csharp/osr/Osr.cs
+++ b/swig/csharp/osr/Osr.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -117,6 +117,7 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public const string SRS_PT_GAUSSSCHREIBERTMERCATOR = "Gauss_Schreiber_Transverse_Mercator";
   public const string SRS_PT_GEOSTATIONARY_SATELLITE = "Geostationary_Satellite";
   public const string SRS_PT_GOODE_HOMOLOSINE = "Goode_Homolosine";
+  public const string SRS_PT_IGH = "Interrupted_Goode_Homolosine";
   public const string SRS_PT_GNOMONIC = "Gnomonic";
   public const string SRS_PT_HOTINE_OBLIQUE_MERCATOR = "Hotine_Oblique_Mercator";
   public const string SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN = "Hotine_Oblique_Mercator_Two_Point_Natural_Origin";
@@ -199,6 +200,8 @@ public delegate void GDALErrorHandlerDelegate(int eclass, int code, IntPtr msg);
   public const string SRS_UL_CHAIN_CONV = "20.116684023368047";
   public const string SRS_UL_ROD = "Rod";
   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_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 4f761d9..1800e67 100644
--- a/swig/csharp/osr/OsrPINVOKE.cs
+++ b/swig/csharp/osr/OsrPINVOKE.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -246,15 +246,27 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsSameGeogCS")]
   public static extern int SpatialReference_IsSameGeogCS(HandleRef jarg1, HandleRef jarg2);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsSameVertCS")]
+  public static extern int SpatialReference_IsSameVertCS(HandleRef jarg1, HandleRef jarg2);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsGeographic")]
   public static extern int SpatialReference_IsGeographic(HandleRef jarg1);
 
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsProjected")]
   public static extern int SpatialReference_IsProjected(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsCompound")]
+  public static extern int SpatialReference_IsCompound(HandleRef jarg1);
+
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsGeocentric")]
+  public static extern int SpatialReference_IsGeocentric(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsLocal")]
   public static extern int SpatialReference_IsLocal(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_IsVertical")]
+  public static extern int SpatialReference_IsVertical(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_EPSGTreatsAsLatLong")]
   public static extern int SpatialReference_EPSGTreatsAsLatLong(HandleRef jarg1);
 
@@ -273,6 +285,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_GetAngularUnits")]
   public static extern double SpatialReference_GetAngularUnits(HandleRef jarg1);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetTargetLinearUnits")]
+  public static extern int SpatialReference_SetTargetLinearUnits(HandleRef jarg1, string jarg2, string jarg3, double jarg4);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetLinearUnits")]
   public static extern int SpatialReference_SetLinearUnits(HandleRef jarg1, string jarg2, double jarg3);
 
@@ -366,6 +381,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetGH")]
   public static extern int SpatialReference_SetGH(HandleRef jarg1, double jarg2, double jarg3, double jarg4);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetIGH")]
+  public static extern int SpatialReference_SetIGH(HandleRef jarg1);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetGEOS")]
   public static extern int SpatialReference_SetGEOS(HandleRef jarg1, double jarg2, double jarg3, double jarg4, double jarg5);
 
@@ -468,6 +486,15 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetProjCS")]
   public static extern int SpatialReference_SetProjCS(HandleRef jarg1, string jarg2);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetGeocCS")]
+  public static extern int SpatialReference_SetGeocCS(HandleRef jarg1, string jarg2);
+
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetVertCS")]
+  public static extern int SpatialReference_SetVertCS(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
+
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetCompoundCS")]
+  public static extern int SpatialReference_SetCompoundCS(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_ImportFromWkt")]
   public static extern int SpatialReference_ImportFromWkt(HandleRef jarg1, ref string jarg2);
 
diff --git a/swig/csharp/osr/SpatialReference.cs b/swig/csharp/osr/SpatialReference.cs
index 64528f1..7d668d4 100644
--- a/swig/csharp/osr/SpatialReference.cs
+++ b/swig/csharp/osr/SpatialReference.cs
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  *
  * Do not make changes to this file unless you know what you are doing--modify
  * the SWIG interface file instead.
@@ -90,6 +90,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int IsSameVertCS(SpatialReference rhs) {
+    int ret = OsrPINVOKE.SpatialReference_IsSameVertCS(swigCPtr, SpatialReference.getCPtr(rhs));
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int IsGeographic() {
     int ret = OsrPINVOKE.SpatialReference_IsGeographic(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -102,12 +108,30 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int IsCompound() {
+    int ret = OsrPINVOKE.SpatialReference_IsCompound(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int IsGeocentric() {
+    int ret = OsrPINVOKE.SpatialReference_IsGeocentric(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int IsLocal() {
     int ret = OsrPINVOKE.SpatialReference_IsLocal(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
     return ret;
   }
 
+  public int IsVertical() {
+    int ret = OsrPINVOKE.SpatialReference_IsVertical(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int EPSGTreatsAsLatLong() {
     int ret = OsrPINVOKE.SpatialReference_EPSGTreatsAsLatLong(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -144,6 +168,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int SetTargetLinearUnits(string target, string name, double to_meters) {
+    int ret = OsrPINVOKE.SpatialReference_SetTargetLinearUnits(swigCPtr, target, name, to_meters);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int SetLinearUnits(string name, double to_meters) {
     int ret = OsrPINVOKE.SpatialReference_SetLinearUnits(swigCPtr, name, to_meters);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -330,6 +360,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int SetIGH() {
+    int ret = OsrPINVOKE.SpatialReference_SetIGH(swigCPtr);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int SetGEOS(double cm, double satelliteheight, double fe, double fn) {
     int ret = OsrPINVOKE.SpatialReference_SetGEOS(swigCPtr, cm, satelliteheight, fe, fn);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
@@ -534,6 +570,24 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public int SetGeocCS(string name) {
+    int ret = OsrPINVOKE.SpatialReference_SetGeocCS(swigCPtr, name);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SetVertCS(string VertCSName, string VertDatumName, int VertDatumType) {
+    int ret = OsrPINVOKE.SpatialReference_SetVertCS(swigCPtr, VertCSName, VertDatumName, VertDatumType);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public int SetCompoundCS(string name, SpatialReference horizcs, SpatialReference vertcs) {
+    int ret = OsrPINVOKE.SpatialReference_SetCompoundCS(swigCPtr, name, SpatialReference.getCPtr(horizcs), SpatialReference.getCPtr(vertcs));
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int ImportFromWkt(ref string ppszInput) {
     int ret = OsrPINVOKE.SpatialReference_ImportFromWkt(swigCPtr, ref ppszInput);
     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 5bb109c..96969ef 100644
--- a/swig/csharp/osr/osr_wrap.cpp
+++ b/swig/csharp/osr/osr_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -201,7 +201,7 @@ static SWIG_CSharpException_t SWIG_csharp_exceptions[] = {
 static SWIG_CSharpExceptionArgument_t SWIG_csharp_exceptions_argument[] = {
   { SWIG_CSharpArgumentException, NULL },
   { SWIG_CSharpArgumentNullException, NULL },
-  { SWIG_CSharpArgumentOutOfRangeException, NULL },
+  { SWIG_CSharpArgumentOutOfRangeException, NULL }
 };
 
 static void SWIGUNUSED SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg) {
@@ -442,15 +442,27 @@ SWIGINTERN int OSRSpatialReferenceShadow_IsSame(OSRSpatialReferenceShadow *self,
 SWIGINTERN int OSRSpatialReferenceShadow_IsSameGeogCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
     return OSRIsSameGeogCS( self, rhs );
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsSameVertCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
+    return OSRIsSameVertCS( self, rhs );
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsGeographic(OSRSpatialReferenceShadow *self){
     return OSRIsGeographic(self);
   }
 SWIGINTERN int OSRSpatialReferenceShadow_IsProjected(OSRSpatialReferenceShadow *self){
     return OSRIsProjected(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsCompound(OSRSpatialReferenceShadow *self){
+    return OSRIsCompound(self);
+  }
+SWIGINTERN int OSRSpatialReferenceShadow_IsGeocentric(OSRSpatialReferenceShadow *self){
+    return OSRIsGeocentric(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsLocal(OSRSpatialReferenceShadow *self){
     return OSRIsLocal(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *self){
+    return OSRIsVertical(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
@@ -470,6 +482,9 @@ SWIGINTERN double OSRSpatialReferenceShadow_GetAngularUnits(OSRSpatialReferenceS
     // Return code ignored.
     return OSRGetAngularUnits( self, 0 );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target,char const *name,double to_meters){
+    return OSRSetTargetLinearUnits( self, target, name, to_meters );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnits( self, name, to_meters );
   }
@@ -594,6 +609,9 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGS(OSRSpatialReferenceShadow *sel
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGH(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
     return OSRSetGH( self, cm, fe, fn );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetIGH(OSRSpatialReferenceShadow *self){
+    return OSRSetIGH( self );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *self,double cm,double satelliteheight,double fe,double fn){
     return OSRSetGEOS( self, cm, satelliteheight,
                        fe, fn );
@@ -723,6 +741,15 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeogCS(OSRSpatialReferenceShadow
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
     return OSRSetProjCS( self, name );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeocCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
+    return OSRSetGeocCS( self, name );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVertCS(OSRSpatialReferenceShadow *self,char const *VertCSName="unnamed",char const *VertDatumName="unnamed",int VertDatumType=0){
+    return OSRSetVertCS( self, VertCSName, VertDatumName, VertDatumType );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCompoundCS(OSRSpatialReferenceShadow *self,char const *name,OSRSpatialReferenceShadow *horizcs,OSRSpatialReferenceShadow *vertcs){
+    return OSRSetCompoundCS( self, name, horizcs, vertcs );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromWkt(OSRSpatialReferenceShadow *self,char **ppszInput){
     return OSRImportFromWkt( self, ppszInput );
   }
@@ -809,15 +836,21 @@ SWIGINTERN void delete_OSRCoordinateTransformationShadow(OSRCoordinateTransforma
     OCTDestroyCoordinateTransformation( self );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_0(OSRCoordinateTransformationShadow *self,double inout[3]){
+    if (self == NULL)
+        return;
     OCTTransform( self, 1, &inout[0], &inout[1], &inout[2] );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_1(OSRCoordinateTransformationShadow *self,double argout[3],double x,double y,double z=0.0){
+    if (self == NULL)
+        return;
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
     OCTTransform( self, 1, &argout[0], &argout[1], &argout[2] );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoints(OSRCoordinateTransformationShadow *self,int nCount,double *x,double *y,double *z){
+    if (self == NULL)
+        return;
     OCTTransform( self, nCount, x, y, z );
   }
 
@@ -1301,6 +1334,48 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsSameGeogCS(void * jarg1, vo
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsSameVertCS(void * jarg1, void * jarg2) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (OSRSpatialReferenceShadow *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsSameVertCS(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_SpatialReference_IsGeographic(void * jarg1) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -1367,6 +1442,72 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsProjected(void * jarg1) {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsCompound(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsCompound(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_IsGeocentric(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsGeocentric(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_IsLocal(void * jarg1) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -1400,6 +1541,39 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsLocal(void * jarg1) {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_IsVertical(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  int result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (int)OSRSpatialReferenceShadow_IsVertical(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_EPSGTreatsAsLatLong(void * jarg1) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -1658,6 +1832,59 @@ SWIGEXPORT double SWIGSTDCALL CSharp_SpatialReference_GetAngularUnits(void * jar
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetTargetLinearUnits(void * jarg1, char * jarg2, char * jarg3, double jarg4) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  double arg4 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (double)jarg4; 
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetTargetLinearUnits(arg1,(char const *)arg2,(char const *)arg3,arg4);
+    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_SpatialReference_SetLinearUnits(void * jarg1, char * jarg2, double jarg3) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -3020,6 +3247,46 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetGH(void * jarg1, double ja
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetIGH(void * jarg1) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetIGH(arg1);
+    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_SpatialReference_SetGEOS(void * jarg1, double jarg2, double jarg3, double jarg4, double jarg5) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -4701,6 +4968,168 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetProjCS(void * jarg1, char
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetGeocCS(void * jarg1, char * jarg2) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) "unnamed" ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetGeocCS(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_SpatialReference_SetVertCS(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) "unnamed" ;
+  char *arg3 = (char *) "unnamed" ;
+  int arg4 = (int) 0 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (char *)jarg3; 
+  arg4 = (int)jarg4; 
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetVertCS(arg1,(char const *)arg2,(char const *)arg3,arg4);
+    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_SpatialReference_SetCompoundCS(void * jarg1, char * jarg2, void * jarg3, void * jarg4) {
+  int jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg4 = (OSRSpatialReferenceShadow *) 0 ;
+  OGRErr result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  arg3 = (OSRSpatialReferenceShadow *)jarg3; 
+  arg4 = (OSRSpatialReferenceShadow *)jarg4; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg4) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (OGRErr)OSRSpatialReferenceShadow_SetCompoundCS(arg1,(char const *)arg2,arg3,arg4);
+    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_SpatialReference_ImportFromWkt(void * jarg1, void * jarg2) {
   int jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -4800,6 +5229,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_ImportFromUrl(void * jarg1, c
   arg1 = (OSRSpatialReferenceShadow *)jarg1; 
   arg2 = (char *)jarg2; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromUrl(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
@@ -5114,6 +5550,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_ImportFromERM(void * jarg1, c
   arg3 = (char *)jarg3; 
   arg4 = (char *)jarg4; 
   {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg3) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
     CPLErrorReset();
     result = (OGRErr)OSRSpatialReferenceShadow_ImportFromERM(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
     CPLErr eclass = CPLGetLastErrorType();
diff --git a/swig/include/Band.i b/swig/include/Band.i
index d2a7c34..2a1148e 100644
--- a/swig/include/Band.i
+++ b/swig/include/Band.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Band.i 20085 2010-07-17 18:00:47Z rouault $
+ * $Id: Band.i 21773 2011-02-21 19:28:07Z rouault $
  *
  * Name:     Band.i
  * Project:  GDAL Python Interface
@@ -530,6 +530,19 @@ CPLErr SetDefaultHistogram( double min, double max,
       return (GDALHasArbitraryOverviews( self ) != 0) ? true : false;
   }
 
+  /* Interface method added for GDAL 1.9.0 */
+%apply (char **options) {char **};
+  char **GetCategoryNames() {
+    return GDALGetRasterCategoryNames( self );
+  }
+%clear char **;
+
+%apply (char **options) { char ** papszCategoryNames };
+  CPLErr SetCategoryNames( char ** papszCategoryNames ) {
+    return GDALSetRasterCategoryNames( self, papszCategoryNames );
+  }
+%clear char **papszMetadata;
+
 } /* %extend */
 
 };
diff --git a/swig/include/MajorObject.i b/swig/include/MajorObject.i
index 0d8a4a8..e3a0f98 100644
--- a/swig/include/MajorObject.i
+++ b/swig/include/MajorObject.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: MajorObject.i 19353 2010-04-09 20:34:50Z rouault $
+ * $Id: MajorObject.i 21979 2011-03-18 22:22:32Z rouault $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  SWIG Definitions for GDALMajorObject.
@@ -46,9 +46,11 @@ public:
 /*
  * SetDescription
  */
+%apply Pointer NONNULL {const char * pszNewDesc};
   void SetDescription( const char *pszNewDesc ) {
     GDALSetDescription( self, pszNewDesc );
   }
+%clear const char * pszNewDesc;
 
 /*
  * GetMetadata methods
diff --git a/swig/include/cpl.i b/swig/include/cpl.i
index 868000a..5631be9 100644
--- a/swig/include/cpl.i
+++ b/swig/include/cpl.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl.i 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: cpl.i 23398 2011-11-20 14:01:47Z ajolma $
  *
  * Name:     cpl.i
  * Project:  GDAL Python Interface
@@ -186,7 +186,7 @@ char* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
 %clear (int len, char *bin_string);
 #endif
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGCSHARP)
 /* We don't want errors to be cleared or thrown by this */
 /* call */
 %exception CPLGetLastErrorNo
@@ -196,7 +196,7 @@ char* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
 #endif
 int CPLGetLastErrorNo();
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGCSHARP)
 /* We don't want errors to be cleared or thrown by this */
 /* call */
 %exception CPLGetLastErrorType
@@ -208,7 +208,7 @@ int CPLGetLastErrorType();
 CPLErr CPLGetLastErrorType();
 #endif
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGCSHARP)
 /* We don't want errors to be cleared or thrown by this */
 /* call */
 %exception CPLGetLastErrorMsg
@@ -248,6 +248,10 @@ retStringAndCPLFree* CPLBinaryToHex( int nBytes, const GByte *pabyData );
 %clear ( int nBytes, const GByte *pabyData );
 #elif defined(SWIGCSHARP)
 retStringAndCPLFree* CPLBinaryToHex( int nBytes, const GByte *pabyData );
+#elif defined(SWIGPYTHON)
+%apply (int nLen, char *pBuf) {( int nBytes, const GByte *pabyData )};
+retStringAndCPLFree* CPLBinaryToHex( int nBytes, const GByte *pabyData );
+%clear ( int nBytes, const GByte *pabyData );
 #else
 /* FIXME : wrong typemap. The string should be freed */
 char * CPLBinaryToHex( int nBytes, const GByte *pabyData );
@@ -287,7 +291,7 @@ void wrapper_VSIFileFromMemBuffer( const char* utf8_path, int nBytes, const GByt
 #endif
 
 /* Added in GDAL 1.7.0 */
-int VSIUnlink(const char * pszFilename );
+int VSIUnlink(const char * utf8_path );
 
 /* Added in GDAL 1.7.0 */
 /* Thread support is necessary for binding languages with threaded GC */
@@ -319,14 +323,107 @@ typedef void VSILFILE;
 %apply RETURN_NONE_TRUE_IS_ERROR {RETURN_NONE};
 RETURN_NONE VSIStatL( const char * utf8_path, VSIStatBufL *psStatBuf );
 %clear RETURN_NONE;
+
+#elif defined(SWIGPYTHON)
+
+%{
+typedef struct
+{
+  int     mode;
+  GIntBig size;
+  GIntBig mtime;
+} StatBuf;
+%}
+
+#define VSI_STAT_EXISTS_FLAG    0x1
+#define VSI_STAT_NATURE_FLAG    0x2
+#define VSI_STAT_SIZE_FLAG      0x4
+
+struct StatBuf
+{
+%apply (GIntBig bigint) { GIntBig };
+%immutable;
+  int         mode;
+  GIntBig     size;
+  GIntBig     mtime;
+%mutable;
+%clear (GIntBig bigint);
+
+%extend {
+  StatBuf( StatBuf *psStatBuf ) {
+    StatBuf *self = (StatBuf*) CPLMalloc( sizeof( StatBuf ) );
+    self->mode = psStatBuf->mode;
+    self->size = psStatBuf->size;
+    self->mtime = psStatBuf->mtime;
+    return self;
+  }
+
+  ~StatBuf() {
+    CPLFree(self);
+  }
+
+  int IsDirectory()
+  {
+     return (self->mode & S_IFDIR) != 0;
+  }
+
+} /* extend */
+} /* StatBuf */ ;
+
+%rename (VSIStatL) wrapper_VSIStatL;
+%inline {
+int wrapper_VSIStatL( const char * utf8_path, StatBuf *psStatBufOut, int nFlags = 0 )
+{
+    VSIStatBufL sStat;
+    memset(&sStat, 0, sizeof(sStat));
+    memset(psStatBufOut, 0, sizeof(StatBuf));
+    int nRet = VSIStatExL(utf8_path, &sStat, nFlags);
+    psStatBufOut->mode = sStat.st_mode;
+    psStatBufOut->size = (GIntBig)sStat.st_size;
+    psStatBufOut->mtime = (GIntBig)sStat.st_mtime;
+    return nRet;
+}
+}
+
 #endif
 
 VSILFILE   *VSIFOpenL( const char *utf8_path, const char *pszMode );
 void    VSIFCloseL( VSILFILE * );
+
+#if defined(SWIGPYTHON)
+%apply (GIntBig bigint) { GIntBig };
+int     VSIFSeekL( VSILFILE *, GIntBig, int );
+GIntBig    VSIFTellL( VSILFILE * );
+int     VSIFTruncateL( VSILFILE *, GIntBig );
+%clear (GIntBig bigint);
+#else
 int     VSIFSeekL( VSILFILE *, long, int );
 long    VSIFTellL( VSILFILE * );
+int     VSIFTruncateL( VSILFILE *, long );
+#endif
+
+#if defined(SWIGPYTHON)
+%rename (VSIFWriteL) wrapper_VSIFWriteL;
+%inline {
+int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE * f)
+{
+    if (nLen < size * memb)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Inconsistant buffer size with 'size' and 'memb' values");
+        return 0;
+    }
+    return VSIFWriteL(pBuf, size, memb, f);
+}
+}
+#elif defined(SWIGPERL)
+size_t VSIFWriteL(const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp);
+#else
 int     VSIFWriteL( const char *, int, int, VSILFILE * );
+#endif
 
+#if defined(SWIGPERL)
+size_t VSIFReadL(void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp);
+#endif
 /* VSIFReadL() handled specially in python/gdal_python.i */
 
 #endif
diff --git a/swig/include/csharp/typemaps_csharp.i b/swig/include/csharp/typemaps_csharp.i
index 6c1698b..478c545 100644
--- a/swig/include/csharp/typemaps_csharp.i
+++ b/swig/include/csharp/typemaps_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_csharp.i 21594 2011-01-27 20:15:39Z tamas $
+ * $Id: typemaps_csharp.i 21588 2011-01-27 15:42:24Z tamas $
  *
  * Name:     typemaps_csharp.i
  * Project:  GDAL CSharp Interface
diff --git a/swig/include/java/gdal_java.i b/swig/include/java/gdal_java.i
index b36d140..2c38061 100644
--- a/swig/include/java/gdal_java.i
+++ b/swig/include/java/gdal_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_java.i 20085 2010-07-17 18:00:47Z rouault $
+ * $Id: gdal_java.i 21579 2011-01-24 21:57:24Z rouault $
  *
  * Name:     gdal_java.i
  * Project:  GDAL SWIG Interface
@@ -42,6 +42,9 @@
   }
 %}
 
+/* This hacks turns the gdalJNI class into a package private class */
+%pragma(java) jniclassimports=%{
+%}
 
 %pragma(java) modulecode=%{
 
diff --git a/swig/include/java/gdalconst_java.i b/swig/include/java/gdalconst_java.i
index e33a9b5..6c75ba1 100644
--- a/swig/include/java/gdalconst_java.i
+++ b/swig/include/java/gdalconst_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalconst_java.i 16316 2009-02-13 20:51:00Z rouault $
+ * $Id: gdalconst_java.i 21579 2011-01-24 21:57:24Z rouault $
  *
  * Name:     gdalconst_java.i
  * Project:  GDAL SWIG Interface
@@ -36,6 +36,10 @@
   }
 %}
 
+/* This hacks turns the gdalconstJNI class into a package private class */
+%pragma(java) jniclassimports=%{
+%}
+
 %pragma(java) modulecode=%{
 
     /* Uninstanciable class */
diff --git a/swig/include/java/ogr_java.i b/swig/include/java/ogr_java.i
index 7431198..31e114a 100644
--- a/swig/include/java/ogr_java.i
+++ b/swig/include/java/ogr_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_java.i 19751 2010-05-22 11:29:53Z rouault $
+ * $Id: ogr_java.i 23330 2011-11-05 21:10:20Z rouault $
  *
  * Name:     ogr_java.i
  * Project:  GDAL SWIG Interface
@@ -129,8 +129,8 @@ import org.gdal.osr.SpatialReference;
       double[] argout = new double[4];
       try
       {
-          GetExtent(argout, (force) ? 1 : 0);
-          return argout;
+          int ret = GetExtent(argout, (force) ? 1 : 0);
+          return (ret == 0) ? argout : null;
       }
       catch(RuntimeException e)
       {
diff --git a/swig/include/java/osr_java.i b/swig/include/java/osr_java.i
index a3e40e3..6b13904 100644
--- a/swig/include/java/osr_java.i
+++ b/swig/include/java/osr_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_java.i 19751 2010-05-22 11:29:53Z rouault $
+ * $Id: osr_java.i 21579 2011-01-24 21:57:24Z rouault $
  *
  * Name:     osr_java.i
  * Project:  GDAL SWIG Interface
@@ -48,6 +48,10 @@
     }
 %}
 
+/* This hacks turns the osrJNI class into a package private class */
+%pragma(java) jniclassimports=%{
+%}
+
 /*
  *  Needed to make the Constructor and getCptr 'public' and not 'protected'.
  *   There is likely a better way to do this (with javamethodmodifiers) but
diff --git a/swig/include/java/typemaps_java.i b/swig/include/java/typemaps_java.i
index 435a917..abe130d 100644
--- a/swig/include/java/typemaps_java.i
+++ b/swig/include/java/typemaps_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_java.i 20641 2010-09-18 11:35:15Z rouault $
+ * $Id: typemaps_java.i 22044 2011-03-26 14:47:20Z rouault $
  *
  * Name:     typemaps_java.i
  * Project:  GDAL SWIG Interface
@@ -1611,7 +1611,6 @@ DEFINE_REGULAR_ARRAY_IN(double, jdouble, GetDoubleArrayElements, ReleaseDoubleAr
     return $jnicall;
   }
 
-
 /***************************************************
  * Typemaps for ( int *panSuccess )
  ***************************************************/
@@ -1651,3 +1650,60 @@ DEFINE_REGULAR_ARRAY_IN(double, jdouble, GetDoubleArrayElements, ReleaseDoubleAr
 %typemap(javaout) ( int *panSuccess ) {
     return $jnicall;
   }
+
+/***************************************************
+ * Typemaps for Gemetry.GetPoints()
+ ***************************************************/
+
+%typemap(in,numinputs=0) (int* pnCount, double** ppadfXY, double** ppadfZ) ( int nPoints = 0, double* padfXY = NULL, double* padfZ = NULL)
+{
+  /* %typemap(in,numinputs=0) (int* pnCount, double** ppadfXY, double** ppadfZ) */
+  $1 = &nPoints;
+  $2 = &padfXY;
+  $3 = &padfZ;
+}
+
+%typemap(argout)  (int* pnCount, double** ppadfXY, double** ppadfZ)
+{
+  /* %typemap(out)  (int* pnCount, double** ppadfXY, double** ppadfZ) */
+
+  int nPointCount = *($1);
+  if (nPointCount == 0)
+  {
+    $result = 0;
+  }
+  else
+  {
+    int nDimensions = (*$3 != NULL) ? 3 : 2;
+    $result = jenv->NewObjectArray(nPointCount, jenv->FindClass("java/lang/Object"), NULL);
+    for( int i=0; i< nPointCount; i++ )
+    {
+        jdoubleArray dblArray = jenv->NewDoubleArray(nDimensions);
+        jenv->SetDoubleArrayRegion(dblArray, 0, 2, &( (*$2)[2*i] ));
+        if (nDimensions == 3)
+            jenv->SetDoubleArrayRegion(dblArray, 2, 1, &( (*$3)[i] ));
+        jenv->SetObjectArrayElement($result, (jsize)i, dblArray);
+        jenv->DeleteLocalRef(dblArray);
+    }
+  }
+}
+
+%typemap(freearg)  (int* pnCount, double** ppadfXY, double** ppadfZ)
+{
+    /* %typemap(freearg)  (int* pnCount, double** ppadfXY, double** ppadfZ) */
+    VSIFree(*$2);
+    VSIFree(*$3);
+}
+
+%typemap(argout)  (retGetPoints*)
+{
+    /* foo */
+}
+
+%typemap(jni) ( retGetPoints* ) "jobjectArray"
+%typemap(jtype) ( retGetPoints* ) "double[][]"
+%typemap(jstype) ( retGetPoints* ) "double[][]"
+%typemap(javain) ( retGetPoints* ) "$javainput"
+%typemap(javaout) ( retGetPoints* ) {
+    return $jnicall;
+  }
diff --git a/swig/include/ogr.i b/swig/include/ogr.i
index b59fadd..39f042f 100644
--- a/swig/include/ogr.i
+++ b/swig/include/ogr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr.i 21660 2011-02-08 21:37:51Z rouault $
+ * $Id: ogr.i 23513 2011-12-10 21:12:59Z rouault $
  *
  * Project:  OGR Core SWIG Interface declarations.
  * Purpose:  OGR declarations.
@@ -151,6 +151,12 @@ typedef void OGRFieldDefnShadow;
 #endif
 %}
 
+#ifdef SWIGJAVA
+%{
+typedef void retGetPoints;
+%}
+#endif
+
 #ifndef SWIGCSHARP
 #ifdef SWIGJAVA
 %javaconst(1);
@@ -202,6 +208,11 @@ typedef void OGRFieldDefnShadow;
 
 %constant NullFID = -1;
 
+%constant ALTER_NAME_FLAG = 1;
+%constant ALTER_TYPE_FLAG = 2;
+%constant ALTER_WIDTH_PRECISION_FLAG = 4;
+%constant ALTER_ALL_FLAG = 1 + 2 + 4;
+
 %constant char *OLCRandomRead          = "RandomRead";
 %constant char *OLCSequentialWrite     = "SequentialWrite";
 %constant char *OLCRandomWrite         = "RandomWrite";
@@ -209,6 +220,9 @@ typedef void OGRFieldDefnShadow;
 %constant char *OLCFastFeatureCount    = "FastFeatureCount";
 %constant char *OLCFastGetExtent       = "FastGetExtent";
 %constant char *OLCCreateField         = "CreateField";
+%constant char *OLCDeleteField         = "DeleteField";
+%constant char *OLCReorderFields       = "ReorderFields";
+%constant char *OLCAlterFieldDefn      = "AlterFieldDefn";
 %constant char *OLCTransactions        = "Transactions";
 %constant char *OLCDeleteFeature       = "DeleteFeature";
 %constant char *OLCFastSetNextByIndex  = "FastSetNextByIndex";
@@ -236,6 +250,9 @@ typedef int OGRErr;
 #define OLCFastFeatureCount    "FastFeatureCount"
 #define OLCFastGetExtent       "FastGetExtent"
 #define OLCCreateField         "CreateField"
+#define OLCDeleteField         "DeleteField"
+#define OLCReorderFields       "ReorderFields"
+#define OLCAlterFieldDefn      "AlterFieldDefn"
 #define OLCTransactions        "Transactions"
 #define OLCDeleteFeature       "DeleteFeature"
 #define OLCFastSetNextByIndex  "FastSetNextByIndex"
@@ -299,6 +316,17 @@ typedef struct
     double      MinY;
     double      MaxY;
 } OGREnvelope;
+
+%rename (Envelope3D) OGREnvelope3D;
+typedef struct
+{
+    double      MinX;
+    double      MaxX;
+    double      MinY;
+    double      MaxY;
+    double      MinZ;
+    double      MaxZ;
+} OGREnvelope3D;
 #endif
 
 #ifndef GDAL_BINDINGS
@@ -346,6 +374,14 @@ public:
   OGRDataSourceShadow *Open( const char* utf8_path, 
                         int update=0 ) {
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*) OGR_Dr_Open(self, utf8_path, update);
+    if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
+    {
+        CPLDebug( "SWIG",
+          "OGR_Dr_Open() succeeded, but an error is posted, so we destroy"
+          " the datasource and fail at swig level." );
+        OGRReleaseDataSource(ds);
+        ds = NULL;
+    }
     return ds;
   }
 
@@ -426,6 +462,10 @@ public:
     return OGR_DS_DeleteLayer(self, index);
   }
 
+  OGRErr SyncToDisk() {
+    return OGR_DS_SyncToDisk(self);
+  }
+  
   /* Note that datasources own their layers */
 #ifndef SWIGJAVA
   %feature( "kwargs" ) CreateLayer;
@@ -600,6 +640,16 @@ public:
   OGRErr GetExtent(OGREnvelope* extent, int force=1) {
     return OGR_L_GetExtent(self, extent, force);
   }
+#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);
+    if (can_return_null)
+        *isvalid = (eErr == OGRERR_NONE);
+    else
+        *isvalid = TRUE;
+    return;
+  }
 #else
 #ifndef SWIGJAVA
   %feature( "kwargs" ) GetExtent;
@@ -623,7 +673,36 @@ public:
     return OGR_L_CreateField(self, field_def, approx_ok);
   }
 %clear OGRFieldDefnShadow *field_def;
-  
+
+  OGRErr DeleteField(int iField)
+  {
+    return OGR_L_DeleteField(self, iField);
+  }
+
+  OGRErr ReorderField(int iOldFieldPos, int iNewFieldPos)
+  {
+    return OGR_L_ReorderField(self, iOldFieldPos, iNewFieldPos);
+  }
+
+  OGRErr ReorderFields(int nList, int *pList)
+  {
+    if (nList != OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)))
+    {
+      CPLError(CE_Failure, CPLE_IllegalArg,
+               "List should have %d elements",
+               OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)));
+      return OGRERR_FAILURE;
+    }
+    return OGR_L_ReorderFields(self, pList);
+  }
+
+%apply Pointer NONNULL {OGRFieldDefnShadow *field_def};
+  OGRErr AlterFieldDefn(int iField, OGRFieldDefnShadow* field_def, int nFlags)
+  {
+    return OGR_L_AlterFieldDefn(self, iField, field_def, nFlags);
+  }
+%clear OGRFieldDefnShadow *field_def;
+
   OGRErr StartTransaction() {
     return OGR_L_StartTransaction(self);
   }
@@ -1252,7 +1331,7 @@ public:
 %inline %{
   OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
                                       reference,
                                       &geom,
@@ -1277,7 +1356,7 @@ public:
 %inline {
 OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb((unsigned char*) pBuf, reference, &geom, nLen);
     if (err != 0 ) {
        CPLError(CE_Failure, err, "%s", OGRErrMessages(err));
@@ -1296,7 +1375,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
 %inline %{
   OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
                                       OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkt(val,
                                       reference,
                                       &geom);
@@ -1350,7 +1429,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
     return NULL;
   }
 
-  return hPolygon;
+  return (OGRGeometryShadow* )hPolygon;
   }
 %}
 
@@ -1365,7 +1444,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
         double dfStartAngle, double dfEndAngle,
         double dfMaxAngleStepSizeDegrees ) {
   
-  return OGR_G_ApproximateArcAngles( 
+  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
              dfCenterX, dfCenterY, dfZ, 
              dfPrimaryRadius, dfSecondaryAxis, dfRotation,
              dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
@@ -1379,7 +1458,7 @@ OGRGeometryShadow* CreateGeometryFromWkb(int nLen, unsigned char *pBuf,
 OGRGeometryShadow* ForceToPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
 }
 %}
 
@@ -1390,7 +1469,7 @@ OGRGeometryShadow* ForceToPolygon( OGRGeometryShadow *geom_in ) {
 OGRGeometryShadow* ForceToMultiPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
 }
 %}
 
@@ -1401,7 +1480,7 @@ OGRGeometryShadow* ForceToMultiPolygon( OGRGeometryShadow *geom_in ) {
 OGRGeometryShadow* ForceToMultiPoint( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
 }
 %}
 
@@ -1412,7 +1491,7 @@ OGRGeometryShadow* ForceToMultiPoint( OGRGeometryShadow *geom_in ) {
 OGRGeometryShadow* ForceToMultiLineString( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
 }
 %}
 
@@ -1522,8 +1601,11 @@ public:
 #endif
 
 #if defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGPERL)
-  retStringAndCPLFree* ExportToJson() {
-    return (retStringAndCPLFree *) OGR_G_ExportToJson(self);
+#ifndef SWIGJAVA
+  %feature("kwargs") ExportToJson;
+#endif
+  retStringAndCPLFree* ExportToJson(char** options=0) {
+    return (retStringAndCPLFree *) OGR_G_ExportToJsonEx(self, options);
   }
 #else
   /* FIXME : wrong typemap. The string should be freed */
@@ -1588,6 +1670,63 @@ public:
     return OGR_G_GetPointCount(self);
   }
 
+  /* since GDAL 1.9.0 */
+#if defined(SWIGPYTHON) || defined(SWIGJAVA)
+#ifdef SWIGJAVA
+  retGetPoints* GetPoints(int* pnCount, double** ppadfXY, double** ppadfZ, int nCoordDimension = 0)
+  {
+    int nPoints = OGR_G_GetPointCount(self);
+    *pnCount = nPoints;
+    if (nPoints == 0)
+    {
+        *ppadfXY = NULL;
+        *ppadfZ = NULL;
+    }
+    *ppadfXY = (double*)VSIMalloc(2 * sizeof(double) * nPoints);
+    if (*ppadfXY == NULL)
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate resulting array");
+        *pnCount = 0;
+        return NULL;
+    }
+    if (nCoordDimension <= 0)
+        nCoordDimension = OGR_G_GetCoordinateDimension(self);
+    *ppadfZ = (nCoordDimension == 3) ? (double*)VSIMalloc(sizeof(double) * nPoints) : NULL;
+    OGR_G_GetPoints(self,
+                    *ppadfXY, 2 * sizeof(double),
+                    (*ppadfXY) + 1, 2 * sizeof(double),
+                    *ppadfZ, sizeof(double));
+    return NULL;
+  }
+#else
+  %feature("kwargs") GetPoints;
+  void GetPoints(int* pnCount, double** ppadfXY, double** ppadfZ, int nCoordDimension = 0)
+  {
+    int nPoints = OGR_G_GetPointCount(self);
+    *pnCount = nPoints;
+    if (nPoints == 0)
+    {
+        *ppadfXY = NULL;
+        *ppadfZ = NULL;
+    }
+    *ppadfXY = (double*)VSIMalloc(2 * sizeof(double) * nPoints);
+    if (*ppadfXY == NULL)
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate resulting array");
+        *pnCount = 0;
+        return;
+    }
+    if (nCoordDimension <= 0)
+        nCoordDimension = OGR_G_GetCoordinateDimension(self);
+    *ppadfZ = (nCoordDimension == 3) ? (double*)VSIMalloc(sizeof(double) * nPoints) : NULL;
+    OGR_G_GetPoints(self,
+                    *ppadfXY, 2 * sizeof(double),
+                    (*ppadfXY) + 1, 2 * sizeof(double),
+                    *ppadfZ, sizeof(double));
+  }
+#endif
+#endif
+
 #ifndef SWIGJAVA
   %feature("kwargs") GetX;  
 #endif
@@ -1653,6 +1792,12 @@ public:
     return (OGRGeometryShadow*) OGR_G_Simplify(self, tolerance);
   }
 
+  /* OGR >= 1.9.0 */
+  %newobject SimplifyPreserveTopology;
+  OGRGeometryShadow* SimplifyPreserveTopology(double tolerance) {
+    return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
+  }
+
   %newobject Boundary;
   OGRGeometryShadow* Boundary() {
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
@@ -1819,10 +1964,18 @@ public:
   void GetEnvelope(OGREnvelope *env) {
     OGR_G_GetEnvelope(self, env);
   }
+
+  void GetEnvelope3D(OGREnvelope3D *env) {
+    OGR_G_GetEnvelope3D(self, env);
+  }
 #else
   void GetEnvelope(double argout[4]) {
     OGR_G_GetEnvelope(self, (OGREnvelope*)argout);
   }
+
+  void GetEnvelope3D(double argout[6]) {
+    OGR_G_GetEnvelope3D(self, (OGREnvelope3D*)argout);
+  }
 #endif  
 
 #ifndef SWIGJAVA
diff --git a/swig/include/osr.i b/swig/include/osr.i
index be75d07..572eeef 100644
--- a/swig/include/osr.i
+++ b/swig/include/osr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr.i 20889 2010-10-19 12:19:02Z dron $
+ * $Id: osr.i 22687 2011-07-10 21:59:49Z rouault $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  OGRSpatialReference related declarations.
@@ -227,6 +227,10 @@ public:
     return OSRIsSameGeogCS( self, rhs );
   }
 
+  int IsSameVertCS( OSRSpatialReferenceShadow *rhs ) {
+    return OSRIsSameVertCS( self, rhs );
+  }
+
   int IsGeographic() {
     return OSRIsGeographic(self);
   }
@@ -235,10 +239,22 @@ public:
     return OSRIsProjected(self);
   }
 
+  int IsCompound() {
+    return OSRIsCompound(self);
+  }
+
+  int IsGeocentric() {
+    return OSRIsGeocentric(self);
+  }
+
   int IsLocal() {
     return OSRIsLocal(self);
   }
 
+  int IsVertical() {
+    return OSRIsVertical(self);
+  }
+
   int EPSGTreatsAsLatLong() {
     return OSREPSGTreatsAsLatLong(self);
   }
@@ -278,6 +294,10 @@ public:
     return OSRGetAngularUnits( self, 0 );
   }
 
+  OGRErr SetTargetLinearUnits( const char *target, const char*name, double to_meters ) {
+    return OSRSetTargetLinearUnits( self, target, name, to_meters );
+  }
+
   OGRErr SetLinearUnits( const char*name, double to_meters ) {
     return OSRSetLinearUnits( self, name, to_meters );
   }
@@ -459,6 +479,10 @@ public:
               double fe, double fn ) {
     return OSRSetGH( self, cm, fe, fn );
   }
+
+  OGRErr SetIGH() {
+    return OSRSetIGH( self );
+  }
     
 %feature( "kwargs" ) SetGEOS;
   OGRErr SetGEOS( double cm, double satelliteheight,
@@ -707,6 +731,24 @@ public:
     return OSRSetProjCS( self, name );
   }
 
+  OGRErr SetGeocCS( const char *name = "unnamed" ) {
+    return OSRSetGeocCS( self, name );
+  }
+
+  OGRErr SetVertCS( const char *VertCSName = "unnamed",
+                    const char *VertDatumName = "unnamed",
+                    int VertDatumType = 0) {
+    return OSRSetVertCS( self, VertCSName, VertDatumName, VertDatumType );
+  }  
+
+%apply Pointer NONNULL {OSRSpatialReferenceShadow* horizcs};
+%apply Pointer NONNULL {OSRSpatialReferenceShadow* vertcs};  
+  OGRErr SetCompoundCS( const char *name,
+                        OSRSpatialReferenceShadow *horizcs,
+                        OSRSpatialReferenceShadow *vertcs ) {
+    return OSRSetCompoundCS( self, name, horizcs, vertcs );
+  }
+
 %apply (char **ignorechange) { (char **) };
   OGRErr ImportFromWkt( char **ppszInput ) {
     return OSRImportFromWkt( self, ppszInput );
@@ -716,10 +758,12 @@ public:
   OGRErr ImportFromProj4( char *ppszInput ) {
     return OSRImportFromProj4( self, ppszInput );
   }
-  
+
+%apply Pointer NONNULL {char* url};
   OGRErr ImportFromUrl( char *url ) {
     return OSRImportFromUrl( self, url );
   }
+
 %apply (char **options) { (char **) };
   OGRErr ImportFromESRI( char **ppszInput ) {
     return OSRImportFromESRI( self, ppszInput );
@@ -748,7 +792,9 @@ public:
   OGRErr ImportFromXML( char const *xmlString ) {
     return OSRImportFromXML( self, xmlString );
   }
-  
+
+%apply Pointer NONNULL {char const *proj};
+%apply Pointer NONNULL {char const *datum};
   OGRErr ImportFromERM( char const *proj, char const *datum,
                         char const *units ) {
     return OSRImportFromERM( self, proj, datum, units );
@@ -868,11 +914,15 @@ public:
 %apply (double argin[ANY]) {(double inout[3])};
 #endif
   void TransformPoint( double inout[3] ) {
+    if (self == NULL)
+        return;
     OCTTransform( self, 1, &inout[0], &inout[1], &inout[2] );
   }
 %clear (double inout[3]);
 
   void TransformPoint( double argout[3], double x, double y, double z = 0.0 ) {
+    if (self == NULL)
+        return;
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
@@ -883,6 +933,8 @@ public:
   %apply (double *inout) {(double*)};
 #endif
   void TransformPoints( int nCount, double *x, double *y, double *z ) {
+    if (self == NULL)
+        return;
     OCTTransform( self, nCount, x, y, z );
   }
 #ifdef SWIGCSHARP
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index 13a8da6..ab0a3b0 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -35,11 +35,13 @@
 %}
 
 %inline %{
+    #ifndef SWIG
     typedef struct
     {
 	SV *fct;
 	SV *data;
     } SavedEnv;
+    #endif
     int callback_d_cp_vp(double d, const char *cp, void *vp)
     {
 	int count, ret;
@@ -136,8 +138,12 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
     use Geo::GDAL::Const;
     use Geo::OGR;
     use Geo::OSR;
-    our $VERSION = '0.23';
-    our $GDAL_VERSION = '1.8.1';
+    # The three first numbers of the module version and the library
+    # version should match. GDAL version is available in runtime but
+    # it is needed here for the build time when it is compared against
+    # the version of GDAL against which we build.
+    our $VERSION = '1.90';
+    our $GDAL_VERSION = '1.9.0';
     use vars qw/
 	%TYPE_STRING2INT %TYPE_INT2STRING
 	%ACCESS_STRING2INT %ACCESS_INT2STRING
@@ -463,10 +469,12 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
     use UNIVERSAL qw(isa);
     use strict;
     use vars qw/
+        @COLOR_INTERPRETATIONS
 	%COLOR_INTERPRETATION_STRING2INT %COLOR_INTERPRETATION_INT2STRING @DOMAINS
 	/;
-    for my $string (qw/Undefined GrayIndex PaletteIndex RedBand GreenBand BlueBand AlphaBand 
-		    HueBand SaturationBand LightnessBand CyanBand MagentaBand YellowBand BlackBand/) {
+    @COLOR_INTERPRETATIONS = qw/Undefined GrayIndex PaletteIndex RedBand GreenBand BlueBand AlphaBand 
+		    HueBand SaturationBand LightnessBand CyanBand MagentaBand YellowBand BlackBand/;
+    for my $string (@COLOR_INTERPRETATIONS) {
 	my $int = eval "\$Geo::GDAL::Constc::GCI_$string";
 	$COLOR_INTERPRETATION_STRING2INT{$string} = $int;
 	$COLOR_INTERPRETATION_INT2STRING{$int} = $string;
@@ -507,6 +515,17 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 	SetNoDataValue($self, $_[0]) if @_ > 0;
 	GetNoDataValue($self);
     }
+    sub Unit {
+	my $self = shift;
+	SetUnitType($self, $_[0]) if @_ > 0;
+	GetUnitType($self);
+    }
+    sub ScaleAndOffset {
+	my $self = shift;
+	SetScale($self, $_[0]) if @_ > 0;
+	SetOffset($self, $_[1]) if @_ > 1;
+	(GetScale($self), GetOffset($self));
+    }
     sub ReadTile {
 	my($self, $xoff, $yoff, $xsize, $ysize) = @_;
 	$xoff = 0 unless defined $xoff;
@@ -589,10 +608,9 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 	    $params{$_} = $defaults{$_} unless defined $params{$_};
 	}
 	$params{ProgressData} = 1 if $params{Progress} and not defined $params{ProgressData};
-	my $h = _GetHistogram($self, $params{Min}, $params{Max}, $params{Buckets},
-			      $params{IncludeOutOfRange}, $params{ApproxOK},
-			      $params{Progress}, $params{ProgressData});
-	return @$h if $h;
+	_GetHistogram($self, $params{Min}, $params{Max}, $params{Buckets},
+		      $params{IncludeOutOfRange}, $params{ApproxOK},
+		      $params{Progress}, $params{ProgressData});
     }
     sub Contours {
 	my $self = shift;
@@ -644,6 +662,7 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
       $_[6] = undef unless defined $_[6];
       Geo::GDAL::FillNodata(@_);
     }
+    *GetBandNumber = *GetBand;
 
     package Geo::GDAL::ColorTable;
     use strict;
@@ -759,6 +778,13 @@ ALTERED_DESTROY(GDALRasterAttributeTableShadow, GDALc, delete_RasterAttributeTab
 	return unless defined wantarray;
 	GetValueAsString($self, $row, $column);
     }
+    sub LinearBinning {
+	my $self = shift;
+	SetLinearBinning($self, @_) if @_ > 0;
+	return unless defined wantarray;
+	my @a = GetLinearBinning($self);
+	return $a[0] ? ($a[1], $a[2]) : ();
+    }
 
  %}
 
diff --git a/swig/include/perl/ogr_perl.i b/swig/include/perl/ogr_perl.i
index dec0f69..547a7ae 100644
--- a/swig/include/perl/ogr_perl.i
+++ b/swig/include/perl/ogr_perl.i
@@ -64,6 +64,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 
   %rename (_UnsetField) UnsetField;
   %rename (_SetField) SetField;
+  %rename (_SetFrom) SetFrom;
 
 }
 
@@ -99,22 +100,18 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 %rename (_ExportToWkb) ExportToWkb;
 %rename (_GetDriver) GetDriver;
 %rename (_TestCapability) TestCapability;
-%rename (_GetName) GetName;
 
 %perlcode %{
     use strict;
     use Carp;
     {
         package Geo::OGR;
-	use vars qw /$name_encoding/;
-	$name_encoding = 'UTF-8';
     }
     {
         package Geo::OGR::Driver;
 	use strict;
 	use vars qw /@CAPABILITIES %CAPABILITIES/;
-	use Encode;
-        @CAPABILITIES = qw/CreateDataSource DeleteDataSource/; 
+	@CAPABILITIES = qw/CreateDataSource DeleteDataSource/; 
 	for my $s (@CAPABILITIES) {
 	    my $cap = eval "\$Geo::OGR::ODrC$s";
 	    $CAPABILITIES{$s} = $cap;
@@ -132,9 +129,6 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    my($self, $cap) = @_;
 	    return _TestCapability($self, $CAPABILITIES{$cap});
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	*Create = *CreateDataSource;
 	*Copy = *CopyDataSource;
 	*OpenDataSource = *Open;
@@ -144,8 +138,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	use Carp;
 	use strict;
 	use vars qw /@CAPABILITIES %CAPABILITIES %LAYERS/;
-	use Encode;
-        @CAPABILITIES = qw/CreateLayer DeleteLayer/;
+	@CAPABILITIES = qw/CreateLayer DeleteLayer/;
 	for my $s (@CAPABILITIES) {
 	    my $cap = eval "\$Geo::OGR::ODsC$s";
 	    $CAPABILITIES{$s} = $cap;
@@ -174,19 +167,16 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	sub OpenShared {
 	    return Geo::OGR::OpenShared(@_);
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	sub Layer {
 	    my($self, $name) = @_;
 	    my $layer;
 	    if (defined $name) {
 		$layer = _GetLayerByName($self, "$name");
+		$layer = _GetLayerByIndex($self, $name) unless $layer;
 	    } else {
-		$name = 0;
+		$layer = _GetLayerByIndex($self, 0);
 	    }
-	    $layer = _GetLayerByIndex($self, $name) if !$layer and $name =~ /^\d+$/;
-	    return unless $layer;
+	    croak "No such layer: $name\n" unless $layer;
 	    $LAYERS{tied(%$layer)} = $self;
 	    return $layer;
 	}
@@ -203,14 +193,14 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    my($self, $index) = @_;
 	    $index = 0 unless defined $index;
 	    my $layer = _GetLayerByIndex($self, $index+0);
-	    return unless $layer;
+	    croak "No such layer: $index\n" unless $layer;
 	    $LAYERS{tied(%$layer)} = $self;
 	    return $layer;
 	}
 	sub GetLayerByName {
 	    my($self, $name) = @_;
-	    my $layer = _GetLayerByName($self, $name);
-	    return unless $layer;
+	    my $layer = _GetLayerByName($self, "$name");
+	    croak "No such layer: $name\n" unless $layer;
 	    $LAYERS{tied(%$layer)} = $self;
 	    return $layer;
 	}
@@ -262,10 +252,11 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	package Geo::OGR::Layer;
 	use strict;
 	use vars qw /@CAPABILITIES %CAPABILITIES/;
-	use Encode;
-        @CAPABILITIES = qw/RandomRead SequentialWrite RandomWrite 
+	@CAPABILITIES = qw/RandomRead SequentialWrite RandomWrite 
 		   FastSpatialFilter FastFeatureCount FastGetExtent 
-		   CreateField Transactions DeleteFeature FastSetNextByIndex/;
+		   CreateField DeleteField ReorderFields AlterFieldDefn
+                   Transactions DeleteFeature FastSetNextByIndex
+                   StringsAsUTF8 IgnoreFields/;
 	for my $s (@CAPABILITIES) {
 	    my $cap = eval "\$Geo::OGR::OLC$s";
 	    $CAPABILITIES{$s} = $cap;
@@ -302,9 +293,6 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    my($self, $cap) = @_;
 	    return _TestCapability($self, $CAPABILITIES{$cap});
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	sub Schema {
 	    my $self = shift;
 	    if (@_) {
@@ -340,11 +328,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    for my $fn (keys %row) {
 		next if $fn eq 'FID';
 		next if $fn eq 'Geometry';
-		if (defined $row{$fn}) {
-		    $f->SetField($fn, $row{$fn});
-		} else {
-		    $f->UnsetField($fn);
-		}
+		$f->SetField($fn, $row{$fn});
 		$changed = 1;
 	    }
 	    $self->SetFeature($f) if $changed;
@@ -385,7 +369,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 		for my $field (@{$s->{Fields}}) {
 		    my $v = shift;
 		    my $n = $field->{Name};
-		    defined $v ? $f->SetField($n, $v) : $f->UnsetField($n);
+		    $f->SetField($n, $v);
 		}
 		$changed = 1;
 	    }
@@ -423,6 +407,10 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    }
 	    $self->CreateFeature($f);
 	}
+	sub GeometryType {
+	    my $self = shift;
+	    return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)};
+	}
 
 	package Geo::OGR::FeatureDefn;
 	use strict;
@@ -446,9 +434,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    }
 	    return $self;
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
+	*Name = *GetName;
 	sub Schema {
 	    my $self = shift;
 	    my %schema;
@@ -472,7 +458,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 		$s->{Index} = $i;
 		push @{$schema{Fields}}, $s;
 	    }
-	    return \%schema;
+	    return wantarray ? %schema : \%schema;
 	}
 	sub GeomType {
 	    my($self, $type) = @_;
@@ -484,11 +470,34 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)} if defined wantarray;
 	}
 	*GeometryType = *GeomType;
+	sub GeometryIgnored {
+	    my $self = shift;
+	    SetGeometryIgnored($self, $_[0]) if @_;
+	    IsGeometryIgnored($self) if defined wantarray;
+	}
+	sub StyleIgnored {
+	    my $self = shift;
+	    SetStyleIgnored($self, $_[0]) if @_;
+	    IsStyleIgnored($self) if defined wantarray;
+	}
 
 	package Geo::OGR::Feature;
 	use strict;
 	use vars qw /%GEOMETRIES/;
 	use Carp;
+	use Encode;
+	sub create {
+	    my $pkg = shift;
+	    $pkg->new(Geo::OGR::FeatureDefn->create(@_));
+	}
+	sub FETCH {
+	    my($self, $index) = @_;
+	    $self->GetField($index);
+	}
+	sub STORE {
+	    my $self = shift;
+	    $self->SetField(@_);
+	}
 	sub FID {
 	    my $self = shift;
 	    $self->SetFID($_[0]) if @_;
@@ -533,11 +542,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    for my $fn (keys %row) {
 		next if $fn eq 'FID';
 		next if $fn eq 'Geometry';
-		if (defined $row{$fn}) {
-		    $self->SetField($fn, $row{$fn});
-		} else {
-		    $self->UnsetField($fn);
-		}
+		$self->SetField($fn, $row{$fn});
 	    }
 	    return unless defined wantarray;
 	    %row = ();
@@ -573,7 +578,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 		for my $field (@{$s->{Fields}}) {
 		    my $v = shift;
 		    my $n = $field->{Name};
-		    defined $v ? $self->SetField($n, $v) : $self->UnsetField($n);
+		    $self->SetField($n, $v);
 		}
 	    }
 	    return unless defined wantarray;
@@ -590,13 +595,16 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	}
 	sub GetFieldType {
 	    my($self, $field) = @_;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    return $Geo::OGR::FieldDefn::TYPE_INT2STRING{_GetFieldType($self, $field)};
 	}
 	sub FieldIsList {
 	    my($self, $field) = @_;
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[1]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    my $type = _GetFieldType($self, $field);
 	    return 1 if ($type == $Geo::OGR::OFTIntegerList or
 			 $type == $Geo::OGR::OFTRealList or
@@ -608,9 +616,9 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	}
 	sub GetField {
 	    my($self, $field) = @_;
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[1]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    return undef unless IsFieldSet($self, $field);
 	    my $type = _GetFieldType($self, $field);
 	    if ($type == $Geo::OGR::OFTInteger) {
@@ -624,15 +632,15 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    }
 	    if ($type == $Geo::OGR::OFTIntegerList) {
 		my $ret = GetFieldAsIntegerList($self, $field);
-		return @$ret;
+		return wantarray ? @$ret : $ret;
 	    } 
 	    if ($type == $Geo::OGR::OFTRealList) {
 		my $ret = GetFieldAsDoubleList($self, $field);
-		return @$ret;
+		return wantarray ? @$ret : $ret;
 	    }
 	    if ($type == $Geo::OGR::OFTStringList) {
 		my $ret = GetFieldAsStringList($self, $field);
-		return @$ret;
+		return wantarray ? @$ret : $ret;
 	    }
 	    if ($type == $Geo::OGR::OFTBinary) {
 		return GetFieldAsString($self, $field);
@@ -640,11 +648,11 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    if ($type == $Geo::OGR::OFTDate) {
 		my @ret = GetFieldAsDateTime($self, $field);
 		# year, month, day, hour, minute, second, timezone
-		return @ret[0..2];
+		return wantarray ? @ret[0..2] : [@ret[0..2]];
 	    }
 	    if ($type == $Geo::OGR::OFTTime) {
 		my @ret = GetFieldAsDateTime($self, $field);
-		return @ret[3..6];
+		return wantarray ? @ret[3..6] : [@ret[3..6]];
 	    }
 	    if ($type == $Geo::OGR::OFTDateTime) {
 		return GetFieldAsDateTime($self, $field);
@@ -653,18 +661,17 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	}
 	sub UnsetField {
 	    my($self, $field) = @_;
-	    my $type = _GetFieldType($self, $field);
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[1]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    _UnsetField($self, $field);
 	}
 	sub SetField {
 	    my $self = shift;
 	    my $field = $_[0];
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[0]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    shift;
 	    if (@_ == 0 or !defined($_[0])) {
 		_UnsetField($self, $field);
@@ -672,10 +679,10 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    }
 	    my $list = ref($_[0]) ? $_[0] : [@_];
 	    my $type = _GetFieldType($self, $field);
-	    if ($type == $Geo::OGR::OFTInteger or 
-		$type == $Geo::OGR::OFTReal or 
+	    if ($type == $Geo::OGR::OFTInteger or
+		$type == $Geo::OGR::OFTReal or
 		$type == $Geo::OGR::OFTString or
-		$type == $Geo::OGR::OFTBinary) 
+		$type == $Geo::OGR::OFTBinary)
 	    {
 		_SetField($self, $field, $_[0]);
 	    } 
@@ -704,7 +711,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 		_SetField($self, $field, @$list[0..6]);
 	    } 
 	    else {
-		carp "unknown/unsupported field type: $type";
+		carp "unknown or unsupported field type: $type";
 	    }
 	}
 	sub Field {
@@ -729,6 +736,26 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    $GEOMETRIES{tied(%$geom)} = $self if $geom;
 	    return $geom;
 	}
+	sub ReferenceGeometry {
+	    my $self = shift;
+	    SetGeometryDirectly($self, $_[0]) if @_;
+	    if (defined wantarray) {
+		my $geometry = GetGeometry($self);
+		return $geometry->Clone() if $geometry;
+	    }
+	}
+	sub SetFrom {
+	    my($self, $other) = @_;
+	    _SetFrom($self, $other), return if @_ <= 2;
+	    my $forgiving = $_[2];
+	    _SetFrom($self, $other, $forgiving), return if @_ <= 3;	    
+	    my $map = $_[3];
+	    my @list;
+	    for my $i (1..GetFieldCount($self)) {
+		push @list, ($map->{$i} || -1);
+	    }
+	    SetFromWithMap($self, $other, 1, \@list);
+	}
 
 	package Geo::OGR::FieldDefn;
 	use strict;
@@ -782,9 +809,6 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    }
 	    return $self;
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	sub Name {
 	    my $self = shift;
 	    SetName($self, $_[0]) if @_;
@@ -816,6 +840,11 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    SetPrecision($self, $_[0]) if @_;
 	    GetPrecision($self) if defined wantarray;
 	}
+	sub Ignored {
+	    my $self = shift;
+	    SetIgnored($self, $_[0]) if @_;
+	    IsIgnored($self) if defined wantarray;
+	}
 	sub Schema {
 	    my $self = shift;
 	    if (@_) {
@@ -827,11 +856,12 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 		$self->Precision($param{Precision}) if exists $param{Precision};
 	    }
 	    return unless defined wantarray;
-	    return { Name => $self->Name, 
-		     Type  => $self->Type,
-		     Justify  => $self->Justify,
-		     Width  => $self->Width,
-		     Precision => $self->Precision };
+	    my %schema = ( Name => $self->Name, 
+			   Type  => $self->Type,
+			   Justify  => $self->Justify,
+			   Width  => $self->Width,
+			   Precision => $self->Precision );
+	    return wantarray ? %schema : \%schema;
 	}
 
 	package Geo::OGR::Geometry;
@@ -999,7 +1029,16 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 		if ($t eq 'Unknown' or $t eq 'None' or $t eq 'GeometryCollection') {
 		    croak("Can't set points of a geometry of type: $t");
 		} elsif ($t eq 'Point') {
-		    $flat ? AddPoint_2D($self, @$points[0..1]) : AddPoint_3D($self, @$points[0..2]);
+		    # support both "Point" as a list of one point and one point
+		    if (ref($points->[0])) {
+			$flat ? 
+			    AddPoint_2D($self, @{$points->[0]}[0..1]) : 
+			    AddPoint_3D($self, @{$points->[0]}[0..2]);
+		    } else {
+			$flat ? 
+			    AddPoint_2D($self, @$points[0..1]) : 
+			    AddPoint_3D($self, @$points[0..2]);
+		    }
 		} elsif ($t eq 'LineString' or $t eq 'LinearRing') {
 		    if ($flat) {
 			for my $p (@$points) {
@@ -1051,16 +1090,16 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	    } else {
 		$n = $self->GetPointCount;
 		if ($n == 1) {
-		    push @points, $flat ? GetPoint_2D($self) : GetPoint_3D($self);
+		    push @points, $flat ? scalar GetPoint_2D($self) : scalar GetPoint_3D($self);
 		} else {
 		    my $i;
 		    if ($flat) {
 			for my $i (0..$n-1) {
-			    push @points, GetPoint_2D($self, $i);
+			    push @points, scalar GetPoint_2D($self, $i);
 			}
 		    } else {
 			for my $i (0..$n-1) {
-			    push @points, GetPoint_3D($self, $i);
+			    push @points, scalar GetPoint_3D($self, $i);
 			}
 		    }
 		}
@@ -1121,6 +1160,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	*AsBinary = *ExportToWkb;
 	*AsGML = *ExportToGML;
 	*AsKML = *ExportToKML;
+	*AsJSON = *ExportToJson;
 	*BuildPolygonFromEdges = *Geo::OGR::BuildPolygonFromEdges;
 	*ForceToPolygon = *Geo::OGR::ForceToPolygon;
 	
@@ -1150,9 +1190,11 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 	return @drivers;
     }
     sub GetDriver {
-	my($name_or_number) = @_;
-	return _GetDriver($name_or_number) if $name_or_number =~ /^\d/;
-	return GetDriverByName("$name_or_number");
+	my($name) = @_;
+	my $driver = GetDriverByName("$name");
+	$driver = _GetDriver($name) unless $driver;
+	croak "No such OGR driver: $name\n" unless $driver;
+	return $driver;
     }
     *Driver = *GetDriver;
 %}
diff --git a/swig/include/perl/osr_perl.i b/swig/include/perl/osr_perl.i
index 5f3df9c..6c1cdaf 100644
--- a/swig/include/perl/osr_perl.i
+++ b/swig/include/perl/osr_perl.i
@@ -2,12 +2,114 @@
 %import typemaps_perl.i
 
 %rename (_TransformPoints) TransformPoints;
+%rename (_GetUTMZone) GetUTMZone;
 
 %perlcode %{
     sub RELEASE_PARENTS {
     }
     package Geo::OSR::SpatialReference;
     use strict;
+    use Carp;
+    use vars qw /@PROJECTIONS %PROJECTIONS @PARAMETERS %PARAMETERS/;
+    @PROJECTIONS = qw/
+ALBERS_CONIC_EQUAL_AREA
+AZIMUTHAL_EQUIDISTANT
+CASSINI_SOLDNER
+CYLINDRICAL_EQUAL_AREA
+BONNE
+ECKERT_I
+ECKERT_II
+ECKERT_III
+ECKERT_IV
+ECKERT_V
+ECKERT_VI
+EQUIDISTANT_CONIC
+EQUIRECTANGULAR
+GALL_STEREOGRAPHIC
+GAUSSSCHREIBERTMERCATOR
+GEOSTATIONARY_SATELLITE
+GOODE_HOMOLOSINE
+IGH
+GNOMONIC
+HOTINE_OBLIQUE_MERCATOR
+HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN
+LABORDE_OBLIQUE_MERCATOR
+LAMBERT_CONFORMAL_CONIC_1SP
+LAMBERT_CONFORMAL_CONIC_2SP
+LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM
+LAMBERT_AZIMUTHAL_EQUAL_AREA
+MERCATOR_1SP
+MERCATOR_2SP
+MILLER_CYLINDRICAL
+MOLLWEIDE
+NEW_ZEALAND_MAP_GRID
+OBLIQUE_STEREOGRAPHIC
+ORTHOGRAPHIC
+POLAR_STEREOGRAPHIC
+POLYCONIC
+ROBINSON
+SINUSOIDAL
+STEREOGRAPHIC
+SWISS_OBLIQUE_CYLINDRICAL
+TRANSVERSE_MERCATOR
+TRANSVERSE_MERCATOR_SOUTH_ORIENTED
+TRANSVERSE_MERCATOR_MI_21
+TRANSVERSE_MERCATOR_MI_22
+TRANSVERSE_MERCATOR_MI_23
+TRANSVERSE_MERCATOR_MI_24
+TRANSVERSE_MERCATOR_MI_25
+TUNISIA_MINING_GRID
+TWO_POINT_EQUIDISTANT
+VANDERGRINTEN
+KROVAK
+IMW_POLYCONIC
+WAGNER_I
+WAGNER_II
+WAGNER_III
+WAGNER_IV
+WAGNER_V
+WAGNER_VI
+WAGNER_VII
+/;
+    for my $s (@PROJECTIONS) {
+	my $p = eval "\$Geo::OGR::SRS_PT_$s";
+	$PROJECTIONS{$s} = $p;
+    }
+    @PARAMETERS = qw/
+CENTRAL_MERIDIAN
+SCALE_FACTOR
+STANDARD_PARALLEL_1
+STANDARD_PARALLEL_2
+PSEUDO_STD_PARALLEL_1
+LONGITUDE_OF_CENTER
+LATITUDE_OF_CENTER
+LONGITUDE_OF_ORIGIN
+LATITUDE_OF_ORIGIN
+FALSE_EASTING
+FALSE_NORTHING
+AZIMUTH
+LONGITUDE_OF_POINT_1
+LATITUDE_OF_POINT_1
+LONGITUDE_OF_POINT_2
+LATITUDE_OF_POINT_2
+LONGITUDE_OF_POINT_3
+LATITUDE_OF_POINT_3
+RECTIFIED_GRID_ANGLE
+LANDSAT_NUMBER
+PATH_NUMBER
+PERSPECTIVE_POINT_HEIGHT
+SATELLITE_HEIGHT
+FIPSZONE
+ZONE
+LATITUDE_OF_1ST_POINT
+LONGITUDE_OF_1ST_POINT
+LATITUDE_OF_2ND_POINT
+LONGITUDE_OF_2ND_POINT
+/;
+    for my $s (@PARAMETERS) {
+	my $p = eval "\$Geo::OGR::SRS_PP_$s";
+	$PARAMETERS{$s} = $p;
+    }
     sub create {
 	my $pkg = shift;
 	my %param = @_;
@@ -19,19 +121,213 @@
 	} elsif ($param{Proj4}) {
 	    ImportFromProj4($self, $param{Proj4});
 	} elsif ($param{ESRI}) {
-	    ImportFromESRI($self, $param{ESRI});
+	    ImportFromESRI($self, @{$param{ESRI}});
 	} elsif ($param{EPSG}) {
 	    ImportFromEPSG($self, $param{EPSG});
+	} elsif ($param{EPSGA}) {
+	    ImportFromEPSGA($self, $param{EPSGA});
 	} elsif ($param{PCI}) {
-	    ImportFromPCI($self, $param{PCI});
+	    ImportFromPCI($self, @{$param{PCI}});
 	} elsif ($param{USGS}) {
-	    ImportFromUSGS($self, $param{USGS});
+	    ImportFromUSGS($self, @{$param{USGS}});
 	} elsif ($param{XML}) {
 	    ImportFromXML($self, $param{XML});
+	} elsif ($param{GML}) {
+	    ImportFromGML($self, $param{GML});
+	} elsif ($param{URL}) {
+	    ImportFromUrl($self, $param{URL});
+	} elsif ($param{ERMapper}) {
+	    ImportFromERM($self, @{$param{ERMapper}} );
+	} elsif ($param{ERM}) {
+	    ImportFromERM($self, @{$param{ERM}} );
+	} elsif ($param{MICoordSys}) {
+	    ImportFromMICoordSys($self, $param{MICoordSys} );
+	} elsif ($param{MapInfoCS}) {
+	    ImportFromMICoordSys($self, $param{MapInfoCS} );
+	} else {
+	    croak "Unrecognized import format for Geo::OSR::SpatialReference.";
 	}
 	bless $self, $pkg if defined $self;
     }
+    sub Export {
+	my $self = shift;
+	my $format = pop if @_ == 1;
+	my %params = @_;
+	$format = $params{to} unless $format;
+	$format = $params{format} unless $format;
+	$format = $params{as} unless $format;
+	if ($format eq 'WKT' or $format eq 'Text') {
+	    return ExportToWkt($self);
+	} elsif ($format eq 'PrettyWKT') {
+	    my $simplify = exists $params{simplify} ? $params{simplify} : 0;
+	    return ExportToPrettyWkt($self, $simplify);
+	} elsif ($format eq 'Proj4') {
+	    return ExportToProj4($self);
+	} elsif ($format eq 'PCI') {	    
+	    return ExportToPCI($self);
+	} elsif ($format eq 'USGS') {
+	    return ExportToUSGS($self);
+	} elsif ($format eq 'GML' or $format eq 'XML') {
+	    my $dialect = exists $params{dialect} ? $params{dialect} : '';
+	    return ExportToXML($self, $dialect);
+	} elsif ($format eq 'MICoordSys' or $format eq 'MapInfoCS') {
+	    return ExportToMICoordSys();
+	} else {
+	    croak "Unrecognized export format for Geo::OSR::SpatialReference.";
+	}
+    }
     *AsText = *ExportToWkt;
+    *As = *Export;
+    sub Set {
+	my($self, %params) = @_;
+	if (exists $params{Authority} and exists $params{Node} and exists $params{Code}) {
+	    SetAuthority($self, $params{TargetKey}, $params{Authority}, $params{Code});
+	} elsif (exists $params{Node} and exists $params{Value}) {
+	    SetAttrValue($self, $params{Node}, $params{Value});
+	} elsif (exists $params{AngularUnits} and exists $params{Value}) {
+	    SetAngularUnits($self, $params{AngularUnits}, $params{Value});
+	} elsif (exists $params{LinearUnits} and exists $params{Node} and exists $params{Value}) {
+	    SetTargetLinearUnits($self, $params{Node}, $params{LinearUnits}, $params{Value});
+	} elsif (exists $params{LinearUnits} and exists $params{Value}) {
+	    SetLinearUnitsAndUpdateParameters($self, $params{LinearUnits}, $params{Value});
+	} elsif ($params{CoordinateSystem} eq 'UTM' and exists $params{Zone} and exists $params{North}) {
+	    my $north = exists $params{North} ? $params{North} : 1;
+	    SetUTM($self, $params{Zone}, $north);
+	} elsif ($params{CoordinateSystem} eq 'State Plane' and exists $params{Zone}) {
+	    my $NAD83 = exists $params{NAD83} ? $params{NAD83} : 1;
+	    my $name = exists $params{UnitName} ? $params{UnitName} : undef;
+	    my $c = exists $params{UnitConversionFactor} ? $params{UnitConversionFactor} : 0.0;
+	    SetStatePlane($self, $params{Zone}, $NAD83, $name, $c);
+	} elsif ($params{Parameter} and exists $params{Value}) {
+	    croak "unknown parameter: $params{Parameter}" unless exists $PARAMETERS{$params{Parameter}};
+	    $params{Normalized} ?
+		SetNormProjParm($self, $params{Parameter}, $params{Value}) :
+		SetProjParm($self, $params{Parameter}, $params{Value});
+	} elsif ($params{Projection}) {
+	    croak "unknown projection: $params{Projection}" unless exists $PROJECTIONS{$params{Projection}};
+	    if (not $params{Parameters}) {
+		SetProjection($self, $PROJECTIONS{$params{Projection}});
+	    } elsif ($params{Projection} eq 'ALBERS_CONIC_EQUAL_AREA' and $params{Parameters}) {
+		SetACEA($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'AZIMUTHAL_EQUIDISTANT' and $params{Parameters}) {
+		SetAE($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'BONNE' and $params{Parameters}) {
+		SetBonne($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'CYLINDRICAL_EQUAL_AREA' and $params{Parameters}) {
+		SetCEA($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'CASSINI_SOLDNER' and $params{Parameters}) {
+		SetCS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'EQUIDISTANT_CONIC' and $params{Parameters}) {
+		SetEC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ECKERT_IV' and $params{Parameters}) {
+		SetEckertIV($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ECKERT_VI' and $params{Parameters}) {
+		SetEckertVI($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'EQUIRECTANGULAR' and $params{Parameters}) {
+		@{$params{Parameters}} == 4 ?
+		    SetEquirectangular($self, @{$params{Parameters}}) :
+		    SetEquirectangular2($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GAUSSSCHREIBERTMERCATOR' and $params{Parameters}) {
+		SetGaussSchreiberTMercator($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GALL_STEREOGRAPHIC' and $params{Parameters}) {
+		SetGS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GOODE_HOMOLOSINE' and $params{Parameters}) {
+		SetGH($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'IGH') {
+		SetIGH($self);
+	    } elsif ($params{Projection} eq 'GEOSTATIONARY_SATELLITE' and $params{Parameters}) {
+		SetGEOS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GNOMONIC' and $params{Parameters}) {
+		SetGnomonic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'HOTINE_OBLIQUE_MERCATOR' and $params{Parameters}) {
+		SetHOM($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN' and $params{Parameters}) {
+		SetHOM2PNO($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'KROVAK' and $params{Parameters}) {
+		SetKrovak($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_AZIMUTHAL_EQUAL_AREA' and $params{Parameters}) {
+		SetLAEA($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_CONFORMAL_CONIC_2SP' and $params{Parameters}) {
+		SetLCC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_CONFORMAL_CONIC_1SP' and $params{Parameters}) {
+		SetLCC1SP($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM' and $params{Parameters}) {
+		SetLCCB($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'MILLER_CYLINDRICAL' and $params{Parameters}) {
+		SetMC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} =~ /^MERCATOR/ and $params{Parameters}) {
+		SetMercator($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'MOLLWEIDE' and $params{Parameters}) {
+		SetMollweide($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'NEW_ZEALAND_MAP_GRID' and $params{Parameters}) {
+		SetNZMG($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'OBLIQUE_STEREOGRAPHIC' and $params{Parameters}) {
+		SetOS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ORTHOGRAPHIC' and $params{Parameters}) {
+		SetOrthographic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'POLYCONIC' and $params{Parameters}) {
+		SetPolyconic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'POLAR_STEREOGRAPHIC' and $params{Parameters}) {
+		SetPS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ROBINSON' and $params{Parameters}) {
+		SetRobinson($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'SINUSOIDAL' and $params{Parameters}) {
+		SetSinusoidal($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'STEREOGRAPHIC' and $params{Parameters}) {
+		SetStereographic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'SWISS_OBLIQUE_CYLINDRICAL' and $params{Parameters}) {
+		SetSOC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'TRANSVERSE_MERCATOR_SOUTH_ORIENTED' and $params{Parameters}) {
+		SetTMSO($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} =~ /^TRANSVERSE_MERCATOR/ and $params{Parameters}) {
+		my($variant) = $params{Projection} =~ /^TRANSVERSE_MERCATOR_(\w+)/;
+		$variant = $params{Name} unless $variant;
+		$variant ?
+		    SetTMVariant($self, $variant, @{$params{Parameters}}) :
+		    SetTM($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'TUNISIA_MINING_GRID' and $params{Parameters}) {
+		SetTMG($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'VANDERGRINTEN' and $params{Parameters}) {
+		SetVDG($self, @{$params{Parameters}});
+	    } elsif ($params{Name}) {
+		SetWellKnownGeogCS($self, $params{Name});
+	    } elsif ($params{GuessFrom}) {
+		SetFromUserInput($self, $params{GuessFrom});
+	    } elsif ($params{CoordinateSystem} eq 'WGS' and $params{Parameters}) {
+		SetTOWGS84($self, @{$params{Parameters}});
+	    } elsif ($params{LOCAL_CS}) {
+		SetLocalCS($self, $params{LOCAL_CS});
+	    } elsif ($params{CoordinateSystem} and $params{Datum} and $params{Spheroid} and $params{Parameters}) {
+		SetGeogCS($self, $params{CoordinateSystem}, $params{Datum}, $params{Spheroid}, @{$params{Parameters}});
+	    } elsif ($params{CoordinateSystem}) {
+		SetProjCS($self, $params{CoordinateSystem});
+	    } elsif ($params{GeocentricCS}) {
+		SetGeocCS($self, $params{GeocentricCS});
+	    } elsif ($params{VerticalCS} and $params{Datum}) {
+		my $type = $params{VertDatumType} || 2005;
+		SetVertCS($self, $params{VerticalCS}, $params{Datum}, $type);
+	    } elsif ($params{CoordinateSystem} and $params{HorizontalCS} and $params{VerticalCS}) {
+		SetCompoundCS($self, $params{CoordinateSystem}, $params{HorizontalCS}, $params{VerticalCS});
+	    } else {
+		croak "Not enough information to set anything in a spatial reference object.";
+	    }
+	}
+    }
+    sub GetUTMZone {
+	my $self = shift;
+	my $zone = _GetUTMZone($self);
+	if (wantarray) {	    
+	    my $north = 1;
+	    if ($zone < 0) {
+		$zone *= -1;
+		$north = 0;
+	    }
+	    return ($zone, $north);
+	} else {
+	    return $zone;
+	}
+    }
+
     package Geo::OSR::CoordinateTransformation;
     use strict;
     sub TransformPoints {
diff --git a/swig/include/perl/typemaps_perl.i b/swig/include/perl/typemaps_perl.i
index aeed523..c2d97af 100644
--- a/swig/include/perl/typemaps_perl.i
+++ b/swig/include/perl/typemaps_perl.i
@@ -41,6 +41,14 @@
   sv_setiv($result, (IV) $1);
   argvi++;
 }
+%typemap(out) const char *
+{
+    /* %typemap(out) const char * */
+    $result = newSVpv(result, 0);
+    SvUTF8_on($result); /* expecting GDAL to give us UTF-8 */
+    sv_2mortal($result);
+    argvi++;
+}
 %typemap(out) (char **CSL)
 {
     /* %typemap(out) char **CSL */
@@ -48,9 +56,10 @@
 	if ($1) {
 	    int i;
 	    for (i = 0; $1[i]; i++) {
-		if (i>items-1) EXTEND(SP, 1);
-		ST(argvi) = sv_2mortal(newSVpv($1[i], 0));
-		argvi++;
+		if (argvi > items-1) EXTEND(SP, 1);
+		SV *sv = newSVpv($1[i], 0);
+		SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
+		ST(argvi++) = sv_2mortal(sv);
 	    }
 	    CSLDestroy($1);
 	}
@@ -59,9 +68,10 @@
 	if ($1) {
 	    int i;
 	    for (i = 0; $1[i]; i++) {
-		SV *s = newSVpv($1[i], 0);
-		if (!av_store(av, i, s))
-		    SvREFCNT_dec(s);
+	      SV *sv = newSVpv($1[i], 0);
+	      SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
+	      if (!av_store(av, i, sv))
+		SvREFCNT_dec(sv);
 	    }
 	    CSLDestroy($1);
 	}
@@ -76,9 +86,10 @@
   if ($1) {
     int i;
     for (i = 0; $1[i]; i++) {
-      SV *s = newSVpv($1[i], 0);
-      if (!av_store(av, i, s))
-	SvREFCNT_dec(s);
+      SV *sv = newSVpv($1[i], 0);
+      SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
+      if (!av_store(av, i, sv))
+	SvREFCNT_dec(sv);
     }
     CSLDestroy($1);
   }
@@ -198,7 +209,9 @@ static SV *
 CreateArrayFromStringArray( char **first ) {
   AV *av = (AV*)sv_2mortal((SV*)newAV());
   for( unsigned int i = 0; *first != NULL; i++ ) {
-    av_store(av,i,newSVpv(*first, strlen(*first)));
+    SV *sv = newSVpv(*first, strlen(*first));
+    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+    av_store(av,i,sv);
     ++first;
   }
   return newRV_noinc((SV*)av);
@@ -233,8 +246,16 @@ CreateArrayFromStringArray( char **first ) {
 %typemap(argout,fragment="CreateArrayFromIntArray") (int len, int *output)
 {
   /* %typemap(argout) (int len, int *output) */
-  $result = CreateArrayFromIntArray( $2, $1 );
-  argvi++;
+  if (GIMME_V == G_ARRAY) {
+    /* return a list */
+    int i;
+    EXTEND(SP, argvi+$1-items+1);
+    for (i = 0; i < $1; i++)
+      ST(argvi++) = sv_2mortal(newSVnv($2[i]));
+  } else {
+    $result = CreateArrayFromIntArray( $2, $1 );
+    argvi++;
+  }
 }
 %typemap(freearg) (int len, int *output)
 {
@@ -275,8 +296,16 @@ CreateArrayFromStringArray( char **first ) {
 %typemap(argout,fragment="CreateArrayFromDoubleArray") ( double argout[ANY])
 {
   /* %typemap(argout) (double argout[ANY]) */
-  $result = CreateArrayFromDoubleArray( $1, $dim0 );
-  argvi++;
+  if (GIMME_V == G_ARRAY) {
+    /* return a list */
+    int i;
+    EXTEND(SP, argvi+$dim0-items+1);
+    for (i = 0; i < $dim0; i++)
+      ST(argvi++) = sv_2mortal(newSVnv($1[i]));
+  } else {
+    $result = CreateArrayFromDoubleArray( $1, $dim0 );
+    argvi++;
+  }  
 }
 
 %typemap(in,numinputs=0) ( double *argout[ANY]) (double *argout)
@@ -358,7 +387,9 @@ CreateArrayFromStringArray( char **first ) {
 	SWIG_croak("expected a reference to an array");
     AV *av = (AV*)(SvRV($input));
     for (int i = 0; i < av_len(av)+1; i++) {
-	char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+	SV *sv = *(av_fetch(av, i, 0));
+	sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+	char *pszItem = SvPV_nolen(sv);
 	$1 = CSLAddString( $1, pszItem );
     }
 }
@@ -637,7 +668,9 @@ CreateArrayFromStringArray( char **first ) {
 	    if (SvTYPE(SvRV($input))==SVt_PVAV) {
 		AV *av = (AV*)(SvRV($input));
 		for (int i = 0; i < av_len(av)+1; i++) {
-		    char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+		    SV *sv = *(av_fetch(av, i, 0));
+		    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+		    char *pszItem = SvPV_nolen(sv);
 		    $1 = CSLAddString( $1, pszItem );
 		}
 	    } else if (SvTYPE(SvRV($input))==SVt_PVHV) {
@@ -648,6 +681,7 @@ CreateArrayFromStringArray( char **first ) {
 		$1 = NULL;
 		hv_iterinit(hv);
 		while(sv = hv_iternextsv(hv,&key,&klen)) {
+		    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
                     $1 = CSLAddNameValue( $1, key, SvPV_nolen(sv) );
 		}
 	    } else
@@ -669,9 +703,10 @@ CreateArrayFromStringArray( char **first ) {
     if ( stringarray != NULL ) {
 	int n = CSLCount( stringarray );
 	for ( int i = 0; i < n; i++ ) {
-	    SV *s = newSVpv(stringarray[i], 0);
-	    if (!av_store(av, i, s))
-		SvREFCNT_dec(s);
+	    SV *sv = newSVpv(stringarray[i], 0);
+	    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+	    if (!av_store(av, i, sv))
+		SvREFCNT_dec(sv);
 	}
     }
     $result = newRV_noinc((SV*)av);
@@ -684,9 +719,10 @@ CreateArrayFromStringArray( char **first ) {
  */
 %typemap(in) (char **ignorechange) ( char *val )
 {
-  /* %typemap(in) (char **ignorechange) */
-  val = SvPV_nolen($input);
-  $1 = &val;
+    /* %typemap(in) (char **ignorechange) */
+    sv_utf8_upgrade($input); /* GDAL expects UTF-8 */
+    val = SvPV_nolen($input);
+    $1 = &val;
 }
 
 /*
@@ -701,8 +737,10 @@ CreateArrayFromStringArray( char **first ) {
 {
   /* %typemap(argout) (char **argout) */
   $result = sv_newmortal();
-  if ( $1 )
+  if ( $1 ) {
     sv_setpv($result, *$1);
+    SvUTF8_on($result); /* expecting UTF-8 from GDAL */
+  }
   argvi++;
 }
 %typemap(freearg) (char **argout)
@@ -739,6 +777,7 @@ CreateArrayFromStringArray( char **first ) {
 %typemap(in) (tostring argin)
 {
   /* %typemap(in) (tostring argin) */
+  sv_utf8_upgrade($input); /* GDAL expects UTF-8 */
   $1 = SvPV_nolen( $input ); 
 }
 %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin)
@@ -794,7 +833,9 @@ static CPLXMLNode *AVToXMLTree( AV *av )
 	return NULL;
 
     nType = SvIV(*(av_fetch(av,0,0)));
-    pszText = SvPV_nolen(*(av_fetch(av,1,0)));
+    SV *sv = *(av_fetch(av,1,0));
+    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+    pszText = SvPV_nolen(sv);
     psThisNode = CPLCreateXMLNode( NULL, (CPLXMLNodeType) nType, pszText );
     
     for( iChild = 0; iChild < nChildCount; iChild++ )
@@ -851,8 +892,10 @@ static AV *XMLTreeToAV( CPLXMLNode *psTree )
     av = (AV*)sv_2mortal((SV*)newAV());
 
     av_store(av,0,newSViv((int) psTree->eType));
-    av_store(av,1,newSVpv(psTree->pszValue, strlen(psTree->pszValue)));
-
+    SV *sv = newSVpv(psTree->pszValue, strlen(psTree->pszValue));
+    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+    av_store(av,1,sv);
+    
     for( psChild = psTree->psChild, iChild = 2; 
          psChild != NULL; 
          psChild = psChild->psNext, iChild++ )
@@ -968,7 +1011,8 @@ CHECK_NOT_UNDEF(OGRFeatureShadow, feature, feature)
 {
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    $1 = (void *)(&saved_env);
 }
 
 %typemap(in) (GDALProgressFunc callback = NULL)
@@ -993,8 +1037,6 @@ CHECK_NOT_UNDEF(OGRFeatureShadow, feature, feature)
     /* %typemap(in) (void* callback_data=NULL) */
     if (SvOK($input))
 	saved_env.data = (SV *)$input;
-    if (saved_env.fct)
-	$1 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
 }
 
 /*
@@ -1026,3 +1068,72 @@ CHECK_NOT_UNDEF(OGRFeatureShadow, feature, feature)
   PUSHs(sv_2mortal(newSVuv(sStatBuf2.st_size)));
   argvi++;
 }
+
+/*
+ * Typemaps for VSIFReadL
+ */
+%typemap(in,numinputs=1) (void *pBuffer, size_t nSize, size_t nCount)
+{
+  /* %typemap(in,numinputs=1) (void *pBuffer, size_t nSize, size_t nCount) */
+  size_t len = SvIV($input);
+  $1 = malloc(len);
+  $2 = 1;
+  $3 = len;
+}
+%typemap(argout) (void *pBuffer, size_t nSize, size_t nCount)
+{
+  /* %typemap(argout) (void *pBuffer, size_t nSize, size_t nCount) */
+  if (result) {
+    $result = newSVpvn((char*)$1, result);
+    sv_2mortal($result);
+  } else {
+    $result = &PL_sv_undef;
+  }
+  argvi++;
+}
+%typemap(out) (size_t VSIFReadL)
+{
+  /* %typemap(out) (size_t VSIFReadL) */
+}
+
+/*
+ * Typemaps for VSIFWriteL
+ */
+%typemap(in,numinputs=1) (const void *pBuffer, size_t nSize, size_t nCount)
+{
+  /* %typemap(in,numinputs=1) (const void *pBuffer, size_t nSize, size_t nCount) */
+  size_t len;
+  $1 = SvPV($input, len);
+  $2 = 1;
+  $3 = len;
+}
+
+/*
+ * Typemaps for ensuring UTF-8 is given to GDAL if requested impacts:
+ * (ogr:) Driver_CreateDataSource, Driver_CopyDataSource, Driver_Open,
+ * Driver_DeleteDataSource Open, OpenShared,
+ * DataSource__GetLayerByName, DataSource__CreateLayer,
+ * Feature_GetFieldDefnRef__SWIG_1, Feature_IsFieldSet__SWIG_1,
+ * Feature_GetFieldIndex (gdal:) PushFinderLocation, FindFile,
+ * ReadDir, FileFromMemBuffer, Unlink, MkDir, RmDir, Stat VSIFOpenL,
+ * Driver__Create, Driver_CreateCopy, Driver_Delete, Open__SWIG_1,
+ * OpenShared__SWIG_1, IdentifyDriver
+ */
+%typemap(in,numinputs=1) (const char* utf8_path)
+{
+  /* %typemap(in,numinputs=1) (const char* utf8_path) */
+  sv_utf8_upgrade($input);
+  $1 = SvPV_nolen($input);
+}
+%typemap(in,numinputs=1) (const char* layer_name)
+{
+  /* %typemap(in,numinputs=1) (const char* layer_name) */
+  sv_utf8_upgrade($input);
+  $1 = SvPV_nolen($input);
+}
+%typemap(in,numinputs=1) (const char* name)
+{
+  /* %typemap(in,numinputs=1) (const char* name) */
+  sv_utf8_upgrade($input);
+  $1 = SvPV_nolen($input);
+}
diff --git a/swig/include/python/docs/README b/swig/include/python/docs/README
new file mode 100644
index 0000000..e849dad
--- /dev/null
+++ b/swig/include/python/docs/README
@@ -0,0 +1,12 @@
+The .i files in this directory are generated files and should not be edited
+manually.
+
+1) cd $(GDAL_ROOT)/ogr
+2) ( cat Doxyfile ; echo "GENERATE_XML=YES" ) | doxygen -
+
+This will generate a $(GDAL_ROOT)/ogr/xml directory with the doc in XML form
+
+3) cd $(GDAL_ROOT)/swig/python
+4) make docs
+
+This will parse $(GDAL_ROOT)/ogr/xml and regenerate $(GDAL_ROOT)/swig/include/python/docs
diff --git a/swig/include/python/docs/ogr_datasource_docs.i b/swig/include/python/docs/ogr_datasource_docs.i
index 654a885..97440a5 100644
--- a/swig/include/python/docs/ogr_datasource_docs.i
+++ b/swig/include/python/docs/ogr_datasource_docs.i
@@ -1,7 +1,7 @@
 %extend OGRDataSourceShadow {
 // File: ogrdatasource_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrdatasource.cpp
-16933 2009-05-03 19:49:41Z rouault $\") ";
+23403 2011-11-20 21:01:21Z ajolma $\") ";
 
 %feature("docstring")  Destroy "void OGR_DS_Destroy(OGRDataSourceH
 hDS)
@@ -135,6 +135,10 @@ pszLayerName:  Layer the layer name of the layer to fetch.
 an handle to the layer, or NULL if the layer is not found or an error
 occurs. ";
 
+%feature("docstring")  OGRDataSourceParseSQLType "static OGRFieldType
+OGRDataSourceParseSQLType(char *pszType, int &nWidth, int &nPrecision)
+";
+
 %feature("docstring")  ExecuteSQL "OGRLayerH
 OGR_DS_ExecuteSQL(OGRDataSourceH hDS, const char *pszStatement,
 OGRGeometryH hSpatialFilter, const char *pszDialect)
@@ -145,7 +149,7 @@ The result of an SQL query is either NULL for statements that are in
 error, or that have no results set, or an OGRLayer handle representing
 a results set from the query. Note that this OGRLayer is in addition
 to the layers in the data store and must be destroyed with
-OGR_DS_ReleaseResultsSet() before the data source is closed
+OGR_DS_ReleaseResultSet() before the data source is closed
 (destroyed).
 
 For more information on the SQL dialect supported internally by OGR
@@ -163,13 +167,15 @@ hDS:  handle to the data source on which the SQL query is executed.
 pszSQLCommand:  the SQL statement to execute.
 
 hSpatialFilter:  handle to a geometry which represents a spatial
-filter.
+filter. Can be NULL.
 
-pszDialect:  allows control of the statement dialect. By default it is
-assumed to be \"generic\" SQL, whatever that is.
+pszDialect:  allows control of the statement dialect. If set to NULL,
+the OGR SQL engine will be used, except for RDBMS drivers that will
+use their dedicated SQL engine, unless OGRSQL is explicitely passed as
+the dialect.
 
 an handle to a OGRLayer containing the results of the query.
-Deallocate with OGR_DS_ReleaseResultsSet(). ";
+Deallocate with OGR_DS_ReleaseResultSet(). ";
 
 %feature("docstring")  ReleaseResultSet "void
 OGR_DS_ReleaseResultSet(OGRDataSourceH hDS, OGRLayerH hLayer)
@@ -182,7 +188,7 @@ deallocate a results set before destroying the OGRDataSource may cause
 errors.
 
 This function is the same as the C++ method
-OGRDataSource::ReleaseResultsSet().
+OGRDataSource::ReleaseResultSet().
 
 Parameters:
 -----------
diff --git a/swig/include/python/docs/ogr_driver_docs.i b/swig/include/python/docs/ogr_driver_docs.i
index 5d7945f..2a9e85e 100644
--- a/swig/include/python/docs/ogr_driver_docs.i
+++ b/swig/include/python/docs/ogr_driver_docs.i
@@ -1,7 +1,7 @@
 %extend OGRDriverShadow {
 // File: ogrsfdriver_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrsfdriver.cpp
-16319 2009-02-13 23:17:58Z rouault $\") ";
+23413 2011-11-22 21:53:32Z rouault $\") ";
 
 %feature("docstring")  CreateDataSource "OGRDataSourceH
 OGR_Dr_CreateDataSource(OGRSFDriverH hDriver, const char *pszName,
@@ -25,7 +25,7 @@ Parameters:
 
 hDriver:  handle to the driver on which data source creation is based.
 
-pszName:  the name for the new data source.
+pszName:  the name for the new data source. UTF-8 encoded.
 
 papszOptions:  a StringList of name=value options. Options are driver
 specific, and driver information can be found at the following
diff --git a/swig/include/python/docs/ogr_feature_docs.i b/swig/include/python/docs/ogr_feature_docs.i
index 7c2844d..94b4045 100644
--- a/swig/include/python/docs/ogr_feature_docs.i
+++ b/swig/include/python/docs/ogr_feature_docs.i
@@ -1,7 +1,7 @@
 %extend OGRFeatureShadow {
 // File: ogrfeature_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrfeature.cpp
-18231 2009-12-09 17:33:09Z rouault $\") ";
+23414 2011-11-23 05:50:05Z warmerdam $\") ";
 
 %feature("docstring")  Create "OGRFeatureH
 OGR_F_Create(OGRFeatureDefnH hDefn)
@@ -102,6 +102,20 @@ OGRERR_NONE if successful, or OGR_UNSUPPORTED_GEOMETRY_TYPE if the
 geometry type is illegal for the OGRFeatureDefn (checking not yet
 implemented). ";
 
+%feature("docstring")  StealGeometry "OGRGeometryH
+OGR_F_StealGeometry(OGRFeatureH hFeat)
+
+Take away ownership of geometry.
+
+Fetch the geometry from this feature, and clear the reference to the
+geometry on the feature. This is a mechanism for the application to
+take over ownship of the geometry from the feature without copying.
+Sort of an inverse to OGR_FSetGeometryDirectly().
+
+After this call the OGRFeature will have a NULL geometry.
+
+the pointer to the geometry. ";
+
 %feature("docstring")  GetGeometryRef "OGRGeometryH
 OGR_F_GetGeometryRef(OGRFeatureH hFeat)
 
@@ -298,7 +312,7 @@ hFeat:  handle to the feature that owned the field.
 iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
 the field value. This string is internal, and should not be modified,
-or freed. It's lifetime may be very brief. ";
+or freed. Its lifetime may be very brief. ";
 
 %feature("docstring")  GetFieldAsIntegerList "const int*
 OGR_F_GetFieldAsIntegerList(OGRFeatureH hFeat, int iField, int
@@ -321,7 +335,7 @@ iField:  the field to fetch, from 0 to GetFieldCount()-1.
 pnCount:  an integer to put the list count (number of integers) into.
 
 the field value. This list is internal, and should not be modified, or
-freed. It's lifetime may be very brief. If *pnCount is zero on return
+freed. Its lifetime may be very brief. If *pnCount is zero on return
 the returned pointer may be NULL or non-NULL. ";
 
 %feature("docstring")  GetFieldAsDoubleList "const double*
@@ -345,7 +359,7 @@ iField:  the field to fetch, from 0 to GetFieldCount()-1.
 pnCount:  an integer to put the list count (number of doubles) into.
 
 the field value. This list is internal, and should not be modified, or
-freed. It's lifetime may be very brief. If *pnCount is zero on return
+freed. Its lifetime may be very brief. If *pnCount is zero on return
 the returned pointer may be NULL or non-NULL. ";
 
 %feature("docstring")  GetFieldAsStringList "char**
@@ -369,7 +383,7 @@ hFeat:  handle to the feature that owned the field.
 iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
 the field value. This list is internal, and should not be modified, or
-freed. It's lifetime may be very brief. ";
+freed. Its lifetime may be very brief. ";
 
 %feature("docstring")  GetFieldAsBinary "GByte*
 OGR_F_GetFieldAsBinary(OGRFeatureH hFeat, int iField, int *pnBytes)
@@ -391,7 +405,7 @@ iField:  the field to fetch, from 0 to GetFieldCount()-1.
 pnBytes:  location to place count of bytes returned.
 
 the field value. This list is internal, and should not be modified, or
-freed. It's lifetime may be very brief. ";
+freed. Its lifetime may be very brief. ";
 
 %feature("docstring")  GetFieldAsDateTime "int
 OGR_F_GetFieldAsDateTime(OGRFeatureH hFeat, int iField, int *pnYear,
diff --git a/swig/include/python/docs/ogr_featuredef_docs.i b/swig/include/python/docs/ogr_featuredef_docs.i
index fbf6dc5..65cf886 100644
--- a/swig/include/python/docs/ogr_featuredef_docs.i
+++ b/swig/include/python/docs/ogr_featuredef_docs.i
@@ -1,7 +1,7 @@
 %extend OGRFeatureDefnShadow {
 // File: ogrfeaturedefn_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrfeaturedefn.cpp
-17587 2009-08-27 17:56:01Z warmerdam $\") ";
+22900 2011-08-07 20:47:41Z rouault $\") ";
 
 %feature("docstring")  Create "OGRFeatureDefnH OGR_FD_Create(const
 char *pszName)
@@ -105,12 +105,15 @@ OGR_FD_AddFieldDefn(OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField)
 
 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_CreateField() instead.
+
 This function should only be called while there are no OGRFeature
 objects in existance based on this OGRFeatureDefn. The OGRFieldDefn
 passed in is copied, and remains the responsibility of the caller.
 
 This function is the same as the C++ method
-OGRFeatureDefn::AddFieldDefn.
+OGRFeatureDefn::AddFieldDefn().
 
 Parameters:
 -----------
@@ -120,6 +123,59 @@ to.
 
 hNewField:  handle to the new field definition. ";
 
+%feature("docstring")  DeleteFieldDefn "OGRErr
+OGR_FD_DeleteFieldDefn(OGRFeatureDefnH hDefn, int iField)
+
+Delete an existing field definition.
+
+To delete an existing field definition from a layer definition, do not
+use this function directly, but use OGR_L_DeleteField() 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++ method
+OGRFeatureDefn::DeleteFieldDefn().
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition.
+
+iField:  the index of the field defintion.
+
+OGRERR_NONE in case of success.
+
+OGR 1.9.0 ";
+
+%feature("docstring")  ReorderFieldDefn "OGRErr
+OGR_FD_ReorderFieldDefn(OGRFeatureDefnH hDefn, int *panMap)
+
+Reorder the field definitions in the array of the feature definition.
+
+To reorder the field definitions in a layer definition, do not use
+this function directly, but use OGR_L_ReorderFields() 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++ method
+OGRFeatureDefn::ReorderFieldDefns().
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition.
+
+panMap:  an array of GetFieldCount() elements which is a permutation
+of [0, GetFieldCount()-1]. panMap is such that, for each field
+definition at position i after reordering, its position before
+reordering was panMap[i].
+
+OGRERR_NONE in case of success.
+
+OGR 1.9.0 ";
+
 %feature("docstring")  GetGeomType "OGRwkbGeometryType
 OGR_FD_GetGeomType(OGRFeatureDefnH hDefn)
 
@@ -229,4 +285,68 @@ pszFieldName:  the field name to search for.
 
 the field index, or -1 if no match found. ";
 
+%feature("docstring")  IsGeometryIgnored "int
+OGR_FD_IsGeometryIgnored(OGRFeatureDefnH hDefn)
+
+Determine whether the geometry can be omitted when fetching features.
+
+This function is the same as the C++ method
+OGRFeatureDefn::IsGeometryIgnored().
+
+Parameters:
+-----------
+
+hDefn:  hanlde to the feature definition on witch OGRFeature are based
+on.
+
+ignore state ";
+
+%feature("docstring")  SetGeometryIgnored "void
+OGR_FD_SetGeometryIgnored(OGRFeatureDefnH hDefn, int bIgnore)
+
+Set whether the geometry can be omitted when fetching features.
+
+This function is the same as the C++ method
+OGRFeatureDefn::SetGeometryIgnored().
+
+Parameters:
+-----------
+
+hDefn:  hanlde to the feature definition on witch OGRFeature are based
+on.
+
+bIgnore:  ignore state ";
+
+%feature("docstring")  IsStyleIgnored "int
+OGR_FD_IsStyleIgnored(OGRFeatureDefnH hDefn)
+
+Determine whether the style can be omitted when fetching features.
+
+This function is the same as the C++ method
+OGRFeatureDefn::IsStyleIgnored().
+
+Parameters:
+-----------
+
+hDefn:  handle to the feature definition on which OGRFeature are based
+on.
+
+ignore state ";
+
+%feature("docstring")  SetStyleIgnored "void
+OGR_FD_SetStyleIgnored(OGRFeatureDefnH hDefn, int bIgnore)
+
+Set whether the style can be omitted when fetching features.
+
+This function is the same as the C++ method
+OGRFeatureDefn::SetStyleIgnored().
+
+Parameters:
+-----------
+
+hDefn:  hanlde to the feature definition on witch OGRFeature are based
+on.
+
+bIgnore:  ignore state ";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/docs/ogr_fielddef_docs.i b/swig/include/python/docs/ogr_fielddef_docs.i
index c61226b..23a4eef 100644
--- a/swig/include/python/docs/ogr_fielddef_docs.i
+++ b/swig/include/python/docs/ogr_fielddef_docs.i
@@ -1,7 +1,7 @@
 %extend OGRFieldDefnShadow {
 // File: ogrfielddefn_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrfielddefn.cpp
-16574 2009-03-14 13:09:10Z rouault $\") ";
+21018 2010-10-30 11:30:51Z rouault $\") ";
 
 %feature("docstring")  Create "OGRFieldDefnH OGR_Fld_Create(const
 char *pszName, OGRFieldType eType)
@@ -220,4 +220,32 @@ zero indicating undefined.
 eJustifyIn:  the formatting justification (OJLeft or OJRight),
 defaults to OJUndefined. ";
 
+%feature("docstring")  IsIgnored "int OGR_Fld_IsIgnored(OGRFieldDefnH
+hDefn)
+
+Return whether this field should be omitted when fetching features.
+
+This method is the same as the C++ method OGRFieldDefn::IsIgnored().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition
+
+ignore state ";
+
+%feature("docstring")  SetIgnored "void
+OGR_Fld_SetIgnored(OGRFieldDefnH hDefn, int ignore)
+
+Set whether this field should be omitted when fetching features.
+
+This method is the same as the C function OGRFieldDefn::SetIgnored().
+
+Parameters:
+-----------
+
+hDefn:  handle to the field definition
+
+ignore:  ignore state ";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/docs/ogr_geometry_docs.i b/swig/include/python/docs/ogr_geometry_docs.i
index 2a3e26a..2cae4c0 100644
--- a/swig/include/python/docs/ogr_geometry_docs.i
+++ b/swig/include/python/docs/ogr_geometry_docs.i
@@ -1,7 +1,7 @@
 %extend OGRGeometryShadow {
 // File: ogrgeometry_8cpp.xml
 %feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrgeometry.cpp
-17010 2009-05-13 20:33:01Z warmerdam $\") ";
+23140 2011-09-29 20:13:09Z rouault $\") ";
 
 %feature("docstring")  DumpReadable "void
 OGR_G_DumpReadable(OGRGeometryH hGeom, FILE *fp, const char
@@ -185,11 +185,26 @@ Parameters:
 hGeom:  handle on the geometry to get the dimension of the coordinates
 from.
 
-in practice this always returns 2 indicating that coordinates are
-specified within a two dimensional space. ";
+in practice this will return 2 or 3. It can also return 0 in the case
+of an empty point. ";
 
 %feature("docstring")  SetCoordinateDimension "void
-OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension) ";
+OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension)
+
+Set the coordinate dimension.
+
+This method sets the explicit coordinate dimension. Setting the
+coordinate dimension of a geometry to 2 should zero out any existing Z
+values. Setting the dimension of a geometry collection will not
+necessarily affect the children geometries.
+
+Parameters:
+-----------
+
+hGeom:  handle on the geometry to set the dimension of the
+coordinates.
+
+nNewDimension:  New coordinate dimension value, either 2 or 3. ";
 
 %feature("docstring")  Equals "int OGR_G_Equals(OGRGeometryH hGeom,
 OGRGeometryH hOther)
@@ -246,6 +261,24 @@ hGeom:  handle of the geometry to get envelope from.
 
 psEnvelope:  the structure in which to place the results. ";
 
+%feature("docstring")  GetEnvelope3D "void
+OGR_G_GetEnvelope3D(OGRGeometryH hGeom, OGREnvelope3D *psEnvelope)
+
+Computes and returns the bounding envelope (3D) for this geometry in
+the passed psEnvelope structure.
+
+This function is the same as the CPP method
+OGRGeometry::getEnvelope().
+
+Parameters:
+-----------
+
+hGeom:  handle of the geometry to get envelope from.
+
+psEnvelope:  the structure in which to place the results.
+
+OGR 1.9.0 ";
+
 %feature("docstring")  ImportFromWkb "OGRErr
 OGR_G_ImportFromWkb(OGRGeometryH hGeom, unsigned char *pabyData, int
 nSize)
@@ -498,6 +531,12 @@ hGeom:  The Geometry to test.
 
 TRUE if the geometry has no points, otherwise FALSE. ";
 
+%feature("docstring")  OGRFromOGCGeomType "OGRwkbGeometryType
+OGRFromOGCGeomType(const char *pszGeomType) ";
+
+%feature("docstring")  OGRToOGCGeomType "const char*
+OGRToOGCGeomType(OGRwkbGeometryType eGeomType) ";
+
 %feature("docstring")  OGRGeometryTypeToName "const char*
 OGRGeometryTypeToName(OGRwkbGeometryType eType)
 
@@ -612,15 +651,15 @@ hTarget:  The Geometry to calculate the convex hull of.
 a handle to a newly allocated geometry now owned by the caller, or
 NULL on failure. ";
 
-%feature("docstring")  GetBoundary "OGRGeometryH
-OGR_G_GetBoundary(OGRGeometryH hTarget)
+%feature("docstring")  Boundary "OGRGeometryH
+OGR_G_Boundary(OGRGeometryH hTarget)
 
 Compute boundary.
 
 A new geometry object is created and returned containing the boundary
 of the geometry on which the method is invoked.
 
-This function is the same as the C++ method OGR_G_GetBoundary().
+This function is the same as the C++ method OGR_G_Boundary().
 
 This function is built on the GEOS library, check it for the
 definition of the geometry operation. If OGR is built without the GEOS
@@ -633,7 +672,16 @@ Parameters:
 hTarget:  The Geometry to calculate the boundary of.
 
 a handle to a newly allocated geometry now owned by the caller, or
-NULL on failure. ";
+NULL on failure.
+
+OGR 1.8.0 ";
+
+%feature("docstring")  GetBoundary "OGRGeometryH
+OGR_G_GetBoundary(OGRGeometryH hTarget)
+
+Compute boundary (deprecated).
+
+Deprecated See:   OGR_G_Boundary() ";
 
 %feature("docstring")  Buffer "OGRGeometryH OGR_G_Buffer(OGRGeometryH
 hTarget, double dfDist, int nQuadSegs)
@@ -721,6 +769,26 @@ hOther:  the other geometry.
 
 a new geometry representing the union or NULL if an error occurs. ";
 
+%feature("docstring")  UnionCascaded "OGRGeometryH
+OGR_G_UnionCascaded(OGRGeometryH hThis)
+
+Compute union using cascading.
+
+This function is the same as the C++ method
+OGRGeometry::UnionCascaded().
+
+This function is built on the GEOS library, check it for the
+definition of the geometry operation. If OGR is built without the GEOS
+library, this function will always fail, issuing a CPLE_NotSupported
+error.
+
+Parameters:
+-----------
+
+hThis:  the geometry.
+
+a new geometry representing the union or NULL if an error occurs. ";
+
 %feature("docstring")  Difference "OGRGeometryH
 OGR_G_Difference(OGRGeometryH hThis, OGRGeometryH hOther)
 
@@ -746,8 +814,8 @@ hOther:  the other geometry.
 a new geometry representing the difference or NULL if the difference
 is empty or an error occurs. ";
 
-%feature("docstring")  SymmetricDifference "OGRGeometryH
-OGR_G_SymmetricDifference(OGRGeometryH hThis, OGRGeometryH hOther)
+%feature("docstring")  SymDifference "OGRGeometryH
+OGR_G_SymDifference(OGRGeometryH hThis, OGRGeometryH hOther)
 
 Compute symmetric difference.
 
@@ -770,7 +838,16 @@ hThis:  the geometry.
 hOther:  the other geometry.
 
 a new geometry representing the symmetric difference or NULL if the
-difference is empty or an error occurs. ";
+difference is empty or an error occurs.
+
+OGR 1.8.0 ";
+
+%feature("docstring")  SymmetricDifference "OGRGeometryH
+OGR_G_SymmetricDifference(OGRGeometryH hThis, OGRGeometryH hOther)
+
+Compute symmetric difference (deprecated).
+
+Deprecated See:   OGR_G_SymmetricDifference() ";
 
 %feature("docstring")  Disjoint "int OGR_G_Disjoint(OGRGeometryH
 hThis, OGRGeometryH hOther)
@@ -912,6 +989,88 @@ hOther:  the other geometry to compare.
 TRUE if they are overlapping, otherwise FALSE. ";
 
 %feature("docstring")  CloseRings "void OGR_G_CloseRings(OGRGeometryH
-hGeom) ";
+hGeom)
+
+Force rings to be closed.
+
+If this geometry, or any contained geometries has polygon rings that
+are not closed, they will be closed by adding the starting point at
+the end.
+
+Parameters:
+-----------
+
+hGeom:  handle to the geometry. ";
+
+%feature("docstring")  Centroid "int OGR_G_Centroid(OGRGeometryH
+hGeom, OGRGeometryH hCentroidPoint)
+
+Compute the geometry centroid.
+
+The centroid location is applied to the passed in OGRPoint object. The
+centroid is not necessarily within the geometry.
+
+This method relates to the SFCOM ISurface::get_Centroid() method
+however the current implementation based on GEOS can operate on other
+geometry types such as multipoint, linestring, geometrycollection such
+as multipolygons. OGC SF SQL 1.1 defines the operation for surfaces
+(polygons). SQL/MM-Part 3 defines the operation for surfaces and
+multisurfaces (multipolygons).
+
+This function is the same as the C++ method OGRGeometry::Centroid().
+
+This function is built on the GEOS library, check it for the
+definition of the geometry operation. If OGR is built without the GEOS
+library, this function will always fail, issuing a CPLE_NotSupported
+error.
+
+OGRERR_NONE on success or OGRERR_FAILURE on error. ";
+
+%feature("docstring")  Simplify "OGRGeometryH
+OGR_G_Simplify(OGRGeometryH hThis, double dTolerance)
+
+Compute a simplified geometry.
+
+This function is the same as the C++ method OGRGeometry::Simplify().
+
+This function is built on the GEOS library, check it for the
+definition of the geometry operation. If OGR is built without the GEOS
+library, this function will always fail, issuing a CPLE_NotSupported
+error.
+
+Parameters:
+-----------
+
+hThis:  the geometry.
+
+dTolerance:  the distance tolerance for the simplification.
+
+the simplified geometry or NULL if an error occurs.
+
+OGR 1.8.0 ";
+
+%feature("docstring")  SimplifyPreserveTopology "OGRGeometryH
+OGR_G_SimplifyPreserveTopology(OGRGeometryH hThis, double dTolerance)
+
+Compute a simplified geometry.
+
+This function is the same as the C++ method
+OGRGeometry::SimplifyPreserveTopology().
+
+This function is built on the GEOS library, check it for the
+definition of the geometry operation. If OGR is built without the GEOS
+library, this function will always fail, issuing a CPLE_NotSupported
+error.
+
+Parameters:
+-----------
+
+hThis:  the geometry.
+
+dTolerance:  the distance tolerance for the simplification.
+
+the simplified geometry or NULL if an error occurs.
+
+OGR 1.9.0 ";
 
 }
\ No newline at end of file
diff --git a/swig/include/python/docs/ogr_layer_docs.i b/swig/include/python/docs/ogr_layer_docs.i
index ab08813..9ff1391 100644
--- a/swig/include/python/docs/ogr_layer_docs.i
+++ b/swig/include/python/docs/ogr_layer_docs.i
@@ -1,7 +1,7 @@
 %extend OGRLayerShadow {
 // File: ogrlayer_8cpp.xml
-%feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrlayer.cpp 17223
-2009-06-07 19:41:08Z rouault $\") ";
+%feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrlayer.cpp 22724
+2011-07-15 16:45:39Z rouault $\") ";
 
 %feature("docstring")  Reference "int OGR_L_Reference(OGRLayerH
 hLayer) ";
@@ -26,6 +26,9 @@ objects.
 
 The returned count takes the spatial filter into account.
 
+Note that some implementations of this method may alter the read
+cursor of the layer.
+
 This function is the same as the CPP OGRLayer::GetFeatureCount().
 
 Parameters:
@@ -56,6 +59,9 @@ 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().
 
 Parameters:
@@ -185,8 +191,7 @@ SetSpatialFilter()) will be returned.
 
 This function implements sequential access to the features of a layer.
 The OGR_L_ResetReading() function can be used to start at the
-beginning again. Random reading, writing and spatial filtering will be
-added to the OGRLayer in the future.
+beginning again.
 
 This function is the same as the C++ method
 OGRLayer::GetNextFeature().
@@ -255,6 +260,16 @@ 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().
 
 Parameters:
@@ -269,6 +284,172 @@ form depending on the limitations of the format driver.
 
 OGRERR_NONE on success. ";
 
+%feature("docstring")  DeleteField "OGRErr
+OGR_L_DeleteField(OGRLayerH hLayer, int iField)
+
+Create a new field on a layer.
+
+You must use this to delete existing fields on a real layer.
+Internally the OGRFeatureDefn for the layer will be updated to reflect
+the deleted 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 OLCDeleteField 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::DeleteField().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer.
+
+iField:  index of the field to delete.
+
+OGRERR_NONE on success.
+
+OGR 1.9.0 ";
+
+%feature("docstring")  ReorderFields "OGRErr
+OGR_L_ReorderFields(OGRLayerH hLayer, int *panMap)
+
+Reorder all the fields of a layer.
+
+You must use this to reorder existing fields on a real layer.
+Internally the OGRFeatureDefn for the layer will be updated to reflect
+the reordering of the fields. 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.
+
+panMap is such that,for each field definition at position i after
+reordering, its position before reordering was panMap[i].
+
+For example, let suppose the fields were \"0\",\"1\",\"2\",\"3\",\"4\"
+initially. ReorderFields([0,2,3,1,4]) will reorder them as
+\"0\",\"2\",\"3\",\"1\",\"4\".
+
+Not all drivers support this function. You can query a layer to check
+if it supports it with the OLCReorderFields 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::ReorderFields().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer.
+
+panMap:  an array of GetLayerDefn()->GetFieldCount() elements which is
+a permutation of [0, GetLayerDefn()->GetFieldCount()-1].
+
+OGRERR_NONE on success.
+
+OGR 1.9.0 ";
+
+%feature("docstring")  ReorderField "OGRErr
+OGR_L_ReorderField(OGRLayerH hLayer, int iOldFieldPos, int
+iNewFieldPos)
+
+Reorder an existing field on a layer.
+
+This function is a conveniency wrapper of OGR_L_ReorderFields()
+dedicated to move a single field.
+
+You must use this to reorder existing fields on a real layer.
+Internally the OGRFeatureDefn for the layer will be updated to reflect
+the reordering of the fields. 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.
+
+The field definition that was at initial position iOldFieldPos will be
+moved at position iNewFieldPos, and elements between will be shuffled
+accordingly.
+
+For example, let suppose the fields were \"0\",\"1\",\"2\",\"3\",\"4\"
+initially. ReorderField(1, 3) will reorder them as
+\"0\",\"2\",\"3\",\"1\",\"4\".
+
+Not all drivers support this function. You can query a layer to check
+if it supports it with the OLCReorderFields 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::ReorderField().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer.
+
+iOldFieldPos:  previous position of the field to move. Must be in the
+range [0,GetFieldCount()-1].
+
+iNewFieldPos:  new position of the field to move. Must be in the range
+[0,GetFieldCount()-1].
+
+OGRERR_NONE on success.
+
+OGR 1.9.0 ";
+
+%feature("docstring")  AlterFieldDefn "OGRErr
+OGR_L_AlterFieldDefn(OGRLayerH hLayer, int iField, OGRFieldDefnH
+hNewFieldDefn, int nFlags)
+
+Alter the definition of an existing field on a layer.
+
+You must use this to alter the definition of an existing field of a
+real layer. Internally the OGRFeatureDefn for the layer will be
+updated to reflect the altered 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 OLCAlterFieldDefn 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. Some drivers might also
+not support all update flags.
+
+This function is the same as the C++ method
+OGRLayer::AlterFieldDefn().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer.
+
+iField:  index of the field whose definition must be altered.
+
+hNewFieldDefn:  new field definition
+
+nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and
+ALTER_WIDTH_PRECISION_FLAG to indicate which of the name and/or type
+and/or width and precision fields from the new field definition must
+be taken into account.
+
+OGRERR_NONE on success.
+
+OGR 1.9.0 ";
+
 %feature("docstring")  StartTransaction "OGRErr
 OGR_L_StartTransaction(OGRLayerH hLayer)
 
@@ -411,6 +592,18 @@ perform the SetNextByIndex() call efficiently, otherwise FALSE.
 OLCCreateField / \"CreateField\": TRUE if this layer can create new
 fields on the current layer using CreateField(), otherwise FALSE.
 
+OLCDeleteField / \"DeleteField\": TRUE if this layer can delete
+existing fields on the current layer using DeleteField(), otherwise
+FALSE.
+
+OLCReorderFields / \"ReorderFields\": TRUE if this layer can reorder
+existing fields on the current layer using ReorderField() or
+ReorderFields(), otherwise FALSE.
+
+OLCAlterFieldDefn / \"AlterFieldDefn\": TRUE if this layer can alter
+the definition of an existing field on the current layer using
+AlterFieldDefn(), otherwise FALSE.
+
 OLCDeleteFeature / \"DeleteFeature\": TRUE if the DeleteFeature()
 method is supported on this layer, otherwise FALSE.
 
@@ -631,4 +824,74 @@ hStyleTable) ";
 %feature("docstring")  SetStyleTable "void
 OGR_L_SetStyleTable(OGRLayerH hLayer, OGRStyleTableH hStyleTable) ";
 
+%feature("docstring")  GetName "const char* OGR_L_GetName(OGRLayerH
+hLayer)
+
+Return the layer name.
+
+This returns the same content as
+OGR_FD_GetName(OGR_L_GetLayerDefn(hLayer)), but for a few drivers,
+calling OGR_L_GetName() directly can avoid lengthy layer definition
+initialization.
+
+This function is the same as the C++ method OGRLayer::GetName().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer.
+
+the layer name (must not been freed)
+
+OGR 1.8.0 ";
+
+%feature("docstring")  GetGeomType "OGRwkbGeometryType
+OGR_L_GetGeomType(OGRLayerH hLayer)
+
+Return the layer geometry type.
+
+This returns the same result as
+OGR_FD_GetGeomType(OGR_L_GetLayerDefn(hLayer)), but for a few drivers,
+calling OGR_L_GetGeomType() directly can avoid lengthy layer
+definition initialization.
+
+This function is the same as the C++ method OGRLayer::GetGeomType().
+
+Parameters:
+-----------
+
+hLayer:  handle to the layer.
+
+the geometry type
+
+OGR 1.8.0 ";
+
+%feature("docstring")  SetIgnoredFields "OGRErr
+OGR_L_SetIgnoredFields(OGRLayerH hLayer, const char **papszFields)
+
+Set which fields can be omitted when retrieving features from the
+layer.
+
+If the driver supports this functionality (testable using
+OLCIgnoreFields capability), it will not fetch the specified fields in
+subsequent calls to GetFeature() / GetNextFeature() and thus save some
+processing time and/or bandwidth.
+
+Besides field names of the layers, the following special fields can be
+passed: \"OGR_GEOMETRY\" to ignore geometry and \"OGR_STYLE\" to
+ignore layer style.
+
+By default, no fields are ignored.
+
+This method is the same as the C++ method OGRLayer::SetIgnoredFields()
+
+Parameters:
+-----------
+
+papszFields:  an array of field names terminated by NULL item. If NULL
+is passed, the ignored list is cleared.
+
+OGRERR_NONE if all field names have been resolved (even if the driver
+does not support this method) ";
+
 }
\ No newline at end of file
diff --git a/swig/include/python/gdal_python.i b/swig/include/python/gdal_python.i
index f9ea770..50caa36 100644
--- a/swig/include/python/gdal_python.i
+++ b/swig/include/python/gdal_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_python.i 20996 2010-10-28 18:38:15Z rouault $
+ * $Id: gdal_python.i 22938 2011-08-15 18:12:28Z rouault $
  *
  * python specific code for gdal bindings.
  */
@@ -113,7 +113,15 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return 0;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
+    PyObject* o = (PyObject*) *buf;
+    char *data = PyBytes_AsString(o); 
+    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * nMembSize < buf_size)
+    {
+        _PyBytes_Resize(&o, nRet * nMembSize);
+        *buf = o;
+    }
+    return nRet;
 #else 
     *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
     if (*buf == NULL)
@@ -121,11 +129,17 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return 0;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    PyObject* o = (PyObject*) *buf;
+    char *data = PyString_AsString(o); 
+    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * nMembSize < buf_size)
+    {
+        _PyString_Resize(&o, nRet * nMembSize);
+        *buf = o;
+    }
+    return nRet;
 #endif
-
-    return VSIFReadL( data, nMembSize, nMembCount, fp );
-} 
+}
 %}
 %clear (void **buf );
 
diff --git a/swig/include/python/ogr_python.i b/swig/include/python/ogr_python.i
index 27bfff4..d5fb227 100644
--- a/swig/include/python/ogr_python.i
+++ b/swig/include/python/ogr_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: ogr_python.i 21216 2010-12-08 18:29:51Z rouault $
+ * $Id: ogr_python.i 23417 2011-11-23 06:45:28Z warmerdam $
  *
  * python specific code for ogr bindings.
  */
@@ -202,12 +202,33 @@ layer[0:4] would return a list of the first four features."""
     def __copy__(self):
         return self.Clone()
 
-    def __getattr__(self, name):
+    # This makes it possible to fetch fields in the form "feature.area". 
+    # This has some risk of name collisions.
+    def __getattr__(self, key):
         """Returns the values of fields by the given name"""
         try:
-            return self.GetField(name)
+            return self.GetField(key)
         except:
-            raise AttributeError(name)
+            raise AttributeError(key)
+
+    # 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:
+            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)
+
+    # 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 )    
 
     def GetField(self, fld_index):
         import types
@@ -222,11 +243,47 @@ layer[0:4] would return a list of the first four features."""
             return self.GetFieldAsInteger(fld_index)
         if fld_type == OFTReal:
             return self.GetFieldAsDouble(fld_index)
+        if fld_type == OFTStringList:
+            return self.GetFieldAsStringList(fld_index)
+        if fld_type == OFTIntegerList:
+            return self.GetFieldAsIntegerList(fld_index)
+        if fld_type == OFTRealList:
+            return self.GetFieldAsDoubleList(fld_index)
         ## if fld_type == OFTDateTime or fld_type == OFTDate or fld_type == OFTTime:
         #     return self.GetFieldAsDate(fld_index)
         # default to returning as a string.  Should we add more types?
         return self.GetFieldAsString(fld_index)
-    
+
+    def SetField2(self, fld_index, value):
+        if isinstance(fld_index, str):
+            fld_index = self.GetFieldIndex(fld_index)
+
+        if value is None:
+            self.UnsetField( fld_index )
+            return
+
+        if isinstance(value,list):
+            if len(value) == 0:
+                self.UnsetField( fld_index )
+                return
+            if isinstance(value[0],int):
+                self.SetFieldIntegerList(fld_index,value)
+                return
+            elif isinstance(value[0],float):
+                self.SetFieldDoubleList(fld_index,value)
+                return
+            elif isinstance(value[0],str):
+                self.SetFieldStringList(fld_index,value)
+                return
+            else:
+                raise TypeError( 'Unsupported type of list in SetField2()' )
+
+        try:
+            self.SetField( fld_index, value )
+        except:
+            self.SetField( fld_index, str(value) )
+        return
+
     def keys(self):
         names = []
         for i in range(self.GetFieldCount()):
@@ -243,10 +300,11 @@ layer[0:4] would return a list of the first four features."""
     def geometry(self):
         return self.GetGeometryRef()
 
-    def ExportToJson(self, as_object = False):
+    def ExportToJson(self, as_object = False, options = None):
         """Exports a GeoJSON object which represents the Feature. The
            as_object parameter determines whether the returned value 
-           should be a Python object instead of a string. Defaults to False."""
+           should be a Python object instead of a string. Defaults to False.
+           The options parameter is passed to Geometry.ExportToJson()"""
 
         try:
             import simplejson
@@ -258,7 +316,9 @@ layer[0:4] would return a list of the first four features."""
 
         geom = self.GetGeometryRef()
         if geom is not None:
-            geom_json_string = geom.ExportToJson()
+            if options is None:
+                options = []
+            geom_json_string = geom.ExportToJson(options = options)
             geom_json_object = simplejson.loads(geom_json_string)
         else:
             geom_json_object = None
diff --git a/swig/include/python/typemaps_python.i b/swig/include/python/typemaps_python.i
index 63df9e8..95b7755 100644
--- a/swig/include/python/typemaps_python.i
+++ b/swig/include/python/typemaps_python.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_python.i 20716 2010-09-30 22:27:35Z rouault $
+ * $Id: typemaps_python.i 23329 2011-11-05 21:09:07Z rouault $
  *
  * Name:     typemaps_python.i
  * Project:  GDAL Python Interface
@@ -93,6 +93,29 @@
   $result = t_output_helper($result,r);
 }
 
+
+%typemap(in,numinputs=0) (double argout[4], int* isvalid) ( double argout[6], int isvalid )
+{
+  /* %typemap(in) (double argout[4], int* isvalid) */
+  $1 = argout;
+  $2 = &isvalid;
+}
+
+%typemap(argout) (double argout[4], int* isvalid)
+{
+   /* %typemap(argout) (double argout[4], int* isvalid)  */
+  PyObject *r;
+  if ( !*$2 ) {
+    Py_INCREF(Py_None);
+    r = Py_None;
+  }
+  else {
+    r = CreateTupleFromDoubleArray($1, 4);
+  }
+  $result = t_output_helper($result,r);
+}
+
+
 /*
  *
  * Define a simple return code typemap which checks if the return code from
@@ -699,6 +722,7 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
         $1 = CSLAddNameValue( $1, nm, val );
         Py_DECREF(it);
       }
+      Py_DECREF(item_list);
     }
   }
   else {
@@ -945,11 +969,33 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
     if( nChildCount < 0 )
     {
         PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
-	return NULL;
+        return NULL;
     }
 
     PyArg_Parse( PyList_GET_ITEM(pyList,0), "i", &nType );
     PyArg_Parse( PyList_GET_ITEM(pyList,1), "s", &pszText );
+
+    /* Detect "pseudo" root */
+    if (nType == CXT_Element && pszText != NULL && strlen(pszText) == 0 && nChildCount == 2)
+    {
+        PyObject *pyFirst = PyList_GET_ITEM(pyList, 2);
+        if (PyList_Size(pyFirst) < 2)
+        {
+            PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
+            return NULL;
+        }
+        int nTypeFirst = 0;
+        char* pszTextFirst = NULL;
+        PyArg_Parse( PyList_GET_ITEM(pyFirst,0), "i", &nTypeFirst );
+        PyArg_Parse( PyList_GET_ITEM(pyFirst,1), "s", &pszTextFirst );
+        if (nTypeFirst == CXT_Element && pszTextFirst != NULL && pszTextFirst[0] == '?')
+        {
+            psThisNode = PyListToXMLTree( PyList_GET_ITEM(pyList,2) );
+            psThisNode->psNext = PyListToXMLTree( PyList_GET_ITEM(pyList,3) );
+            return psThisNode;
+        }
+    }
+
     psThisNode = CPLCreateXMLNode( NULL, (CPLXMLNodeType) nType, pszText );
 
     for( iChild = 0; iChild < nChildCount; iChild++ )
@@ -1036,33 +1082,6 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
   if ( $1 ) CPLDestroyXMLNode( $1 );
 }
 
-/* Check inputs to ensure they are not NULL but instead empty #1775 */
-%define CHECK_NOT_UNDEF(type, param, msg)
-%typemap(check) (const char *pszNewDesc)
-{
-    /* %typemap(check) (type *param) */
-    if ( bUseExceptions && !$1) {
-        PyErr_SetString( PyExc_RuntimeError, "Description cannot be None" );
-        SWIG_fail;
-    }
-}
-%enddef
-
-//CHECK_NOT_UNDEF(char, method, method)
-//CHECK_NOT_UNDEF(const char, name, name)
-//CHECK_NOT_UNDEF(const char, request, request)
-//CHECK_NOT_UNDEF(const char, cap, capability)
-//CHECK_NOT_UNDEF(const char, statement, statement)
-CHECK_NOT_UNDEF(const char, pszNewDesc, description)
-CHECK_NOT_UNDEF(OSRCoordinateTransformationShadow, , coordinate transformation)
-CHECK_NOT_UNDEF(OGRGeometryShadow, other, other geometry)
-CHECK_NOT_UNDEF(OGRGeometryShadow, other_disown, other geometry)
-CHECK_NOT_UNDEF(OGRGeometryShadow, geom, geometry)
-CHECK_NOT_UNDEF(OGRFieldDefnShadow, defn, field definition)
-CHECK_NOT_UNDEF(OGRFieldDefnShadow, field_defn, field definition)
-CHECK_NOT_UNDEF(OGRFeatureShadow, feature, feature)
-
-
 /* ==================================================================== */
 /*	Support function for progress callbacks to python.                  */
 /* ==================================================================== */
@@ -1513,6 +1532,51 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
     VSIFree($5);
 }
 
+
+/***************************************************
+ * Typemaps for Gemetry.GetPoints()
+ ***************************************************/
+%typemap(in,numinputs=0) (int* pnCount, double** ppadfXY, double** ppadfZ) ( int nPoints = 0, double* padfXY = NULL, double* padfZ = NULL )
+{
+  /* %typemap(in,numinputs=0) (int* pnCount, double** ppadfXY, double** ppadfZ) */
+  $1 = &nPoints;
+  $2 = &padfXY;
+  $3 = &padfZ;
+}
+
+%typemap(argout)  (int* pnCount, double** ppadfXY, double** ppadfZ)
+{
+  /* %typemap(argout)  (int* pnCount, double** ppadfXY, double** ppadfZ) */
+  Py_DECREF($result);
+  int nPointCount = *($1);
+  if (nPointCount == 0)
+  {
+    $result = Py_None;
+  }
+  else
+  {
+    PyObject *xyz = PyList_New( nPointCount );
+    int nDimensions = (*$3 != NULL) ? 3 : 2;
+    for( int i=0; i< nPointCount; i++ ) {
+        PyObject *tuple = PyTuple_New( nDimensions );
+        PyTuple_SetItem( tuple, 0, PyFloat_FromDouble( (*$2)[2*i] ) );
+        PyTuple_SetItem( tuple, 1, PyFloat_FromDouble( (*$2)[2*i+1] ) );
+        if (nDimensions == 3)
+            PyTuple_SetItem( tuple, 2, PyFloat_FromDouble( (*$3)[i] ) );
+        PyList_SetItem( xyz, i, tuple );
+    }
+    $result = xyz;
+  }
+}
+
+%typemap(freearg)  (int* pnCount, double** ppadfXY, double** ppadfZ)
+{
+    /* %typemap(freearg)  (int* pnCount, double** ppadfXY, double** ppadfZ) */
+    VSIFree(*$2);
+    VSIFree(*$3);
+}
+
+
 %typemap(in) (const char *utf8_path) (int bToFree = 0)
 {
     /* %typemap(in) (const char *utf8_path) */
@@ -1529,3 +1593,21 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr($1, bToFree$argnum);
 }
+
+/*
+ * Typemap argout of StatBuf * used in VSIStatL( )
+ */
+%typemap(in,numinputs=0) (StatBuf *psStatBufOut) (StatBuf sStatBuf )
+{
+  /* %typemap(in,numinputs=0) (StatBuf *psStatBufOut) (StatBuf sStatBuf ) */
+  $1 = &sStatBuf;
+}
+%typemap(argout) (StatBuf *psStatBufOut)
+{
+  /* %typemap(argout) (StatBuf *psStatBufOut)*/
+  Py_DECREF($result);
+  if (result == 0)
+    $result = SWIG_NewPointerObj((void*)new_StatBuf( $1 ),SWIGTYPE_p_StatBuf,1);
+  else
+    $result = Py_None;
+}
diff --git a/swig/include/ruby/gdal_ruby.i b/swig/include/ruby/gdal_ruby.i
index 9056f04..e49b49e 100644
--- a/swig/include/ruby/gdal_ruby.i
+++ b/swig/include/ruby/gdal_ruby.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_ruby.i 8449 2005-09-26 08:18:55Z cfis $
+ * $Id: gdal_ruby.i 21964 2011-03-17 14:00:08Z warmerdam $
  *
  * ruby specific code for gdal bindings.
  */
@@ -36,7 +36,7 @@ static CPLXMLNode *RubyArrayToXMLTree(VALUE rubyArray)
     CPLXMLNode *psChild;
     char       *pszText = NULL;
 
-    nChildCount = RARRAY(rubyArray)->len - 2;
+    nChildCount = RARRAY_LEN(rubyArray) - 2;
     if( nChildCount < 0 )
     {
 		 rb_raise(rb_eRuntimeError, "Error in input XMLTree, child count is less than zero.");
diff --git a/swig/include/ruby/typemaps_ruby.i b/swig/include/ruby/typemaps_ruby.i
index 030db71..ea5f84d 100644
--- a/swig/include/ruby/typemaps_ruby.i
+++ b/swig/include/ruby/typemaps_ruby.i
@@ -1,6 +1,6 @@
 
 /******************************************************************************
- * $Id: typemaps_ruby.i 9021 2006-01-17 04:41:26Z cfis $
+ * $Id: typemaps_ruby.i 21964 2011-03-17 14:00:08Z warmerdam $
  *
  * Name:     typemaps_ruby.i
  * Project:  GDAL Ruby Interface
@@ -147,7 +147,7 @@
   Check_Type($input, T_ARRAY);
 
   /* Get the length */
-  int seq_size = RARRAY($input)->len;
+  int seq_size = RARRAY_LEN($input);
   
   if ( seq_size != $dim0 ) {
     rb_raise(rb_eRangeError, "sequence must have length %i.", seq_size);
@@ -225,7 +225,7 @@
   Check_Type($input, T_ARRAY);
 
   /* Get the length */
-  $1 = RARRAY($input)->len;
+  $1 = RARRAY_LEN($input);
   
   /* Allocate space for the C array. */
   $2 = (int*) malloc($1*sizeof(int));
@@ -315,7 +315,7 @@
   /* Check if is a list */
   Check_Type($input, T_ARRAY);
 
-  $1 = RARRAY($input)->len;
+  $1 = RARRAY_LEN($input);
   tmpGCPList = (GDAL_GCP*) malloc($1*sizeof(GDAL_GCP));
   $2 = tmpGCPList;
 
@@ -386,7 +386,7 @@
   /* is the provided object an array or a hash? */
   if ( TYPE($input) == T_ARRAY) {
     /* get the size of the array */
-    int size = RARRAY($input)->len;
+    int size = RARRAY_LEN($input);
     
     for (int i = 0; i < size; i++) {
       /* get the ruby object */
@@ -489,7 +489,7 @@
   /* Check if is a list */
   Check_Type($input, T_ARRAY);
 
-  int size = RARRAY($input)->len;
+  int size = RARRAY_LEN($input);
   for (int i = 0; i < size; i++) {
     VALUE item = rb_ary_entry($input, i);
     char *pszItem = StringValuePtr(item);
diff --git a/swig/java/GNUmakefile b/swig/java/GNUmakefile
index a7125cb..e0b8ed6 100644
--- a/swig/java/GNUmakefile
+++ b/swig/java/GNUmakefile
@@ -67,7 +67,7 @@ test:
 	${JAVA_RUN} gdalmajorobject
 	${JAVA_RUN} GDALTestIO
 	${JAVA_RUN} GDALContour -i 1 tmp_test/byte.tif tmp_test/contour.shp
-
+	${JAVA_RUN} testgetpoints
 
 $(JAVA_MODULES): lib%jni.$(SO_EXT): %_wrap.$(OBJ_EXT)
 	$(LINK) $(LDFLAGS) $(CONFIG_LIBS) $< -o $@ $(LINK_EXTRAFLAGS)
diff --git a/swig/java/apps/gdalinfo.java b/swig/java/apps/gdalinfo.java
index 31d70c9..0f38458 100644
--- a/swig/java/apps/gdalinfo.java
+++ b/swig/java/apps/gdalinfo.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalinfo.java 16360 2009-02-18 20:45:09Z rouault $
+ * $Id: gdalinfo.java 22688 2011-07-10 22:00:30Z rouault $
  *
  * Name:     gdalinfo.java
  * Project:  GDAL SWIG Interface
@@ -649,10 +649,12 @@ public class gdalinfo {
 				hLatLong = hProj.CloneGeogCS();
 
 			if (hLatLong != null) {
-				//CPLPushErrorHandler( gdalconstConstants.CPLQuietErrorHandler );
+				gdal.PushErrorHandler( "CPLQuietErrorHandler" );
 				hTransform = new CoordinateTransformation(hProj, hLatLong);
-				//CPLPopErrorHandler();
+				gdal.PopErrorHandler();
 				hLatLong.delete();
+				if (gdal.GetLastErrorMsg().indexOf("Unable to load PROJ.4 library") != -1)
+					hTransform = null;
 			}
 
 			if (hProj != null)
diff --git a/swig/java/apps/ogr2ogr.java b/swig/java/apps/ogr2ogr.java
index 4327e0f..40b4482 100644
--- a/swig/java/apps/ogr2ogr.java
+++ b/swig/java/apps/ogr2ogr.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2ogr.java 22027 2011-03-25 19:28:44Z rouault $
+ * $Id: ogr2ogr.java 23515 2011-12-10 21:14:02Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Java port of a simple client for translating between formats.
@@ -82,6 +82,14 @@ public class ogr2ogr
     static final int OGRNullFID = -1;
     static int nFIDToFetch = OGRNullFID;
 
+    static class GeomOperation
+    {
+        private GeomOperation() {}
+        public static GeomOperation NONE = new GeomOperation();
+        public static GeomOperation SEGMENTIZE = new GeomOperation();
+        public static GeomOperation SIMPLIFY_PRESERVE_TOPOLOGY = new GeomOperation();
+    }
+
 /************************************************************************/
 /*                                main()                                */
 /************************************************************************/
@@ -103,10 +111,11 @@ public class ogr2ogr
         String pszWHERE = null;
         Geometry poSpatialFilter = null;
         String pszSelect;
-        Vector papszSelFields = new Vector();
+        Vector papszSelFields = null;
         String pszSQLStatement = null;
         int    eGType = -2;
-        double dfMaxSegmentLength = 0;
+        GeomOperation eGeomOp = GeomOperation.NONE;
+        double dfGeomOpParam = 0;
         Vector papszFieldTypesToString = new Vector();
         boolean bDisplayProgress = false;
         ProgressCallback pfnProgress = null;
@@ -126,6 +135,8 @@ public class ogr2ogr
         boolean bExplodeCollections = false;
         String pszZField = null;
 
+        ogr.DontUseExceptions();
+
     /* -------------------------------------------------------------------- */
     /*      Register format(s).                                             */
     /* -------------------------------------------------------------------- */
@@ -276,12 +287,19 @@ public class ogr2ogr
             {
                 pszSelect = args[++iArg];
                 StringTokenizer tokenizer = new StringTokenizer(pszSelect, " ,");
+                papszSelFields = new Vector();
                 while(tokenizer.hasMoreElements())
                     papszSelFields.addElement(tokenizer.nextToken());
             }
+            else if( args[iArg].equalsIgnoreCase("-simplify") && iArg < args.length-1 )
+            {
+                eGeomOp = GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY;
+                dfGeomOpParam = new Double(args[++iArg]).doubleValue();
+            }
             else if( args[iArg].equalsIgnoreCase("-segmentize") && iArg < args.length-1 )
             {
-                dfMaxSegmentLength = new Double(args[++iArg]).doubleValue();
+                eGeomOp = GeomOperation.SEGMENTIZE;
+                dfGeomOpParam = new Double(args[++iArg]).doubleValue();
             }
             else if( args[iArg].equalsIgnoreCase("-fieldTypeToString") && iArg < args.length-1 )
             {
@@ -567,16 +585,7 @@ public class ogr2ogr
         {
             int                  iDriver;
     
-            for( iDriver = 0;
-                iDriver < ogr.GetDriverCount() && poDriver == null;
-                iDriver++ )
-            {
-                if( ogr.GetDriver(iDriver).GetName().equalsIgnoreCase(pszFormat) )
-                {
-                    poDriver = ogr.GetDriver(iDriver);
-                }
-            }
-    
+            poDriver = ogr.GetDriverByName(pszFormat);
             if( poDriver == null )
             {
                 System.err.println("Unable to find driver `" + pszFormat +"'." );
@@ -594,7 +603,35 @@ public class ogr2ogr
                 System.err.println( pszFormat + " driver does not support data source creation.");
                 System.exit( 1 );
             }
-    
+
+    /* -------------------------------------------------------------------- */
+    /*      Special case to improve user experience when translating        */
+    /*      a datasource with multiple layers into a shapefile. If the      */
+    /*      user gives a target datasource with .shp and it does not exist, */
+    /*      the shapefile driver will try to create a file, but this is not */
+    /*      appropriate because here we have several layers, so create      */
+    /*      a directory instead.                                            */
+    /* -------------------------------------------------------------------- */
+            if (poDriver.GetName().equalsIgnoreCase("ESRI Shapefile") &&
+                pszSQLStatement == null &&
+                (papszLayers.size() > 1 ||
+                 (papszLayers.size() == 0 && poDS.GetLayerCount() > 1)) &&
+                pszNewLayerName == null &&
+                (pszDestDataSource.endsWith(".shp") || pszDestDataSource.endsWith(".SHP")))
+            {
+                File f = new File(pszDestDataSource);
+                if (!f.exists())
+                {
+                    if (!f.mkdir())
+                    {
+                        System.err.println(
+                            "Failed to create directory " + pszDestDataSource + "\n" +
+                            "for shapefile datastore.");
+                        System.exit(1);
+                    }
+                }
+            }
+
     /* -------------------------------------------------------------------- */
     /*      Create the output data source.                                  */
     /* -------------------------------------------------------------------- */
@@ -669,7 +706,8 @@ public class ogr2ogr
 /*      single file shapefile and source has only one layer, and that   */
 /*      the layer name isn't specified                                  */
 /* -------------------------------------------------------------------- */
-                if (poDriver.GetName().equals("ESRI Shapefile") && pszNewLayerName == null)
+                if (poDriver.GetName().equalsIgnoreCase("ESRI Shapefile") &&
+                    pszNewLayerName == null)
                 {
                     File f = new File(pszDestDataSource);
                     if (f.exists() && f.listFiles() == null)
@@ -684,7 +722,7 @@ public class ogr2ogr
                 if( !TranslateLayer( poDS, poResultSet, poODS, papszLCO, 
                                     pszNewLayerName, bTransform, poOutputSRS,
                                     poSourceSRS, papszSelFields, bAppend, eGType,
-                                    bOverwrite, dfMaxSegmentLength, papszFieldTypesToString,
+                                    bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
                                     nCountLayerFeatures, poClipSrc, poClipDst, bExplodeCollections,
                                     pszZField, pszWHERE, pfnProgress ))
                 {
@@ -754,7 +792,8 @@ public class ogr2ogr
 /*      single file shapefile and source has only one layer, and that   */
 /*      the layer name isn't specified                                  */
 /* -------------------------------------------------------------------- */
-            if (poDriver.GetName().equals("ESRI Shapefile") && nLayerCount == 1 && pszNewLayerName == null)
+            if (poDriver.GetName().equalsIgnoreCase("ESRI Shapefile") &&
+                nLayerCount == 1 && pszNewLayerName == null)
             {
                 File f = new File(pszDestDataSource);
                 if (f.exists() && f.listFiles() == null)
@@ -778,7 +817,14 @@ public class ogr2ogr
                 Layer        poLayer = papoLayers[iLayer];
 
                 if( pszWHERE != null )
-                    poLayer.SetAttributeFilter( pszWHERE );
+                {
+                    if( poLayer.SetAttributeFilter( pszWHERE ) != ogr.OGRERR_NONE )
+                    {
+                        System.err.println("FAILURE: SetAttributeFilter(" + pszWHERE + ") failed.");
+                        if (!bSkipFailures)
+                            System.exit( 1 );
+                    }
+                }
 
                 if( poSpatialFilter != null )
                     poLayer.SetSpatialFilter( poSpatialFilter );
@@ -818,7 +864,7 @@ public class ogr2ogr
                 if( !TranslateLayer( poDS, poLayer, poODS, papszLCO, 
                                     pszNewLayerName, bTransform, poOutputSRS,
                                     poSourceSRS, papszSelFields, bAppend, eGType,
-                                    bOverwrite, dfMaxSegmentLength, papszFieldTypesToString,
+                                    bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
                                     panLayerCountFeatures[iLayer], poClipSrc, poClipDst, bExplodeCollections,
                                     pszZField, pszWHERE, pfnProgress) 
                     && !bSkipFailures )
@@ -854,6 +900,7 @@ public class ogr2ogr
                 "               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n" +
                 "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n" +
                 "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n" +
+                "               [-simplify tolerance]\n" +
                 // "               [-segmentize max_dist] [-fieldTypeToString All|(type1[,type2]*)]\n" +
                 "               [-fieldTypeToString All|(type1[,type2]*)] [-explodecollections]\n" +
                 "               dst_datasource_name src_datasource_name\n" +
@@ -880,6 +927,7 @@ public class ogr2ogr
                 " -skipfailures: skip features or layers that fail to convert\n" +
                 " -gt n: group n features per transaction (default 200)\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" +
                 //"                       Used to create intermediate points\n" +
                 " -dsco NAME=VALUE: Dataset creation option (format specific)\n" +
@@ -1064,7 +1112,8 @@ public class ogr2ogr
                             SpatialReference poSourceSRS,
                             Vector papszSelFields,
                             boolean bAppend, int eGType, boolean bOverwrite,
-                            double dfMaxSegmentLength,
+                            GeomOperation eGeomOp,
+                            double dfGeomOpParam,
                             Vector papszFieldTypesToString,
                             long nCountLayerFeatures,
                             Geometry poClipSrc,
@@ -1142,30 +1191,36 @@ public class ogr2ogr
     /* -------------------------------------------------------------------- */
     /*      Find the layer.                                                 */
     /* -------------------------------------------------------------------- */
-        int iLayer = -1;
-        poDstLayer = null;
 
         /* 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) */
         gdal.PushErrorHandler("CPLQuietErrorHandler");
-        poDstDS.GetLayerByName(pszNewLayerName);
+        poDstLayer = poDstDS.GetLayerByName(pszNewLayerName);
         gdal.PopErrorHandler();
         gdal.ErrorReset();
 
-        for( iLayer = 0; iLayer < poDstDS.GetLayerCount(); iLayer++ )
+        int iLayer = -1;
+        if( poDstLayer != null )
         {
-            Layer        poLayer = poDstDS.GetLayer(iLayer);
-    
-            if( poLayer != null 
-                && poLayer.GetLayerDefn().GetName().equalsIgnoreCase(pszNewLayerName) )
+            int nLayerCount = poDstDS.GetLayerCount();
+            for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
             {
-                poDstLayer = poLayer;
-                break;
+                Layer        poLayer = poDstDS.GetLayer(iLayer);
+
+                if( poLayer != null
+                    && poLayer.GetName().equals(poDstLayer.GetName()) )
+                {
+                    break;
+                }
             }
+
+            if (iLayer == nLayerCount)
+                /* shouldn't happen with an ideal driver */
+                poDstLayer = null;
         }
-        
+
     /* -------------------------------------------------------------------- */
     /*      If the user requested overwrite, and we have the layer in       */
     /*      question we need to delete it now so it will get recreated      */
@@ -1211,7 +1266,8 @@ public class ogr2ogr
                         eGType = ogr.wkbUnknown | n25DBit;
                     }
                 }
-                else if ( pszZField != null )
+
+                if ( pszZField != null )
                     eGType |= ogr.wkb25DBit;
             }
     
@@ -1267,7 +1323,7 @@ public class ogr2ogr
 
         FeatureDefn poDstFDefn = poDstLayer.GetLayerDefn();
 
-        if (papszSelFields.size() > 0 && !bAppend )
+        if (papszSelFields != null && !bAppend )
         {
             int  nDstFieldCount = 0;
             if (poDstFDefn != null)
@@ -1351,6 +1407,10 @@ public class ogr2ogr
                             break;
                         }
                     }
+
+                    if (pszZField != null && pszFieldName.equals(pszZField))
+                        bFieldRequested = true;
+
                     /* If source field not requested, add it to ignored files list */
                     if (!bFieldRequested)
                         papszIgnoredFields.addElement(pszFieldName);
@@ -1516,9 +1576,6 @@ public class ogr2ogr
                 if( bPreserveFID )
                     poDstFeature.SetFID( poFeature.GetFID() );
 
-                /*if (poDstFeature.GetGeometryRef() != null && dfMaxSegmentLength > 0)
-                    poDstFeature.GetGeometryRef().segmentize(dfMaxSegmentLength);*/
-
                 Geometry poDstGeometry = poDstFeature.GetGeometryRef();
                 if (poDstGeometry != null)
                 {
@@ -1531,7 +1588,28 @@ public class ogr2ogr
                     }
 
                     if (iSrcZField != -1)
+                    {
                         SetZ(poDstGeometry, poFeature.GetFieldAsDouble(iSrcZField));
+                        /* This will correct the coordinate dimension to 3 */
+                        Geometry poDupGeometry = poDstGeometry.Clone();
+                        poDstFeature.SetGeometryDirectly(poDupGeometry);
+                        poDstGeometry = poDupGeometry;
+                    }
+
+                    if (eGeomOp == GeomOperation.SEGMENTIZE)
+                    {
+                /*if (poDstFeature.GetGeometryRef() != null && dfGeomOpParam > 0)
+                    poDstFeature.GetGeometryRef().segmentize(dfGeomOpParam);*/
+                    }
+                    else if (eGeomOp == GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY && dfGeomOpParam > 0)
+                    {
+                        Geometry poNewGeom = poDstGeometry.SimplifyPreserveTopology(dfGeomOpParam);
+                        if (poNewGeom != null)
+                        {
+                            poDstFeature.SetGeometryDirectly(poNewGeom);
+                            poDstGeometry = poNewGeom;
+                        }
+                    }
 
                     if (poClipSrc != null)
                     {
diff --git a/swig/java/apps/ogrinfo.java b/swig/java/apps/ogrinfo.java
index cbad974..d011d33 100644
--- a/swig/java/apps/ogrinfo.java
+++ b/swig/java/apps/ogrinfo.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrinfo.java 16314 2009-02-13 20:18:32Z rouault $
+ * $Id: ogrinfo.java 23139 2011-09-29 19:52:45Z rouault $
  *
  * Name:     ogrinfo.java
  * Project:  GDAL SWIG Interface
@@ -60,6 +60,8 @@ public class ogrinfo
         String pszSQLStatement = null;
         String pszDialect = null;
 
+        ogr.DontUseExceptions();
+
 /* -------------------------------------------------------------------- */
 /*      Register format(s).                                             */
 /* -------------------------------------------------------------------- */
@@ -205,7 +207,13 @@ public class ogrinfo
             if( poResultSet != null )
             {
                 if( pszWHERE != null )
-                    poResultSet.SetAttributeFilter( pszWHERE );
+                {
+                    if( poResultSet.SetAttributeFilter( pszWHERE ) != ogr.OGRERR_NONE )
+                    {
+                        System.err.println("FAILURE: SetAttributeFilter(" + pszWHERE + ") failed.");
+                        return;
+                    }
+                }
     
                 ReportOnLayer( poResultSet, null, null );
                 poDS.ReleaseResultSet( poResultSet );
@@ -219,34 +227,61 @@ public class ogrinfo
     
         for( int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
         {
-            for( int iLayer = 0; iLayer < poDS.GetLayerCount(); iLayer++ )
+            if (papszLayers.size() == 0)
             {
-                Layer        poLayer = poDS.GetLayer(iLayer);
-    
-                if( poLayer == null )
-                {
-                    System.out.println( "FAILURE: Couldn't fetch advertised layer " + iLayer + "!");
-                    return;
-                }
-    
-                if( papszLayers.size() == 0 && !bAllLayers )
+/* -------------------------------------------------------------------- */
+/*      Process each data source layer.                                 */
+/* -------------------------------------------------------------------- */
+                for( int iLayer = 0; iLayer < poDS.GetLayerCount(); iLayer++ )
                 {
-                    System.out.print(
-                            (iLayer+1) + ": " + poLayer.GetLayerDefn().GetName() );
-    
-                    if( poLayer.GetLayerDefn().GetGeomType() != ogrConstants.wkbUnknown )
-                        System.out.print( " (" +
-                                ogr.GeometryTypeToName( 
-                                    poLayer.GetLayerDefn().GetGeomType()) + ")" );
-    
-                    System.out.println();
+                    Layer        poLayer = poDS.GetLayer(iLayer);
+
+                    if( poLayer == null )
+                    {
+                        System.out.println( "FAILURE: Couldn't fetch advertised layer " + iLayer + "!");
+                        return;
+                    }
+
+                    if (!bAllLayers)
+                    {
+                        System.out.print(
+                                (iLayer+1) + ": " + poLayer.GetLayerDefn().GetName() );
+
+                        if( poLayer.GetLayerDefn().GetGeomType() != ogrConstants.wkbUnknown )
+                            System.out.print( " (" +
+                                    ogr.GeometryTypeToName(
+                                        poLayer.GetLayerDefn().GetGeomType()) + ")" );
+
+                        System.out.println();
+                    }
+                    else
+                    {
+                        if( iRepeat != 0 )
+                            poLayer.ResetReading();
+
+                        ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
+                    }
                 }
-                else if( bAllLayers 
-                        || papszLayers.contains(poLayer.GetLayerDefn().GetName() ) )
+            }
+            else
+            {
+/* -------------------------------------------------------------------- */
+/*      Process specified data source layers.                           */
+/* -------------------------------------------------------------------- */
+                for(int i = 0; i < papszLayers.size(); i++)
                 {
+                    Layer poLayer = poDS.GetLayerByName((String)papszLayers.get(i));
+
+                    if( poLayer == null )
+                    {
+                        System.out.println( "FAILURE: Couldn't fetch requested layer " +
+                                            (String)papszLayers.get(i) + "!");
+                        return;
+                    }
+
                     if( iRepeat != 0 )
                         poLayer.ResetReading();
-    
+
                     ReportOnLayer( poLayer, pszWHERE, poSpatialFilter );
                 }
             }
@@ -279,7 +314,13 @@ public class ogrinfo
 /*      Set filters if provided.                                        */
 /* -------------------------------------------------------------------- */
         if( pszWHERE != null )
-            poLayer.SetAttributeFilter( pszWHERE );
+        {
+            if( poLayer.SetAttributeFilter( pszWHERE ) != ogr.OGRERR_NONE )
+            {
+                System.err.println("FAILURE: SetAttributeFilter(" + pszWHERE + ") failed.");
+                return;
+            }
+        }
     
         if( poSpatialFilter != null )
             poLayer.SetSpatialFilter( poSpatialFilter );
diff --git a/swig/java/apps/testgetpoints.java b/swig/java/apps/testgetpoints.java
new file mode 100644
index 0000000..b212c70
--- /dev/null
+++ b/swig/java/apps/testgetpoints.java
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * $Id: testgetpoints.java 22044 2011-03-26 14:47:20Z rouault $
+ *
+ * Name:     testgetpoints.java
+ * Project:  OGR Java Interface
+ * Purpose:  A sample app to test Geometry.GetPoints()
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, 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.ogr.Geometry;
+
+public class testgetpoints
+{
+    public static void showCoords(Geometry geom)
+    {
+        double[][] coords = geom.GetPoints();
+        for(int i = 0; i < coords.length; i++)
+        {
+            if (i > 0)
+                System.out.print(", ");
+            if (coords[i].length == 2)
+                System.out.print(coords[i][0] + " " + coords[i][1]);
+            else
+                System.out.print(coords[i][0] + " " + coords[i][1] + " " + coords[i][2]);
+        }
+        System.out.print("\n");
+    }
+
+    public static void showCoords(Geometry geom, int nCoordDimension)
+    {
+        double[][] coords = geom.GetPoints(nCoordDimension);
+        for(int i = 0; i < coords.length; i++)
+        {
+            if (i > 0)
+                System.out.print(", ");
+            if (coords[i].length == 2)
+                System.out.print(coords[i][0] + " " + coords[i][1]);
+            else
+                System.out.print(coords[i][0] + " " + coords[i][1] + " " + coords[i][2]);
+        }
+        System.out.print("\n");
+    }
+
+    public static void main(String[] args)
+    {
+        showCoords(Geometry.CreateFromWkt("LINESTRING(0 1,2 3)"));
+        showCoords(Geometry.CreateFromWkt("LINESTRING(0 1 2,3 4 5)"));
+        showCoords(Geometry.CreateFromWkt("LINESTRING(0 1,2 3)"), 3);
+        showCoords(Geometry.CreateFromWkt("LINESTRING(0 1 2,3 4 5)"), 2);
+    }
+}
\ No newline at end of file
diff --git a/swig/java/javadoc.java b/swig/java/javadoc.java
index 02d4c4d..f9611a1 100644
--- a/swig/java/javadoc.java
+++ b/swig/java/javadoc.java
@@ -1,5 +1,5 @@
 /* ***************************************************************************
-* $Id: javadoc.java 21370 2011-01-01 18:56:16Z rouault $
+* $Id: javadoc.java 23513 2011-12-10 21:12:59Z rouault $
 *
 * Project:  GDAL/OGR Java bindings
 * Purpose:  Documentation for the Java bindings
@@ -166,13 +166,13 @@ public class gdal:public static int PushErrorHandler()
  * action failed, but that normal recover mechanisms will be used or
  * CE_Fatal meaning that a fatal error has occured, and that Error()
  * should not return.  
- *
+ * <p>
  * The default behaviour of Error() is to report errors to stderr,
  * and to abort() after reporting a gdalconst.CE_Fatal error.  It is expected that
  * some applications will want to supress error reporting, and will want to
  * install a C++ exception, or longjmp() approach to no local fatal error
  * recovery.
- *
+ * <p>
  * Regardless of how application error handlers or the default error
  * handler choose to handle an error, the error number, and message will
  * be stored for recovery with gdal.GetLastErrorNo() and gdal.GetLastErrorMsg().
@@ -185,7 +185,7 @@ public class gdal:public static void Error(int msg_class, int err_code, String m
 
 /**
  * Pop error handler off stack.
- *
+ * <p>
  * Discards the current error handler on the error handler stack, and restores 
  * the one in use before the last gdal.PushErrorHandler() call.  This method
  * has no effect if there are no error handlers on the current threads error
@@ -195,7 +195,7 @@ public class gdal:public static void PopErrorHandler()
 
 /**
  * Erase any traces of previous errors.
- *
+ * <p>
  * This is normally used to ensure that an error which has been recovered
  * from does not appear to be still in play with high level functions.
  */
@@ -215,9 +215,9 @@ public class gdal:public static String EscapeString(byte[] byteArray, int scheme
  * Create memory "file" from a buffer.
  *
  * A virtual memory file is created from the passed buffer with the indicated filename. Under normal conditions the filename would need to be absolute and within the /vsimem/ portion of the filesystem.
- *
+ * <p>
  * The filename then can be used with GDAL and OGR drivers that uses the virtual file API.
- *
+ * <p>
  * To free the memory associated with the file, you must use Unlink(fileName), otherwise memory leaks will occur.
  *
  * @param fileName filename (should begin with "/vsimem/")
@@ -231,10 +231,10 @@ public class gdal:public static void FileFromMemBuffer(String fileName, byte[] b
 
 /**
  * Delete a file.
- *
+ * <p>
  * Deletes a file object from the file system. This method goes through the
  * VSIFileHandler virtualization and may work on unusual filesystems such as in memory.
- *
+ * <p>
  * Analog of the POSIX unlink() function.
  *
  * @param fileName the path of the file to be deleted.
@@ -292,7 +292,7 @@ public class gdal:public static String EscapeString(String str, int scheme)
 
 /**
  * Fetch the last error number.
- *
+ * <p>
  * This is the error number, not the error class.
  *
  * @return the error number of the last error to occur, or gdalconst.CPLE_None (0)
@@ -303,7 +303,7 @@ public class gdal:public static int GetLastErrorNo()
 
 /**
  * Fetch the last error type.
- *
+ * <p>
  * This is the error class, not the error number.
  *
  * @return the error number of the last error to occur, or gdalconst.CE_None (0)
@@ -313,7 +313,7 @@ public class gdal:public static int GetLastErrorType()
 
 /**
  * Get the last error message.
- *
+ * <p>
  * Fetches the last error message posted with CPLError(), that hasn't
  * been cleared by gdal.ErrorReset().
  *
@@ -324,7 +324,7 @@ public class gdal:public static String GetLastErrorMsg()
 
 /**
   * Set a configuration option for GDAL/OGR use.
-  *
+  * <p>
   * Those options are defined as a (key, value) couple. The value corresponding
   * to a key can be got later with the gdal.GetConfigOption() method.
   * <p>
@@ -348,7 +348,7 @@ public class gdal:public static void SetConfigOption(String key, String value)
 
 /**
   * Get the value of a configuration option.
-  * 
+  * <p>
   * The value is the value of a (key, value) option set with gdal.SetConfigOption().
   * If the given option was no defined with gdal.SetConfigOption(), it tries to find
   * it in environment variables.
@@ -364,7 +364,7 @@ public class gdal:public static String GetConfigOption(String key, String defaul
 
 /**
   * Get the value of a configuration option.
-  * 
+  * <p>
   * Same as below with defaultValue == null
   *
   * @see #GetConfigOption(String key, String defaultValue)
@@ -376,7 +376,7 @@ public class gdal:public static String GetConfigOption(String key)
 
 /**
  * Generate Geotransform from GCPs. 
- *
+ * <p>
  * Given a set of GCPs perform first order fit as a geotransform. 
  * <p>
  * Due to imprecision in the calculations the fit algorithm will often 
@@ -401,7 +401,7 @@ public class gdal:public static int GCPsToGeoTransform(GCP[] gcpArray, double[]
 
 /**
  * Generate Geotransform from GCPs. 
- *
+ * <p>
  * Same as below with bApproxOK == 0
  *
  * @see #GCPsToGeoTransform(GCP[] gcpArray, double[] outGeoTransform, int bApproxOK)
@@ -413,7 +413,7 @@ public class gdal:public static int GCPsToGeoTransform(GCP[] gcpArray, double[]
 
 /**
  * Compute optimal PCT for RGB image.
- *
+ * <p>
  * This function implements a median cut algorithm to compute an "optimal"
  * pseudocolor table for representing an input RGB image.  This PCT could
  * then be used with GDALDitherRGB2PCT() to convert a 24bit RGB image into
@@ -448,7 +448,7 @@ public class gdal:public static int ComputeMedianCutPCT(Band red, Band green, Ba
 
 /**
  * Compute optimal PCT for RGB image.
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, ProgressCallback callback)
@@ -460,7 +460,7 @@ public class gdal:public static int ComputeMedianCutPCT(Band red, Band green, Ba
 
 /**
  * 24bit to 8bit conversion with dithering.
- *
+ * <p>
  * This functions utilizes Floyd-Steinberg dithering in the process of 
  * converting a 24bit RGB image into a pseudocolored 8bit image using a
  * provided color table.  
@@ -488,7 +488,7 @@ public class gdal:public static int DitherRGB2PCT(Band red, Band green, Band blu
 
 /**
  * 24bit to 8bit conversion with dithering.
- *
+ * <p>
  * Same as below with callback == null
  * @see #DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, ProgressCallback callback)
  *
@@ -498,7 +498,7 @@ public class gdal:public static int DitherRGB2PCT(Band red, Band green, Band blu
 
 /**
  * Reproject image.
- *
+ * <p>
  * This is a convenience function utilizing the GDALWarpOperation class to
  * reproject an image from a source to a destination.  In particular, this
  * function takes care of establishing the transformation function to
@@ -532,7 +532,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
 
 /**
  * Reproject image.
- *
+ * <p>
  * Same as below with callback == null.
  * 
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
@@ -545,7 +545,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
 
 /**
  * Reproject image.
- *
+ * <p>
  * Same as below with maxError == 0.0 and callback == null.
  * 
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
@@ -556,7 +556,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
 
 /**
  * Reproject image.
- *
+ * <p>
  * Same as below with warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
  * 
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
@@ -567,7 +567,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
 
 /**
  * Reproject image.
- *
+ * <p>
  * Same as below with resampleAlg == gdalconst.GRA_NearestNeighbour, warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
  * 
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
@@ -578,7 +578,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
 
 /**
  * Reproject image.
- *
+ * <p>
  * Same as below with dst_wkt == null, resampleAlg == gdalconst.GRA_NearestNeighbour, warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
  * 
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
@@ -589,7 +589,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
 
 /**
  * Reproject image.
- *
+ * <p>
  * Same as below with src_wkt == null, dst_wkt == null, resampleAlg == gdalconst.GRA_NearestNeighbour, warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
  * 
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
@@ -600,7 +600,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
 
 /**
  * Compute the proximity of all pixels in the image to a set of pixels in the source image.
- *
+ * <p>
  * The following options are used to define the behavior of the function.  By
  * default all non-zero pixels in srcBand will be considered the
  * "target", and all proximities will be computed in pixels.  Note
@@ -643,7 +643,7 @@ public class gdal:public static int ComputeProximity(Band srcBand, Band proximit
 
 /**
  * Compute the proximity of all pixels in the image to a set of pixels in the source image.
- *
+ * <p>
  * Same as below with callback = null
  *
  * @see #ComputeProximity(Band srcBand, Band proximityBand, java.util.Vector options, ProgressCallback callback)
@@ -655,7 +655,7 @@ public class gdal:public static int ComputeProximity(Band srcBand, Band proximit
 
 /**
  * Compute the proximity of all pixels in the image to a set of pixels in the source image.
- *
+ * <p>
  * Same as below with options == null and callback == null
  *
  * @see #ComputeProximity(Band srcBand, Band proximityBand, java.util.Vector options, ProgressCallback callback)
@@ -667,7 +667,7 @@ public class gdal:public static int ComputeProximity(Band srcBand, Band proximit
 
 /**
  * Burn geometries from the specified layer into raster.
- *
+ * <p>
  * Rasterize all the geometric objects from a layer into a raster
  * dataset.
  * <p>
@@ -708,7 +708,7 @@ public class gdal:public static int RasterizeLayer(Dataset dataset, int[] bandNu
 
 /**
  * Burn geometries from the specified layer into raster.
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #RasterizeLayer(Dataset dataset, int[] bandNumbers, org.gdal.ogr.Layer layer, double[] burn_values, java.util.Vector options, ProgressCallback callback)
@@ -720,7 +720,7 @@ public class gdal:public static int RasterizeLayer(Dataset dataset, int[] bandNu
 
 /**
  * Burn geometries from the specified layer into raster.
- *
+ * <p>
  * Same as below with options == null and callback == null
  *
  * @see #RasterizeLayer(Dataset dataset, int[] bandNumbers, org.gdal.ogr.Layer layer, double[] burn_values, java.util.Vector options, ProgressCallback callback)
@@ -732,7 +732,7 @@ public class gdal:public static int RasterizeLayer(Dataset dataset, int[] bandNu
 
 /**
  * Burn geometries from the specified layer into raster.
- *
+ * <p>
  * Same as below with burn_values == null, options == null and callback == null
  *
  * @see #RasterizeLayer(Dataset dataset, int[] bandNumbers, org.gdal.ogr.Layer layer, double[] burn_values, java.util.Vector options, ProgressCallback callback)
@@ -743,7 +743,7 @@ public class gdal:public static int RasterizeLayer(Dataset dataset, int[] bandNu
 
 /**
  * Create polygon coverage from raster data.
- *
+ * <p>
  * This function creates vector polygons for all connected regions of pixels in
  * the raster sharing a common pixel value.  Optionally each polygon may be
  * labelled with the pixel value in an attribute.  Optionally a mask band
@@ -794,7 +794,7 @@ public class gdal:public static int Polygonize(Band srcBand, Band maskBand, org.
 
 /**
  * Create polygon coverage from raster data.
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #Polygonize(Band srcBand, Band maskBand, org.gdal.ogr.Layer outLayer, int iPixValField, java.util.Vector options, ProgressCallback callback)
@@ -805,7 +805,7 @@ public class gdal:public static int Polygonize(Band srcBand, Band maskBand, org.
 
 /**
  * Create polygon coverage from raster data.
- *
+ * <p>
  * Same as below with options == null and callback == null
  *
  * @see #Polygonize(Band srcBand, Band maskBand, org.gdal.ogr.Layer outLayer, int iPixValField, java.util.Vector options, ProgressCallback callback)
@@ -816,7 +816,7 @@ public class gdal:public static int Polygonize(Band srcBand, Band maskBand, org.
 
 /**
  * Fill selected raster regions by interpolation from the edges.
- *
+ * <p>
  * This algorithm will interpolate values for all designated 
  * nodata pixels (marked by zeros in maskBand).  For each pixel
  * a four direction conic search is done to find values to interpolate
@@ -850,7 +850,7 @@ public class gdal:public static int FillNodata(Band targetBand, Band maskBand, d
 
 /**
  * Fill selected raster regions by interpolation from the edges.
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, java.util.Vector options, ProgressCallback callback)
@@ -861,7 +861,7 @@ public class gdal:public static int FillNodata(Band targetBand, Band maskBand, d
 
 /**
  * Fill selected raster regions by interpolation from the edges.
- *
+ * <p>
  * Same as below with options == null and callback == null
  *
  * @see #FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, java.util.Vector options, ProgressCallback callback)
@@ -872,7 +872,7 @@ public class gdal:public static int FillNodata(Band targetBand, Band maskBand, d
 
 /** 
  * Removes small raster polygons. 
- *
+ * <p>
  * The function removes raster polygons smaller than a provided
  * threshold size (in pixels) and replaces replaces them with the pixel value 
  * of the largest neighbour polygon.  
@@ -919,7 +919,7 @@ public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Ban
 
 /**
  * Removes small raster polygons. 
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness, java.util.Vector options, ProgressCallback callback)
@@ -930,7 +930,7 @@ public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Ban
 
 /**
  * Removes small raster polygons. 
- *
+ * <p>
  * Same as below with options == null and callback == null
  *
  * @see #SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness, java.util.Vector options, ProgressCallback callback)
@@ -941,7 +941,7 @@ public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Ban
 
 /**
  * Removes small raster polygons. 
- *
+ * <p>
  * Same as below with connectedness == 4, options == null and callback == null
  *
  * @see #SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness, java.util.Vector options, ProgressCallback callback)
@@ -952,7 +952,7 @@ public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Ban
 
 /**
  * Generate downsampled overviews.
- *
+ * <p>
  * This function will generate one or more overview images from a base
  * image using the requested downsampling algorithm.  It's primary use
  * is for generating overviews via Dataset.<a href="Dataset.html#BuildOverviews(java.lang.String, int[], org.gdal.gdal.ProgressCallback)">BuildOverviews()</a>, but it
@@ -979,7 +979,7 @@ public class gdal:public static int RegenerateOverviews(Band srcBand, Band[] ove
 
 /**
  * Generate downsampled overviews.
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #RegenerateOverviews(Band srcBand, Band[] overviewBands, String resampling, ProgressCallback callback)
@@ -990,7 +990,7 @@ public class gdal:public static int RegenerateOverviews(Band srcBand, Band[] ove
 
 /**
  * Generate downsampled overviews.
- *
+ * <p>
  * Same as below with resampling == "AVERAGE" and callback == null
  *
  * @see #RegenerateOverviews(Band srcBand, Band[] overviewBands, String resampling, ProgressCallback callback)
@@ -1001,7 +1001,7 @@ public class gdal:public static int RegenerateOverviews(Band srcBand, Band[] ove
 
 /**
  * Generate downsampled overview.
- *
+ * <p>
  * Same as below for a unique overview band
  *
  * @see #RegenerateOverviews(Band srcBand, Band[] overviewBands, String resampling, ProgressCallback callback)
@@ -1012,7 +1012,7 @@ public class gdal:public static int RegenerateOverview(Band srcBand, Band overvi
 
 /**
  * Generate downsampled overview.
- *
+ * <p>
  * Same as below for a unique overview band and callback == null
  *
  * @see #RegenerateOverviews(Band srcBand, Band[] overviewBands, String resampling, ProgressCallback callback)
@@ -1023,7 +1023,7 @@ public class gdal:public static int RegenerateOverview(Band srcBand, Band overvi
 
 /**
  * Generate downsampled overview.
- *
+ * <p>
  * Same as below for a unique overview band, resampling == "AVERAGE" and callback == null
  *
  * @see #RegenerateOverviews(Band srcBand, Band[] overviewBands, String resampling, ProgressCallback callback)
@@ -1035,7 +1035,7 @@ public class gdal:public static int RegenerateOverview(Band srcBand, Band overvi
 
 /**
  * Create virtual warped dataset automatically.
- *
+ * <p>
  * This function will create a warped virtual file representing the 
  * input image warped into the target coordinate system.  A GenImgProj
  * transformation is created to accomplish any required GCP/Geotransform
@@ -1075,7 +1075,7 @@ public class gdal:public static Dataset AutoCreateWarpedVRT(Dataset src_ds, Stri
 
 /**
  * Create virtual warped dataset automatically.
- *
+ * <p>
  * Same as below with maxError == 0.0
  *
  * @see #AutoCreateWarpedVRT(Dataset src_ds, String src_wkt, String dst_wkt, int eResampleAlg, double maxError)
@@ -1086,7 +1086,7 @@ public class gdal:public static Dataset AutoCreateWarpedVRT(Dataset src_ds, Stri
 
 /**
  * Create virtual warped dataset automatically.
- *
+ * <p>
  * Same as below with eResampleAlg == gdalconst.GRA_NearestNeighbour and maxError == 0.0
  *
  * @see #AutoCreateWarpedVRT(Dataset src_ds, String src_wkt, String dst_wkt, int eResampleAlg, double maxError)
@@ -1097,7 +1097,7 @@ public class gdal:public static Dataset AutoCreateWarpedVRT(Dataset src_ds, Stri
 
 /**
  * Create virtual warped dataset automatically.
- *
+ * <p>
  * Same as below with dst_wkt == null, eResampleAlg == gdalconst.GRA_NearestNeighbour and maxError == 0.0
  *
  * @see #AutoCreateWarpedVRT(Dataset src_ds, String src_wkt, String dst_wkt, int eResampleAlg, double maxError)
@@ -1108,7 +1108,7 @@ public class gdal:public static Dataset AutoCreateWarpedVRT(Dataset src_ds, Stri
 
 /**
  * Create virtual warped dataset automatically.
- *
+ * <p>
  * Same as below with src_wkt == null, dst_wkt == null, eResampleAlg == gdalconst.GRA_NearestNeighbour and maxError == 0.0
  *
  * @see #AutoCreateWarpedVRT(Dataset src_ds, String src_wkt, String dst_wkt, int eResampleAlg, double maxError)
@@ -1119,7 +1119,7 @@ public class gdal:public static Dataset AutoCreateWarpedVRT(Dataset src_ds)
 
 /**
  * Get runtime version information.
- *
+ * <p>
  * Available request values:
  * <ul>
  * <li> "VERSION_NUM": Returns GDAL_VERSION_NUM formatted as a string.  ie. "1170"
@@ -1149,7 +1149,7 @@ public class gdal:public static String VersionInfo()
 
 /**
  * Register all known configured GDAL drivers.
- *
+ * <p>
  * This function will drive any of the following that are configured into
  * GDAL.  Many others as well that haven't been updated in this
  * documentation (see <a href="http://gdal.org/formats_list.html">full list</a>):
@@ -1177,7 +1177,7 @@ public class gdal:public static void AllRegister()
 
 /**
  * Get maximum cache memory.
- *
+ * <p>
  * Gets the maximum amount of memory available to the GDALRasterBlock
  * caching system for caching GDAL read/write imagery. 
  *
@@ -1187,7 +1187,7 @@ public class gdal:public static int GetCacheMax()
 
 /**
  * Set maximum cache memory.
- *
+ * <p>
  * This function sets the maximum amount of memory that GDAL is permitted
  * to use for GDALRasterBlock caching.
  *
@@ -1197,7 +1197,7 @@ public class gdal:public static void SetCacheMax(int newSize)
 
 /**
  * Get cache memory used.
- *
+ * 
  * @return the number of bytes of memory currently in use by the 
  * GDALRasterBlock memory caching.
  */
@@ -1206,7 +1206,7 @@ public class gdal:public static int GetCacheUsed()
 
 /**
  * Get data type size in bits.
- *
+ * <p>
  * Returns the size of a a GDT_* type <b>in bits</b>, not bytes!
  *
  * @param eDataType type, such as gdalconst.GDT_Byte. 
@@ -1225,7 +1225,7 @@ public class gdal:public static int DataTypeIsComplex(int eDataType)
 
 /**
  * Get name of data type.
- *
+ * <p>
  * Returns a symbolic name for the data type.  This is essentially the
  * the enumerated item name with the GDT_ prefix removed.  So gdalconst.GDT_Byte returns
  * "Byte". These strings are useful for reporting
@@ -1238,7 +1238,7 @@ public class gdal:public static String GetDataTypeName(int eDataType)
 
 /**
  * Get data type by symbolic name.
- *
+ * <p>
  * Returns a data type corresponding to the given symbolic name. This
  * function is opposite to the gdal.GetDataTypeName().
  *
@@ -1250,7 +1250,7 @@ public class gdal:public static int GetDataTypeByName(String dataTypeName)
 
 /**
  * Get name of color interpretation.
- *
+ * <p>
  * Returns a symbolic name for the color interpretation.  This is derived from
  * the enumerated item name with the GCI_ prefix removed, but there are some
  * variations. So GCI_GrayIndex returns "Gray" and GCI_RedBand returns "Red".
@@ -1265,7 +1265,7 @@ public class gdal:public static String GetColorInterpretationName(int eColorInte
 
 /**
  * Get name of palette interpretation.
- *
+ * <p>
  * Returns a symbolic name for the palette interpretation.  This is the
  * the enumerated item name with the GPI_ prefix removed.  So GPI_Gray returns
  * "Gray".  The returned strings are static strings and should not be modified
@@ -1303,7 +1303,7 @@ public class gdal:public static Driver GetDriver(int iDriver)
 
 /**
  * Open a raster file as a Dataset object.
- *
+ * <p>
  * This function will try to open the passed file, or virtual dataset
  * name by invoking the Open method of each registered Driver in turn. 
  * The first successful open will result in a returned dataset.  If all
@@ -1328,7 +1328,7 @@ public class gdal:public static Dataset Open(String name, int eAccess)
 
 /**
  * Open a raster file as a Dataset object.
- *
+ * <p>
  * Same as below with eAccess == gdalconst.GA_ReadOnly
  *
  * @see #Open(String name, int eAccess)
@@ -1339,7 +1339,7 @@ public class gdal:public static Dataset Open(String name)
 
 /**
  * Open a raster file as a GDALDataset.
- *
+ * <p>
  * This function works the same as gdal.Open(), but allows the sharing of
  * GDALDataset handles for a dataset with other callers to gdal.OpenShared().
  * <p>
@@ -1363,7 +1363,7 @@ public class gdal:public static Dataset OpenShared(String name, int eAccess)
 
 /**
  * Open a raster file as a Dataset object.
- *
+ * <p>
  * Same as below with eAccess == gdalconst.GA_ReadOnly
  *
  * @see #OpenShared(String name, int eAccess)
@@ -1375,7 +1375,7 @@ public class gdal:public static Dataset OpenShared(String name)
 
 /**
  * Identify the driver that can open a raster file.
- *
+ * <p>
  * This function will try to identify the driver that can open the passed file
  * name by invoking the Identify method of each registered Driver in turn. 
  * The first driver that successful identifies the file name will be returned.
@@ -1385,7 +1385,7 @@ public class gdal:public static Dataset OpenShared(String name)
  * file system machinery, it is possible to give an optional list of files.
  * This is the list of all files at the same level in the file system as the
  * target file, including the target file. The filenames will not include any
- * path components, are an essentially just the output of CPLReadDir() on the
+ * path components, are an essentially just the output of ReadDir() on the
  * parent directory. If the target object does not have filesystem semantics
  * then the file list should be null.
  *
@@ -1403,7 +1403,7 @@ public class gdal:public static Driver IdentifyDriver(String name, java.util.Vec
 
 /**
  * Identify the driver that can open a raster file.
- *
+ * <p>
  * Same as below with fileList == null
  *
  * @see #IdentifyDriver(String name, java.util.Vector fileList)
@@ -1414,12 +1414,12 @@ public class gdal:public static Driver IdentifyDriver(String name)
 
 /**
  * Parse an XML string into tree form.
- *
+ * <p>
  * The passed document is parsed into a  XMLNode tree representation. 
  * If the document is not well formed XML then null is returned, and errors
  * are reported via CPLError().  No validation beyond wellformedness is
  * done.
- *
+ * <p>
  * If the document has more than one "root level" element then those after the 
  * first will be attached to the first as siblings (via the psNext pointers)
  * even though there is no common parent.  A document with no XML structure
@@ -1436,7 +1436,7 @@ public class gdal:public static XMLNode ParseXMLString(String xmlString)
 
 /**
  * Convert tree into string document.
- *
+ * <p>
  * This function converts a XMLNode tree representation of a document
  * into a flat string representation.  White space indentation is used
  * visually preserve the tree structure of the document.
@@ -1451,7 +1451,7 @@ public class gdal:public static String SerializeXMLTree(XMLNode xmlnode)
 
 /**
  * Apply GeoTransform to x/y coordinate.
- *
+ * <p>
  * Applies the following computation, converting a (pixel,line) coordinate
  * into a georeferenced (geo_x,geo_y) location.
  * <pre>
@@ -1471,7 +1471,7 @@ public class gdal:public static void ApplyGeoTransform(double[] padfGeoTransform
 
 /**
  * Invert Geotransform.
- *
+ * <p>
  * This function will invert a standard 3x2 set of GeoTransform coefficients.
  * This converts the equation from being pixel to geo to being geo to pixel.
  *
@@ -1486,7 +1486,7 @@ public class gdal:public static int InvGeoTransform(double[] gt_in, double[] gt_
 
 /**
  * Invert Geotransform.
- *
+ * <p>
  * This function will invert a standard 3x2 set of GeoTransform coefficients.
  * This converts the equation from being pixel to geo to being geo to pixel.
  *
@@ -1501,6 +1501,87 @@ public class gdal:public static double[] InvGeoTransform(double[] gt_in)
 
 @hide public class gdal:public static int HasThreadSupport()
 
+
+/**
+ * Create a directory.
+ * <p>
+ * Create a new directory with the indicated mode.  The mode is ignored
+ * on some platforms.  A reasonable default mode value would be 0666.
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ * <p>
+ * Analog of the POSIX mkdir() function.
+ *
+ * @param path the path to the directory to create.
+ * @param mode the permissions mode.
+ *
+ * @return 0 on success or -1 on an error.
+ *
+ * @since Java bindings 1.8.0
+ */
+public class gdal:public static int Mkdir(String path, int mode)
+
+/**
+ * Rename a file.
+ * <p>
+ * Renames a file object in the file system.  It should be possible
+ * to rename a file onto a new filesystem, but it is safest if this
+ * function is only used to rename files that remain in the same directory.
+ * <p>
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ * <p>
+ * Analog of the POSIX rename() function.
+ *
+ * @param oldpath the name of the file to be renamed.
+ * @param newpath the name the file should be given.
+ *
+ * @return 0 on success or -1 on an error.
+ *
+ * @since Java bindings 1.8.0
+ */
+
+public class gdal:public static int Rename( String oldpath, String newpath )
+
+/**
+ * Delete a directory.
+ * <p>
+ * Deletes a directory object from the file system.  On some systems
+ * the directory must be empty before it can be deleted.
+ * <p>
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ * <p>
+ * Analog of the POSIX rmdir() function.
+ *
+ * @param path the path of the directory to be deleted.
+ *
+ * @return 0 on success or -1 on an error.
+ *
+ * @since Java bindings 1.8.0
+ */
+
+public class gdal:public static int Rmdir(String path)
+
+/**
+ * Read names in a directory.
+ * <p>
+ * This function abstracts access to directory contains.  It returns a
+ * list of strings containing the names of files, and directories in this
+ * directory.
+ * <p>
+ * Note that no error is issued via CPLError() if the directory path is
+ * invalid, though null is returned.
+ *
+ * @param path the relative, or absolute path of a directory to read.
+ * @return The list of entries in the directory, or null if the directory
+ * doesn't exist.
+ *
+ * @since Java bindings 1.7.0
+ */
+
+public class gdal:public static java.util.Vector ReadDir(String path)
+
 /* Class ColorTable */
 
 /**
@@ -1513,7 +1594,7 @@ public class ColorTable
 
 /**
  * Construct a new color table.
- *
+ * <p>
  * Same as below with ePaletteInterpretation == gdalconst.GPI_RGB
  *
  * @see #ColorTable(int ePaletteInterpretation)
@@ -1537,7 +1618,7 @@ public class ColorTable:public ColorTable Clone()
 
 /**
  * Create color ramp.
- *
+ * <p>
  * Automatically creates a color ramp from one color entry to another. It can be called several times to create multiples ramps in the same color table.
  *
  * @param nStartIndex 	index to start the ramp on the color table [0..255]
@@ -1565,7 +1646,7 @@ public class ColorTable:public int GetCount()
 
 /**
  * Fetch palette interpretation.
- *
+ * <p>
  * The returned value is used to interprete the values in the GDALColorEntry.
  *
  * @return palette interpretation enumeration value, usually gdalconst.GPI_RGB. 
@@ -1574,9 +1655,9 @@ public class ColorTable:public int GetPaletteInterpretation()
 
 /**
  * Set entry in color table.
- *
+ * <p>
  * The passed in entry must match the color interpretation of the table to which it is being assigned.
- *
+ * <p>
  * The table is grown as needed to hold the supplied offset.
  *
  * @param entry entry offset from zero to GetCount()-1.
@@ -1605,10 +1686,10 @@ public class Dataset
 
 /**
  * Add a band to a dataset.
- *
+ * <p>
  * This method will add a new band to the dataset if the underlying format
  * supports this action.  Except VRT and MEM drivers, most formats do not.
- *
+ * <p>
  * Note that the new Band object is not returned.  It may be fetched
  * after successful completion of the method by calling 
  * ds.GetRasterBand(ds.GetRasterCount()) as the newest
@@ -1625,7 +1706,7 @@ public class Dataset:public int AddBand(int datatype, java.util.Vector options)
 
 /**
  * Add a band to a dataset.
- *
+ * <p>
  * Same as below with options == null
  *
  * @see #AddBand(int datatype, java.util.Vector options)
@@ -1636,7 +1717,7 @@ public class Dataset:public int AddBand(int datatype)
 
 /**
  * Add a band to a dataset.
- *
+ * <p>
  * Same as below with datatype == gdalconst.GDT_Byte and options == null
  *
  * @see #AddBand(int datatype, java.util.Vector options)
@@ -1648,7 +1729,7 @@ public class Dataset:public int AddBand()
 
 /**
  * Build raster overview(s).
- *
+ * <p>
  * If the operation is unsupported for the indicated dataset, then 
  * gdalconst.CE_Failure is returned, and gdal.GetLastErrorNo() will return 
  * gdalconst.CPLE_NotSupported.
@@ -1675,7 +1756,7 @@ public class Dataset:public int BuildOverviews(String resampling, int[] overview
 
 /**
  * Build raster overview(s).
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #BuildOverviews(String resampling, int[] overviewlist, ProgressCallback callback)
@@ -1684,7 +1765,7 @@ public class Dataset:public int BuildOverviews(String resampling, int[] overview
 
 /**
  * Build raster overview(s).
- *
+ * <p>
  * Same as below with resampling == "NEAREST" and callback == null
  *
  * @see #BuildOverviews(String resampling, int[] overviewlist, ProgressCallback callback)
@@ -1695,7 +1776,7 @@ public class Dataset:public int BuildOverviews(int[] overviewlist)
 
 /**
  * Build raster overview(s).
- *
+ * <p>
  * Same as below with resampling == "NEAREST"
  *
  * @see #BuildOverviews(String resampling, int[] overviewlist, ProgressCallback callback)
@@ -1706,7 +1787,7 @@ public class Dataset:public int BuildOverviews(int[] overviewlist, ProgressCallb
 
 /**
  * Adds a mask band to the current band.
- *
+ * <p>
  * The default implementation of the CreateMaskBand() method is implemented
  * based on similar rules to the .ovr handling implemented using the
  * GDALDefaultOverviews object. A TIFF file with the extension .msk will
@@ -1726,7 +1807,7 @@ public class Dataset:public int CreateMaskBand(int nFlags)
 
 /**
   * Frees the native resource associated to a Dataset object and close the file.
-  *
+  * <p>
   * This method will delete the underlying C++ object. After it has been called,
   * all native resources will have been destroyed, so it will be illegal (and likely to
   * cause JVM crashes) to use any method on this object or any derived objects,
@@ -1740,7 +1821,7 @@ public class Dataset:public void delete()
 
 /**
  * Flush all write cached data to disk.
- *
+ * <p>
  * Any raster (or other GDAL) data written via GDAL calls, but buffered
  * internally will be written to disk.
  * <p>
@@ -1761,7 +1842,7 @@ public class Dataset:public void FlushCache()
 public class Dataset:public Driver GetDriver()
 
 /**
- *  Fetch a band object for a dataset.
+ * Fetch a band object for a dataset.
  *
  * @param nBandId the index number of the band to fetch, from 1 to
                   GetRasterCount().
@@ -1771,11 +1852,11 @@ public class Dataset:public Band GetRasterBand(int nBandId)
 
 /**
  * Fetch the projection definition string for this dataset.
- *
+ * <p>
  * The returned string defines the projection coordinate system of the
  * image in OpenGIS WKT format.  It should be suitable for use with the 
  * OGRSpatialReference class.
- *
+ * <p>
  * When a projection definition is not available an empty (but not null)
  * string is returned.
  *
@@ -1787,11 +1868,11 @@ public class Dataset:public String GetProjection()
 
 /**
  * Fetch the projection definition string for this dataset.
- *
+ * <p>
  * The returned string defines the projection coordinate system of the
  * image in OpenGIS WKT format.  It should be suitable for use with the 
  * OGRSpatialReference class.
- *
+ * <p>
  * When a projection definition is not available an empty (but not null)
  * string is returned.
  *
@@ -1804,7 +1885,7 @@ public class Dataset:public String GetProjectionRef()
 
 /**
  * Set the projection reference string for this dataset.
- *
+ * <p>
  * The string should be in OGC WKT or PROJ.4 format.  An error may occur
  * because of incorrectly specified projection strings, because the dataset
  * is not writable, or because the dataset does not support the indicated
@@ -1819,7 +1900,7 @@ public class Dataset:public int SetProjection(String projection)
 
 /**
  * Fetch the affine transformation coefficients.
- *
+ * <p>
  * Fetches the coefficients for transforming between pixel/line (P,L) raster
  * space, and projection coordinates (Xp,Yp) space.
  * <p>
@@ -1852,7 +1933,7 @@ public class Dataset:public void GetGeoTransform(double[] geoTransformArray)
 
 /**
  * Fetch the affine transformation coefficients.
- *
+ * <p>
  * Same as below, except the geotransform array is returned by the method
  *
  * @see #GetGeoTransform(double[] geoTransformArray)
@@ -1866,7 +1947,7 @@ public class Dataset:public double[] GetGeoTransform()
 
 /**
  * Set the affine transformation coefficients.
- *
+ * <p>
  * See <a href="#GetGeoTransform(double[])">#GetGeoTransform()</a> for details on the meaning of the geoTransformArray
  * coefficients.
  *
@@ -1882,7 +1963,7 @@ public class Dataset:public int SetGeoTransform(double[] geoTransformArray)
 
 /**
  * Fetch files forming dataset.
- *
+ * <p>
  * Returns a list of files believed to be part of this dataset.  If it returns
  * an empty list of files it means there is believed to be no local file
  * system files associated with the dataset (for instance a virtual dataset).
@@ -1903,7 +1984,7 @@ public class Dataset:public int GetGCPCount()
 
 /**
  * Get output projection for GCPs. 
- *
+ * <p>
  * The projection string follows the normal rules from <a href="#GetProjectionRef()">GetProjectionRef()</a>.
  * 
  * @return projection string or "" if there are no GCPs. 
@@ -1912,7 +1993,7 @@ public class Dataset:public String GetGCPProjection()
 
 /**
  * Fetch GCPs.
- *
+ * <p>
  * Add to the provided vector the GCPs of the dataset
  *
  * @param gcpVector non null Vector object
@@ -1931,7 +2012,7 @@ public class Dataset:public java.util.Vector GetGCPs()
 
 /**
  * Assign GCPs.
- *
+ * <p>
  * This method assigns the passed set of GCPs to this dataset, as well as
  * setting their coordinate system.  Internally copies are made of the
  * coordinate system and list of points, so the caller remains resposible for
@@ -2003,7 +2084,7 @@ public class Dataset:public int GetRasterCount()
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * This method allows reading a region of one or more Band's from
  * this dataset into a buffer. It automatically takes care of data type
  * translation if the data type (buf_type) of the buffer is different than
@@ -2079,7 +2160,7 @@ public class Dataset:public int ReadRaster_Direct(int xoff, int yoff, int xsize,
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #ReadRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2090,7 +2171,7 @@ public class Dataset:public int ReadRaster_Direct(int xoff, int yoff, int xsize,
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * This method allows reading a region of one or more Band's from
  * this dataset into a buffer. It automatically takes care of data type
  * translation if the data type (buf_type) of the buffer is different than
@@ -2162,7 +2243,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2185,7 +2266,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, short[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2196,7 +2277,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
  *
  * @since Java bindings 1.7.0
@@ -2208,7 +2289,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, int[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2231,7 +2312,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2254,7 +2335,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 
 /**
  * Read a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2265,7 +2346,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 
 /**
  * Write a region of image data from multiple bands.
- *
+ * <p>
  * This method allows writing data from a buffer into a region 
  * of the Band's.  It automatically takes care of data type
  * translation if the data type (buf_type) of the buffer is different than
@@ -2341,7 +2422,7 @@ public class Dataset:public int WriteRaster_Direct(int xoff, int yoff, int xsize
 
 /**
  * Write a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #WriteRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2353,7 +2434,7 @@ public class Dataset:public int WriteRaster_Direct(int xoff, int yoff, int xsize
 
 /**
  * Write a region of image data from multiple bands.
- *
+ * <p>
  * This method allows writing data from a buffer into a region 
  * of the Band's.  It automatically takes care of data type
  * translation if the data type (buf_type) of the buffer is different than
@@ -2424,7 +2505,7 @@ public class Dataset:public int WriteRaster(int xoff, int yoff, int xsize, int y
 
 /**
  * Write a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2505,7 +2586,7 @@ public class Dataset:public int WriteRaster(int xoff, int yoff, int xsize, int y
 
 /**
  * Write a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2532,7 +2613,7 @@ public class Dataset:public int WriteRaster(int xoff, int yoff, int xsize, int y
 
 /**
  * Write a region of image data from multiple bands.
- *
+ * <p>
  * Same as below with nPixelSpace == 0, nLineSpace == 0 and nBandSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int[] band_list, int nPixelSpace, int nLineSpace, int nBandSpace)
@@ -2552,7 +2633,7 @@ public class Dataset:public int WriteRaster(int xoff, int yoff, int xsize, int y
 
 /**
  * Class Band is an uninstanciable class providing various methods to access a single raster band (or channel).
- *
+ * 
  * <p>
  * The Band class is a binding for the C++ <a href="http://gdal.org/classGDALRasterBand.html">GDALRasterBand</a> class.
  * <p>
@@ -2596,7 +2677,7 @@ public class Band:public void delete()
 
 /**
  * Compute checksum for image region. 
- *
+ * <p>
  * Computes a 16bit (0-65535) checksum from a region of raster data on the raster band.
  * Floating point data is converted to 32bit integer 
  * so decimal portions of such raster data will not affect the checksum.
@@ -2613,7 +2694,7 @@ public class Band:public int Checksum(int xoff, int yoff, int xsize, int ysize)
 
 /**
  * Compute checksum for while image.
- *
+ * <p>
  * Computes a 16bit (0-65535) checksum from data on the raster band.
  * Floating point data is converted to 32bit integer 
  * so decimal portions of such raster data will not affect the checksum.
@@ -2635,7 +2716,7 @@ public class Band:public void ComputeBandStats(double[] meanAndStdDevArray, int
 
 /**
  * Compute mean and standard deviation values.
- *
+ * <p>
  * Same as below with samplestep == 1
  *
  * @see #ComputeBandStats(double[] meanAndStdDevArray, int samplestep)
@@ -2645,7 +2726,7 @@ public class Band:public void ComputeBandStats(double[] meanAndStdDevArray)
 
 /**
  * Compute the min/max values for a band.
- * 
+ * <p>
  * If approximate is OK, then the band's GetMinimum()/GetMaximum() will
  * be trusted.  If it doesn't work, a subsample of blocks will be read to
  * get an approximate min/max.  If the band has a nodata value it will
@@ -2662,7 +2743,7 @@ public class Band:public void ComputeRasterMinMax(double[] minMaxArray, int appr
 
 /**
  * Compute the min/max values for a band.
- * 
+ * <p>
  * Same as below with approx_ok == 0
  *
  * @see #ComputeRasterMinMax(double[] minMaxArray, int approx_ok)
@@ -2672,7 +2753,7 @@ public class Band:public void ComputeRasterMinMax(double[] minMaxArray)
 
 /**
  * Compute image statistics. 
- *
+ * <p>
  * Returns the minimum, maximum, mean and standard deviation of all
  * pixel values in this band.  If approximate statistics are sufficient,
  * the approx_ok flag can be set to true in which case overviews, or a
@@ -2704,7 +2785,7 @@ public class Band:public int ComputeStatistics(boolean approx_ok, double[] min,
 
 /**
  * Compute image statistics. 
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #ComputeStatistics(boolean approx_ok, double[] min, double[] max, double[] mean, double[] stddev, ProgressCallback callback)
@@ -2717,7 +2798,7 @@ public class Band:public int ComputeStatistics(boolean approx_ok, double[] min,
 
 /**
  * Compute image statistics. 
- *
+ * <p>
  * Same as below with mean == null, stddev == null and callback == null
  *
  * @see #ComputeStatistics(boolean approx_ok, double[] min, double[] max, double[] mean, double[] stddev, ProgressCallback callback)
@@ -2730,7 +2811,7 @@ public class Band:public int ComputeStatistics(boolean approx_ok, double[] min,
 
 /**
  * Compute image statistics. 
- *
+ * <p>
  * Same as below with min == null, max == null, mean == null, stddev == null and callback == null
  *
  * @see #ComputeStatistics(boolean approx_ok, double[] min, double[] max, double[] mean, double[] stddev, ProgressCallback callback)
@@ -2741,7 +2822,7 @@ public class Band:public int ComputeStatistics(boolean approx_ok)
 
 /**
  * Adds a mask band to the current band.
- *
+ * <p>
  * The default implementation of the CreateMaskBand() method is implemented
  * based on similar rules to the .ovr handling implemented using the
  * GDALDefaultOverviews object. A TIFF file with the extension .msk will
@@ -2761,7 +2842,7 @@ public class Band:public int CreateMaskBand(int nFlags)
 
 /** 
  * Fill this band with a constant value.
- *
+ * <p>
  * GDAL makes no guarantees
  * about what values pixels in newly created files are set to, so this
  * method can be used to clear a band to a specified "default" value.
@@ -2779,7 +2860,7 @@ public class Band:public int Fill(double real_fill, double imag_fill)
 
 /** 
  * Fill this band with a constant value.
- *
+ * <p>
  * Same as below with image_fill == 0
  *
  * @see #Fill(double real_fill, double imag_fill)
@@ -2790,7 +2871,7 @@ public class Band:public int Fill(double real_fill)
 
 /**
  * Flush raster data cache.
- *
+ * <p>
  * This call will recover memory used to cache data blocks for this raster
  * band, and ensure that new requests are referred to the underlying driver.
  */
@@ -2798,7 +2879,7 @@ public class Band:public void FlushCache()
 
 /**
  * Fetch the band number.
- *
+ * <p>
  * This method returns the band that this Band object represents
  * within its dataset.  This method may return a value of 0 to indicate
  * Band objects without an apparently relationship to a dataset,
@@ -2812,7 +2893,7 @@ public class Band:public int GetBand()
 
 /**
  * Fetch the "natural" block size of this band.
- *
+ * <p>
  * GDAL contains a concept of the natural block size of rasters so that
  * applications can organized data access efficiently for some file formats.
  * The natural block size is the block size that is most efficient for
@@ -2851,7 +2932,7 @@ public class Band:public int GetBlockYSize()
 
 /**
  * How should this band be interpreted as color?
- *
+ * <p>
  * gdalconst.GCI_Undefined is returned when the format doesn't know anything
  * about the color interpretation. 
  *
@@ -2863,7 +2944,7 @@ public class Band:public int GetColorInterpretation()
 
 /**
  * Fetch the color table associated with band.
- *
+ * <p>
  * If there is no associated color table, the return result is null.  The
  * returned color table remains owned by the Band object.
  * It should not be modified by the caller.
@@ -2874,7 +2955,7 @@ public class Band:public ColorTable GetColorTable()
 
 /**
  * Return the data type of the band.
- *
+ * <p>
  * A value such as gdalconst.GDT_Byte, gdalconst.GDT_Int16, ...
  * @return the data type of the band.
  */
@@ -2883,7 +2964,7 @@ public class Band:public int getDataType()
 
 /**
  * Fetch default raster histogram. 
- *
+ * <p>
  * The default method in GDALRasterBand will compute a default histogram. This
  * method is overriden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
  * that may be able to fetch efficiently an already stored histogram.
@@ -2921,7 +3002,7 @@ public class Band:public int GetDefaultHistogram(double[] min_ret, double[] max_
 
 /**
  * Fetch default raster histogram. 
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #GetDefaultHistogram(double[] min_ret, double[] max_ret, int[][] histogram_ret, boolean force, ProgressCallback callback)
@@ -2932,7 +3013,7 @@ public class Band:public int GetDefaultHistogram(double[] min_ret, double[] max_
 
 /**
  * Fetch default raster histogram. 
- *
+ * <p>
  * Same as below with force == true and callback == null
  *
  * @see #GetDefaultHistogram(double[] min_ret, double[] max_ret, int[][] histogram_ret, boolean force, ProgressCallback callback)
@@ -2943,7 +3024,7 @@ public class Band:public int GetDefaultHistogram(double[] min_ret, double[] max_
 
 /**
  * Fetch default Raster Attribute Table.
- *
+ * <p>
  * 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 altered by the application. 
@@ -2954,7 +3035,7 @@ public class Band:public RasterAttributeTable GetDefaultRAT()
 
 /**
  * Compute raster histogram. 
- *
+ * <p>
  * Note that the bucket size is (dfMax-dfMin) / nBuckets.  
  * <p>
  * For example to compute a simple 256 entry histogram of eight bit data, 
@@ -2990,7 +3071,7 @@ public class Band:public int GetHistogram(double min, double max, int[] histogra
 
 /**
  * Compute raster histogram. 
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #GetHistogram(double min, double max, int[] histogram, boolean include_out_of_range, boolean approx_ok, ProgressCallback callback)
@@ -3001,7 +3082,7 @@ public class Band:public int GetHistogram(double min, double max, int[] histogra
 
 /**
  * Compute raster histogram. 
- *
+ * <p>
  * Same as below with include_out_of_range == 0, approx_ok == true and callback == null
  *
  * @see #GetHistogram(double min, double max, int[] histogram, boolean include_out_of_range, boolean approx_ok, ProgressCallback callback)
@@ -3012,7 +3093,7 @@ public class Band:public int GetHistogram(double min, double max, int[] histogra
 
 /**
  * Compute raster histogram. 
- *
+ * <p>
  * Same as below with include_out_of_range == 0, approx_ok == true and callback == null
  *
  * @see #GetHistogram(double min, double max, int[] histogram, boolean include_out_of_range, boolean approx_ok, ProgressCallback callback)
@@ -3023,7 +3104,7 @@ public class Band:public int GetHistogram(int[] histogram)
 
 /**
  * Return the mask band associated with the band.
- *
+ * <p>
  * The GDALRasterBand class includes a default implementation of GetMaskBand() that
  * returns one of four default implementations :
  * <ul>
@@ -3057,7 +3138,7 @@ public class Band:public Band GetMaskBand()
 
 /**
  * Return the status flags of the mask band associated with the band.
- *
+ * <p>
  * The GetMaskFlags() method returns an bitwise OR-ed set of status flags with
  * the following available definitions that may be extended in the future:
  * <ul>
@@ -3069,7 +3150,7 @@ public class Band:public Band GetMaskBand()
  * <li>GMF_NODATA(0x08): Indicates the mask is actually being generated from nodata values.
  *     (mutually exclusive of GMF_ALPHA)</li>
  * </ul>
- *
+ * <p>
  * The GDALRasterBand class includes a default implementation of GetMaskBand() that
  * returns one of four default implementations :
  * <ul>
@@ -3100,7 +3181,7 @@ public class Band:public int GetMaskFlags()
 
 /**
  * Fetch the minimum value for this band.
- * 
+ * <p>
  * For file formats that don't know this intrinsically, no value will be returned
  *
  * @param val empty allocated array of type Double[] of size 1. val[0] will contain a Double object
@@ -3110,7 +3191,7 @@ public class Band:public void GetMinimum(Double[] val)
 
 /**
  * Fetch the maximum value for this band.
- * 
+ * <p>
  * For file formats that don't know this intrinsically, no value will be returned
  *
  * @param val empty allocated array of type Double[] of size 1. val[0] will contain a Double object
@@ -3120,7 +3201,7 @@ public class Band:public void GetMaximum(Double[] val)
 
 /**
  * Fetch the raster value offset.
- *
+ * <p>
  * This value (in combination with the GetScale() value) is used to
  * transform raw pixel values into the units returned by GetUnits().  
  * For example this might be used to store elevations in GUInt16 bands
@@ -3137,7 +3218,7 @@ public class Band:public void GetOffset(Double[] val)
 
 /**
  * Fetch the raster value scale.
- *
+ * <p>
  * This value (in combination with the GetOffset() value) is used to
  * transform raw pixel values into the units returned by GetUnits().  
  * For example this might be used to store elevations in GUInt16 bands
@@ -3154,7 +3235,7 @@ public class Band:public void GetScale(Double[] val)
 
 /**
  * Fetch the no data value for this band.
- * 
+ * <p>
  * The no data value for a band is generally a special marker
  * value used to mark pixels that are not valid data.  Such pixels should
  * generally not be displayed, nor contribute to analysis operations.
@@ -3182,7 +3263,20 @@ public class Band:public int GetOverviewCount()
 
 /**
  * Fetch the list of category names for this raster.
+ * <p>
+ * Raster values without
+ * associated names will have an empty string in the returned list.  The
+ * first entry in the list is for raster values of zero, and so on.
+ *
+ * @return vector of names, or null if none.
  *
+ * @since GDAL 1.9.0
+ */
+public class Band:public java.util.Vector GetCategoryNames()
+
+/**
+ * Fetch the list of category names for this raster.
+ * <p>
  * Raster values without 
  * associated names will have an empty string in the returned list.  The
  * first entry in the list is for raster values of zero, and so on. 
@@ -3193,7 +3287,7 @@ public class Band:public java.util.Vector GetRasterCategoryNames()
 
 /**
  * How should this band be interpreted as color?
- *
+ * <p>
  * gdalconst.GCI_Undefined is returned when the format doesn't know anything
  * about the color interpretation. 
  *
@@ -3203,7 +3297,7 @@ public class Band:public int GetRasterColorInterpretation()
 
 /**
  * Fetch the color table associated with band.
- *
+ * <p>
  * If there is no associated color table, the return result is null.  The
  * returned color table remains owned by the Band object.
  * It should not be modified by the caller.
@@ -3214,7 +3308,7 @@ public class Band:public ColorTable GetRasterColorTable()
 
 /**
  * Return the data type of the band.
- *
+ * <p>
  * A value such as gdalconst.GDT_Byte, gdalconst.GDT_Int16, ...
  * @return the data type of the band.
  *
@@ -3224,7 +3318,7 @@ public class Band:public int GetRasterDataType()
 
 /**
  * Fetch image statistics. 
- *
+ * <p>
  * Returns the minimum, maximum, mean and standard deviation of all
  * pixel values in this band.  If approximate statistics are sufficient,
  * the approx_ok flag can be set to true in which case overviews, or a
@@ -3264,7 +3358,7 @@ public class Band:public int GetStatistics(boolean approx_ok, boolean force, dou
 
 /**
  * Fetch image statistics. 
- *
+ * <p>
  * Same as below but boolean value of true should be replaced with 1, and false with 0.
  *
  * @see #GetStatistics(boolean approx_ok, boolean force, double[] min, double[] max, double[] mean, double[] stddev)
@@ -3273,7 +3367,7 @@ public class Band:public int GetStatistics(int approx_ok, int force, double[] mi
 
 /**
  * Return raster unit type.
- *
+ * <p>
  * Return a name for the units of this raster's values.  For instance, it
  * might be "m" for an elevation model in meters, or "ft" for feet.  If no 
  * units are available, a value of "" will be returned.
@@ -3319,7 +3413,7 @@ public class Band:public int GetYSize()
 
 /**
  * Check for arbitrary overviews.
- *
+ * <p>
  * This returns true if the underlying datastore can compute arbitrary 
  * overviews efficiently, such as is the case with OGDI over a network. 
  * Datastores with arbitrary overviews don't generally have any fixed
@@ -3335,7 +3429,7 @@ public class Band:public boolean HasArbitraryOverviews()
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * This method allows reading a region of a GDALRasterBand into a buffer.  It
  * automatically takes care of data type translation if the data type
  * (buf_type) of the buffer is different than that of the GDALRasterBand.
@@ -3406,7 +3500,7 @@ public class Band:public int ReadRaster_Direct(int xoff, int yoff, int xsize, in
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int nPixelSpace, int nLineSpace)
@@ -3415,7 +3509,7 @@ public class Band:public int ReadRaster_Direct(int xoff, int yoff, int xsize, in
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_type == gdalconst.GDT_Byte, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int nPixelSpace, int nLineSpace)
@@ -3426,7 +3520,7 @@ public class Band:public int ReadRaster_Direct(int xoff, int yoff, int xsize, in
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, buf_type == gdalconst.GDT_Byte, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int nPixelSpace, int nLineSpace)
@@ -3437,7 +3531,7 @@ public class Band:public int ReadRaster_Direct(int xoff, int yoff, int xsize, in
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below but buffer is allocated by the method
  *
  * @return a newly allocated byte buffer with the read region. Its byte order is BIG_ENDIAN by default.
@@ -3450,7 +3544,7 @@ public class Band:public java.nio.ByteBuffer ReadRaster_Direct(int xoff, int yof
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, nPixelSpace == 0 and nLineSpace == 0 but buffer is allocated by the method
  *
  * @return a newly allocated byte buffer with the read region. Its byte order is BIG_ENDIAN by default.
@@ -3463,7 +3557,7 @@ public class Band:public java.nio.ByteBuffer ReadRaster_Direct(int xoff, int yof
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0 but buffer is allocated by the method
  *
  * @return a newly allocated byte buffer with the read region. Its byte order is BIG_ENDIAN by default.
@@ -3478,7 +3572,7 @@ public class Band:public java.nio.ByteBuffer ReadRaster_Direct(int xoff, int yof
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * This method allows reading a region of a GDALRasterBand into a buffer.  It
  * automatically takes care of data type translation if the data type
  * (buf_type) of the buffer is different than that of the GDALRasterBand.
@@ -3544,7 +3638,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
@@ -3555,7 +3649,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
@@ -3566,7 +3660,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, buf_type = gdalconst.GDT_Byte, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
@@ -3592,7 +3686,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, short[] array, int nPixelSpace, int nLineSpace)
@@ -3603,7 +3697,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, short[] array, int nPixelSpace, int nLineSpace)
@@ -3614,7 +3708,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, buf_type = gdalconst.GDT_Int16, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, short[] array, int nPixelSpace, int nLineSpace)
@@ -3628,7 +3722,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
  *
  * @since Java bindings 1.7.0
@@ -3639,7 +3733,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, int[] array, int nPixelSpace, int nLineSpace)
@@ -3650,7 +3744,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, int[] array, int nPixelSpace, int nLineSpace)
@@ -3661,7 +3755,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, buf_type = gdalconst.GDT_Int32, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, int[] array, int nPixelSpace, int nLineSpace)
@@ -3675,7 +3769,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
  *
  * @since Java bindings 1.7.0
@@ -3686,7 +3780,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int nPixelSpace, int nLineSpace)
@@ -3697,7 +3791,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int nPixelSpace, int nLineSpace)
@@ -3708,7 +3802,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, buf_type = gdalconst.GDT_Float32, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int nPixelSpace, int nLineSpace)
@@ -3733,7 +3827,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int nPixelSpace, int nLineSpace)
@@ -3744,7 +3838,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int nPixelSpace, int nLineSpace)
@@ -3755,7 +3849,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Read a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize = xsize, buf_ysize = ysize, buf_type = gdalconst.GDT_Float64, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #ReadRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int nPixelSpace, int nLineSpace)
@@ -3769,7 +3863,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * This method allows writing data from a buffer into a region 
  * of the Band.  It
  * automatically takes care of data type translation if the data type
@@ -3839,7 +3933,7 @@ public class Band:public int WriteRaster_Direct(int xoff, int yoff, int xsize, i
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int nPixelSpace, int nLineSpace)
@@ -3848,7 +3942,7 @@ public class Band:public int WriteRaster_Direct(int xoff, int yoff, int xsize, i
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_type == gdalconst.GDT_Byte, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int nPixelSpace, int nLineSpace)
@@ -3859,7 +3953,7 @@ public class Band:public int WriteRaster_Direct(int xoff, int yoff, int xsize, i
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int nPixelSpace, int nLineSpace)
@@ -3870,7 +3964,7 @@ public class Band:public int WriteRaster_Direct(int xoff, int yoff, int xsize, i
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, buf_type == gdalconst.GDT_Byte, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster_Direct(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, java.nio.ByteBuffer nioBuffer, int nPixelSpace, int nLineSpace)
@@ -3885,7 +3979,7 @@ public class Band:public int WriteRaster_Direct(int xoff, int yoff, int xsize, i
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * This method allows writing data from a buffer into a region 
  * of the Band.  It
  * automatically takes care of data type translation if the data type
@@ -3950,7 +4044,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
@@ -3961,7 +4055,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
@@ -3972,7 +4066,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, buf_type == gdalconst.GDT_Byte, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
@@ -3984,7 +4078,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
  *
  * @since Java bindings 1.7.0
@@ -3995,7 +4089,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, short[] array, int nPixelSpace, int nLineSpace)
@@ -4006,7 +4100,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, short[] array, int nPixelSpace, int nLineSpace)
@@ -4017,7 +4111,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, buf_type == gdalconst.GDT_Int16, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, short[] array, int nPixelSpace, int nLineSpace)
@@ -4029,7 +4123,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
  *
  * @since Java bindings 1.7.0
@@ -4040,7 +4134,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, int[] array, int nPixelSpace, int nLineSpace)
@@ -4051,7 +4145,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, int[] array, int nPixelSpace, int nLineSpace)
@@ -4062,7 +4156,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, buf_type == gdalconst.GDT_Int32, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, int[] array, int nPixelSpace, int nLineSpace)
@@ -4085,7 +4179,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int nPixelSpace, int nLineSpace)
@@ -4096,7 +4190,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int nPixelSpace, int nLineSpace)
@@ -4107,7 +4201,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, buf_type == gdalconst.GDT_Float32, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, float[] array, int nPixelSpace, int nLineSpace)
@@ -4119,7 +4213,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, byte[] array, int nPixelSpace, int nLineSpace)
  *
  * @since Java bindings 1.7.0
@@ -4130,7 +4224,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int nPixelSpace, int nLineSpace)
@@ -4141,7 +4235,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int nPixelSpace, int nLineSpace)
@@ -4152,7 +4246,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Write a region of image data for this band.
- *
+ * <p>
  * Same as below with buf_xsize == xsize, buf_ysize == ysize, buf_type == gdalconst.GDT_Float64, nPixelSpace == 0 and nLineSpace == 0
  *
  * @see #WriteRaster(int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize, int buf_type, double[] array, int nPixelSpace, int nLineSpace)
@@ -4164,7 +4258,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
 
 /**
  * Read a block of image data efficiently.
- *
+ * <p>
  * This method accesses a "natural" block from the raster band without
  * resampling, or data type conversion.  For a more generalized, but
  * potentially less efficient access use ReadRaster().
@@ -4187,7 +4281,7 @@ public class Band:public int ReadBlock_Direct(int nXBlockOff, int nYBlockOff, ja
 
 /**
  * Write a block of image data efficiently.
- *
+ * <p>
  * This method accesses a "natural" block from the raster band without
  * resampling, or data type conversion.  For a more generalized, but
  * potentially less efficient access use WriteRaster().
@@ -4261,7 +4355,7 @@ public class Band:public int SetDefaultHistogram(double min, double max, int[] h
 
 /**
  * Set default Raster Attribute Table.
- *
+ * <p>
  * Associates a default RAT with the band.  If not implemented for the
  * format a CPLE_NotSupported error will be issued.
  *
@@ -4274,7 +4368,7 @@ public class Band:public int SetDefaultRAT(RasterAttributeTable table)
 
 /**
  * Set the no data value for this band. 
- *
+ * <p>
  * To clear the nodata value, just set it with an "out of range" value.
  * Complex band no data values must have an imagery component of zero.
  *
@@ -4288,7 +4382,7 @@ public class Band:public int SetNoDataValue(double nodataValue)
 
 /**
  * Set scaling offset.
- *
+ * <p>
  * Very few formats implement this method.
  * When not implemented it will issue a CPLE_NotSupported error and return CE_Failure.
  *
@@ -4302,7 +4396,7 @@ public class Band:public int SetOffset(double newoffset)
 
 /**
  * Set scaling ratio.
- *
+ * <p>
  * Very few formats implement this method.
  * When not implemented it will issue a CPLE_NotSupported error and return CE_Failure.
  *
@@ -4316,7 +4410,7 @@ public class Band:public int SetScale(double newscale)
 
 /**
  * Set unit type.
- *
+ * <p>
  * Set the unit type for a raster band.  Values should be one of
  * "" (the default indicating it is unknown), "m" indicating meters, 
  * or "ft" indicating feet, though other nonstandard values are allowed.
@@ -4332,7 +4426,24 @@ public class Band:public int SetUnitType(String newunittype)
 
 /**
  * Set the category names for this band.
+ * <p>
+ * See the GetCategoryNames() method for more on the interpretation of
+ * category names.
+ *
+ * @param names a vector of strings with category names.  May
+ * be ,ull to just clear the existing list.
+ *
+ * @return gdalconst.CE_None on success, or gdalconst.CE_Failure on failure.  If unsupported
+ * by the driver, CE_Failure is returned by no error message will have
+ * been emitted.
  *
+ * @since GDAL 1.9.0
+ */
+public class Band:public int SetCategoryNames(java.util.Vector names)
+
+/**
+ * Set the category names for this band.
+ * <p>
  * See the GetCategoryNames() method for more on the interpretation of
  * category names. 
  *
@@ -4347,7 +4458,7 @@ public class Band:public int SetRasterCategoryNames(java.util.Vector names)
 
 /**
  * Set statistics on band.
- *
+ * <p>
  * This method can be used to store min/max/mean/standard deviation
  * statistics on a raster band.  
  * <p>
@@ -4414,7 +4525,7 @@ public class RasterAttributeTable:public RasterAttributeTable()
 
 /**
  * Copy Raster Attribute Table.
- *
+ * <p>
  * Creates a new copy of an existing raster attribute table.
  *
  * @return new copy of the RAT. 
@@ -4423,7 +4534,7 @@ public class RasterAttributeTable:public RasterAttributeTable Clone()
 
 /**
  * Create new column.
- *
+ * <p>
  * 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) 
@@ -4439,7 +4550,7 @@ public class RasterAttributeTable:public int CreateColumn(String name, int eFiel
 
 /**
  * Fetch column index for given usage.
- *
+ * <p>
  * Returns the index of the first column of the requested usage type, or -1 
  * if no match is found. 
  *
@@ -4458,7 +4569,7 @@ public class RasterAttributeTable:public int GetColumnCount()
 
 /**
  * Get linear binning information.
- *
+ * <p>
  * Returns linear binning information if any is associated with the RAT.
  *
  * @param pdfRow0Min (out) array of 1 double that will contain the lower bound (pixel value) of the first category.
@@ -4488,7 +4599,7 @@ public class RasterAttributeTable:public int GetRowCount()
 
 /**
  * Get row for pixel value.
- *
+ * <p>
  * 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. 
@@ -4519,7 +4630,7 @@ public class RasterAttributeTable:public int GetUsageOfCol(int iCol)
 
 /**
  * Fetch field value as a double.
- *
+ * <p>
  * 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.
@@ -4533,7 +4644,7 @@ public class RasterAttributeTable:public double GetValueAsDouble(int iRow, int i
 
 /**
  * Fetch field value as a integer.
- *
+ * <p>
  * 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.
@@ -4547,7 +4658,7 @@ public class RasterAttributeTable:public int GetValueAsInt(int iRow, int iCol)
 
 /**
  * Fetch field value as a string.
- *
+ * <p>
  * 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.
@@ -4562,7 +4673,7 @@ public class RasterAttributeTable:public String GetValueAsString(int iRow, int i
 
 /**
  * Set linear binning information.
- *
+ * <p>
  * 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.
@@ -4578,7 +4689,7 @@ public class RasterAttributeTable:public int SetLinearBinning(double dfRow0Min,
 
 /**
  * Set row count.
- *
+ * <p>
  * 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. 
@@ -4589,7 +4700,7 @@ public class RasterAttributeTable:public void SetRowCount(int nCount)
 
 /**
  * Set field value from double.
- *
+ * <p>
  * 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.
@@ -4602,7 +4713,7 @@ public class RasterAttributeTable:public void SetValueAsDouble(int iRow, int iCo
 
 /**
  * Set field value from integer.
- *
+ * <p>
  * 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.
@@ -4615,7 +4726,7 @@ public class RasterAttributeTable:public void SetValueAsInt(int iRow, int iCol,
 
 /**
  * Set field value from string.
- *
+ * <p>
  * 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.
@@ -4648,7 +4759,7 @@ public class org.gdal.gdal.Driver:public void delete()
 
 /**
  * Create a new dataset with this driver.
- *
+ * <p>
  * What argument values are legal for particular drivers is driver specific,
  * and there is no way to query in advance to establish legal values (except
  * querying driver.GetMetadataItem(gdalconst.DMD_CREATIONOPTIONLIST)
@@ -4675,7 +4786,7 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
 
 /**
  * Create a new dataset with this driver.
- *
+ * <p>
  * Same as below but options are passed as a Vector of String.
  *
  * @see #Create(String name, int xsize, int ysize, int nBands, int eType, String[] options)
@@ -4684,7 +4795,7 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
 
 /**
  * Create a new dataset with this driver.
- *
+ * <p>
  * Same as below with eType == gdalconst.GDT_Byte
  *
  * @see #Create(String name, int xsize, int ysize, int nBands, int eType, String[] options)
@@ -4695,7 +4806,7 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
 
 /**
  * Create a new dataset with this driver.
- *
+ * <p>
  * Same as below with options == null
  *
  * @see #Create(String name, int xsize, int ysize, int nBands, int eType, String[] options)
@@ -4706,7 +4817,7 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
 
 /**
  * Create a new dataset with this driver.
- *
+ * <p>
  * Same as below with eType == gdalconst.GDT_Byte and options == null
  *
  * @see #Create(String name, int xsize, int ysize, int nBands, int eType, String[] options)
@@ -4717,7 +4828,7 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
 
 /**
  * Create a new dataset with this driver.
- *
+ * <p>
  * Same as below with nbands == 1, eType == gdalconst.GDT_Byte and options == null
  *
  * @see #Create(String name, int xsize, int ysize, int nBands, int eType, String[] options)
@@ -4728,7 +4839,7 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
 
 /**
  * Create a copy of a dataset.
- *
+ * <p>
  * This method will attempt to create a copy of a raster dataset with the
  * indicated filename, and in this drivers format.  Band number, size, 
  * type, projection, geotransform and so forth are all to be copied from
@@ -4769,7 +4880,7 @@ public class org.gdal.gdal.Driver:public Dataset CreateCopy(String name, Dataset
 
 /**
  * Create a copy of a dataset.
- *
+ * <p>
  * Same as below with callback == null
  *
  * @see #CreateCopy(String name, Dataset src_ds, int strict, java.util.Vector options, ProgressCallback callback)
@@ -4778,7 +4889,7 @@ public class org.gdal.gdal.Driver:public Dataset CreateCopy(String name, Dataset
 
 /**
  * Create a copy of a dataset.
- *
+ * <p>
  * Same as below with strict == 1 and callback == null
  *
  * @see #CreateCopy(String name, Dataset src_ds, int strict, java.util.Vector options, ProgressCallback callback)
@@ -4789,7 +4900,7 @@ public class org.gdal.gdal.Driver:public Dataset CreateCopy(String name, Dataset
 
 /**
  * Create a copy of a dataset.
- *
+ * <p>
  * Same as below with options == null and callback == null
  *
  * @see #CreateCopy(String name, Dataset src_ds, int strict, java.util.Vector options, ProgressCallback callback)
@@ -4800,7 +4911,7 @@ public class org.gdal.gdal.Driver:public Dataset CreateCopy(String name, Dataset
 
 /**
  * Create a copy of a dataset.
- *
+ * <p>
  * Same as below with strict == 1, options == null and callback == null
  *
  * @see #CreateCopy(String name, Dataset src_ds, int strict, java.util.Vector options, ProgressCallback callback)
@@ -4811,7 +4922,7 @@ public class org.gdal.gdal.Driver:public Dataset CreateCopy(String name, Dataset
 
 /**
  * Create a copy of a dataset.
- *
+ * <p>
  * Same as below with callback == null and options as an array of strings
  *
  * @see #CreateCopy(String name, Dataset src_ds, int strict, java.util.Vector options, ProgressCallback callback)
@@ -4820,7 +4931,7 @@ public class org.gdal.gdal.Driver:public Dataset CreateCopy(String name, Dataset
 
 /**
  * Create a copy of a dataset.
- *
+ * <p>
  * Same as below with strict == 1, callback == null and options as an array of strings
  *
  * @see #CreateCopy(String name, Dataset src_ds, int strict, java.util.Vector options, ProgressCallback callback)
@@ -4831,7 +4942,7 @@ public class org.gdal.gdal.Driver:public Dataset CreateCopy(String name, Dataset
 
 /**
  * Delete named dataset.
- *
+ * <p>
  * The driver will attempt to delete the named dataset in a driver specific
  * fashion.  Full featured drivers will delete all associated files,
  * database objects, or whatever is appropriate.  The default behaviour when
@@ -4849,7 +4960,7 @@ public class org.gdal.gdal.Driver:public int Delete(String name)
 
 /**
  * Rename a dataset.
- *
+ * <p>
  * Rename a dataset. This may including moving the dataset to a new directory
  * or even a new filesystem.  
  * <p>
@@ -4866,7 +4977,7 @@ public class org.gdal.gdal.Driver:public int Rename(String newName, String oldNa
 
 /**
  * Register a driver for use.
- *
+ * <p>
  * Normally this method is used by format specific C callable registration
  * entry points such as GDALRegister_GTiff() rather than being called
  * directly by application level code.
@@ -4887,7 +4998,7 @@ public class org.gdal.gdal.Driver:public void Deregister()
 
 /**
  * Return the short name of a driver.
- *
+ * <p>
  * This is the string that can be
  * passed to the GDALGetDriverByName() function.
  * <p>
@@ -4898,8 +5009,8 @@ public class org.gdal.gdal.Driver:public void Deregister()
 public class org.gdal.gdal.Driver:public String getShortName()
 
 /**
- * Return the long name of a driver
- *
+ * Return the long name of a driver.
+ * <p>
  * For the GeoTIFF driver, this is "GeoTIFF"
  *
  * @return the long name of the driver or empty string.
@@ -4907,8 +5018,8 @@ public class org.gdal.gdal.Driver:public String getShortName()
 public class org.gdal.gdal.Driver:public String getLongName()
 
 /**
- * Return the URL to the help that describes the driver
- *
+ * Return the URL to the help that describes the driver.
+ * <p>
  * That URL is relative to the GDAL documentation directory.
  * <p>
  * For the GeoTIFF driver, this is "frmt_gtiff.html"
@@ -4922,7 +5033,7 @@ public class org.gdal.gdal.Driver:public String getHelpTopic()
 
 /**
   * Class used to report progression of long operations.
-  *
+  * <p>
   * This class will not do anything by itself, but it can be subclassed, like <a href="TermProgressCallback.html">TermProgressCallback</a> class.
   * to do more usefull things.
   *
@@ -4932,7 +5043,7 @@ public class ProgressCallback
 
 /**
   * Callback method called from long processing from GDAL methods.
-  *
+  * <p>
   * This method is called back with the progression percentage. Its return value
   * is used by the caller to determine whether the processing should go on or be
   * interrupted.
@@ -4953,7 +5064,7 @@ public class ProgressCallback:public int run(double dfComplete, String message)
 
 /**
   * Class used for simple progress report to terminal.
-  *
+  * <p>
   * This progress reporter prints simple progress report to the
   * terminal window.  The progress report generally looks something like
   * this:
@@ -4980,7 +5091,7 @@ public class TermProgressCallback
 
 /**
   * Class used for object with metadata. 
-  *
+  * 
   * <p>
   * The MajorObject class is a binding for the C++ <a href="http://gdal.org/classGDALMajorObject.html">GDALMajorObject</a> class.
   */
@@ -4988,7 +5099,7 @@ public class MajorObject
 
 /**
  * Fetch object description. 
- *
+ * <p>
  * The semantics of the returned description are specific to the derived
  * type.  For Dataset object it is the dataset name.  For Band object
  * it is actually a description (if supported) or "".
@@ -5001,7 +5112,7 @@ public class MajorObject:public String GetDescription()
 
 /**
  * Set object description. 
- *
+ * <p>
  * The semantics of the returned description are specific to the derived
  * type.  For Dataset object it is the dataset name.  For Band object
  * it is actually a description (if supported) or "".
@@ -5052,7 +5163,7 @@ public class MajorObject:public java.util.Vector GetMetadata_List(String domain)
 
 /**
  * Fetch metadata.
- *
+ * <p>
  * Returns metadata from the default domain as a vector of strings of the format "KEY=VALUE".
  * 
  * @return null or a vector of strings
@@ -5063,7 +5174,7 @@ public class MajorObject:public java.util.Vector GetMetadata_List()
 
 /** 
  * Set metadata. 
- *
+ * <p>
  * The metadata is set into the domain specified.
  *
  * @param metadata the metadata as a table of (key, value) tuples to apply
@@ -5079,7 +5190,7 @@ public class MajorObject:public int SetMetadata(java.util.Hashtable metadata, St
 
 /** 
  * Set metadata. 
- *
+ * <p>
  * The metadata is set into the default domain
  *
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure and gdalconst.CE_Warning if the
@@ -5093,7 +5204,7 @@ public class MajorObject:public int SetMetadata(java.util.Hashtable metadata)
 
 /** 
  * Set metadata.
- *
+ * <p>
  * The metadata is set into the domain specified.
  *
  * @param metadataString the metadata to apply as a string of the format "KEY=VALUE".
@@ -5108,7 +5219,7 @@ public class MajorObject:public int SetMetadata(String metadataString, String do
 
 /** 
  * Set metadata.
- *
+ * <p>
  * The metadata is set into the default domain
  *
  * @param metadataString the metadata to apply as a string of the format "KEY=VALUE".
@@ -5123,7 +5234,7 @@ public class MajorObject:public int SetMetadata(String metadataString)
 
 /** 
  * Set metadata.
- *
+ * <p>
  * The metadata is set into the domain specified.
  *
  * @param metadata the metadata to apply as a vector of strings of the format "KEY=VALUE".
@@ -5140,7 +5251,7 @@ public class MajorObject:public int SetMetadata(java.util.Vector metadata, Strin
 
 /** 
  * Set metadata.
- *
+ * <p>
  * The metadata is set into the default domain
  *
  * @param metadata the metadata to apply as a vector of strings of the format "KEY=VALUE".
@@ -5166,7 +5277,7 @@ public class MajorObject:public String GetMetadataItem( String name, String doma
 
 /**
  * Fetch single metadata item.
- *
+ * <p>
  * The metadata item is searched into the default domain.
  *
  * @param name the key for the metadata item to fetch.
@@ -5193,7 +5304,7 @@ public class MajorObject:public int SetMetadataItem( String name, String value,
 
 /**
  * Set single metadata item.
- *
+ * <p>
  * The metadata item is set into the default domain.
  *
  * @param name the key for the metadata item to fetch.
@@ -5217,7 +5328,7 @@ public class Transformer
 
 /**
  * Create image to image transformer.
- *
+ * <p>
  * This function creates a transformation object that maps from pixel/line
  * coordinates on one image to pixel/line coordinates on another image.  The
  * images may potentially be georeferenced in different coordinate systems, 
@@ -5266,7 +5377,7 @@ public class Transformer:public Transformer(Dataset src_ds, Dataset dst_ds, java
 
 /**
   * Transform a 3D point.
-  *
+  * <p>
   * The method will use the provided 3 double values and update them.
   *
   * @param inout array of 3 double values (x, y, z) used for input and output.
@@ -5277,7 +5388,7 @@ public class Transformer:public int TransformPoint(int bDstToSrc, double[] inout
 
 /**
   * Transform a 3D point.
-  *
+  * <p>
   * The method will use the provided (x, y, z) values and put the transformed
   * values into argout
   *
@@ -5292,7 +5403,7 @@ public class Transformer:public int TransformPoint(double[] argout, int bDstToSr
 
 /**
   * Transform a 2D point.
-  *
+  * <p>
   * The method will use the provided (x, y) values and put the transformed
   * values into argout
   *
@@ -5308,7 +5419,7 @@ public class Transformer:public int TransformPoint(double[] argout, int bDstToSr
 
 /**
   * Transform an array of coordinates.
-  *
+  * <p>
   * The method will use the provided array of values and put the update coordinates
   * into it.
   *
@@ -5327,7 +5438,7 @@ public class Transformer:public int TransformPoints(int bDstToSrc, double[][] ar
 
 /**
   * Various constants used by the org.gdal.gdal package.
-  *
+  * <p>
   * These constants correspond to different enumerations : error codes, XML content type, metadata, palette interpretation,
   * color interpretation, data type, raster color table attribute type, band mask flags, resampling methods...
   */
@@ -5419,7 +5530,7 @@ public interface gdalconstConstants:public final static int CPLE_ObjectNull
 
 /**
  * CPLES_BackslashQuotable(0).
- *
+ * <p>
  * This scheme turns a binary string into 
  * a form suitable to be placed within double quotes as a string constant.
  * The backslash, quote, '\\0' and newline characters are all escaped in 
@@ -5429,7 +5540,7 @@ public interface gdalconstConstants:public final static int CPLES_BackslashQuota
 
 /**
  * CPLES_XML(1).
- *
+ * <p>
  * This scheme converts the '<', '<' and '&' characters into
  * their XML/HTML equivelent (>, < and &) making a string safe
  * to embed as CDATA within an XML element.  The '\\0' is not escaped and 
@@ -5439,7 +5550,7 @@ public interface gdalconstConstants:public final static int CPLES_XML
 
 /**
  * CPLES_URL(2).
- *
+ * <p>
  * Everything except alphanumerics and the underscore are 
  * converted to a percent followed by a two digit hex encoding of the character
  * (leading zero supplied if needed).  This is the mechanism used for encoding
@@ -5449,7 +5560,7 @@ public interface gdalconstConstants:public final static int CPLES_URL
 
 /**
  * CPLES_SQL(3).
- *
+ * <p>
  * All single quotes are replaced with two single quotes.  
  * Suitable for use when constructing literal values for SQL commands where
  * the literal will be enclosed in single quotes.
@@ -5458,7 +5569,7 @@ public interface gdalconstConstants:public final static int CPLES_SQL
 
 /**
  * CPLES_CSV(4).
- *
+ * <p>
  * If the values contains commas, double quotes, or newlines it 
  * placed in double quotes, and double quotes in the value are doubled.
  * Suitable for use when constructing field values for .csv files.  Note that
@@ -5807,6 +5918,7 @@ public class org.gdal.ogr.Driver:public void delete()
 
 /**
  Attempt to create a new data source based on the passed driver.
+ <p>
  The papszOptions argument can be used to control driver specific
  creation options.  These options are normally documented in the format
  specific documentation.
@@ -5826,7 +5938,7 @@ public class org.gdal.ogr.Driver:public DataSource CreateDataSource(String name,
 
 /**
  * Attempt to create a new data source based on the passed driver.
- *
+ * <p>
  * Same as below with options == null.
  *
  * @see #CreateDataSource(String name, java.util.Vector options)
@@ -5853,7 +5965,7 @@ public class org.gdal.ogr.Driver:public DataSource CopyDataSource(DataSource src
 /**
  * Creates a new datasource by copying all the layers from the
  * source datasource.
- *
+ * <p>
  * Same as below with options == null.
  *
  * @see #CreateDataSource(String name, java.util.Vector options)
@@ -5879,7 +5991,7 @@ public class org.gdal.ogr.Driver:public DataSource Open(String name, int update)
 
 /**
  * Attempt to open file with this driver. 
- *
+ * <p>
  * Same as below with update == 0.
  *
  * @see #Open(String name, int update)
@@ -5890,7 +6002,7 @@ public class org.gdal.ogr.Driver:public DataSource Open(String name)
 
 /**
  Destroy a datasource.
-
+ <p>
  Destroy the named datasource.  Normally it would be safest if the
  datasource was not open at the time. 
  <p>
@@ -5906,7 +6018,7 @@ public class org.gdal.ogr.Driver:public int DeleteDataSource(String name)
 
 /**
  Test if capability is available.
-
+ <p>
  One of the following data source capability names can be passed into this
  function, and a TRUE or FALSE value will be returned indicating whether
  or not the capability is available for this object.
@@ -5927,7 +6039,7 @@ public class org.gdal.ogr.Driver:public boolean TestCapability(String cap)
 
 /** 
   Fetch name of driver (file format).
-
+ <p>
   This name should be relatively short
   (10-40 characters), and should reflect the underlying file format.  For
   instance "ESRI Shapefile".
@@ -5938,7 +6050,7 @@ public class org.gdal.ogr.Driver:public String getName()
 
 /** 
   Fetch name of driver (file format).
-
+ <p>
   This name should be relatively short
   (10-40 characters), and should reflect the underlying file format.  For
   instance "ESRI Shapefile".
@@ -5950,7 +6062,7 @@ public class org.gdal.ogr.Driver:public String GetName()
 
 /** 
   Add a driver to the list of registered drivers.
-
+ <p>
   If the driver is already registered (based on handle comparison) 
   then the driver isn't registered.  New drivers are added at the end of
   the list of registered drivers.
@@ -5969,7 +6081,7 @@ public class org.gdal.ogr.Driver:public void Deregister()
 /* Class DataSource */
 /**
   * This class represents a data source.
-  *
+  * 
   * <p>
   * The DataSource class is a binding for the C++ <a href="http://gdal.org/ogr/classOGRDataSource.html">OGRDataSource</a> class.
   * <p>
@@ -5981,7 +6093,7 @@ public class DataSource
 
 /**
   * Frees the native resource associated to a DataSource object and close the file.
-  *
+  * <p>
   * This method will delete the underlying C++ object. After it has been called,
   * all native resources will have been destroyed, so it will be illegal (and likely to
   * cause JVM crashes) to use any method on this object or any derived objects,
@@ -5995,7 +6107,7 @@ public class DataSource:public void delete()
 
 /**
  Duplicate an existing layer.
-
+ <p>
  This function creates a new layer, duplicate the field definitions of the
  source layer and then duplicate each features of the source layer.
  The papszOptions argument
@@ -6015,7 +6127,7 @@ public class DataSource:public Layer CopyLayer(Layer src_layer, String new_name,
 
 /**
  * Duplicate an existing layer.
- *
+ * <p>
  * Same as below with options == null.
  *
  * @see #CopyLayer(Layer src_layer, String new_name, java.util.Vector options)
@@ -6026,7 +6138,7 @@ public class DataSource:public Layer CopyLayer(Layer src_layer, String new_name)
 
 /**
 Create a new layer on the data source with the indicated name, coordinate system, geometry type.
-
+<p>
 The options argument
 can be used to control driver specific creation options.  These options are
 normally documented in the format specific documentation. 
@@ -6068,7 +6180,7 @@ public class DataSource:public Layer CreateLayer(String name, SpatialReference s
 
 /**
  * Create a new layer on the data source with the indicated name, coordinate system, geometry type.
- *
+ * <p>
  * Same as below with options == null.
  *
  * @see #CreateLayer(String name, SpatialReference srs, int geom_type, java.util.Vector options)
@@ -6079,7 +6191,7 @@ public class DataSource:public Layer CreateLayer(String name, SpatialReference s
 
 /**
  * Create a new layer on the data source with the indicated name, coordinate system.
- *
+ * <p>
  * Same as below with geom_type == ogr.wkbUnknown and options == null.
  *
  * @see #CreateLayer(String name, SpatialReference srs, int geom_type, java.util.Vector options)
@@ -6090,7 +6202,7 @@ public class DataSource:public Layer CreateLayer(String name, SpatialReference s
 
 /**
  * Create a new layer on the data source with the indicated name.
- *
+ * <p>
  * Same as below with srs == null, geom_type == ogr.wkbUnknown and options == null.
  *
  * @see #CreateLayer(String name, SpatialReference srs, int geom_type, java.util.Vector options)
@@ -6101,6 +6213,7 @@ public class DataSource:public Layer CreateLayer(String name)
 
 /**
  Delete the indicated layer from the datasource.
+ <p>
  If this method is supported
  the ODsCDeleteLayer capability will test true on the DataSource.
 
@@ -6113,7 +6226,7 @@ public class DataSource:public int DeleteLayer(int index)
 
 /**
  Execute an SQL statement against the data store. 
-
+ <p>
  The result of an SQL query is either null for statements that are in error,
  or that have no results set, or a Layer representing a results
  set from the query.  Note that this Layer is in addition to the layers
@@ -6136,7 +6249,7 @@ public class DataSource:public Layer ExecuteSQL(String statement, Geometry spati
 
 /**
  * Execute an SQL statement against the data store.
- *
+ * <p>
  * Same as below with dialect = ""
  *
  * @see #ExecuteSQL(String statement, Geometry spatialFilter, String dialect)
@@ -6147,7 +6260,7 @@ public class DataSource:public Layer ExecuteSQL(String statement, Geometry spati
 
 /**
  * Execute an SQL statement against the data store.
- *
+ * <p>
  * Same as below with spatialFilter == null and dialect = ""
  *
  * @see #ExecuteSQL(String statement, Geometry spatialFilter, String dialect)
@@ -6158,7 +6271,7 @@ public class DataSource:public Layer ExecuteSQL(String statement)
 
 /**
  Release results of ExecuteSQL().
-
+ <p>
  This method should only be used to deallocate Layers resulting from
  an ExecuteSQL() call on the same DataSource.  Failure to deallocate a
  results set before destroying the DataSource may cause errors. 
@@ -6167,9 +6280,35 @@ public class DataSource:public Layer ExecuteSQL(String statement)
 */
 public class DataSource:public void ReleaseResultSet(Layer layer)
 
+
+
 /**
- Test if capability is available.
+Flush pending changes to disk.
+<p>
+This call is intended to force the datasource to flush any pending writes to
+disk, and leave the disk file in a consistent state.  It would not normally
+have any effect on read-only datasources.
+<p>
+Some data sources do not implement this method, and will still return
+ogr.OGRERR_NONE.  An error is only returned if an error occurs while attempting
+to flush to disk.
+<p>
+The default implementation of this method just calls the SyncToDisk() method
+on each of the layers.  Conceptionally, calling SyncToDisk() on a datasource
+should include any work that might be accomplished by calling SyncToDisk()
+on layers in that data source.
+<p>
+In any event, you should always close any opened datasource with
+delete() that will ensure all data is correctly flushed.
+
+ at return ogr.OGRERR_NONE if no error occurs (even if nothing is done) or an
+error code.
+*/
+public class DataSource:public int SyncToDisk()
 
+/**
+ Test if capability is available.
+ <p>
  One of the following data source capability names can be passed into this
  method, and a true or false value will be returned indicating whether or not
  the capability is available for this object.
@@ -6189,7 +6328,7 @@ public class DataSource:public boolean TestCapability(String cap)
 
 /**
  Fetch a layer by index.
-
+ <p>
  The returned layer remains owned by the 
  DataSource and should not be deleted by the application.
 
@@ -6201,7 +6340,7 @@ public class DataSource:public Layer GetLayerByIndex(int index)
 
 /**
  Fetch a layer by index.
-
+ <p>
  The returned layer remains owned by the 
  DataSource and should not be deleted by the application.
 
@@ -6215,7 +6354,7 @@ public class DataSource:public Layer GetLayer(int index)
 
 /**
  Fetch a layer by name.
-
+ <p>
  The returned layer remains owned by the 
  DataSource and should not be deleted by the application.
 
@@ -6247,7 +6386,9 @@ public class DataSource:public Layer GetLayer(String layer_name)
 public class DataSource:public int GetLayerCount()
 
 /** 
- Returns the name of the data source.  This string should be sufficient to
+ Returns the name of the data source.
+<p>
+ This string should be sufficient to
  open the data source if passed to the same Driver that this data
  source was opened with, but it need not be exactly the same string that
  was used to open the data source.  Normally this is a filename. 
@@ -6257,7 +6398,9 @@ public class DataSource:public int GetLayerCount()
 public class DataSource:public String GetName()
 
 /** 
- Returns the name of the data source.  This string should be sufficient to
+ Returns the name of the data source.
+ <p>
+ This string should be sufficient to
  open the data source if passed to the same Driver that this data
  source was opened with, but it need not be exactly the same string that
  was used to open the data source.  Normally this is a filename. 
@@ -6306,7 +6449,7 @@ public class Layer:public void delete()
 
 /**
  Create and write a new feature within a layer.
-
+ <p>
  The passed feature is written to the layer as a new feature, rather than
  overwriting an existing one.  If the feature has a feature id other than
  OGRNullFID, then the native implementation may use that as the feature id
@@ -6323,11 +6466,19 @@ public class Layer:public int CreateFeature(Feature feature)
 
 /**
 Create a new field on a layer.
-
+<p>
 You must use this to create new fields
 on a real layer. Internally the FeatureDefn for the layer will be updated
 to reflect the new field.  Applications should never modify the FeatureDefn
 used by a layer directly.
+<p>
+This method should not be called while there are feature objects in existance that
+were obtained or created with the previous layer definition.
+<p>
+Not all drivers support this method. 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.
 
 @param field_def field definition to write to disk. 
 @param approx_ok If 1, the field may be created in a slightly different
@@ -6348,8 +6499,126 @@ public class Layer:public int CreateField(FieldDefn field_def)
 
 
 /**
- Fetch the extent of this layer.
+Delete an existing field on a layer.
+<p>
+You must use this to delete existing fields
+on a real layer. Internally the FeatureDefn for the layer will be updated
+to reflect the deleted field.  Applications should never modify the FeatureDefn
+used by a layer directly.
+<p>
+This method should not be called while there are feature objects in existance that
+were obtained or created with the previous layer definition.
+<p>
+Not all drivers support this method. You can query a layer to check if it supports it
+with the OLCDeleteField 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.
+
+ at param iField index of the field to delete.
+
+ at return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
+
+ at since OGR 1.9.0
+*/
+public class Layer:public int DeleteField( int iField )
+
+/**
+Reorder all the fields of a layer.
+<p>
+You must use this to reorder existing fields
+on a real layer. Internally the FeatureDefn for the layer will be updated
+to reflect the reordering of the fields.  Applications should never modify the FeatureDefn
+used by a layer directly.
+<p>
+This method should not be called while there are feature objects in existance that
+were obtained or created with the previous layer definition.
+<p>
+panMap is such that,for each field definition at position i after reordering,
+its position before reordering was panMap[i].
+<p>
+For example, let suppose the fields were "0","1","2","3","4" initially.
+ReorderFields(new Integer[]{0,2,3,1,4}) will reorder them as "0","2","3","1","4".
+<p>
+Not all drivers support this method. You can query a layer to check if it supports it
+with the OLCReorderFields 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.
+
+ at param panMap an array of GetLayerDefn().GetFieldCount() elements which
+is a permutation of [0, GetLayerDefn().GetFieldCount()-1].
+
+ at return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
+
+ at since OGR 1.9.0
+*/
+public class Layer:public int ReorderFields( int[] panMap )
+
+/**
+Reorder an existing field on a layer.
+<p>
+This method is a conveniency wrapper of ReorderFields() dedicated to move a single field.
+It is a non-virtual method, so drivers should implement ReorderFields() instead.
+<p>
+You must use this to reorder existing fields
+on a real layer. Internally the FeatureDefn for the layer will be updated
+to reflect the reordering of the fields.  Applications should never modify the FeatureDefn
+used by a layer directly.
+<p>
+This method should not be called while there are feature objects in existance that
+were obtained or created with the previous layer definition.
+<p>
+The field definition that was at initial position iOldFieldPos will be moved at
+position iNewFieldPos, and elements between will be shuffled accordingly.
+<p>
+For example, let suppose the fields were "0","1","2","3","4" initially.
+ReorderField(1, 3) will reorder them as "0","2","3","1","4".
+<p>
+Not all drivers support this method. You can query a layer to check if it supports it
+with the OLCReorderFields 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.
+
+ at param iOldFieldPos previous position of the field to move. Must be in the range [0,GetFieldCount()-1].
+ at param iNewFieldPos new position of the field to move. Must be in the range [0,GetFieldCount()-1].
+
+ at return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
+
+ at since OGR 1.9.0
+*/
+public class Layer:public int ReorderField( int iOldFieldPos, int iNewFieldPos )
+
+/**
+Alter the definition of an existing field on a layer.
+<p>
+You must use this to alter the definition of an existing field of a real layer.
+Internally the FeatureDefn for the layer will be updated
+to reflect the altered field.  Applications should never modify the FeatureDefn
+used by a layer directly.
+<p>
+This method should not be called while there are feature objects in existance that
+were obtained or created with the previous layer definition.
+<p>
+Not all drivers support this method. You can query a layer to check if it supports it
+with the OLCAlterFieldDefn 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. Some drivers might also not support
+all update flags.
+
+ at param iField index of the field whose definition must be altered.
+ at param newFieldDefn new field definition
+ at param nFlags combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and ALTER_WIDTH_PRECISION_FLAG
+to indicate which of the name and/or type and/or width and precision fields from the new field
+definition must be taken into account.
+
+ at return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
 
+ at since OGR 1.9.0
+*/
+public class Layer:public int AlterFieldDefn( int iField, FieldDefn newFieldDefn, int nFlags )
+
+/**
+ Fetch the extent of this layer.
+ <p>
  Returns the extent (MBR) of the data in the layer.  If force is 0,
  and it would be expensive to establish the extent then a RuntimeException
  will be throwned indicating that the extent isn't know.  If force is 
@@ -6373,7 +6642,7 @@ public class Layer:public int GetExtent(double[] extent, int force)
 
 /**
  Fetch the extent of this layer.
-
+ <p>
  Returns the extent (MBR) of the data in the layer.  If force is false,
  and it would be expensive to establish the extent then a null value
  will be returned indicating that the extent isn't know.  If force is 
@@ -6452,7 +6721,7 @@ public class Layer:public Feature GetFeature(int fid)
 
 /**
  Fetch the feature count in this layer. 
-
+ <p>
  Returns the number of features in the layer.  For dynamic databases the
  count may not be exact.  If force is 0, and it would be expensive
  to establish the feature count a value of -1 may be returned indicating
@@ -6470,7 +6739,7 @@ public class Layer:public int GetFeatureCount(int force)
 
 /**
   * Fetch the feature count in this layer.
-  *
+  * <p>
   * Same as below with force == 1.
   *
   * @see #GetFeatureCount(int force)
@@ -6481,6 +6750,7 @@ public class Layer:public int GetFeatureCount()
 
 /**
   * Return the total number of features read.
+  * <p>
   * Note: not all drivers seem to update properly this count.
   * @return total number of features read.
   *
@@ -6490,7 +6760,7 @@ public class Layer:public long GetFeaturesRead()
 
 /**
  Returns the name of the FID column.
-
+ <p>
  This method returns the name of the underlying database column
  being used as the FID column, or "" if not supported.
 
@@ -6500,7 +6770,7 @@ public class Layer:public String GetFIDColumn()
 
 /**
  Returns the name of the geometry column.
-
+ <p>
  This method returns the name of the underlying database column
  being used as the geometry column, or "" if not supported.
 
@@ -6511,13 +6781,13 @@ public class Layer:public String GetGeometryColumn()
 
 /**
  Set which fields can be omitted when retrieving features from the layer.
-
+ <p>
  If the driver supports this functionality (testable using OLCIgnoreFields capability), it will not fetch the specified fields
  in subsequent calls to GetFeature() / GetNextFeature() and thus save some processing time and/or bandwidth.
-
+ <p>
  Besides field names of the layers, the following special fields can be passed: "OGR_GEOMETRY" to ignore geometry and
  "OGR_STYLE" to ignore layer style.
-
+ <p>
  By default, no fields are ignored.
 
  @param fieldNames a vector of field names. If null is passed, the ignored list is cleared.
@@ -6529,7 +6799,7 @@ public class Layer:public int SetIgnoredFields(java.util.Vector fieldNames)
 
 /** 
  Fetch the schema information for this layer.
-
+ <p>
  The returned FeatureDefn is owned by the Layer, and should not be
  modified or freed by the application.  It encapsulates the attribute schema
  of the features of the layer. 
@@ -6540,7 +6810,7 @@ public class Layer:public FeatureDefn GetLayerDefn()
 
 /**
  * Return the layer name.
- *
+ * <p>
  * This returns the same content as GetLayerDefn().GetName(), but for a
  * few drivers, calling GetName() directly can avoid lengthy layer
  * definition initialization.
@@ -6551,7 +6821,7 @@ public class Layer:public String GetName()
 
 /**
  * Return the layer geometry type.
- *
+ * <p>
  * This returns the same result as GetLayerDefn().GetGeomType(), but for a
  * few drivers, calling GetGeomType() directly can avoid lengthy layer
  * definition initialization.
@@ -6564,7 +6834,7 @@ public class Layer:public int GetGeomType()
 
 /**
  Fetch the next available feature from this layer.
-
+ <p>
  Only features matching the current spatial filter (set with 
  <a href="#SetSpatialFilter(org.gdal.ogr.Geometry)")>SetSpatialFilter()</a> will be returned. 
  <p>
@@ -6581,7 +6851,7 @@ public class Layer:public Feature GetNextFeature()
 
 /**
  Fetch reference count.
-
+ <p>
  Should be of little use in Java...
 
  @return the current reference count for the layer object itself.
@@ -6610,7 +6880,7 @@ public class Layer:public void ResetReading()
 
 /** 
  Set a new attribute query.
-
+ <p>
  This method sets the attribute query string to be used when 
  fetching features via the <a href="#GetNextFeature()">GetNextFeature()</a> method.  Only features for which
  the query evaluates as true will be returned.
@@ -6635,7 +6905,7 @@ public class Layer:public int SetAttributeFilter(String filter_string)
 
 /**
  Rewrite an existing feature.
-
+ <p>
  This method will write a feature to the layer, based on the feature id
  within the Feature.
  <p>
@@ -6652,7 +6922,7 @@ public class Layer:public int SetFeature(Feature feature)
 
 /**
  Move read cursor to the new_index'th feature in the current resultset. 
-
+ <p>
  This method allows positioning of a layer such that the <a href="#GetNextFeature()">GetNextFeature()</a>
  call will read the requested feature, where nIndex is an absolute index
  into the current result set.   So, setting it to 3 would mean the next
@@ -6676,7 +6946,7 @@ public class Layer:public int SetNextByIndex(int new_index)
 
 /** 
  Set a new spatial filter. 
-
+ <p>
  This method set the geometry to be used as a spatial filter when 
  fetching features via the <a href="#GetNextFeature()">GetNextFeature()</a> method.  Only features that
  geometrically intersect the filter geometry will be returned.  
@@ -6726,7 +6996,7 @@ public class Layer:public void SetSpatialFilterRect(double minx, double miny, do
 
 /**
 Flush pending changes to disk.
-
+<p>
 This call is intended to force the layer to flush any pending writes to
 disk, and leave the disk file in a consistent state.  It would not normally
 have any effect on read-only datasources. 
@@ -6741,7 +7011,9 @@ public class Layer:public int SyncToDisk()
 
 /**
  For datasources which support transactions, StartTransaction creates 
- a transaction. If starting the transaction fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
+ a transaction.
+ <p>
+ If starting the transaction fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
  Datasources which do not support transactions will always return 0.
 
  @return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
@@ -6750,7 +7022,9 @@ public class Layer:public int StartTransaction()
 
 /**
  For datasources which support transactions, CommitTransaction commits a 
- transaction.  If no transaction is active, or the commit fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
+ transaction.
+ <p>
+ If no transaction is active, or the commit fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
  Datasources which do not support transactions will always return 0.
 
  @return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
@@ -6760,7 +7034,8 @@ public class Layer:public int CommitTransaction()
 /**
 
  For datasources which support transactions, RollbackTransaction will roll 
- back a datasource to its state before the start of the current transaction. 
+ back a datasource to its state before the start of the current transaction.
+ <p>
  If no transaction is active, or the rollback fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
  Datasources which do not support transactions will always return 0.
 
@@ -6770,7 +7045,7 @@ public class Layer:public int RollbackTransaction()
 
 /**
  Test if this layer supported the named capability.
-
+ <p>
  The capability codes that can be tested are represented as strings, but
  ogrConstants constants exists to ensure correct spelling.  Specific layer 
  types may implement class specific capabilities, but this can't generally
@@ -6815,6 +7090,15 @@ 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>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
+existing fields on the current layer using DeleteField(), otherwise false.<p>
+
+ <li> <b>OLCReorderFields</b> / "ReorderFields": TRUE if this layer can reorder
+existing fields on the current layer using ReorderField() or ReorderFields(), otherwise false.<p>
+
+ <li> <b>OLCAlterFieldDefn</b> / "AlterFieldDefn": TRUE if this layer can alter
+the definition of an existing field on the current layer using AlterFieldDefn(), otherwise false.<p>
+
  <li> <b>OLCDeleteFeature</b> / "DeleteFeature": true if the DeleteFeature()
 method is supported on this layer, otherwise false.<p>
 
@@ -6856,7 +7140,7 @@ public class Feature
 
 /**
  * Constructor.
- *
+ * <p>
  * Note that the Feature will increment the reference count of its
  * defining FeatureDefn.
  *
@@ -6867,7 +7151,7 @@ public class Feature:public Feature(FeatureDefn feature_def)
 
 /**
  * Duplicate feature.
- *
+ * <p>
  * The newly created feature is owned by the caller, and will have its own
  * reference to the FeatureDefn.
  *
@@ -6877,6 +7161,7 @@ public class Feature:public Feature Clone()
 
 /**
  * Delete (in memory) a feature.
+ * <p>
  * Calling this method is not required as normal garbage collection will
  * reclaim associated resources when the object goes out of scope.
  * Otherwise calling delete() explicitely will help release resources sooner.
@@ -6886,7 +7171,7 @@ public class Feature:public void delete()
 
 /**
  * Dump this feature in a human readable form.
- *
+ * <p>
  * This dumps the attributes, and geometry; however, it doesn't definition
  * information (other than field types and names), nor does it report the
  * geometry spatial reference system.
@@ -6896,7 +7181,7 @@ public class Feature:public void DumpReadable()
 
 /**
  * Test if two features are the same.
- *
+ * <p>
  * Two features are considered equal if they share the (pointer equality)
  * same FeatureDefn, have the same field values, and the same geometry
  * (as tested by Geometry.Equal()) as well as the same feature id.
@@ -6923,7 +7208,7 @@ public class Feature:public int GetFID()
 
 /**
  * Fetch field value as date and time.
- *
+ * <p>
  * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
  *
  * @param ifield the field to fetch, from 0 to GetFieldCount()-1.
@@ -6939,7 +7224,7 @@ public class Feature:public void GetFieldAsDateTime(int ifield, int[] pnYear, in
 
 /**
  * Fetch field value as a double.
- *
+ * <p>
  * OFTString features will be translated using atof().  OFTInteger fields
  * will be cast to double.   Other field types, or errors will result in
  * a return value of zero.
@@ -6952,7 +7237,7 @@ public class Feature:public double GetFieldAsDouble(int ifield)
 
 /**
  * Fetch field value as a double.
- *
+ * <p>
  * OFTString features will be translated using atof().  OFTInteger fields
  * will be cast to double.   Other field types, or errors will result in
  * a return value of zero.
@@ -6965,7 +7250,7 @@ public class Feature:public double GetFieldAsDouble(String name)
 
 /**
  * Fetch field value as a list of doubles.
- *
+ * <p>
  * Currently this method only works for OFTRealList fields.
  *
  * @param ifield the field to fetch, from 0 to GetFieldCount()-1.
@@ -6978,7 +7263,7 @@ public class Feature:public double[] GetFieldAsDoubleList(int ifield)
 
 /**
  * Fetch field value as integer.
- *
+ * <p>
  * OFTString features will be translated using atoi().  OFTReal fields
  * will be cast to integer.   Other field types, or errors will result in
  * a return value of zero.
@@ -6991,7 +7276,7 @@ public class Feature:public int GetFieldAsInteger(int ifield)
 
 /**
  * Fetch field value as integer.
- *
+ * <p>
  * OFTString features will be translated using atoi().  OFTReal fields
  * will be cast to integer.   Other field types, or errors will result in
  * a return value of zero.
@@ -7004,7 +7289,7 @@ public class Feature:public int GetFieldAsInteger(String name)
 
 /**
  * Fetch field value as a list of integers.
- *
+ * <p>
  * Currently this method only works for OFTIntegerList fields.
  *
  * @param ifield the field to fetch, from 0 to GetFieldCount()-1.
@@ -7017,7 +7302,7 @@ public class Feature:public int[] GetFieldAsIntegerList(int ifield)
 
 /**
  * Fetch field value as a string.
- *
+ * <p>
  * OFTReal and OFTInteger fields will be translated to string using
  * sprintf(), but not necessarily using the established formatting rules.
  * Other field types, or errors will result in a return value of zero.
@@ -7030,7 +7315,7 @@ public class Feature:public String GetFieldAsString(int ifield)
 
 /**
  * Fetch field value as a string.
- *
+ * <p>
  * OFTReal and OFTInteger fields will be translated to string using
  * sprintf(), but not necessarily using the established formatting rules.
  * Other field types, or errors will result in a return value of zero.
@@ -7043,7 +7328,7 @@ public class Feature:public String GetFieldAsString(String name)
 
 /**
  * Fetch field value as a list of strings.
- *
+ * <p>
  * Currently this method only works for OFTStringList fields.
  *
  * @param ifield the field to fetch, from 0 to GetFieldCount()-1.
@@ -7094,7 +7379,7 @@ public class Feature:public int GetFieldIndex(String name)
 
 /**
  * Fetch the field type.
- *
+ * <p>
  * This is a cover for the FeatureDefn.GetFieldType() method. 
  *
  * @param ifield the field to fetch, from 0 to GetFieldCount()-1.
@@ -7105,7 +7390,7 @@ public class Feature:public int GetFieldType(int ifield)
 
 /**
  * Fetch the field type.
- *
+ * <p>
  * This is a cover for the FeatureDefn.GetFieldType() method. 
  *
  * @param name the name of the field to fetch.
@@ -7124,7 +7409,7 @@ public class Feature:public Geometry GetGeometryRef()
 
 /**
  * Fetch style string for this feature.
- *
+ * <p>
  * Set the OGR Feature Style Specification for details on the format of
  * this string, and ogr_featurestyle.h for services available to parse it.
  * 
@@ -7153,7 +7438,7 @@ public class Feature:public boolean IsFieldSet(String name)
 
 /**
  * Set the feature identifier.
- *
+ * <p>
  * For specific types of features this operation may fail on illegal
  * features ids.  Generally it always succeeds.  Feature ids should be
  * greater than or equal to zero, with the exception of OGRNullFID (-1)
@@ -7167,7 +7452,7 @@ public class Feature:public int SetFID(int fid)
 
 /**
  * Set field to double value. 
- *
+ * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
  * taking into account formatting constraints on this field.  Other field
@@ -7180,7 +7465,7 @@ public class Feature:public void SetField(int ifield, double val)
 
 /**
  * Set field to integer value. 
- *
+ * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
  * taking into account formatting constraints on this field.  Other field
@@ -7193,7 +7478,7 @@ public class Feature:public void SetField(int ifield, int val)
 
 /**
  * Set field to date.
- *
+ * <p>
  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
  * fields.
  *
@@ -7210,7 +7495,7 @@ public class Feature:public void SetField(int ifield, int year, int month, int d
 
 /**
  * Set field to string value. 
- *
+ * <p>
  * OFTInteger fields will be set based on an atoi() conversion of the string.
  * OFTReal fields will be set based on an atof() conversion of the string.
  * Other field types may be unaffected.
@@ -7222,7 +7507,7 @@ public class Feature:public void SetField(int ifield, String val)
 
 /**
  * Set field to double value. 
- *
+ * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
  * taking into account formatting constraints on this field.  Other field
@@ -7235,7 +7520,7 @@ public class Feature:public void SetField(String name, double val)
 
 /**
  * Set field to integer value. 
- *
+ * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
  * taking into account formatting constraints on this field.  Other field
@@ -7248,7 +7533,7 @@ public class Feature:public void SetField(String name, int val)
 
 /**
  * Set field to date.
- *
+ * <p>
  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
  * fields.
  *
@@ -7265,7 +7550,7 @@ public class Feature:public void SetField(String name, int year, int month, int
 
 /**
  * Set field to string value. 
- *
+ * <p>
  * OFTInteger fields will be set based on an atoi() conversion of the string.
  * OFTReal fields will be set based on an atof() conversion of the string.
  * Other field types may be unaffected.
@@ -7277,7 +7562,7 @@ public class Feature:public void SetField(String name, String val)
 
 /**
  * Set field to list of doubles value. 
- *
+ * <p>
  * This method currently on has an effect of OFTRealList fields.
  *
  * @param ifield the field to set, from 0 to GetFieldCount()-1.
@@ -7288,7 +7573,7 @@ public class Feature:public void SetFieldDoubleList(int ifield, double[] values)
 
 /**
  * Set field to list of integers value. 
- *
+ * <p>
  * This method currently on has an effect of OFTIntegerList fields.
  *
  * @param ifield the field to set, from 0 to GetFieldCount()-1.
@@ -7298,7 +7583,7 @@ public class Feature:public void SetFieldIntegerList(int ifield, int[] values)
 
 /**
  * Set field to list of strings value. 
- *
+ * <p>
  * This method currently on has an effect of OFTStringList fields.
  *
  * @param ifield the field to set, from 0 to GetFieldCount()-1.
@@ -7311,7 +7596,7 @@ public class Feature:public void SetFieldStringList(int ifield, java.util.Vector
 
 /**
  * Set one feature from another.
- *
+ * <p>
  * Overwrite the contents of this feature from the geometry and attributes
  * of another.  The srcFeature does not need to have the same
  * FeatureDefn.  Field values are copied by corresponding field names.
@@ -7333,7 +7618,7 @@ public class Feature:public int SetFrom(Feature srcFeature, int forgiving)
 
 /**
  * Set one feature from another.
- *
+ * <p>
  * Same as below with forgiving == 1
  *
  * @see #SetFrom(Feature srcFeature, int forgiving)
@@ -7344,7 +7629,7 @@ public class Feature:public int SetFrom(Feature srcFeature)
 
 /**
  * Set one feature from another.
- *
+ * <p>
  * Overwrite the contents of this feature from the geometry and attributes
  * of another.  The hOtherFeature does not need to have the same
  * OGRFeatureDefn.  Field values are copied according to the provided indices
@@ -7377,7 +7662,7 @@ public class Feature:public int SetFromWithMap(Feature srcFeature, int forgiving
 
 /**
  * Set feature geometry.
- *
+ * <p>
  * This method updates the features geometry, and operate exactly as
  * SetGeometryDirectly(), except that this method does not assume ownership
  * of the passed geometry, but instead makes a copy of it. 
@@ -7394,7 +7679,7 @@ public class Feature:public int SetGeometry(Geometry geom)
 
 /**
  * Set feature geometry.
- *
+ * <p>
  * This method updates the features geometry, and operate exactly as
  * SetGeometry(), except that this method assumes ownership of the
  * passed geometry.
@@ -7439,11 +7724,6 @@ public class Feature:public void UnsetField(String name)
  * <p>
  * The Geometry class is a binding for the C++ <a href="http://gdal.org/ogr/classOGRGeometry.html">OGRGeometry</a> class.
  * <p>
- * Note that the family of spatial analysis methods (Equal(), Disjoint(), ...,
- * ConvexHull(), Buffer(), ...) are not implemented at ths time.  Some other
- * required and optional geometry methods have also been omitted at this
- * time.
- * <p>
  * Some spatial analysis methods require that OGR is built on the GEOS library
  * to work properly. The precise meaning of methods that describe spatial relationships
  * between geometries is described in the SFCOM, or other simple features interface
@@ -7456,7 +7736,7 @@ public class Geometry
 
 /** 
  * Create an empty geometry of desired type.
- *
+ * <p>
  * The type may be one of ogr.wkbPoint, etc..
  *
  * @param eGeometryType the type code of the geometry class to be instantiated.
@@ -7467,7 +7747,7 @@ public class Geometry:public Geometry(int eGeometryType)
 
 /** 
  * Create a new geometry.
- *
+ * <p>
  * The geometry can be instanciated by 4 different and exclusive way :
  * <ul>
  * <li> By specifying the geometry type (ogr.wkbPoint, etc..)</li>
@@ -7494,7 +7774,7 @@ public class Geometry:public Geometry(int eGeometryType, String wkt, byte[] wkb,
 
 /**
  * Add a geometry to the container.
- *
+ * <p>
  * Some subclasses of OGRGeometryCollection restrict the types of geometry
  * that can be added, and may return an error.  The passed geometry is cloned
  * to make an internal copy.
@@ -7514,7 +7794,7 @@ public class Geometry:public int AddGeometry(Geometry other)
 
 /**
  * Add a geometry directly to the container.
- *
+ * <p>
  * Some subclasses of OGRGeometryCollection restrict the types of geometry
  * that can be added, and may return an error.  Ownership of the passed
  * geometry is taken by the container rather than cloning as addGeometry()
@@ -7535,7 +7815,7 @@ public class Geometry:public int AddGeometryDirectly(Geometry other)
 
 /**
  * Add a point to a geometry (line string or point).
- *
+ * <p>
  * The vertex count of the line string is increased by one, and assigned from
  * the passed location value.
  *
@@ -7546,7 +7826,7 @@ public class Geometry:public void AddPoint_2D(double x, double y)
 
 /**
  * Add a point to a geometry (line string or point).
- *
+ * <p>
  * The vertex count of the line string is increased by one, and assigned from
  * the passed location value.
  *
@@ -7558,7 +7838,7 @@ public class Geometry:public void AddPoint(double x, double y, double z)
 
 /**
  * Add a point to a geometry (line string or point).
- *
+ * <p>
  * The vertex count of the line string is increased by one, and assigned from
  * the passed location value.
  *
@@ -7570,7 +7850,9 @@ public class Geometry:public void AddPoint(double x, double y, double z)
 public class Geometry:public void AddPoint(double x, double y)
 
 /**
- * Assign spatial reference to this object.  Any existing spatial reference
+ * Assign spatial reference to this object.
+ * <p>
+ * Any existing spatial reference
  * is replaced, but under no circumstances does this result in the object
  * being reprojected.  It is just changing the interpretation of the existing
  * geometry.  Note that assigning a spatial reference increments the
@@ -7585,7 +7867,7 @@ public class Geometry:public void AssignSpatialReference(SpatialReference srs)
 
 /**
  * Compute buffer of geometry.
- *
+ * <p>
  * Builds a new geometry containing the buffer region around the geometry
  * on which it is invoked.  The buffer is a polygon containing the region within
  * the buffer distance of the original geometry.  
@@ -7612,7 +7894,7 @@ public class Geometry:public Geometry Buffer(double distance, int quadsecs)
 
 /**
  * Compute buffer of geometry.
- *
+ * <p>
  * Same as below with quadsecs == 30.
  *
  * @see #Buffer(double distance, int quadsecs)
@@ -7644,7 +7926,7 @@ public class Geometry:public Geometry Centroid()
 
 /**
  * Make a copy of this object.
- *
+ * <p>
  * This method relates to the SFCOM IGeometry::clone() method.
  * 
  * @return a new object instance with the same geometry, and spatial
@@ -7654,7 +7936,7 @@ public class Geometry:public Geometry Clone()
 
 /**
  * Force rings to be closed.
- *
+ * <p>
  * If this geometry, or any contained geometries has polygon rings that 
  * are not closed, they will be closed by adding the starting point at
  * the end. 
@@ -7663,7 +7945,7 @@ public class Geometry:public void CloseRings()
 
 /**
  * Test for containment.
- *
+ * <p>
  * Tests if actual geometry object contains the passed geometry.
  * <p>
  * This method is built on the GEOS library, check it for the definition
@@ -7678,7 +7960,7 @@ public class Geometry:public boolean Contains(Geometry other)
 
 /**
  * Compute convex hull.
- *
+ * <p>
  * A new geometry object is created and returned containing the convex
  * hull of the geometry on which the method is invoked.  
  * <p>
@@ -7692,7 +7974,7 @@ public class Geometry:public Geometry ConvexHull()
 
 /**
  * Create geometry from GML.
- *
+ * <p>
  * This method translates a fragment of GML containing only the geometry
  * portion into a corresponding Geometry.  There are many limitations
  * on the forms of GML geometries supported by this parser, but they are
@@ -7744,7 +8026,7 @@ public class Geometry:public static Geometry CreateFromWkt(String wkt)
 
 /**
  * Test for crossing.
- *
+ * <p>
  * Tests if this geometry and the other passed into the method are crossing.
  * <p>
  * This method is built on the GEOS library, check it for the definition
@@ -7759,6 +8041,7 @@ public class Geometry:public boolean Crosses(Geometry other)
 
 /**
  * Delete a geometry.
+ * <p>
  * Calling this method is not required as normal garbage collection will
  * reclaim associated resources when the object goes out of scope.
  * Otherwise calling delete() explicitely will help release resources sooner.
@@ -7768,7 +8051,7 @@ public class Geometry:public void delete()
 
 /**
  * Compute difference.
- *
+ * <p>
  * Generates a new geometry which is the region of this geometry with the
  * region of the second geometry removed. 
  * <p>
@@ -7785,7 +8068,7 @@ public class Geometry:public Geometry Difference(Geometry other)
 
 /**
  * Test for disjointness.
- *
+ * <p>
  * Tests if this geometry and the other passed into the method are disjoint. 
  * <p>
  * This method is built on the GEOS library, check it for the definition
@@ -7800,7 +8083,7 @@ public class Geometry:public boolean Disjoint(Geometry other)
 
 /**
  * Compute distance between two geometries.
- *
+ * <p>
  * Returns the shortest distance between the two geometries. 
  * <p>
  * This method is built on the GEOS library, check it for the definition
@@ -7814,7 +8097,9 @@ public class Geometry:public boolean Disjoint(Geometry other)
 public class Geometry:public double Distance(Geometry other)
 
 /**
- * Clear geometry information.  This restores the geometry to it's initial
+ * Clear geometry information.
+ * <p>
+ * This restores the geometry to it's initial
  * state after construction, and before assignment of actual geometry.
  * <p>
  * This method relates to the SFCOM IGeometry::Empty() method.
@@ -7830,7 +8115,7 @@ public class Geometry:public boolean Equal(Geometry other)
 
 /**
  * Convert a geometry into GML format.
- *
+ * <p>
  * The GML geometry is expressed directly in terms of GML basic data
  * types assuming the this is available in the gml namespace.
  *
@@ -7865,7 +8150,7 @@ public class Geometry:public String ExportToJson()
 
 /**
  * Convert a geometry into well known binary format.
- *
+ * <p>
  * This function relates to the SFCOM IWks::ExportToWKB() method.
  *
  * @param byte_order One of wkbXDR or wkbNDR indicating MSB or LSB byte order
@@ -7879,7 +8164,7 @@ public class Geometry:public byte[] ExportToWkb(int byte_order)
 
 /**
  * Convert a geometry into well known binary format.
- *
+ * <p>
  * This function relates to the SFCOM IWks::ExportToWKB() method.
  *
  * @param wkbArray a sufficiently large array (at least WkbSize() large) to receive the wkb content.
@@ -7892,7 +8177,7 @@ public class Geometry:public int ExportToWkb(byte[] wkbArray, int byte_order)
 
 /**
  * Convert a geometry into well known binary format.
- *
+ * <p>
  * This function relates to the SFCOM IWks::ExportToWKB() method.
  * MSB order (wkbXDR) will be used.
  *
@@ -7904,7 +8189,7 @@ public class Geometry:public byte[] ExportToWkb()
 
 /**
  * Convert a geometry into well known text format.
- *
+ * <p>
  * This method relates to the SFCOM IWks::ExportToWKT() method.
  *
  * @param argout an allocated array of 1 string where the WKT output will be inserted
@@ -7915,7 +8200,7 @@ public class Geometry:public int ExportToWkt(String[] argout)
 
 /**
  * Convert a geometry into well known text format.
- *
+ * <p>
  * This method relates to the SFCOM IWks::ExportToWKT() method.
  *
  * @return the WKT string
@@ -7925,14 +8210,16 @@ public class Geometry:public int ExportToWkt(String[] argout)
 public class Geometry:public String ExportToWkt()
 
 /**
- * Convert geometry to strictly 2D.  In a sense this converts all Z coordinates
+ * Convert geometry to strictly 2D.
+ * <p>
+ * In a sense this converts all Z coordinates
  * to 0.0.
  */
 public class Geometry:public void FlattenTo2D()
 
 /**
  * Compute geometry area.
- *
+ * <p>
  * Computes the area for an OGRLinearRing, OGRPolygon or OGRMultiPolygon.
  * Undefined for all other geometry types (returns zero).
  *
@@ -7953,7 +8240,7 @@ public class Geometry:public double GetArea()
 
 /**
  * Compute boundary.
- *
+ * <p>
  * A new geometry object is created and returned containing the boundary
  * of the geometry on which the method is invoked.
  * <p>
@@ -7978,7 +8265,7 @@ public class Geometry:public Geometry GetBoundary()
 
 /**
  * Get the dimension of the coordinates in this object.
- *
+ * <p>
  * This method corresponds to the SFCOM IGeometry::GetDimension() method.
  *
  * @return in practice this always returns 2 indicating that coordinates are
@@ -7988,7 +8275,7 @@ public class Geometry:public int GetCoordinateDimension()
 
 /**
  * Get the dimension of this object.
- *
+ * <p>
  * This method corresponds to the SFCOM IGeometry::GetDimension() method.
  * It indicates the dimension of the object, but does not indicate the
  * dimension of the underlying space (as indicated by
@@ -8000,7 +8287,7 @@ public class Geometry:public int GetDimension()
 
 /**
  * Computes and returns the bounding envelope for this geometry.
- *
+ * <p>
  * @param argout an allocated array of 4 doubles into which to place the result
  */
 public class Geometry:public void GetEnvelope(double[] argout)
@@ -8008,7 +8295,7 @@ public class Geometry:public void GetEnvelope(double[] argout)
 /**
  * Fetch the number of elements in a geometry or number of geometries in
  * container.
- *
+ * <p>
  * Only geometries of type wkbPolygon[25D], wkbMultiPoint[25D], wkbMultiLineString[25D],
  * wkbMultiPolygon[25D] or wkbGeometryCollection[25D] may return a valid value.
  * Other geometry types will silently return 0.
@@ -8021,7 +8308,7 @@ public class Geometry:public int GetGeometryCount()
 
 /**
  * Fetch WKT name for geometry type.
- *
+ * <p>
  * There is no SFCOM analog to this method.  
  *
  * @return name used for this geometry type in well known text format.
@@ -8030,7 +8317,7 @@ public class Geometry:public String GetGeometryName()
 
 /**
  * Fetch geometry from a geometry container.
- *
+ * <p>
  * This function returns an handle to a geometry within the container.
  * The returned geometry remains owned by the container, and should not be
  * modified.  The handle is only valid untill the next change to the
@@ -8050,7 +8337,7 @@ public class Geometry:public Geometry GetGeometryRef(int iSubGeom)
 
 /**
  * Fetch geometry type.
- *
+ * <p>
  * Note that the geometry type may include the 2.5D flag.  To get a 2D
  * flattened version of the geometry type apply the wkbFlatten() macro
  * to the return result.
@@ -8097,7 +8384,7 @@ public class Geometry:public double[] GetPoint_2D(int iPoint)
 
 /**
  * Fetch number of points from a geometry.
- *
+ * <p>
  * Only wkbPoint[25D] or wkbLineString[25D] may return a valid value.
  * Other geometry types will silently return 0.
  *
@@ -8106,8 +8393,40 @@ public class Geometry:public double[] GetPoint_2D(int iPoint)
 public class Geometry:public int GetPointCount()
 
 /**
- * Returns spatial reference system for object.
+ * Returns all points of a point or a line string.
+ * <p>
+ * This method returns an array of tuples with the [x,y] or [x,y,z] coordinates pair or triplets.
+ * <p>
+ * Only wkbPoint[25D] or wkbLineString[25D] may return a valid value.
+ * Other geometry types will return null.
+ *
+ * @param nCoordinateDimension if nCoordinateDimension == 0 then the number of coordinates per tuple
+ * will reflect the coordinate dimension of the geometry. If nCoordinateDimension == 2,
+ * the number of coordinates per tuple will be 2. If nCoordinateDimension == 3, the number of
+ * coordinates per tuple will be 3.
+ *
+ * @return the coordinates
+ *
+ * @since OGR 1.9.0
+ */
+public class Geometry:public double[][] GetPoints(int nCoordinateDimension)
+
+/**
+ * Returns all points of a point or a line string.
+ * <p>
+ * Same as below with nCoordinateDimension == 0
+ *
+ * @return the coordinates
  *
+ * @since OGR 1.9.0
+ *
+ * @see #GetPoints(int)
+ */
+public class Geometry:public double[][] GetPoints()
+
+/**
+ * Returns spatial reference system for object.
+ * <p>
  * This method relates to the SFCOM IGeometry::get_SpatialReference() method.
  *
  * @return a reference to the spatial reference object.  The object may be
@@ -8168,7 +8487,7 @@ public class Geometry:public double GetZ()
 
 /**
  * Do these features intersect?
- *
+ * <p>
  * Determines whether two geometries intersect.  If GEOS is enabled, then
  * this is done in rigerous fashion otherwise true is returned if the
  * envelopes (bounding boxes) of the two features overlap. 
@@ -8185,7 +8504,7 @@ public class Geometry:public boolean Intersect(Geometry other)
 
 /**
  * Compute intersection.
- *
+ * <p>
  * Generates a new geometry which is the region of intersection of the
  * two geometries operated on.  The Intersect() method can be used to test if
  * two geometries intersect. 
@@ -8202,7 +8521,9 @@ public class Geometry:public boolean Intersect(Geometry other)
 public class Geometry:public Geometry Intersection(Geometry other)
 
 /**
- * Returns true (non-zero) if the object has no points.  Normally this
+ * Returns true (non-zero) if the object has no points.
+ * <p>
+ * Normally this
  * returns false except between when an object is instantiated and points
  * have been assigned.
  *
@@ -8214,7 +8535,7 @@ public class Geometry:public boolean IsEmpty()
 
 /**
  * Test if the geometry is valid.
- *
+ * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
  * If OGR is built without the GEOS library, this method will always return 
@@ -8228,7 +8549,7 @@ public class Geometry:public boolean IsValid()
 
 /**
  * Test if the geometry is simple.
- *
+ * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
  * If OGR is built without the GEOS library, this method will always return 
@@ -8241,7 +8562,7 @@ public class Geometry:public boolean IsSimple()
 
 /**
  * Test if the geometry is a ring.
- *
+ * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
  * If OGR is built without the GEOS library, this method will always return 
@@ -8254,7 +8575,7 @@ public class Geometry:public boolean IsRing()
 
 /**
  * Test for overlap.
- *
+ * <p>
  * Tests if this geometry and the other passed into the method overlap, that is
  * their intersection has a non-zero area. 
  *
@@ -8270,7 +8591,7 @@ public class Geometry:public boolean Overlaps(Geometry other)
 
 /**
  * Modify the geometry such it has no segment longer then the given distance.
- *
+ * <p>
  * Interpolated points will have Z and M values (if needed) set to 0.
  * Distance computation is performed in 2d only
  *
@@ -8282,7 +8603,7 @@ public class Geometry:public void Segmentize(double max_length)
 
 /**
  * Set the coordinate dimension. 
- *
+ * <p>
  * This method sets the explicit coordinate dimension.  Setting the coordinate
  * dimension of a geometry to 2 should zero out any existing Z values.  Setting
  * the dimension of a geometry collection will not necessarily affect the
@@ -8294,7 +8615,7 @@ public class Geometry:public void SetCoordinateDimension(int dimension)
 
 /**
  * Set the location of a vertex in a point or linestring geometry.
- *
+ * <p>
  * If ipoint is larger than the number of existing
  * points in the linestring, the point count will be increased to
  * accomodate the request.
@@ -8308,7 +8629,7 @@ public class Geometry:public void SetPoint_2D(int ipoint, double x, double y)
 
 /**
  * Set the location of a vertex in a point or linestring geometry.
- *
+ * <p>
  * If ipoint is larger than the number of existing
  * points in the linestring, the point count will be increased to
  * accomodate the request.
@@ -8323,7 +8644,7 @@ public class Geometry:public void SetPoint(int ipoint, double x, double y, doubl
 
 /**
  * Set the location of a vertex in a point or linestring geometry.
- *
+ * <p>
  * If ipoint is larger than the number of existing
  * points in the linestring, the point count will be increased to
  * accomodate the request.
@@ -8339,7 +8660,7 @@ public class Geometry:public void SetPoint(int ipoint, double x, double y)
 
 /**
  * Simplify the geometry.
- *
+ * <p>
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
  * If OGR is built without the GEOS library, this function will always fail,
@@ -8353,10 +8674,26 @@ public class Geometry:public void SetPoint(int ipoint, double x, double y)
  */
 public class Geometry:public Geometry Simplify(double dTolerance)
 
+/**
+ * Simplify the geometry while preserving topology.
+ * <p>
+ * This function is built on the GEOS library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
+ *
+ * @param dTolerance the distance tolerance for the simplification.
+ *
+ * @return the simplified geometry or null if an error occurs.
+ *
+ * @since OGR 1.9.0
+ */
+public class Geometry:public Geometry SimplifyPreserveTopology(double dTolerance)
+
 
 /**
  * Compute symmetric difference.
- *
+ * <p>
  * Generates a new geometry which is the symmetric difference of this
  * geometry and the second geometry passed into the method.
  * <p>
@@ -8384,7 +8721,7 @@ public class Geometry:public Geometry SymmetricDifference(Geometry other)
 
 /**
  * Test for touching.
- *
+ * <p>
  * Tests if this geometry and the other passed into the method are touching.
  *
  * This method is built on the GEOS library, check it for the definition
@@ -8399,7 +8736,7 @@ public class Geometry:public boolean Touches(Geometry other)
 
 /**
  * Transform geometry to new spatial reference system.
- *
+ * <p>
  * This method will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
@@ -8425,7 +8762,7 @@ public class Geometry:public int TransformTo(SpatialReference srs)
 
 /**
  * Apply arbitrary coordinate transformation to geometry.
- *
+ * <p>
  * This method will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
@@ -8446,7 +8783,7 @@ public class Geometry:public int Transform(CoordinateTransformation ct)
 
 /**
  * Compute union.
- *
+ * <p>
  * Generates a new geometry which is the region of union of the
  * two geometries operated on.  
  * <p>
@@ -8462,7 +8799,7 @@ public class Geometry:public Geometry Union(Geometry other)
 
 /**
  * Compute union using cascading.
- *
+ * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
  * If OGR is built without the GEOS library, this method will always fail,
@@ -8476,7 +8813,7 @@ public class Geometry:public Geometry UnionCascaded()
 
 /**
  * Test for containment.
- *
+ * <p>
  * Tests if actual geometry object is within the passed geometry.
  *
  * This method is built on the GEOS library, check it for the definition
@@ -8491,7 +8828,7 @@ public class Geometry:public boolean Within(Geometry other)
 
 /**
  * Returns size of related binary representation.
- *
+ * <p>
  * This method returns the exact number of bytes required to hold the
  * well known binary representation of this geometry object.  Its computation
  * may be slightly expensive for complex geometries.
@@ -8529,7 +8866,7 @@ public class FeatureDefn
 
 /**
  * Constructor.
- *
+ * <p>
  * The FeatureDefn maintains a reference count, but this starts at
  * zero.  It is mainly intended to represent a count of Feature's
  * based on this definition.
@@ -8539,7 +8876,7 @@ public class FeatureDefn:public FeatureDefn()
 
 /**
  * Constructor.
- *
+ * <p>
  * The FeatureDefn maintains a reference count, but this starts at
  * zero.  It is mainly intended to represent a count of Feature's
  * based on this definition.
@@ -8553,7 +8890,10 @@ public class FeatureDefn:public FeatureDefn(String name)
 
 /**
  * Add a new field definition.
- *
+ * <p>
+ * To add a new field definition to a layer definition, do not use this
+ * function directly, but use Layer.<a href="Layer.html#CreateField(org.gdal.ogr.FieldDefn)">CreateField()</a> instead.
+ * <p>
  * This method should only be called while there are no Feature
  * objects in existance based on this FeatureDefn.  The FieldDefn
  * passed in is copied, and remains the responsibility of the caller.
@@ -8588,7 +8928,7 @@ public class FeatureDefn:public FieldDefn GetFieldDefn(int ifield)
 
 /**
  * Find field by name.
- *
+ * <p>
  * The field index of the first field matching the passed field name (case
  * insensitively) is returned.
  *
@@ -8636,7 +8976,7 @@ public class FeatureDefn:public void SetStyleIgnored(int bIgnore)
 
 /**
  * Fetch the geometry base type.
- *
+ * <p>
  * Note that some drivers are unable to determine a specific geometry
  * type for a layer, in which case wkbUnknown is returned.  A value of
  * wkbNone indicates no geometry is available for the layer at all.
@@ -8650,7 +8990,7 @@ public class FeatureDefn:public int GetGeomType()
 
 /**
  * Assign the base geometry type for this layer.
- *
+ * <p>
  * All geometry objects using this type must be of the defined type or
  * a derived type.  The default upon creation is wkbUnknown which allows for
  * any geometry type.  The geometry type should generally not be changed
@@ -8680,7 +9020,7 @@ public class FieldDefn
 
 /**
  * Constructor.
- *
+ * <p>
  * The new field will be named "unnamed" and of type OFTString
  *
  * @since Java bindings 1.7.0
@@ -8689,7 +9029,7 @@ public class FieldDefn:public FieldDefn()
 
 /**
  * Constructor.
- *
+ * <p>
  * The new field will be of type OFTString
  * @param name the name of the new field.
  *
@@ -8743,7 +9083,9 @@ public class FieldDefn:public String GetName()
 public class FieldDefn:public String GetNameRef()
 
 /**
- * Get the formatting precision for this field.  This should normally be
+ * Get the formatting precision for this field.
+ * <p>
+ * This should normally be
  * zero for fields of types other than OFTReal.
  *
  * @return the precision.
@@ -8780,7 +9122,7 @@ public class FieldDefn:public void SetName(String name)
 
 /**
  * Set the formatting precision for this field in characters.
- * 
+ *  <p>
  * This should normally be zero for fields of types other than OFTReal. 
  *
  * @param precision the new precision. 
@@ -8788,7 +9130,9 @@ public class FieldDefn:public void SetName(String name)
 public class FieldDefn:public void SetPrecision(int precision)
 
 /**
- * Set the type of this field.  This should never be done to an FieldDefn
+ * Set the type of this field.
+ * <p>
+ * This should never be done to an FieldDefn
  * that is already part of an FeatureDefn.
  *
  * @param type the new field type.
@@ -8831,7 +9175,7 @@ public class ogr
 
 /**
  * Use exceptions instead of error return codes.
- *
+ * <p>
  * This is the default behavious : methods that in C/C++ return an OGRErr return code
  * would throw a RuntimeException() in case the code it is different
  * from ogr.OGRERR_NONE. By calling this method, you can get
@@ -8844,7 +9188,7 @@ public class ogr:public static void UseExceptions()
 
 /**
  * Use return code instead of exceptions.
- *
+ * <p>
  * By default, methods that in C/C++ return an OGRErr return code
  * would throw a RuntimeException() in case the code it is different
  * from ogr.OGRERR_NONE. By calling this method, you can prevent
@@ -8858,7 +9202,7 @@ public class ogr:public static void DontUseExceptions()
 
 /**
  * Stroke arc to linestring.
- *
+ * <p>
  * Stroke an arc of a circle to a linestring based on a center
  * point, radius, start angle and end angle, all angles in degrees.
  *
@@ -8880,7 +9224,7 @@ public class ogr:public static Geometry ApproximateArcAngles(double dfCenterX, d
 
 /**
  * Build a ring from a bunch of arcs.
- *
+ * <p>
  * Same as below with bAutoClose == 0 and dfTolerance == 0.
  *
  * @see #BuildPolygonFromEdges(Geometry lineCollection, int bBestEffort, int bAutoClose, double dfTolerance)
@@ -8891,7 +9235,7 @@ public class ogr:public static Geometry BuildPolygonFromEdges(Geometry hLineColl
 
 /**
  * Build a ring from a bunch of arcs.
- *
+ * <p>
  * Same as below with dfTolerance == 0.
  *
  * @see #BuildPolygonFromEdges(Geometry lineCollection, int bBestEffort, int bAutoClose, double dfTolerance)
@@ -8970,7 +9314,7 @@ public class ogr:public static Geometry CreateGeometryFromWkt(String wkt, Spatia
 
    /**
     * General utility option processing.
-    *
+    * <p>
     * This function is intended to provide a variety of generic commandline 
     * options for all OGR commandline utilities.  It takes care of the following
     * commandline options:
@@ -9006,7 +9350,7 @@ public class ogr:public static String[] GeneralCmdLineProcessor(String[] args, i
 
    /**
     * General utility option processing.
-    *
+    * <p>
     * Same as below with options == 0
     *
     * @see #GeneralCmdLineProcessor(String[] args, int options)
@@ -9017,7 +9361,7 @@ public class ogr:public static String[] GeneralCmdLineProcessor(String[] args)
 
    /**
     * General utility option processing.
-    *
+    * <p>
     * Same as below but with arguments as a Vector of strings
     *
     * @return updated argument list as a new Vector of strings
@@ -9030,7 +9374,7 @@ public class ogr:public static java.util.Vector GeneralCmdLineProcessor(java.uti
 
    /**
     * General utility option processing.
-    *
+    * <p>
     * Same as below but with arguments as a Vector of strings and options == 0
     *
     * @return updated argument list as a new Vector of strings
@@ -9104,7 +9448,7 @@ public class ogr:public static int GetOpenDSCount()
 
 /**
   * Open a file / data source with one of the registered drivers.
-  *
+  * <p>
   * Same as below with update == 0
   *
   * @see #Open(String filename, int update)
@@ -9115,7 +9459,7 @@ public class ogr:public static DataSource Open(String filename)
 
 /**
   * Open a file / data source with one of the registered drivers.
-  *
+  * <p>
   * Same as below with boolean value being transformed to 1 (for true) or 0 (for false)
   *
   * @see #Open(String filename, int update)
@@ -9126,7 +9470,7 @@ public class ogr:public static DataSource Open(String filename, boolean update)
 
 /**
   Open a file / data source with one of the registered drivers.
-
+  <p>
   This method loops through all the drivers registered with the driver
   manager trying each until one succeeds with the given data source.
   <p>
@@ -9163,7 +9507,7 @@ public class ogr:public static DataSource Open(String filename, int update)
 
 /**
   * Open a file / data source with one of the registered drivers.
-  *
+  * <p>
   * This first try finding an existing open dataset matching exactly
   * on the original datasource raw name used to open the
   * datasource.
@@ -9180,7 +9524,7 @@ public class ogr:public static DataSource OpenShared(String filename)
 
 /**
   * Open a file / data source with one of the registered drivers.
-  *
+  * <p>
   * This first try finding an existing open dataset matching exactly
   * on the original datasource raw name used to open the
   * datasource.
@@ -9195,7 +9539,7 @@ public class ogr:public static DataSource OpenShared(String filename, int update
 
 /**
  * Register all known configured OGR drivers.
- *
+ * <p>
  * This function will drive any of the following that are configured into
  * OGR.  Many others as well that haven't been updated in this
  * documentation (see <a href="http://gdal.org/ogr/ogr_formats.html">full list</a>):
@@ -9244,7 +9588,7 @@ public class ogr:public static void RegisterAll()
 
 /**
   * Special entry point to enable the hack for generating DB2 V7.2 style WKB.
-  *
+  * <p>
   * DB2 seems to have placed  (and require) an extra 0x30 or'ed with the byte order in
   * WKB.  This entry point is used to turn on or off the
   * generation of such WKB.
@@ -9253,10 +9597,10 @@ public class ogr:public static int SetGenerate_DB2_V72_BYTE_ORDER(int bGenerate_
 
 /**
  * Convert to polygon.
- *
+ * <p>
  * Tries to force the provided geometry to be a polygon.  Currently
  * this just effects a change on multipolygons.
- *
+ * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
  * 
  * @param geom the input geometry
@@ -9267,10 +9611,10 @@ public class ogr:public static Geometry ForceToPolygon(Geometry geom)
 
 /**
  * Convert to multipolygon.
- *
+ * <p>
  * Tries to force the provided geometry to be a multipolygon.  Currently
  * this just effects a change on polygons.
- *
+ * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
  * 
  * @param geom the input geometry
@@ -9281,10 +9625,10 @@ public class ogr:public static Geometry ForceToMultiPolygon(Geometry geom)
 
 /**
  * Convert to multipoint.
- *
+ * <p>
  * Tries to force the provided geometry to be a multipoint.  Currently
  * this just effects a change on points.
- *
+ * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
  * 
  * @param geom the input geometry
@@ -9295,7 +9639,7 @@ public class ogr:public static Geometry ForceToMultiPoint(Geometry geom)
 
 /**
  * Convert to multilinestring.
- *
+ * <p>
  * Tries to force the provided geometry to be a multilinestring.
  * <ul>
  * <li>linestrings are placed in a multilinestring.
@@ -9303,7 +9647,7 @@ public class ogr:public static Geometry ForceToMultiPoint(Geometry geom)
  * contain linestrings.
  * <li>polygons will be changed to a collection of linestrings (one per ring).
  * </ul>
- *
+ * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
  * 
  * @param geom the input geometry
@@ -9333,11 +9677,11 @@ public class SpatialReference
 
 /**
  * Constructor.
- *
+ * <p>
  * This constructor takes an optional string argument which if passed
  * should be a WKT representation of an SRS.  Passing this is equivelent
  * to not passing it, and then calling importFromWkt() with the WKT string.
- *
+ * <p>
  * Note that newly created objects are given a reference count of one. 
  *
  * @param wkt well known text definition to which the object should
@@ -9347,7 +9691,7 @@ public class SpatialReference:public SpatialReference(String wkt)
 
 /**
  * Constructor.
- *
+ * <p>
  * Same as below with wkt == null.
  *
  * @see #SpatialReference(String wkt)
@@ -9365,7 +9709,7 @@ public class SpatialReference:public String __str__()
 
 /**
  * Set EPSG authority info if possible.
- *
+ * <p>
  * This method inspects a WKT definition, and adds EPSG authority nodes
  * where an aspect of the coordinate system can be easily and safely 
  * corresponded with an EPSG identifier.  In practice, this method will 
@@ -9399,7 +9743,7 @@ public class SpatialReference:public SpatialReference CloneGeogCS()
 
 /**
  * Copy GEOGCS from another OGRSpatialReference.
- *
+ * <p>
  * The GEOGCS information is copied into this SpatialReference from another.
  * If this object has a PROJCS root already, the GEOGCS is installed within
  * it, otherwise it is installed as the root.
@@ -9429,7 +9773,7 @@ public class SpatialReference:public int ExportToMICoordSys(String[] argout)
 
 /**
  * Export coordinate system in PCI projection definition.
- *
+ * <p>
  * Converts the loaded coordinate reference system into PCI projection
  * definition to the extent possible. 
  * <p>
@@ -9450,7 +9794,7 @@ public class SpatialReference:public int ExportToPCI(String[] proj, String[] uni
 
 /**
  * Convert this SRS into a a nicely formatted WKT string for display to a person.
- *
+ * <p>
  * Same as below with simplify == 0 and the string is returned as a return value
  *
  * @see #ExportToPrettyWkt(String[] argout, int simplify)
@@ -9461,7 +9805,7 @@ public class SpatialReference:public String ExportToPrettyWkt()
 
 /**
  * Convert this SRS into a a nicely formatted WKT string for display to a person.
- *
+ * <p>
  * Same as below but the string is returned as a return value
  *
  * @see #ExportToPrettyWkt(String[] argout, int simplify)
@@ -9472,7 +9816,7 @@ public class SpatialReference:public String ExportToPrettyWkt(int simplify)
 
 /**
  * Convert this SRS into a a nicely formatted WKT string for display to a person.
- *
+ * <p>
  * Same as below with simplify == 0.
  *
  * @see #ExportToPrettyWkt(String[] argout, int simplify)
@@ -9493,7 +9837,7 @@ public class SpatialReference:public int ExportToPrettyWkt(String[] argout, int
 
 /**
  * Export coordinate system in PROJ.4 format.
- *
+ * <p>
  * Same as below but the string is returned as a return value
  *
  * @see #ExportToProj4(String[] argout)
@@ -9504,7 +9848,7 @@ public class SpatialReference:public String ExportToProj4()
 
 /**
  * Export coordinate system in PROJ.4 format.
- *
+ * <p>
  * Converts the loaded coordinate reference system into PROJ.4 format
  * to the extent possible. 
  * <p>
@@ -9538,7 +9882,7 @@ public class SpatialReference:public int ExportToUSGS(int[] projsys, int[] zone,
 
 /**
  * Convert this SRS into WKT format.
- *
+ * <p>
  * Same as below but the string is returned as a return value
  *
  * @see #ExportToWkt(String[] argout)
@@ -9585,10 +9929,10 @@ public class SpatialReference:public int ExportToXML(String[] argout)
 
 /**
  * Export coordinate system in XML format.
- *
+ * <p>
  * Converts the loaded coordinate reference system into XML format
  * to the extent possible.
- *
+ * <p>
  * LOCAL_CS coordinate systems are not translatable.  An empty string
  * will be returned along with 0.  
  *
@@ -9601,7 +9945,7 @@ public class SpatialReference:public int ExportToXML(String[] argout, String dia
 
 /**
  * Fixup as needed.
- *
+ * <p>
  * Some mechanisms to create WKT using OGRSpatialReference, and some
  * imported WKT, are not valid according to the OGC CT specification.  This
  * method attempts to fill in any missing defaults that are required, and
@@ -9622,7 +9966,7 @@ public class SpatialReference:public int Fixup()
 
 /**
  * Correct parameter ordering to match CT Specification.
- *
+ * <p>
  * Some mechanisms to create WKT using OGRSpatialReference, and some
  * imported WKT fail to maintain the order of parameters required according
  * to the BNF definitions in the OpenGIS SF-SQL and CT Specifications.  This
@@ -9635,7 +9979,7 @@ public class SpatialReference:public int FixupOrdering()
 
 /**
  * Fetch angular geographic coordinate system units.
- *
+ * <p>
  * If no units are available, a value of "degree" and SRS_UA_DEGREE_CONV 
  * will be assumed.  This method only checks directly under the GEOGCS node
  * for units.
@@ -9647,7 +9991,7 @@ public class SpatialReference:public double GetAngularUnits()
 
 /**
  * Fetch first attribute of named node.
- *
+ * <p>
  * This method uses GetAttrNode() to find the named node, and then extracts
  * the value of the first child.
  *
@@ -9661,7 +10005,7 @@ public class SpatialReference:public String GetAttrValue(String name)
 
 /**
  * Fetch indicated attribute of named node.
- *
+ * <p>
  * This method uses GetAttrNode() to find the named node, and then extracts
  * the value of the indicated child.  Thus a call to GetAttrValue("UNIT",1)
  * would return the second child of the UNIT node, which is normally the
@@ -9676,7 +10020,7 @@ public class SpatialReference:public String GetAttrValue(String name, int child)
 
 /**
  * Get the authority code for a node.
- *
+ * <p>
  * This method is used to query an AUTHORITY[] node from within the 
  * WKT tree, and fetch the code value.  
  * <p>
@@ -9693,7 +10037,7 @@ public class SpatialReference:public String GetAuthorityCode(String target_key)
 
 /**
  * Get the authority name for a node.
- *
+ * <p>
  * This method is used to query an AUTHORITY[] node from within the 
  * WKT tree, and fetch the authority name value.  
  * <p>
@@ -9709,7 +10053,7 @@ public class SpatialReference:public String GetAuthorityName(String target_key)
 
 /**
  * Fetch linear projection units. 
- *
+ * <p>
  * If no units are available, a value of "Meters" and 1.0 will be assumed.
  * This method only checks directly under the PROJCS or LOCAL_CS node for 
  * units.
@@ -9721,7 +10065,7 @@ public class SpatialReference:public double GetLinearUnits()
 
 /**
  * Fetch linear projection units name.
- *
+ * <p>
  * If no units are available, a value of "Meters" will be assumed.
  * This method only checks directly under the PROJCS or LOCAL_CS node for 
  * units.
@@ -9732,7 +10076,7 @@ public class SpatialReference:public String GetLinearUnitsName()
 
 /**
  * Fetch a normalized projection parameter value.
- *
+ * <p>
  * Same as below with default_val == 0
  *
  * @see #GetNormProjParm(String name, double default_val)
@@ -9743,7 +10087,7 @@ public class SpatialReference:public double GetNormProjParm(String name)
 
 /**
  * Fetch a normalized projection parameter value.
- *
+ * <p>
  * This method is the same as GetProjParm() except that the value of
  * the parameter is "normalized" into degrees or meters depending on 
  * whether it is linear or angular.
@@ -9759,7 +10103,7 @@ public class SpatialReference:public double GetNormProjParm(String name, double
 
 /**
  * Fetch a projection parameter value.
- *
+ * <p>
  * Same as below with default_val == 0
  *
  * @see #GetProjParm(String name, double default_val)
@@ -9770,7 +10114,7 @@ public class SpatialReference:public double GetProjParm(String name)
 
 /**
  * Fetch a projection parameter value.
- *
+ * <p>
  * NOTE: This code should be modified to translate non degree angles into
  * degrees based on the GEOGCS unit.  This has not yet been done.
  *
@@ -9803,7 +10147,7 @@ public class SpatialReference:public int GetTOWGS84(double[] argout)
 
 /**
  * Initialize SRS based on EPSG GCS or PCS code.
- *
+ * <p>
  * This method will initialize the spatial reference based on the
  * passed in EPSG GCS or PCS code.  The coordinate system definitions
  * are normally read from the EPSG derived support files such as 
@@ -9831,7 +10175,7 @@ public class SpatialReference:public int ImportFromEPSG(int nCode)
 
 /**
  * Import coordinate system from ESRI .prj format(s).
- *
+ * <p>
  * This function will read the text loaded from an ESRI .prj file, and
  * translate it into an OGRSpatialReference definition.  This should support
  * many (but by no means all) old style (Arc/Info 7.x) .prj files, as well
@@ -9857,7 +10201,7 @@ public class SpatialReference:public int ImportFromESRI(java.util.Vector ppszInp
 
 /**
  * Import Mapinfo style CoordSys definition.
- *
+ * <p>
  * The SpatialReference is initialized from the passed Mapinfo style CoordSys definition string.
  *
  * @param coord_sys Mapinfo style CoordSys definition string.
@@ -9868,7 +10212,7 @@ public class SpatialReference:public int ImportFromMICoordSys(String coord_sys)
 
 /**
  * Import coordinate system from PCI projection definition.
- *
+ * <p>
  * Same as below with units == null and prjParams == null
  *
  * @see #ImportFromPCI(String proj, String units, double[] prjParams)
@@ -9879,7 +10223,7 @@ public class SpatialReference:public int ImportFromPCI(String proj)
 
 /**
  * Import coordinate system from PCI projection definition.
- *
+ * <p>
  * Same as below with prjParams == null
  *
  * @see #ImportFromPCI(String proj, String units, double[] prjParams)
@@ -9890,7 +10234,7 @@ public class SpatialReference:public int ImportFromPCI(String proj, String units
 
 /**
  * Import coordinate system from PCI projection definition.
- *
+ * <p>
  * PCI software uses 16-character string to specify coordinate system
  * and datum/ellipsoid. You should supply at least this string to the
  * importFromPCI() function.
@@ -9932,7 +10276,7 @@ public class SpatialReference:public int ImportFromPCI(String proj, String units
 
 /**
  * Import PROJ.4 coordinate string.
- *
+ * <p>
  * The OGRSpatialReference is initialized from the passed PROJ.4 style
  * coordinate system string.  In addition to many +proj formulations which
  * have OGC equivelents, it is also possible to import "+init=epsg:n" style
@@ -9978,7 +10322,7 @@ public class SpatialReference:public int ImportFromProj4(String proj4)
 
 /**
  * Set spatial reference from a URL.
- *
+ * <p>
  * This method will download the spatial reference at a given URL and 
  * feed it into SetFromUserInput for you.
  * 
@@ -9990,7 +10334,7 @@ public class SpatialReference:public int ImportFromUrl(String url)
 
 /**
  * Import coordinate system from USGS projection definition.
- *
+ * <p>
  * Same as below with iZone == 0, padfPrjParams == null and iDatum == 0
  *
  * @see #ImportFromUSGS(int iProjSys, int iZone, double[] padfPrjParams, int iDatum)
@@ -10001,7 +10345,7 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys)
 
 /**
  * Import coordinate system from USGS projection definition.
- *
+ * <p>
  * Same as below with padfPrjParams == null and iDatum == 0
  *
  * @see #ImportFromUSGS(int iProjSys, int iZone, double[] padfPrjParams, int iDatum)
@@ -10012,7 +10356,7 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone)
 
 /**
  * Import coordinate system from USGS projection definition.
- *
+ * <p>
  * Same as below with iDatum == 0
  *
  * @see #ImportFromUSGS(int iProjSys, int iZone, double[] padfPrjParams, int iDatum)
@@ -10023,7 +10367,7 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone,
 
 /**
  * Import coordinate system from USGS projection definition.
- *
+ * <p>
  * This method will import projection definition in style, used by USGS GCTP
  * software. GCTP operates on angles in packed DMS format (see
  * CPLDecToPackedDMS() function for details), so all angle values (latitudes,
@@ -10247,7 +10591,7 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone,
 
 /**
  * Import from WKT string.
- *
+ * <p>
  * This method will wipe the existing SRS definition, and
  * reassign it based on the contents of the passed WKT string.  Only as
  * much of the input string as needed to construct this SRS is consumed from
@@ -10269,6 +10613,25 @@ public class SpatialReference:public int ImportFromWkt(String wkt)
 public class SpatialReference:public int ImportFromXML(String xmlString)
 
 /**
+ * Check if coordinate system is compound.
+ *
+ * @return 1 if this is rooted with a COMPD_CS node.
+ *
+ * @since GDAL 1.9.0
+ */
+public class SpatialReference:public int IsCompound()
+
+/**
+ * Check if geocentric coordinate system.
+ *
+ * @return 1 if this contains a GEOCCS node indicating a it is a
+ * geocentric coordinate system.
+ *
+ * @since GDAL 1.9.0
+ */
+public class SpatialReference:public int IsGeocentric()
+
+/**
  * Check if geographic coordinate system.
  *
  * @return 1 if this spatial reference is geographic ... that is the 
@@ -10311,8 +10674,27 @@ public class SpatialReference:public int IsSame(SpatialReference other)
 public class SpatialReference:public int IsSameGeogCS(SpatialReference other)
 
 /**
- * Convert in place from ESRI WKT format.
+ * Do the VertCS'es match?
+ *
+ * @param other the SRS being compared against.
+ *
+ * @return 1 if they are the same or 0 otherwise.
+ */
+public class SpatialReference:public int IsSameVertCS(SpatialReference other)
+
+/**
+ * Check if vertical coordinate system.
+ *
+ * @return 1 if this contains a VERT_CS node indicating a it is a
+ * vertical coordinate system.
  *
+ * @since OGR 1.8.0
+ */
+public class SpatialReference:public int IsVertical()
+
+/**
+ * Convert in place from ESRI WKT format.
+ * <p>
  * The value notes of this coordinate system are modified in various manners
  * to adhere more closely to the WKT standard.  This mostly involves
  * translating a variety of ESRI names for projections, arguments and
@@ -10325,7 +10707,7 @@ public class SpatialReference:public int MorphFromESRI()
 
 /**
  * Convert in place to ESRI WKT format.
- *
+ * <p>
  * The value nodes of this coordinate system are modified in various manners
  * more closely map onto the ESRI concept of WKT format.  This includes
  * renaming a variety of projections and arguments, and stripping out 
@@ -10337,7 +10719,7 @@ public class SpatialReference:public int MorphToESRI()
 
 /**
  * Set the angular units for the geographic coordinate system.
- *
+ * <p>
  * This method creates a UNITS subnode with the specified values as a
  * child of the GEOGCS node. 
  *
@@ -10354,7 +10736,7 @@ public class SpatialReference:public int SetAngularUnits(String name, double to_
 
 /**
  * Set attribute value in spatial reference.
- *
+ * <p>
  * Missing intermediate nodes in the path will be created if not already
  * in existance.  If the attribute has no children one will be created and
  * assigned the value otherwise the zeroth child will be assigned the value.
@@ -10386,7 +10768,7 @@ public class SpatialReference:public int SetAuthority(String target_key, String
 
 /**
  * Set spatial reference from various text formats.
- *
+ * <p>
  * This method will examine the provided input, and try to deduce the
  * format, and then use it to initialize the spatial reference system.  It
  * may take the following forms:
@@ -10421,8 +10803,35 @@ public class SpatialReference:public int SetAuthority(String target_key, String
 public class SpatialReference:public int SetFromUserInput(String definition)
 
 /**
- * Set geographic coordinate system. 
+ * Set the user visible GEOCCS name.
+ * <p>
+ * Same as below with name == null
+ *
+ * @see #SetGeocCS(String name)
+ *
+ * @since OGR 1.9.0
+ */
+public class SpatialReference:public int SetGeocCS()
+
+/**
+ * Set the user visible GEOCCS name.
+ * <p>
+ * This method is will ensure a GEOCCS node is created as the root,
+ * and set the provided name on it.  If used on a GEOGCS coordinate system,
+ * the DATUM and PRIMEM nodes from the GEOGCS will be tarnsferred over to
+ * the GEOGCS.
+ *
+ * @param name the user visible name to assign. Not used as a key. May be null
+ *
+ * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  *
+ * @since OGR 1.9.0
+ */
+public class SpatialReference:public int SetGeocCS(String name)
+
+/**
+ * Set geographic coordinate system. 
+ * <p>
  * Same as below with pszPMName = "Greenwich", dfPMOffset = 0.0, pszAngularUnits = "degree" and dfConvertToRadians =  0.0174532925199433
  *
  * @see #SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening, String pszPMName, double dfPMOffset, String pszAngularUnits, double dfConvertToRadians)
@@ -10433,7 +10842,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 
 /**
  * Set geographic coordinate system. 
- *
+ * <p>
  * Same as below with dfPMOffset = 0.0, pszAngularUnits = "degree" and dfConvertToRadians =  0.0174532925199433
  *
  * @see #SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening, String pszPMName, double dfPMOffset, String pszAngularUnits, double dfConvertToRadians)
@@ -10444,7 +10853,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 
 /**
  * Set geographic coordinate system. 
- *
+ * <p>
  * Same as below with pszAngularUnits = "degree" and dfConvertToRadians =  0.0174532925199433
  *
  * @see #SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening, String pszPMName, double dfPMOffset, String pszAngularUnits, double dfConvertToRadians)
@@ -10455,7 +10864,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 
 /**
  * Set geographic coordinate system. 
- *
+ * <p>
  * Same as below with dfConvertToRadians =  0.0174532925199433
  *
  * @see #SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening, String pszPMName, double dfPMOffset, String pszUnits, double dfConvertToRadians)
@@ -10466,7 +10875,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 
 /**
  * Set geographic coordinate system. 
- *
+ * <p>
  * This method is used to set the datum, ellipsoid, prime meridian and
  * angular units for a geographic coordinate system.  It can be used on it's
  * own to establish a geographic spatial reference, or applied to a 
@@ -10507,7 +10916,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 
 /**
  * Set the linear units for the projection.
- *
+ * <p>
  * This method creates a UNITS subnode with the specified values as a
  * child of the PROJCS or LOCAL_CS node. 
  *
@@ -10525,7 +10934,7 @@ public class SpatialReference:public int SetLinearUnits(String name, double to_m
 
 /**
  * Set the linear units for the projection.
- *
+ * <p>
  * This method creates a UNITS subnode with the specified values as a
  * child of the PROJCS or LOCAL_CS node.   It works the same as the
  * SetLinearUnits() method, but it also updates all existing linear
@@ -10545,7 +10954,7 @@ public class SpatialReference:public int SetLinearUnitsAndUpdateParameters(Strin
 
 /**
  * Set the user visible LOCAL_CS name.
- *
+ * <p>
  * This method is will ensure a LOCAL_CS node is created as the root, 
  * and set the provided name on it.  It must be used before SetLinearUnits().
  *
@@ -10557,7 +10966,7 @@ public class SpatialReference:public int SetLocalCS(String name)
 
 /**
  * Set a projection parameter with a normalized value.
- *
+ * <p>
  * This method is the same as SetProjParm() except that the value of
  * the parameter passed in is assumed to be in "normalized" form (decimal
  * degrees for angular values, meters for linear values.  The values are 
@@ -10574,7 +10983,7 @@ public class SpatialReference:public int SetNormProjParm(String name, double val
 
 /**
  * Set the user visible PROJCS name.
- *
+ * <p>
  * Same as below with name == null
  *
  * @see #SetProjCS(String name)
@@ -10583,7 +10992,7 @@ public class SpatialReference:public int SetProjCS()
 
 /**
  * Set the user visible PROJCS name.
- *
+ * <p>
  * This method is will ensure a PROJCS node is created as the root, 
  * and set the provided name on it.  If used on a GEOGCS coordinate system, 
  * the GEOGCS node will be demoted to be a child of the new PROJCS root.
@@ -10606,7 +11015,7 @@ public class SpatialReference:public int SetProjection(String name)
 
 /**
  * Set a projection parameter value.
- *
+ * <p>
  * Adds a new PARAMETER under the PROJCS with the indicated name and value.
  * <p>
  * Please check <a href="http://www.remotesensing.org/geotiff/proj_list">http://www.remotesensing.org/geotiff/proj_list</a> pages for
@@ -10623,7 +11032,7 @@ public class SpatialReference:public int SetProjParm(String name, double val)
 
 /**
  * Set State Plane projection definition.
- *
+ * <p>
  * Same as below with is_nad83 == 1, unitsname == "" and units == 0
  *
  * @see #SetStatePlane(int zone, int is_nad83, String unitsname, double units)
@@ -10634,7 +11043,7 @@ public class SpatialReference:public int SetStatePlane(int zone)
 
 /**
  * Set State Plane projection definition.
- *
+ * <p>
  * Same as below with unitsname == "" and units == 0
  *
  * @see #SetStatePlane(int zone, int is_nad83, String unitsname, double units)
@@ -10645,7 +11054,7 @@ public class SpatialReference:public int SetStatePlane(int zone, int is_nad83)
 
 /**
  * Set State Plane projection definition.
- *
+ * <p>
  * Same as below with units == 0
  *
  * @see #SetStatePlane(int zone, int is_nad83, String unitsname, double units)
@@ -10656,7 +11065,7 @@ public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, S
 
 /**
  * Set State Plane projection definition.
- *
+ * <p>
  * This will attempt to generate a complete definition of a state plane
  * zone based on generating the entire SRS from the EPSG tables.  If the
  * EPSG tables are unavailable, it will produce a stubbed LOCAL_CS definition
@@ -10679,8 +11088,31 @@ public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, S
 public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, String unitsname, double units)
 
 /**
- * Set the Bursa-Wolf conversion to WGS84. 
+ * Set the linear units for the projection.
+ * <p>
+ * This method creates a UNIT subnode with the specified values as a
+ * child of the target node.
+ *
+ * @param target the keyword to set the linear units for.  ie. "PROJCS" or "VERT_CS"
+ *
+ * @param name the units name to be used.  Some preferred units
+ * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
+ * and SRS_UL_US_FOOT.
+ *
+ * @param to_meters the value to multiple by a length in the indicated
+ * units to transform to meters.  Some standard conversion factors can
+ * be found in ogr_srs_api.h.
  *
+ * @return OGRERR_NONE on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
+ *
+ * @since OGR 1.9.0
+ */
+
+public class SpatialReference:public int SetTargetLinearUnits(String target, String name, double to_meters)
+
+/**
+ * Set the Bursa-Wolf conversion to WGS84. 
+ * <p>
  * Same as below with dfEX == dfEY == dfEZ == dfPPM == 0
  *
  * @see #SetTOWGS84(double dfDX, double dfDY, double dfDZ, double dfEX, double dfEY, double dfEZ, double dfPPM)
@@ -10691,7 +11123,7 @@ public class SpatialReference:public int SetTOWGS84(double p1, double p2, double
 
 /**
  * Set the Bursa-Wolf conversion to WGS84. 
- * 
+ * <p>
  * This will create the TOWGS84 node as a child of the DATUM.  It will fail
  * if there is no existing DATUM node.  Unlike most OGRSpatialReference
  * methods it will insert itself in the appropriate order, and will replace
@@ -10714,7 +11146,7 @@ public class SpatialReference:public int SetTOWGS84(double dfDX, double dfDY, do
 
 /**
  * Set UTM projection definition.
- *
+ * <p>
  * Same as below with north == 1
  *
  * @see #SetUTM(int zone, int north)
@@ -10725,7 +11157,7 @@ public class SpatialReference:public int SetUTM(int zone)
 
 /**
  * Set UTM projection definition.
- *
+ * <p>
  * This will generate a projection definition with the full set of 
  * transverse mercator projection parameters for the given UTM zone.
  * If no PROJCS[] description is set yet, one will be set to look
@@ -10751,8 +11183,29 @@ public class SpatialReference:public int SetUTM(int zone, int north)
 public class SpatialReference:public int GetUTMZone()
 
 /**
- * Set a GeogCS based on well known name.
+ * Set the user visible VERT_CS name.
+ * <p>
+ * This method is will ensure a VERT_CS node is created if needed.  If the
+ * existing coordinate system is GEOGCS or PROJCS rooted, then it will be
+ * turned into a COMPD_CS.
+ *
+ * @param VertCSName the user visible name of the vertical coordinate
+ * system. Not used as a key.
  *
+ * @param VertDatumName the user visible name of the vertical datum.  It
+ * is helpful if this matches the EPSG name.
+ *
+ * @param VertDatumType the OGC vertical datum type, usually 2005.
+ *
+ * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
+ *
+ * @since OGR 1.9.0
+ */
+public class SpatialReference:public int SetVertCS(String VertCSName, String VertDatumName, int VertDatumType)
+
+/**
+ * Set a GeogCS based on well known name.
+ * <p>
  * This may be called on an empty OGRSpatialReference to make a geographic
  * coordinate system, or on something with an existing PROJCS node to 
  * set the underlying geographic coordinate system of a projected coordinate
@@ -10774,7 +11227,7 @@ public class SpatialReference:public int SetWellKnownGeogCS(String name)
 
 /** 
  * Strip OGC CT Parameters.
- *
+ * <p>
  * This method will remove all components of the coordinate system
  * that are specific to the OGC CT Specification.  That is it will attempt
  * to strip it down to being compatible with the Simple Features 1.0 
@@ -10793,7 +11246,7 @@ public class SpatialReference:public String toString()
 
 /**
  * Validate SRS tokens.
- *
+ * <p>
  * This method attempts to verify that the spatial reference system is
  * well formed, and consists of known tokens.  The validation is not
  * comprehensive. 
@@ -10802,6 +11255,21 @@ public class SpatialReference:public String toString()
  */
 public class SpatialReference:public int Validate()
 
+/**
+ * This method returns TRUE if EPSG feels this geographic coordinate
+ * system should be treated as having lat/long coordinate ordering.
+ * <p>
+ * Currently this returns TRUE for all geographic coordinate systems
+ * with an EPSG code set, and AXIS values set defining it as lat, long.
+ * Note that coordinate systems with an EPSG code and no axis settings
+ * will be assumed to not be lat/long.
+ * <p>
+ * FALSE will be returned for all coordinate systems that are not geographic,
+ * or that do not have an EPSG code set.
+ *
+ * @return TRUE or FALSE.
+ */
+public class SpatialReference:public int EPSGTreatsAsLatLong()
 
 
 /* Class CoordinateTransformation */
@@ -10816,7 +11284,7 @@ public class CoordinateTransformation
 
 /**
  * Create transformation object.
- *
+ * <p>
  * Input spatial reference system objects are assigned 
  * by copy (calling clone() method) and no ownership transfer occurs.
  *
@@ -10827,7 +11295,7 @@ public class CoordinateTransformation:public CoordinateTransformation(SpatialRef
 
 /**
  * Transform point from source to destination space.
- *
+ * <p>
  * The provided array will be modified in place.
  *
  * @param inout an array of 3 doubles
@@ -10879,7 +11347,7 @@ public class CoordinateTransformation:public double[] TransformPoint(double x, d
 
 /**
  * Transform points from source to destination space.
- *
+ * <p>
  * The provided array will be modified in place.
  *
  * @param pointArray an array of coordinates. Each coordinate can be either 2D or 3D
@@ -10895,7 +11363,7 @@ public class osr
 
 /**
  * Use exceptions instead of error return codes.
- *
+ * <p>
  * This is the default behavious : methods that in C/C++ return an OGRErr return code
  * would throw a RuntimeException() in case the code it is different
  * from ogr.OGRERR_NONE. By calling this method, you can get
@@ -10908,7 +11376,7 @@ public class osr:public static void UseExceptions()
 
 /**
  * Use return code instead of exceptions.
- *
+ * <p>
  * By default, methods that in C/C++ return an OGRErr return code
  * would throw a RuntimeException() in case the code is different
  * from ogr.OGRERR_NONE. By calling this method, you can prevent
@@ -10922,7 +11390,7 @@ public class osr:public static void DontUseExceptions()
 
 /**
  * Utility function that returns the WKT definition of the SRS expressed as a user input.
- *
+ * <p>
  * Such a user input is what can be passed in to
  * SpatialReference.<a href="SpatialReference.html#SetFromUserInput(java.lang.String)">SetFromUserInput()</a>.
  *
@@ -10934,7 +11402,7 @@ public class osr:public static String GetUserInputAsWKT(String definition)
 
 /**
  * Utility function that returns the WKT definition of the SRS expressed as a well known Geog CS.
- *
+ * <p>
  * Such a user input is what can be passed in to
  * SpatialReference.<a href="SpatialReference.html#SetWellKnownGeogCS(java.lang.String)">SetWellKnownGeogCS()</a>.
  *
diff --git a/swig/java/makefile.vc b/swig/java/makefile.vc
index 377d5c5..a490296 100644
--- a/swig/java/makefile.vc
+++ b/swig/java/makefile.vc
@@ -57,6 +57,7 @@ test:
 	$(JAVA_RUN) gdalmajorobject
 	$(JAVA_RUN) GDALTestIO
 	$(JAVA_RUN) GDALContour -i 1 tmp_test/byte.tif tmp_test/contour.shp
+	$(JAVA_RUN) testgetpoints
 
 clean:
 	if exist org\nul rmdir /s /q org
diff --git a/swig/perl/Doxyfile b/swig/perl/Doxyfile
index bdb4fd9..b1b7f03 100644
--- a/swig/perl/Doxyfile
+++ b/swig/perl/Doxyfile
@@ -4,7 +4,7 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 PROJECT_NAME           = Geo::GDAL
-PROJECT_NUMBER         = 1.8.0
+PROJECT_NUMBER         = 1.9
 OUTPUT_DIRECTORY       = .
 CREATE_SUBDIRS         = NO
 OUTPUT_LANGUAGE        = English
diff --git a/swig/perl/Makefile.PL b/swig/perl/Makefile.PL
index 9b4e036..1768073 100644
--- a/swig/perl/Makefile.PL
+++ b/swig/perl/Makefile.PL
@@ -1,35 +1,76 @@
 use ExtUtils::MakeMaker;
 
-$LIB = '';
-$INC = '';
+# pick up our parameters from @ARGV
+my %ARGV;
+for (@ARGV) {
+    if (/^(.*?)\=(.*)/) {
+	$ARGV{$1} = $2;
+    } else {
+	$ARGV{$_} = 1;
+    }
+    $_ = '' if /^--gdal-config/;
+    $_ = '' if /^--no-version-check/;
+}
+
+# search and decide which GDAL (gdal-config) to build against
+
+# scan known possible locations in the order of preference:
+my @configs;
+for ('../../apps/gdal-config',
+     'c:/msys/1.0/local/bin/gdal-config',
+     '/usr/local/bin/gdal-config',
+     '/usr/bin/gdal-config') {
+    push @configs, $_ if -r $_;
+}
+print "Found @configs\n";
+
+my $config;
+if ($ARGV{'--gdal-config'}) {
+    die "'$ARGV{'--gdal-config'}' does not exist or is unreadable." unless -r $ARGV{'--gdal-config'};
+    $config = $ARGV{'--gdal-config'};
+} else {
+    $config = shift @configs;
+}
+
+die "Can't find gdal-config. Please install GDAL development files or\n".
+    "define the location of gdal-config using --gdal-config=XXX.\n"
+    unless $config;
+
+print "Using $config.\n";
+
 # check that we're part of GDAL distro
 # or that installed GDAL version is the same as that in lib/Geo/GDAL.pm 
-if (-f "../../GDALmake.opt") {
-    print "Building in GDAL distro tree\n";
-    $LIB .= '-L../../.libs -L../..';
-    $INC .= '-I../../gcore -I../../alg -I../../ogr -I../../port ';
-    $fh = "../../apps/gdal-config";
-} elsif (-f "c:/msys/1.0/local/bin/gdal-config") {
-    print "found gdal-config in c:/msys/1.0/local/bin/\n";
-    $LIB .= '-Lc:/msys/1.0/local/lib';
+
+my $LIB = '';
+my $INC = '';
+if ($config eq '../../apps/gdal-config') { 
+    print "Building against GDAL in this distro tree\n";
+    $LIB .= '-L../../.libs -L../.. ';
+} elsif ($config eq 'c:/msys/1.0/local/bin/gdal-config') {
+    print "Building against GDAL in c:/msys/1.0/local/bin/\n";
+    $LIB .= '-Lc:/msys/1.0/local/lib ';
     $INC .= '-Ic:/msys/1.0/local/include ';
-    $fh = "c:/msys/1.0/local/bin/gdal-config";
-} elsif (-f "/usr/local/bin/gdal-config") {
-    print "found gdal-config in /usr/local/bin/\n";
-    $fh = "/usr/local/bin/gdal-config";
-} elsif (-f "/usr/bin/gdal-config") {
-    print "found gdal-config in /usr/bin/\n";
-    $fh = "/usr/bin/gdal-config";
 } else {
-    die "can't find gdal-config";
+    print "Building against GDAL defined in $config\n";
 }
-open $fh, $fh or die "$fh not found!";
-$LIB .= " -lgdal ";
-if ($fh) {
-    @config = <$fh>;
-    close $fh;
-    for (@config) {
+
+my $gdal_version;
+my $pm_version;
+my $fh;
+if (open($fh, $config)) {
+    for (<$fh>) {
 	($gdal_version) = /(\d+\.\d+\.\d+)/ if /^CONFIG_VERSION/;
+	if (/^CONFIG_LIBS/) {
+	    s/^CONFIG_LIBS="//;
+	    s/"\s*$//;
+	    if ($_ =~ /\.la$/) { 
+		# parse a libtool library file
+		$LIB .= parse_libtool_library_file_for_l($_);
+	    } else {
+		$LIB .= $_;
+	    }
+	    $LIB .= ' ';
+	}
 	if (/^CONFIG_DEP_LIBS/) {
 	    s/^CONFIG_DEP_LIBS="//;
 	    s/"\s*$//;
@@ -41,21 +82,36 @@ if ($fh) {
 	    $INC .= $_;
 	}
     }
-    open $fh, "lib/Geo/GDAL.pm" or die "lib/Geo/GDAL.pm not found, perhaps you need to run make generate?";
-    @config = <$fh>;
     close $fh;
-    for (@config) {
+}
+if (open($fh, "lib/Geo/GDAL.pm")) {
+    for (<$fh>) {
 	($pm_version) = /(\d+\.\d+\.\d+)/ if /GDAL_VERSION/;
     }
-    die "GDAL version ($gdal_version) and module version ($pm_version) do not match" 
-	unless $gdal_version eq $pm_version;
+    close $fh;
+} else {
+    die "GDAL Perl modules not found, perhaps you need to run make generate?";
 }
 
+die "=======================================================\n".
+    "PLEASE NOTE!\n".
+    "The GDAL that you try to build against has version\n".
+    "$gdal_version and this module was released from version\n".
+    "$pm_version. These do not match. Building against newer\n".
+    "version may work but you need to remove this check first.\n".
+    "You can pass by this warning with --no-version-check.\n".
+    "Thank you.\n".
+    "=======================================================\n"
+    if ($gdal_version ne $pm_version) and !$ARGV{'--no-version-check'};
+
 %object = ( 'Geo::GDAL' => 'gdal_wrap.o',
 	    'Geo::GDAL::Const' => 'gdalconst_wrap.o',
 	    'Geo::OGR' => 'ogr_wrap.o',
 	    'Geo::OSR' => 'osr_wrap.o' );
 
+#print "LIB = $LIB\n";
+#print "INC = $INC\n";
+
 for my $module (keys %object) {
     my $add = $module;
     $add =~ s/:/_/g;
@@ -67,3 +123,22 @@ for my $module (keys %object) {
 		   OBJECT => $object{$module}
 		   );
 }
+
+sub parse_libtool_library_file_for_l {
+    my $fn = shift;
+    my $fh;
+    my $l = '';
+    if (open($fh, $fn)) {
+	while (<$fh>) {
+	    if (/^dlname=(.*)/) {
+		$l = $1;
+		$l =~ s/^'//;
+		$l =~ s/^lib/\-l/;
+		$l =~ s/\..*$//;
+		last;
+	    }
+	}
+	close $fh;
+    }
+    return $l;
+}
diff --git a/swig/perl/check_dox.pl b/swig/perl/check_dox.pl
new file mode 100644
index 0000000..ac15302
--- /dev/null
+++ b/swig/perl/check_dox.pl
@@ -0,0 +1,85 @@
+# run to check what methods have been doxymented and which not
+# also checks if something is in dox that maybe shouldn't be
+
+report(check('GDAL'));
+report(check('OGR'));
+report(check('OSR'));
+
+sub report {
+    my($dox, $pm) = @_;
+    for my $class (sort keys %$pm) {
+	my @m;	
+	for my $method (sort keys %{$pm->{$class}}) {
+	    push @m, "  $method not in dox\n" unless $dox->{$class}{$method};
+	}
+	next unless @m;
+	print "$class\n at m";
+    }
+    return;
+    for my $class (sort keys %$dox) {
+	my @m;	
+	for my $method (sort keys %{$dox->{$class}}) {
+	    push @m, "  $method not in pm\n" unless $pm->{$class}{$method};
+	}
+	next unless @m;
+	print "$class\n at m";
+    }
+}
+
+sub check {
+    my($file) = @_;
+    @gdal = `cat lib/Geo/$file.dox`;
+    my %pm;
+    my %dox;
+    for (@gdal) {
+	($_) = /(.*?)\(/ if /\(/;
+	@l = split /\s+/;
+	next unless @l;
+	if ($l[$#l-1] eq '@class') {
+	    $class = $l[$#l];
+	    $class =~ s/\s+$//;
+	    next;
+	}
+	if (/^##/) {	
+	    ($method) = $l[$#l];
+	    $method =~ s/^\\//;
+	    $method =~ s/^[\$\@\%]//;
+	    $dox{$class}{$method} = 1;
+	    next;
+	}
+    }
+    @gdal = `cat lib/Geo/$file.pm`;
+    for (@gdal) {
+	@l = split /\s+/;
+	if (/^package/) {
+	    $class = $l[$#l];
+	    $class =~ s/;//;
+	    $class =~ s/\s+$//;
+	    next;
+	}
+	if (/^\*/) {	
+	    $method = $l[0];
+	    $method =~ s/\*//;
+	    next if $method =~ /^_/;
+	    next if $method =~ /^GDAL_/;
+	    next if $method =~ /^swig_/;
+	    next if $method =~ /^VSI/;
+	    next if $method =~ /^SRS_/;
+	    next if $method =~ /^[0-9A-Z_]+$/;
+	    $pm{$class}{$method} = 1;
+	    next;
+	}
+	if (/^sub/) {	
+	    $method = $l[1];
+	    next if $method =~ /^_/;
+	    next if $method =~ /^GDAL_/;
+	    next if $method =~ /^swig_/;
+	    next if $method =~ /^VSI/;
+	    next if $method =~ /^SRS_/;
+	    next if $method =~ /^[0-9A-Z_]+$/;
+	    $pm{$class}{$method} = 1;
+	    next;
+	}
+    }
+    return (\%dox, \%pm);
+}
diff --git a/swig/perl/gdal_wrap.cpp b/swig/perl/gdal_wrap.cpp
index 20399ba..37145c2 100644
--- a/swig/perl/gdal_wrap.cpp
+++ b/swig/perl/gdal_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -918,6 +918,7 @@ SWIG_Perl_ErrorType(int code) {
 
 /* for raw pointers */
 #define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
 #define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
 
 /* for raw packed data */
@@ -1134,10 +1135,14 @@ SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
 /* Function for getting a pointer value */
 
 SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
   swig_cast_info *tc;
   void *voidptr = (void *)0;
   SV *tsv = 0;
+
+  if (own)
+    *own = 0;
+
   /* If magical, apply more magic */
   if (SvGMAGICAL(sv))
     mg_get(sv);
@@ -1187,7 +1192,11 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
     {
       int newmemory = 0;
       *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      assert(!newmemory); /* newmemory handling not yet implemented */
+      if (newmemory == SWIG_CAST_NEW_MEMORY) {
+        assert(own);
+        if (own)
+          *own = *own | SWIG_CAST_NEW_MEMORY;
+      }
     }
   } else {
     *ptr = voidptr;
@@ -1217,9 +1226,14 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
   return SWIG_OK;
 }
 
+SWIGRUNTIME int
+SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
+}
+
 SWIGRUNTIME void
 SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & SWIG_SHADOW)) {
+  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
     SV *self;
     SV *obj=newSV(0);
     HV *hash=newHV();
@@ -1394,6 +1408,9 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #ifdef do_close
   #undef do_close
 #endif
+#ifdef do_exec
+  #undef do_exec
+#endif
 #ifdef scalar
   #undef scalar
 #endif
@@ -1513,18 +1530,17 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #define SWIGTYPE_p_GDALTransformerInfoShadow swig_types[12]
 #define SWIGTYPE_p_GDAL_GCP swig_types[13]
 #define SWIGTYPE_p_OGRLayerShadow swig_types[14]
-#define SWIGTYPE_p_SavedEnv swig_types[15]
-#define SWIGTYPE_p_VSIStatBufL 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_GDAL_GCP swig_types[21]
-#define SWIGTYPE_p_p_char swig_types[22]
-#define SWIGTYPE_p_p_int swig_types[23]
-#define SWIGTYPE_p_void swig_types[24]
-static swig_type_info *swig_types[26];
-static swig_module_info swig_module = {swig_types, 25, 0, 0, 0, 0};
+#define SWIGTYPE_p_VSIStatBufL swig_types[15]
+#define SWIGTYPE_p_char swig_types[16]
+#define SWIGTYPE_p_double swig_types[17]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[18]
+#define SWIGTYPE_p_int swig_types[19]
+#define SWIGTYPE_p_p_GDAL_GCP swig_types[20]
+#define SWIGTYPE_p_p_char swig_types[21]
+#define SWIGTYPE_p_p_int swig_types[22]
+#define SWIGTYPE_p_void swig_types[23]
+static swig_type_info *swig_types[25];
+static swig_module_info swig_module = {swig_types, 24, 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)
 
@@ -1535,7 +1551,7 @@ static swig_module_info swig_module = {swig_types, 25, 0, 0, 0, 0};
 #define SWIG_name   "Geo::GDALc::boot_Geo__GDAL"
 #define SWIG_prefix "Geo::GDALc::"
 
-#define SWIGVERSION 0x010339 
+#define SWIGVERSION 0x010340 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -1586,11 +1602,13 @@ typedef int RETURN_NONE;
 
 
 
+    #ifndef SWIG
     typedef struct
     {
 	SV *fct;
 	SV *data;
     } SavedEnv;
+    #endif
     int callback_d_cp_vp(double d, const char *cp, void *vp)
     {
 	int count, ret;
@@ -1876,26 +1894,6 @@ retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_S
 } 
 
 
-SWIGINTERNINLINE SV *
-SWIG_FromCharPtrAndSize(const char* carray, size_t size)
-{
-  SV *obj = sv_newmortal();
-  if (carray) {
-    sv_setpvn(obj, carray, size);
-  } else {
-    sv_setsv(obj, &PL_sv_undef);
-  }
-  return obj;
-}
-
-
-SWIGINTERNINLINE SV * 
-SWIG_FromCharPtr(const char *cptr)
-{ 
-  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
-}
-
-
 const char *wrapper_CPLGetConfigOption( const char * pszKey, const char * pszDefault = NULL )
 {
     return CPLGetConfigOption( pszKey, pszDefault );
@@ -1918,6 +1916,77 @@ int wrapper_HasThreadSupport()
     return strcmp(CPLGetThreadingModel(), "stub") != 0;
 }
 
+
+SWIGINTERN int
+SWIG_AsVal_unsigned_SS_long SWIG_PERL_DECL_ARGS_2(SV *obj, unsigned long *val) 
+{
+  if (SvUOK(obj)) {
+    if (val) *val = SvUV(obj);
+    return SWIG_OK;
+  } else  if (SvIOK(obj)) {
+    long v = SvIV(obj);
+    if (v >= 0) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      return SWIG_OverflowError;
+    }
+  } else {
+    int dispatch = 0;
+    const char *nptr = SvPV_nolen(obj);
+    if (nptr) {
+      char *endptr;
+      unsigned long v;
+      errno = 0;
+      v = strtoul(nptr, &endptr,0);
+      if (errno == ERANGE) {
+	errno = 0;
+	return SWIG_OverflowError;
+      } else {
+	if (*endptr == '\0') {
+	  if (val) *val = v;
+	  return SWIG_Str2NumCast(SWIG_OK);
+	}
+      }
+    }
+    if (!dispatch) {
+      double d;
+      int res = SWIG_AddCast(SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(obj,&d));
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+	if (val) *val = (unsigned long)(d);
+	return res;
+      }
+    }
+  }
+  return SWIG_TypeError;
+}
+
+
+SWIGINTERNINLINE int
+SWIG_AsVal_size_t SWIG_PERL_DECL_ARGS_2(SV * obj, size_t *val)
+{
+  unsigned long v;
+  int res = SWIG_AsVal_unsigned_SS_long SWIG_PERL_CALL_ARGS_2(obj, val ? &v : 0);
+  if (SWIG_IsOK(res) && val) *val = static_cast< size_t >(v);
+  return res;
+}
+
+
+SWIGINTERNINLINE SV *
+SWIG_From_unsigned_SS_long  SWIG_PERL_DECL_ARGS_1(unsigned long value)
+{    
+  SV *obj = sv_newmortal();
+  sv_setuv(obj, (UV) value);
+  return obj;
+}
+
+
+SWIGINTERNINLINE SV *
+SWIG_From_size_t  SWIG_PERL_DECL_ARGS_1(size_t value)
+{    
+  return SWIG_From_unsigned_SS_long  SWIG_PERL_CALL_ARGS_1(static_cast< unsigned long >(value));
+}
+
 SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
     return GDALGetDescription( self );
   }
@@ -1999,6 +2068,26 @@ SWIG_From_double  SWIG_PERL_DECL_ARGS_1(double value)
   return obj;
 }
 
+
+SWIGINTERNINLINE SV *
+SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+{
+  SV *obj = sv_newmortal();
+  if (carray) {
+    sv_setpvn(obj, carray, size);
+  } else {
+    sv_setsv(obj, &PL_sv_undef);
+  }
+  return obj;
+}
+
+
+SWIGINTERNINLINE SV * 
+SWIG_FromCharPtr(const char *cptr)
+{ 
+  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
+}
+
 SWIGINTERN GDAL_GCP *new_GDAL_GCP(double x=0.0,double y=0.0,double z=0.0,double pixel=0.0,double line=0.0,char const *info="",char const *id=""){
 
     GDAL_GCP *self = (GDAL_GCP*) CPLMalloc( sizeof( GDAL_GCP ) );
@@ -2813,6 +2902,12 @@ SWIG_From_bool  SWIG_PERL_DECL_ARGS_1(bool value)
   return obj;
 }
 
+SWIGINTERN char **GDALRasterBandShadow_GetCategoryNames(GDALRasterBandShadow *self){
+    return GDALGetRasterCategoryNames( self );
+  }
+SWIGINTERN CPLErr GDALRasterBandShadow_SetCategoryNames(GDALRasterBandShadow *self,char **papszCategoryNames){
+    return GDALSetRasterCategoryNames( self, papszCategoryNames );
+  }
 SWIGINTERN CPLErr GDALRasterBandShadow_ContourGenerate(GDALRasterBandShadow *self,double dfContourInterval,double dfContourBase,int nFixedLevelCount,double *padfFixedLevels,int bUseNoData,double dfNoDataValue,OGRLayerShadow *hLayer,int iIDField,int iElevField,GDALProgressFunc callback=NULL,void *callback_data=NULL){
 	return GDALContourGenerate( self, dfContourInterval, dfContourBase,
 				    nFixedLevelCount, padfFixedLevels,
@@ -3247,8 +3342,10 @@ static AV *XMLTreeToAV( CPLXMLNode *psTree )
     av = (AV*)sv_2mortal((SV*)newAV());
 
     av_store(av,0,newSViv((int) psTree->eType));
-    av_store(av,1,newSVpv(psTree->pszValue, strlen(psTree->pszValue)));
-
+    SV *sv = newSVpv(psTree->pszValue, strlen(psTree->pszValue));
+    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+    av_store(av,1,sv);
+    
     for( psChild = psTree->psChild, iChild = 2; 
          psChild != NULL; 
          psChild = psChild->psNext, iChild++ )
@@ -3277,7 +3374,9 @@ static CPLXMLNode *AVToXMLTree( AV *av )
 	return NULL;
 
     nType = SvIV(*(av_fetch(av,0,0)));
-    pszText = SvPV_nolen(*(av_fetch(av,1,0)));
+    SV *sv = *(av_fetch(av,1,0));
+    sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+    pszText = SvPV_nolen(sv);
     psThisNode = CPLCreateXMLNode( NULL, (CPLXMLNodeType) nType, pszText );
     
     for( iChild = 0; iChild < nChildCount; iChild++ )
@@ -3390,215 +3489,6 @@ SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SW
 #ifdef __cplusplus
 extern "C" {
 #endif
-XS(_wrap_SavedEnv_fct_set) {
-  {
-    SavedEnv *arg1 = (SavedEnv *) 0 ;
-    SV *arg2 = (SV *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SavedEnv_fct_set(self,fct);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_SavedEnv, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SavedEnv_fct_set" "', argument " "1"" of type '" "SavedEnv *""'"); 
-    }
-    arg1 = reinterpret_cast< SavedEnv * >(argp1);
-    arg2 = ST(1);
-    if (arg1) (arg1)->fct = arg2;
-    ST(argvi) = sv_newmortal();
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SavedEnv_fct_get) {
-  {
-    SavedEnv *arg1 = (SavedEnv *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    SV *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SavedEnv_fct_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_SavedEnv, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SavedEnv_fct_get" "', argument " "1"" of type '" "SavedEnv *""'"); 
-    }
-    arg1 = reinterpret_cast< SavedEnv * >(argp1);
-    result = (SV *) ((arg1)->fct);
-    ST(argvi) = result; argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SavedEnv_data_set) {
-  {
-    SavedEnv *arg1 = (SavedEnv *) 0 ;
-    SV *arg2 = (SV *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SavedEnv_data_set(self,data);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_SavedEnv, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SavedEnv_data_set" "', argument " "1"" of type '" "SavedEnv *""'"); 
-    }
-    arg1 = reinterpret_cast< SavedEnv * >(argp1);
-    arg2 = ST(1);
-    if (arg1) (arg1)->data = arg2;
-    ST(argvi) = sv_newmortal();
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_SavedEnv_data_get) {
-  {
-    SavedEnv *arg1 = (SavedEnv *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    SV *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SavedEnv_data_get(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_SavedEnv, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SavedEnv_data_get" "', argument " "1"" of type '" "SavedEnv *""'"); 
-    }
-    arg1 = reinterpret_cast< SavedEnv * >(argp1);
-    result = (SV *) ((arg1)->data);
-    ST(argvi) = result; argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_new_SavedEnv) {
-  {
-    int argvi = 0;
-    SavedEnv *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 0) || (items > 0)) {
-      SWIG_croak("Usage: new_SavedEnv();");
-    }
-    {
-      CPLErrorReset();
-      result = (SavedEnv *)new SavedEnv();
-      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_SavedEnv, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    XSRETURN(argvi);
-  fail:
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_delete_SavedEnv) {
-  {
-    SavedEnv *arg1 = (SavedEnv *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_SavedEnv(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_SavedEnv, SWIG_POINTER_DISOWN |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_SavedEnv" "', argument " "1"" of type '" "SavedEnv *""'"); 
-    }
-    arg1 = reinterpret_cast< SavedEnv * >(argp1);
-    {
-      CPLErrorReset();
-      delete 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) = sv_newmortal();
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
 XS(_wrap_callback_d_cp_vp) {
   {
     double arg1 ;
@@ -4269,7 +4159,13 @@ XS(_wrap_GetLastErrorMsg) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
     SWIG_croak_null();
@@ -4280,20 +4176,17 @@ XS(_wrap_GetLastErrorMsg) {
 XS(_wrap_PushFinderLocation) {
   {
     char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int argvi = 0;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: PushFinderLocation(utf8_path);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PushFinderLocation" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -4324,10 +4217,8 @@ XS(_wrap_PushFinderLocation) {
       
     }
     ST(argvi) = sv_newmortal();
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     SWIG_croak_null();
   }
 }
@@ -4420,9 +4311,6 @@ XS(_wrap__FindFile) {
     int res1 ;
     char *buf1 = 0 ;
     int alloc1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     char *result = 0 ;
     dXSARGS;
@@ -4435,11 +4323,11 @@ XS(_wrap__FindFile) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_FindFile" "', argument " "1"" of type '" "char const *""'");
     }
     arg1 = reinterpret_cast< char * >(buf1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_FindFile" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -4469,13 +4357,17 @@ XS(_wrap__FindFile) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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 (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
@@ -4484,9 +4376,6 @@ XS(_wrap__FindFile) {
 XS(_wrap__ReadDir) {
   {
     char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int argvi = 0;
     char **result = 0 ;
     dXSARGS;
@@ -4494,11 +4383,11 @@ XS(_wrap__ReadDir) {
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: _ReadDir(utf8_path);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_ReadDir" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -4534,9 +4423,10 @@ XS(_wrap__ReadDir) {
         if (result) {
           int i;
           for (i = 0; result[i]; i++) {
-            if (i>items-1) EXTEND(SP, 1);
-            ST(argvi) = sv_2mortal(newSVpv(result[i], 0));
-            argvi++;
+            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);
         }
@@ -4545,9 +4435,10 @@ XS(_wrap__ReadDir) {
         if (result) {
           int i;
           for (i = 0; result[i]; i++) {
-            SV *s = newSVpv(result[i], 0);
-            if (!av_store(av, i, s))
-            SvREFCNT_dec(s);
+            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);
         }
@@ -4555,10 +4446,8 @@ XS(_wrap__ReadDir) {
         argvi++;
       }
     }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     SWIG_croak_null();
   }
 }
@@ -4689,7 +4578,13 @@ XS(_wrap_GetConfigOption) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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 (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
@@ -4836,9 +4731,6 @@ XS(_wrap_FileFromMemBuffer) {
     char *arg1 = (char *) 0 ;
     int arg2 ;
     GByte *arg3 = (GByte *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     void *argp3 = 0 ;
@@ -4849,11 +4741,11 @@ XS(_wrap_FileFromMemBuffer) {
     if ((items < 3) || (items > 3)) {
       SWIG_croak("Usage: FileFromMemBuffer(utf8_path,nBytes,pabyData);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FileFromMemBuffer" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
       SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FileFromMemBuffer" "', argument " "2"" of type '" "int""'");
@@ -4894,12 +4786,10 @@ XS(_wrap_FileFromMemBuffer) {
       
     }
     ST(argvi) = sv_newmortal();
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     
     SWIG_croak_null();
@@ -4910,21 +4800,18 @@ XS(_wrap_FileFromMemBuffer) {
 XS(_wrap_Unlink) {
   {
     char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int argvi = 0;
     int result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Unlink(pszFilename);");
+      SWIG_croak("Usage: Unlink(utf8_path);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Unlink" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -4955,10 +4842,8 @@ XS(_wrap_Unlink) {
       
     }
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     SWIG_croak_null();
   }
 }
@@ -5009,9 +4894,6 @@ XS(_wrap_Mkdir) {
   {
     char *arg1 = (char *) 0 ;
     int arg2 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
@@ -5021,11 +4903,11 @@ XS(_wrap_Mkdir) {
     if ((items < 2) || (items > 2)) {
       SWIG_croak("Usage: Mkdir(utf8_path,mode);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Mkdir" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
       SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Mkdir" "', argument " "2"" of type '" "int""'");
@@ -5061,11 +4943,9 @@ XS(_wrap_Mkdir) {
       
     }
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
@@ -5075,9 +4955,6 @@ XS(_wrap_Mkdir) {
 XS(_wrap_Rmdir) {
   {
     char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int argvi = 0;
     int result;
     dXSARGS;
@@ -5085,11 +4962,11 @@ XS(_wrap_Rmdir) {
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: Rmdir(utf8_path);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Rmdir" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -5120,10 +4997,8 @@ XS(_wrap_Rmdir) {
       
     }
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     SWIG_croak_null();
   }
 }
@@ -5196,9 +5071,6 @@ XS(_wrap_Stat) {
   {
     char *arg1 = (char *) 0 ;
     VSIStatBufL *arg2 = (VSIStatBufL *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     VSIStatBufL sStatBuf2 ;
     int argvi = 0;
     RETURN_NONE result;
@@ -5211,11 +5083,11 @@ XS(_wrap_Stat) {
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: Stat(utf8_path);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Stat" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -5268,7 +5140,6 @@ XS(_wrap_Stat) {
       PUSHs(sv_2mortal(newSVuv(sStatBuf2.st_size)));
       argvi++;
     }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     {
       /* %typemap(ret) RETURN_NONE_TRUE_IS_ERROR */
@@ -5278,7 +5149,6 @@ XS(_wrap_Stat) {
     }
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
@@ -5289,9 +5159,6 @@ XS(_wrap_VSIFOpenL) {
   {
     char *arg1 = (char *) 0 ;
     char *arg2 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int res2 ;
     char *buf2 = 0 ;
     int alloc2 = 0 ;
@@ -5302,11 +5169,11 @@ XS(_wrap_VSIFOpenL) {
     if ((items < 2) || (items > 2)) {
       SWIG_croak("Usage: VSIFOpenL(utf8_path,pszMode);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFOpenL" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
     if (!SWIG_IsOK(res2)) {
       SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "VSIFOpenL" "', argument " "2"" of type '" "char const *""'");
@@ -5342,11 +5209,9 @@ XS(_wrap_VSIFOpenL) {
       
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
@@ -5519,49 +5384,32 @@ XS(_wrap_VSIFTellL) {
 }
 
 
-XS(_wrap_VSIFWriteL) {
+XS(_wrap_VSIFTruncateL) {
   {
-    char *arg1 = (char *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    VSILFILE *arg4 = (VSILFILE *) 0 ;
+    VSILFILE *arg1 = (VSILFILE *) 0 ;
+    long arg2 ;
     int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
-    int val2 ;
+    long val2 ;
     int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int res4 ;
     int argvi = 0;
     int result;
     dXSARGS;
     
-    if ((items < 4) || (items > 4)) {
-      SWIG_croak("Usage: VSIFWriteL(char const *,int,int,VSILFILE *);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: VSIFTruncateL(VSILFILE *,long);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
+    res1 = SWIG_ConvertPtr(ST(0),SWIG_as_voidptrptr(&arg1), 0, 0);
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFWriteL" "', argument " "1"" of type '" "char const *""'");
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFTruncateL" "', argument " "1"" of type '" "VSILFILE *""'"); 
     }
-    arg1 = reinterpret_cast< char * >(buf1);
-    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 '" "VSIFWriteL" "', 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 '" "VSIFWriteL" "', argument " "3"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VSIFTruncateL" "', argument " "2"" of type '" "long""'");
     } 
-    arg3 = static_cast< int >(val3);
-    res4 = SWIG_ConvertPtr(ST(3),SWIG_as_voidptrptr(&arg4), 0, 0);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "VSIFWriteL" "', argument " "4"" of type '" "VSILFILE *""'"); 
-    }
+    arg2 = static_cast< long >(val2);
     {
       CPLErrorReset();
-      result = (int)VSIFWriteL((char const *)arg1,arg2,arg3,arg4);
+      result = (int)VSIFTruncateL(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5584,15 +5432,143 @@ XS(_wrap_VSIFWriteL) {
       
     }
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_VSIFWriteL) {
+  {
+    void *arg1 = (void *) 0 ;
+    size_t arg2 ;
+    size_t arg3 ;
+    VSILFILE *arg4 = (VSILFILE *) 0 ;
+    int res4 ;
+    int argvi = 0;
+    size_t result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: VSIFWriteL(pBuffer,nSize,nCount,fp);");
+    }
+    {
+      /* %typemap(in,numinputs=1) (const void *pBuffer, size_t nSize, size_t nCount) */
+      size_t len;
+      arg1 = SvPV(ST(0), len);
+      arg2 = 1;
+      arg3 = len;
+    }
+    res4 = SWIG_ConvertPtr(ST(1),SWIG_as_voidptrptr(&arg4), 0, 0);
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "VSIFWriteL" "', argument " "4"" of type '" "VSILFILE *""'"); 
+    }
+    {
+      CPLErrorReset();
+      result = VSIFWriteL((void const *)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" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_size_t  SWIG_PERL_CALL_ARGS_1(static_cast< size_t >(result)); argvi++ ;
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_VSIFReadL) {
+  {
+    void *arg1 = (void *) 0 ;
+    size_t arg2 ;
+    size_t arg3 ;
+    VSILFILE *arg4 = (VSILFILE *) 0 ;
+    int res4 ;
+    int argvi = 0;
+    SV * _saved[1] ;
+    size_t result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: VSIFReadL(pBuffer,nSize,nCount,fp);");
+    }
+    {
+      /* %typemap(in,numinputs=1) (void *pBuffer, size_t nSize, size_t nCount) */
+      size_t len = SvIV(ST(0));
+      arg1 = malloc(len);
+      arg2 = 1;
+      arg3 = len;
+    }
+    res4 = SWIG_ConvertPtr(ST(1),SWIG_as_voidptrptr(&arg4), 0, 0);
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "VSIFReadL" "', argument " "4"" of type '" "VSILFILE *""'"); 
+    }
+    _saved[0] = ST(0);
+    {
+      CPLErrorReset();
+      result = VSIFReadL(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) (size_t VSIFReadL) */
+    }
+    {
+      /* %typemap(argout) (void *pBuffer, size_t nSize, size_t nCount) */
+      if (result) {
+        ST(argvi) = newSVpvn((char*)arg1, result);
+        sv_2mortal(ST(argvi));
+      } else {
+        ST(argvi) = &PL_sv_undef;
+      }
+      argvi++;
+    }
     
+    XSRETURN(argvi);
+  fail:
     
     SWIG_croak_null();
   }
@@ -5640,7 +5616,13 @@ XS(_wrap_MajorObject_GetDescription) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -5676,9 +5658,9 @@ XS(_wrap_MajorObject_SetDescription) {
     }
     arg2 = reinterpret_cast< char * >(buf2);
     {
-      /* %typemap(check) (const char *pszNewDesc) */
-      if (!arg2)
-      SWIG_croak("The description must not be undefined");
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
     }
     {
       CPLErrorReset();
@@ -6128,7 +6110,13 @@ XS(_wrap_MajorObject_GetMetadataItem) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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;
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -6276,7 +6264,13 @@ XS(_wrap_Driver_ShortName_get) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -6327,7 +6321,13 @@ XS(_wrap_Driver_LongName_get) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -6378,7 +6378,13 @@ XS(_wrap_Driver_HelpTopic_get) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -6399,9 +6405,6 @@ XS(_wrap_Driver__Create) {
     char **arg7 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int val3 ;
     int ecode3 = 0 ;
     int val4 ;
@@ -6422,11 +6425,11 @@ XS(_wrap_Driver__Create) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver__Create" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
     }
     arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver__Create" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    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 '" "Driver__Create" "', argument " "3"" of type '" "int""'");
@@ -6459,7 +6462,9 @@ XS(_wrap_Driver__Create) {
             if (SvTYPE(SvRV(ST(6)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(6)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
                 arg7 = CSLAddString( arg7, pszItem );
               }
             } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
@@ -6470,6 +6475,7 @@ XS(_wrap_Driver__Create) {
               arg7 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
                 arg7 = CSLAddNameValue( arg7, key, SvPV_nolen(sv) );
               }
             } else
@@ -6510,7 +6516,6 @@ XS(_wrap_Driver__Create) {
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     
     
@@ -6522,7 +6527,6 @@ XS(_wrap_Driver__Create) {
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     
     
@@ -6547,9 +6551,6 @@ XS(_wrap_Driver_CreateCopy) {
     void *arg7 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     void *argp3 = 0 ;
     int res3 = 0 ;
     int val4 ;
@@ -6560,7 +6561,8 @@ XS(_wrap_Driver_CreateCopy) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg7 = (void *)(&saved_env);
     if ((items < 3) || (items > 7)) {
       SWIG_croak("Usage: Driver_CreateCopy(self,utf8_path,src,strict,options,callback,callback_data);");
     }
@@ -6569,11 +6571,11 @@ XS(_wrap_Driver_CreateCopy) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateCopy" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
     }
     arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CreateCopy" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
     if (!SWIG_IsOK(res3)) {
       SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Driver_CreateCopy" "', argument " "3"" of type '" "GDALDatasetShadow *""'"); 
@@ -6594,7 +6596,9 @@ XS(_wrap_Driver_CreateCopy) {
             if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -6605,6 +6609,7 @@ XS(_wrap_Driver_CreateCopy) {
               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
@@ -6636,8 +6641,6 @@ XS(_wrap_Driver_CreateCopy) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(6)))
         saved_env.data = (SV *)ST(6);
-        if (saved_env.fct)
-        arg7 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -6676,7 +6679,6 @@ XS(_wrap_Driver_CreateCopy) {
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     
     {
@@ -6687,7 +6689,6 @@ XS(_wrap_Driver_CreateCopy) {
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     
     {
@@ -6706,9 +6707,6 @@ XS(_wrap_Driver_Delete) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     int result;
     dXSARGS;
@@ -6721,11 +6719,11 @@ XS(_wrap_Driver_Delete) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Delete" "', argument " "1"" of type '" "GDALDriverShadow *""'"); 
     }
     arg1 = reinterpret_cast< GDALDriverShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_Delete" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -6757,11 +6755,9 @@ XS(_wrap_Driver_Delete) {
     }
     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();
   }
 }
@@ -8647,7 +8643,13 @@ XS(_wrap_GDAL_GCP_Info_get) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -8769,7 +8771,13 @@ XS(_wrap_GDAL_GCP_Id_get) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -9496,7 +9504,13 @@ XS(_wrap_GDAL_GCP_get_Info) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -9618,7 +9632,13 @@ XS(_wrap_GDAL_GCP_get_Id) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -9769,8 +9789,16 @@ XS(_wrap_GCPsToGeoTransform) {
     }
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg3, 6 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+6-items+1);
+        for (i = 0; i < 6; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg3, 6 );
+        argvi++;
+      }  
     }
     {
       /* %typemap(freearg) (int nGCPs, GDAL_GCP const *pGCPs ) */
@@ -10425,7 +10453,13 @@ XS(_wrap_Dataset_GetProjection) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -10476,7 +10510,13 @@ XS(_wrap_Dataset_GetProjectionRef) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -10604,8 +10644,16 @@ XS(_wrap_Dataset_GetGeoTransform) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+6-items+1);
+        for (i = 0; i < 6; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
+        argvi++;
+      }  
     }
     
     
@@ -10705,7 +10753,8 @@ XS(_wrap_Dataset_BuildOverviews) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
     if ((items < 1) || (items > 5)) {
       SWIG_croak("Usage: Dataset_BuildOverviews(self,resampling,overviewlist,pOverviews,callback,callback_data);");
     }
@@ -10757,8 +10806,6 @@ XS(_wrap_Dataset_BuildOverviews) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(4)))
         saved_env.data = (SV *)ST(4);
-        if (saved_env.fct)
-        arg6 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -10901,7 +10948,13 @@ XS(_wrap_Dataset_GetGCPProjection) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -11169,7 +11222,9 @@ XS(_wrap_Dataset__AddBand) {
             if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -11180,6 +11235,7 @@ XS(_wrap_Dataset__AddBand) {
               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
@@ -11345,9 +11401,10 @@ XS(_wrap_Dataset_GetFileList) {
         if (result) {
           int i;
           for (i = 0; result[i]; i++) {
-            if (i>items-1) EXTEND(SP, 1);
-            ST(argvi) = sv_2mortal(newSVpv(result[i], 0));
-            argvi++;
+            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);
         }
@@ -11356,9 +11413,10 @@ XS(_wrap_Dataset_GetFileList) {
         if (result) {
           int i;
           for (i = 0; result[i]; i++) {
-            SV *s = newSVpv(result[i], 0);
-            if (!av_store(av, i, s))
-            SvREFCNT_dec(s);
+            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);
         }
@@ -12522,7 +12580,13 @@ XS(_wrap_Band_GetUnitType) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -12644,9 +12708,10 @@ XS(_wrap_Band_GetRasterCategoryNames) {
       if ( stringarray != NULL ) {
         int n = CSLCount( stringarray );
         for ( int i = 0; i < n; i++ ) {
-          SV *s = newSVpv(stringarray[i], 0);
-          if (!av_store(av, i, s))
-          SvREFCNT_dec(s);
+          SV *sv = newSVpv(stringarray[i], 0);
+          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+          if (!av_store(av, i, sv))
+          SvREFCNT_dec(sv);
         }
       }
       ST(argvi) = newRV_noinc((SV*)av);
@@ -12686,7 +12751,9 @@ XS(_wrap_Band_SetRasterCategoryNames) {
           if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
-              char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+              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) {
@@ -12697,6 +12764,7 @@ XS(_wrap_Band_SetRasterCategoryNames) {
             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
@@ -13288,7 +13356,8 @@ XS(_wrap_Band_ComputeStatistics) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg8 = (void *)(&saved_env);
     arg3 = &temp3;
     arg4 = &temp4;
     arg5 = &temp5;
@@ -13328,8 +13397,6 @@ XS(_wrap_Band_ComputeStatistics) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(3)))
         saved_env.data = (SV *)ST(3);
-        if (saved_env.fct)
-        arg8 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -13773,8 +13840,16 @@ XS(_wrap_Band_ComputeRasterMinMax) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 2 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+2-items+1);
+        for (i = 0; i < 2; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 2 );
+        argvi++;
+      }  
     }
     
     
@@ -13848,8 +13923,16 @@ XS(_wrap_Band_ComputeBandStats) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 2 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+2-items+1);
+        for (i = 0; i < 2; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 2 );
+        argvi++;
+      }  
     }
     
     
@@ -14897,7 +14980,8 @@ XS(_wrap_Band__GetHistogram) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg9 = (void *)(&saved_env);
     if ((items < 1) || (items > 8)) {
       SWIG_croak("Usage: Band__GetHistogram(self,min,max,buckets,panHistogram,include_out_of_range,approx_ok,callback,callback_data);");
     }
@@ -14962,8 +15046,6 @@ XS(_wrap_Band__GetHistogram) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(7)))
         saved_env.data = (SV *)ST(7);
-        if (saved_env.fct)
-        arg9 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -15002,8 +15084,16 @@ XS(_wrap_Band__GetHistogram) {
     }
     {
       /* %typemap(argout) (int len, int *output) */
-      ST(argvi) = CreateArrayFromIntArray( arg5, arg4 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+arg4-items+1);
+        for (i = 0; i < arg4; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg5[i]));
+      } else {
+        ST(argvi) = CreateArrayFromIntArray( arg5, arg4 );
+        argvi++;
+      }
     }
     
     
@@ -15058,7 +15148,8 @@ XS(_wrap_Band_GetDefaultHistogram) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg8 = (void *)(&saved_env);
     arg2 = &temp2;
     arg3 = &temp3;
     {
@@ -15103,8 +15194,6 @@ XS(_wrap_Band_GetDefaultHistogram) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(3)))
         saved_env.data = (SV *)ST(3);
-        if (saved_env.fct)
-        arg8 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -15314,6 +15403,161 @@ XS(_wrap_Band_HasArbitraryOverviews) {
 }
 
 
+XS(_wrap_Band_GetCategoryNames) {
+  {
+    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    char **result = 0 ;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Band_GetCategoryNames(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &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);
+    {
+      CPLErrorReset();
+      result = (char **)GDALRasterBandShadow_GetCategoryNames(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 **options -> ( string ) */
+      AV* av = (AV*)sv_2mortal((SV*)newAV());
+      char **stringarray = result;
+      if ( stringarray != NULL ) {
+        int n = CSLCount( stringarray );
+        for ( int i = 0; i < n; i++ ) {
+          SV *sv = newSVpv(stringarray[i], 0);
+          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+          if (!av_store(av, i, sv))
+          SvREFCNT_dec(sv);
+        }
+      }
+      ST(argvi) = newRV_noinc((SV*)av);
+      argvi++;
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Band_SetCategoryNames) {
+  {
+    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+    char **arg2 = (char **) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    CPLErr result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Band_SetCategoryNames(self,papszCategoryNames);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &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 *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALRasterBandShadow * >(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("'options' is not a reference to an array or hash");
+        } else
+        SWIG_croak("'options' is not a reference");   
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(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++ ;
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg2) CSLDestroy( arg2 );
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg2) CSLDestroy( arg2 );
+    }
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_Band_ContourGenerate) {
   {
     GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -15346,7 +15590,8 @@ XS(_wrap_Band_ContourGenerate) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg12 = (void *)(&saved_env);
     if ((items < 8) || (items > 10)) {
       SWIG_croak("Usage: Band_ContourGenerate(self,dfContourInterval,dfContourBase,nFixedLevelCount,padfFixedLevels,bUseNoData,dfNoDataValue,hLayer,iIDField,iElevField,callback,callback_data);");
     }
@@ -15419,8 +15664,6 @@ XS(_wrap_Band_ContourGenerate) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(9)))
         saved_env.data = (SV *)ST(9);
-        if (saved_env.fct)
-        arg12 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -16334,7 +16577,13 @@ XS(_wrap_RasterAttributeTable_GetNameOfCol) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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);
@@ -16637,7 +16886,13 @@ XS(_wrap_RasterAttributeTable_GetValueAsString) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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++;
+    }
     
     
     
@@ -16828,6 +17083,7 @@ XS(_wrap_RasterAttributeTable_SetValueAsString) {
     arg3 = static_cast< int >(val3);
     {
       /* %typemap(in) (tostring argin) */
+      sv_utf8_upgrade(ST(3)); /* GDAL expects UTF-8 */
       arg4 = SvPV_nolen( ST(3) ); 
     }
     {
@@ -17476,7 +17732,8 @@ XS(_wrap__ComputeMedianCutPCT) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg7 = (void *)(&saved_env);
     if ((items < 5) || (items > 7)) {
       SWIG_croak("Usage: _ComputeMedianCutPCT(red,green,blue,num_colors,colors,callback,callback_data);");
     }
@@ -17527,8 +17784,6 @@ XS(_wrap__ComputeMedianCutPCT) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(6)))
         saved_env.data = (SV *)ST(6);
-        if (saved_env.fct)
-        arg7 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -17620,7 +17875,8 @@ XS(_wrap__DitherRGB2PCT) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg7 = (void *)(&saved_env);
     if ((items < 5) || (items > 7)) {
       SWIG_croak("Usage: _DitherRGB2PCT(red,green,blue,target,colors,callback,callback_data);");
     }
@@ -17671,8 +17927,6 @@ XS(_wrap__DitherRGB2PCT) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(6)))
         saved_env.data = (SV *)ST(6);
-        if (saved_env.fct)
-        arg7 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -17777,7 +18031,8 @@ XS(_wrap__ReprojectImage) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg9 = (void *)(&saved_env);
     if ((items < 2) || (items > 9)) {
       SWIG_croak("Usage: _ReprojectImage(src_ds,dst_ds,src_wkt,dst_wkt,eResampleAlg,WarpMemoryLimit,maxerror,callback,callback_data);");
     }
@@ -17848,8 +18103,6 @@ XS(_wrap__ReprojectImage) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(8)))
         saved_env.data = (SV *)ST(8);
-        if (saved_env.fct)
-        arg9 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -17927,7 +18180,8 @@ XS(_wrap__ComputeProximity) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg5 = (void *)(&saved_env);
     if ((items < 2) || (items > 5)) {
       SWIG_croak("Usage: _ComputeProximity(srcBand,proximityBand,options,callback,callback_data);");
     }
@@ -17949,7 +18203,9 @@ XS(_wrap__ComputeProximity) {
             if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -17960,6 +18216,7 @@ XS(_wrap__ComputeProximity) {
               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
@@ -17991,8 +18248,6 @@ XS(_wrap__ComputeProximity) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(4)))
         saved_env.data = (SV *)ST(4);
-        if (saved_env.fct)
-        arg5 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -18076,7 +18331,8 @@ XS(_wrap__RasterizeLayer) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg11 = (void *)(&saved_env);
     if ((items < 3) || (items > 9)) {
       SWIG_croak("Usage: _RasterizeLayer(dataset,bands,band_list,layer,pfnTransformer,pTransformArg,burn_values,burn_values_list,options,callback,callback_data);");
     }
@@ -18136,7 +18392,9 @@ XS(_wrap__RasterizeLayer) {
             if (SvTYPE(SvRV(ST(6)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(6)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
                 arg9 = CSLAddString( arg9, pszItem );
               }
             } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
@@ -18147,6 +18405,7 @@ XS(_wrap__RasterizeLayer) {
               arg9 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
                 arg9 = CSLAddNameValue( arg9, key, SvPV_nolen(sv) );
               }
             } else
@@ -18178,8 +18437,6 @@ XS(_wrap__RasterizeLayer) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(8)))
         saved_env.data = (SV *)ST(8);
-        if (saved_env.fct)
-        arg11 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -18285,7 +18542,8 @@ XS(_wrap__Polygonize) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg7 = (void *)(&saved_env);
     if ((items < 4) || (items > 7)) {
       SWIG_croak("Usage: _Polygonize(srcBand,maskBand,outLayer,iPixValField,options,callback,callback_data);");
     }
@@ -18317,7 +18575,9 @@ XS(_wrap__Polygonize) {
             if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -18328,6 +18588,7 @@ XS(_wrap__Polygonize) {
               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
@@ -18359,8 +18620,6 @@ XS(_wrap__Polygonize) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(6)))
         saved_env.data = (SV *)ST(6);
-        if (saved_env.fct)
-        arg7 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -18446,7 +18705,8 @@ XS(_wrap_FillNodata) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg7 = (void *)(&saved_env);
     if ((items < 4) || (items > 7)) {
       SWIG_croak("Usage: FillNodata(targetBand,maskBand,maxSearchDist,smoothingIterations,options,callback,callback_data);");
     }
@@ -18478,7 +18738,9 @@ XS(_wrap_FillNodata) {
             if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -18489,6 +18751,7 @@ XS(_wrap_FillNodata) {
               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
@@ -18520,8 +18783,6 @@ XS(_wrap_FillNodata) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(6)))
         saved_env.data = (SV *)ST(6);
-        if (saved_env.fct)
-        arg7 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -18605,7 +18866,8 @@ XS(_wrap__SieveFilter) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg8 = (void *)(&saved_env);
     if ((items < 4) || (items > 8)) {
       SWIG_croak("Usage: _SieveFilter(srcBand,maskBand,dstBand,threshold,connectedness,options,callback,callback_data);");
     }
@@ -18644,7 +18906,9 @@ XS(_wrap__SieveFilter) {
             if (SvTYPE(SvRV(ST(5)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(5)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                SV *sv = *(av_fetch(av, i, 0));
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+                char *pszItem = SvPV_nolen(sv);
                 arg6 = CSLAddString( arg6, pszItem );
               }
             } else if (SvTYPE(SvRV(ST(5)))==SVt_PVHV) {
@@ -18655,6 +18919,7 @@ XS(_wrap__SieveFilter) {
               arg6 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv,&key,&klen)) {
+                sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
                 arg6 = CSLAddNameValue( arg6, key, SvPV_nolen(sv) );
               }
             } else
@@ -18686,8 +18951,6 @@ XS(_wrap__SieveFilter) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(7)))
         saved_env.data = (SV *)ST(7);
-        if (saved_env.fct)
-        arg8 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -18772,7 +19035,8 @@ XS(_wrap__RegenerateOverview) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg5 = (void *)(&saved_env);
     if ((items < 2) || (items > 5)) {
       SWIG_croak("Usage: _RegenerateOverview(srcBand,overviewBand,resampling,callback,callback_data);");
     }
@@ -18815,8 +19079,6 @@ XS(_wrap__RegenerateOverview) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(4)))
         saved_env.data = (SV *)ST(4);
-        if (saved_env.fct)
-        arg5 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -18905,7 +19167,8 @@ XS(_wrap_ContourGenerate) {
     
     SavedEnv saved_env;
     saved_env.fct = NULL;
-    saved_env.data = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg12 = (void *)(&saved_env);
     if ((items < 9) || (items > 11)) {
       SWIG_croak("Usage: ContourGenerate(srcBand,contourInterval,contourBase,fixedLevelCount,fixedLevels,useNoData,noDataValue,dstLayer,idField,elevField,callback,callback_data);");
     }
@@ -18983,8 +19246,6 @@ XS(_wrap_ContourGenerate) {
         /* %typemap(in) (void* callback_data=NULL) */
         if (SvOK(ST(10)))
         saved_env.data = (SV *)ST(10);
-        if (saved_env.fct)
-        arg12 = (void *)(&saved_env); /* the Perl layer must make sure that this parameter is always given */
       }
     }
     {
@@ -19196,7 +19457,9 @@ XS(_wrap_new_Transformer) {
           if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
             AV *av = (AV*)(SvRV(ST(2)));
             for (int i = 0; i < av_len(av)+1; i++) {
-              char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+              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) {
@@ -19207,6 +19470,7 @@ XS(_wrap_new_Transformer) {
             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
@@ -19376,8 +19640,16 @@ XS(_wrap_Transformer_TransformPoint__SWIG_0) {
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg3, 3 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+3-items+1);
+        for (i = 0; i < 3; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg3, 3 );
+        argvi++;
+      }  
     }
     
     
@@ -19476,8 +19748,16 @@ XS(_wrap_Transformer_TransformPoint__SWIG_1) {
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+3-items+1);
+        for (i = 0; i < 3; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
+        argvi++;
+      }  
     }
     
     
@@ -19912,8 +20192,16 @@ XS(_wrap_InvGeoTransform) {
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+6-items+1);
+        for (i = 0; i < 6; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
+        argvi++;
+      }  
     }
     
     
@@ -19975,7 +20263,13 @@ XS(_wrap_VersionInfo) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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 (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     XSRETURN(argvi);
   fail:
@@ -20340,7 +20634,13 @@ XS(_wrap_GetDataTypeName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -20443,7 +20743,13 @@ XS(_wrap_GetColorInterpretationName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -20494,7 +20800,13 @@ XS(_wrap_GetPaletteInterpretationName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -20564,7 +20876,13 @@ XS(_wrap_DecToDMS) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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;
     
@@ -20963,9 +21281,6 @@ XS(_wrap__Open__SWIG_1) {
   {
     char *arg1 = (char *) 0 ;
     GDALAccess arg2 = (GDALAccess) GA_ReadOnly ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
@@ -20975,11 +21290,11 @@ XS(_wrap__Open__SWIG_1) {
     if ((items < 1) || (items > 2)) {
       SWIG_croak("Usage: _Open(utf8_path,eAccess);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_Open" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     if (items > 1) {
       ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
       if (!SWIG_IsOK(ecode2)) {
@@ -21017,11 +21332,9 @@ XS(_wrap__Open__SWIG_1) {
       
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
@@ -21082,9 +21395,6 @@ XS(_wrap__OpenShared__SWIG_1) {
   {
     char *arg1 = (char *) 0 ;
     GDALAccess arg2 = (GDALAccess) GA_ReadOnly ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
@@ -21094,11 +21404,11 @@ XS(_wrap__OpenShared__SWIG_1) {
     if ((items < 1) || (items > 2)) {
       SWIG_croak("Usage: _OpenShared(utf8_path,eAccess);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_OpenShared" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     if (items > 1) {
       ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
       if (!SWIG_IsOK(ecode2)) {
@@ -21136,11 +21446,9 @@ XS(_wrap__OpenShared__SWIG_1) {
       
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
@@ -21201,9 +21509,6 @@ XS(_wrap_IdentifyDriver) {
   {
     char *arg1 = (char *) 0 ;
     char **arg2 = (char **) NULL ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int argvi = 0;
     GDALDriverShadow *result = 0 ;
     dXSARGS;
@@ -21211,11 +21516,11 @@ XS(_wrap_IdentifyDriver) {
     if ((items < 1) || (items > 2)) {
       SWIG_croak("Usage: IdentifyDriver(utf8_path,papszSiblings);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IdentifyDriver" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     if (items > 1) {
       {
         /* %typemap(in) char **options */
@@ -21224,7 +21529,9 @@ XS(_wrap_IdentifyDriver) {
             if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -21235,6 +21542,7 @@ XS(_wrap_IdentifyDriver) {
               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
@@ -21274,14 +21582,12 @@ XS(_wrap_IdentifyDriver) {
       
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) char **options */
       if (arg2) CSLDestroy( arg2 );
     }
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) char **options */
       if (arg2) CSLDestroy( arg2 );
@@ -21318,7 +21624,6 @@ static swig_type_info _swigt__p_GDALRasterBandShadow = {"_p_GDALRasterBandShadow
 static swig_type_info _swigt__p_GDALTransformerInfoShadow = {"_p_GDALTransformerInfoShadow", "GDALTransformerInfoShadow *", 0, 0, (void*)"Geo::GDAL::Transformer", 0};
 static swig_type_info _swigt__p_GDAL_GCP = {"_p_GDAL_GCP", "GDAL_GCP *", 0, 0, (void*)"Geo::GDAL::GCP", 0};
 static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)"Geo::OGR::Layer", 0};
-static swig_type_info _swigt__p_SavedEnv = {"_p_SavedEnv", "SavedEnv *", 0, 0, (void*)"Geo::GDAL::SavedEnv", 0};
 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};
@@ -21345,7 +21650,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GDALTransformerInfoShadow,
   &_swigt__p_GDAL_GCP,
   &_swigt__p_OGRLayerShadow,
-  &_swigt__p_SavedEnv,
   &_swigt__p_VSIStatBufL,
   &_swigt__p_char,
   &_swigt__p_double,
@@ -21372,7 +21676,6 @@ static swig_cast_info _swigc__p_GDALRasterBandShadow[] = {  {&_swigt__p_GDALRast
 static swig_cast_info _swigc__p_GDALTransformerInfoShadow[] = {  {&_swigt__p_GDALTransformerInfoShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDAL_GCP[] = {  {&_swigt__p_GDAL_GCP, 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_SavedEnv[] = {  {&_swigt__p_SavedEnv, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_VSIStatBufL[] = {  {&_swigt__p_VSIStatBufL, 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_double[] = {  {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}};
@@ -21399,7 +21702,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GDALTransformerInfoShadow,
   _swigc__p_GDAL_GCP,
   _swigc__p_OGRLayerShadow,
-  _swigc__p_SavedEnv,
   _swigc__p_VSIStatBufL,
   _swigc__p_char,
   _swigc__p_double,
@@ -21424,12 +21726,6 @@ static swig_variable_info swig_variables[] = {
 {0,0,0,0}
 };
 static swig_command_info swig_commands[] = {
-{"Geo::GDALc::SavedEnv_fct_set", _wrap_SavedEnv_fct_set},
-{"Geo::GDALc::SavedEnv_fct_get", _wrap_SavedEnv_fct_get},
-{"Geo::GDALc::SavedEnv_data_set", _wrap_SavedEnv_data_set},
-{"Geo::GDALc::SavedEnv_data_get", _wrap_SavedEnv_data_get},
-{"Geo::GDALc::new_SavedEnv", _wrap_new_SavedEnv},
-{"Geo::GDALc::delete_SavedEnv", _wrap_delete_SavedEnv},
 {"Geo::GDALc::callback_d_cp_vp", _wrap_callback_d_cp_vp},
 {"Geo::GDALc::UseExceptions", _wrap_UseExceptions},
 {"Geo::GDALc::DontUseExceptions", _wrap_DontUseExceptions},
@@ -21462,7 +21758,9 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::VSIFCloseL", _wrap_VSIFCloseL},
 {"Geo::GDALc::VSIFSeekL", _wrap_VSIFSeekL},
 {"Geo::GDALc::VSIFTellL", _wrap_VSIFTellL},
+{"Geo::GDALc::VSIFTruncateL", _wrap_VSIFTruncateL},
 {"Geo::GDALc::VSIFWriteL", _wrap_VSIFWriteL},
+{"Geo::GDALc::VSIFReadL", _wrap_VSIFReadL},
 {"Geo::GDALc::MajorObject_GetDescription", _wrap_MajorObject_GetDescription},
 {"Geo::GDALc::MajorObject_SetDescription", _wrap_MajorObject_SetDescription},
 {"Geo::GDALc::MajorObject_GetMetadata", _wrap_MajorObject_GetMetadata},
@@ -21596,6 +21894,8 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::Band_GetDefaultHistogram", _wrap_Band_GetDefaultHistogram},
 {"Geo::GDALc::Band_SetDefaultHistogram", _wrap_Band_SetDefaultHistogram},
 {"Geo::GDALc::Band_HasArbitraryOverviews", _wrap_Band_HasArbitraryOverviews},
+{"Geo::GDALc::Band_GetCategoryNames", _wrap_Band_GetCategoryNames},
+{"Geo::GDALc::Band_SetCategoryNames", _wrap_Band_SetCategoryNames},
 {"Geo::GDALc::Band_ContourGenerate", _wrap_Band_ContourGenerate},
 {"Geo::GDALc::new_ColorTable", _wrap_new_ColorTable},
 {"Geo::GDALc::delete_ColorTable", _wrap_delete_ColorTable},
@@ -21968,7 +22268,6 @@ XS(SWIG_init) {
     GDALAllRegister();
   }
   
-  SWIG_TypeClientData(SWIGTYPE_p_SavedEnv, (void*) "Geo::GDAL::SavedEnv");
   SWIG_TypeClientData(SWIGTYPE_p_GDALMajorObjectShadow, (void*) "Geo::GDAL::MajorObject");
   SWIG_TypeClientData(SWIGTYPE_p_GDALDriverShadow, (void*) "Geo::GDAL::Driver");
   SWIG_TypeClientData(SWIGTYPE_p_GDAL_GCP, (void*) "Geo::GDAL::GCP");
@@ -21977,7 +22276,7 @@ XS(SWIG_init) {
   SWIG_TypeClientData(SWIGTYPE_p_GDALRasterBandShadow, (void*) "Geo::GDAL::Band");
   SWIG_TypeClientData(SWIGTYPE_p_GDALColorTableShadow, (void*) "Geo::GDAL::ColorTable");
   SWIG_TypeClientData(SWIGTYPE_p_GDALRasterAttributeTableShadow, (void*) "Geo::GDAL::RasterAttributeTable");
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "TermProgress", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_NewFunctionPtrObj((void *)(int (*)(double,char const *,void *))(GDALTermProgress), SWIGTYPE_p_f_double_p_q_const__char_p_void__int));
     SvREADONLY_on(sv);
diff --git a/swig/perl/gdalconst_wrap.c b/swig/perl/gdalconst_wrap.c
index 0baeb01..5188290 100644
--- a/swig/perl/gdalconst_wrap.c
+++ b/swig/perl/gdalconst_wrap.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -894,6 +894,7 @@ SWIG_Perl_ErrorType(int code) {
 
 /* for raw pointers */
 #define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
 #define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
 
 /* for raw packed data */
@@ -1110,10 +1111,14 @@ SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
 /* Function for getting a pointer value */
 
 SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
   swig_cast_info *tc;
   void *voidptr = (void *)0;
   SV *tsv = 0;
+
+  if (own)
+    *own = 0;
+
   /* If magical, apply more magic */
   if (SvGMAGICAL(sv))
     mg_get(sv);
@@ -1163,7 +1168,11 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
     {
       int newmemory = 0;
       *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      assert(!newmemory); /* newmemory handling not yet implemented */
+      if (newmemory == SWIG_CAST_NEW_MEMORY) {
+        assert(own);
+        if (own)
+          *own = *own | SWIG_CAST_NEW_MEMORY;
+      }
     }
   } else {
     *ptr = voidptr;
@@ -1193,9 +1202,14 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
   return SWIG_OK;
 }
 
+SWIGRUNTIME int
+SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
+}
+
 SWIGRUNTIME void
 SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & SWIG_SHADOW)) {
+  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
     SV *self;
     SV *obj=newSV(0);
     HV *hash=newHV();
@@ -1370,6 +1384,9 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #ifdef do_close
   #undef do_close
 #endif
+#ifdef do_exec
+  #undef do_exec
+#endif
 #ifdef scalar
   #undef scalar
 #endif
@@ -1484,7 +1501,7 @@ static swig_module_info swig_module = {swig_types, 1, 0, 0, 0, 0};
 #define SWIG_name   "Geo::GDAL::Constc::boot_Geo__GDAL__Const"
 #define SWIG_prefix "Geo::GDAL::Constc::"
 
-#define SWIGVERSION 0x010339 
+#define SWIGVERSION 0x010340 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -1898,537 +1915,537 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   }
   
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_Unknown", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Unknown)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_Byte", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Byte)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_UInt16", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_UInt16)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_Int16", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Int16)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_UInt32", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_UInt32)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_Int32", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Int32)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_Float32", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Float32)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_Float64", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_Float64)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_CInt16", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CInt16)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_CInt32", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CInt32)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_CFloat32", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CFloat32)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_CFloat64", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_CFloat64)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GDT_TypeCount", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GDT_TypeCount)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GA_ReadOnly", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GA_ReadOnly)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GA_Update", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GA_Update)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GF_Read", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GF_Read)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GF_Write", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GF_Write)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_Undefined", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_Undefined)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_GrayIndex", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_GrayIndex)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_PaletteIndex", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_PaletteIndex)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_RedBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_RedBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_GreenBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_GreenBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_BlueBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_BlueBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_AlphaBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_AlphaBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_HueBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_HueBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_SaturationBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_SaturationBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_LightnessBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_LightnessBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_CyanBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_CyanBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_MagentaBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_MagentaBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_YellowBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YellowBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_BlackBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_BlackBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_YCbCr_YBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YCbCr_YBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_YCbCr_CrBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YCbCr_CrBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GCI_YCbCr_CbBand", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GCI_YCbCr_CbBand)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GRA_NearestNeighbour", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_NearestNeighbour)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GRA_Bilinear", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Bilinear)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GRA_Cubic", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Cubic)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GRA_CubicSpline", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_CubicSpline)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GRA_Lanczos", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GRA_Lanczos)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GPI_Gray", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_Gray)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GPI_RGB", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_RGB)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GPI_CMYK", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_CMYK)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GPI_HLS", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GPI_HLS)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CXT_Element", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Element)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CXT_Text", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Text)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CXT_Attribute", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Attribute)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CXT_Comment", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Comment)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CXT_Literal", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CXT_Literal)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CE_None", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_None)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CE_Debug", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Debug)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CE_Warning", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Warning)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CE_Failure", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Failure)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CE_Fatal", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CE_Fatal)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_None", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_None)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_AppDefined", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_AppDefined)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_OutOfMemory", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_OutOfMemory)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_FileIO", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_FileIO)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_OpenFailed", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_OpenFailed)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_IllegalArg", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_IllegalArg)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_NotSupported", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_NotSupported)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_AssertionFailed", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_AssertionFailed)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_NoWriteAccess", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_NoWriteAccess)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLE_UserInterrupt", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLE_UserInterrupt)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DMD_LONGNAME", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_LONGNAME));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DMD_HELPTOPIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_HELPTOPIC));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DMD_MIMETYPE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_MIMETYPE));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DMD_EXTENSION", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_EXTENSION));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DMD_CREATIONOPTIONLIST", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_CREATIONOPTIONLIST));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DMD_CREATIONDATATYPES", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DMD_CREATIONDATATYPES));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DCAP_CREATE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_CREATE));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DCAP_CREATECOPY", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_CREATECOPY));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "DCAP_VIRTUALIO", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr(GDAL_DCAP_VIRTUALIO));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLES_BackslashQuotable", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_BackslashQuotable)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLES_XML", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_XML)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLES_URL", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_URL)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLES_SQL", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_SQL)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "CPLES_CSV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(CPLES_CSV)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFT_Integer", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFT_Integer)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFT_Real", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFT_Real)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFT_String", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFT_String)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Generic", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Generic)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_PixelCount", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_PixelCount)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Name", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Name)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Min", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Min)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Max", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Max)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_MinMax", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_MinMax)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Red", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Red)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Green", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Green)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Blue", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Blue)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_Alpha", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_Alpha)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_RedMin", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_RedMin)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_GreenMin", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_GreenMin)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_BlueMin", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_BlueMin)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_AlphaMin", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_AlphaMin)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_RedMax", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_RedMax)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_GreenMax", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_GreenMax)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_BlueMax", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_BlueMax)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_AlphaMax", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_AlphaMax)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GFU_MaxCount", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GFU_MaxCount)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GMF_ALL_VALID", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x01)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GMF_PER_DATASET", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x02)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GMF_ALPHA", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x04)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GMF_NODATA", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x08)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GARIO_PENDING", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_PENDING)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GARIO_UPDATE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_UPDATE)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GARIO_ERROR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_ERROR)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GARIO_COMPLETE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_COMPLETE)));
     SvREADONLY_on(sv);
diff --git a/swig/perl/index.dox b/swig/perl/index.dox
index 3cd2dcc..b7abba0 100644
--- a/swig/perl/index.dox
+++ b/swig/perl/index.dox
@@ -5,24 +5,27 @@
 These pages document the development version of the GDAL Perl API,
 which is extended from the released versions APIs.
 
-<a href="http://map.hut.fi/doc/Geo-GDAL-1.4/html/index.html">The
+<a href="http://geoinformatics.tkk.fi/doc/Geo-GDAL-1.4/html/index.html">The
 documentation for the version 1.4 API.</a>
 
-<a href="http://map.hut.fi/doc/Geo-GDAL-1.5/html/index.html">The
+<a href="http://geoinformatics.tkk.fi/doc/Geo-GDAL-1.5/html/index.html">The
 documentation for the version 1.5 API.</a>
 
-<a href="http://map.hut.fi/doc/Geo-GDAL-1.6/html/index.html">The
+<a href="http://geoinformatics.tkk.fi/doc/Geo-GDAL-1.6/html/index.html">The
 documentation for the version 1.6 API.</a>
 
-<a href="http://map.hut.fi/doc/Geo-GDAL-1.7/html/index.html">The
+<a href="http://geoinformatics.tkk.fi/doc/Geo-GDAL-1.7/html/index.html">The
 documentation for the version 1.7 API.</a>
 
+<a href="http://geoinformatics.tkk.fi/doc/Geo-GDAL-1.8/html/index.html">The
+documentation for the version 1.8 API.</a>
+
 \section index_intro Introduction
 
 The Geo::GDAL modules are the Perl bindings to the GDAL/OGR
-library. The modules allow you to access and manipulate from Perl all
-geospatial data that the installed GDAL library is configured to
-read/write.
+library. The modules allow you to use Perl to access and manipulate
+all geospatial data that the installed GDAL library is configured to
+access and manipulate.
 
 This documentation covers mainly the syntax of the bindings. For more
 in-depth documentation see the main documentation of <a
@@ -102,10 +105,10 @@ constructors (new and create) must be called as class methods.
 
 \section index_exceptions Exceptions
 
-Geo::GDAL uses the Perl exception mechanism in such a way that
-exceptions that are classified in GDAL as failures or fatal errors
-trigger a Perl exception, and an exception that is classified as a
-warning triggers a Perl warning.
+Geo::GDAL uses the Perl exception mechanism. This means that
+exceptions that GDAL classifies as failures or fatal errors trigger a
+Perl exception, and an exception that is classified as a warning
+triggers a Perl warning.
 
 Perl exceptions can be caught by \a eval() and Perl warnings can be
 caught by signal '__WARN__'. Examples:
@@ -139,6 +142,7 @@ Warning: Driver GTiff does not support a creation option at site/lib/Geo/GDAL.pm
 This documentation is generated from files within the GDAL
 distribution (directory swig/perl) with a tweaked version of <a
 href="http://www.bigsister.ch/doxygenfilter/">Perl Doxygen Filter</a>
-with Doxygen.
+with Doxygen. The modified version is available <a
+href="https://geoinformatics.tkk.fi/svn/doxygenfilter/">here</a>.
 
 */
diff --git a/swig/perl/lib/Geo/GDAL.dox b/swig/perl/lib/Geo/GDAL.dox
index d843424..cdfc235 100644
--- a/swig/perl/lib/Geo/GDAL.dox
+++ b/swig/perl/lib/Geo/GDAL.dox
@@ -10,6 +10,7 @@
 ## @ignore STORE
 ## @ignore this
 ## @ignore UseExceptions
+## @ignore DontUseExceptions
 ## @ignore PushErrorHandler
 ## @ignore PopErrorHandler
 ## @ignore Debug
@@ -18,6 +19,21 @@
 ## @ignore GetLastErrorNo
 ## @ignore GetLastErrorType
 ## @ignore GetLastErrorMsg
+## @ignore ApplyGeoTransform
+## @ignore ContourGenerate
+## @ignore EscapeString
+## @ignore FileFromMemBuffer
+## @ignore FillNodata
+## @ignore GDALDestroyDriverManager
+## @ignore HasThreadSupport
+## @ignore InvGeoTransform
+## @ignore Mkdir
+## @ignore Rename
+## @ignore Rmdir
+## @ignore TermProgress
+## @ignore TermProgress_nocb
+## @ignore Unlink
+## @ignore callback_d_cp_vp 
 
 ## @fn @ReadDir($dir)
 # @return Contents of the directory.
@@ -28,6 +44,28 @@
 # for a socket, b for a block special file, and c for a character
 # special file.
 
+## @fn Unlink($filename)
+# @param filename The file to delete.
+# @return 0 on success and -1 on an error.
+
+## @fn $VSIFOpenL($filename, $mode)
+# @param filename Name of the file to open. For example "/vsimem/x".
+# @param mode Access mode. 'r', 'r+', 'w', etc.
+# @return A file handle on success.
+
+## @fn VSIFCloseL($file)
+# @param file The file handle.
+
+## @fn $VSIFWriteL($scalar, $file)
+# @param scalar The byte string to write to the file.
+# @param file The file handle.
+# @return Number of bytes written into the file.
+
+## @fn $VSIFReadL($count, $file)
+# @param count The number of bytes to read from the file.
+# @param file The file handle.
+# @return A byte string.
+
 ## @fn $VersionInfo($request = 'VERSION_NUM')
 # @param request A string specifying the request. Currently either
 # "VERSION_NUM", "RELEASE_DATE", "RELEASE_NAME", or
@@ -46,8 +84,7 @@
 # Clear the set of support file search paths.
 
 ## @fn $FindFile($class, $basename)
-#
-# \brief Search for GDAL support files.
+# Search for GDAL support files.
 #
 # An example:
 # \code
@@ -190,7 +227,7 @@
 
 ## @fn Geo::GDAL::Driver Driver($driver)
 # Create a driver object for the internal GDAL driver.
-# \note aka GetDriver
+# \note a.k.a. GetDriver
 # @param driver The name or number of the driver.
 # @return a new Geo::GDAL::Driver object
 
@@ -204,7 +241,7 @@
 # @return a new Geo::GDAL::Driver object
 
 ## @fn ComputeMedianCutPCT($red, $green, $blue, $num_colors, $colors, $callback, $callback_data)
-# \brief Compute an "optimal" color table for a three band image.
+# Compute an "optimal" color table for a three band image.
 # @param red a Geo::GDAL::Band object
 # @param green a Geo::GDAL::Band object
 # @param blue a Geo::GDAL::Band object
@@ -217,7 +254,7 @@
 # <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
 
 ## @fn DitherRGB2PCT($red, $green, $blue, $target, $colors, $callback, $callback_data)
-# \brief Dither a three band image into one band using a color table.
+# Dither a three band image into one band using a color table.
 # @param red a Geo::GDAL::Band object
 # @param green a Geo::GDAL::Band object
 # @param blue a Geo::GDAL::Band object
@@ -393,11 +430,17 @@
 # @return
 
 
-## @class Geo::GDAL::MajorObject
+## @class Geo::GDAL::AsyncReader
 # @isa (Geo::GDAL)
+# This class is not yet documented not tested in the GDAL Perl wrappers
+
+## @ignore GetNextUpdatedRegion
+## @ignore LockBuffer
+## @ignore UnlockBuffer
 
-## @ignore DISOWN
-## @ignore ACQUIRE
+
+## @class Geo::GDAL::MajorObject
+# @isa (Geo::GDAL)
 
 ## @attr DOMAINS
 # a class specific list, well known metadata domains
@@ -415,16 +458,22 @@
 ## @method SetDescription($NewDesc)
 # @param NewDesc
 
+## @ignore SetMetadataItem
+
+## @ignore GetMetadataItem
+
 ## @method \%Metadata(\%metadata = undef, $domain = '')
 # @param metadata
 # @param domain
 # @return the metadata in a non-void context.
 
 ## @method \%GetMetadata($domain = "")
+# @note see Metadata
 # @param domain
 # @return
 
 ## @method SetMetadata(\%metadata, $domain = "")
+# @note see Metadata
 # @param metadata
 # @param domain
 
@@ -432,12 +481,11 @@
 ## @class Geo::GDAL::Driver
 # @isa (Geo::GDAL::MajorObject Geo::GDAL)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
+## @ignore Register
 
-## @ignore Register()
+## @ignore Deregister
 
-## @ignore Deregister()
+## @ignore CopyFiles
 
 ## @attr ShortName
 # $driver->{ShortName}
@@ -488,8 +536,8 @@
 
 ## @method Geo::GDAL::Dataset Create($name, $xsize, $ysize, $bands =1, $type = 'Byte', \%options = undef)
 # Create a GDAL dataset using this driver.
-# \note aka CreateDataset
-# @brief Create a new Geo::GDAL::Dataset
+# \note a.k.a. CreateDataset
+# Create a new Geo::GDAL::Dataset
 # @param name
 # @param xsize
 # @param ysize
@@ -503,10 +551,11 @@
 # \endcode
 # @return a new Geo::GDAL::Dataset object
 
+## @ignore CreateCopy
+
 ## @method Geo::GDAL::Dataset Copy($name, $src, $strict = 1, \%options = undef)
-# Copy a GDAL dataset.
-# \note aka CopyDataset
-# @brief Create a new Geo::GDAL::Dataset as a copy of an existing dataset.
+# Create a new Geo::GDAL::Dataset as a copy of an existing dataset.
+# @note a.k.a. CreateCopy 
 # @param name
 # @param src A Geo::GDAL::Dataset object.
 # @param strict
@@ -520,10 +569,6 @@
 ## @class Geo::GDAL::GCP
 # @isa (Geo::GDAL)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-
 ## @cmethod $new($x = 0.0, $y = 0.0, $z = 0.0, $pixel = 0.0, $line = 0.0, $info = "", $id = "")
 # @param x
 # @param y
@@ -561,10 +606,6 @@
 ## @class Geo::GDAL::Dataset
 # @isa (Geo::GDAL::MajorObject Geo::GDAL)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-
 ## @attr RasterXSize
 # scalar (access as $dataset->{RasterXSize})
 
@@ -589,6 +630,9 @@
 # @param access Either ReadOnly or Update.
 # @return a new Geo::GDAL::Dataset object.
 
+## @method @GetFileList()
+# @return list of files GDAL believes to be part of this dataset.
+
 ## @method @Size()
 # @return (width, height)
 
@@ -597,7 +641,7 @@
 
 ## @method Geo::GDAL::Band Band($index)
 # Create a band object for the band within the dataset.
-# \note aka GetRasterBand
+# \note a.k.a. GetRasterBand
 # @param index 1...RasterCount
 # @return a new Geo::GDAL::Band object
 
@@ -612,8 +656,7 @@
 ## @method $GetProjection()
 # @return the projection as WKT
 
-## @ignore $GetProjectionRef()
-# @return the projection as WKT
+## @ignore GetProjectionRef
 
 ## @method $SetProjection($proj)
 # @param proj projection as WKT
@@ -703,8 +746,7 @@
 ## @class Geo::GDAL::Band
 # @isa ( Geo::GDAL::MajorObject Geo::GDAL )
 
-## @ignore DISOWN
-## @ignore ACQUIRE
+## @attr list COLOR_INTERPRETATIONS
 
 ## @attr XSize
 # scalar (access as $band->{XSize})
@@ -712,6 +754,12 @@
 ## @attr YSize
 # scalar (access as $band->{YSize})
 
+## @ignore GetBand
+
+## @method $GetBandNumber()
+# @note a.k.a. GetBand
+# @return the number of this band.
+
 ## @method $DataType()
 # @return a data type string (Byte, UInt16, Int16, UInt32, Int32, Float32,
 # Float64, CInt16, CInt32, CFloat32, or CFloat64).
@@ -723,26 +771,51 @@
 # @return the size of a preferred i/o raster blocks as a list (width,
 # height).
 
+## @ignore GetRasterColorInterpretation
+## @ignore SetRasterColorInterpretation
+## @ignore GetColorInterpretation
+## @ignore SetColorInterpretation
+
 ## @method $ColorInterpretation($color_interpretation)
-# Color interpretation is currently one of Undefined GrayIndex
-# PaletteIndex RedBand GreenBand BlueBand AlphaBand HueBand
-# SaturationBand LightnessBand CyanBand MagentaBand YellowBand
-# BlackBand
-# @param color_interpretation [optional] new color interpretation
-# @return color interpretation
+# @note a.k.a. GetRasterColorInterpretation and GetColorInterpretation
+# (get only and returns an integer), SetRasterColorInterpretation and
+# SetColorInterpretation (set only and requires an integer)
+# @param color_interpretation [optional] new color interpretation, one
+# of \@Geo::GDAL::Band::COLOR_INTERPRETATIONS
+# @return color interpretation, one of \@Geo::GDAL::Band::COLOR_INTERPRETATIONS
+
+## @ignore GetNoDataValue
+## @ignore SetNoDataValue
 
 ## @method $NoDataValue($NoDataValue)
+# @note a.k.a. GetNoDataValue (get only), SetNoDataValue (set only)
 # @param NoDataValue [optional]
 # Get or set the no data value.
 # @note There does not exist a good way to clear the no data
 # value. $band->NoDataValue(undef) does not do what you want.
 # @return the nodata value.
 
-## @method $GetNoDataValue()
-# @return number (the "no data" value) or undef (there is no "no data" value).
+## @ignore GetUnitType
+## @ignore SetUnitType
+
+## @method Unit($type)
+# @param [optional] the unit (a string).
+# @return the unit (a string).
+# @since version 1.9 of the bindings.
 
-## @method SetNoDataValue($NoDataValue)
-# @param NoDataValue A number. undef does not do what it should do.
+## @ignore GetScale
+## @ignore SetScale
+## @ignore GetOffset
+## @ignore SetOffset
+
+## @method ScaleAndOffset($scale, $offset)
+# Scale and offset are used to transform raw pixel values into the
+# units returned by GetUnits(). The conversion function is:
+# \code
+# Units value = (raw value * scale) + offset
+# \endcode
+# @return ($scale, $offset)
+# @since version 1.9 of the bindings.
 
 ## @method $GetMinimum()
 # @return statistical minimum of the band or undef if statistics are
@@ -752,21 +825,10 @@
 # @return statistical minimum of the band or undef if statistics are
 # not kept or computed.
 
-## @method $GetOffset()
-# Scale and offset used to store data values in transformed form. The
-# conversion function is:
-# \code
-# Units value = (raw value * scale) + offset
-# \endcode
-# @return offset or undef.
-
-## @method $GetScale()
-# Scale and offset are used to store data values in transformed form. The
-# conversion function is:
-# \code
-# Units value = (raw value * scale) + offset
-# \endcode
-# @return scale or undef.
+## @method @ComputeStatistics($approx_ok)
+# @param approx_ok Whether it is allowed to compute the statistics
+# based on overviews or similar.
+# @return a list ($min, $max, $mean, $stddev).
 
 ## @method @GetStatistics($approx_ok, $force)
 # @param approx_ok Whether it is allowed to compute the statistics
@@ -789,6 +851,9 @@
 # @param band 0..GetOverviewCount-1
 # @return a new Geo::GDAL::Band object.
 
+## @method HasArbitraryOverviews()
+# @return true or false.
+
 ## @method $Checksum($xoff = 0, $yoff = 0, $xsize = undef, $ysize = undef)
 # Computes a checksum from the raster or a part of it.
 # @param xoff
@@ -856,8 +921,8 @@
 # - \a Min the lower bound, default is -0.5
 # - \a Max the upper bound, default is 255.5
 # - \a Buckets the number of buckets in the histogram, default is 256
-# - \a IncludeOutOfRange whether to use $histogram[0] and
-# $histogram[$#histogram] for out of range values, default is false;
+# - \a IncludeOutOfRange whether to use the first and last values in the returned list
+# for out of range values, default is false;
 # the bucket size is (Max-Min) / Buckets if this is false and
 # (Max-Min) / (Buckets-2) if this is true
 # - \a ApproxOK if histogram can be computed from overviews, default is false
@@ -865,6 +930,18 @@
 # - \a ProgressData data for the progress function, the default is undef
 # @return a list which contains the count of values in each bucket
 
+## @method @GetDefaultHistogram($force = 1, $callback = undef, $callback_data = undef)
+# @param force true to force the computation
+# @param callback [optional] a reference to a subroutine, which will
+# be called with parameters (number progress, string msg, callback_data)
+# @param callback_data [optional]
+# @return a list: ($min, $max, arrayref histogram).
+
+## @method @SetDefaultHistogram($min, $max, $histogram)
+# @param min
+# @param max
+# @param histogram reference to an array containing the histogram
+
 ## @method FlushCache()
 # Write cached data to disk. There is usually no need to call this
 # method.
@@ -874,10 +951,16 @@
 # @param ColorTable [optional] a Geo::GDAL::ColorTable object
 # @return a new Geo::GDAL::ColorTable object in a non-void context.
 
-## @method Geo::GDAL::ColorTable GetRasterColorTable()
+## @ignore GetRasterColorTable
+
+## @method Geo::GDAL::ColorTable GetColorTable()
+# @note a.k.a. GetRasterColorTable, see also ColorTable
 # @return a color table object.
 
-## @method SetRasterColorTable($ColorTable)
+## @ignore SetRasterColorTable
+
+## @method SetColorTable($ColorTable)
+# @note a.k.a. SetRasterColorTable, see also ColorTable
 # @param ColorTable A color table object.
 
 ## @method CreateMaskBand()
@@ -890,10 +973,16 @@
 # @param names [optional]
 # @return
 
+## @ignore GetCategoryNames
+
 ## @method $GetRasterCategoryNames()
-# @return
+# @note a.k.a. GetCategoryNames, see also CategoryNames
+# @return names
+
+## @ignore SetCategoryNames
 
 ## @method SetRasterCategoryNames($names)
+# @note a.k.a. SetCategoryNames, see also CategoryNames
 # @param names
 
 ## @method Geo::GDAL::RasterAttributeTable AttributeTable($AttributeTable)
@@ -910,8 +999,11 @@
 ## @method SetDefaultRAT($AttributeTable)
 # @param AttributeTable a Geo::GDAL::RasterAttributeTable object
 
+## @ignore ContourGenerate
+
 ## @method Geo::OGR::Layer Contours($DataSource, \%LayerConstructor, $ContourInterval, $ContourBase, \@FixedLevels, $NoDataValue, $IDField, $ElevField, $callback, $callback_data)
 # Generate contours for this raster band. This method can also be used with named parameters.
+# @note This method is a wrapper for ContourGenerate.
 # @param DataSource a Geo::OGR::DataSource object, default is a Memory data source
 # @param LayerConstructor data for Geo::OGR::DataSource::CreateLayer, default is {Name => 'contours'}
 # @param ContourInterval default is 100
@@ -926,31 +1018,22 @@
 # @return
 
 ## @method FillNodata($mask, $max_search_dist = 10, $smoothing_iterations = 0, $options = {}, $callback, $callback_data)
+# @note This is a wrapper for Geo::GDAL::FillNodata.
 # @param mask a mask band indicating pixels to be interpolated (zero valued)
 # @param max_search_dist [optional] the maximum number of pixels to
 # search in all directions to find values to interpolate from.
 # @param smoothing_iterations [optional] the number of 3x3 smoothing filter passes to run (0 or more).
-# @param options [optional] A reference to an anonymous hash. No options have been defined so far.
+# @param options [optional] A reference to a hash. No options have been defined so far for this algorithm.
 # @param callback [optional] a reference to a subroutine, which will
 # be called with parameters (number progress, string msg, callback_data)
 # @param callback_data [optional]
 #
 # <a href="http://www.gdal.org/gdal__alg_8h.html">Documentation for GDAL algorithms</a>
 
-## @method $GetRasterColorInterpretation()
-# @deprecated use Geo::GDAL::Band::ColorInterpretation, which understands strings
-
-## @method SetRasterColorInterpretation()
-# @deprecated use Geo::GDAL::Band::ColorInterpretation, which understands strings
-
 
 ## @class Geo::GDAL::ColorTable
 # @isa ( Geo::GDAL::MajorObject Geo::GDAL )
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-
 ## @cmethod Geo::GDAL::ColorTable new($GDALPaletteInterp = $Geo::GDAL::Const::GPI_RGB)
 # @deprecated use Geo::GDAL::ColorTable::create, which uses string constants
 # @return a new Geo::GDAL::ColorTable object
@@ -1005,10 +1088,6 @@
 ## @class Geo::GDAL::RasterAttributeTable
 # @isa = ( Geo::GDAL::MajorObject Geo::GDAL )
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-
 ## @cmethod Geo::GDAL::RasterAttributeTable new()
 # @return a new Geo::GDAL::RasterAttributeTable object
 
@@ -1095,3 +1174,15 @@
 # @param row
 # @param column
 # @param value
+
+## @ignore GetLinearBinning
+## @ignore SetLinearBinning
+
+## @method LinearBinning($Row0MinIn, $BinSizeIn)
+# @param Row0MinIn [optional] the lower bound (pixel value) of the first category.
+# @param BinSizeIn [optional] the width of each category (in pixel value units).
+# @return ($Row0MinIn, $BinSizeIn) or an empty list if LinearBinning is not set.
+
+
+## @class Geo::GDAL::Transformer
+# This class is not yet documented for the GDAL Perl bindings.
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
index 18c89ff..780c123 100644
--- a/swig/perl/lib/Geo/GDAL.pm
+++ b/swig/perl/lib/Geo/GDAL.pm
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.39
+# Version 1.3.40
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -83,7 +83,9 @@ package Geo::GDAL;
 *VSIFCloseL = *Geo::GDALc::VSIFCloseL;
 *VSIFSeekL = *Geo::GDALc::VSIFSeekL;
 *VSIFTellL = *Geo::GDALc::VSIFTellL;
+*VSIFTruncateL = *Geo::GDALc::VSIFTruncateL;
 *VSIFWriteL = *Geo::GDALc::VSIFWriteL;
+*VSIFReadL = *Geo::GDALc::VSIFReadL;
 *GDAL_GCP_GCPX_get = *Geo::GDALc::GDAL_GCP_GCPX_get;
 *GDAL_GCP_GCPX_set = *Geo::GDALc::GDAL_GCP_GCPX_set;
 *GDAL_GCP_GCPY_get = *Geo::GDALc::GDAL_GCP_GCPY_get;
@@ -151,47 +153,6 @@ package Geo::GDAL;
 *_OpenShared = *Geo::GDALc::_OpenShared;
 *IdentifyDriver = *Geo::GDALc::IdentifyDriver;
 
-############# Class : Geo::GDAL::SavedEnv ##############
-
-package Geo::GDAL::SavedEnv;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GDAL );
-%OWNER = ();
-%ITERATORS = ();
-*swig_fct_get = *Geo::GDALc::SavedEnv_fct_get;
-*swig_fct_set = *Geo::GDALc::SavedEnv_fct_set;
-*swig_data_get = *Geo::GDALc::SavedEnv_data_get;
-*swig_data_set = *Geo::GDALc::SavedEnv_data_set;
-sub new {
-    my $pkg = shift;
-    my $self = Geo::GDALc::new_SavedEnv(@_);
-    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::GDALc::delete_SavedEnv($self);
-        delete $OWNER{$self};
-    }
-}
-
-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::GDAL::MajorObject ##############
 
 package Geo::GDAL::MajorObject;
@@ -458,6 +419,8 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 *GetDefaultHistogram = *Geo::GDALc::Band_GetDefaultHistogram;
 *SetDefaultHistogram = *Geo::GDALc::Band_SetDefaultHistogram;
 *HasArbitraryOverviews = *Geo::GDALc::Band_HasArbitraryOverviews;
+*GetCategoryNames = *Geo::GDALc::Band_GetCategoryNames;
+*SetCategoryNames = *Geo::GDALc::Band_SetCategoryNames;
 *ContourGenerate = *Geo::GDALc::Band_ContourGenerate;
 sub DISOWN {
     my $self = shift;
@@ -632,8 +595,12 @@ package Geo::GDAL;
     use Geo::GDAL::Const;
     use Geo::OGR;
     use Geo::OSR;
-    our $VERSION = '0.23';
-    our $GDAL_VERSION = '1.8.1';
+    # The three first numbers of the module version and the library
+    # version should match. GDAL version is available in runtime but
+    # it is needed here for the build time when it is compared against
+    # the version of GDAL against which we build.
+    our $VERSION = '1.90';
+    our $GDAL_VERSION = '1.9.0';
     use vars qw/
 	%TYPE_STRING2INT %TYPE_INT2STRING
 	%ACCESS_STRING2INT %ACCESS_INT2STRING
@@ -959,10 +926,12 @@ package Geo::GDAL;
     use UNIVERSAL qw(isa);
     use strict;
     use vars qw/
+        @COLOR_INTERPRETATIONS
 	%COLOR_INTERPRETATION_STRING2INT %COLOR_INTERPRETATION_INT2STRING @DOMAINS
 	/;
-    for my $string (qw/Undefined GrayIndex PaletteIndex RedBand GreenBand BlueBand AlphaBand 
-		    HueBand SaturationBand LightnessBand CyanBand MagentaBand YellowBand BlackBand/) {
+    @COLOR_INTERPRETATIONS = qw/Undefined GrayIndex PaletteIndex RedBand GreenBand BlueBand AlphaBand 
+		    HueBand SaturationBand LightnessBand CyanBand MagentaBand YellowBand BlackBand/;
+    for my $string (@COLOR_INTERPRETATIONS) {
 	my $int = eval "\$Geo::GDAL::Constc::GCI_$string";
 	$COLOR_INTERPRETATION_STRING2INT{$string} = $int;
 	$COLOR_INTERPRETATION_INT2STRING{$int} = $string;
@@ -1003,6 +972,17 @@ package Geo::GDAL;
 	SetNoDataValue($self, $_[0]) if @_ > 0;
 	GetNoDataValue($self);
     }
+    sub Unit {
+	my $self = shift;
+	SetUnitType($self, $_[0]) if @_ > 0;
+	GetUnitType($self);
+    }
+    sub ScaleAndOffset {
+	my $self = shift;
+	SetScale($self, $_[0]) if @_ > 0;
+	SetOffset($self, $_[1]) if @_ > 1;
+	(GetScale($self), GetOffset($self));
+    }
     sub ReadTile {
 	my($self, $xoff, $yoff, $xsize, $ysize) = @_;
 	$xoff = 0 unless defined $xoff;
@@ -1085,10 +1065,9 @@ package Geo::GDAL;
 	    $params{$_} = $defaults{$_} unless defined $params{$_};
 	}
 	$params{ProgressData} = 1 if $params{Progress} and not defined $params{ProgressData};
-	my $h = _GetHistogram($self, $params{Min}, $params{Max}, $params{Buckets},
-			      $params{IncludeOutOfRange}, $params{ApproxOK},
-			      $params{Progress}, $params{ProgressData});
-	return @$h if $h;
+	_GetHistogram($self, $params{Min}, $params{Max}, $params{Buckets},
+		      $params{IncludeOutOfRange}, $params{ApproxOK},
+		      $params{Progress}, $params{ProgressData});
     }
     sub Contours {
 	my $self = shift;
@@ -1140,6 +1119,7 @@ package Geo::GDAL;
       $_[6] = undef unless defined $_[6];
       Geo::GDAL::FillNodata(@_);
     }
+    *GetBandNumber = *GetBand;
 
     package Geo::GDAL::ColorTable;
     use strict;
@@ -1255,5 +1235,12 @@ package Geo::GDAL;
 	return unless defined wantarray;
 	GetValueAsString($self, $row, $column);
     }
+    sub LinearBinning {
+	my $self = shift;
+	SetLinearBinning($self, @_) if @_ > 0;
+	return unless defined wantarray;
+	my @a = GetLinearBinning($self);
+	return $a[0] ? ($a[1], $a[2]) : ();
+    }
 
  1;
diff --git a/swig/perl/lib/Geo/GDAL/Const.pm b/swig/perl/lib/Geo/GDAL/Const.pm
index ea2c695..9beea2e 100644
--- a/swig/perl/lib/Geo/GDAL/Const.pm
+++ b/swig/perl/lib/Geo/GDAL/Const.pm
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.39
+# Version 1.3.40
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
diff --git a/swig/perl/lib/Geo/OGR.dox b/swig/perl/lib/Geo/OGR.dox
index 197194b..88dc9d7 100644
--- a/swig/perl/lib/Geo/OGR.dox
+++ b/swig/perl/lib/Geo/OGR.dox
@@ -10,26 +10,27 @@
 ## @ignore STORE
 ## @ignore this
 
-## @ignore UseExceptions()
+## @ignore BuildPolygonFromEdges
+## @ignore ForceToMultiLineString
+## @ignore ForceToMultiPoint
+## @ignore ForceToMultiPolygon
+## @ignore ForceToPolygon
+
+## @ignore GeneralCmdLineProcessor
+## @ignore GeometryTypeToName
+## @ignore GetFieldTypeName
 
+## @ignore UseExceptions()
 ## @ignore DontUseExceptions()
 
 ## @fn @GeometryTypes()
 # @return a list of all geometry types.
 
-## @fn Geo::OGR::Geometry CreateGeometryFromWkb($WKB, $srs = undef)
-# @param WKB Buffer containing well known binary.
-# @param srs A Geo::OSR::SpatialReference object.
-# @return a new Geo::OGR::Geometry object.
-
-## @fn Geo::OGR::Geometry CreateGeometryFromWkt($WKT, $srs = undef)
-# @param WKT String containing well known text.
-# @param srs A Geo::OSR::SpatialReference object.
-# @return a new Geo::OGR::Geometry object.
-
-## @fn Geo::OGR::Geometry CreateGeometryFromGML($GML)
-# @param GML String containing GML.
-# @return a new Geo::OGR::Geometry object.
+## @ignore CreateGeometryFromWkb
+## @ignore CreateGeometryFromWkt
+## @ignore CreateGeometryFromGML
+## @ignore CreateGeometryFromJson
+## @ignore ApproximateArcAngles
 
 ## @fn @Drivers()
 # @return a list of Geo::OGR::Driver objects, one for each OGR format.
@@ -66,163 +67,75 @@
 
 ## @fn Geo::OGR::Driver Driver($driver) 
 # Create a driver object for the internal OGR driver.
-# @note aka GetDriver
+# @note a.k.a. GetDriver
 # @param driver the index or the name of the driver
 # @return a new Geo::OGR::Driver object
 
-## @attr wkb25Bit
-# @deprecated
-
-## @attr wkbUnknown
-# @deprecated
-
-## @attr wkbPoint
-# @deprecated use string 'Point' instead
-
-## @attr wkbLineString
-# @deprecated use string 'LineString' instead
-
-## @attr wkbPolygon
-# @deprecated use string 'Polygon' instead
-
-## @attr wkbMultiPoint
-# @deprecated use string 'MultiPoint' instead
-
-## @attr wkbMultiLineString
-# @deprecated use string 'MultiLineString' instead
-
-## @attr wkbMultiPolygon
-# @deprecated use string 'MultiPolygon' instead
-
-## @attr wkbGeometryCollection
-# @deprecated use string 'GeometryCollection' instead
-
-## @attr wkbNone
-# @deprecated
-
-## @attr wkbLinearRing
-# @deprecated use string 'LinearRing' instead
-
-## @attr wkbPoint25D
-# @deprecated use string 'Point25D' instead
-
-## @attr wkbLineString25D
-# @deprecated use string 'LineString25D' instead
-
-## @attr wkbPolygon25D
-# @deprecated use string 'Polygon25D' instead
-
-## @attr wkbMultiPoint25D
-# @deprecated use string 'MultiPoint25D' instead
-
-## @attr wkbMultiLineString25D
-# @deprecated use string 'MultiLineString25D' instead
-
-## @attr wkbMultiPolygon25D
-# @deprecated use string 'MultiPolygon25D' instead
-
-## @attr wkbGeometryCollection25D
-# @deprecated use string 'GeometryCollection25D' instead
-
-## @attr OFTInteger
-# @deprecated use string 'Integer' instead
-
-## @attr OFTIntegerList
-# @deprecated use string 'IntegerList' instead
-
-## @attr OFTReal
-# @deprecated use string 'Real' instead
-
-## @attr OFTRealList
-# @deprecated use string 'RealList' instead
-
-## @attr OFTString
-# @deprecated use string 'String' instead
-
-## @attr OFTStringList
-# @deprecated use string 'StringList' instead
-
-## @attr OFTWideString
-# @deprecated use string 'WideString' instead
-
-## @attr OFTWideStringList
-# @deprecated use string 'WideStringList' instead
-
-## @attr OFTBinary
-# @deprecated use string 'Binary' instead
-
-## @attr OFTDate
-# @deprecated use string 'Date' instead
-
-## @attr OFTTime
-# @deprecated use string 'Time' instead
-
-## @attr OFTDateTime
-# @deprecated use string 'DateTime' instead
-
-## @attr OJUndefined
-# @deprecated use string 'Undefined' instead
-
-## @attr OJLeft
-# @deprecated use string 'Left' instead
-
-## @attr OJRight
-# @deprecated use string 'Right' instead
-
-## @attr wkbXDR
-# @deprecated use string 'XDR' instead
-
-## @attr wkbNDR
-# @deprecated use string 'NDR' instead
-
-## @attr OLCRandomRead
-# @deprecated use string 'RandomRead' instead
-
-## @attr OLCSequentialWrite
-# @deprecated use string 'SequentialWrite' instead
-
-## @attr OLCRandomWrite
-# @deprecated use string 'RandomWrite' instead
-
-## @attr OLCFastSpatialFilter
-# @deprecated use string 'FastSpatialFilter' instead
-
-## @attr OLCFastFeatureCount
-# @deprecated use string 'FastFeatureCount' instead
-
-## @attr OLCFastGetExtent
-# @deprecated use string 'FastGetExtent' instead
-
-## @attr OLCCreateField
-# @deprecated use string 'CreateField' instead
-
-## @attr OLCTransactions
-# @deprecated use string 'Transactions' instead
-
-## @attr OLCDeleteFeature
-# @deprecated use string 'DeleteFeature' instead
-
-## @attr OLCFastSetNextByIndex
-# @deprecated use string 'FastSetNextByIndex' instead
-
-## @attr ODsCCreateLayer
-# @deprecated use string 'CreateLayer' instead
-
-## @attr ODsCDeleteLayer
-# @deprecated use string 'DeleteLayer' instead
-
-## @attr ODrCCreateDataSource
-# @deprecated use string 'CreateDataSource' instead
-
-## @attr ODrCDeleteDataSource
-# @deprecated use string 'DeleteDataSource' instead
-
+## @ignore NullFID
+## @ignore wkb25Bit
+## @ignore wkb25DBit
+## @ignore wkbUnknown
+## @ignore wkbPoint
+## @ignore wkbLineString
+## @ignore wkbPolygon
+## @ignore wkbMultiPoint
+## @ignore wkbMultiLineString
+## @ignore wkbMultiPolygon
+## @ignore wkbGeometryCollection
+## @ignore wkbNone
+## @ignore wkbLinearRing
+## @ignore wkbPoint25D
+## @ignore wkbLineString25D
+## @ignore wkbPolygon25D
+## @ignore wkbMultiPoint25D
+## @ignore wkbMultiLineString25D
+## @ignore wkbMultiPolygon25D
+## @ignore wkbGeometryCollection25D
+## @ignore OFTInteger
+## @ignore OFTIntegerList
+## @ignore OFTReal
+## @ignore OFTRealList
+## @ignore OFTString
+## @ignore OFTStringList
+## @ignore OFTWideString
+## @ignore OFTWideStringList
+## @ignore OFTBinary
+## @ignore OFTDate
+## @ignore OFTTime
+## @ignore OFTDateTime
+## @ignore OJUndefined
+## @ignore OJLeft
+## @ignore OJRight
+## @ignore wkbXDR
+## @ignore wkbNDR
+## @ignore OLCRandomRead
+## @ignore OLCSequentialWrite
+## @ignore OLCRandomWrite
+## @ignore OLCFastSpatialFilter
+## @ignore OLCFastFeatureCount
+## @ignore OLCFastGetExtent
+## @ignore OLCCreateField
+## @ignore OLCTransactions
+## @ignore OLCDeleteFeature
+## @ignore OLCFastSetNextByIndex
+## @ignore OLCAlterFieldDefn
+## @ignore OLCDeleteField
+## @ignore OLCIgnoreFields
+## @ignore OLCReorderFields
+## @ignore OLCStringsAsUTF8
+## @ignore ODsCCreateLayer
+## @ignore ODsCDeleteLayer
+## @ignore ODrCCreateDataSource
+## @ignore ODrCDeleteDataSource
 
 ## @class Geo::OGR::Driver
 # @isa (Geo::OGR)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
+## @attr list CAPABILITIES
+# Driver capabilities known to GDAL
+
+## @ignore Register
+## @ignore Deregister
 
 ## @attr name
 # scalar (access as $driver->{name})
@@ -241,9 +154,11 @@
 # @param cap A capability string.
 # @return boolean value.
 
+## @ignore CreateDataSource
+
 ## @method Geo::OGR::DataSource Create($name, \%options = undef )
 # Create an OGR data source object.
-# \note aka CreateDataSource
+# \note a.k.a. CreateDataSource
 # @param name The data source name.
 # @param options Driver specific options.
 #
@@ -253,9 +168,11 @@
 # \endcode
 # @return a new Geo::OGR::DataSource object.
 
+## @ignore CopyDataSource
+
 ## @method Geo::OGR::DataSource Copy($ds, $name, \@options = undef)
 # Copy an OGR data source object.
-# \note CopyDataSource
+# \note a.k.a. CopyDataSource
 # @param ds The Geo::OGR::DataSource object to be copied.
 # @param name The name for the new data source.
 # @param options Driver specific options.
@@ -267,9 +184,11 @@
 # @param update Whether to open the data source in update mode.
 # @return a new Geo::OGR::DataSource object
 
+## @ignore DeleteDataSource
+
 ## @method Delete($name)
 # Delete an OGR data source.
-# \note aka DeleteDataSource
+# \note a.k.a. DeleteDataSource
 # @param name The name of data source.
 
 ## @method $GetName()
@@ -279,9 +198,10 @@
 ## @class Geo::OGR::DataSource
 # @isa (Geo::OGR)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
+## @attr list CAPABILITIES
+# Data source capabilities known to GDAL
+
+## @ignore SyncToDisk
 
 ## @attr name
 # string (access as $datasource->{name})
@@ -330,12 +250,12 @@
 
 ## @method Geo::OGR::Layer CreateLayer($Name, $SRS = undef, $GeometryType = 'Unknown', \%Options = undef, \%Schema = undef)
 # \note This method can also be used with named parameters: $ds->CreateLayer({parameter=>value, ...}).
-# @param Name A name for the new layer.
+# @param Name name for the new layer.
 # @param SRS a Geo::OSR::SpatialReference object.
-# @param GeometryType One of geometry types (a string: Point, LineString, or some else)
+# @param GeometryType one of \@Geo::OGR::Geometry::GEOMETRY_TYPES
 # @param Options A ref to a hash of format specific options.
-# @param Schema Forwarded to Layer::Schema, which is called if this parameter exists.
-# @return a new Geo::OGR::Layer object.
+# @param Schema forwarded to Layer::Schema, which is called if this parameter exists
+# @return a new Geo::OGR::Layer object
 
 ## @method Geo::OGR::Layer CopyLayer($layer, $name, \%options = undef)
 # @param layer A Geo::OGR::Layer object to be copied.
@@ -372,18 +292,16 @@
 # @param name A string.
 # @return a new Geo::OGR::Layer object.
 
-## @ignore $GetRefCount()
-# @return integer
+## @ignore GetRefCount
 
-## @ignore $GetSummaryRefCount()
-# @return integer
+## @ignore GetSummaryRefCount
 
 
 ## @class Geo::OGR::Layer
 # @isa (Geo::OGR)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
+## @attr list CAPABILITIES
+# Layer capabilities known to GDAL
 
 ## @cmethod @Capabilities()
 # @return a list of capabilities. The class method returns a list of
@@ -504,7 +422,14 @@
 # @param force
 # @return integer
 
-## @method \@GetExtent($force = 1)
+## @method @GetExtent($force = 1)
+# @param force compute the extent even if it is expensive
+# @note In scalar context returns a reference to an anonymous array
+# containing the extent.
+# @note The order of values is different from those returned by
+# Geo::OGR::Geometry::GetEnvelope.
+# @return the extent ($minx, $miny, $maxx, $maxy)
+
 # @param force
 # @return the extent = ($minx, $miny, $maxx, $maxy) as a listref
 
@@ -521,21 +446,50 @@
 ## @method Geo::OSR::SpatialReference GetSpatialRef()
 # @return a new Geo::OSR::SpatialReference object
 
-## @method $GetRefCount()
-# @return integer
+## @ignore GetRefCount
+
+## @method AlterFieldDefn($field, $definition, $flags)
+# Alter the definition of an existing field on a layer.
+# @param field index of the field whose definition is altered
+# @param definition a Geo::OGR::FieldDefn object
+# @param flags 1 to alter the name, 2 to alter the type, 4 to alter
+# the width, use combinations 3, 5, 6 or 7 to alter two or more
+# properties
+# @todo Perlify: support field names and string flags
+
+## @method DeleteField($field)
+# Delete an existing field from a layer.
+# @param field index of the field which is deleted
+
+## @method $GetFIDColumn()
+# @return the name of the underlying database column being used as the FID column, or "" if not supported.
+
+## @method $GetGeometryColumn()
+# @return the name of the underlying database column being used as the geometry column, or "" if not supported
+
+## @ignore GetGeomType
+
+## @method $GeometryType()
+# @return the geometry type of the layer, one of \@Geo::OGR::Geometry::GEOMETRY_TYPES
+
+## @ignore ReorderField
+## @ignore ReorderFields
+
+## @method SetIgnoredFields(@fields)
+# @param fields a list of field names
 
 
 ## @class Geo::OGR::Feature
 # @isa (Geo::OGR)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-
 ## @cmethod Geo::OGR::Feature new($feature_def)
 # @param feature_def a Geo::OGR::FeatureDefn object
 # @return a new Geo::OGR::Feature object
 
+## @cmethod Geo::OGR::Feature create(%schema)
+# @param schema as in Schema
+# @return a new Geo::OGR::Feature object
+
 ## @method \%Schema(%schema)
 # Get or set the schema. The schema is a hash (Name => name,
 # GeometryType => geometry_type, Fields => [list of
@@ -572,23 +526,38 @@
 ## @method Geo::OGR::FeatureDefn GetDefnRef()
 # @return a new Geo::OGR::FeatureDefn object
 
-## @method $Geometry($geometry)
-# Get a copy of the geometry or copy the geometry into the feature.
-# @param geometry [optional]
+## @method Geo::OGR::FieldDefn GetFieldDefnRef($param)
+# @param param the index (0..count-1) or the name of the field
+# @return a new Geo::OGR::FieldDefn object
 
-## @method SetGeometry($geometry)
-# The geometry is copied into the feature.
-# @param geometry a Geo::OGR::Geometry object
+## @method $GetFieldType($field)
+# @param field the index (0..count-1) or the name of the field
+# @return one of field types
 
-## @method SetGeometryDirectly($geometry)
-# This feature is not destroyed while the Geo::OGR::Geometry object exists.
-# @param geometry a Geo::OGR::Geometry object
+## @ignore SetGeometry
 
-## @method Geo::OGR::Geometry GetGeometry()
-# Creates a new Geo::OGR::Geometry object, whose data is owned by the
-# feature. The underlying OGR feature is not destroyed while the
-# geometry object exists.
-# @return a new Geo::OGR::Geometry object
+## @method $Geometry($geometry)
+# Get a copy of the geometry as a new Geo::OGR::Geometry object and/or
+# copy the geometry into the feature.
+# @note a.k.a. SetGeometry (only copy into)
+# @param geometry [optional] a Geo::OGR::Geometry object
+# @return a new Geo::OGR::Geometry object in a non-void context
+
+## @ignore SetGeometryDirectly
+## @ignore GetGeometry
+## @ignore GetGeometryRef
+
+## @method $ReferenceGeometry($geometry)
+# Create a new Geo::OGR::Geometry object, which references the
+# geometry within the feature and/or create a reference to the
+# argument geometry within the feature. This method maintains a link
+# between the two objects and will not let the feature object be
+# destroyed while the geometry object exists. Use with caution.
+# @note a.k.a. SetGeometryDirectly (only reference in), GetGeometry
+# (only create with a reference), GetGeometryRef (only create with a
+# reference and do not create the link between the objects).
+# @param geometry [optional] a Geo::OGR::Geometry object
+# @return a new Geo::OGR::Geometry object in a non-void context
 
 ## @method Geo::OGR::Feature Clone()
 # @return a new Geo::OGR::Feature object
@@ -597,29 +566,65 @@
 # @param feature a Geo::OGR::Feature object for comparison
 # @return boolean
 
+## @method $GetFieldIndex($name)
+# @param name the name of the field
+# @return integer the index of the field (0..Count-1)
+
 ## @method $GetFieldCount()
 # @return an integer
 
-## @method Geo::OGR::FieldDefn GetFieldDefnRef($param)
-# @param param the index or the name of the field
-# @return a new Geo::OGR::FieldDefn object
+## @ignore GetFieldAsString
+## @ignore GetFieldAsInteger
+## @ignore GetFieldAsDouble
+## @ignore GetFieldAsDateTime
+## @ignore GetFieldAsDoubleList
+## @ignore GetFieldAsIntegerList
+## @ignore GetFieldAsStringList
 
 ## @method @GetField($field)
-# @param field the index or the name of the field
+# @note A number of GetFieldAs* methods exist but they are not
+# documented. Syntax $feature->{field} can be used to access the
+# field (v1.9.0)
+# @param field the index (0..Count-1) or the name of the field
 # @return the value of the field, which may be a scalar or a list,
 # depending on the field type.
 
+## @ignore SetFieldDoubleList
+## @ignore SetFieldIntegerList
+## @ignore SetFieldStringList
+
+## @method SetField($field, @value)
+# @note Syntax $feature->{field} can be used to access the
+# field (v1.9.0)
+# @param field the index (0..Count-1) or the name of the field
+# @param value is a string, integer, double, a list (year, month,
+# day), a list (hour, minute, second, tzflag), a list (year, month,
+# day, hour, minute, second, tzflag), or a list of integers, doubles,
+# or strings.
+# @note If value is not given or is undefined this method unsets the field.
+
+## @ignore SetFromWithMap
+
+## @method SetFrom($other, $forgiving = 1, \%map)
+# @param other a Geo::OGR::Feature object
+# @param forgiving [optional] set to false if the operation should not
+# continue if output fields do not match some of the source fields
+# @param map [optional] a mapping from output field indexes to source
+# fields, include into the hash all field indexes of this feature
+# which should be set
+
 ## @method $IsFieldSet($field)
-# @param field the index or the name of the field
+# @param field the index (0..Count-1) or the name of the field
 # @return boolean
 
-## @method $GetFieldIndex($name)
-# @param name the name of the field
-# @return integer the index of the field
+## @method UnsetField($field)
+# @note Field value can be unset by calling SetField without
+# parameters or with an undefined argument.
+# @param field the index (0..Count-1) or the name of the field
 
 ## @method $FID($fid)
-# @param fid [optional]
-# @return integer the feature id
+# @param fid [optional] the id to set for this feature
+# @return integer the id of this feature
 
 ## @method $GetFID()
 # @return integer the feature id
@@ -629,20 +634,6 @@
 
 ## @method DumpReadable()
 
-## @method UnsetField($field)
-# @param field the index or the name of the field
-
-## @method SetField($field, @value)
-# @param field the index or the name of the field
-# @param value is a string, integer, double, a list (year, month,
-# day), a list (hour, minute, second, tzflag), a list (year, month,
-# day, hour, minute, second, tzflag), or a list of integers, doubles,
-# or strings.
-
-## @method SetFrom($other, $forgiving = 1)
-# @param other a Geo::OGR::Feature object
-# @param forgiving
-
 ## @method $StyleString($string)
 # @param string [optional]
 # @return
@@ -653,34 +644,10 @@
 ## @method SetStyleString($string)
 # @param string
 
-## @method $GetFieldType($field)
-# @param field the index or the name of the field
-# @return one of field types
-
-## @method $GetFieldAsString($field)
-# @deprecated use Geo::OGR::Feature::GetField
-
-## @method $GetFieldAsInteger($field)
-# @deprecated use Geo::OGR::Feature::GetField
-
-## @method $GetFieldAsDouble($field)
-# @deprecated use Geo::OGR::Feature::GetField
-
-## @method Geo::OGR::Geometry GetGeometryRef()
-# Creates a new Geo::OGR::Geometry object, whose data is still owned
-# by the feature. This link is not recorded.
-# @deprecated use Geo::OGR::Feature::GetGeometry unless you know what
-# you are doing.
-# @return a new Geo::OGR::Geometry object
-
 
 ## @class Geo::OGR::FeatureDefn
 # @isa (Geo::OGR)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-
 ## @cmethod Geo::OGR::FeatureDefn new($name = undef)
 # @param name
 # @return a Geo::OGR::FeatureDefn object
@@ -688,8 +655,10 @@
 ## @cmethod Geo::OGR::FeatureDefn create(%schema)
 # Example usage:
 # \code
-# $fd = Geo::OGR::FeatureDefn->create( Name => "name", GeometryType =>
-# "Polygon", Fields => [{Name => 'field1', Type => 'String'}] );
+# $fd = Geo::OGR::FeatureDefn->create( 
+#     Name => "name", 
+#     GeometryType => "Polygon",
+#     Fields => [{ Name => 'field1', Type => 'String' }] );
 # \endcode
 # @param schema The schema for the new feature definition, as in
 # Geo::OGR::FeatureDefn::Schema.
@@ -708,6 +677,7 @@
 # @return
 
 ## @method $GetName()
+# @note a.k.a. Name
 # @return a string
 
 ## @method $GetFieldCount()
@@ -724,29 +694,47 @@
 ## @method AddFieldDefn($defn)
 # @param defn a Geo::OGR::FieldDefn object
 
+## @ignore GetGeomType
+## @ignore SetGeomType
+
 ## @method $GeometryType($geometry_type)
-# Get or set the geometry type. Alternative name: GeomType.
-# @param geometry_type [optional] one of geometry types
-# @return the geometry types
+# Get or set the geometry type.
+# @note a.k.a. GeomType, GetGeomType (deprecated, returns an integer),
+# SetGeomType (deprecated, requires an integer)
+# @param geometry_type [optional] one of \@Geo::OGR::Geometry::GEOMETRY_TYPES
+# @return the geometry type, one of \@Geo::OGR::Geometry::GEOMETRY_TYPES
 
-## @method $GetGeomType()
-# @deprecated use Geo::OGR::FeatureDefn::GeometryType, which returns a string
-# @return geometry type as integer
+## @ignore GetReferenceCount
 
-## @method SetGeomType($type)
-# @deprecated use Geo::OGR::FeatureDefn::GeomType, which accepts a string
-# @param type as integer
+## @ignore IsGeometryIgnored
+## @ignore SetGeometryIgnored
 
-## @method $GetReferenceCount()
-# @return integer
+## @method $GeometryIgnored($IgnoreState)
+# @note a.k.a. GetGeometryIgnored (only get), SetGeometryIgnored (only set)
+# Get or set the ignore status of geometry when fetching features.
+# @return the ignore status of geometry
+# @since 1.9.0
+
+## @ignore IsStyleIgnored
+## @ignore SetStyleIgnored
+
+## @method $StyleIgnored($IgnoreState)
+# @note a.k.a. GetStyleIgnored (only get), SetStyleIgnored (only set)
+# Get or set the ignore status of style information when fetching features.
+# @return the ignore status of style information
+# @since 1.9.0
 
 
 ## @class Geo::OGR::FieldDefn
 # @isa (Geo::OGR)
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
+## @attr list FIELD_TYPES
+# Field types supported by GDAL, one of: Integer IntegerList Real
+# RealList String StringList WideString WideStringList Binary Date
+# Time DateTime
+
+## @attr list JUSTIFY_TYPES
+# Justify types supported by GDAL, one of: Undefined Left Right
 
 ## @cmethod Geo::OGR::FieldDefn new($name = "unnamed", $field_type = $Geo::OGR::OFTString)
 # @deprecated use Geo::OGR::FieldDefn::create, which accepts type as a string
@@ -781,80 +769,79 @@
 # @return a reference to a hash whose keys are Name, Type, Justify,
 # Width, and Precision
 
+## @ignore GetName
+## @ignore GetNameRef
+## @ignore SetName
+
 ## @method $Name($name)
-# Get and/or set the name
+# Get and/or set the name of the field.
+# @note a.k.a. GetName, GetNameRef, SetName
 # @param name [optional]
 # @return the name in non-void context
 
+## @ignore GetFieldTypeName
+## @ignore GetTypeName
+## @ignore GetType
+## @ignore SetType
+
 ## @method $Type($type)
+# @note a.k.a. GetFieldTypeName, GetTypeName, GetType, SetType
 # @param type [optional] one of field types: Integer, IntegerList, Real,
 # RealList, String, StringList, WideString, WideStringList, Binary, Date,
-# Time, or DateTime (wide strings are not really supported yet)
+# Time, or DateTime (wide strings are not really supported yet?)
 # @return one of field types in non-void context
 
+## @ignore GetJustify
+## @ignore SetJustify
+
 ## @method $Justify($justify)
-# Get and/or set the justification
+# Get and/or set the justification of this field.
+# @note a.k.a. GetJustify, SetJustify
 # @param justify [optional] as string: Undefined, Left, or Right
 # @return one of Undefined Left Right in non-void context
 
+## @ignore GetWidth
+## @ignore SetWidth
+
 ## @method $Width($width)
-# Get and/or set the field width
+# Get and/or set the field width.
+# @note a.k.a. GetWidth, SetWidth
 # @param width [optional]
 # @return integer in non-void context
 
+## @ignore GetPrecision
+## @ignore SetPrecision
+
 ## @method $Precision($precision)
-# Get and/or set the precision
+# Get and/or set the precision of this field.
+# @note a.k.a. GetPrecision, SetPrecision
 # @param precision [optional]
 # @return integer in non-void context
 
-## @method $GetName()
-# @return
-
-## @method $GetNameRef()
-# Same as GetName.
-# @return
-
-## @method SetName($name)
-# @param name
-
-## @method $GetPrecision()
-# @return
-
-## @method SetPrecision($precision)
-# @param precision
-
-## @method $GetWidth()
-# return
-
-## @method SetWidth($width)
-# @param width
-
-## @method $GetFieldTypeName()
-# @deprecated use string type names
-
-## @method $GetType()
-# @deprecated use Geo::OGR::FieldDefn::Type, which returns a string
-# @return type as integer
-
-## @method SetType($type)
-# @deprecated use Geo::OGR::FieldDefn::Type, which accepts a string
-# @param type
-
-## @method $GetJustify()
-# @deprecated use Geo::OGR::FieldDefn::Justify, which returns a string
-# @return justify as an integer
-
-## @method SetJustify($justify)
-# @deprecated use Geo::OGR::FieldDefn::Justify, which accepts a string
-# @param justify as an integer
+## @ignore IsIgnored
+## @ignore SetIgnored
 
+## @method $Ignored($ignore)
+# Get and/or set the ignore status (whether this field should be
+# omitted when fetching features) of this field.
+# @note a.k.a. IsIgnored, SetIgnored
+# @param ignore [optional]
+# @return the ignore status in non-void context
+# @since 1.9.0
 
 ## @class Geo::OGR::Geometry
 # @isa (Geo::OGR)
+# @note Most spatial analysis methods require <a
+# href="http://geos.osgeo.org/doxygen/">GEOS</a> to work rigorously.
+
+## @attr list GEOMETRY_TYPES
+# Geometry types supported by GDAL, one of: Unknown Point LineString
+# Polygon MultiPoint MultiLineString MultiPolygon GeometryCollection
+# None LinearRingPoint25D LineString25D Polygon25D MultiPoint25D
+# MultiLineString25D MultiPolygon25D GeometryCollection25D
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
+## @attr list BYTE_ORDER_TYPES
+# Byte order strings, one of: XDR NDR
 
 ## @cmethod Geo::OGR::Geometry new($type = $Geo::OGR::wkbUnknown, $WKT = undef, $WKB = undef, $GML = undef)
 # @deprecated use Geo::OGR::Geometry::create, which accepts type as a string
@@ -881,6 +868,8 @@
 #    PrimaryRadius, SecondaryRadius, Rotation, StartAngle, EndAngle,
 #    MaxAngleStepSizeDegrees]
 #
+# @note uses CreateGeometryFrom* functions from Geo::OGR
+#
 # Usage:
 # \code
 # $g = Geo::OGR::Geometry->create(...arguments...);
@@ -902,23 +891,40 @@
 ## @method $GetDimension()
 # @return 0, 1, or 2
 
+## @ignore ExportToWkt
+
 ## @method $AsText()
-# This geometric object in Well-known text. Alternative name: ExportToWkt.
+# This geometric object in Well Known Text.
+# @note a.k.a. ExportToWkt
 # @return a WKT string
 
 ## @method $AsBinary($byte_order = 'XDR')
-# This geometric object as a Well-known binary string. Alternative name: ExportToWkb.
+# This geometric object as a Well-known binary string.
+# @note a.k.a. ExportToWkb
 # @param byte_order XDR or NDR
 # @return a WKB binary string
 
-## @method $ExportToGML()
-# This geometric object as a GML string. Alternative name: AsGML.
+## @ignore ExportToGML
+
+## @method $AsGML()
+# This geometric object as a GML string.
+# @note a.k.a. ExportToGML
 # @return a GML string
 
-## @method $ExportToKML()
-# This geometric object as a KML string. Alternative name: AsKML.
+## @ignore ExportToKML
+
+## @method $AsKML()
+# This geometric object as a KML string.
+# @note a.k.a. ExportToKML
 # @return KML string
 
+## @ignore ExportToJson
+
+## @method $AsJSON()
+# This geometric object as a JSON string.
+# @note a.k.a. ExportToJson
+# @return JSON string
+
 ## @method AddPoint($x, $y, $z)
 # Set the data of a point or add a point to a line string. Consider
 # using Geo::OGR::Geometry::Points.  Note that the coordinate
@@ -1042,8 +1048,14 @@
 ## @method $GeometryType()
 # @return the geometry type
 
-## @method $GetArea()
-# @return a number
+## @method $Length()
+# @return the length of the linestring
+
+## @ignore GetArea
+
+## @method $Area()
+# @note a.k.a. GetArea
+# @return the area of the polygon or multipolygon
 
 ## @method $GetGeometryCount()
 # @return an integer
@@ -1053,9 +1065,6 @@
 # @return a new Geo::OGR::Geometry object whose data is a part of the
 # parent geometry
 
-## @method Geo::OGR::Geometry GetBoundary()
-# @return a new Geo::OGR::Geometry object
-
 ## @method Geo::OGR::Geometry ConvexHull()
 # @return a new Geo::OGR::Geometry object
 
@@ -1098,7 +1107,7 @@
 
 ## @method Geo::OGR::Geometry ForceToCollection(@geometries)
 # Create a geometrycollection from the geometry.
-# @param polygons [optional] More geometries to add to the collection.
+# @param geometries [optional] More geometries to add to the collection.
 # @return a new Geo::OGR::Geometry object of type geometrycollection.
 
 ## @method Geo::OGR::Geometry Buffer($distance, $quadsecs = 30)
@@ -1114,49 +1123,80 @@
 # @param other a Geo::OGR::Geometry object
 # @return a new Geo::OGR::Geometry object
 
+## @method Geo::OGR::Geometry UnionCascaded()
+# @return a new Geo::OGR::Geometry object
+# @since 1.8.0
+
 ## @method Geo::OGR::Geometry Difference($other)
 # @param other a Geo::OGR::Geometry object
 # @return a new Geo::OGR::Geometry object
 
-## @method Geo::OGR::Geometry SymmetricDifference($other)
+## @ignore SymmetricDifference
+
+## @method Geo::OGR::Geometry SymDifference($other)
+# Compute symmetric difference. 
+# @note a.k.a. SymmetricDifference
 # @param other a Geo::OGR::Geometry object
 # @return a new Geo::OGR::Geometry object
+# @since 1.8.0
+
+## @ignore GetBoundary
+
+## @method Geo::OGR::Geometry Boundary()
+# @note a.k.a. GetBoundary
+# @return the boundary of this geometry as a geometry
+# @since 1.8.0
 
 ## @method $Distance($other)
 # @param other a Geo::OGR::Geometry object
-# @return
+# @return the distance to the other geometry
 
-## @method $Intersect($other)
+## @ignore Intersect
+
+## @method $Intersects($other)
+# @note a.k.a. Intersect (deprecated)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry intersects with the other geometry, false otherwise
 
-## @method $Equal($other)
+## @ignore Equal
+
+## @method $Equals($other)
+# @note a.k.a. Equal (deprecated)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry is equivalent to the other geometry, false otherwise
 
 ## @method $Disjoint($other)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry is disjoint from the other geometry, false otherwise
 
 ## @method $Touches($other)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry touches the other geometry, false otherwise
 
 ## @method $Crosses($other)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry crosses the other geometry, false otherwise
 
 ## @method $Within($other)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry is within the other geometry, false otherwise
 
 ## @method $Contains($other)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry contains the other geometry, false otherwise
 
 ## @method $Overlaps($other)
 # @param other a Geo::OGR::Geometry object
-# @return boolean
+# @return true if this geometry overlaps the other geometry, false otherwise
+
+## @method Segmentize($MaxLength)
+# Modify the geometry such it has no segment longer than the given length.
+# @param MaxLength the given length
+
+## @method Simplify($Tolerance)
+# Simplify the geometry.
+# @param Tolerance the length tolerance for the simplification
+# @since 1.8.0
 
 ## @method TransformTo($srs)
 # @param srs a Geo::OSR::SpatialReference object
@@ -1172,11 +1212,22 @@
 
 ## @method CloseRings()
 
-## @method \@GetEnvelope()
-# @return arrayref = [$minx, $maxx, $miny, $maxy]
+## @method @GetEnvelope()
+# @note In scalar context returns a reference to an anonymous array
+# containing the envelope.
+# @note The order of values is different from those returned by
+# Geo::OGR::Layer::GetExtent.
+# @return the envelope ($minx, $maxx, $miny, $maxy)
+
+## @method @GetEnvelope3D()
+# @note In scalar context returns a reference to an anonymous array
+# containing the envelope.
+# @return the 3-D envelope ($minx, $maxx, $miny, $maxy, $minz, $maxz)
+# @since 1.9.0
 
 ## @method Geo::OGR::Geometry Centroid()
 # @return a new Geo::OGR::Geometry object
+# @since 1.8.0
 
 ## @method $WkbSize()
 # @return an integer
diff --git a/swig/perl/lib/Geo/OGR.pm b/swig/perl/lib/Geo/OGR.pm
index 2355c05..138fc69 100644
--- a/swig/perl/lib/Geo/OGR.pm
+++ b/swig/perl/lib/Geo/OGR.pm
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.39
+# Version 1.3.40
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -89,7 +89,7 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 *Open = *Geo::OGRc::Driver_Open;
 *DeleteDataSource = *Geo::OGRc::Driver_DeleteDataSource;
 *_TestCapability = *Geo::OGRc::Driver__TestCapability;
-*_GetName = *Geo::OGRc::Driver__GetName;
+*GetName = *Geo::OGRc::Driver_GetName;
 *Register = *Geo::OGRc::Driver_Register;
 *Deregister = *Geo::OGRc::Driver_Deregister;
 sub DISOWN {
@@ -135,8 +135,9 @@ sub DESTROY {
 *GetSummaryRefCount = *Geo::OGRc::DataSource_GetSummaryRefCount;
 *GetLayerCount = *Geo::OGRc::DataSource_GetLayerCount;
 *_GetDriver = *Geo::OGRc::DataSource__GetDriver;
-*_GetName = *Geo::OGRc::DataSource__GetName;
+*GetName = *Geo::OGRc::DataSource_GetName;
 *_DeleteLayer = *Geo::OGRc::DataSource__DeleteLayer;
+*SyncToDisk = *Geo::OGRc::DataSource_SyncToDisk;
 *_CreateLayer = *Geo::OGRc::DataSource__CreateLayer;
 *CopyLayer = *Geo::OGRc::DataSource_CopyLayer;
 *_GetLayerByIndex = *Geo::OGRc::DataSource__GetLayerByIndex;
@@ -169,7 +170,7 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 *GetSpatialFilter = *Geo::OGRc::Layer_GetSpatialFilter;
 *SetAttributeFilter = *Geo::OGRc::Layer_SetAttributeFilter;
 *ResetReading = *Geo::OGRc::Layer_ResetReading;
-*_GetName = *Geo::OGRc::Layer__GetName;
+*GetName = *Geo::OGRc::Layer_GetName;
 *GetGeomType = *Geo::OGRc::Layer_GetGeomType;
 *GetGeometryColumn = *Geo::OGRc::Layer_GetGeometryColumn;
 *GetFIDColumn = *Geo::OGRc::Layer_GetFIDColumn;
@@ -185,6 +186,10 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 *GetExtent = *Geo::OGRc::Layer_GetExtent;
 *_TestCapability = *Geo::OGRc::Layer__TestCapability;
 *CreateField = *Geo::OGRc::Layer_CreateField;
+*DeleteField = *Geo::OGRc::Layer_DeleteField;
+*ReorderField = *Geo::OGRc::Layer_ReorderField;
+*ReorderFields = *Geo::OGRc::Layer_ReorderFields;
+*AlterFieldDefn = *Geo::OGRc::Layer_AlterFieldDefn;
 *StartTransaction = *Geo::OGRc::Layer_StartTransaction;
 *CommitTransaction = *Geo::OGRc::Layer_CommitTransaction;
 *RollbackTransaction = *Geo::OGRc::Layer_RollbackTransaction;
@@ -258,7 +263,7 @@ sub new {
 *SetFieldIntegerList = *Geo::OGRc::Feature_SetFieldIntegerList;
 *SetFieldDoubleList = *Geo::OGRc::Feature_SetFieldDoubleList;
 *SetFieldStringList = *Geo::OGRc::Feature_SetFieldStringList;
-*SetFrom = *Geo::OGRc::Feature_SetFrom;
+*_SetFrom = *Geo::OGRc::Feature__SetFrom;
 *SetFromWithMap = *Geo::OGRc::Feature_SetFromWithMap;
 *GetStyleString = *Geo::OGRc::Feature_GetStyleString;
 *SetStyleString = *Geo::OGRc::Feature_SetStyleString;
@@ -305,7 +310,7 @@ sub new {
     bless $self, $pkg if defined($self);
 }
 
-*_GetName = *Geo::OGRc::FeatureDefn__GetName;
+*GetName = *Geo::OGRc::FeatureDefn_GetName;
 *GetFieldCount = *Geo::OGRc::FeatureDefn_GetFieldCount;
 *GetFieldDefn = *Geo::OGRc::FeatureDefn_GetFieldDefn;
 *GetFieldIndex = *Geo::OGRc::FeatureDefn_GetFieldIndex;
@@ -359,7 +364,7 @@ sub new {
     bless $self, $pkg if defined($self);
 }
 
-*_GetName = *Geo::OGRc::FieldDefn__GetName;
+*GetName = *Geo::OGRc::FieldDefn_GetName;
 *GetNameRef = *Geo::OGRc::FieldDefn_GetNameRef;
 *SetName = *Geo::OGRc::FieldDefn_SetName;
 *GetType = *Geo::OGRc::FieldDefn_GetType;
@@ -442,6 +447,7 @@ sub new {
 *SetPoint_2D = *Geo::OGRc::Geometry_SetPoint_2D;
 *GetGeometryRef = *Geo::OGRc::Geometry_GetGeometryRef;
 *Simplify = *Geo::OGRc::Geometry_Simplify;
+*SimplifyPreserveTopology = *Geo::OGRc::Geometry_SimplifyPreserveTopology;
 *Boundary = *Geo::OGRc::Geometry_Boundary;
 *GetBoundary = *Geo::OGRc::Geometry_GetBoundary;
 *ConvexHull = *Geo::OGRc::Geometry_ConvexHull;
@@ -476,6 +482,7 @@ sub new {
 *FlattenTo2D = *Geo::OGRc::Geometry_FlattenTo2D;
 *Segmentize = *Geo::OGRc::Geometry_Segmentize;
 *GetEnvelope = *Geo::OGRc::Geometry_GetEnvelope;
+*GetEnvelope3D = *Geo::OGRc::Geometry_GetEnvelope3D;
 *Centroid = *Geo::OGRc::Geometry_Centroid;
 *WkbSize = *Geo::OGRc::Geometry_WkbSize;
 *GetCoordinateDimension = *Geo::OGRc::Geometry_GetCoordinateDimension;
@@ -536,6 +543,10 @@ package Geo::OGR;
 *wkbXDR = *Geo::OGRc::wkbXDR;
 *wkbNDR = *Geo::OGRc::wkbNDR;
 *NullFID = *Geo::OGRc::NullFID;
+*ALTER_NAME_FLAG = *Geo::OGRc::ALTER_NAME_FLAG;
+*ALTER_TYPE_FLAG = *Geo::OGRc::ALTER_TYPE_FLAG;
+*ALTER_WIDTH_PRECISION_FLAG = *Geo::OGRc::ALTER_WIDTH_PRECISION_FLAG;
+*ALTER_ALL_FLAG = *Geo::OGRc::ALTER_ALL_FLAG;
 *OLCRandomRead = *Geo::OGRc::OLCRandomRead;
 *OLCSequentialWrite = *Geo::OGRc::OLCSequentialWrite;
 *OLCRandomWrite = *Geo::OGRc::OLCRandomWrite;
@@ -543,6 +554,9 @@ package Geo::OGR;
 *OLCFastFeatureCount = *Geo::OGRc::OLCFastFeatureCount;
 *OLCFastGetExtent = *Geo::OGRc::OLCFastGetExtent;
 *OLCCreateField = *Geo::OGRc::OLCCreateField;
+*OLCDeleteField = *Geo::OGRc::OLCDeleteField;
+*OLCReorderFields = *Geo::OGRc::OLCReorderFields;
+*OLCAlterFieldDefn = *Geo::OGRc::OLCAlterFieldDefn;
 *OLCTransactions = *Geo::OGRc::OLCTransactions;
 *OLCDeleteFeature = *Geo::OGRc::OLCDeleteFeature;
 *OLCFastSetNextByIndex = *Geo::OGRc::OLCFastSetNextByIndex;
@@ -557,15 +571,12 @@ package Geo::OGR;
     use Carp;
     {
         package Geo::OGR;
-	use vars qw /$name_encoding/;
-	$name_encoding = 'UTF-8';
     }
     {
         package Geo::OGR::Driver;
 	use strict;
 	use vars qw /@CAPABILITIES %CAPABILITIES/;
-	use Encode;
-        @CAPABILITIES = qw/CreateDataSource DeleteDataSource/; 
+	@CAPABILITIES = qw/CreateDataSource DeleteDataSource/; 
 	for my $s (@CAPABILITIES) {
 	    my $cap = eval "\$Geo::OGR::ODrC$s";
 	    $CAPABILITIES{$s} = $cap;
@@ -583,9 +594,6 @@ package Geo::OGR;
 	    my($self, $cap) = @_;
 	    return _TestCapability($self, $CAPABILITIES{$cap});
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	*Create = *CreateDataSource;
 	*Copy = *CopyDataSource;
 	*OpenDataSource = *Open;
@@ -595,8 +603,7 @@ package Geo::OGR;
 	use Carp;
 	use strict;
 	use vars qw /@CAPABILITIES %CAPABILITIES %LAYERS/;
-	use Encode;
-        @CAPABILITIES = qw/CreateLayer DeleteLayer/;
+	@CAPABILITIES = qw/CreateLayer DeleteLayer/;
 	for my $s (@CAPABILITIES) {
 	    my $cap = eval "\$Geo::OGR::ODsC$s";
 	    $CAPABILITIES{$s} = $cap;
@@ -625,19 +632,16 @@ package Geo::OGR;
 	sub OpenShared {
 	    return Geo::OGR::OpenShared(@_);
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	sub Layer {
 	    my($self, $name) = @_;
 	    my $layer;
 	    if (defined $name) {
 		$layer = _GetLayerByName($self, "$name");
+		$layer = _GetLayerByIndex($self, $name) unless $layer;
 	    } else {
-		$name = 0;
+		$layer = _GetLayerByIndex($self, 0);
 	    }
-	    $layer = _GetLayerByIndex($self, $name) if !$layer and $name =~ /^\d+$/;
-	    return unless $layer;
+	    croak "No such layer: $name\n" unless $layer;
 	    $LAYERS{tied(%$layer)} = $self;
 	    return $layer;
 	}
@@ -654,14 +658,14 @@ package Geo::OGR;
 	    my($self, $index) = @_;
 	    $index = 0 unless defined $index;
 	    my $layer = _GetLayerByIndex($self, $index+0);
-	    return unless $layer;
+	    croak "No such layer: $index\n" unless $layer;
 	    $LAYERS{tied(%$layer)} = $self;
 	    return $layer;
 	}
 	sub GetLayerByName {
 	    my($self, $name) = @_;
-	    my $layer = _GetLayerByName($self, $name);
-	    return unless $layer;
+	    my $layer = _GetLayerByName($self, "$name");
+	    croak "No such layer: $name\n" unless $layer;
 	    $LAYERS{tied(%$layer)} = $self;
 	    return $layer;
 	}
@@ -713,10 +717,11 @@ package Geo::OGR;
 	package Geo::OGR::Layer;
 	use strict;
 	use vars qw /@CAPABILITIES %CAPABILITIES/;
-	use Encode;
-        @CAPABILITIES = qw/RandomRead SequentialWrite RandomWrite 
+	@CAPABILITIES = qw/RandomRead SequentialWrite RandomWrite 
 		   FastSpatialFilter FastFeatureCount FastGetExtent 
-		   CreateField Transactions DeleteFeature FastSetNextByIndex/;
+		   CreateField DeleteField ReorderFields AlterFieldDefn
+                   Transactions DeleteFeature FastSetNextByIndex
+                   StringsAsUTF8 IgnoreFields/;
 	for my $s (@CAPABILITIES) {
 	    my $cap = eval "\$Geo::OGR::OLC$s";
 	    $CAPABILITIES{$s} = $cap;
@@ -753,9 +758,6 @@ package Geo::OGR;
 	    my($self, $cap) = @_;
 	    return _TestCapability($self, $CAPABILITIES{$cap});
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	sub Schema {
 	    my $self = shift;
 	    if (@_) {
@@ -791,11 +793,7 @@ package Geo::OGR;
 	    for my $fn (keys %row) {
 		next if $fn eq 'FID';
 		next if $fn eq 'Geometry';
-		if (defined $row{$fn}) {
-		    $f->SetField($fn, $row{$fn});
-		} else {
-		    $f->UnsetField($fn);
-		}
+		$f->SetField($fn, $row{$fn});
 		$changed = 1;
 	    }
 	    $self->SetFeature($f) if $changed;
@@ -836,7 +834,7 @@ package Geo::OGR;
 		for my $field (@{$s->{Fields}}) {
 		    my $v = shift;
 		    my $n = $field->{Name};
-		    defined $v ? $f->SetField($n, $v) : $f->UnsetField($n);
+		    $f->SetField($n, $v);
 		}
 		$changed = 1;
 	    }
@@ -874,6 +872,10 @@ package Geo::OGR;
 	    }
 	    $self->CreateFeature($f);
 	}
+	sub GeometryType {
+	    my $self = shift;
+	    return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)};
+	}
 
 	package Geo::OGR::FeatureDefn;
 	use strict;
@@ -897,9 +899,7 @@ package Geo::OGR;
 	    }
 	    return $self;
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
+	*Name = *GetName;
 	sub Schema {
 	    my $self = shift;
 	    my %schema;
@@ -923,7 +923,7 @@ package Geo::OGR;
 		$s->{Index} = $i;
 		push @{$schema{Fields}}, $s;
 	    }
-	    return \%schema;
+	    return wantarray ? %schema : \%schema;
 	}
 	sub GeomType {
 	    my($self, $type) = @_;
@@ -935,11 +935,34 @@ package Geo::OGR;
 	    return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)} if defined wantarray;
 	}
 	*GeometryType = *GeomType;
+	sub GeometryIgnored {
+	    my $self = shift;
+	    SetGeometryIgnored($self, $_[0]) if @_;
+	    IsGeometryIgnored($self) if defined wantarray;
+	}
+	sub StyleIgnored {
+	    my $self = shift;
+	    SetStyleIgnored($self, $_[0]) if @_;
+	    IsStyleIgnored($self) if defined wantarray;
+	}
 
 	package Geo::OGR::Feature;
 	use strict;
 	use vars qw /%GEOMETRIES/;
 	use Carp;
+	use Encode;
+	sub create {
+	    my $pkg = shift;
+	    $pkg->new(Geo::OGR::FeatureDefn->create(@_));
+	}
+	sub FETCH {
+	    my($self, $index) = @_;
+	    $self->GetField($index);
+	}
+	sub STORE {
+	    my $self = shift;
+	    $self->SetField(@_);
+	}
 	sub FID {
 	    my $self = shift;
 	    $self->SetFID($_[0]) if @_;
@@ -984,11 +1007,7 @@ package Geo::OGR;
 	    for my $fn (keys %row) {
 		next if $fn eq 'FID';
 		next if $fn eq 'Geometry';
-		if (defined $row{$fn}) {
-		    $self->SetField($fn, $row{$fn});
-		} else {
-		    $self->UnsetField($fn);
-		}
+		$self->SetField($fn, $row{$fn});
 	    }
 	    return unless defined wantarray;
 	    %row = ();
@@ -1024,7 +1043,7 @@ package Geo::OGR;
 		for my $field (@{$s->{Fields}}) {
 		    my $v = shift;
 		    my $n = $field->{Name};
-		    defined $v ? $self->SetField($n, $v) : $self->UnsetField($n);
+		    $self->SetField($n, $v);
 		}
 	    }
 	    return unless defined wantarray;
@@ -1041,13 +1060,16 @@ package Geo::OGR;
 	}
 	sub GetFieldType {
 	    my($self, $field) = @_;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    return $Geo::OGR::FieldDefn::TYPE_INT2STRING{_GetFieldType($self, $field)};
 	}
 	sub FieldIsList {
 	    my($self, $field) = @_;
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[1]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    my $type = _GetFieldType($self, $field);
 	    return 1 if ($type == $Geo::OGR::OFTIntegerList or
 			 $type == $Geo::OGR::OFTRealList or
@@ -1059,9 +1081,9 @@ package Geo::OGR;
 	}
 	sub GetField {
 	    my($self, $field) = @_;
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[1]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    return undef unless IsFieldSet($self, $field);
 	    my $type = _GetFieldType($self, $field);
 	    if ($type == $Geo::OGR::OFTInteger) {
@@ -1075,15 +1097,15 @@ package Geo::OGR;
 	    }
 	    if ($type == $Geo::OGR::OFTIntegerList) {
 		my $ret = GetFieldAsIntegerList($self, $field);
-		return @$ret;
+		return wantarray ? @$ret : $ret;
 	    } 
 	    if ($type == $Geo::OGR::OFTRealList) {
 		my $ret = GetFieldAsDoubleList($self, $field);
-		return @$ret;
+		return wantarray ? @$ret : $ret;
 	    }
 	    if ($type == $Geo::OGR::OFTStringList) {
 		my $ret = GetFieldAsStringList($self, $field);
-		return @$ret;
+		return wantarray ? @$ret : $ret;
 	    }
 	    if ($type == $Geo::OGR::OFTBinary) {
 		return GetFieldAsString($self, $field);
@@ -1091,11 +1113,11 @@ package Geo::OGR;
 	    if ($type == $Geo::OGR::OFTDate) {
 		my @ret = GetFieldAsDateTime($self, $field);
 		# year, month, day, hour, minute, second, timezone
-		return @ret[0..2];
+		return wantarray ? @ret[0..2] : [@ret[0..2]];
 	    }
 	    if ($type == $Geo::OGR::OFTTime) {
 		my @ret = GetFieldAsDateTime($self, $field);
-		return @ret[3..6];
+		return wantarray ? @ret[3..6] : [@ret[3..6]];
 	    }
 	    if ($type == $Geo::OGR::OFTDateTime) {
 		return GetFieldAsDateTime($self, $field);
@@ -1104,18 +1126,17 @@ package Geo::OGR;
 	}
 	sub UnsetField {
 	    my($self, $field) = @_;
-	    my $type = _GetFieldType($self, $field);
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[1]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    _UnsetField($self, $field);
 	}
 	sub SetField {
 	    my $self = shift;
 	    my $field = $_[0];
-	    my $count = GetFieldCount($self);
-	    $field = GetFieldIndex($self, $field) unless $field =~ /^\d+$/;
-	    croak("no such field: $_[0]") if $field < 0 or $field >= $count;
+	    my $index = GetFieldIndex($self, "$field");
+	    $field = $index unless $index == -1;
+	    croak "No such field: $field" if $field < 0 or $field >= GetFieldCount($self);
 	    shift;
 	    if (@_ == 0 or !defined($_[0])) {
 		_UnsetField($self, $field);
@@ -1123,10 +1144,10 @@ package Geo::OGR;
 	    }
 	    my $list = ref($_[0]) ? $_[0] : [@_];
 	    my $type = _GetFieldType($self, $field);
-	    if ($type == $Geo::OGR::OFTInteger or 
-		$type == $Geo::OGR::OFTReal or 
+	    if ($type == $Geo::OGR::OFTInteger or
+		$type == $Geo::OGR::OFTReal or
 		$type == $Geo::OGR::OFTString or
-		$type == $Geo::OGR::OFTBinary) 
+		$type == $Geo::OGR::OFTBinary)
 	    {
 		_SetField($self, $field, $_[0]);
 	    } 
@@ -1155,7 +1176,7 @@ package Geo::OGR;
 		_SetField($self, $field, @$list[0..6]);
 	    } 
 	    else {
-		carp "unknown/unsupported field type: $type";
+		carp "unknown or unsupported field type: $type";
 	    }
 	}
 	sub Field {
@@ -1180,6 +1201,26 @@ package Geo::OGR;
 	    $GEOMETRIES{tied(%$geom)} = $self if $geom;
 	    return $geom;
 	}
+	sub ReferenceGeometry {
+	    my $self = shift;
+	    SetGeometryDirectly($self, $_[0]) if @_;
+	    if (defined wantarray) {
+		my $geometry = GetGeometry($self);
+		return $geometry->Clone() if $geometry;
+	    }
+	}
+	sub SetFrom {
+	    my($self, $other) = @_;
+	    _SetFrom($self, $other), return if @_ <= 2;
+	    my $forgiving = $_[2];
+	    _SetFrom($self, $other, $forgiving), return if @_ <= 3;	    
+	    my $map = $_[3];
+	    my @list;
+	    for my $i (1..GetFieldCount($self)) {
+		push @list, ($map->{$i} || -1);
+	    }
+	    SetFromWithMap($self, $other, 1, \@list);
+	}
 
 	package Geo::OGR::FieldDefn;
 	use strict;
@@ -1233,9 +1274,6 @@ package Geo::OGR;
 	    }
 	    return $self;
 	}
-	sub GetName {
-	  return $Geo::OGR::name_encoding ? $_[0]->_GetName : decode($Geo::OGR::name_encoding, $_[0]->_GetName);
-	}
 	sub Name {
 	    my $self = shift;
 	    SetName($self, $_[0]) if @_;
@@ -1267,6 +1305,11 @@ package Geo::OGR;
 	    SetPrecision($self, $_[0]) if @_;
 	    GetPrecision($self) if defined wantarray;
 	}
+	sub Ignored {
+	    my $self = shift;
+	    SetIgnored($self, $_[0]) if @_;
+	    IsIgnored($self) if defined wantarray;
+	}
 	sub Schema {
 	    my $self = shift;
 	    if (@_) {
@@ -1278,11 +1321,12 @@ package Geo::OGR;
 		$self->Precision($param{Precision}) if exists $param{Precision};
 	    }
 	    return unless defined wantarray;
-	    return { Name => $self->Name, 
-		     Type  => $self->Type,
-		     Justify  => $self->Justify,
-		     Width  => $self->Width,
-		     Precision => $self->Precision };
+	    my %schema = ( Name => $self->Name, 
+			   Type  => $self->Type,
+			   Justify  => $self->Justify,
+			   Width  => $self->Width,
+			   Precision => $self->Precision );
+	    return wantarray ? %schema : \%schema;
 	}
 
 	package Geo::OGR::Geometry;
@@ -1450,7 +1494,16 @@ package Geo::OGR;
 		if ($t eq 'Unknown' or $t eq 'None' or $t eq 'GeometryCollection') {
 		    croak("Can't set points of a geometry of type: $t");
 		} elsif ($t eq 'Point') {
-		    $flat ? AddPoint_2D($self, @$points[0..1]) : AddPoint_3D($self, @$points[0..2]);
+		    # support both "Point" as a list of one point and one point
+		    if (ref($points->[0])) {
+			$flat ? 
+			    AddPoint_2D($self, @{$points->[0]}[0..1]) : 
+			    AddPoint_3D($self, @{$points->[0]}[0..2]);
+		    } else {
+			$flat ? 
+			    AddPoint_2D($self, @$points[0..1]) : 
+			    AddPoint_3D($self, @$points[0..2]);
+		    }
 		} elsif ($t eq 'LineString' or $t eq 'LinearRing') {
 		    if ($flat) {
 			for my $p (@$points) {
@@ -1502,16 +1555,16 @@ package Geo::OGR;
 	    } else {
 		$n = $self->GetPointCount;
 		if ($n == 1) {
-		    push @points, $flat ? GetPoint_2D($self) : GetPoint_3D($self);
+		    push @points, $flat ? scalar GetPoint_2D($self) : scalar GetPoint_3D($self);
 		} else {
 		    my $i;
 		    if ($flat) {
 			for my $i (0..$n-1) {
-			    push @points, GetPoint_2D($self, $i);
+			    push @points, scalar GetPoint_2D($self, $i);
 			}
 		    } else {
 			for my $i (0..$n-1) {
-			    push @points, GetPoint_3D($self, $i);
+			    push @points, scalar GetPoint_3D($self, $i);
 			}
 		    }
 		}
@@ -1572,6 +1625,7 @@ package Geo::OGR;
 	*AsBinary = *ExportToWkb;
 	*AsGML = *ExportToGML;
 	*AsKML = *ExportToKML;
+	*AsJSON = *ExportToJson;
 	*BuildPolygonFromEdges = *Geo::OGR::BuildPolygonFromEdges;
 	*ForceToPolygon = *Geo::OGR::ForceToPolygon;
 	
@@ -1601,9 +1655,11 @@ package Geo::OGR;
 	return @drivers;
     }
     sub GetDriver {
-	my($name_or_number) = @_;
-	return _GetDriver($name_or_number) if $name_or_number =~ /^\d/;
-	return GetDriverByName("$name_or_number");
+	my($name) = @_;
+	my $driver = GetDriverByName("$name");
+	$driver = _GetDriver($name) unless $driver;
+	croak "No such OGR driver: $name\n" unless $driver;
+	return $driver;
     }
     *Driver = *GetDriver;
 1;
diff --git a/swig/perl/lib/Geo/OSR.dox b/swig/perl/lib/Geo/OSR.dox
index 274de4e..89fc7d2 100644
--- a/swig/perl/lib/Geo/OSR.dox
+++ b/swig/perl/lib/Geo/OSR.dox
@@ -2,6 +2,9 @@
 
 ## @class Geo::OSR
 
+## @ignore UseExceptions
+## @ignore DontUseExceptions
+
 ## @ignore TIEHASH
 ## @ignore CLEAR
 ## @ignore FIRSTKEY
@@ -28,286 +31,197 @@
 ## @fn @GetProjectionMethodParamInfo($method, $parameter)
 # @return ($user_friendly_name, $type, $defaultval)
 
-## @attr SRS_PT_ALBERS_CONIC_EQUAL_AREA
-# @deprecated
-
-## @attr SRS_PT_AZIMUTHAL_EQUIDISTANT
-# @deprecated
-
-## @attr SRS_PT_CASSINI_SOLDNER
-# @deprecated
-
-## @attr SRS_PT_CYLINDRICAL_EQUAL_AREA
-# @deprecated
-
-## @attr SRS_PT_ECKERT_IV
-# @deprecated
-
-## @attr SRS_PT_ECKERT_VI
-# @deprecated
-
-## @attr SRS_PT_EQUIDISTANT_CONIC
-# @deprecated
-
-## @attr SRS_PT_EQUIRECTANGULAR
-# @deprecated
-
-## @attr SRS_PT_GALL_STEREOGRAPHIC
-# @deprecated
-
-## @attr SRS_PT_GNOMONIC
-# @deprecated
-
-## @attr SRS_PT_GOODE_HOMOLOSINE
-# @deprecated
-
-## @attr SRS_PT_HOTINE_OBLIQUE_MERCATOR
-# @deprecated
-
-## @attr SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN
-# @deprecated
-
-## @attr SRS_PT_LABORDE_OBLIQUE_MERCATOR
-# @deprecated
-
-## @attr SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP
-# @deprecated
-
-## @attr SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP
-# @deprecated
-
-## @attr SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM
-# @deprecated
-
-## @attr SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA
-# @deprecated
-
-## @attr SRS_PT_MERCATOR_1SP
-# @deprecated
-
-## @attr SRS_PT_MERCATOR_2SP
-# @deprecated
-
-## @attr SRS_PT_MILLER_CYLINDRICAL
-# @deprecated
-
-## @attr SRS_PT_MOLLWEIDE
-# @deprecated
-
-## @attr SRS_PT_NEW_ZEALAND_MAP_GRID
-# @deprecated
-
-## @attr SRS_PT_OBLIQUE_STEREOGRAPHIC
-# @deprecated
-
-## @attr SRS_PT_ORTHOGRAPHIC
-# @deprecated
-
-## @attr SRS_PT_POLAR_STEREOGRAPHIC
-# @deprecated
-
-## @attr SRS_PT_POLYCONIC
-# @deprecated
-
-## @attr SRS_PT_ROBINSON
-# @deprecated
-
-## @attr SRS_PT_SINUSOIDAL
-# @deprecated
-
-## @attr SRS_PT_STEREOGRAPHIC
-# @deprecated
-
-## @attr SRS_PT_SWISS_OBLIQUE_CYLINDRICAL
-# @deprecated
-
-## @attr SRS_PT_TRANSVERSE_MERCATOR
-# @deprecated
-
-## @attr SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED
-# @deprecated
-
-## @attr SRS_PT_TRANSVERSE_MERCATOR_MI_22
-# @deprecated
-
-## @attr SRS_PT_TRANSVERSE_MERCATOR_MI_23
-# @deprecated
-
-## @attr SRS_PT_TRANSVERSE_MERCATOR_MI_24
-# @deprecated
-
-## @attr SRS_PT_TRANSVERSE_MERCATOR_MI_25
-# @deprecated
-
-## @attr SRS_PT_TUNISIA_MINING_GRID
-# @deprecated
-
-## @attr SRS_PT_VANDERGRINTEN
-# @deprecated
-
-## @attr SRS_PT_KROVAK
-# @deprecated
-
-## @attr SRS_PP_CENTRAL_MERIDIAN
-# @deprecated
-
-## @attr SRS_PP_SCALE_FACTOR
-# @deprecated
-
-## @attr SRS_PP_STANDARD_PARALLEL_1
-# @deprecated
-
-## @attr SRS_PP_STANDARD_PARALLEL_2
-# @deprecated
-
-## @attr SRS_PP_PSEUDO_STD_PARALLEL_1
-# @deprecated
-
-## @attr SRS_PP_LONGITUDE_OF_CENTER
-# @deprecated
-
-## @attr SRS_PP_LATITUDE_OF_CENTER
-# @deprecated
-
-## @attr SRS_PP_LONGITUDE_OF_ORIGIN
-# @deprecated
-
-## @attr SRS_PP_LATITUDE_OF_ORIGIN
-# @deprecated
-
-## @attr SRS_PP_FALSE_EASTING
-# @deprecated
-
-## @attr SRS_PP_FALSE_NORTHING
-# @deprecated
-
-## @attr SRS_PP_AZIMUTH
-# @deprecated
-
-## @attr SRS_PP_LONGITUDE_OF_POINT_1
-# @deprecated
-
-## @attr SRS_PP_LATITUDE_OF_POINT_1
-# @deprecated
-
-## @attr SRS_PP_LONGITUDE_OF_POINT_2
-# @deprecated
-
-## @attr SRS_PP_LATITUDE_OF_POINT_2
-# @deprecated
-
-## @attr SRS_PP_LONGITUDE_OF_POINT_3
-# @deprecated
-
-## @attr SRS_PP_LATITUDE_OF_POINT_3
-# @deprecated
-
-## @attr SRS_PP_RECTIFIED_GRID_ANGLE
-# @deprecated
-
-## @attr SRS_PP_LANDSAT_NUMBER
-# @deprecated
-
-## @attr SRS_PP_PATH_NUMBER
-# @deprecated
-
-## @attr SRS_PP_PERSPECTIVE_POINT_HEIGHT
-# @deprecated
-
-## @attr SRS_PP_FIPSZONE
-# @deprecated
-
-## @attr SRS_PP_ZONE
-# @deprecated
-
-## @attr SRS_UL_METER
-# @deprecated
-
-## @attr SRS_UL_FOOT
-# @deprecated
-
-## @attr SRS_UL_FOOT_CONV
-# @deprecated
-
-## @attr SRS_UL_US_FOOT
-# @deprecated
-
-## @attr SRS_UL_US_FOOT_CONV
-# @deprecated
-
-## @attr SRS_UL_NAUTICAL_MILE
-# @deprecated
-
-## @attr SRS_UL_NAUTICAL_MILE_CONV
-# @deprecated
-
-## @attr SRS_UL_LINK
-# @deprecated
-
-## @attr SRS_UL_LINK_CONV
-# @deprecated
-
-## @attr SRS_UL_CHAIN
-# @deprecated
-
-## @attr SRS_UL_CHAIN_CONV
-# @deprecated
-
-## @attr SRS_UL_ROD
-# @deprecated
-
-## @attr SRS_UL_ROD_CONV
-# @deprecated
-
-## @attr SRS_DN_NAD27
-# @deprecated
-
-## @attr SRS_DN_NAD83
-# @deprecated
-
-## @attr SRS_DN_WGS72
-# @deprecated
-
-## @attr SRS_DN_WGS84
-# @deprecated
-
-## @attr SRS_WGS84_SEMIMAJOR
-# @deprecated
-
-## @attr SRS_WGS84_INVFLATTENING
-# @deprecated
-
 
 ## @class Geo::OSR::SpatialReference
 # @brief <a href="http://www.gdal.org/ogr/classOGRSpatialReference.html">Documentation
 # of the underlying C++ class at www.gdal.org</a>
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-## @ignore __str__
+## @attr list PROJECTIONS
+# Projections known to GDAL
+
+## @attr list PARAMETERS
+# Some projection parameters known to GDAL
 
 ## @cmethod Geo::OSR::SpatialReference new($wkt = undef)
 # @param wkt well known text
 # @return a new Geo::OSR::SpatialReference object
 
+## @ignore ImportFromEPSGA
+## @ignore ImportFromERM
+## @ignore ImportFromMICoordSys
+## @ignore ImportFromWkt
+## @ignore ImportFromProj4
+## @ignore ImportFromESRI
+## @ignore ImportFromEPSG
+## @ignore ImportFromPCI
+## @ignore ImportFromUSGS
+## @ignore ImportFromXML
+## @ignore ImportFromUrl
+
 ## @cmethod Geo::OSR::SpatialReference create(%params)
-# Create a new spatial reference object using named parameters. This
-# constructor recognizes the following named parameters: WKT, Text,
-# Proj4, ESRI, EPSG, PCI, USGS, XML.
+# Create a new spatial reference object using a named parameter. This
+# constructor recognizes the following key words (alternative in
+# parenthesis): WKT (Text), Proj4, ESRI, EPSG, EPSGA, PCI, USGS, GML
+# (XML), URL, ERMapper (ERM), MapInfoCS (MICoordSys). The value
+# depends on the key.
+# - WKT: Well Known Text string
+# - Proj4: PROJ.4 string
+# - ESRI: reference to a list of strings (contents of ESRI .prj file)
+# - EPSG: EPSG code number
+# - EPSGA: EPSG code number (the resulting CS will have EPSG preferred axis ordering)
+# - PCI: listref: [PCI_projection_string, Grid_units_code, [17 cs parameters]]
+# - USGS: listref: [Projection_system_code, Zone, [15 cs parameters], Datum_code, Format_flag]
+# - GML: GML string
+# - URL: URL for downloading the spatial reference from
+# - ERMapper: listref: [Projection, Datum, Units]
+# - MapInfoCS: MapInfo style co-ordinate system definition
+#
+# For more information, consult the import methods in <a href="http://www.gdal.org/ogr/classOGRSpatialReference.html">OGR documentation</a>.
+#
+# @note ImportFrom* methods also exist but are not documented here.
 #
 # Usage:
 # \code
-# $sr = Geo::OSR::SpatialReference->create(...arguments...);
+# $sr = Geo::OSR::SpatialReference->create( key => value );
 # \endcode
 # @return a new Geo::OSR::SpatialReference object
 
-## @method $IsSame($rhs)
-# @param rhs a Geo::OSR::SpatialReference object
+## @method Geo::OSR::SpatialReference Clone()
+# Make a duplicate of this SpatialReference object.
+# @return a new Geo::OSR::SpatialReference object
+
+## @method Geo::OSR::SpatialReference CloneGeogCS()
+# Make a duplicate of the GEOGCS node of this SpatialReference object.
+# @return a new Geo::OSR::SpatialReference object
+
+## @ignore AsText
+## @ignore ExportToPrettyWkt
+## @ignore ExportToProj4
+## @ignore ExportToPCI
+## @ignore ExportToUSGS
+## @ignore ExportToXML
+## @ignore ExportToMICoordSys
+## @ignore ExportToWkt
+
+## @method Export($format)
+# Export the spatial reference to a selected format.
+# @note a.k.a. As
+# @param format One of the following. The return value is explained
+# after the format. Other arguments are explained in parenthesis.
+# - WKT (Text): Well Known Text string
+# - PrettyWKT: Well Known Text string nicely formatted (simplify)
+# - Proj4: PROJ.4 string
+# - PCI: a list: ($proj_string, $units, [$parms1, ...])
+# - USGS: a list: ($code, $zone, [$parms1, ...], $datum)
+# - GML (XML): GML based string (dialect)
+# - MapInfoCS (MICoordSys): MapInfo style co-ordinate system definition
+#
+# @note The named parameter syntax also works and is needed is those
+# cases when other arguments need or may be given. The format should
+# be given using key as, 'to' or 'format'.
+#
+# @note ExportTo* and AsText methods also exist but are not documented here.
+#
+# @return a scalar or a list depending on the export format
+
+## @ignore SetACEA
+## @ignore SetAE
+## @ignore SetAngularUnits
+## @ignore SetAttrValue
+## @ignore SetBonne
+## @ignore SetCS
+## @ignore SetCompoundCS
+## @ignore SetEC
+## @ignore SetEckertIV
+## @ignore SetEckertVI
+## @ignore SetEquirectangular
+## @ignore SetEquirectangular2
+## @ignore SetFromUserInput
+## @ignore SetGS
+## @ignore SetGaussSchreiberTMercator
+## @ignore SetGeocCS
+## @ignore SetIGH
+## @ignore SetLinearUnits
+## @ignore SetLinearUnitsAndUpdateParameters
+## @ignore SetNormProjParm
+## @ignore SetProjParm
+## @ignore SetProjection
+## @ignore SetStatePlane
+## @ignore SetTargetLinearUnits
+## @ignore SetUTM
+## @ignore SetVertCS
+## @ignore SetWellKnownGeogCS
+## @ignore SetAuthority
+## @ignore SetCEA
+## @ignore SetGEOS
+## @ignore SetGH
+## @ignore SetGnomonic
+## @ignore SetHOM
+## @ignore SetHOM2PNO
+## @ignore SetKrovak
+## @ignore SetLAEA
+## @ignore SetLCC
+## @ignore SetLCC1SP
+## @ignore SetLCCB
+## @ignore SetLocalCS
+## @ignore SetMC
+## @ignore SetMercator
+## @ignore SetMollweide
+## @ignore SetNZMG
+## @ignore SetOS
+## @ignore SetOrthographic
+## @ignore SetPS
+## @ignore SetPolyconic
+## @ignore SetRobinson
+## @ignore SetSOC
+## @ignore SetSinusoidal
+## @ignore SetStereographic
+## @ignore SetTM
+## @ignore SetTMG
+## @ignore SetTMSO
+## @ignore SetTMVariant
+## @ignore SetVDG
+## @ignore SetTOWGS84
+## @ignore SetGeogCS
+## @ignore SetProjCS
+
+## @method Set(%params)
+# Set a parameter or parameters in the spatial reference object.
+# @param params Named parameters. Recognized keys and respective
+# values are the following.
+# - Authority: authority name
+# - Node: partial or complete path to the target node
+# - AngularUnits: angular units for the geographic coordinate system
+# - LinearUnits: linear units for the target node or the object
+# - CoordinateSystem: 'UTM', 'State Plane', 'WGS' or a user visible name 
+# - Zone: zone for setting up UTM or State Plane coordinate systems (State Plane zone in USGS numbering scheme)
+# - Projection: one from \@Geo::OSR::PROJECTIONS
+# - Parameter: one from \@Geo::OSR::PARAMETERS
+# - Code: code for value with an authority
+# - Value: value to be assigned to a node, the projection or the object
+# - Normalized: set to true to indicate that the Value argument is in "normalized" form
+# - Parameters: a reference to a list containing the projection parameters
+# - Name: Transverse Mercator variant name or a well known name (e.g. WGS84)
+# - GuessFrom: tries to guess from given text
+# - North: set false for southern hemisphere
+# - NAD83: set false if the NAD27 zone definition should be used instead of NAD83
+# - UnitName: to override the legal definition for a zone
+# - UnitConversionFactor: to override the legal definition for a zone
+# - LOCAL_CS: local cs name
+# - Datum: a known (OGC or EPSG) name
+# - Spheroid: user visible name
+# - GeocentricCS: Geocentric coorinate system name
+# - HorizontalCS: Horizontal coordinate system name
+# - VerticalCS: Vertical coordinate system name (setting requires Datum)
+#
+# @note Numerous Set* methods also exist but are not documented here.
+
+## @method $IsSame($rs)
+# @param rs a Geo::OSR::SpatialReference object
 # @return boolean
 
-## @method $IsSameGeogCS($rhs)
-# @param rhs a Geo::OSR::SpatialReference object
+## @method $IsSameGeogCS($rs)
+# @param rs a Geo::OSR::SpatialReference object
 # @return boolean
 
 ## @method $IsGeographic()
@@ -319,26 +233,27 @@
 ## @method $IsLocal()
 # @return boolean
 
+## @method $IsCompound()
+# @return boolean
+
+## @method $IsGeocentric()
+# @return boolean
+
+## @method $IsVertical()
+# @return boolean
+
+## @method $IsSameVertCS($rs)
+# @param rs a Geo::OSR::SpatialReference object
+# @return boolean
+
 ## @method $GetAttrValue($name, $child = 0)
 # @param name
 # @param child
 # @return string
 
-## @method SetAttrValue($name, $value)
-# @param name
-# @param value
-
-## @method SetAngularUnits($name, $to_radians)
-# @param name
-# @param to_radians
-
 ## @method $GetAngularUnits()
 # @return a number
 
-## @method SetLinearUnits($name, $to_meters)
-# @param name
-# @param to_meters
-
 ## @method $GetLinearUnits()
 # @return a number
 
@@ -353,116 +268,40 @@
 # @param target_key
 # @return string
 
-## @method SetUTM($zone, $north = 1)
-# @param zone
-# @param north
-
-## @method SetStatePlane($zone, $is_nad83 = 1, $unitsname = "", $units = 0.0)
-# @param zone
-# @param is_nad83
-# @param unitsname
-# @param units
-
-## @method AutoIdentifyEPSG()
-
-## @method SetProjection($arg)
-# @param arg
-
-## @method SetProjParm($name, $val)
-# @param name
-# @param val
-
 ## @method $GetProjParm($name, $default_val = 0.0)
 # @param name
 # @param default_val
 # @return a number
 
-## @method SetNormProjParm($name, $val)
-# @param name
-# @param val
-
 ## @method $GetNormProjParm($name, $default_val = 0.0)
 # @param name
 # @param default_val
 # @return a number
 
-## @method SetACEA($stdp1, $stdp2, $clat, $clong, $fe, $fn)
-
-## @method SetAE($clat, $clon, $fe, $fn)
-
-## @method SetCS($clat, $clon, $fe, $fn)
-
-## @method SetBonne($clat, $clon, $fe, $fn)
-
-## @method SetEC($stdp1, $stdp2, $clat, $clong, $fe, $fn)
-
-## @method SetEckertIV($cm, $fe, $fn)
-
-## @method SetEckertVI($cm, $fe, $fn)
-
-## @method SetEquirectangular($clat, $clong, $fe, $fn)
-
-## @method SetGS($cm, $fe, $fn)
-
-## @method SetWellKnownGeogCS($name)
-
-## @method SetFromUserInput($name)
-
 ## @method CopyGeogCSFrom($rhs)
 # @param rhs Geo::OSR::SpatialReference
 
-## @method SetTOWGS84($p1, $p2, $p3, $p4 = 0.0, $p5 = 0.0, $p6 = 0.0, $p7 = 0.0)
-
 ## @method GetTOWGS84()
 # @return array = ($p1, $p2, $p3, $p4, $p5, $p6, $p7)
 
-## @method SetGeogCS($GeogName, $DatumName, $EllipsoidName, $SemiMajor, $InvFlattening, $PMName = "Greenwich", $PMOffset = 0.0, $Units = "degree", $ConvertToRadians =  0.0174532925199433)
+## @method GetInvFlattening()
 
-## @method SetProjCS($name = "unnamed")
+## @method GetSemiMinor()
 
-## @method ImportFromWkt($wkt)
+## @method GetSemiMajor() 
 
-## @method ImportFromProj4($proj4)
+## @method GetUTMZone()
+# Get UTM zone information. 
+# @return The UTM zone (integer). In scalar context the returned value
+# is negative for southern hemisphere zones. In list context returns
+# two values ($zone, $north), where $zone is always non-negative and
+# $north is true or false.
 
-## @method ImportFromESRI($esri)
-
-## @method ImportFromEPSG($epsg_number)
-
-## @method ImportFromPCI($proj, $units = "METRE", \@argin = undef)
-# @param proj
-# @param units
-# @param argin = array of 17 numbers
-
-## @method ImportFromUSGS($proj_code, $zone = 0, \@argin[15] = undef,  $datum_code = 0)
-# @param proj_code
-# @param zone
-# @param argin = array of 15 numbers
-# @param datum_code
-
-## @method ImportFromXML($xml_string)
-
-## @method $AsText()
-# Return a well known text representation of this spatial reference
-# system.  An alternative name: ExportToWkt.
-# @return WKT string
-
-## @method $ExportToPrettyWkt($simplify = 0)
-# @return WKT string
-
-## @method $ExportToProj4()
-# @return proj4 string
-
-## @method @ExportToPCI()
-# @return ($proj_string, $units, [$parms1, ...])
-
-## @method @ExportToUSGS()
-# @return ($code, $zone, [$parms1, ...], $datum)
-
-## @method $ExportToXML($dialect = "")
-# @return XML string
+## @method AutoIdentifyEPSG()
+# Set EPSG authority info if possible.
 
-## @method Geo::OSR::SpatialReference CloneGeogCS()
-# @return a new Geo::OSR::SpatialReference object
+## @method EPSGTreatsAsLatLong()
+# Returns TRUE if EPSG feels this geographic coordinate system should be treated as having lat/long coordinate ordering.
 
 ## @method Validate()
 
@@ -476,74 +315,9 @@
 
 ## @method MorphFromESRI()
 
-## @method ImportFromUrl()
-
-## @method SetAuthority()
-
-## @method SetCEA()
-
-## @method SetGEOS()
-
-## @method SetGH()
-
-## @method SetGnomonic()
-
-## @method SetHOM()
-
-## @method SetHOM2PNO()
-
-## @method SetKrovak()
-
-## @method SetLAEA()
-
-## @method SetLCC()
-
-## @method SetLCC1SP()
-
-## @method SetLCCB()
-
-## @method SetLocalCS()
-
-## @method SetMC()
-
-## @method SetMercator()
-
-## @method SetMollweide()
-
-## @method SetNZMG()
-
-## @method SetOS()
-
-## @method SetOrthographic()
-
-## @method SetPS()
-
-## @method SetPolyconic()
-
-## @method SetRobinson()
-
-## @method SetSOC()
-
-## @method SetSinusoidal()
-
-## @method SetStereographic()
-
-## @method SetTM()
-
-## @method SetTMG()
-
-## @method SetTMSO()
-
-## @method SetTMVariant()
-
-## @method SetVDG()
 
 ## @class Geo::OSR::CoordinateTransformation
 
-## @ignore DISOWN
-## @ignore ACQUIRE
-## @ignore DESTROY
-
 ## @cmethod Geo::OSR::CoordinateTransformation new($src, $dst)
 # @param src a Geo::OSR::SpatialReference object
 # @param dst a Geo::OSR::SpatialReference object
diff --git a/swig/perl/lib/Geo/OSR.pm b/swig/perl/lib/Geo/OSR.pm
index cb9ef6b..75802e2 100644
--- a/swig/perl/lib/Geo/OSR.pm
+++ b/swig/perl/lib/Geo/OSR.pm
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 1.3.39
+# Version 1.3.40
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -88,15 +88,20 @@ sub DESTROY {
 *__str__ = *Geo::OSRc::SpatialReference___str__;
 *IsSame = *Geo::OSRc::SpatialReference_IsSame;
 *IsSameGeogCS = *Geo::OSRc::SpatialReference_IsSameGeogCS;
+*IsSameVertCS = *Geo::OSRc::SpatialReference_IsSameVertCS;
 *IsGeographic = *Geo::OSRc::SpatialReference_IsGeographic;
 *IsProjected = *Geo::OSRc::SpatialReference_IsProjected;
+*IsCompound = *Geo::OSRc::SpatialReference_IsCompound;
+*IsGeocentric = *Geo::OSRc::SpatialReference_IsGeocentric;
 *IsLocal = *Geo::OSRc::SpatialReference_IsLocal;
+*IsVertical = *Geo::OSRc::SpatialReference_IsVertical;
 *EPSGTreatsAsLatLong = *Geo::OSRc::SpatialReference_EPSGTreatsAsLatLong;
 *SetAuthority = *Geo::OSRc::SpatialReference_SetAuthority;
 *GetAttrValue = *Geo::OSRc::SpatialReference_GetAttrValue;
 *SetAttrValue = *Geo::OSRc::SpatialReference_SetAttrValue;
 *SetAngularUnits = *Geo::OSRc::SpatialReference_SetAngularUnits;
 *GetAngularUnits = *Geo::OSRc::SpatialReference_GetAngularUnits;
+*SetTargetLinearUnits = *Geo::OSRc::SpatialReference_SetTargetLinearUnits;
 *SetLinearUnits = *Geo::OSRc::SpatialReference_SetLinearUnits;
 *SetLinearUnitsAndUpdateParameters = *Geo::OSRc::SpatialReference_SetLinearUnitsAndUpdateParameters;
 *GetLinearUnits = *Geo::OSRc::SpatialReference_GetLinearUnits;
@@ -104,7 +109,7 @@ sub DESTROY {
 *GetAuthorityCode = *Geo::OSRc::SpatialReference_GetAuthorityCode;
 *GetAuthorityName = *Geo::OSRc::SpatialReference_GetAuthorityName;
 *SetUTM = *Geo::OSRc::SpatialReference_SetUTM;
-*GetUTMZone = *Geo::OSRc::SpatialReference_GetUTMZone;
+*_GetUTMZone = *Geo::OSRc::SpatialReference__GetUTMZone;
 *SetStatePlane = *Geo::OSRc::SpatialReference_SetStatePlane;
 *AutoIdentifyEPSG = *Geo::OSRc::SpatialReference_AutoIdentifyEPSG;
 *SetProjection = *Geo::OSRc::SpatialReference_SetProjection;
@@ -128,6 +133,7 @@ sub DESTROY {
 *SetGaussSchreiberTMercator = *Geo::OSRc::SpatialReference_SetGaussSchreiberTMercator;
 *SetGS = *Geo::OSRc::SpatialReference_SetGS;
 *SetGH = *Geo::OSRc::SpatialReference_SetGH;
+*SetIGH = *Geo::OSRc::SpatialReference_SetIGH;
 *SetGEOS = *Geo::OSRc::SpatialReference_SetGEOS;
 *SetGnomonic = *Geo::OSRc::SpatialReference_SetGnomonic;
 *SetHOM = *Geo::OSRc::SpatialReference_SetHOM;
@@ -162,6 +168,9 @@ sub DESTROY {
 *SetLocalCS = *Geo::OSRc::SpatialReference_SetLocalCS;
 *SetGeogCS = *Geo::OSRc::SpatialReference_SetGeogCS;
 *SetProjCS = *Geo::OSRc::SpatialReference_SetProjCS;
+*SetGeocCS = *Geo::OSRc::SpatialReference_SetGeocCS;
+*SetVertCS = *Geo::OSRc::SpatialReference_SetVertCS;
+*SetCompoundCS = *Geo::OSRc::SpatialReference_SetCompoundCS;
 *ImportFromWkt = *Geo::OSRc::SpatialReference_ImportFromWkt;
 *ImportFromProj4 = *Geo::OSRc::SpatialReference_ImportFromProj4;
 *ImportFromUrl = *Geo::OSRc::SpatialReference_ImportFromUrl;
@@ -262,6 +271,7 @@ package Geo::OSR;
 *SRS_PT_GAUSSSCHREIBERTMERCATOR = *Geo::OSRc::SRS_PT_GAUSSSCHREIBERTMERCATOR;
 *SRS_PT_GEOSTATIONARY_SATELLITE = *Geo::OSRc::SRS_PT_GEOSTATIONARY_SATELLITE;
 *SRS_PT_GOODE_HOMOLOSINE = *Geo::OSRc::SRS_PT_GOODE_HOMOLOSINE;
+*SRS_PT_IGH = *Geo::OSRc::SRS_PT_IGH;
 *SRS_PT_GNOMONIC = *Geo::OSRc::SRS_PT_GNOMONIC;
 *SRS_PT_HOTINE_OBLIQUE_MERCATOR = *Geo::OSRc::SRS_PT_HOTINE_OBLIQUE_MERCATOR;
 *SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN = *Geo::OSRc::SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN;
@@ -344,6 +354,8 @@ package Geo::OSR;
 *SRS_UL_CHAIN_CONV = *Geo::OSRc::SRS_UL_CHAIN_CONV;
 *SRS_UL_ROD = *Geo::OSRc::SRS_UL_ROD;
 *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_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;
@@ -359,6 +371,107 @@ package Geo::OSR;
     }
     package Geo::OSR::SpatialReference;
     use strict;
+    use Carp;
+    use vars qw /@PROJECTIONS %PROJECTIONS @PARAMETERS %PARAMETERS/;
+    @PROJECTIONS = qw/
+ALBERS_CONIC_EQUAL_AREA
+AZIMUTHAL_EQUIDISTANT
+CASSINI_SOLDNER
+CYLINDRICAL_EQUAL_AREA
+BONNE
+ECKERT_I
+ECKERT_II
+ECKERT_III
+ECKERT_IV
+ECKERT_V
+ECKERT_VI
+EQUIDISTANT_CONIC
+EQUIRECTANGULAR
+GALL_STEREOGRAPHIC
+GAUSSSCHREIBERTMERCATOR
+GEOSTATIONARY_SATELLITE
+GOODE_HOMOLOSINE
+IGH
+GNOMONIC
+HOTINE_OBLIQUE_MERCATOR
+HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN
+LABORDE_OBLIQUE_MERCATOR
+LAMBERT_CONFORMAL_CONIC_1SP
+LAMBERT_CONFORMAL_CONIC_2SP
+LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM
+LAMBERT_AZIMUTHAL_EQUAL_AREA
+MERCATOR_1SP
+MERCATOR_2SP
+MILLER_CYLINDRICAL
+MOLLWEIDE
+NEW_ZEALAND_MAP_GRID
+OBLIQUE_STEREOGRAPHIC
+ORTHOGRAPHIC
+POLAR_STEREOGRAPHIC
+POLYCONIC
+ROBINSON
+SINUSOIDAL
+STEREOGRAPHIC
+SWISS_OBLIQUE_CYLINDRICAL
+TRANSVERSE_MERCATOR
+TRANSVERSE_MERCATOR_SOUTH_ORIENTED
+TRANSVERSE_MERCATOR_MI_21
+TRANSVERSE_MERCATOR_MI_22
+TRANSVERSE_MERCATOR_MI_23
+TRANSVERSE_MERCATOR_MI_24
+TRANSVERSE_MERCATOR_MI_25
+TUNISIA_MINING_GRID
+TWO_POINT_EQUIDISTANT
+VANDERGRINTEN
+KROVAK
+IMW_POLYCONIC
+WAGNER_I
+WAGNER_II
+WAGNER_III
+WAGNER_IV
+WAGNER_V
+WAGNER_VI
+WAGNER_VII
+/;
+    for my $s (@PROJECTIONS) {
+	my $p = eval "\$Geo::OGR::SRS_PT_$s";
+	$PROJECTIONS{$s} = $p;
+    }
+    @PARAMETERS = qw/
+CENTRAL_MERIDIAN
+SCALE_FACTOR
+STANDARD_PARALLEL_1
+STANDARD_PARALLEL_2
+PSEUDO_STD_PARALLEL_1
+LONGITUDE_OF_CENTER
+LATITUDE_OF_CENTER
+LONGITUDE_OF_ORIGIN
+LATITUDE_OF_ORIGIN
+FALSE_EASTING
+FALSE_NORTHING
+AZIMUTH
+LONGITUDE_OF_POINT_1
+LATITUDE_OF_POINT_1
+LONGITUDE_OF_POINT_2
+LATITUDE_OF_POINT_2
+LONGITUDE_OF_POINT_3
+LATITUDE_OF_POINT_3
+RECTIFIED_GRID_ANGLE
+LANDSAT_NUMBER
+PATH_NUMBER
+PERSPECTIVE_POINT_HEIGHT
+SATELLITE_HEIGHT
+FIPSZONE
+ZONE
+LATITUDE_OF_1ST_POINT
+LONGITUDE_OF_1ST_POINT
+LATITUDE_OF_2ND_POINT
+LONGITUDE_OF_2ND_POINT
+/;
+    for my $s (@PARAMETERS) {
+	my $p = eval "\$Geo::OGR::SRS_PP_$s";
+	$PARAMETERS{$s} = $p;
+    }
     sub create {
 	my $pkg = shift;
 	my %param = @_;
@@ -370,19 +483,213 @@ package Geo::OSR;
 	} elsif ($param{Proj4}) {
 	    ImportFromProj4($self, $param{Proj4});
 	} elsif ($param{ESRI}) {
-	    ImportFromESRI($self, $param{ESRI});
+	    ImportFromESRI($self, @{$param{ESRI}});
 	} elsif ($param{EPSG}) {
 	    ImportFromEPSG($self, $param{EPSG});
+	} elsif ($param{EPSGA}) {
+	    ImportFromEPSGA($self, $param{EPSGA});
 	} elsif ($param{PCI}) {
-	    ImportFromPCI($self, $param{PCI});
+	    ImportFromPCI($self, @{$param{PCI}});
 	} elsif ($param{USGS}) {
-	    ImportFromUSGS($self, $param{USGS});
+	    ImportFromUSGS($self, @{$param{USGS}});
 	} elsif ($param{XML}) {
 	    ImportFromXML($self, $param{XML});
+	} elsif ($param{GML}) {
+	    ImportFromGML($self, $param{GML});
+	} elsif ($param{URL}) {
+	    ImportFromUrl($self, $param{URL});
+	} elsif ($param{ERMapper}) {
+	    ImportFromERM($self, @{$param{ERMapper}} );
+	} elsif ($param{ERM}) {
+	    ImportFromERM($self, @{$param{ERM}} );
+	} elsif ($param{MICoordSys}) {
+	    ImportFromMICoordSys($self, $param{MICoordSys} );
+	} elsif ($param{MapInfoCS}) {
+	    ImportFromMICoordSys($self, $param{MapInfoCS} );
+	} else {
+	    croak "Unrecognized import format for Geo::OSR::SpatialReference.";
 	}
 	bless $self, $pkg if defined $self;
     }
+    sub Export {
+	my $self = shift;
+	my $format = pop if @_ == 1;
+	my %params = @_;
+	$format = $params{to} unless $format;
+	$format = $params{format} unless $format;
+	$format = $params{as} unless $format;
+	if ($format eq 'WKT' or $format eq 'Text') {
+	    return ExportToWkt($self);
+	} elsif ($format eq 'PrettyWKT') {
+	    my $simplify = exists $params{simplify} ? $params{simplify} : 0;
+	    return ExportToPrettyWkt($self, $simplify);
+	} elsif ($format eq 'Proj4') {
+	    return ExportToProj4($self);
+	} elsif ($format eq 'PCI') {	    
+	    return ExportToPCI($self);
+	} elsif ($format eq 'USGS') {
+	    return ExportToUSGS($self);
+	} elsif ($format eq 'GML' or $format eq 'XML') {
+	    my $dialect = exists $params{dialect} ? $params{dialect} : '';
+	    return ExportToXML($self, $dialect);
+	} elsif ($format eq 'MICoordSys' or $format eq 'MapInfoCS') {
+	    return ExportToMICoordSys();
+	} else {
+	    croak "Unrecognized export format for Geo::OSR::SpatialReference.";
+	}
+    }
     *AsText = *ExportToWkt;
+    *As = *Export;
+    sub Set {
+	my($self, %params) = @_;
+	if (exists $params{Authority} and exists $params{Node} and exists $params{Code}) {
+	    SetAuthority($self, $params{TargetKey}, $params{Authority}, $params{Code});
+	} elsif (exists $params{Node} and exists $params{Value}) {
+	    SetAttrValue($self, $params{Node}, $params{Value});
+	} elsif (exists $params{AngularUnits} and exists $params{Value}) {
+	    SetAngularUnits($self, $params{AngularUnits}, $params{Value});
+	} elsif (exists $params{LinearUnits} and exists $params{Node} and exists $params{Value}) {
+	    SetTargetLinearUnits($self, $params{Node}, $params{LinearUnits}, $params{Value});
+	} elsif (exists $params{LinearUnits} and exists $params{Value}) {
+	    SetLinearUnitsAndUpdateParameters($self, $params{LinearUnits}, $params{Value});
+	} elsif ($params{CoordinateSystem} eq 'UTM' and exists $params{Zone} and exists $params{North}) {
+	    my $north = exists $params{North} ? $params{North} : 1;
+	    SetUTM($self, $params{Zone}, $north);
+	} elsif ($params{CoordinateSystem} eq 'State Plane' and exists $params{Zone}) {
+	    my $NAD83 = exists $params{NAD83} ? $params{NAD83} : 1;
+	    my $name = exists $params{UnitName} ? $params{UnitName} : undef;
+	    my $c = exists $params{UnitConversionFactor} ? $params{UnitConversionFactor} : 0.0;
+	    SetStatePlane($self, $params{Zone}, $NAD83, $name, $c);
+	} elsif ($params{Parameter} and exists $params{Value}) {
+	    croak "unknown parameter: $params{Parameter}" unless exists $PARAMETERS{$params{Parameter}};
+	    $params{Normalized} ?
+		SetNormProjParm($self, $params{Parameter}, $params{Value}) :
+		SetProjParm($self, $params{Parameter}, $params{Value});
+	} elsif ($params{Projection}) {
+	    croak "unknown projection: $params{Projection}" unless exists $PROJECTIONS{$params{Projection}};
+	    if (not $params{Parameters}) {
+		SetProjection($self, $PROJECTIONS{$params{Projection}});
+	    } elsif ($params{Projection} eq 'ALBERS_CONIC_EQUAL_AREA' and $params{Parameters}) {
+		SetACEA($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'AZIMUTHAL_EQUIDISTANT' and $params{Parameters}) {
+		SetAE($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'BONNE' and $params{Parameters}) {
+		SetBonne($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'CYLINDRICAL_EQUAL_AREA' and $params{Parameters}) {
+		SetCEA($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'CASSINI_SOLDNER' and $params{Parameters}) {
+		SetCS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'EQUIDISTANT_CONIC' and $params{Parameters}) {
+		SetEC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ECKERT_IV' and $params{Parameters}) {
+		SetEckertIV($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ECKERT_VI' and $params{Parameters}) {
+		SetEckertVI($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'EQUIRECTANGULAR' and $params{Parameters}) {
+		@{$params{Parameters}} == 4 ?
+		    SetEquirectangular($self, @{$params{Parameters}}) :
+		    SetEquirectangular2($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GAUSSSCHREIBERTMERCATOR' and $params{Parameters}) {
+		SetGaussSchreiberTMercator($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GALL_STEREOGRAPHIC' and $params{Parameters}) {
+		SetGS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GOODE_HOMOLOSINE' and $params{Parameters}) {
+		SetGH($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'IGH') {
+		SetIGH($self);
+	    } elsif ($params{Projection} eq 'GEOSTATIONARY_SATELLITE' and $params{Parameters}) {
+		SetGEOS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'GNOMONIC' and $params{Parameters}) {
+		SetGnomonic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'HOTINE_OBLIQUE_MERCATOR' and $params{Parameters}) {
+		SetHOM($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN' and $params{Parameters}) {
+		SetHOM2PNO($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'KROVAK' and $params{Parameters}) {
+		SetKrovak($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_AZIMUTHAL_EQUAL_AREA' and $params{Parameters}) {
+		SetLAEA($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_CONFORMAL_CONIC_2SP' and $params{Parameters}) {
+		SetLCC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_CONFORMAL_CONIC_1SP' and $params{Parameters}) {
+		SetLCC1SP($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM' and $params{Parameters}) {
+		SetLCCB($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'MILLER_CYLINDRICAL' and $params{Parameters}) {
+		SetMC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} =~ /^MERCATOR/ and $params{Parameters}) {
+		SetMercator($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'MOLLWEIDE' and $params{Parameters}) {
+		SetMollweide($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'NEW_ZEALAND_MAP_GRID' and $params{Parameters}) {
+		SetNZMG($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'OBLIQUE_STEREOGRAPHIC' and $params{Parameters}) {
+		SetOS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ORTHOGRAPHIC' and $params{Parameters}) {
+		SetOrthographic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'POLYCONIC' and $params{Parameters}) {
+		SetPolyconic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'POLAR_STEREOGRAPHIC' and $params{Parameters}) {
+		SetPS($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'ROBINSON' and $params{Parameters}) {
+		SetRobinson($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'SINUSOIDAL' and $params{Parameters}) {
+		SetSinusoidal($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'STEREOGRAPHIC' and $params{Parameters}) {
+		SetStereographic($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'SWISS_OBLIQUE_CYLINDRICAL' and $params{Parameters}) {
+		SetSOC($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'TRANSVERSE_MERCATOR_SOUTH_ORIENTED' and $params{Parameters}) {
+		SetTMSO($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} =~ /^TRANSVERSE_MERCATOR/ and $params{Parameters}) {
+		my($variant) = $params{Projection} =~ /^TRANSVERSE_MERCATOR_(\w+)/;
+		$variant = $params{Name} unless $variant;
+		$variant ?
+		    SetTMVariant($self, $variant, @{$params{Parameters}}) :
+		    SetTM($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'TUNISIA_MINING_GRID' and $params{Parameters}) {
+		SetTMG($self, @{$params{Parameters}});
+	    } elsif ($params{Projection} eq 'VANDERGRINTEN' and $params{Parameters}) {
+		SetVDG($self, @{$params{Parameters}});
+	    } elsif ($params{Name}) {
+		SetWellKnownGeogCS($self, $params{Name});
+	    } elsif ($params{GuessFrom}) {
+		SetFromUserInput($self, $params{GuessFrom});
+	    } elsif ($params{CoordinateSystem} eq 'WGS' and $params{Parameters}) {
+		SetTOWGS84($self, @{$params{Parameters}});
+	    } elsif ($params{LOCAL_CS}) {
+		SetLocalCS($self, $params{LOCAL_CS});
+	    } elsif ($params{CoordinateSystem} and $params{Datum} and $params{Spheroid} and $params{Parameters}) {
+		SetGeogCS($self, $params{CoordinateSystem}, $params{Datum}, $params{Spheroid}, @{$params{Parameters}});
+	    } elsif ($params{CoordinateSystem}) {
+		SetProjCS($self, $params{CoordinateSystem});
+	    } elsif ($params{GeocentricCS}) {
+		SetGeocCS($self, $params{GeocentricCS});
+	    } elsif ($params{VerticalCS} and $params{Datum}) {
+		my $type = $params{VertDatumType} || 2005;
+		SetVertCS($self, $params{VerticalCS}, $params{Datum}, $type);
+	    } elsif ($params{CoordinateSystem} and $params{HorizontalCS} and $params{VerticalCS}) {
+		SetCompoundCS($self, $params{CoordinateSystem}, $params{HorizontalCS}, $params{VerticalCS});
+	    } else {
+		croak "Not enough information to set anything in a spatial reference object.";
+	    }
+	}
+    }
+    sub GetUTMZone {
+	my $self = shift;
+	my $zone = _GetUTMZone($self);
+	if (wantarray) {	    
+	    my $north = 1;
+	    if ($zone < 0) {
+		$zone *= -1;
+		$north = 0;
+	    }
+	    return ($zone, $north);
+	} else {
+	    return $zone;
+	}
+    }
+
     package Geo::OSR::CoordinateTransformation;
     use strict;
     sub TransformPoints {
diff --git a/swig/perl/ogr_wrap.cpp b/swig/perl/ogr_wrap.cpp
index 334371e..f1d8757 100644
--- a/swig/perl/ogr_wrap.cpp
+++ b/swig/perl/ogr_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -918,6 +918,7 @@ SWIG_Perl_ErrorType(int code) {
 
 /* for raw pointers */
 #define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
 #define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
 
 /* for raw packed data */
@@ -1134,10 +1135,14 @@ SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
 /* Function for getting a pointer value */
 
 SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
   swig_cast_info *tc;
   void *voidptr = (void *)0;
   SV *tsv = 0;
+
+  if (own)
+    *own = 0;
+
   /* If magical, apply more magic */
   if (SvGMAGICAL(sv))
     mg_get(sv);
@@ -1187,7 +1192,11 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
     {
       int newmemory = 0;
       *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      assert(!newmemory); /* newmemory handling not yet implemented */
+      if (newmemory == SWIG_CAST_NEW_MEMORY) {
+        assert(own);
+        if (own)
+          *own = *own | SWIG_CAST_NEW_MEMORY;
+      }
     }
   } else {
     *ptr = voidptr;
@@ -1217,9 +1226,14 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
   return SWIG_OK;
 }
 
+SWIGRUNTIME int
+SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
+}
+
 SWIGRUNTIME void
 SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & SWIG_SHADOW)) {
+  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
     SV *self;
     SV *obj=newSV(0);
     HV *hash=newHV();
@@ -1394,6 +1408,9 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #ifdef do_close
   #undef do_close
 #endif
+#ifdef do_exec
+  #undef do_exec
+#endif
 #ifdef scalar
   #undef scalar
 #endif
@@ -1526,7 +1543,7 @@ static swig_module_info swig_module = {swig_types, 16, 0, 0, 0, 0};
 #define SWIG_name   "Geo::OGRc::boot_Geo__OGR"
 #define SWIG_prefix "Geo::OGRc::"
 
-#define SWIGVERSION 0x010339 
+#define SWIGVERSION 0x010340 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -1836,6 +1853,14 @@ SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val)
 
 SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_Open(OGRDriverShadow *self,char const *utf8_path,int update=0){
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*) OGR_Dr_Open(self, utf8_path, update);
+    if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
+    {
+        CPLDebug( "SWIG",
+          "OGR_Dr_Open() succeeded, but an error is posted, so we destroy"
+          " the datasource and fail at swig level." );
+        OGRReleaseDataSource(ds);
+        ds = NULL;
+    }
     return ds;
   }
 SWIGINTERN int OGRDriverShadow_DeleteDataSource(OGRDriverShadow *self,char const *utf8_path){
@@ -1917,6 +1942,9 @@ OGRErrMessages( int rc ) {
   }
 }
 
+SWIGINTERN OGRErr OGRDataSourceShadow_SyncToDisk(OGRDataSourceShadow *self){
+    return OGR_DS_SyncToDisk(self);
+  }
 SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_CreateLayer(OGRDataSourceShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
     OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_CreateLayer( self,
 								  name,
@@ -2034,6 +2062,25 @@ SWIGINTERN bool OGRLayerShadow_TestCapability(OGRLayerShadow *self,char const *c
 SWIGINTERN OGRErr OGRLayerShadow_CreateField(OGRLayerShadow *self,OGRFieldDefnShadow *field_def,int approx_ok=1){
     return OGR_L_CreateField(self, field_def, approx_ok);
   }
+SWIGINTERN OGRErr OGRLayerShadow_DeleteField(OGRLayerShadow *self,int iField){
+    return OGR_L_DeleteField(self, iField);
+  }
+SWIGINTERN OGRErr OGRLayerShadow_ReorderField(OGRLayerShadow *self,int iOldFieldPos,int iNewFieldPos){
+    return OGR_L_ReorderField(self, iOldFieldPos, iNewFieldPos);
+  }
+SWIGINTERN OGRErr OGRLayerShadow_ReorderFields(OGRLayerShadow *self,int nList,int *pList){
+    if (nList != OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)))
+    {
+      CPLError(CE_Failure, CPLE_IllegalArg,
+               "List should have %d elements",
+               OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)));
+      return OGRERR_FAILURE;
+    }
+    return OGR_L_ReorderFields(self, pList);
+  }
+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_StartTransaction(OGRLayerShadow *self){
     return OGR_L_StartTransaction(self);
   }
@@ -2138,7 +2185,9 @@ static SV *
 CreateArrayFromStringArray( char **first ) {
   AV *av = (AV*)sv_2mortal((SV*)newAV());
   for( unsigned int i = 0; *first != NULL; i++ ) {
-    av_store(av,i,newSVpv(*first, strlen(*first)));
+    SV *sv = newSVpv(*first, strlen(*first));
+    SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+    av_store(av,i,sv);
     ++first;
   }
   return newRV_noinc((SV*)av);
@@ -2352,7 +2401,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 
   OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
                                       reference,
                                       &geom,
@@ -2368,7 +2417,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 
   OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
                                       OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkt(val,
                                       reference,
                                       &geom);
@@ -2412,7 +2461,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
     return NULL;
   }
 
-  return hPolygon;
+  return (OGRGeometryShadow* )hPolygon;
   }
 
 
@@ -2422,7 +2471,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
         double dfStartAngle, double dfEndAngle,
         double dfMaxAngleStepSizeDegrees ) {
   
-  return OGR_G_ApproximateArcAngles( 
+  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
              dfCenterX, dfCenterY, dfZ, 
              dfPrimaryRadius, dfSecondaryAxis, dfRotation,
              dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
@@ -2432,28 +2481,28 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 OGRGeometryShadow* ForceToPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiPoint( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiLineString( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
 }
 
 SWIGINTERN void delete_OGRGeometryShadow(OGRGeometryShadow *self){
@@ -2492,8 +2541,8 @@ SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToGML(OGRGeometryShadow
 SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToKML(OGRGeometryShadow *self,char const *altitude_mode=NULL){
     return (retStringAndCPLFree *) OGR_G_ExportToKML(self, altitude_mode);
   }
-SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow *self){
-    return (retStringAndCPLFree *) OGR_G_ExportToJson(self);
+SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow *self,char **options=0){
+    return (retStringAndCPLFree *) OGR_G_ExportToJsonEx(self, options);
   }
 SWIGINTERN void OGRGeometryShadow_AddPoint(OGRGeometryShadow *self,double x,double y,double z=0){
     OGR_G_AddPoint( self, x, y, z );
@@ -2560,6 +2609,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_GetGeometryRef(OGRGeometryShadow
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Simplify(OGRGeometryShadow *self,double tolerance){
     return (OGRGeometryShadow*) OGR_G_Simplify(self, tolerance);
   }
+SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SimplifyPreserveTopology(OGRGeometryShadow *self,double tolerance){
+    return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Boundary(OGRGeometryShadow *self){
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
   }
@@ -2665,6 +2717,9 @@ SWIGINTERN void OGRGeometryShadow_Segmentize(OGRGeometryShadow *self,double dfMa
 SWIGINTERN void OGRGeometryShadow_GetEnvelope(OGRGeometryShadow *self,double argout[4]){
     OGR_G_GetEnvelope(self, (OGREnvelope*)argout);
   }
+SWIGINTERN void OGRGeometryShadow_GetEnvelope3D(OGRGeometryShadow *self,double argout[6]){
+    OGR_G_GetEnvelope3D(self, (OGREnvelope3D*)argout);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Centroid(OGRGeometryShadow *self){
     OGRGeometryShadow *pt = (OGRGeometryShadow*) OGR_G_CreateGeometry( wkbPoint );
     OGR_G_Centroid( self, pt );
@@ -2878,7 +2933,13 @@ XS(_wrap_Driver_name_get) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -2895,9 +2956,6 @@ XS(_wrap_Driver_CreateDataSource) {
     char **arg3 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     OGRDataSourceShadow *result = 0 ;
     dXSARGS;
@@ -2910,11 +2968,11 @@ XS(_wrap_Driver_CreateDataSource) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_CreateDataSource" "', 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_CreateDataSource" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     if (items > 2) {
       {
         /* %typemap(in) char **options */
@@ -2923,7 +2981,9 @@ XS(_wrap_Driver_CreateDataSource) {
             if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -2934,6 +2994,7 @@ XS(_wrap_Driver_CreateDataSource) {
               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
@@ -2974,7 +3035,6 @@ XS(_wrap_Driver_CreateDataSource) {
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     {
       /* %typemap(freearg) char **options */
       if (arg3) CSLDestroy( arg3 );
@@ -2982,7 +3042,6 @@ XS(_wrap_Driver_CreateDataSource) {
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     {
       /* %typemap(freearg) char **options */
       if (arg3) CSLDestroy( arg3 );
@@ -3002,9 +3061,6 @@ XS(_wrap_Driver_CopyDataSource) {
     int res1 = 0 ;
     void *argp2 = 0 ;
     int res2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
     int argvi = 0;
     OGRDataSourceShadow *result = 0 ;
     dXSARGS;
@@ -3022,11 +3078,11 @@ XS(_wrap_Driver_CopyDataSource) {
       SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Driver_CopyDataSource" "', argument " "2"" of type '" "OGRDataSourceShadow *""'"); 
     }
     arg2 = reinterpret_cast< OGRDataSourceShadow * >(argp2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Driver_CopyDataSource" "', argument " "3"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(2));
+      arg3 = SvPV_nolen(ST(2));
     }
-    arg3 = reinterpret_cast< char * >(buf3);
     if (items > 3) {
       {
         /* %typemap(in) char **options */
@@ -3035,7 +3091,9 @@ XS(_wrap_Driver_CopyDataSource) {
             if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -3046,6 +3104,7 @@ XS(_wrap_Driver_CopyDataSource) {
               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
@@ -3087,7 +3146,6 @@ XS(_wrap_Driver_CopyDataSource) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     {
       /* %typemap(freearg) char **options */
       if (arg4) CSLDestroy( arg4 );
@@ -3096,7 +3154,6 @@ XS(_wrap_Driver_CopyDataSource) {
   fail:
     
     
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     {
       /* %typemap(freearg) char **options */
       if (arg4) CSLDestroy( arg4 );
@@ -3113,9 +3170,6 @@ XS(_wrap_Driver_Open) {
     int arg3 = (int) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -3130,11 +3184,11 @@ XS(_wrap_Driver_Open) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_Open" "', 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_Open" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     if (items > 2) {
       ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
       if (!SWIG_IsOK(ecode3)) {
@@ -3173,12 +3227,10 @@ XS(_wrap_Driver_Open) {
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -3191,9 +3243,6 @@ XS(_wrap_Driver_DeleteDataSource) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     int result;
     dXSARGS;
@@ -3206,11 +3255,11 @@ XS(_wrap_Driver_DeleteDataSource) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_DeleteDataSource" "', 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_DeleteDataSource" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       /* %typemap(check) (const char *utf8_path) */
       if (!arg2)
@@ -3242,11 +3291,9 @@ XS(_wrap_Driver_DeleteDataSource) {
     }
     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();
   }
 }
@@ -3319,7 +3366,7 @@ XS(_wrap_Driver__TestCapability) {
 }
 
 
-XS(_wrap_Driver__GetName) {
+XS(_wrap_Driver_GetName) {
   {
     OGRDriverShadow *arg1 = (OGRDriverShadow *) 0 ;
     void *argp1 = 0 ;
@@ -3329,11 +3376,11 @@ XS(_wrap_Driver__GetName) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Driver__GetName(self);");
+      SWIG_croak("Usage: Driver_GetName(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__GetName" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Driver_GetName" "', argument " "1"" of type '" "OGRDriverShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRDriverShadow * >(argp1);
     {
@@ -3360,7 +3407,13 @@ XS(_wrap_Driver__GetName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -3511,7 +3564,13 @@ XS(_wrap_DataSource_name_get) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -3775,7 +3834,7 @@ XS(_wrap_DataSource__GetDriver) {
 }
 
 
-XS(_wrap_DataSource__GetName) {
+XS(_wrap_DataSource_GetName) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
     void *argp1 = 0 ;
@@ -3785,11 +3844,11 @@ XS(_wrap_DataSource__GetName) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: DataSource__GetName(self);");
+      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__GetName" "', 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);
     {
@@ -3816,7 +3875,13 @@ XS(_wrap_DataSource__GetName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -3894,6 +3959,64 @@ XS(_wrap_DataSource__DeleteLayer) {
 }
 
 
+XS(_wrap_DataSource_SyncToDisk) {
+  {
+    OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: DataSource_SyncToDisk(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_SyncToDisk" "', argument " "1"" of type '" "OGRDataSourceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRDataSourceShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (OGRErr)OGRDataSourceShadow_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_DataSource__CreateLayer) {
   {
     OGRDataSourceShadow *arg1 = (OGRDataSourceShadow *) 0 ;
@@ -3903,9 +4026,6 @@ XS(_wrap_DataSource__CreateLayer) {
     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 ;
@@ -3922,11 +4042,11 @@ XS(_wrap_DataSource__CreateLayer) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__CreateLayer" "', 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__CreateLayer" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     if (items > 2) {
       res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
       if (!SWIG_IsOK(res3)) {
@@ -3949,7 +4069,9 @@ XS(_wrap_DataSource__CreateLayer) {
             if (SvTYPE(SvRV(ST(4)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -3960,6 +4082,7 @@ XS(_wrap_DataSource__CreateLayer) {
               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
@@ -4000,7 +4123,6 @@ XS(_wrap_DataSource__CreateLayer) {
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     
     {
@@ -4010,7 +4132,6 @@ XS(_wrap_DataSource__CreateLayer) {
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     
     {
@@ -4065,7 +4186,9 @@ XS(_wrap_DataSource_CopyLayer) {
             if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -4076,6 +4199,7 @@ XS(_wrap_DataSource_CopyLayer) {
               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
@@ -4205,9 +4329,6 @@ XS(_wrap_DataSource__GetLayerByName) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     OGRLayerShadow *result = 0 ;
     dXSARGS;
@@ -4220,11 +4341,11 @@ XS(_wrap_DataSource__GetLayerByName) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "DataSource__GetLayerByName" "', 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__GetLayerByName" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %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 = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
@@ -4251,11 +4372,9 @@ XS(_wrap_DataSource__GetLayerByName) {
     }
     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();
   }
 }
@@ -4849,7 +4968,7 @@ XS(_wrap_Layer_ResetReading) {
 }
 
 
-XS(_wrap_Layer__GetName) {
+XS(_wrap_Layer_GetName) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
     void *argp1 = 0 ;
@@ -4859,11 +4978,11 @@ XS(_wrap_Layer__GetName) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Layer__GetName(self);");
+      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__GetName" "', 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);
     {
@@ -4890,7 +5009,13 @@ XS(_wrap_Layer__GetName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -4992,7 +5117,13 @@ XS(_wrap_Layer_GetGeometryColumn) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -5043,7 +5174,13 @@ XS(_wrap_Layer_GetFIDColumn) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -5686,8 +5823,16 @@ XS(_wrap_Layer_GetExtent) {
     }
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 4 );
-      argvi++;
+      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++;
+      }  
     }
     
     
@@ -5854,6 +5999,327 @@ XS(_wrap_Layer_CreateField) {
 }
 
 
+XS(_wrap_Layer_DeleteField) {
+  {
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 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: 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_DeleteField" "', 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);
+      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_ReorderField) {
+  {
+    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;
+    dXSARGS;
+    
+    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_ReorderField" "', 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);
+      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_ReorderFields) {
+  {
+    OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+    int arg2 ;
+    int *arg3 = (int *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Layer_ReorderFields(self,nList,pList);");
+    }
+    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 *""'"); 
+    }
+    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");
+      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);
+      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 (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) {
+  {
+    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;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 4) || (items > 4)) {
+      SWIG_croak("Usage: Layer_AlterFieldDefn(self,iField,field_def,nFlags);");
+    }
+    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 *""'"); 
+    }
+    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() );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /* 
+          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_StartTransaction) {
   {
     OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
@@ -6160,7 +6626,9 @@ XS(_wrap_Layer_SetIgnoredFields) {
           if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
-              char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+              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) {
@@ -6171,6 +6639,7 @@ XS(_wrap_Layer_SetIgnoredFields) {
             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
@@ -6815,9 +7284,6 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     OGRFieldDefnShadow *result = 0 ;
     dXSARGS;
@@ -6830,11 +7296,11 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', 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_GetFieldDefnRef" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -6866,11 +7332,9 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
@@ -7005,7 +7469,13 @@ XS(_wrap_Feature_GetFieldAsString) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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);
@@ -7571,9 +8041,6 @@ XS(_wrap_Feature_IsFieldSet__SWIG_1) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     bool result;
     dXSARGS;
@@ -7586,11 +8053,11 @@ XS(_wrap_Feature_IsFieldSet__SWIG_1) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', 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_IsFieldSet" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -7622,11 +8089,9 @@ XS(_wrap_Feature_IsFieldSet__SWIG_1) {
     }
     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();
   }
 }
@@ -7718,9 +8183,6 @@ XS(_wrap_Feature_GetFieldIndex) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     int result;
     dXSARGS;
@@ -7733,11 +8195,11 @@ XS(_wrap_Feature_GetFieldIndex) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', 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_GetFieldIndex" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -7769,11 +8231,9 @@ XS(_wrap_Feature_GetFieldIndex) {
     }
     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();
   }
 }
@@ -8035,6 +8495,7 @@ XS(_wrap_Feature__SetField__SWIG_0) {
     arg2 = static_cast< int >(val2);
     {
       /* %typemap(in) (tostring argin) */
+      sv_utf8_upgrade(ST(2)); /* GDAL expects UTF-8 */
       arg3 = SvPV_nolen( ST(2) ); 
     }
     {
@@ -8791,7 +9252,9 @@ XS(_wrap_Feature_SetFieldStringList) {
           if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
             AV *av = (AV*)(SvRV(ST(2)));
             for (int i = 0; i < av_len(av)+1; i++) {
-              char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+              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) {
@@ -8802,6 +9265,7 @@ XS(_wrap_Feature_SetFieldStringList) {
             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
@@ -8854,7 +9318,7 @@ XS(_wrap_Feature_SetFieldStringList) {
 }
 
 
-XS(_wrap_Feature_SetFrom) {
+XS(_wrap_Feature__SetFrom) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     OGRFeatureShadow *arg2 = (OGRFeatureShadow *) 0 ;
@@ -8870,22 +9334,22 @@ XS(_wrap_Feature_SetFrom) {
     dXSARGS;
     
     if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFrom(self,other,forgiving);");
+      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 *""'"); 
+      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 *""'"); 
+      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""'");
+        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetFrom" "', argument " "3"" of type '" "int""'");
       } 
       arg3 = static_cast< int >(val3);
     }
@@ -9087,7 +9551,13 @@ XS(_wrap_Feature_GetStyleString) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -9225,9 +9695,6 @@ XS(_wrap_Feature__GetFieldType__SWIG_1) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     OGRFieldType result;
     dXSARGS;
@@ -9240,11 +9707,11 @@ XS(_wrap_Feature__GetFieldType__SWIG_1) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__GetFieldType" "', 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__GetFieldType" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -9276,11 +9743,9 @@ XS(_wrap_Feature__GetFieldType__SWIG_1) {
     }
     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();
   }
 }
@@ -9470,7 +9935,7 @@ XS(_wrap_new_FeatureDefn) {
 }
 
 
-XS(_wrap_FeatureDefn__GetName) {
+XS(_wrap_FeatureDefn_GetName) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     void *argp1 = 0 ;
@@ -9480,11 +9945,11 @@ XS(_wrap_FeatureDefn__GetName) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn__GetName(self);");
+      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 *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetName" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
@@ -9511,7 +9976,13 @@ XS(_wrap_FeatureDefn__GetName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -9639,9 +10110,6 @@ XS(_wrap_FeatureDefn_GetFieldIndex) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     int result;
     dXSARGS;
@@ -9654,11 +10122,11 @@ XS(_wrap_FeatureDefn_GetFieldIndex) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -9690,11 +10158,9 @@ XS(_wrap_FeatureDefn_GetFieldIndex) {
     }
     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();
   }
 }
@@ -10265,7 +10731,7 @@ XS(_wrap_new_FieldDefn) {
 }
 
 
-XS(_wrap_FieldDefn__GetName) {
+XS(_wrap_FieldDefn_GetName) {
   {
     OGRFieldDefnShadow *arg1 = (OGRFieldDefnShadow *) 0 ;
     void *argp1 = 0 ;
@@ -10275,11 +10741,11 @@ XS(_wrap_FieldDefn__GetName) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FieldDefn__GetName(self);");
+      SWIG_croak("Usage: FieldDefn_GetName(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_GetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
     {
@@ -10306,7 +10772,13 @@ XS(_wrap_FieldDefn__GetName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -10357,7 +10829,13 @@ XS(_wrap_FieldDefn_GetNameRef) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -10373,9 +10851,6 @@ XS(_wrap_FieldDefn_SetName) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
@@ -10387,11 +10862,11 @@ XS(_wrap_FieldDefn_SetName) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FieldDefn_SetName" "', argument " "1"" of type '" "OGRFieldDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFieldDefnShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "FieldDefn_SetName" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -10423,11 +10898,9 @@ XS(_wrap_FieldDefn_SetName) {
     }
     ST(argvi) = sv_newmortal();
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
@@ -10918,7 +11391,13 @@ XS(_wrap_FieldDefn_GetTypeName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -10977,7 +11456,13 @@ XS(_wrap_FieldDefn_GetFieldTypeName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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);
@@ -11184,6 +11669,7 @@ XS(_wrap_CreateGeometryFromWkt) {
     }
     {
       /* %typemap(in) (char **ignorechange) */
+      sv_utf8_upgrade(ST(0)); /* GDAL expects UTF-8 */
       val1 = SvPV_nolen(ST(0));
       arg1 = &val1;
     }
@@ -11960,8 +12446,10 @@ XS(_wrap_Geometry_ExportToWkt) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     
@@ -12105,7 +12593,9 @@ XS(_wrap_Geometry_ExportToGML) {
             if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
-                char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+                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) {
@@ -12116,6 +12606,7 @@ XS(_wrap_Geometry_ExportToGML) {
               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
@@ -12258,23 +12749,55 @@ XS(_wrap_Geometry_ExportToKML) {
 XS(_wrap_Geometry_ExportToJson) {
   {
     OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+    char **arg2 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
     retStringAndCPLFree *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Geometry_ExportToJson(self);");
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: Geometry_ExportToJson(self,options);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToJson" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+    if (items > 1) {
+      {
+        /* %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("'options' is not a reference to an array or hash");
+          } else
+          SWIG_croak("'options' is not a reference");   
+        }
+      }
+    }
     {
       CPLErrorReset();
-      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1);
+      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -12310,9 +12833,17 @@ XS(_wrap_Geometry_ExportToJson) {
     argvi++ ;
     
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg2) CSLDestroy( arg2 );
+    }
     XSRETURN(argvi);
   fail:
     
+    {
+      /* %typemap(freearg) char **options */
+      if (arg2) CSLDestroy( arg2 );
+    }
     SWIG_croak_null();
   }
 }
@@ -12757,7 +13288,13 @@ XS(_wrap_Geometry_GetGeometryName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -13219,8 +13756,16 @@ XS(_wrap_Geometry_GetPoint_3D) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg3, 3 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+3-items+1);
+        for (i = 0; i < 3; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg3, 3 );
+        argvi++;
+      }  
     }
     
     
@@ -13294,8 +13839,16 @@ XS(_wrap_Geometry_GetPoint_2D) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg3, 2 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+2-items+1);
+        for (i = 0; i < 2; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg3[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg3, 2 );
+        argvi++;
+      }  
     }
     
     
@@ -13655,6 +14208,67 @@ XS(_wrap_Geometry_Simplify) {
 }
 
 
+XS(_wrap_Geometry_SimplifyPreserveTopology) {
+  {
+    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+    double arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    double val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    OGRGeometryShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Geometry_SimplifyPreserveTopology(self,tolerance);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SimplifyPreserveTopology" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRGeometryShadow * >(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 '" "Geometry_SimplifyPreserveTopology" "', argument " "2"" of type '" "double""'");
+    } 
+    arg2 = static_cast< double >(val2);
+    {
+      CPLErrorReset();
+      result = (OGRGeometryShadow *)OGRGeometryShadow_SimplifyPreserveTopology(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, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_Geometry_Boundary) {
   {
     OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -15708,8 +16322,87 @@ XS(_wrap_Geometry_GetEnvelope) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 4 );
-      argvi++;
+      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:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Geometry_GetEnvelope3D) {
+  {
+    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+    double *arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    double argout2[6] ;
+    int argvi = 0;
+    dXSARGS;
+    
+    {
+      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+      arg2 = argout2;
+    }
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Geometry_GetEnvelope3D(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetEnvelope3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+    {
+      CPLErrorReset();
+      OGRGeometryShadow_GetEnvelope3D(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) = sv_newmortal();
+    {
+      /* %typemap(argout) (double argout[ANY]) */
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+6-items+1);
+        for (i = 0; i < 6; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 6 );
+        argvi++;
+      }  
     }
     
     
@@ -16289,7 +16982,13 @@ XS(_wrap_GeometryTypeToName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -16340,7 +17039,13 @@ XS(_wrap_GetFieldTypeName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -16405,9 +17110,6 @@ XS(_wrap_Open) {
   {
     char *arg1 = (char *) 0 ;
     int arg2 = (int) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
@@ -16417,11 +17119,11 @@ XS(_wrap_Open) {
     if ((items < 1) || (items > 2)) {
       SWIG_croak("Usage: Open(utf8_path,update);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Open" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     if (items > 1) {
       ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
       if (!SWIG_IsOK(ecode2)) {
@@ -16459,11 +17161,9 @@ XS(_wrap_Open) {
       
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
@@ -16474,9 +17174,6 @@ XS(_wrap_OpenShared) {
   {
     char *arg1 = (char *) 0 ;
     int arg2 = (int) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
@@ -16486,11 +17183,11 @@ XS(_wrap_OpenShared) {
     if ((items < 1) || (items > 2)) {
       SWIG_croak("Usage: OpenShared(utf8_path,update);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "OpenShared" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* utf8_path) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     if (items > 1) {
       ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
       if (!SWIG_IsOK(ecode2)) {
@@ -16528,11 +17225,9 @@ XS(_wrap_OpenShared) {
       
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDataSourceShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     
     SWIG_croak_null();
   }
@@ -16542,9 +17237,6 @@ XS(_wrap_OpenShared) {
 XS(_wrap_GetDriverByName) {
   {
     char *arg1 = (char *) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     int argvi = 0;
     OGRDriverShadow *result = 0 ;
     dXSARGS;
@@ -16552,11 +17244,11 @@ XS(_wrap_GetDriverByName) {
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: GetDriverByName(name);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetDriverByName" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -16587,10 +17279,8 @@ XS(_wrap_GetDriverByName) {
       
     }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     SWIG_croak_null();
   }
 }
@@ -16667,7 +17357,9 @@ XS(_wrap_GeneralCmdLineProcessor) {
           if (SvTYPE(SvRV(ST(0)))==SVt_PVAV) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
-              char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+              SV *sv = *(av_fetch(av, i, 0));
+              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
+              char *pszItem = SvPV_nolen(sv);
               arg1 = CSLAddString( arg1, pszItem );
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
@@ -16678,6 +17370,7 @@ XS(_wrap_GeneralCmdLineProcessor) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv,&key,&klen)) {
+              sv_utf8_upgrade(sv); /* GDAL expects UTF-8 */
               arg1 = CSLAddNameValue( arg1, key, SvPV_nolen(sv) );
             }
           } else
@@ -16724,9 +17417,10 @@ XS(_wrap_GeneralCmdLineProcessor) {
       if ( stringarray != NULL ) {
         int n = CSLCount( stringarray );
         for ( int i = 0; i < n; i++ ) {
-          SV *s = newSVpv(stringarray[i], 0);
-          if (!av_store(av, i, s))
-          SvREFCNT_dec(s);
+          SV *sv = newSVpv(stringarray[i], 0);
+          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
+          if (!av_store(av, i, sv))
+          SvREFCNT_dec(sv);
         }
       }
       ST(argvi) = newRV_noinc((SV*)av);
@@ -16845,7 +17539,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Driver_Open", _wrap_Driver_Open},
 {"Geo::OGRc::Driver_DeleteDataSource", _wrap_Driver_DeleteDataSource},
 {"Geo::OGRc::Driver__TestCapability", _wrap_Driver__TestCapability},
-{"Geo::OGRc::Driver__GetName", _wrap_Driver__GetName},
+{"Geo::OGRc::Driver_GetName", _wrap_Driver_GetName},
 {"Geo::OGRc::Driver_Register", _wrap_Driver_Register},
 {"Geo::OGRc::Driver_Deregister", _wrap_Driver_Deregister},
 {"Geo::OGRc::DataSource_name_get", _wrap_DataSource_name_get},
@@ -16854,8 +17548,9 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::DataSource_GetSummaryRefCount", _wrap_DataSource_GetSummaryRefCount},
 {"Geo::OGRc::DataSource_GetLayerCount", _wrap_DataSource_GetLayerCount},
 {"Geo::OGRc::DataSource__GetDriver", _wrap_DataSource__GetDriver},
-{"Geo::OGRc::DataSource__GetName", _wrap_DataSource__GetName},
+{"Geo::OGRc::DataSource_GetName", _wrap_DataSource_GetName},
 {"Geo::OGRc::DataSource__DeleteLayer", _wrap_DataSource__DeleteLayer},
+{"Geo::OGRc::DataSource_SyncToDisk", _wrap_DataSource_SyncToDisk},
 {"Geo::OGRc::DataSource__CreateLayer", _wrap_DataSource__CreateLayer},
 {"Geo::OGRc::DataSource_CopyLayer", _wrap_DataSource_CopyLayer},
 {"Geo::OGRc::DataSource__GetLayerByIndex", _wrap_DataSource__GetLayerByIndex},
@@ -16869,7 +17564,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Layer_GetSpatialFilter", _wrap_Layer_GetSpatialFilter},
 {"Geo::OGRc::Layer_SetAttributeFilter", _wrap_Layer_SetAttributeFilter},
 {"Geo::OGRc::Layer_ResetReading", _wrap_Layer_ResetReading},
-{"Geo::OGRc::Layer__GetName", _wrap_Layer__GetName},
+{"Geo::OGRc::Layer_GetName", _wrap_Layer_GetName},
 {"Geo::OGRc::Layer_GetGeomType", _wrap_Layer_GetGeomType},
 {"Geo::OGRc::Layer_GetGeometryColumn", _wrap_Layer_GetGeometryColumn},
 {"Geo::OGRc::Layer_GetFIDColumn", _wrap_Layer_GetFIDColumn},
@@ -16885,6 +17580,10 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Layer_GetExtent", _wrap_Layer_GetExtent},
 {"Geo::OGRc::Layer__TestCapability", _wrap_Layer__TestCapability},
 {"Geo::OGRc::Layer_CreateField", _wrap_Layer_CreateField},
+{"Geo::OGRc::Layer_DeleteField", _wrap_Layer_DeleteField},
+{"Geo::OGRc::Layer_ReorderField", _wrap_Layer_ReorderField},
+{"Geo::OGRc::Layer_ReorderFields", _wrap_Layer_ReorderFields},
+{"Geo::OGRc::Layer_AlterFieldDefn", _wrap_Layer_AlterFieldDefn},
 {"Geo::OGRc::Layer_StartTransaction", _wrap_Layer_StartTransaction},
 {"Geo::OGRc::Layer_CommitTransaction", _wrap_Layer_CommitTransaction},
 {"Geo::OGRc::Layer_RollbackTransaction", _wrap_Layer_RollbackTransaction},
@@ -16918,14 +17617,14 @@ 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_SetFrom", _wrap_Feature_SetFrom},
+{"Geo::OGRc::Feature__SetFrom", _wrap_Feature__SetFrom},
 {"Geo::OGRc::Feature_SetFromWithMap", _wrap_Feature_SetFromWithMap},
 {"Geo::OGRc::Feature_GetStyleString", _wrap_Feature_GetStyleString},
 {"Geo::OGRc::Feature_SetStyleString", _wrap_Feature_SetStyleString},
 {"Geo::OGRc::Feature__GetFieldType", _wrap_Feature__GetFieldType},
 {"Geo::OGRc::delete_FeatureDefn", _wrap_delete_FeatureDefn},
 {"Geo::OGRc::new_FeatureDefn", _wrap_new_FeatureDefn},
-{"Geo::OGRc::FeatureDefn__GetName", _wrap_FeatureDefn__GetName},
+{"Geo::OGRc::FeatureDefn_GetName", _wrap_FeatureDefn_GetName},
 {"Geo::OGRc::FeatureDefn_GetFieldCount", _wrap_FeatureDefn_GetFieldCount},
 {"Geo::OGRc::FeatureDefn_GetFieldDefn", _wrap_FeatureDefn_GetFieldDefn},
 {"Geo::OGRc::FeatureDefn_GetFieldIndex", _wrap_FeatureDefn_GetFieldIndex},
@@ -16939,7 +17638,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::FeatureDefn_SetStyleIgnored", _wrap_FeatureDefn_SetStyleIgnored},
 {"Geo::OGRc::delete_FieldDefn", _wrap_delete_FieldDefn},
 {"Geo::OGRc::new_FieldDefn", _wrap_new_FieldDefn},
-{"Geo::OGRc::FieldDefn__GetName", _wrap_FieldDefn__GetName},
+{"Geo::OGRc::FieldDefn_GetName", _wrap_FieldDefn_GetName},
 {"Geo::OGRc::FieldDefn_GetNameRef", _wrap_FieldDefn_GetNameRef},
 {"Geo::OGRc::FieldDefn_SetName", _wrap_FieldDefn_SetName},
 {"Geo::OGRc::FieldDefn_GetType", _wrap_FieldDefn_GetType},
@@ -16992,6 +17691,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Geometry_SetPoint_2D", _wrap_Geometry_SetPoint_2D},
 {"Geo::OGRc::Geometry_GetGeometryRef", _wrap_Geometry_GetGeometryRef},
 {"Geo::OGRc::Geometry_Simplify", _wrap_Geometry_Simplify},
+{"Geo::OGRc::Geometry_SimplifyPreserveTopology", _wrap_Geometry_SimplifyPreserveTopology},
 {"Geo::OGRc::Geometry_Boundary", _wrap_Geometry_Boundary},
 {"Geo::OGRc::Geometry_GetBoundary", _wrap_Geometry_GetBoundary},
 {"Geo::OGRc::Geometry_ConvexHull", _wrap_Geometry_ConvexHull},
@@ -17026,6 +17726,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Geometry_FlattenTo2D", _wrap_Geometry_FlattenTo2D},
 {"Geo::OGRc::Geometry_Segmentize", _wrap_Geometry_Segmentize},
 {"Geo::OGRc::Geometry_GetEnvelope", _wrap_Geometry_GetEnvelope},
+{"Geo::OGRc::Geometry_GetEnvelope3D", _wrap_Geometry_GetEnvelope3D},
 {"Geo::OGRc::Geometry_Centroid", _wrap_Geometry_Centroid},
 {"Geo::OGRc::Geometry_WkbSize", _wrap_Geometry_WkbSize},
 {"Geo::OGRc::Geometry_GetCoordinateDimension", _wrap_Geometry_GetCoordinateDimension},
@@ -17338,267 +18039,302 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   }
   
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkb25DBit", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000000)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkb25Bit", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000000)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbUnknown", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbPoint", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbLineString", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbPolygon", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(3)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPoint", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(4)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbMultiLineString", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(5)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPolygon", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(6)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbGeometryCollection", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(7)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbNone", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(100)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbLinearRing", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(101)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbPoint25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(wkbPoint+wkb25DBit)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbLineString25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(wkbLineString+wkb25DBit)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbPolygon25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(wkbPolygon+wkb25DBit)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPoint25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(wkbMultiPoint+wkb25DBit)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbMultiLineString25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(wkbMultiLineString+wkb25DBit)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbMultiPolygon25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(wkbMultiPolygon+wkb25DBit)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbGeometryCollection25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(wkbGeometryCollection+wkb25DBit)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTInteger", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTIntegerList", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTReal", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTRealList", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(3)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTString", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(4)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTStringList", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(5)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTWideString", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(6)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTWideStringList", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(7)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTBinary", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(8)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTDate", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(9)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTTime", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(10)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OFTDateTime", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(11)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OJUndefined", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OJLeft", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OJRight", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbXDR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbNDR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "NullFID", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(-1)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "ALTER_NAME_FLAG", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "ALTER_TYPE_FLAG", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "ALTER_WIDTH_PRECISION_FLAG", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(4)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "ALTER_ALL_FLAG", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1+2+4)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCRandomRead", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("RandomRead"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCSequentialWrite", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("SequentialWrite"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCRandomWrite", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("RandomWrite"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCFastSpatialFilter", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("FastSpatialFilter"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCFastFeatureCount", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("FastFeatureCount"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCFastGetExtent", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("FastGetExtent"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCCreateField", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("CreateField"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "OLCDeleteField", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("DeleteField"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "OLCReorderFields", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("ReorderFields"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "OLCAlterFieldDefn", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("AlterFieldDefn"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCTransactions", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transactions"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCDeleteFeature", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("DeleteFeature"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCFastSetNextByIndex", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("FastSetNextByIndex"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCStringsAsUTF8", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("StringsAsUTF8"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "OLCIgnoreFields", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("IgnoreFields"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/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);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "ODsCDeleteLayer", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("DeleteLayer"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/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);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "ODrCDeleteDataSource", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("DeleteDataSource"));
     SvREADONLY_on(sv);
diff --git a/swig/perl/osr_wrap.cpp b/swig/perl/osr_wrap.cpp
index 27faee4..aa53512 100644
--- a/swig/perl/osr_wrap.cpp
+++ b/swig/perl/osr_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 1.3.39
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -918,6 +918,7 @@ SWIG_Perl_ErrorType(int code) {
 
 /* for raw pointers */
 #define SWIG_ConvertPtr(obj, pp, type, flags)           SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
 #define SWIG_NewPointerObj(p, type, flags)              SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
 
 /* for raw packed data */
@@ -1134,10 +1135,14 @@ SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
 /* Function for getting a pointer value */
 
 SWIGRUNTIME int
-SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
   swig_cast_info *tc;
   void *voidptr = (void *)0;
   SV *tsv = 0;
+
+  if (own)
+    *own = 0;
+
   /* If magical, apply more magic */
   if (SvGMAGICAL(sv))
     mg_get(sv);
@@ -1187,7 +1192,11 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
     {
       int newmemory = 0;
       *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
-      assert(!newmemory); /* newmemory handling not yet implemented */
+      if (newmemory == SWIG_CAST_NEW_MEMORY) {
+        assert(own);
+        if (own)
+          *own = *own | SWIG_CAST_NEW_MEMORY;
+      }
     }
   } else {
     *ptr = voidptr;
@@ -1217,9 +1226,14 @@ SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *
   return SWIG_OK;
 }
 
+SWIGRUNTIME int
+SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+  return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
+}
+
 SWIGRUNTIME void
 SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
-  if (ptr && (flags & SWIG_SHADOW)) {
+  if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
     SV *self;
     SV *obj=newSV(0);
     HV *hash=newHV();
@@ -1394,6 +1408,9 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #ifdef do_close
   #undef do_close
 #endif
+#ifdef do_exec
+  #undef do_exec
+#endif
 #ifdef scalar
   #undef scalar
 #endif
@@ -1518,7 +1535,7 @@ static swig_module_info swig_module = {swig_types, 8, 0, 0, 0, 0};
 #define SWIG_name   "Geo::OSRc::boot_Geo__OSR"
 #define SWIG_prefix "Geo::OSRc::"
 
-#define SWIGVERSION 0x010339 
+#define SWIGVERSION 0x010340 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -1751,15 +1768,27 @@ SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
 SWIGINTERN int OSRSpatialReferenceShadow_IsSameGeogCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
     return OSRIsSameGeogCS( self, rhs );
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsSameVertCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
+    return OSRIsSameVertCS( self, rhs );
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsGeographic(OSRSpatialReferenceShadow *self){
     return OSRIsGeographic(self);
   }
 SWIGINTERN int OSRSpatialReferenceShadow_IsProjected(OSRSpatialReferenceShadow *self){
     return OSRIsProjected(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsCompound(OSRSpatialReferenceShadow *self){
+    return OSRIsCompound(self);
+  }
+SWIGINTERN int OSRSpatialReferenceShadow_IsGeocentric(OSRSpatialReferenceShadow *self){
+    return OSRIsGeocentric(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsLocal(OSRSpatialReferenceShadow *self){
     return OSRIsLocal(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *self){
+    return OSRIsVertical(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
@@ -1907,6 +1936,9 @@ SWIGINTERN double OSRSpatialReferenceShadow_GetAngularUnits(OSRSpatialReferenceS
     // Return code ignored.
     return OSRGetAngularUnits( self, 0 );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target,char const *name,double to_meters){
+    return OSRSetTargetLinearUnits( self, target, name, to_meters );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnits( self, name, to_meters );
   }
@@ -2031,6 +2063,9 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGS(OSRSpatialReferenceShadow *sel
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGH(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
     return OSRSetGH( self, cm, fe, fn );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetIGH(OSRSpatialReferenceShadow *self){
+    return OSRSetIGH( self );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *self,double cm,double satelliteheight,double fe,double fn){
     return OSRSetGEOS( self, cm, satelliteheight,
                        fe, fn );
@@ -2171,6 +2206,15 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeogCS(OSRSpatialReferenceShadow
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
     return OSRSetProjCS( self, name );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeocCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
+    return OSRSetGeocCS( self, name );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVertCS(OSRSpatialReferenceShadow *self,char const *VertCSName="unnamed",char const *VertDatumName="unnamed",int VertDatumType=0){
+    return OSRSetVertCS( self, VertCSName, VertDatumName, VertDatumType );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCompoundCS(OSRSpatialReferenceShadow *self,char const *name,OSRSpatialReferenceShadow *horizcs,OSRSpatialReferenceShadow *vertcs){
+    return OSRSetCompoundCS( self, name, horizcs, vertcs );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromWkt(OSRSpatialReferenceShadow *self,char **ppszInput){
     return OSRImportFromWkt( self, ppszInput );
   }
@@ -2257,15 +2301,21 @@ SWIGINTERN void delete_OSRCoordinateTransformationShadow(OSRCoordinateTransforma
     OCTDestroyCoordinateTransformation( self );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_0(OSRCoordinateTransformationShadow *self,double inout[3]){
+    if (self == NULL)
+        return;
     OCTTransform( self, 1, &inout[0], &inout[1], &inout[2] );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_1(OSRCoordinateTransformationShadow *self,double argout[3],double x,double y,double z=0.0){
+    if (self == NULL)
+        return;
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
     OCTTransform( self, 1, &argout[0], &argout[1], &argout[2] );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoints(OSRCoordinateTransformationShadow *self,int nCount,double *x,double *y,double *z){
+    if (self == NULL)
+        return;
     OCTTransform( self, nCount, x, y, z );
   }
 #ifdef __cplusplus
@@ -2335,9 +2385,6 @@ XS(_wrap_GetWellKnownGeogCSAsWKT) {
   {
     char *arg1 = (char *) 0 ;
     char **arg2 = (char **) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     char *argout2 = 0 ;
     int argvi = 0;
     OGRErr result;
@@ -2350,11 +2397,11 @@ XS(_wrap_GetWellKnownGeogCSAsWKT) {
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: GetWellKnownGeogCSAsWKT(name);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetWellKnownGeogCSAsWKT" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -2395,11 +2442,12 @@ XS(_wrap_GetWellKnownGeogCSAsWKT) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) (char **argout) */
       if ( *arg2 )
@@ -2407,7 +2455,6 @@ XS(_wrap_GetWellKnownGeogCSAsWKT) {
     }
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) (char **argout) */
       if ( *arg2 )
@@ -2422,9 +2469,6 @@ XS(_wrap_GetUserInputAsWKT) {
   {
     char *arg1 = (char *) 0 ;
     char **arg2 = (char **) 0 ;
-    int res1 ;
-    char *buf1 = 0 ;
-    int alloc1 = 0 ;
     char *argout2 = 0 ;
     int argvi = 0;
     OGRErr result;
@@ -2437,11 +2481,11 @@ XS(_wrap_GetUserInputAsWKT) {
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: GetUserInputAsWKT(name);");
     }
-    res1 = SWIG_AsCharPtrAndSize(ST(0), &buf1, NULL, &alloc1);
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetUserInputAsWKT" "', argument " "1"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(0));
+      arg1 = SvPV_nolen(ST(0));
     }
-    arg1 = reinterpret_cast< char * >(buf1);
     {
       if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -2482,11 +2526,12 @@ XS(_wrap_GetUserInputAsWKT) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) (char **argout) */
       if ( *arg2 )
@@ -2494,7 +2539,6 @@ XS(_wrap_GetUserInputAsWKT) {
     }
     XSRETURN(argvi);
   fail:
-    if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) (char **argout) */
       if ( *arg2 )
@@ -2544,9 +2588,10 @@ XS(_wrap_GetProjectionMethods) {
         if (result) {
           int i;
           for (i = 0; result[i]; i++) {
-            if (i>items-1) EXTEND(SP, 1);
-            ST(argvi) = sv_2mortal(newSVpv(result[i], 0));
-            argvi++;
+            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);
         }
@@ -2555,9 +2600,10 @@ XS(_wrap_GetProjectionMethods) {
         if (result) {
           int i;
           for (i = 0; result[i]; i++) {
-            SV *s = newSVpv(result[i], 0);
-            if (!av_store(av, i, s))
-            SvREFCNT_dec(s);
+            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);
         }
@@ -2631,9 +2677,10 @@ XS(_wrap_GetProjectionMethodParameterList) {
       if (result) {
         int i;
         for (i = 0; result[i]; i++) {
-          SV *s = newSVpv(result[i], 0);
-          if (!av_store(av, i, s))
-          SvREFCNT_dec(s);
+          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);
       }
@@ -2643,8 +2690,10 @@ XS(_wrap_GetProjectionMethodParameterList) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -2733,15 +2782,19 @@ XS(_wrap_GetProjectionMethodParamInfo) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg3 )
-      sv_setpv(ST(argvi), *arg3);
+      if ( arg3 ) {
+        sv_setpv(ST(argvi), *arg3);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg4 )
-      sv_setpv(ST(argvi), *arg4);
+      if ( arg4 ) {
+        sv_setpv(ST(argvi), *arg4);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     if (SWIG_IsTmpObj(res5)) {
@@ -3066,6 +3119,72 @@ XS(_wrap_SpatialReference_IsSameGeogCS) {
 }
 
 
+XS(_wrap_SpatialReference_IsSameVertCS) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: SpatialReference_IsSameVertCS(self,rhs);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_IsSameVertCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_IsSameVertCS" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (int)OSRSpatialReferenceShadow_IsSameVertCS(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_SpatialReference_IsGeographic) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -3168,6 +3287,108 @@ XS(_wrap_SpatialReference_IsProjected) {
 }
 
 
+XS(_wrap_SpatialReference_IsCompound) {
+  {
+    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_IsCompound(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_IsCompound" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OSRSpatialReferenceShadow_IsCompound(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_IsGeocentric) {
+  {
+    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_IsGeocentric(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_IsGeocentric" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OSRSpatialReferenceShadow_IsGeocentric(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_IsLocal) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -3219,6 +3440,57 @@ XS(_wrap_SpatialReference_IsLocal) {
 }
 
 
+XS(_wrap_SpatialReference_IsVertical) {
+  {
+    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_IsVertical(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_IsVertical" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)OSRSpatialReferenceShadow_IsVertical(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_EPSGTreatsAsLatLong) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -3367,9 +3639,6 @@ XS(_wrap_SpatialReference_GetAttrValue) {
     int arg3 = (int) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -3384,11 +3653,11 @@ XS(_wrap_SpatialReference_GetAttrValue) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetAttrValue" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_GetAttrValue" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     if (items > 2) {
       ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
       if (!SWIG_IsOK(ecode3)) {
@@ -3425,14 +3694,18 @@ XS(_wrap_SpatialReference_GetAttrValue) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -3446,9 +3719,6 @@ XS(_wrap_SpatialReference_SetAttrValue) {
     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 ;
@@ -3464,11 +3734,11 @@ XS(_wrap_SpatialReference_SetAttrValue) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetAttrValue" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetAttrValue" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    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 '" "SpatialReference_SetAttrValue" "', argument " "3"" of type '" "char const *""'");
@@ -3512,12 +3782,10 @@ XS(_wrap_SpatialReference_SetAttrValue) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     SWIG_croak_null();
   }
@@ -3531,9 +3799,6 @@ XS(_wrap_SpatialReference_SetAngularUnits) {
     double arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     double val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -3548,11 +3813,11 @@ XS(_wrap_SpatialReference_SetAngularUnits) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetAngularUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetAngularUnits" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
     if (!SWIG_IsOK(ecode3)) {
       SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetAngularUnits" "', argument " "3"" of type '" "double""'");
@@ -3596,12 +3861,10 @@ XS(_wrap_SpatialReference_SetAngularUnits) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -3659,16 +3922,103 @@ XS(_wrap_SpatialReference_GetAngularUnits) {
 }
 
 
-XS(_wrap_SpatialReference_SetLinearUnits) {
+XS(_wrap_SpatialReference_SetTargetLinearUnits) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
     char *arg2 = (char *) 0 ;
-    double arg3 ;
+    char *arg3 = (char *) 0 ;
+    double arg4 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int res2 ;
     char *buf2 = 0 ;
     int alloc2 = 0 ;
+    double val4 ;
+    int ecode4 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 4) || (items > 4)) {
+      SWIG_croak("Usage: SpatialReference_SetTargetLinearUnits(self,target,name,to_meters);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetTargetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetTargetLinearUnits" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(2));
+      arg3 = SvPV_nolen(ST(2));
+    }
+    ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTargetLinearUnits" "', argument " "4"" of type '" "double""'");
+    } 
+    arg4 = static_cast< double >(val4);
+    {
+      if (!arg3) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRErr)OSRSpatialReferenceShadow_SetTargetLinearUnits(arg1,(char const *)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" );
+      }
+      
+      
+    }
+    {
+      /* %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 (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_SpatialReference_SetLinearUnits) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    double arg3 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
     double val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -3683,11 +4033,11 @@ XS(_wrap_SpatialReference_SetLinearUnits) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetLinearUnits" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
     if (!SWIG_IsOK(ecode3)) {
       SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLinearUnits" "', argument " "3"" of type '" "double""'");
@@ -3731,12 +4081,10 @@ XS(_wrap_SpatialReference_SetLinearUnits) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -3750,9 +4098,6 @@ XS(_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters) {
     double arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     double val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -3767,11 +4112,11 @@ XS(_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLinearUnitsAndUpdateParameters" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetLinearUnitsAndUpdateParameters" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
     if (!SWIG_IsOK(ecode3)) {
       SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetLinearUnitsAndUpdateParameters" "', argument " "3"" of type '" "double""'");
@@ -3815,12 +4160,10 @@ XS(_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -3919,7 +4262,13 @@ XS(_wrap_SpatialReference_GetLinearUnitsName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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:
@@ -3979,7 +4328,13 @@ XS(_wrap_SpatialReference_GetAuthorityCode) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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);
@@ -4041,7 +4396,13 @@ XS(_wrap_SpatialReference_GetAuthorityName) {
       
       
     }
-    ST(argvi) = SWIG_FromCharPtr((const char *)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);
@@ -4133,7 +4494,7 @@ XS(_wrap_SpatialReference_SetUTM) {
 }
 
 
-XS(_wrap_SpatialReference_GetUTMZone) {
+XS(_wrap_SpatialReference__GetUTMZone) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
     void *argp1 = 0 ;
@@ -4143,11 +4504,11 @@ XS(_wrap_SpatialReference_GetUTMZone) {
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetUTMZone(self);");
+      SWIG_croak("Usage: SpatialReference__GetUTMZone(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_GetUTMZone" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference__GetUTMZone" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
     {
@@ -4423,9 +4784,6 @@ XS(_wrap_SpatialReference_SetProjParm) {
     double arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     double val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -4440,11 +4798,11 @@ XS(_wrap_SpatialReference_SetProjParm) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetProjParm" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
     if (!SWIG_IsOK(ecode3)) {
       SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetProjParm" "', argument " "3"" of type '" "double""'");
@@ -4488,12 +4846,10 @@ XS(_wrap_SpatialReference_SetProjParm) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -4507,9 +4863,6 @@ XS(_wrap_SpatialReference_GetProjParm) {
     double arg3 = (double) 0.0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     double val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -4524,11 +4877,11 @@ XS(_wrap_SpatialReference_GetProjParm) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_GetProjParm" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     if (items > 2) {
       ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
       if (!SWIG_IsOK(ecode3)) {
@@ -4567,12 +4920,10 @@ XS(_wrap_SpatialReference_GetProjParm) {
     }
     ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -4586,9 +4937,6 @@ XS(_wrap_SpatialReference_SetNormProjParm) {
     double arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     double val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -4603,11 +4951,11 @@ XS(_wrap_SpatialReference_SetNormProjParm) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetNormProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetNormProjParm" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
     if (!SWIG_IsOK(ecode3)) {
       SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "SpatialReference_SetNormProjParm" "', argument " "3"" of type '" "double""'");
@@ -4651,12 +4999,10 @@ XS(_wrap_SpatialReference_SetNormProjParm) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -4670,9 +5016,6 @@ XS(_wrap_SpatialReference_GetNormProjParm) {
     double arg3 = (double) 0.0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     double val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
@@ -4687,11 +5030,11 @@ XS(_wrap_SpatialReference_GetNormProjParm) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetNormProjParm" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_GetNormProjParm" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     if (items > 2) {
       ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
       if (!SWIG_IsOK(ecode3)) {
@@ -4730,12 +5073,10 @@ XS(_wrap_SpatialReference_GetNormProjParm) {
     }
     ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
     SWIG_croak_null();
   }
@@ -6189,6 +6530,64 @@ XS(_wrap_SpatialReference_SetGH) {
 }
 
 
+XS(_wrap_SpatialReference_SetIGH) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: SpatialReference_SetIGH(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_SetIGH" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (OGRErr)OSRSpatialReferenceShadow_SetIGH(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_SpatialReference_SetGEOS) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -8934,9 +9333,6 @@ XS(_wrap_SpatialReference_SetWellKnownGeogCS) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
@@ -8949,11 +9345,11 @@ XS(_wrap_SpatialReference_SetWellKnownGeogCS) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetWellKnownGeogCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetWellKnownGeogCS" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -8992,11 +9388,9 @@ XS(_wrap_SpatialReference_SetWellKnownGeogCS) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
@@ -9008,9 +9402,6 @@ XS(_wrap_SpatialReference_SetFromUserInput) {
     char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
@@ -9023,11 +9414,11 @@ XS(_wrap_SpatialReference_SetFromUserInput) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetFromUserInput" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetFromUserInput" "', argument " "2"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      sv_utf8_upgrade(ST(1));
+      arg2 = SvPV_nolen(ST(1));
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -9066,11 +9457,9 @@ XS(_wrap_SpatialReference_SetFromUserInput) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
@@ -9228,11 +9617,316 @@ XS(_wrap_SpatialReference_SetTOWGS84) {
       if (!SWIG_IsOK(ecode8)) {
         SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetTOWGS84" "', argument " "8"" of type '" "double""'");
       } 
-      arg8 = static_cast< double >(val8);
+      arg8 = static_cast< double >(val8);
+    }
+    {
+      CPLErrorReset();
+      result = (OGRErr)OSRSpatialReferenceShadow_SetTOWGS84(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+      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_SpatialReference_GetTOWGS84) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    double *arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    double argout2[7] ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    {
+      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+      arg2 = argout2;
+    }
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: SpatialReference_GetTOWGS84(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_GetTOWGS84" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (OGRErr)OSRSpatialReferenceShadow_GetTOWGS84(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) );
+      }
+    }
+    {
+      /* %typemap(argout) (double argout[ANY]) */
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+7-items+1);
+        for (i = 0; i < 7; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 7 );
+        argvi++;
+      }  
+    }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_SpatialReference_SetLocalCS) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: SpatialReference_SetLocalCS(self,pszName);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLocalCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetLocalCS" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+    {
+      CPLErrorReset();
+      result = (OGRErr)OSRSpatialReferenceShadow_SetLocalCS(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) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) SWIG_croak(err); /* this is usually better */
+        SWIG_croak( OGRErrMessages(result) );
+      }
+    }
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    XSRETURN(argvi);
+  fail:
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_SpatialReference_SetGeogCS) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    char *arg3 = (char *) 0 ;
+    char *arg4 = (char *) 0 ;
+    double arg5 ;
+    double arg6 ;
+    char *arg7 = (char *) "Greenwich" ;
+    double arg8 = (double) 0.0 ;
+    char *arg9 = (char *) "degree" ;
+    double arg10 = (double) 0.0174532925199433 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
+    int res3 ;
+    char *buf3 = 0 ;
+    int alloc3 = 0 ;
+    int res4 ;
+    char *buf4 = 0 ;
+    int alloc4 = 0 ;
+    double val5 ;
+    int ecode5 = 0 ;
+    double val6 ;
+    int ecode6 = 0 ;
+    int res7 ;
+    char *buf7 = 0 ;
+    int alloc7 = 0 ;
+    double val8 ;
+    int ecode8 = 0 ;
+    int res9 ;
+    char *buf9 = 0 ;
+    int alloc9 = 0 ;
+    double val10 ;
+    int ecode10 = 0 ;
+    int argvi = 0;
+    OGRErr result;
+    dXSARGS;
+    
+    if ((items < 6) || (items > 10)) {
+      SWIG_croak("Usage: SpatialReference_SetGeogCS(self,pszGeogName,pszDatumName,pszEllipsoidName,dfSemiMajor,dfInvFlattening,pszPMName,dfPMOffset,pszUnits,dfConvertToRadians);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGeogCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetGeogCS" "', argument " "2"" of type '" "char const *""'");
+    }
+    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 '" "SpatialReference_SetGeogCS" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+    res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_SetGeogCS" "', argument " "4"" of type '" "char const *""'");
+    }
+    arg4 = reinterpret_cast< char * >(buf4);
+    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetGeogCS" "', 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 '" "SpatialReference_SetGeogCS" "', argument " "6"" of type '" "double""'");
+    } 
+    arg6 = static_cast< double >(val6);
+    if (items > 6) {
+      res7 = SWIG_AsCharPtrAndSize(ST(6), &buf7, NULL, &alloc7);
+      if (!SWIG_IsOK(res7)) {
+        SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "SpatialReference_SetGeogCS" "', argument " "7"" of type '" "char const *""'");
+      }
+      arg7 = reinterpret_cast< char * >(buf7);
+    }
+    if (items > 7) {
+      ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
+      if (!SWIG_IsOK(ecode8)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetGeogCS" "', argument " "8"" of type '" "double""'");
+      } 
+      arg8 = static_cast< double >(val8);
+    }
+    if (items > 8) {
+      res9 = SWIG_AsCharPtrAndSize(ST(8), &buf9, NULL, &alloc9);
+      if (!SWIG_IsOK(res9)) {
+        SWIG_exception_fail(SWIG_ArgError(res9), "in method '" "SpatialReference_SetGeogCS" "', argument " "9"" of type '" "char const *""'");
+      }
+      arg9 = reinterpret_cast< char * >(buf9);
+    }
+    if (items > 9) {
+      ecode10 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(9), &val10);
+      if (!SWIG_IsOK(ecode10)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "SpatialReference_SetGeogCS" "', argument " "10"" of type '" "double""'");
+      } 
+      arg10 = static_cast< double >(val10);
     }
     {
       CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetTOWGS84(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+      result = (OGRErr)OSRSpatialReferenceShadow_SetGeogCS(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,(char const *)arg7,arg8,(char const *)arg9,arg10);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9263,54 +9957,65 @@ XS(_wrap_SpatialReference_SetTOWGS84) {
       }
     }
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
     
     
+    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
     
-    
-    
-    
+    if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
     
     XSRETURN(argvi);
   fail:
     
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
     
     
+    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
     
-    
-    
-    
+    if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
     
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_SpatialReference_GetTOWGS84) {
+XS(_wrap_SpatialReference_SetProjCS) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    double *arg2 ;
+    char *arg2 = (char *) "unnamed" ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    double argout2[7] ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (double argout2[ANY]) */
-      arg2 = argout2;
-    }
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: SpatialReference_GetTOWGS84(self);");
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: SpatialReference_SetProjCS(self,name);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetTOWGS84" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetProjCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    if (items > 1) {
+      {
+        /* %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 = (OGRErr)OSRSpatialReferenceShadow_GetTOWGS84(arg1,arg2);
+      result = (OGRErr)OSRSpatialReferenceShadow_SetProjCS(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9340,51 +10045,48 @@ XS(_wrap_SpatialReference_GetTOWGS84) {
         SWIG_croak( OGRErrMessages(result) );
       }
     }
-    {
-      /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 7 );
-      argvi++;
-    }
-    
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_SpatialReference_SetLocalCS) {
+XS(_wrap_SpatialReference_SetGeocCS) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    char *arg2 = (char *) "unnamed" ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetLocalCS(self,pszName);");
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: SpatialReference_SetGeocCS(self,name);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetLocalCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGeocCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetLocalCS" "', argument " "2"" of type '" "char const *""'");
+    if (items > 1) {
+      {
+        /* %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.");
+      }
     }
-    arg2 = reinterpret_cast< char * >(buf2);
     {
       CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetLocalCS(arg1,(char const *)arg2);
+      result = (OGRErr)OSRSpatialReferenceShadow_SetGeocCS(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9415,28 +10117,20 @@ XS(_wrap_SpatialReference_SetLocalCS) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_SpatialReference_SetGeogCS) {
+XS(_wrap_SpatialReference_SetVertCS) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char *arg4 = (char *) 0 ;
-    double arg5 ;
-    double arg6 ;
-    char *arg7 = (char *) "Greenwich" ;
-    double arg8 = (double) 0.0 ;
-    char *arg9 = (char *) "degree" ;
-    double arg10 = (double) 0.0174532925199433 ;
+    char *arg2 = (char *) "unnamed" ;
+    char *arg3 = (char *) "unnamed" ;
+    int arg4 = (int) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int res2 ;
@@ -9445,91 +10139,44 @@ XS(_wrap_SpatialReference_SetGeogCS) {
     int res3 ;
     char *buf3 = 0 ;
     int alloc3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    double val5 ;
-    int ecode5 = 0 ;
-    double val6 ;
-    int ecode6 = 0 ;
-    int res7 ;
-    char *buf7 = 0 ;
-    int alloc7 = 0 ;
-    double val8 ;
-    int ecode8 = 0 ;
-    int res9 ;
-    char *buf9 = 0 ;
-    int alloc9 = 0 ;
-    double val10 ;
-    int ecode10 = 0 ;
+    int val4 ;
+    int ecode4 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 6) || (items > 10)) {
-      SWIG_croak("Usage: SpatialReference_SetGeogCS(self,pszGeogName,pszDatumName,pszEllipsoidName,dfSemiMajor,dfInvFlattening,pszPMName,dfPMOffset,pszUnits,dfConvertToRadians);");
+    if ((items < 1) || (items > 4)) {
+      SWIG_croak("Usage: SpatialReference_SetVertCS(self,VertCSName,VertDatumName,VertDatumType);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetGeogCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetVertCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetGeogCS" "', argument " "2"" of type '" "char const *""'");
-    }
-    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 '" "SpatialReference_SetGeogCS" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_SetGeogCS" "', argument " "4"" of type '" "char const *""'");
-    }
-    arg4 = reinterpret_cast< char * >(buf4);
-    ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "SpatialReference_SetGeogCS" "', 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 '" "SpatialReference_SetGeogCS" "', argument " "6"" of type '" "double""'");
-    } 
-    arg6 = static_cast< double >(val6);
-    if (items > 6) {
-      res7 = SWIG_AsCharPtrAndSize(ST(6), &buf7, NULL, &alloc7);
-      if (!SWIG_IsOK(res7)) {
-        SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "SpatialReference_SetGeogCS" "', argument " "7"" of type '" "char const *""'");
+    if (items > 1) {
+      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+      if (!SWIG_IsOK(res2)) {
+        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetVertCS" "', argument " "2"" of type '" "char const *""'");
       }
-      arg7 = reinterpret_cast< char * >(buf7);
-    }
-    if (items > 7) {
-      ecode8 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-      if (!SWIG_IsOK(ecode8)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "SpatialReference_SetGeogCS" "', argument " "8"" of type '" "double""'");
-      } 
-      arg8 = static_cast< double >(val8);
+      arg2 = reinterpret_cast< char * >(buf2);
     }
-    if (items > 8) {
-      res9 = SWIG_AsCharPtrAndSize(ST(8), &buf9, NULL, &alloc9);
-      if (!SWIG_IsOK(res9)) {
-        SWIG_exception_fail(SWIG_ArgError(res9), "in method '" "SpatialReference_SetGeogCS" "', argument " "9"" of type '" "char const *""'");
+    if (items > 2) {
+      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
+      if (!SWIG_IsOK(res3)) {
+        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetVertCS" "', argument " "3"" of type '" "char const *""'");
       }
-      arg9 = reinterpret_cast< char * >(buf9);
+      arg3 = reinterpret_cast< char * >(buf3);
     }
-    if (items > 9) {
-      ecode10 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(9), &val10);
-      if (!SWIG_IsOK(ecode10)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode10), "in method '" "SpatialReference_SetGeogCS" "', argument " "10"" of type '" "double""'");
+    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 '" "SpatialReference_SetVertCS" "', argument " "4"" of type '" "int""'");
       } 
-      arg10 = static_cast< double >(val10);
+      arg4 = static_cast< int >(val4);
     }
     {
       CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetGeogCS(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,(char const *)arg7,arg8,(char const *)arg9,arg10);
+      result = (OGRErr)OSRSpatialReferenceShadow_SetVertCS(arg1,(char const *)arg2,(char const *)arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9562,66 +10209,75 @@ XS(_wrap_SpatialReference_SetGeogCS) {
     
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    
-    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
-    
-    if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
     
     XSRETURN(argvi);
   fail:
     
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    
-    
-    if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
-    
-    if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
     
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_SpatialReference_SetProjCS) {
+XS(_wrap_SpatialReference_SetCompoundCS) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
-    char *arg2 = (char *) "unnamed" ;
+    char *arg2 = (char *) 0 ;
+    OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) 0 ;
+    OSRSpatialReferenceShadow *arg4 = (OSRSpatialReferenceShadow *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
+    void *argp3 = 0 ;
+    int res3 = 0 ;
+    void *argp4 = 0 ;
+    int res4 = 0 ;
     int argvi = 0;
     OGRErr result;
     dXSARGS;
     
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: SpatialReference_SetProjCS(self,name);");
+    if ((items < 4) || (items > 4)) {
+      SWIG_croak("Usage: SpatialReference_SetCompoundCS(self,name,horizcs,vertcs);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetProjCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_SetCompoundCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
     }
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetProjCS" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
+    {
+      /* %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_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetCompoundCS" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
+    res4 = SWIG_ConvertPtr(ST(3), &argp4,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_SetCompoundCS" "', argument " "4"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg4 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp4);
     {
       if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
     {
+      if (!arg3) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      if (!arg4) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
       CPLErrorReset();
-      result = (OGRErr)OSRSpatialReferenceShadow_SetProjCS(arg1,(char const *)arg2);
+      result = (OGRErr)OSRSpatialReferenceShadow_SetCompoundCS(arg1,(char const *)arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -9652,11 +10308,13 @@ XS(_wrap_SpatialReference_SetProjCS) {
       }
     }
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
+    
     XSRETURN(argvi);
   fail:
     
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    
+    
     SWIG_croak_null();
   }
 }
@@ -9683,6 +10341,7 @@ XS(_wrap_SpatialReference_ImportFromWkt) {
     arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
     {
       /* %typemap(in) (char **ignorechange) */
+      sv_utf8_upgrade(ST(1)); /* GDAL expects UTF-8 */
       val2 = SvPV_nolen(ST(1));
       arg2 = &val2;
     }
@@ -9825,6 +10484,11 @@ XS(_wrap_SpatialReference_ImportFromUrl) {
     }
     arg2 = reinterpret_cast< char * >(buf2);
     {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
       CPLErrorReset();
       result = (OGRErr)OSRSpatialReferenceShadow_ImportFromUrl(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
@@ -9892,7 +10556,9 @@ XS(_wrap_SpatialReference_ImportFromESRI) {
           if (SvTYPE(SvRV(ST(1)))==SVt_PVAV) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
-              char *pszItem = SvPV_nolen(*(av_fetch(av, i, 0)));
+              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) {
@@ -9903,6 +10569,7 @@ XS(_wrap_SpatialReference_ImportFromESRI) {
             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
@@ -10418,6 +11085,16 @@ XS(_wrap_SpatialReference_ImportFromERM) {
     }
     arg4 = reinterpret_cast< char * >(buf4);
     {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      if (!arg3) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
       CPLErrorReset();
       result = (OGRErr)OSRSpatialReferenceShadow_ImportFromERM(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
       CPLErr eclass = CPLGetLastErrorType();
@@ -10591,8 +11268,10 @@ XS(_wrap_SpatialReference_ExportToWkt) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     
@@ -10682,8 +11361,10 @@ XS(_wrap_SpatialReference_ExportToPrettyWkt) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     
@@ -10765,8 +11446,10 @@ XS(_wrap_SpatialReference_ExportToProj4) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     
@@ -10858,15 +11541,19 @@ XS(_wrap_SpatialReference_ExportToPCI) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg3 )
-      sv_setpv(ST(argvi), *arg3);
+      if ( arg3 ) {
+        sv_setpv(ST(argvi), *arg3);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     {
@@ -11093,8 +11780,10 @@ XS(_wrap_SpatialReference_ExportToXML) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     
@@ -11176,8 +11865,10 @@ XS(_wrap_SpatialReference_ExportToMICoordSys) {
     {
       /* %typemap(argout) (char **argout) */
       ST(argvi) = sv_newmortal();
-      if ( arg2 )
-      sv_setpv(ST(argvi), *arg2);
+      if ( arg2 ) {
+        sv_setpv(ST(argvi), *arg2);
+        SvUTF8_on(ST(argvi)); /* expecting UTF-8 from GDAL */
+      }
       argvi++;
     }
     
@@ -11828,8 +12519,16 @@ XS(_wrap_CoordinateTransformation_TransformPoint__SWIG_0) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+3-items+1);
+        for (i = 0; i < 3; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
+        argvi++;
+      }  
     }
     
     
@@ -11922,8 +12621,16 @@ XS(_wrap_CoordinateTransformation_TransformPoint__SWIG_1) {
     ST(argvi) = sv_newmortal();
     {
       /* %typemap(argout) (double argout[ANY]) */
-      ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
-      argvi++;
+      if (GIMME_V == G_ARRAY) {
+        /* return a list */
+        int i;
+        EXTEND(SP, argvi+3-items+1);
+        for (i = 0; i < 3; i++)
+        ST(argvi++) = sv_2mortal(newSVnv(arg2[i]));
+      } else {
+        ST(argvi) = CreateArrayFromDoubleArray( arg2, 3 );
+        argvi++;
+      }  
     }
     
     
@@ -12234,15 +12941,20 @@ static swig_command_info swig_commands[] = {
 {"Geo::OSRc::SpatialReference___str__", _wrap_SpatialReference___str__},
 {"Geo::OSRc::SpatialReference_IsSame", _wrap_SpatialReference_IsSame},
 {"Geo::OSRc::SpatialReference_IsSameGeogCS", _wrap_SpatialReference_IsSameGeogCS},
+{"Geo::OSRc::SpatialReference_IsSameVertCS", _wrap_SpatialReference_IsSameVertCS},
 {"Geo::OSRc::SpatialReference_IsGeographic", _wrap_SpatialReference_IsGeographic},
 {"Geo::OSRc::SpatialReference_IsProjected", _wrap_SpatialReference_IsProjected},
+{"Geo::OSRc::SpatialReference_IsCompound", _wrap_SpatialReference_IsCompound},
+{"Geo::OSRc::SpatialReference_IsGeocentric", _wrap_SpatialReference_IsGeocentric},
 {"Geo::OSRc::SpatialReference_IsLocal", _wrap_SpatialReference_IsLocal},
+{"Geo::OSRc::SpatialReference_IsVertical", _wrap_SpatialReference_IsVertical},
 {"Geo::OSRc::SpatialReference_EPSGTreatsAsLatLong", _wrap_SpatialReference_EPSGTreatsAsLatLong},
 {"Geo::OSRc::SpatialReference_SetAuthority", _wrap_SpatialReference_SetAuthority},
 {"Geo::OSRc::SpatialReference_GetAttrValue", _wrap_SpatialReference_GetAttrValue},
 {"Geo::OSRc::SpatialReference_SetAttrValue", _wrap_SpatialReference_SetAttrValue},
 {"Geo::OSRc::SpatialReference_SetAngularUnits", _wrap_SpatialReference_SetAngularUnits},
 {"Geo::OSRc::SpatialReference_GetAngularUnits", _wrap_SpatialReference_GetAngularUnits},
+{"Geo::OSRc::SpatialReference_SetTargetLinearUnits", _wrap_SpatialReference_SetTargetLinearUnits},
 {"Geo::OSRc::SpatialReference_SetLinearUnits", _wrap_SpatialReference_SetLinearUnits},
 {"Geo::OSRc::SpatialReference_SetLinearUnitsAndUpdateParameters", _wrap_SpatialReference_SetLinearUnitsAndUpdateParameters},
 {"Geo::OSRc::SpatialReference_GetLinearUnits", _wrap_SpatialReference_GetLinearUnits},
@@ -12250,7 +12962,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OSRc::SpatialReference_GetAuthorityCode", _wrap_SpatialReference_GetAuthorityCode},
 {"Geo::OSRc::SpatialReference_GetAuthorityName", _wrap_SpatialReference_GetAuthorityName},
 {"Geo::OSRc::SpatialReference_SetUTM", _wrap_SpatialReference_SetUTM},
-{"Geo::OSRc::SpatialReference_GetUTMZone", _wrap_SpatialReference_GetUTMZone},
+{"Geo::OSRc::SpatialReference__GetUTMZone", _wrap_SpatialReference__GetUTMZone},
 {"Geo::OSRc::SpatialReference_SetStatePlane", _wrap_SpatialReference_SetStatePlane},
 {"Geo::OSRc::SpatialReference_AutoIdentifyEPSG", _wrap_SpatialReference_AutoIdentifyEPSG},
 {"Geo::OSRc::SpatialReference_SetProjection", _wrap_SpatialReference_SetProjection},
@@ -12274,6 +12986,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OSRc::SpatialReference_SetGaussSchreiberTMercator", _wrap_SpatialReference_SetGaussSchreiberTMercator},
 {"Geo::OSRc::SpatialReference_SetGS", _wrap_SpatialReference_SetGS},
 {"Geo::OSRc::SpatialReference_SetGH", _wrap_SpatialReference_SetGH},
+{"Geo::OSRc::SpatialReference_SetIGH", _wrap_SpatialReference_SetIGH},
 {"Geo::OSRc::SpatialReference_SetGEOS", _wrap_SpatialReference_SetGEOS},
 {"Geo::OSRc::SpatialReference_SetGnomonic", _wrap_SpatialReference_SetGnomonic},
 {"Geo::OSRc::SpatialReference_SetHOM", _wrap_SpatialReference_SetHOM},
@@ -12308,6 +13021,9 @@ static swig_command_info swig_commands[] = {
 {"Geo::OSRc::SpatialReference_SetLocalCS", _wrap_SpatialReference_SetLocalCS},
 {"Geo::OSRc::SpatialReference_SetGeogCS", _wrap_SpatialReference_SetGeogCS},
 {"Geo::OSRc::SpatialReference_SetProjCS", _wrap_SpatialReference_SetProjCS},
+{"Geo::OSRc::SpatialReference_SetGeocCS", _wrap_SpatialReference_SetGeocCS},
+{"Geo::OSRc::SpatialReference_SetVertCS", _wrap_SpatialReference_SetVertCS},
+{"Geo::OSRc::SpatialReference_SetCompoundCS", _wrap_SpatialReference_SetCompoundCS},
 {"Geo::OSRc::SpatialReference_ImportFromWkt", _wrap_SpatialReference_ImportFromWkt},
 {"Geo::OSRc::SpatialReference_ImportFromProj4", _wrap_SpatialReference_ImportFromProj4},
 {"Geo::OSRc::SpatialReference_ImportFromUrl", _wrap_SpatialReference_ImportFromUrl},
@@ -12632,552 +13348,567 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   }
   
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_WKT_WGS84", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ALBERS_CONIC_EQUAL_AREA", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Albers_Conic_Equal_Area"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_AZIMUTHAL_EQUIDISTANT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Azimuthal_Equidistant"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_CASSINI_SOLDNER", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Cassini_Soldner"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_CYLINDRICAL_EQUAL_AREA", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Cylindrical_Equal_Area"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_BONNE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Bonne"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_I", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Eckert_I"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_II", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Eckert_II"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_III", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Eckert_III"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_IV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Eckert_IV"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_V", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Eckert_V"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ECKERT_VI", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Eckert_VI"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_EQUIDISTANT_CONIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Equidistant_Conic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_EQUIRECTANGULAR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Equirectangular"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GALL_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Gall_Stereographic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GAUSSSCHREIBERTMERCATOR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Gauss_Schreiber_Transverse_Mercator"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GEOSTATIONARY_SATELLITE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Geostationary_Satellite"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GOODE_HOMOLOSINE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Goode_Homolosine"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_IGH", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Interrupted_Goode_Homolosine"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_GNOMONIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Gnomonic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_HOTINE_OBLIQUE_MERCATOR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Hotine_Oblique_Mercator"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Hotine_Oblique_Mercator_Two_Point_Natural_Origin"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LABORDE_OBLIQUE_MERCATOR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Laborde_Oblique_Mercator"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Lambert_Conformal_Conic_1SP"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP_Belgium"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Lambert_Azimuthal_Equal_Area"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MERCATOR_1SP", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Mercator_1SP"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MERCATOR_2SP", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Mercator_2SP"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MILLER_CYLINDRICAL", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Miller_Cylindrical"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_MOLLWEIDE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Mollweide"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_NEW_ZEALAND_MAP_GRID", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("New_Zealand_Map_Grid"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_OBLIQUE_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Oblique_Stereographic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ORTHOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Orthographic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_POLAR_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Polar_Stereographic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_POLYCONIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Polyconic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_ROBINSON", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Robinson"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_SINUSOIDAL", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Sinusoidal"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_STEREOGRAPHIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Stereographic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_SWISS_OBLIQUE_CYLINDRICAL", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Swiss_Oblique_Cylindrical"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_South_Orientated"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_21", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_21"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_22", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_22"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_23", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_23"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_24", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_24"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TRANSVERSE_MERCATOR_MI_25", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Transverse_Mercator_MapInfo_25"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TUNISIA_MINING_GRID", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Tunisia_Mining_Grid"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_TWO_POINT_EQUIDISTANT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Two_Point_Equidistant"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_VANDERGRINTEN", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("VanDerGrinten"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_KROVAK", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Krovak"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_IMW_POLYCONIC", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("International_Map_of_the_World_Polyconic"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_I", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Wagner_I"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_II", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Wagner_II"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_III", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Wagner_III"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_IV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Wagner_IV"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_V", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Wagner_V"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_VI", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Wagner_VI"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PT_WAGNER_VII", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Wagner_VII"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_CENTRAL_MERIDIAN", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("central_meridian"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_SCALE_FACTOR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("scale_factor"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_STANDARD_PARALLEL_1", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("standard_parallel_1"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_STANDARD_PARALLEL_2", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("standard_parallel_2"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_PSEUDO_STD_PARALLEL_1", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("pseudo_standard_parallel_1"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_CENTER", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("longitude_of_center"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_CENTER", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("latitude_of_center"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_ORIGIN", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("longitude_of_origin"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_ORIGIN", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("latitude_of_origin"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_FALSE_EASTING", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("false_easting"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_FALSE_NORTHING", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("false_northing"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_AZIMUTH", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("azimuth"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_POINT_1", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("longitude_of_point_1"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_POINT_1", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("latitude_of_point_1"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_POINT_2", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("longitude_of_point_2"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_POINT_2", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("latitude_of_point_2"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_POINT_3", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("longitude_of_point_3"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_POINT_3", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("latitude_of_point_3"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_RECTIFIED_GRID_ANGLE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("rectified_grid_angle"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LANDSAT_NUMBER", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("landsat_number"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_PATH_NUMBER", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("path_number"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_PERSPECTIVE_POINT_HEIGHT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("perspective_point_height"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_SATELLITE_HEIGHT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("satellite_height"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_FIPSZONE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("fipszone"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_ZONE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("zone"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_1ST_POINT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Latitude_Of_1st_Point"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_1ST_POINT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Longitude_Of_1st_Point"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LATITUDE_OF_2ND_POINT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Latitude_Of_2nd_Point"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PP_LONGITUDE_OF_2ND_POINT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Longitude_Of_2nd_Point"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_METER", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Meter"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_FOOT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Foot (International)"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("0.3048"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_FOOT", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Foot_US"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_US_FOOT_CONV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("0.3048006096012192"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_NAUTICAL_MILE", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Nautical Mile"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_NAUTICAL_MILE_CONV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("1852.0"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Link"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK_CONV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("0.20116684023368047"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CHAIN", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Chain"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_CHAIN_CONV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("20.116684023368047"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_ROD", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Rod"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_ROD_CONV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("5.02921005842012"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK_Clarke", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("Link_Clarke"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "SRS_UL_LINK_Clarke_CONV", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("0.2011661949"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/usr/share/swig1.3/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);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UA_DEGREE_CONV", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("0.0174532925199433"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_UA_RADIAN", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("radian"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_PM_GREENWICH", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("Greenwich"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_NAD27", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("North_American_Datum_1927"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_NAD83", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("North_American_Datum_1983"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_WGS72", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("WGS_1972"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_DN_WGS84", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("WGS_1984"));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_WGS84_SEMIMAJOR", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(6378137.0)));
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
-  /*@SWIG:/usr/local/swig-1.3.39/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+  /*@SWIG:/usr/share/swig1.3/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "SRS_WGS84_INVFLATTENING", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(298.257223563)));
     SvREADONLY_on(sv);
diff --git a/swig/perl/t/gdal.t b/swig/perl/t/gdal.t
index 8bf6f7a..0322c49 100644
--- a/swig/perl/t/gdal.t
+++ b/swig/perl/t/gdal.t
@@ -54,6 +54,19 @@ if (0) {
 }
 
 {
+    # test memory files
+    my $fp = Geo::GDAL::VSIFOpenL('/vsimem/x', 'w');
+    my $c = Geo::GDAL::VSIFWriteL("hello world!\n", $fp);
+    ok($c == 13, 'Wrote 13 characters to a memory file.');
+    Geo::GDAL::VSIFCloseL($fp);
+    $fp = Geo::GDAL::VSIFOpenL('/vsimem/x', 'r');
+    my $b = Geo::GDAL::VSIFReadL(40, $fp);
+    ok($b eq "hello world!\n", 'Read back what I Wrote to a memory file.');
+    Geo::GDAL::VSIFCloseL($fp);
+    Geo::GDAL::Unlink('/vsimem/x');
+}
+
+{
     my $driver = Geo::GDAL::GetDriver('MEM');
     my $dataset = $driver->Create('tmp', 10, 10, 3 , 'Int32', []);
     ok($dataset->isa('Geo::GDAL::Dataset'), 'Geo::GDAL::Dataset');
@@ -223,14 +236,10 @@ ok(is_deeply($a, $b), "xml parsing");
 
 my @tmp = sort keys %available_driver;
 
-if (@fails) {
-    print STDERR "\nUnexpected failures:\n", at fails;
-    print STDERR "\nAvailable drivers were ",join(', ', at tmp),"\n";
-    print STDERR "Drivers used in tests were: ",join(', ', at tested_drivers),"\n";
-} else {
-    print STDERR "\nAvailable drivers were ",join(', ', at tmp),"\n";
-    print STDERR "Drivers used in tests were: ",join(', ', at tested_drivers),"\n";
-}
+print STDERR "\nGDAL version: ",Geo::GDAL::VersionInfo,"\n";
+print STDERR "Unexpected failures:\n", at fails,"\n" if @fails;
+print STDERR "Available drivers were ",join(', ', at tmp),"\n";
+print STDERR "Drivers used in tests were: ",join(', ', at tested_drivers),"\n";
 
 system "rm -rf tmp_ds_*" unless $^O eq 'MSWin32';
 
diff --git a/swig/perl/t/ogr.t b/swig/perl/t/ogr.t
index dcab810..8f52616 100644
--- a/swig/perl/t/ogr.t
+++ b/swig/perl/t/ogr.t
@@ -82,6 +82,20 @@ system "rm -rf tmp_ds_*" unless $^O eq 'MSWin32';
 }
 
 {
+    # test the Points method
+    my $g = Geo::OGR::Geometry->create( WKT => 'POINT(1.1 2.2)');
+    my $p = $g->Points;
+    $g->Points($p);
+    my $q = $g->Points;
+    is_deeply($p, $q, "Points with a point");
+    $g = Geo::OGR::Geometry->create(wkt => "linestring(1 1, 1 2, 2 2)");
+    $p = $g->Points;
+    $g->Points($p);
+    $q = $g->Points;
+    is_deeply($p, $q, "Points with a linestring");
+}
+
+{
     my $g = Geo::OGR::Geometry->create(wkt => "linestring(1 1, 1 2, 2 2)");
     ok ($g->Length == 2, "Length 1");
 }
@@ -168,9 +182,11 @@ system "rm -rf tmp_ds_*" unless $^O eq 'MSWin32';
     ok(is_deeply(\@cap, ['CreateLayer','DeleteLayer']), "data source capabilities");
     
     my $layer = $datasource->CreateLayer('a', undef, 'Point');
-    @cap = $layer->Capabilities;
-    ok(is_deeply(\@cap, [qw/RandomRead SequentialWrite RandomWrite 
-	  FastFeatureCount CreateField DeleteFeature FastSetNextByIndex/]), "layer capabilities");
+    my %cap = map { $_ => 1 } $layer->Capabilities;
+    for (qw/RandomRead SequentialWrite RandomWrite	
+	  FastFeatureCount CreateField DeleteFeature FastSetNextByIndex/) {
+	ok($cap{$_}, "layer has capability: $_");
+    }
     $datasource->CreateLayer('b', undef, 'Point');
     $datasource->CreateLayer('c', undef, 'Point');
     my @layers = $datasource->Layers;
diff --git a/swig/python/GNUmakefile b/swig/python/GNUmakefile
index bcaeabf..b4d5e90 100644
--- a/swig/python/GNUmakefile
+++ b/swig/python/GNUmakefile
@@ -49,8 +49,15 @@ gdal_array_wrap.cpp:  ../include/gdal_array.i ../include/python/typemaps_python.
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ gdal_array.i
 
 # A few hacks (cat, mv) : the first one for SWIG < 1.3.36 and the second one for SWIG <= 1.3.39 python 3.X on 64bit platforms
+# The python3.2.patch is from https://sourceforge.net/tracker/?func=detail&aid=3057804&group_id=1645&atid=101645
+# and is no longer necessary with swig 2.0.4
 generate: ${WRAPPERS} gdal_array_wrap.cpp
 	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp; do sed "s/PyErr_Format(PyExc_RuntimeError, mesg)/PyErr_SetString(PyExc_RuntimeError, mesg)/" ${SWIGOUTPUTDIR}/$$i | sed "s/int len;/Py_ssize_t len;/" > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; done
+	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && patch -p0 < python3.2.patch
+	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/ogr_wrap/" | patch -p0
+	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/osr_wrap/" | patch -p0
+	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap\.cpp/gdalconst_wrap\.c/" | patch -p0
+	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/gdal_array_wrap/" | patch -p0
     
 build:
 	$(PYTHON) setup.py build
@@ -83,3 +90,6 @@ docs:
 	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrfeaturedefn_8cpp.xml ../include/python/docs/ogr_featuredef_docs.i OGRFeatureDefnShadow OGR_FD_
 
 	$(PYTHON) ../include/python/docs/doxy2swig.py ../../ogr/xml/ogrfielddefn_8cpp.xml ../include/python/docs/ogr_fielddef_docs.i OGRFieldDefnShadow OGR_Fld_
+
+epydoc: generate
+	epydoc --config epydoc.conf
diff --git a/swig/python/epydoc.conf b/swig/python/epydoc.conf
new file mode 100644
index 0000000..74d290c
--- /dev/null
+++ b/swig/python/epydoc.conf
@@ -0,0 +1,8 @@
+[epydoc]
+name: GDAL/OGR Python API
+url: http://gdal.org/
+modules: osgeo
+output: html
+target: html/
+graph: all
+dotpath: /usr/bin/dot
diff --git a/swig/python/extensions/gdal_array_wrap.cpp b/swig/python/extensions/gdal_array_wrap.cpp
index 170de82..e2585ba 100644
--- a/swig/python/extensions/gdal_array_wrap.cpp
+++ b/swig/python/extensions/gdal_array_wrap.cpp
@@ -1129,6 +1129,10 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
+#if PY_VERSION_HEX >= 0x03020000
+#define SWIG_PYTHON_USE_CAPSULE
+#endif
+
 #define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
@@ -2448,8 +2452,12 @@ SWIG_Python_GetModule(void) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
+#else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+#endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2492,11 +2500,26 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
+#ifdef SWIG_PYTHON_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *capsule)
+{
+  swig_module_info *swig_module;
+  swig_type_info **types;
+  size_t i;
+  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+  if (swig_module == NULL)
+  {
+    PyErr_Clear();
+    return;
+  }
+  types = swig_module->types;
+#else
 SWIG_Python_DestroyModule(void *vptr)
 {
   swig_module_info *swig_module = (swig_module_info *) vptr;
   swig_type_info **types = swig_module->types;
   size_t i;
+#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2518,7 +2541,13 @@ SWIG_Python_SetModule(swig_module_info *swig_module) {
   PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				   swig_empty_runtime_method_table);
 #endif
+#ifdef SWIG_PYTHON_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module,
+                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
+                                    SWIG_Python_DestroyModule);
+#else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
@@ -2541,12 +2570,20 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+#endif
   } else {
     swig_module_info *swig_module = SWIG_Python_GetModule();
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
+#endif
       PyDict_SetItem(cache, key, obj);
       Py_DECREF(obj);
     }
diff --git a/swig/python/extensions/gdal_wrap.cpp b/swig/python/extensions/gdal_wrap.cpp
index 21c2983..1b37d98 100644
--- a/swig/python/extensions/gdal_wrap.cpp
+++ b/swig/python/extensions/gdal_wrap.cpp
@@ -1129,6 +1129,10 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
+#if PY_VERSION_HEX >= 0x03020000
+#define SWIG_PYTHON_USE_CAPSULE
+#endif
+
 #define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
@@ -2448,8 +2452,12 @@ SWIG_Python_GetModule(void) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
+#else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+#endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2492,11 +2500,26 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
+#ifdef SWIG_PYTHON_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *capsule)
+{
+  swig_module_info *swig_module;
+  swig_type_info **types;
+  size_t i;
+  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+  if (swig_module == NULL)
+  {
+    PyErr_Clear();
+    return;
+  }
+  types = swig_module->types;
+#else
 SWIG_Python_DestroyModule(void *vptr)
 {
   swig_module_info *swig_module = (swig_module_info *) vptr;
   swig_type_info **types = swig_module->types;
   size_t i;
+#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2518,7 +2541,13 @@ SWIG_Python_SetModule(swig_module_info *swig_module) {
   PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				   swig_empty_runtime_method_table);
 #endif
+#ifdef SWIG_PYTHON_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module,
+                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
+                                    SWIG_Python_DestroyModule);
+#else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
@@ -2541,12 +2570,20 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+#endif
   } else {
     swig_module_info *swig_module = SWIG_Python_GetModule();
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
+#endif
       PyDict_SetItem(cache, key, obj);
       Py_DECREF(obj);
     }
@@ -2701,18 +2738,19 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
 #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_char swig_types[16]
-#define SWIGTYPE_p_double swig_types[17]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[18]
-#define SWIGTYPE_p_int swig_types[19]
-#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[20]
-#define SWIGTYPE_p_p_GDAL_GCP swig_types[21]
-#define SWIGTYPE_p_p_char swig_types[22]
-#define SWIGTYPE_p_p_int swig_types[23]
-#define SWIGTYPE_p_p_void swig_types[24]
-#define SWIGTYPE_p_void swig_types[25]
-static swig_type_info *swig_types[27];
-static swig_module_info swig_module = {swig_types, 26, 0, 0, 0, 0};
+#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 SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -2975,7 +3013,15 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return 0;
     }
-    char *data = PyBytes_AsString( (PyObject *)*buf ); 
+    PyObject* o = (PyObject*) *buf;
+    char *data = PyBytes_AsString(o); 
+    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * nMembSize < buf_size)
+    {
+        _PyBytes_Resize(&o, nRet * nMembSize);
+        *buf = o;
+    }
+    return nRet;
 #else 
     *buf = (void *)PyString_FromStringAndSize( NULL, buf_size ); 
     if (*buf == NULL)
@@ -2983,11 +3029,17 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate result buffer");
         return 0;
     }
-    char *data = PyString_AsString( (PyObject *)*buf ); 
+    PyObject* o = (PyObject*) *buf;
+    char *data = PyString_AsString(o); 
+    GIntBig nRet = (GIntBig)VSIFReadL( data, nMembSize, nMembCount, fp );
+    if (nRet * nMembSize < buf_size)
+    {
+        _PyString_Resize(&o, nRet * nMembSize);
+        *buf = o;
+    }
+    return nRet;
 #endif
-
-    return VSIFReadL( data, nMembSize, nMembCount, fp );
-} 
+}
 
 
 #include <limits.h>
@@ -3375,6 +3427,51 @@ int wrapper_HasThreadSupport()
     return strcmp(CPLGetThreadingModel(), "stub") != 0;
 }
 
+
+typedef struct
+{
+  int     mode;
+  GIntBig size;
+  GIntBig mtime;
+} StatBuf;
+
+SWIGINTERN StatBuf *new_StatBuf(StatBuf *psStatBuf){
+    StatBuf *self = (StatBuf*) CPLMalloc( sizeof( StatBuf ) );
+    self->mode = psStatBuf->mode;
+    self->size = psStatBuf->size;
+    self->mtime = psStatBuf->mtime;
+    return self;
+  }
+SWIGINTERN void delete_StatBuf(StatBuf *self){
+    CPLFree(self);
+  }
+SWIGINTERN int StatBuf_IsDirectory(StatBuf *self){
+     return (self->mode & S_IFDIR) != 0;
+  }
+
+int wrapper_VSIStatL( const char * utf8_path, StatBuf *psStatBufOut, int nFlags = 0 )
+{
+    VSIStatBufL sStat;
+    memset(&sStat, 0, sizeof(sStat));
+    memset(psStatBufOut, 0, sizeof(StatBuf));
+    int nRet = VSIStatExL(utf8_path, &sStat, nFlags);
+    psStatBufOut->mode = sStat.st_mode;
+    psStatBufOut->size = (GIntBig)sStat.st_size;
+    psStatBufOut->mtime = (GIntBig)sStat.st_mtime;
+    return nRet;
+}
+
+
+int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE * f)
+{
+    if (nLen < size * memb)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Inconsistant buffer size with 'size' and 'memb' values");
+        return 0;
+    }
+    return VSIFWriteL(pBuf, size, memb, f);
+}
+
 SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
     return GDALGetDescription( self );
   }
@@ -4311,6 +4408,12 @@ SWIGINTERNINLINE PyObject*
   return PyBool_FromLong(value ? 1 : 0);
 }
 
+SWIGINTERN char **GDALRasterBandShadow_GetCategoryNames(GDALRasterBandShadow *self){
+    return GDALGetRasterCategoryNames( self );
+  }
+SWIGINTERN CPLErr GDALRasterBandShadow_SetCategoryNames(GDALRasterBandShadow *self,char **papszCategoryNames){
+    return GDALSetRasterCategoryNames( self, papszCategoryNames );
+  }
 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;
@@ -4897,11 +5000,33 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
     if( nChildCount < 0 )
     {
         PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
-	return NULL;
+        return NULL;
     }
 
     PyArg_Parse( PyList_GET_ITEM(pyList,0), "i", &nType );
     PyArg_Parse( PyList_GET_ITEM(pyList,1), "s", &pszText );
+
+    /* Detect "pseudo" root */
+    if (nType == CXT_Element && pszText != NULL && strlen(pszText) == 0 && nChildCount == 2)
+    {
+        PyObject *pyFirst = PyList_GET_ITEM(pyList, 2);
+        if (PyList_Size(pyFirst) < 2)
+        {
+            PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
+            return NULL;
+        }
+        int nTypeFirst = 0;
+        char* pszTextFirst = NULL;
+        PyArg_Parse( PyList_GET_ITEM(pyFirst,0), "i", &nTypeFirst );
+        PyArg_Parse( PyList_GET_ITEM(pyFirst,1), "s", &pszTextFirst );
+        if (nTypeFirst == CXT_Element && pszTextFirst != NULL && pszTextFirst[0] == '?')
+        {
+            psThisNode = PyListToXMLTree( PyList_GET_ITEM(pyList,2) );
+            psThisNode->psNext = PyListToXMLTree( PyList_GET_ITEM(pyList,3) );
+            return psThisNode;
+        }
+    }
+
     psThisNode = CPLCreateXMLNode( NULL, (CPLXMLNodeType) nType, pszText );
 
     for( iChild = 0; iChild < nChildCount; iChild++ )
@@ -5822,30 +5947,55 @@ SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObje
   PyObject *resultobj = 0;
   int arg1 ;
   GByte *arg2 = (GByte *) 0 ;
-  int val1 ;
-  int ecode1 = 0 ;
-  void *argp2 = 0 ;
-  int res2 = 0 ;
+  int alloc1 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  char *result = 0 ;
+  retStringAndCPLFree *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:CPLBinaryToHex",&obj0,&obj1)) SWIG_fail;
-  ecode1 = SWIG_AsVal_int(obj0, &val1);
-  if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "CPLBinaryToHex" "', argument " "1"" of type '" "int""'");
-  } 
-  arg1 = static_cast< int >(val1);
-  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GByte, 0 |  0 );
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CPLBinaryToHex" "', argument " "2"" of type '" "GByte const *""'"); 
+  if (!PyArg_ParseTuple(args,(char *)"O:CPLBinaryToHex",&obj0)) SWIG_fail;
+  {
+    /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
+#if PY_VERSION_HEX>=0x03000000
+    if (PyUnicode_Check(obj0))
+    {
+      size_t safeLen = 0;
+      int ret = SWIG_AsCharPtrAndSize(obj0, (char**) &arg2, &safeLen, &alloc1);
+      if (!SWIG_IsOK(ret)) {
+        SWIG_exception( SWIG_RuntimeError, "invalid Unicode string" );
+      }
+      
+      if (safeLen) safeLen--;
+      arg1 = (int) safeLen;
+    }
+    else if (PyBytes_Check(obj0))
+    {
+      Py_ssize_t safeLen = 0;
+      PyBytes_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      arg1 = (int) safeLen;
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a unicode string or a bytes");
+      SWIG_fail;
+    }
+#else
+    if (PyString_Check(obj0))
+    {
+      Py_ssize_t safeLen = 0;
+      PyString_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      arg1 = (int) safeLen;
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a string");
+      SWIG_fail;
+    }
+#endif
   }
-  arg2 = reinterpret_cast< GByte * >(argp2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)CPLBinaryToHex(arg1,(GByte const *)arg2);
+    result = (retStringAndCPLFree *)CPLBinaryToHex(arg1,(GByte const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -5853,9 +6003,28 @@ SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObje
       }
     }
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
+  {
+    /* %typemap(out) (retStringAndCPLFree*) */
+    if(result)
+    {
+      resultobj = GDALPythonObjectFromCStr( (const char *)result);
+      CPLFree(result);
+    }
+  }
+  {
+    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    if( alloc1 == SWIG_NEWOBJ ) {
+      delete[] arg2;
+    }
+  }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    if( alloc1 == SWIG_NEWOBJ ) {
+      delete[] arg2;
+    }
+  }
   return NULL;
 }
 
@@ -6006,21 +6175,18 @@ fail:
 SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   char *arg1 = (char *) 0 ;
-  int res1 ;
-  char *buf1 = 0 ;
-  int alloc1 = 0 ;
+  int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)"O:Unlink",&obj0)) SWIG_fail;
-  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Unlink" "', argument " "1"" of type '" "char const *""'");
-  }
-  arg1 = reinterpret_cast< char * >(buf1);
   {
-    if (!arg1) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
     }
   }
   {
@@ -6036,10 +6202,16 @@ SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     }
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
   return resultobj;
 fail:
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
   return NULL;
 }
 
@@ -6213,6 +6385,262 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_StatBuf_mode_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  StatBuf *arg1 = (StatBuf *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:StatBuf_mode_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_StatBuf, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StatBuf_mode_get" "', argument " "1"" of type '" "StatBuf *""'"); 
+  }
+  arg1 = reinterpret_cast< StatBuf * >(argp1);
+  result = (int) ((arg1)->mode);
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_StatBuf_size_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  StatBuf *arg1 = (StatBuf *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  GIntBig result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:StatBuf_size_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_StatBuf, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StatBuf_size_get" "', argument " "1"" of type '" "StatBuf *""'"); 
+  }
+  arg1 = reinterpret_cast< StatBuf * >(argp1);
+  result =  ((arg1)->size);
+  {
+    char szTmp[32];
+    sprintf(szTmp, CPL_FRMT_GIB, result);
+#if PY_VERSION_HEX>=0x03000000
+    resultobj = PyLong_FromString(szTmp, NULL, 10);
+#else
+    resultobj = PyInt_FromString(szTmp, NULL, 10);
+#endif
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_StatBuf_mtime_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  StatBuf *arg1 = (StatBuf *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  GIntBig result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:StatBuf_mtime_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_StatBuf, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StatBuf_mtime_get" "', argument " "1"" of type '" "StatBuf *""'"); 
+  }
+  arg1 = reinterpret_cast< StatBuf * >(argp1);
+  result =  ((arg1)->mtime);
+  {
+    char szTmp[32];
+    sprintf(szTmp, CPL_FRMT_GIB, result);
+#if PY_VERSION_HEX>=0x03000000
+    resultobj = PyLong_FromString(szTmp, NULL, 10);
+#else
+    resultobj = PyInt_FromString(szTmp, NULL, 10);
+#endif
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  StatBuf *arg1 = (StatBuf *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  StatBuf *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:new_StatBuf",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_StatBuf, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_StatBuf" "', argument " "1"" of type '" "StatBuf *""'"); 
+  }
+  arg1 = reinterpret_cast< StatBuf * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (StatBuf *)new_StatBuf(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_StatBuf, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  StatBuf *arg1 = (StatBuf *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:delete_StatBuf",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_StatBuf, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_StatBuf" "', argument " "1"" of type '" "StatBuf *""'"); 
+  }
+  arg1 = reinterpret_cast< StatBuf * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    delete_StatBuf(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_StatBuf_IsDirectory(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  StatBuf *arg1 = (StatBuf *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:StatBuf_IsDirectory",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_StatBuf, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StatBuf_IsDirectory" "', argument " "1"" of type '" "StatBuf *""'"); 
+  }
+  arg1 = reinterpret_cast< StatBuf * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)StatBuf_IsDirectory(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 *StatBuf_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_StatBuf, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_VSIStatL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  char *arg1 = (char *) 0 ;
+  StatBuf *arg2 = (StatBuf *) 0 ;
+  int arg3 = (int) 0 ;
+  int bToFree1 = 0 ;
+  StatBuf sStatBuf2 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  {
+    /* %typemap(in,numinputs=0) (StatBuf *psStatBufOut) (StatBuf sStatBuf2 ) */
+    arg2 = &sStatBuf2;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O|O:VSIStatL",&obj0,&obj1)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  if (obj1) {
+    ecode3 = SWIG_AsVal_int(obj1, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIStatL" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)wrapper_VSIStatL((char const *)arg1,arg2,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));
+  {
+    /* %typemap(argout) (StatBuf *psStatBufOut)*/
+    Py_DECREF(resultobj);
+    if (result == 0)
+    resultobj = SWIG_NewPointerObj((void*)new_StatBuf( arg2 ),SWIGTYPE_p_StatBuf,1);
+    else
+    resultobj = Py_None;
+  }
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_VSIFOpenL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   char *arg1 = (char *) 0 ;
@@ -6284,7 +6712,57 @@ SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    VSIFCloseL(arg1);
+    VSIFCloseL(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_VSIFSeekL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  VSILFILE *arg1 = (VSILFILE *) 0 ;
+  GIntBig arg2 ;
+  int arg3 ;
+  int res1 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:VSIFSeekL",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0,SWIG_as_voidptrptr(&arg1), 0, 0);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFSeekL" "', argument " "1"" of type '" "VSILFILE *""'"); 
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFSeekL" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)VSIFSeekL(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6292,48 +6770,30 @@ SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_VSIFSeekL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_VSIFTellL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
-  long arg2 ;
-  int arg3 ;
   int res1 ;
-  long val2 ;
-  int ecode2 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  int result;
+  GIntBig result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO:VSIFSeekL",&obj0,&obj1,&obj2)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:VSIFTellL",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0,SWIG_as_voidptrptr(&arg1), 0, 0);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFSeekL" "', argument " "1"" of type '" "VSILFILE *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFTellL" "', argument " "1"" of type '" "VSILFILE *""'"); 
   }
-  ecode2 = SWIG_AsVal_long(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VSIFSeekL" "', argument " "2"" of type '" "long""'");
-  } 
-  arg2 = static_cast< long >(val2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFSeekL" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIFSeekL(arg1,arg2,arg3);
+    result = VSIFTellL(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6341,30 +6801,48 @@ SWIGINTERN PyObject *_wrap_VSIFSeekL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       }
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    char szTmp[32];
+    sprintf(szTmp, CPL_FRMT_GIB, result);
+#if PY_VERSION_HEX>=0x03000000
+    resultobj = PyLong_FromString(szTmp, NULL, 10);
+#else
+    resultobj = PyInt_FromString(szTmp, NULL, 10);
+#endif
+  }
   return resultobj;
 fail:
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_VSIFTellL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_VSIFTruncateL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
+  GIntBig arg2 ;
   int res1 ;
   PyObject * obj0 = 0 ;
-  long result;
+  PyObject * obj1 = 0 ;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:VSIFTellL",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:VSIFTruncateL",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0,SWIG_as_voidptrptr(&arg1), 0, 0);
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFTellL" "', argument " "1"" of type '" "VSILFILE *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFTruncateL" "', argument " "1"" of type '" "VSILFILE *""'"); 
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (long)VSIFTellL(arg1);
+    result = (int)VSIFTruncateL(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6372,7 +6850,7 @@ SWIGINTERN PyObject *_wrap_VSIFTellL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
       }
     }
   }
-  resultobj = SWIG_From_long(static_cast< long >(result));
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
   return NULL;
@@ -6381,18 +6859,17 @@ fail:
 
 SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  char *arg1 = (char *) 0 ;
-  int arg2 ;
+  int arg1 ;
+  char *arg2 = (char *) 0 ;
   int arg3 ;
-  VSILFILE *arg4 = (VSILFILE *) 0 ;
-  int res1 ;
-  char *buf1 = 0 ;
+  int arg4 ;
+  VSILFILE *arg5 = (VSILFILE *) 0 ;
   int alloc1 = 0 ;
-  int val2 ;
-  int ecode2 = 0 ;
   int val3 ;
   int ecode3 = 0 ;
-  int res4 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int res5 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
@@ -6400,30 +6877,64 @@ SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)"OOOO:VSIFWriteL",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
-  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFWriteL" "', argument " "1"" of type '" "char const *""'");
+  {
+    /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
+#if PY_VERSION_HEX>=0x03000000
+    if (PyUnicode_Check(obj0))
+    {
+      size_t safeLen = 0;
+      int ret = SWIG_AsCharPtrAndSize(obj0, (char**) &arg2, &safeLen, &alloc1);
+      if (!SWIG_IsOK(ret)) {
+        SWIG_exception( SWIG_RuntimeError, "invalid Unicode string" );
+      }
+      
+      if (safeLen) safeLen--;
+      arg1 = (int) safeLen;
+    }
+    else if (PyBytes_Check(obj0))
+    {
+      Py_ssize_t safeLen = 0;
+      PyBytes_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      arg1 = (int) safeLen;
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a unicode string or a bytes");
+      SWIG_fail;
+    }
+#else
+    if (PyString_Check(obj0))
+    {
+      Py_ssize_t safeLen = 0;
+      PyString_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      arg1 = (int) safeLen;
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a string");
+      SWIG_fail;
+    }
+#endif
   }
-  arg1 = reinterpret_cast< char * >(buf1);
-  ecode2 = SWIG_AsVal_int(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VSIFWriteL" "', argument " "2"" of type '" "int""'");
-  } 
-  arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  ecode3 = SWIG_AsVal_int(obj1, &val3);
   if (!SWIG_IsOK(ecode3)) {
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFWriteL" "', argument " "3"" of type '" "int""'");
   } 
   arg3 = static_cast< int >(val3);
-  res4 = SWIG_ConvertPtr(obj3,SWIG_as_voidptrptr(&arg4), 0, 0);
-  if (!SWIG_IsOK(res4)) {
-    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "VSIFWriteL" "', argument " "4"" of type '" "VSILFILE *""'"); 
+  ecode4 = SWIG_AsVal_int(obj2, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "VSIFWriteL" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  res5 = SWIG_ConvertPtr(obj3,SWIG_as_voidptrptr(&arg5), 0, 0);
+  if (!SWIG_IsOK(res5)) {
+    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "VSIFWriteL" "', argument " "5"" of type '" "VSILFILE *""'"); 
   }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIFWriteL((char const *)arg1,arg2,arg3,arg4);
+    result = (int)wrapper_VSIFWriteL(arg1,arg2,arg3,arg4,arg5);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6432,10 +6943,20 @@ SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *
     }
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    if( alloc1 == SWIG_NEWOBJ ) {
+      delete[] arg2;
+    }
+  }
   return resultobj;
 fail:
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    if( alloc1 == SWIG_NEWOBJ ) {
+      delete[] arg2;
+    }
+  }
   return NULL;
 }
 
@@ -6497,10 +7018,8 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(s
   }
   arg2 = reinterpret_cast< char * >(buf2);
   {
-    /* %typemap(check) (OGRFeatureShadow *feature) */
-    if ( bUseExceptions && !arg2) {
-      PyErr_SetString( PyExc_RuntimeError, "Description cannot be None" );
-      SWIG_fail;
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
     }
   }
   {
@@ -6711,6 +7230,7 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
           arg2 = CSLAddNameValue( arg2, nm, val );
           Py_DECREF(it);
         }
+        Py_DECREF(item_list);
       }
     }
     else {
@@ -15005,6 +15525,137 @@ fail:
 }
 
 
+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 ) {
+        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_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  CPLErr result;
+  
+  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_SetCategoryNames" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  {
+    /* %typemap(in) char **options */
+    /* Check if is a list */
+    if ( ! PySequence_Check(obj1)) {
+      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 = (CPLErr)GDALRasterBandShadow_SetCategoryNames(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));
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -20292,19 +20943,28 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"ReadDir", _wrap_ReadDir, METH_VARARGS, (char *)"ReadDir(char utf8_path) -> char"},
 	 { (char *)"SetConfigOption", _wrap_SetConfigOption, METH_VARARGS, (char *)"SetConfigOption(char pszKey, char pszValue)"},
 	 { (char *)"GetConfigOption", _wrap_GetConfigOption, METH_VARARGS, (char *)"GetConfigOption(char pszKey, char pszDefault = None) -> char"},
-	 { (char *)"CPLBinaryToHex", _wrap_CPLBinaryToHex, METH_VARARGS, (char *)"CPLBinaryToHex(int nBytes, GByte pabyData) -> char"},
+	 { (char *)"CPLBinaryToHex", _wrap_CPLBinaryToHex, METH_VARARGS, (char *)"CPLBinaryToHex(int nBytes) -> retStringAndCPLFree"},
 	 { (char *)"CPLHexToBinary", _wrap_CPLHexToBinary, METH_VARARGS, (char *)"CPLHexToBinary(char pszHex, int pnBytes) -> GByte"},
 	 { (char *)"FileFromMemBuffer", _wrap_FileFromMemBuffer, METH_VARARGS, (char *)"FileFromMemBuffer(char utf8_path, int nBytes)"},
-	 { (char *)"Unlink", _wrap_Unlink, METH_VARARGS, (char *)"Unlink(char pszFilename) -> int"},
+	 { (char *)"Unlink", _wrap_Unlink, METH_VARARGS, (char *)"Unlink(char utf8_path) -> int"},
 	 { (char *)"HasThreadSupport", _wrap_HasThreadSupport, METH_VARARGS, (char *)"HasThreadSupport() -> int"},
 	 { (char *)"Mkdir", _wrap_Mkdir, METH_VARARGS, (char *)"Mkdir(char utf8_path, int mode) -> int"},
 	 { (char *)"Rmdir", _wrap_Rmdir, METH_VARARGS, (char *)"Rmdir(char utf8_path) -> int"},
 	 { (char *)"Rename", _wrap_Rename, METH_VARARGS, (char *)"Rename(char pszOld, char pszNew) -> int"},
+	 { (char *)"StatBuf_mode_get", _wrap_StatBuf_mode_get, METH_VARARGS, (char *)"StatBuf_mode_get(StatBuf self) -> int"},
+	 { (char *)"StatBuf_size_get", _wrap_StatBuf_size_get, METH_VARARGS, (char *)"StatBuf_size_get(StatBuf self) -> GIntBig"},
+	 { (char *)"StatBuf_mtime_get", _wrap_StatBuf_mtime_get, METH_VARARGS, (char *)"StatBuf_mtime_get(StatBuf self) -> GIntBig"},
+	 { (char *)"new_StatBuf", _wrap_new_StatBuf, METH_VARARGS, (char *)"new_StatBuf(StatBuf psStatBuf) -> StatBuf"},
+	 { (char *)"delete_StatBuf", _wrap_delete_StatBuf, METH_VARARGS, (char *)"delete_StatBuf(StatBuf self)"},
+	 { (char *)"StatBuf_IsDirectory", _wrap_StatBuf_IsDirectory, METH_VARARGS, (char *)"StatBuf_IsDirectory(StatBuf self) -> int"},
+	 { (char *)"StatBuf_swigregister", StatBuf_swigregister, METH_VARARGS, NULL},
+	 { (char *)"VSIStatL", _wrap_VSIStatL, METH_VARARGS, (char *)"VSIStatL(char utf8_path, int nFlags = 0) -> int"},
 	 { (char *)"VSIFOpenL", _wrap_VSIFOpenL, METH_VARARGS, (char *)"VSIFOpenL(char utf8_path, char pszMode) -> VSILFILE"},
 	 { (char *)"VSIFCloseL", _wrap_VSIFCloseL, METH_VARARGS, (char *)"VSIFCloseL(VSILFILE arg0)"},
-	 { (char *)"VSIFSeekL", _wrap_VSIFSeekL, METH_VARARGS, (char *)"VSIFSeekL(VSILFILE arg0, long arg1, int arg2) -> int"},
-	 { (char *)"VSIFTellL", _wrap_VSIFTellL, METH_VARARGS, (char *)"VSIFTellL(VSILFILE arg0) -> long"},
-	 { (char *)"VSIFWriteL", _wrap_VSIFWriteL, METH_VARARGS, (char *)"VSIFWriteL(char arg0, int arg1, int arg2, VSILFILE arg3) -> int"},
+	 { (char *)"VSIFSeekL", _wrap_VSIFSeekL, METH_VARARGS, (char *)"VSIFSeekL(VSILFILE arg0, GIntBig arg1, int arg2) -> int"},
+	 { (char *)"VSIFTellL", _wrap_VSIFTellL, METH_VARARGS, (char *)"VSIFTellL(VSILFILE arg0) -> GIntBig"},
+	 { (char *)"VSIFTruncateL", _wrap_VSIFTruncateL, METH_VARARGS, (char *)"VSIFTruncateL(VSILFILE arg0, GIntBig arg1) -> int"},
+	 { (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_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char pszDomain = \"\") -> char"},
@@ -20515,6 +21175,8 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Band_SetDefaultHistogram", _wrap_Band_SetDefaultHistogram, METH_VARARGS, (char *)"Band_SetDefaultHistogram(Band self, double min, double max, int buckets_in) -> CPLErr"},
 	 { (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_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"
@@ -20690,6 +21352,7 @@ static swig_type_info _swigt__p_GDALTransformerInfoShadow = {"_p_GDALTransformer
 static swig_type_info _swigt__p_GDAL_GCP = {"_p_GDAL_GCP", "GDAL_GCP *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 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_StatBuf = {"_p_StatBuf", "StatBuf *", 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_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};
@@ -20718,6 +21381,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GDAL_GCP,
   &_swigt__p_GIntBig,
   &_swigt__p_OGRLayerShadow,
+  &_swigt__p_StatBuf,
   &_swigt__p_char,
   &_swigt__p_double,
   &_swigt__p_f_double_p_q_const__char_p_void__int,
@@ -20746,6 +21410,7 @@ static swig_cast_info _swigc__p_GDALTransformerInfoShadow[] = {  {&_swigt__p_GDA
 static swig_cast_info _swigc__p_GDAL_GCP[] = {  {&_swigt__p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 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_StatBuf[] = {  {&_swigt__p_StatBuf, 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_double[] = {  {&_swigt__p_double, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_f_double_p_q_const__char_p_void__int[] = {  {&_swigt__p_f_double_p_q_const__char_p_void__int, 0, 0, 0},{0, 0, 0, 0}};
@@ -20774,6 +21439,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GDAL_GCP,
   _swigc__p_GIntBig,
   _swigc__p_OGRLayerShadow,
+  _swigc__p_StatBuf,
   _swigc__p_char,
   _swigc__p_double,
   _swigc__p_f_double_p_q_const__char_p_void__int,
@@ -21384,6 +22050,9 @@ SWIG_init(void) {
     GDALAllRegister();
   }
   
+  SWIG_Python_SetConstant(d, "VSI_STAT_EXISTS_FLAG",SWIG_From_int(static_cast< int >(0x1)));
+  SWIG_Python_SetConstant(d, "VSI_STAT_NATURE_FLAG",SWIG_From_int(static_cast< int >(0x2)));
+  SWIG_Python_SetConstant(d, "VSI_STAT_SIZE_FLAG",SWIG_From_int(static_cast< int >(0x4)));
   
 #if PY_VERSION_HEX >= 0x03000000
   return m;
diff --git a/swig/python/extensions/gdalconst_wrap.c b/swig/python/extensions/gdalconst_wrap.c
index 1fac660..f6ac51d 100644
--- a/swig/python/extensions/gdalconst_wrap.c
+++ b/swig/python/extensions/gdalconst_wrap.c
@@ -1105,6 +1105,10 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
+#if PY_VERSION_HEX >= 0x03020000
+#define SWIG_PYTHON_USE_CAPSULE
+#endif
+
 #define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
@@ -2424,8 +2428,12 @@ SWIG_Python_GetModule(void) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
+#else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+#endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2468,11 +2476,26 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
+#ifdef SWIG_PYTHON_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *capsule)
+{
+  swig_module_info *swig_module;
+  swig_type_info **types;
+  size_t i;
+  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+  if (swig_module == NULL)
+  {
+    PyErr_Clear();
+    return;
+  }
+  types = swig_module->types;
+#else
 SWIG_Python_DestroyModule(void *vptr)
 {
   swig_module_info *swig_module = (swig_module_info *) vptr;
   swig_type_info **types = swig_module->types;
   size_t i;
+#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2494,7 +2517,13 @@ SWIG_Python_SetModule(swig_module_info *swig_module) {
   PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				   swig_empty_runtime_method_table);
 #endif
+#ifdef SWIG_PYTHON_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module,
+                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
+                                    SWIG_Python_DestroyModule);
+#else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
@@ -2517,12 +2546,20 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+#endif
   } else {
     swig_module_info *swig_module = SWIG_Python_GetModule();
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
+#endif
       PyDict_SetItem(cache, key, obj);
       Py_DECREF(obj);
     }
diff --git a/swig/python/extensions/ogr_wrap.cpp b/swig/python/extensions/ogr_wrap.cpp
index 48dae69..c4ebd0a 100644
--- a/swig/python/extensions/ogr_wrap.cpp
+++ b/swig/python/extensions/ogr_wrap.cpp
@@ -1129,6 +1129,10 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
+#if PY_VERSION_HEX >= 0x03020000
+#define SWIG_PYTHON_USE_CAPSULE
+#endif
+
 #define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
@@ -2448,8 +2452,12 @@ SWIG_Python_GetModule(void) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
+#else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+#endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2492,11 +2500,26 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
+#ifdef SWIG_PYTHON_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *capsule)
+{
+  swig_module_info *swig_module;
+  swig_type_info **types;
+  size_t i;
+  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+  if (swig_module == NULL)
+  {
+    PyErr_Clear();
+    return;
+  }
+  types = swig_module->types;
+#else
 SWIG_Python_DestroyModule(void *vptr)
 {
   swig_module_info *swig_module = (swig_module_info *) vptr;
   swig_type_info **types = swig_module->types;
   size_t i;
+#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2518,7 +2541,13 @@ SWIG_Python_SetModule(swig_module_info *swig_module) {
   PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				   swig_empty_runtime_method_table);
 #endif
+#ifdef SWIG_PYTHON_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module,
+                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
+                                    SWIG_Python_DestroyModule);
+#else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
@@ -2541,12 +2570,20 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+#endif
   } else {
     swig_module_info *swig_module = SWIG_Python_GetModule();
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
+#endif
       PyDict_SetItem(cache, key, obj);
       Py_DECREF(obj);
     }
@@ -3233,6 +3270,14 @@ SWIG_AsVal_int (PyObject * obj, int *val)
 
 SWIGINTERN OGRDataSourceShadow *OGRDriverShadow_Open(OGRDriverShadow *self,char const *utf8_path,int update=0){
     OGRDataSourceShadow* ds = (OGRDataSourceShadow*) OGR_Dr_Open(self, utf8_path, update);
+    if( CPLGetLastErrorType() == CE_Failure && ds != NULL )
+    {
+        CPLDebug( "SWIG",
+          "OGR_Dr_Open() succeeded, but an error is posted, so we destroy"
+          " the datasource and fail at swig level." );
+        OGRReleaseDataSource(ds);
+        ds = NULL;
+    }
     return ds;
   }
 SWIGINTERN int OGRDriverShadow_DeleteDataSource(OGRDriverShadow *self,char const *utf8_path){
@@ -3308,6 +3353,9 @@ OGRErrMessages( int rc ) {
   }
 }
 
+SWIGINTERN OGRErr OGRDataSourceShadow_SyncToDisk(OGRDataSourceShadow *self){
+    return OGR_DS_SyncToDisk(self);
+  }
 SWIGINTERN OGRLayerShadow *OGRDataSourceShadow_CreateLayer(OGRDataSourceShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
     OGRLayerShadow* layer = (OGRLayerShadow*) OGR_DS_CreateLayer( self,
 								  name,
@@ -3402,26 +3450,13 @@ SWIGINTERN OGRFeatureDefnShadow *OGRLayerShadow_GetLayerDefn(OGRLayerShadow *sel
 SWIGINTERN int OGRLayerShadow_GetFeatureCount(OGRLayerShadow *self,int force=1){
     return OGR_L_GetFeatureCount(self, force);
   }
-
-#define t_output_helper SWIG_Python_AppendOutput
-
-
-static PyObject *
-CreateTupleFromDoubleArray( double *first, unsigned int size ) {
-  PyObject *out = PyTuple_New( size );
-  for( unsigned int i=0; i<size; i++ ) {
-    PyObject *val = PyFloat_FromDouble( *first );
-    ++first;
-    PyTuple_SetItem( out, i, val );
-  }
-  return out;
-}
-
-SWIGINTERN OGRErr OGRLayerShadow_GetExtent(OGRLayerShadow *self,double argout[4],int force=1){
-
-
-
-    return 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){
+    OGRErr eErr = OGR_L_GetExtent(self, (OGREnvelope*)argout, force);
+    if (can_return_null)
+        *isvalid = (eErr == OGRERR_NONE);
+    else
+        *isvalid = TRUE;
+    return;
   }
 SWIGINTERN bool OGRLayerShadow_TestCapability(OGRLayerShadow *self,char const *cap){
     return (OGR_L_TestCapability(self, cap) > 0);
@@ -3429,6 +3464,25 @@ SWIGINTERN bool OGRLayerShadow_TestCapability(OGRLayerShadow *self,char const *c
 SWIGINTERN OGRErr OGRLayerShadow_CreateField(OGRLayerShadow *self,OGRFieldDefnShadow *field_def,int approx_ok=1){
     return OGR_L_CreateField(self, field_def, approx_ok);
   }
+SWIGINTERN OGRErr OGRLayerShadow_DeleteField(OGRLayerShadow *self,int iField){
+    return OGR_L_DeleteField(self, iField);
+  }
+SWIGINTERN OGRErr OGRLayerShadow_ReorderField(OGRLayerShadow *self,int iOldFieldPos,int iNewFieldPos){
+    return OGR_L_ReorderField(self, iOldFieldPos, iNewFieldPos);
+  }
+SWIGINTERN OGRErr OGRLayerShadow_ReorderFields(OGRLayerShadow *self,int nList,int *pList){
+    if (nList != OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)))
+    {
+      CPLError(CE_Failure, CPLE_IllegalArg,
+               "List should have %d elements",
+               OGR_FD_GetFieldCount(OGR_L_GetLayerDefn(self)));
+      return OGRERR_FAILURE;
+    }
+    return OGR_L_ReorderFields(self, pList);
+  }
+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_StartTransaction(OGRLayerShadow *self){
     return OGR_L_StartTransaction(self);
   }
@@ -3780,7 +3834,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 
   OGRGeometryShadow* CreateGeometryFromWkb( int len, char *bin_string, 
                                             OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkb( (unsigned char *) bin_string,
                                       reference,
                                       &geom,
@@ -3796,7 +3850,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 
   OGRGeometryShadow* CreateGeometryFromWkt( char **val, 
                                       OSRSpatialReferenceShadow *reference=NULL ) {
-    OGRGeometryShadow *geom;
+    OGRGeometryH geom = NULL;
     OGRErr err = OGR_G_CreateFromWkt(val,
                                       reference,
                                       &geom);
@@ -3840,7 +3894,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
     return NULL;
   }
 
-  return hPolygon;
+  return (OGRGeometryShadow* )hPolygon;
   }
 
 
@@ -3850,7 +3904,7 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
         double dfStartAngle, double dfEndAngle,
         double dfMaxAngleStepSizeDegrees ) {
   
-  return OGR_G_ApproximateArcAngles( 
+  return (OGRGeometryShadow* )OGR_G_ApproximateArcAngles( 
              dfCenterX, dfCenterY, dfZ, 
              dfPrimaryRadius, dfSecondaryAxis, dfRotation,
              dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
@@ -3860,28 +3914,28 @@ SWIGINTERN void OGRFieldDefnShadow_SetIgnored(OGRFieldDefnShadow *self,int bIgno
 OGRGeometryShadow* ForceToPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToPolygon( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiPolygon( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPolygon( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiPoint( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiPoint( OGR_G_Clone(geom_in) );
 }
 
 
 OGRGeometryShadow* ForceToMultiLineString( OGRGeometryShadow *geom_in ) {
  if (geom_in == NULL)
      return NULL;
- return OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
+ return (OGRGeometryShadow* )OGR_G_ForceToMultiLineString( OGR_G_Clone(geom_in) );
 }
 
 SWIGINTERN void delete_OGRGeometryShadow(OGRGeometryShadow *self){
@@ -3906,6 +3960,9 @@ SWIGINTERN OGRGeometryShadow *new_OGRGeometryShadow(OGRwkbGeometryType type=wkbU
         return NULL;}
 
   }
+
+#define t_output_helper SWIG_Python_AppendOutput
+
 SWIGINTERN OGRErr OGRGeometryShadow_ExportToWkt(OGRGeometryShadow *self,char **argout){
     return OGR_G_ExportToWkt(self, argout);
   }
@@ -3920,8 +3977,8 @@ SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToGML(OGRGeometryShadow
 SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToKML(OGRGeometryShadow *self,char const *altitude_mode=NULL){
     return (retStringAndCPLFree *) OGR_G_ExportToKML(self, altitude_mode);
   }
-SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow *self){
-    return (retStringAndCPLFree *) OGR_G_ExportToJson(self);
+SWIGINTERN retStringAndCPLFree *OGRGeometryShadow_ExportToJson(OGRGeometryShadow *self,char **options=0){
+    return (retStringAndCPLFree *) OGR_G_ExportToJsonEx(self, options);
   }
 SWIGINTERN void OGRGeometryShadow_AddPoint(OGRGeometryShadow *self,double x,double y,double z=0){
     OGR_G_AddPoint( self, x, y, z );
@@ -3956,6 +4013,29 @@ SWIGINTERN double OGRGeometryShadow_GetArea(OGRGeometryShadow *self){
 SWIGINTERN int OGRGeometryShadow_GetPointCount(OGRGeometryShadow *self){
     return OGR_G_GetPointCount(self);
   }
+SWIGINTERN void OGRGeometryShadow_GetPoints(OGRGeometryShadow *self,int *pnCount,double **ppadfXY,double **ppadfZ,int nCoordDimension=0){
+    int nPoints = OGR_G_GetPointCount(self);
+    *pnCount = nPoints;
+    if (nPoints == 0)
+    {
+        *ppadfXY = NULL;
+        *ppadfZ = NULL;
+    }
+    *ppadfXY = (double*)VSIMalloc(2 * sizeof(double) * nPoints);
+    if (*ppadfXY == NULL)
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate resulting array");
+        *pnCount = 0;
+        return;
+    }
+    if (nCoordDimension <= 0)
+        nCoordDimension = OGR_G_GetCoordinateDimension(self);
+    *ppadfZ = (nCoordDimension == 3) ? (double*)VSIMalloc(sizeof(double) * nPoints) : NULL;
+    OGR_G_GetPoints(self,
+                    *ppadfXY, 2 * sizeof(double),
+                    (*ppadfXY) + 1, 2 * sizeof(double),
+                    *ppadfZ, sizeof(double));
+  }
 SWIGINTERN double OGRGeometryShadow_GetX(OGRGeometryShadow *self,int point=0){
     return OGR_G_GetX(self, point);
   }
@@ -3965,6 +4045,18 @@ SWIGINTERN double OGRGeometryShadow_GetY(OGRGeometryShadow *self,int point=0){
 SWIGINTERN double OGRGeometryShadow_GetZ(OGRGeometryShadow *self,int point=0){
     return OGR_G_GetZ(self, point);
   }
+
+static PyObject *
+CreateTupleFromDoubleArray( double *first, unsigned int size ) {
+  PyObject *out = PyTuple_New( size );
+  for( unsigned int i=0; i<size; i++ ) {
+    PyObject *val = PyFloat_FromDouble( *first );
+    ++first;
+    PyTuple_SetItem( out, i, val );
+  }
+  return out;
+}
+
 SWIGINTERN void OGRGeometryShadow_GetPoint(OGRGeometryShadow *self,int iPoint=0,double argout[3]=NULL){
 
     OGR_G_GetPoint( self, iPoint, argout+0, argout+1, argout+2 );
@@ -3988,6 +4080,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_GetGeometryRef(OGRGeometryShadow
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Simplify(OGRGeometryShadow *self,double tolerance){
     return (OGRGeometryShadow*) OGR_G_Simplify(self, tolerance);
   }
+SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SimplifyPreserveTopology(OGRGeometryShadow *self,double tolerance){
+    return (OGRGeometryShadow*) OGR_G_SimplifyPreserveTopology(self, tolerance);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Boundary(OGRGeometryShadow *self){
     return (OGRGeometryShadow*) OGR_G_Boundary(self);
   }
@@ -4093,6 +4188,9 @@ SWIGINTERN void OGRGeometryShadow_Segmentize(OGRGeometryShadow *self,double dfMa
 SWIGINTERN void OGRGeometryShadow_GetEnvelope(OGRGeometryShadow *self,double argout[4]){
     OGR_G_GetEnvelope(self, (OGREnvelope*)argout);
   }
+SWIGINTERN void OGRGeometryShadow_GetEnvelope3D(OGRGeometryShadow *self,double argout[6]){
+    OGR_G_GetEnvelope3D(self, (OGREnvelope3D*)argout);
+  }
 SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_Centroid(OGRGeometryShadow *self){
     OGRGeometryShadow *pt = (OGRGeometryShadow*) OGR_G_CreateGeometry( wkbPoint );
     OGR_G_Centroid( self, pt );
@@ -5044,6 +5142,55 @@ fail:
 }
 
 
+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 ;
@@ -6398,41 +6545,54 @@ SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObj
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
   double *arg2 ;
-  int arg3 = (int) 1 ;
+  int *arg3 = (int *) NULL ;
+  int arg4 = (int) 1 ;
+  int arg5 = (int) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  double argout2[4] ;
-  int val3 ;
-  int ecode3 = 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", NULL 
+    (char *) "self",(char *) "force",(char *) "can_return_null", NULL 
   };
-  OGRErr result;
   
   {
-    /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    /* %typemap(in) (double argout2[4], int* isvalid2) */
     arg2 = argout2;
+    arg3 = &isvalid2;
   }
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:Layer_GetExtent",kwnames,&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|OO:Layer_GetExtent",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_GetExtent" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
   if (obj1) {
-    ecode3 = SWIG_AsVal_int(obj1, &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Layer_GetExtent" "', argument " "3"" of type '" "int""'");
+    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""'");
     } 
-    arg3 = static_cast< int >(val3);
+    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();
     }
-    result = (OGRErr)OGRLayerShadow_GetExtent(arg1,arg2,arg3);
+    OGRLayerShadow_GetExtent(arg1,arg2,arg3,arg4,arg5);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6440,27 +6600,18 @@ SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObj
       }
     }
   }
+  resultobj = SWIG_Py_Void();
   {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(argout) (double argout[ANY]) */
-    PyObject *out = CreateTupleFromDoubleArray( arg2, 4 );
-    resultobj = t_output_helper(resultobj,out);
-  }
-  {
-    /* %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:
@@ -6595,25 +6746,34 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+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 *)"O:Layer_StartTransaction",&obj0)) 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_StartTransaction" "', 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);
+  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_StartTransaction(arg1);
+    result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6644,25 +6804,43 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 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 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_CommitTransaction",&obj0)) 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_CommitTransaction" "', 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);
+  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_CommitTransaction(arg1);
+    result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6693,25 +6871,47 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRLayerShadow *arg1 = (OGRLayerShadow *) 0 ;
+  int arg2 ;
+  int *arg3 = (int *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_RollbackTransaction",&obj0)) 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_RollbackTransaction" "', 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);
   {
+    /* %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);
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
+    result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6727,6 +6927,12 @@ SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(se
     }
   }
   {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg3) {
+      free((void*) arg3);
+    }
+  }
+  {
     /* %typemap(ret) OGRErr */
     if (resultobj == Py_None ) {
       Py_DECREF(resultobj);
@@ -6738,29 +6944,67 @@ SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(se
   }
   return resultobj;
 fail:
+  {
+    /* %typemap(freearg) (int nList, int* pList) */
+    if (arg3) {
+      free((void*) arg3);
+    }
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+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 ;
-  OSRSpatialReferenceShadow *result = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  OGRErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Layer_GetSpatialRef",&obj0)) SWIG_fail;
+  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_GetSpatialRef" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+    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);
+  {
+    if (!arg3) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+    result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6768,17 +7012,213 @@ SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), P
       }
     }
   }
-  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 ;
+  {
+    /* %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_StartTransaction(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_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_StartTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OGRLayerShadow_StartTransaction(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_Layer_CommitTransaction(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_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_CommitTransaction" "', argument " "1"" of type '" "OGRLayerShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRLayerShadow * >(argp1);
+  {
+    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() );
+      }
+    }
+  }
+  {
+    /* %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_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_RollbackTransaction(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_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() );
+      }
+    }
+  }
+  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;
@@ -12247,25 +12687,72 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  char **arg2 = (char **) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "options", NULL 
+  };
   retStringAndCPLFree *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:Geometry_ExportToJson",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:Geometry_ExportToJson",kwnames,&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_ExportToJson" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
   }
   arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  if (obj1) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list */
+      if ( ! PySequence_Check(obj1)) {
+        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 = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1);
+    result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -12281,8 +12768,16 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self),
       CPLFree(result);
     }
   }
-  return resultobj;
-fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
   return NULL;
 }
 
@@ -12756,6 +13251,97 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Geometry_GetPoints(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  int *arg2 = (int *) 0 ;
+  double **arg3 = (double **) 0 ;
+  double **arg4 = (double **) 0 ;
+  int arg5 = (int) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int nPoints2 = 0 ;
+  double *padfXY2 = NULL ;
+  double *padfZ2 = NULL ;
+  int val5 ;
+  int ecode5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "nCoordDimension", NULL 
+  };
+  
+  {
+    /* %typemap(in,numinputs=0) (int* pnCount, double** ppadfXY, double** ppadfZ) */
+    arg2 = &nPoints2;
+    arg3 = &padfXY2;
+    arg4 = &padfZ2;
+  }
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:Geometry_GetPoints",kwnames,&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetPoints" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  if (obj1) {
+    ecode5 = SWIG_AsVal_int(obj1, &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Geometry_GetPoints" "', argument " "5"" of type '" "int""'");
+    } 
+    arg5 = static_cast< int >(val5);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_GetPoints(arg1,arg2,arg3,arg4,arg5);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(argout)  (int* pnCount, double** ppadfXY, double** ppadfZ) */
+    Py_DECREF(resultobj);
+    int nPointCount = *(arg2);
+    if (nPointCount == 0)
+    {
+      resultobj = Py_None;
+    }
+    else
+    {
+      PyObject *xyz = PyList_New( nPointCount );
+      int nDimensions = (*arg4 != NULL) ? 3 : 2;
+      for( int i=0; i< nPointCount; i++ ) {
+        PyObject *tuple = PyTuple_New( nDimensions );
+        PyTuple_SetItem( tuple, 0, PyFloat_FromDouble( (*arg3)[2*i] ) );
+        PyTuple_SetItem( tuple, 1, PyFloat_FromDouble( (*arg3)[2*i+1] ) );
+        if (nDimensions == 3)
+        PyTuple_SetItem( tuple, 2, PyFloat_FromDouble( (*arg4)[i] ) );
+        PyList_SetItem( xyz, i, tuple );
+      }
+      resultobj = xyz;
+    }
+  }
+  {
+    /* %typemap(freearg)  (int* pnCount, double** ppadfXY, double** ppadfZ) */
+    VSIFree(*arg3);
+    VSIFree(*arg4);
+  }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg)  (int* pnCount, double** ppadfXY, double** ppadfZ) */
+    VSIFree(*arg3);
+    VSIFree(*arg4);
+  }
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Geometry_GetX(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -13257,6 +13843,48 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Geometry_SimplifyPreserveTopology(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRGeometryShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Geometry_SimplifyPreserveTopology",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_SimplifyPreserveTopology" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Geometry_SimplifyPreserveTopology" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRGeometryShadow *)OGRGeometryShadow_SimplifyPreserveTopology(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_OGRGeometryShadow, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Geometry_Boundary(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -14709,6 +15337,49 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope3D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  double *arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double argout2[6] ;
+  PyObject * obj0 = 0 ;
+  
+  {
+    /* %typemap(in,numinputs=0) (double argout2[ANY]) */
+    arg2 = argout2;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O:Geometry_GetEnvelope3D",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_GetEnvelope3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    OGRGeometryShadow_GetEnvelope3D(arg1,arg2);
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(argout) (double argout[ANY]) */
+    PyObject *out = CreateTupleFromDoubleArray( arg2, 6 );
+    resultobj = t_output_helper(resultobj,out);
+  }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Geometry_Centroid(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -15430,7 +16101,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"hDriver:  handle to the driver on which data source creation is based.\n"
 		"\n"
-		"pszName:  the name for the new data source.\n"
+		"pszName:  the name for the new data source. UTF-8 encoded.\n"
 		"\n"
 		"papszOptions:  a StringList of name=value options. Options are driver\n"
 		"specific, and driver information can be found at the following\n"
@@ -15678,6 +16349,40 @@ static PyMethodDef SwigMethods[] = {
 		"OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting\n"
 		"layers is not supported for this datasource. \n"
 		""},
+	 { (char *)"DataSource_SyncToDisk", _wrap_DataSource_SyncToDisk, METH_VARARGS, (char *)"\n"
+		"DataSource_SyncToDisk(DataSource self) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_DS_SyncToDisk(OGRDataSourceH hDS)\n"
+		"\n"
+		"Flush pending changes to disk.\n"
+		"\n"
+		"This call is intended to force the datasource to flush any pending\n"
+		"writes to disk, and leave the disk file in a consistent state. It\n"
+		"would not normally have any effect on read-only datasources.\n"
+		"\n"
+		"Some data sources do not implement this method, and will still return\n"
+		"OGRERR_NONE. An error is only returned if an error occurs while\n"
+		"attempting to flush to disk.\n"
+		"\n"
+		"The default implementation of this method just calls the SyncToDisk()\n"
+		"method on each of the layers. Conceptionally, calling SyncToDisk() on\n"
+		"a datasource should include any work that might be accomplished by\n"
+		"calling SyncToDisk() on layers in that data source.\n"
+		"\n"
+		"In any event, you should always close any opened datasource with\n"
+		"OGR_DS_Destroy() that will ensure all data is correctly flushed.\n"
+		"\n"
+		"This method is the same as the C++ method OGRDataSource::SyncToDisk()\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDS:  handle to the data source\n"
+		"\n"
+		"OGRERR_NONE if no error occurs (even if nothing is done) or an error\n"
+		"code. \n"
+		""},
 	 { (char *)"DataSource_CreateLayer", (PyCFunction) _wrap_DataSource_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
 		"DataSource_CreateLayer(DataSource self, char name, SpatialReference srs = None, \n"
 		"    OGRwkbGeometryType geom_type = wkbUnknown, \n"
@@ -15819,7 +16524,7 @@ static PyMethodDef SwigMethods[] = {
 		"error, or that have no results set, or an OGRLayer handle representing\n"
 		"a results set from the query. Note that this OGRLayer is in addition\n"
 		"to the layers in the data store and must be destroyed with\n"
-		"OGR_DS_ReleaseResultsSet() before the data source is closed\n"
+		"OGR_DS_ReleaseResultSet() before the data source is closed\n"
 		"(destroyed).\n"
 		"\n"
 		"For more information on the SQL dialect supported internally by OGR\n"
@@ -15837,13 +16542,15 @@ static PyMethodDef SwigMethods[] = {
 		"pszSQLCommand:  the SQL statement to execute.\n"
 		"\n"
 		"hSpatialFilter:  handle to a geometry which represents a spatial\n"
-		"filter.\n"
+		"filter. Can be NULL.\n"
 		"\n"
-		"pszDialect:  allows control of the statement dialect. By default it is\n"
-		"assumed to be \"generic\" SQL, whatever that is.\n"
+		"pszDialect:  allows control of the statement dialect. If set to NULL,\n"
+		"the OGR SQL engine will be used, except for RDBMS drivers that will\n"
+		"use their dedicated SQL engine, unless OGRSQL is explicitely passed as\n"
+		"the dialect.\n"
 		"\n"
 		"an handle to a OGRLayer containing the results of the query.\n"
-		"Deallocate with OGR_DS_ReleaseResultsSet(). \n"
+		"Deallocate with OGR_DS_ReleaseResultSet(). \n"
 		""},
 	 { (char *)"DataSource_ReleaseResultSet", _wrap_DataSource_ReleaseResultSet, METH_VARARGS, (char *)"\n"
 		"DataSource_ReleaseResultSet(DataSource self, Layer layer)\n"
@@ -15859,7 +16566,7 @@ static PyMethodDef SwigMethods[] = {
 		"errors.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
-		"OGRDataSource::ReleaseResultsSet().\n"
+		"OGRDataSource::ReleaseResultSet().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -16030,8 +16737,54 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"hLayer:  handle to the layer on which features are read. \n"
 		""},
-	 { (char *)"Layer_GetName", _wrap_Layer_GetName, METH_VARARGS, (char *)"Layer_GetName(Layer self) -> char"},
-	 { (char *)"Layer_GetGeomType", _wrap_Layer_GetGeomType, METH_VARARGS, (char *)"Layer_GetGeomType(Layer self) -> OGRwkbGeometryType"},
+	 { (char *)"Layer_GetName", _wrap_Layer_GetName, METH_VARARGS, (char *)"\n"
+		"Layer_GetName(Layer self) -> char\n"
+		"\n"
+		"const char* OGR_L_GetName(OGRLayerH\n"
+		"hLayer)\n"
+		"\n"
+		"Return the layer name.\n"
+		"\n"
+		"This returns the same content as\n"
+		"OGR_FD_GetName(OGR_L_GetLayerDefn(hLayer)), but for a few drivers,\n"
+		"calling OGR_L_GetName() directly can avoid lengthy layer definition\n"
+		"initialization.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::GetName().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"the layer name (must not been freed)\n"
+		"\n"
+		"OGR 1.8.0 \n"
+		""},
+	 { (char *)"Layer_GetGeomType", _wrap_Layer_GetGeomType, METH_VARARGS, (char *)"\n"
+		"Layer_GetGeomType(Layer self) -> OGRwkbGeometryType\n"
+		"\n"
+		"OGRwkbGeometryType\n"
+		"OGR_L_GetGeomType(OGRLayerH hLayer)\n"
+		"\n"
+		"Return the layer geometry type.\n"
+		"\n"
+		"This returns the same result as\n"
+		"OGR_FD_GetGeomType(OGR_L_GetLayerDefn(hLayer)), but for a few drivers,\n"
+		"calling OGR_L_GetGeomType() directly can avoid lengthy layer\n"
+		"definition initialization.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::GetGeomType().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"the geometry type\n"
+		"\n"
+		"OGR 1.8.0 \n"
+		""},
 	 { (char *)"Layer_GetGeometryColumn", _wrap_Layer_GetGeometryColumn, METH_VARARGS, (char *)"\n"
 		"Layer_GetGeometryColumn(Layer self) -> char\n"
 		"\n"
@@ -16124,8 +16877,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"This function implements sequential access to the features of a layer.\n"
 		"The OGR_L_ResetReading() function can be used to start at the\n"
-		"beginning again. Random reading, writing and spatial filtering will be\n"
-		"added to the OGRLayer in the future.\n"
+		"beginning again.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
 		"OGRLayer::GetNextFeature().\n"
@@ -16316,6 +17068,9 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"The returned count takes the spatial filter into account.\n"
 		"\n"
+		"Note that some implementations of this method may alter the read\n"
+		"cursor of the layer.\n"
+		"\n"
 		"This function is the same as the CPP OGRLayer::GetFeatureCount().\n"
 		"\n"
 		"Parameters:\n"
@@ -16329,7 +17084,7 @@ 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) -> OGRErr\n"
+		"Layer_GetExtent(Layer self, int force = 1, int can_return_null = 0)\n"
 		"\n"
 		"OGRErr OGR_L_GetExtent(OGRLayerH\n"
 		"hLayer, OGREnvelope *psExtent, int bForce)\n"
@@ -16349,6 +17104,9 @@ static PyMethodDef SwigMethods[] = {
 		"Layers without any geometry may return OGRERR_FAILURE just indicating\n"
 		"that no meaningful extents could be collected.\n"
 		"\n"
+		"Note that some implementations of this method may alter the read\n"
+		"cursor of the layer.\n"
+		"\n"
 		"This function is the same as the C++ method OGRLayer::GetExtent().\n"
 		"\n"
 		"Parameters:\n"
@@ -16414,6 +17172,18 @@ static PyMethodDef SwigMethods[] = {
 		"OLCCreateField / \"CreateField\": TRUE if this layer can create new\n"
 		"fields on the current layer using CreateField(), otherwise FALSE.\n"
 		"\n"
+		"OLCDeleteField / \"DeleteField\": TRUE if this layer can delete\n"
+		"existing fields on the current layer using DeleteField(), otherwise\n"
+		"FALSE.\n"
+		"\n"
+		"OLCReorderFields / \"ReorderFields\": TRUE if this layer can reorder\n"
+		"existing fields on the current layer using ReorderField() or\n"
+		"ReorderFields(), otherwise FALSE.\n"
+		"\n"
+		"OLCAlterFieldDefn / \"AlterFieldDefn\": TRUE if this layer can alter\n"
+		"the definition of an existing field on the current layer using\n"
+		"AlterFieldDefn(), otherwise FALSE.\n"
+		"\n"
 		"OLCDeleteFeature / \"DeleteFeature\": TRUE if the DeleteFeature()\n"
 		"method is supported on this layer, otherwise FALSE.\n"
 		"\n"
@@ -16452,6 +17222,16 @@ static PyMethodDef SwigMethods[] = {
 		"Applications should never modify the OGRFeatureDefn used by a layer\n"
 		"directly.\n"
 		"\n"
+		"This function should not be called while there are feature objects in\n"
+		"existance that were obtained or created with the previous layer\n"
+		"definition.\n"
+		"\n"
+		"Not all drivers support this function. You can query a layer to check\n"
+		"if it supports it with the OLCCreateField capability. Some drivers may\n"
+		"only support this method while there are still no features in the\n"
+		"layer. When it is supported, the existings features of the backing\n"
+		"file/database should be updated accordingly.\n"
+		"\n"
 		"This function is the same as the C++ method OGRLayer::CreateField().\n"
 		"\n"
 		"Parameters:\n"
@@ -16466,6 +17246,184 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"OGRERR_NONE on success. \n"
 		""},
+	 { (char *)"Layer_DeleteField", _wrap_Layer_DeleteField, METH_VARARGS, (char *)"\n"
+		"Layer_DeleteField(Layer self, int iField) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_DeleteField(OGRLayerH hLayer, int iField)\n"
+		"\n"
+		"Create a new field on a layer.\n"
+		"\n"
+		"You must use this to delete existing fields on a real layer.\n"
+		"Internally the OGRFeatureDefn for the layer will be updated to reflect\n"
+		"the deleted field. Applications should never modify the OGRFeatureDefn\n"
+		"used by a layer directly.\n"
+		"\n"
+		"This function should not be called while there are feature objects in\n"
+		"existance that were obtained or created with the previous layer\n"
+		"definition.\n"
+		"\n"
+		"Not all drivers support this function. You can query a layer to check\n"
+		"if it supports it with the OLCDeleteField capability. Some drivers may\n"
+		"only support this method while there are still no features in the\n"
+		"layer. When it is supported, the existings features of the backing\n"
+		"file/database should be updated accordingly.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::DeleteField().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"iField:  index of the field to delete.\n"
+		"\n"
+		"OGRERR_NONE on success.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
+	 { (char *)"Layer_ReorderField", _wrap_Layer_ReorderField, METH_VARARGS, (char *)"\n"
+		"Layer_ReorderField(Layer self, int iOldFieldPos, int iNewFieldPos) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_ReorderField(OGRLayerH hLayer, int iOldFieldPos, int\n"
+		"iNewFieldPos)\n"
+		"\n"
+		"Reorder an existing field on a layer.\n"
+		"\n"
+		"This function is a conveniency wrapper of OGR_L_ReorderFields()\n"
+		"dedicated to move a single field.\n"
+		"\n"
+		"You must use this to reorder existing fields on a real layer.\n"
+		"Internally the OGRFeatureDefn for the layer will be updated to reflect\n"
+		"the reordering of the fields. Applications should never modify the\n"
+		"OGRFeatureDefn used by a layer directly.\n"
+		"\n"
+		"This function should not be called while there are feature objects in\n"
+		"existance that were obtained or created with the previous layer\n"
+		"definition.\n"
+		"\n"
+		"The field definition that was at initial position iOldFieldPos will be\n"
+		"moved at position iNewFieldPos, and elements between will be shuffled\n"
+		"accordingly.\n"
+		"\n"
+		"For example, let suppose the fields were \"0\",\"1\",\"2\",\"3\",\"4\"\n"
+		"initially. ReorderField(1, 3) will reorder them as\n"
+		"\"0\",\"2\",\"3\",\"1\",\"4\".\n"
+		"\n"
+		"Not all drivers support this function. You can query a layer to check\n"
+		"if it supports it with the OLCReorderFields capability. Some drivers\n"
+		"may only support this method while there are still no features in the\n"
+		"layer. When it is supported, the existings features of the backing\n"
+		"file/database should be updated accordingly.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::ReorderField().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"iOldFieldPos:  previous position of the field to move. Must be in the\n"
+		"range [0,GetFieldCount()-1].\n"
+		"\n"
+		"iNewFieldPos:  new position of the field to move. Must be in the range\n"
+		"[0,GetFieldCount()-1].\n"
+		"\n"
+		"OGRERR_NONE on success.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
+	 { (char *)"Layer_ReorderFields", _wrap_Layer_ReorderFields, METH_VARARGS, (char *)"\n"
+		"Layer_ReorderFields(Layer self, int nList) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_ReorderFields(OGRLayerH hLayer, int *panMap)\n"
+		"\n"
+		"Reorder all the fields of a layer.\n"
+		"\n"
+		"You must use this to reorder existing fields on a real layer.\n"
+		"Internally the OGRFeatureDefn for the layer will be updated to reflect\n"
+		"the reordering of the fields. Applications should never modify the\n"
+		"OGRFeatureDefn used by a layer directly.\n"
+		"\n"
+		"This function should not be called while there are feature objects in\n"
+		"existance that were obtained or created with the previous layer\n"
+		"definition.\n"
+		"\n"
+		"panMap is such that,for each field definition at position i after\n"
+		"reordering, its position before reordering was panMap[i].\n"
+		"\n"
+		"For example, let suppose the fields were \"0\",\"1\",\"2\",\"3\",\"4\"\n"
+		"initially. ReorderFields([0,2,3,1,4]) will reorder them as\n"
+		"\"0\",\"2\",\"3\",\"1\",\"4\".\n"
+		"\n"
+		"Not all drivers support this function. You can query a layer to check\n"
+		"if it supports it with the OLCReorderFields capability. Some drivers\n"
+		"may only support this method while there are still no features in the\n"
+		"layer. When it is supported, the existings features of the backing\n"
+		"file/database should be updated accordingly.\n"
+		"\n"
+		"This function is the same as the C++ method OGRLayer::ReorderFields().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"panMap:  an array of GetLayerDefn()->GetFieldCount() elements which is\n"
+		"a permutation of [0, GetLayerDefn()->GetFieldCount()-1].\n"
+		"\n"
+		"OGRERR_NONE on success.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
+	 { (char *)"Layer_AlterFieldDefn", _wrap_Layer_AlterFieldDefn, METH_VARARGS, (char *)"\n"
+		"Layer_AlterFieldDefn(Layer self, int iField, FieldDefn field_def, int nFlags) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_AlterFieldDefn(OGRLayerH hLayer, int iField, OGRFieldDefnH\n"
+		"hNewFieldDefn, int nFlags)\n"
+		"\n"
+		"Alter the definition of an existing field on a layer.\n"
+		"\n"
+		"You must use this to alter the definition of an existing field of a\n"
+		"real layer. Internally the OGRFeatureDefn for the layer will be\n"
+		"updated to reflect the altered field. Applications should never modify\n"
+		"the OGRFeatureDefn used by a layer directly.\n"
+		"\n"
+		"This function should not be called while there are feature objects in\n"
+		"existance that were obtained or created with the previous layer\n"
+		"definition.\n"
+		"\n"
+		"Not all drivers support this function. You can query a layer to check\n"
+		"if it supports it with the OLCAlterFieldDefn capability. Some drivers\n"
+		"may only support this method while there are still no features in the\n"
+		"layer. When it is supported, the existings features of the backing\n"
+		"file/database should be updated accordingly. Some drivers might also\n"
+		"not support all update flags.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRLayer::AlterFieldDefn().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hLayer:  handle to the layer.\n"
+		"\n"
+		"iField:  index of the field whose definition must be altered.\n"
+		"\n"
+		"hNewFieldDefn:  new field definition\n"
+		"\n"
+		"nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and\n"
+		"ALTER_WIDTH_PRECISION_FLAG to indicate which of the name and/or type\n"
+		"and/or width and precision fields from the new field definition must\n"
+		"be taken into account.\n"
+		"\n"
+		"OGRERR_NONE on success.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
 	 { (char *)"Layer_StartTransaction", _wrap_Layer_StartTransaction, METH_VARARGS, (char *)"\n"
 		"Layer_StartTransaction(Layer self) -> OGRErr\n"
 		"\n"
@@ -16560,7 +17518,37 @@ static PyMethodDef SwigMethods[] = {
 		"GIntBig\n"
 		"OGR_L_GetFeaturesRead(OGRLayerH hLayer) \n"
 		""},
-	 { (char *)"Layer_SetIgnoredFields", _wrap_Layer_SetIgnoredFields, METH_VARARGS, (char *)"Layer_SetIgnoredFields(Layer self, char options) -> OGRErr"},
+	 { (char *)"Layer_SetIgnoredFields", _wrap_Layer_SetIgnoredFields, METH_VARARGS, (char *)"\n"
+		"Layer_SetIgnoredFields(Layer self, char options) -> OGRErr\n"
+		"\n"
+		"OGRErr\n"
+		"OGR_L_SetIgnoredFields(OGRLayerH hLayer, const char **papszFields)\n"
+		"\n"
+		"Set which fields can be omitted when retrieving features from the\n"
+		"layer.\n"
+		"\n"
+		"If the driver supports this functionality (testable using\n"
+		"OLCIgnoreFields capability), it will not fetch the specified fields in\n"
+		"subsequent calls to GetFeature() / GetNextFeature() and thus save some\n"
+		"processing time and/or bandwidth.\n"
+		"\n"
+		"Besides field names of the layers, the following special fields can be\n"
+		"passed: \"OGR_GEOMETRY\" to ignore geometry and \"OGR_STYLE\" to\n"
+		"ignore layer style.\n"
+		"\n"
+		"By default, no fields are ignored.\n"
+		"\n"
+		"This method is the same as the C++ method OGRLayer::SetIgnoredFields()\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"papszFields:  an array of field names terminated by NULL item. If NULL\n"
+		"is passed, the ignored list is cleared.\n"
+		"\n"
+		"OGRERR_NONE if all field names have been resolved (even if the driver\n"
+		"does not support this method) \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"},
@@ -16760,7 +17748,7 @@ static PyMethodDef SwigMethods[] = {
 		"iField:  the field to fetch, from 0 to GetFieldCount()-1.\n"
 		"\n"
 		"the field value. This string is internal, and should not be modified,\n"
-		"or freed. It's lifetime may be very brief. \n"
+		"or freed. Its lifetime may be very brief. \n"
 		""},
 	 { (char *)"Feature_GetFieldAsInteger", _wrap_Feature_GetFieldAsInteger, METH_VARARGS, (char *)"\n"
 		"GetFieldAsInteger(int id) -> int\n"
@@ -16876,7 +17864,7 @@ static PyMethodDef SwigMethods[] = {
 		"pnCount:  an integer to put the list count (number of integers) into.\n"
 		"\n"
 		"the field value. This list is internal, and should not be modified, or\n"
-		"freed. It's lifetime may be very brief. If *pnCount is zero on return\n"
+		"freed. Its lifetime may be very brief. If *pnCount is zero on return\n"
 		"the returned pointer may be NULL or non-NULL. \n"
 		""},
 	 { (char *)"Feature_GetFieldAsDoubleList", _wrap_Feature_GetFieldAsDoubleList, METH_VARARGS, (char *)"\n"
@@ -16903,7 +17891,7 @@ static PyMethodDef SwigMethods[] = {
 		"pnCount:  an integer to put the list count (number of doubles) into.\n"
 		"\n"
 		"the field value. This list is internal, and should not be modified, or\n"
-		"freed. It's lifetime may be very brief. If *pnCount is zero on return\n"
+		"freed. Its lifetime may be very brief. If *pnCount is zero on return\n"
 		"the returned pointer may be NULL or non-NULL. \n"
 		""},
 	 { (char *)"Feature_GetFieldAsStringList", _wrap_Feature_GetFieldAsStringList, METH_VARARGS, (char *)"\n"
@@ -16930,7 +17918,7 @@ static PyMethodDef SwigMethods[] = {
 		"iField:  the field to fetch, from 0 to GetFieldCount()-1.\n"
 		"\n"
 		"the field value. This list is internal, and should not be modified, or\n"
-		"freed. It's lifetime may be very brief. \n"
+		"freed. Its lifetime may be very brief. \n"
 		""},
 	 { (char *)"Feature_IsFieldSet", _wrap_Feature_IsFieldSet, METH_VARARGS, (char *)"\n"
 		"IsFieldSet(int id) -> bool\n"
@@ -17350,12 +18338,15 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"Add a new field definition to the passed feature definition.\n"
 		"\n"
+		"To add a new field definition to a layer definition, do not use this\n"
+		"function directly, but use OGR_L_CreateField() instead.\n"
+		"\n"
 		"This function should only be called while there are no OGRFeature\n"
 		"objects in existance based on this OGRFeatureDefn. The OGRFieldDefn\n"
 		"passed in is copied, and remains the responsibility of the caller.\n"
 		"\n"
 		"This function is the same as the C++ method\n"
-		"OGRFeatureDefn::AddFieldDefn.\n"
+		"OGRFeatureDefn::AddFieldDefn().\n"
 		"\n"
 		"Parameters:\n"
 		"-----------\n"
@@ -17428,10 +18419,82 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"the current reference count. \n"
 		""},
-	 { (char *)"FeatureDefn_IsGeometryIgnored", _wrap_FeatureDefn_IsGeometryIgnored, METH_VARARGS, (char *)"FeatureDefn_IsGeometryIgnored(FeatureDefn self) -> int"},
-	 { (char *)"FeatureDefn_SetGeometryIgnored", _wrap_FeatureDefn_SetGeometryIgnored, METH_VARARGS, (char *)"FeatureDefn_SetGeometryIgnored(FeatureDefn self, int bIgnored)"},
-	 { (char *)"FeatureDefn_IsStyleIgnored", _wrap_FeatureDefn_IsStyleIgnored, METH_VARARGS, (char *)"FeatureDefn_IsStyleIgnored(FeatureDefn self) -> int"},
-	 { (char *)"FeatureDefn_SetStyleIgnored", _wrap_FeatureDefn_SetStyleIgnored, METH_VARARGS, (char *)"FeatureDefn_SetStyleIgnored(FeatureDefn self, int bIgnored)"},
+	 { (char *)"FeatureDefn_IsGeometryIgnored", _wrap_FeatureDefn_IsGeometryIgnored, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_IsGeometryIgnored(FeatureDefn self) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_FD_IsGeometryIgnored(OGRFeatureDefnH hDefn)\n"
+		"\n"
+		"Determine whether the geometry can be omitted when fetching features.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeatureDefn::IsGeometryIgnored().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  hanlde to the feature definition on witch OGRFeature are based\n"
+		"on.\n"
+		"\n"
+		"ignore state \n"
+		""},
+	 { (char *)"FeatureDefn_SetGeometryIgnored", _wrap_FeatureDefn_SetGeometryIgnored, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_SetGeometryIgnored(FeatureDefn self, int bIgnored)\n"
+		"\n"
+		"void\n"
+		"OGR_FD_SetGeometryIgnored(OGRFeatureDefnH hDefn, int bIgnore)\n"
+		"\n"
+		"Set whether the geometry can be omitted when fetching features.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeatureDefn::SetGeometryIgnored().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  hanlde to the feature definition on witch OGRFeature are based\n"
+		"on.\n"
+		"\n"
+		"bIgnore:  ignore state \n"
+		""},
+	 { (char *)"FeatureDefn_IsStyleIgnored", _wrap_FeatureDefn_IsStyleIgnored, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_IsStyleIgnored(FeatureDefn self) -> int\n"
+		"\n"
+		"int\n"
+		"OGR_FD_IsStyleIgnored(OGRFeatureDefnH hDefn)\n"
+		"\n"
+		"Determine whether the style can be omitted when fetching features.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeatureDefn::IsStyleIgnored().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the feature definition on which OGRFeature are based\n"
+		"on.\n"
+		"\n"
+		"ignore state \n"
+		""},
+	 { (char *)"FeatureDefn_SetStyleIgnored", _wrap_FeatureDefn_SetStyleIgnored, METH_VARARGS, (char *)"\n"
+		"FeatureDefn_SetStyleIgnored(FeatureDefn self, int bIgnored)\n"
+		"\n"
+		"void\n"
+		"OGR_FD_SetStyleIgnored(OGRFeatureDefnH hDefn, int bIgnore)\n"
+		"\n"
+		"Set whether the style can be omitted when fetching features.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRFeatureDefn::SetStyleIgnored().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  hanlde to the feature definition on witch OGRFeature are based\n"
+		"on.\n"
+		"\n"
+		"bIgnore:  ignore state \n"
+		""},
 	 { (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"},
@@ -17617,8 +18680,40 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"FieldDefn_GetTypeName", _wrap_FieldDefn_GetTypeName, METH_VARARGS, (char *)"FieldDefn_GetTypeName(FieldDefn self) -> char"},
 	 { (char *)"FieldDefn_GetFieldTypeName", _wrap_FieldDefn_GetFieldTypeName, METH_VARARGS, (char *)"FieldDefn_GetFieldTypeName(FieldDefn self, OGRFieldType type) -> char"},
-	 { (char *)"FieldDefn_IsIgnored", _wrap_FieldDefn_IsIgnored, METH_VARARGS, (char *)"FieldDefn_IsIgnored(FieldDefn self) -> int"},
-	 { (char *)"FieldDefn_SetIgnored", _wrap_FieldDefn_SetIgnored, METH_VARARGS, (char *)"FieldDefn_SetIgnored(FieldDefn self, int bIgnored)"},
+	 { (char *)"FieldDefn_IsIgnored", _wrap_FieldDefn_IsIgnored, METH_VARARGS, (char *)"\n"
+		"FieldDefn_IsIgnored(FieldDefn self) -> int\n"
+		"\n"
+		"int OGR_Fld_IsIgnored(OGRFieldDefnH\n"
+		"hDefn)\n"
+		"\n"
+		"Return whether this field should be omitted when fetching features.\n"
+		"\n"
+		"This method is the same as the C++ method OGRFieldDefn::IsIgnored().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition\n"
+		"\n"
+		"ignore state \n"
+		""},
+	 { (char *)"FieldDefn_SetIgnored", _wrap_FieldDefn_SetIgnored, METH_VARARGS, (char *)"\n"
+		"FieldDefn_SetIgnored(FieldDefn self, int bIgnored)\n"
+		"\n"
+		"void\n"
+		"OGR_Fld_SetIgnored(OGRFieldDefnH hDefn, int ignore)\n"
+		"\n"
+		"Set whether this field should be omitted when fetching features.\n"
+		"\n"
+		"This method is the same as the C function OGRFieldDefn::SetIgnored().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hDefn:  handle to the field definition\n"
+		"\n"
+		"ignore:  ignore state \n"
+		""},
 	 { (char *)"FieldDefn_swigregister", FieldDefn_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"},
@@ -17696,7 +18791,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"Geometry_ExportToGML", (PyCFunction) _wrap_Geometry_ExportToGML, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_ExportToGML(Geometry self, char options = None) -> retStringAndCPLFree"},
 	 { (char *)"Geometry_ExportToKML", _wrap_Geometry_ExportToKML, METH_VARARGS, (char *)"Geometry_ExportToKML(Geometry self, char altitude_mode = None) -> retStringAndCPLFree"},
-	 { (char *)"Geometry_ExportToJson", _wrap_Geometry_ExportToJson, METH_VARARGS, (char *)"Geometry_ExportToJson(Geometry self) -> retStringAndCPLFree"},
+	 { (char *)"Geometry_ExportToJson", (PyCFunction) _wrap_Geometry_ExportToJson, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_ExportToJson(Geometry self, char options = None) -> retStringAndCPLFree"},
 	 { (char *)"Geometry_AddPoint", (PyCFunction) _wrap_Geometry_AddPoint, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_AddPoint(Geometry self, double x, double y, double z = 0)"},
 	 { (char *)"Geometry_AddPoint_2D", _wrap_Geometry_AddPoint_2D, METH_VARARGS, (char *)"Geometry_AddPoint_2D(Geometry self, double x, double y)"},
 	 { (char *)"Geometry_AddGeometryDirectly", _wrap_Geometry_AddGeometryDirectly, METH_VARARGS, (char *)"Geometry_AddGeometryDirectly(Geometry self, Geometry other_disown) -> OGRErr"},
@@ -17767,6 +18862,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Geometry_Area", _wrap_Geometry_Area, METH_VARARGS, (char *)"Geometry_Area(Geometry self) -> double"},
 	 { (char *)"Geometry_GetArea", _wrap_Geometry_GetArea, METH_VARARGS, (char *)"Geometry_GetArea(Geometry self) -> double"},
 	 { (char *)"Geometry_GetPointCount", _wrap_Geometry_GetPointCount, METH_VARARGS, (char *)"Geometry_GetPointCount(Geometry self) -> int"},
+	 { (char *)"Geometry_GetPoints", (PyCFunction) _wrap_Geometry_GetPoints, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetPoints(Geometry self, int nCoordDimension = 0)"},
 	 { (char *)"Geometry_GetX", (PyCFunction) _wrap_Geometry_GetX, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetX(Geometry self, int point = 0) -> double"},
 	 { (char *)"Geometry_GetY", (PyCFunction) _wrap_Geometry_GetY, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetY(Geometry self, int point = 0) -> double"},
 	 { (char *)"Geometry_GetZ", (PyCFunction) _wrap_Geometry_GetZ, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_GetZ(Geometry self, int point = 0) -> double"},
@@ -17776,20 +18872,71 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Geometry_SetPoint", (PyCFunction) _wrap_Geometry_SetPoint, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_SetPoint(Geometry self, int point, double x, double y, double z = 0)"},
 	 { (char *)"Geometry_SetPoint_2D", (PyCFunction) _wrap_Geometry_SetPoint_2D, METH_VARARGS | METH_KEYWORDS, (char *)"Geometry_SetPoint_2D(Geometry self, int point, double x, double y)"},
 	 { (char *)"Geometry_GetGeometryRef", _wrap_Geometry_GetGeometryRef, METH_VARARGS, (char *)"Geometry_GetGeometryRef(Geometry self, int geom) -> Geometry"},
-	 { (char *)"Geometry_Simplify", _wrap_Geometry_Simplify, METH_VARARGS, (char *)"Geometry_Simplify(Geometry self, double tolerance) -> Geometry"},
-	 { (char *)"Geometry_Boundary", _wrap_Geometry_Boundary, METH_VARARGS, (char *)"Geometry_Boundary(Geometry self) -> Geometry"},
-	 { (char *)"Geometry_GetBoundary", _wrap_Geometry_GetBoundary, METH_VARARGS, (char *)"\n"
-		"Geometry_GetBoundary(Geometry self) -> Geometry\n"
+	 { (char *)"Geometry_Simplify", _wrap_Geometry_Simplify, METH_VARARGS, (char *)"\n"
+		"Geometry_Simplify(Geometry self, double tolerance) -> Geometry\n"
 		"\n"
 		"OGRGeometryH\n"
-		"OGR_G_GetBoundary(OGRGeometryH hTarget)\n"
+		"OGR_G_Simplify(OGRGeometryH hThis, double dTolerance)\n"
+		"\n"
+		"Compute a simplified geometry.\n"
+		"\n"
+		"This function is the same as the C++ method OGRGeometry::Simplify().\n"
+		"\n"
+		"This function is built on the GEOS library, check it for the\n"
+		"definition of the geometry operation. If OGR is built without the GEOS\n"
+		"library, this function will always fail, issuing a CPLE_NotSupported\n"
+		"error.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hThis:  the geometry.\n"
+		"\n"
+		"dTolerance:  the distance tolerance for the simplification.\n"
+		"\n"
+		"the simplified geometry or NULL if an error occurs.\n"
+		"\n"
+		"OGR 1.8.0 \n"
+		""},
+	 { (char *)"Geometry_SimplifyPreserveTopology", _wrap_Geometry_SimplifyPreserveTopology, METH_VARARGS, (char *)"\n"
+		"Geometry_SimplifyPreserveTopology(Geometry self, double tolerance) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_G_SimplifyPreserveTopology(OGRGeometryH hThis, double dTolerance)\n"
+		"\n"
+		"Compute a simplified geometry.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRGeometry::SimplifyPreserveTopology().\n"
+		"\n"
+		"This function is built on the GEOS library, check it for the\n"
+		"definition of the geometry operation. If OGR is built without the GEOS\n"
+		"library, this function will always fail, issuing a CPLE_NotSupported\n"
+		"error.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hThis:  the geometry.\n"
+		"\n"
+		"dTolerance:  the distance tolerance for the simplification.\n"
+		"\n"
+		"the simplified geometry or NULL if an error occurs.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
+	 { (char *)"Geometry_Boundary", _wrap_Geometry_Boundary, METH_VARARGS, (char *)"\n"
+		"Geometry_Boundary(Geometry self) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_G_Boundary(OGRGeometryH hTarget)\n"
 		"\n"
 		"Compute boundary.\n"
 		"\n"
 		"A new geometry object is created and returned containing the boundary\n"
 		"of the geometry on which the method is invoked.\n"
 		"\n"
-		"This function is the same as the C++ method OGR_G_GetBoundary().\n"
+		"This function is the same as the C++ method OGR_G_Boundary().\n"
 		"\n"
 		"This function is built on the GEOS library, check it for the\n"
 		"definition of the geometry operation. If OGR is built without the GEOS\n"
@@ -17802,7 +18949,19 @@ static PyMethodDef SwigMethods[] = {
 		"hTarget:  The Geometry to calculate the boundary of.\n"
 		"\n"
 		"a handle to a newly allocated geometry now owned by the caller, or\n"
-		"NULL on failure. \n"
+		"NULL on failure.\n"
+		"\n"
+		"OGR 1.8.0 \n"
+		""},
+	 { (char *)"Geometry_GetBoundary", _wrap_Geometry_GetBoundary, METH_VARARGS, (char *)"\n"
+		"Geometry_GetBoundary(Geometry self) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_G_GetBoundary(OGRGeometryH hTarget)\n"
+		"\n"
+		"Compute boundary (deprecated).\n"
+		"\n"
+		"Deprecated See:   OGR_G_Boundary() \n"
 		""},
 	 { (char *)"Geometry_ConvexHull", _wrap_Geometry_ConvexHull, METH_VARARGS, (char *)"\n"
 		"Geometry_ConvexHull(Geometry self) -> Geometry\n"
@@ -17925,7 +19084,29 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"a new geometry representing the union or NULL if an error occurs. \n"
 		""},
-	 { (char *)"Geometry_UnionCascaded", _wrap_Geometry_UnionCascaded, METH_VARARGS, (char *)"Geometry_UnionCascaded(Geometry self) -> Geometry"},
+	 { (char *)"Geometry_UnionCascaded", _wrap_Geometry_UnionCascaded, METH_VARARGS, (char *)"\n"
+		"Geometry_UnionCascaded(Geometry self) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_G_UnionCascaded(OGRGeometryH hThis)\n"
+		"\n"
+		"Compute union using cascading.\n"
+		"\n"
+		"This function is the same as the C++ method\n"
+		"OGRGeometry::UnionCascaded().\n"
+		"\n"
+		"This function is built on the GEOS library, check it for the\n"
+		"definition of the geometry operation. If OGR is built without the GEOS\n"
+		"library, this function will always fail, issuing a CPLE_NotSupported\n"
+		"error.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hThis:  the geometry.\n"
+		"\n"
+		"a new geometry representing the union or NULL if an error occurs. \n"
+		""},
 	 { (char *)"Geometry_Difference", _wrap_Geometry_Difference, METH_VARARGS, (char *)"\n"
 		"Geometry_Difference(Geometry self, Geometry other) -> Geometry\n"
 		"\n"
@@ -17954,12 +19135,11 @@ static PyMethodDef SwigMethods[] = {
 		"a new geometry representing the difference or NULL if the difference\n"
 		"is empty or an error occurs. \n"
 		""},
-	 { (char *)"Geometry_SymDifference", _wrap_Geometry_SymDifference, METH_VARARGS, (char *)"Geometry_SymDifference(Geometry self, Geometry other) -> Geometry"},
-	 { (char *)"Geometry_SymmetricDifference", _wrap_Geometry_SymmetricDifference, METH_VARARGS, (char *)"\n"
-		"Geometry_SymmetricDifference(Geometry self, Geometry other) -> Geometry\n"
+	 { (char *)"Geometry_SymDifference", _wrap_Geometry_SymDifference, METH_VARARGS, (char *)"\n"
+		"Geometry_SymDifference(Geometry self, Geometry other) -> Geometry\n"
 		"\n"
 		"OGRGeometryH\n"
-		"OGR_G_SymmetricDifference(OGRGeometryH hThis, OGRGeometryH hOther)\n"
+		"OGR_G_SymDifference(OGRGeometryH hThis, OGRGeometryH hOther)\n"
 		"\n"
 		"Compute symmetric difference.\n"
 		"\n"
@@ -17982,7 +19162,19 @@ static PyMethodDef SwigMethods[] = {
 		"hOther:  the other geometry.\n"
 		"\n"
 		"a new geometry representing the symmetric difference or NULL if the\n"
-		"difference is empty or an error occurs. \n"
+		"difference is empty or an error occurs.\n"
+		"\n"
+		"OGR 1.8.0 \n"
+		""},
+	 { (char *)"Geometry_SymmetricDifference", _wrap_Geometry_SymmetricDifference, METH_VARARGS, (char *)"\n"
+		"Geometry_SymmetricDifference(Geometry self, Geometry other) -> Geometry\n"
+		"\n"
+		"OGRGeometryH\n"
+		"OGR_G_SymmetricDifference(OGRGeometryH hThis, OGRGeometryH hOther)\n"
+		"\n"
+		"Compute symmetric difference (deprecated).\n"
+		"\n"
+		"Deprecated See:   OGR_G_SymmetricDifference() \n"
 		""},
 	 { (char *)"Geometry_Distance", _wrap_Geometry_Distance, METH_VARARGS, (char *)"\n"
 		"Geometry_Distance(Geometry self, Geometry other) -> double\n"
@@ -18441,7 +19633,18 @@ static PyMethodDef SwigMethods[] = {
 		"Geometry_CloseRings(Geometry self)\n"
 		"\n"
 		"void OGR_G_CloseRings(OGRGeometryH\n"
-		"hGeom) \n"
+		"hGeom)\n"
+		"\n"
+		"Force rings to be closed.\n"
+		"\n"
+		"If this geometry, or any contained geometries has polygon rings that\n"
+		"are not closed, they will be closed by adding the starting point at\n"
+		"the end.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle to the geometry. \n"
 		""},
 	 { (char *)"Geometry_FlattenTo2D", _wrap_Geometry_FlattenTo2D, METH_VARARGS, (char *)"\n"
 		"Geometry_FlattenTo2D(Geometry self)\n"
@@ -18501,7 +19704,54 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"psEnvelope:  the structure in which to place the results. \n"
 		""},
-	 { (char *)"Geometry_Centroid", _wrap_Geometry_Centroid, METH_VARARGS, (char *)"Geometry_Centroid(Geometry self) -> Geometry"},
+	 { (char *)"Geometry_GetEnvelope3D", _wrap_Geometry_GetEnvelope3D, METH_VARARGS, (char *)"\n"
+		"Geometry_GetEnvelope3D(Geometry self)\n"
+		"\n"
+		"void\n"
+		"OGR_G_GetEnvelope3D(OGRGeometryH hGeom, OGREnvelope3D *psEnvelope)\n"
+		"\n"
+		"Computes and returns the bounding envelope (3D) for this geometry in\n"
+		"the passed psEnvelope structure.\n"
+		"\n"
+		"This function is the same as the CPP method\n"
+		"OGRGeometry::getEnvelope().\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle of the geometry to get envelope from.\n"
+		"\n"
+		"psEnvelope:  the structure in which to place the results.\n"
+		"\n"
+		"OGR 1.9.0 \n"
+		""},
+	 { (char *)"Geometry_Centroid", _wrap_Geometry_Centroid, METH_VARARGS, (char *)"\n"
+		"Geometry_Centroid(Geometry self) -> Geometry\n"
+		"\n"
+		"int OGR_G_Centroid(OGRGeometryH\n"
+		"hGeom, OGRGeometryH hCentroidPoint)\n"
+		"\n"
+		"Compute the geometry centroid.\n"
+		"\n"
+		"The centroid location is applied to the passed in OGRPoint object. The\n"
+		"centroid is not necessarily within the geometry.\n"
+		"\n"
+		"This method relates to the SFCOM ISurface::get_Centroid() method\n"
+		"however the current implementation based on GEOS can operate on other\n"
+		"geometry types such as multipoint, linestring, geometrycollection such\n"
+		"as multipolygons. OGC SF SQL 1.1 defines the operation for surfaces\n"
+		"(polygons). SQL/MM-Part 3 defines the operation for surfaces and\n"
+		"multisurfaces (multipolygons).\n"
+		"\n"
+		"This function is the same as the C++ method OGRGeometry::Centroid().\n"
+		"\n"
+		"This function is built on the GEOS library, check it for the\n"
+		"definition of the geometry operation. If OGR is built without the GEOS\n"
+		"library, this function will always fail, issuing a CPLE_NotSupported\n"
+		"error.\n"
+		"\n"
+		"OGRERR_NONE on success or OGRERR_FAILURE on error. \n"
+		""},
 	 { (char *)"Geometry_WkbSize", _wrap_Geometry_WkbSize, METH_VARARGS, (char *)"\n"
 		"Geometry_WkbSize(Geometry self) -> int\n"
 		"\n"
@@ -18544,14 +19794,29 @@ static PyMethodDef SwigMethods[] = {
 		"hGeom:  handle on the geometry to get the dimension of the coordinates\n"
 		"from.\n"
 		"\n"
-		"in practice this always returns 2 indicating that coordinates are\n"
-		"specified within a two dimensional space. \n"
+		"in practice this will return 2 or 3. It can also return 0 in the case\n"
+		"of an empty point. \n"
 		""},
 	 { (char *)"Geometry_SetCoordinateDimension", _wrap_Geometry_SetCoordinateDimension, METH_VARARGS, (char *)"\n"
 		"Geometry_SetCoordinateDimension(Geometry self, int dimension)\n"
 		"\n"
 		"void\n"
-		"OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension) \n"
+		"OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension)\n"
+		"\n"
+		"Set the coordinate dimension.\n"
+		"\n"
+		"This method sets the explicit coordinate dimension. Setting the\n"
+		"coordinate dimension of a geometry to 2 should zero out any existing Z\n"
+		"values. Setting the dimension of a geometry collection will not\n"
+		"necessarily affect the children geometries.\n"
+		"\n"
+		"Parameters:\n"
+		"-----------\n"
+		"\n"
+		"hGeom:  handle on the geometry to set the dimension of the\n"
+		"coordinates.\n"
+		"\n"
+		"nNewDimension:  New coordinate dimension value, either 2 or 3. \n"
 		""},
 	 { (char *)"Geometry_GetDimension", _wrap_Geometry_GetDimension, METH_VARARGS, (char *)"\n"
 		"Geometry_GetDimension(Geometry self) -> int\n"
@@ -19295,6 +20560,10 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "wkbXDR",SWIG_From_int(static_cast< int >(0)));
   SWIG_Python_SetConstant(d, "wkbNDR",SWIG_From_int(static_cast< int >(1)));
   SWIG_Python_SetConstant(d, "NullFID",SWIG_From_int(static_cast< int >(-1)));
+  SWIG_Python_SetConstant(d, "ALTER_NAME_FLAG",SWIG_From_int(static_cast< int >(1)));
+  SWIG_Python_SetConstant(d, "ALTER_TYPE_FLAG",SWIG_From_int(static_cast< int >(2)));
+  SWIG_Python_SetConstant(d, "ALTER_WIDTH_PRECISION_FLAG",SWIG_From_int(static_cast< int >(4)));
+  SWIG_Python_SetConstant(d, "ALTER_ALL_FLAG",SWIG_From_int(static_cast< int >(1+2+4)));
   SWIG_Python_SetConstant(d, "OLCRandomRead",SWIG_FromCharPtr("RandomRead"));
   SWIG_Python_SetConstant(d, "OLCSequentialWrite",SWIG_FromCharPtr("SequentialWrite"));
   SWIG_Python_SetConstant(d, "OLCRandomWrite",SWIG_FromCharPtr("RandomWrite"));
@@ -19302,6 +20571,9 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "OLCFastFeatureCount",SWIG_FromCharPtr("FastFeatureCount"));
   SWIG_Python_SetConstant(d, "OLCFastGetExtent",SWIG_FromCharPtr("FastGetExtent"));
   SWIG_Python_SetConstant(d, "OLCCreateField",SWIG_FromCharPtr("CreateField"));
+  SWIG_Python_SetConstant(d, "OLCDeleteField",SWIG_FromCharPtr("DeleteField"));
+  SWIG_Python_SetConstant(d, "OLCReorderFields",SWIG_FromCharPtr("ReorderFields"));
+  SWIG_Python_SetConstant(d, "OLCAlterFieldDefn",SWIG_FromCharPtr("AlterFieldDefn"));
   SWIG_Python_SetConstant(d, "OLCTransactions",SWIG_FromCharPtr("Transactions"));
   SWIG_Python_SetConstant(d, "OLCDeleteFeature",SWIG_FromCharPtr("DeleteFeature"));
   SWIG_Python_SetConstant(d, "OLCFastSetNextByIndex",SWIG_FromCharPtr("FastSetNextByIndex"));
diff --git a/swig/python/extensions/osr_wrap.cpp b/swig/python/extensions/osr_wrap.cpp
index 932e585..4f37896 100644
--- a/swig/python/extensions/osr_wrap.cpp
+++ b/swig/python/extensions/osr_wrap.cpp
@@ -1129,6 +1129,10 @@ SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
 
 /* Runtime API */
 
+#if PY_VERSION_HEX >= 0x03020000
+#define SWIG_PYTHON_USE_CAPSULE
+#endif
+
 #define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
 #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
 #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
@@ -2448,8 +2452,12 @@ SWIG_Python_GetModule(void) {
 #ifdef SWIG_LINK_RUNTIME
     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
 #else
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
+#else
     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+#endif
     if (PyErr_Occurred()) {
       PyErr_Clear();
       type_pointer = (void *)0;
@@ -2492,11 +2500,26 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 #endif
 
 SWIGRUNTIME void
+#ifdef SWIG_PYTHON_USE_CAPSULE
+SWIG_Python_DestroyModule(PyObject *capsule)
+{
+  swig_module_info *swig_module;
+  swig_type_info **types;
+  size_t i;
+  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+  if (swig_module == NULL)
+  {
+    PyErr_Clear();
+    return;
+  }
+  types = swig_module->types;
+#else
 SWIG_Python_DestroyModule(void *vptr)
 {
   swig_module_info *swig_module = (swig_module_info *) vptr;
   swig_type_info **types = swig_module->types;
   size_t i;
+#endif
   for (i =0; i < swig_module->size; ++i) {
     swig_type_info *ty = types[i];
     if (ty->owndata) {
@@ -2518,7 +2541,13 @@ SWIG_Python_SetModule(swig_module_info *swig_module) {
   PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
 				   swig_empty_runtime_method_table);
 #endif
+#ifdef SWIG_PYTHON_USE_CAPSULE
+  PyObject *pointer = PyCapsule_New((void *) swig_module,
+                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
+                                    SWIG_Python_DestroyModule);
+#else
   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+#endif
   if (pointer && module) {
     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
   } else {
@@ -2541,12 +2570,20 @@ SWIG_Python_TypeQuery(const char *type)
   PyObject *obj = PyDict_GetItem(cache, key);
   swig_type_info *descriptor;
   if (obj) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
+#else
     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+#endif
   } else {
     swig_module_info *swig_module = SWIG_Python_GetModule();
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
+#ifdef SWIG_PYTHON_USE_CAPSULE
+      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
+#else
       obj = PyCObject_FromVoidPtr(descriptor, NULL);
+#endif
       PyDict_SetItem(cache, key, obj);
       Py_DECREF(obj);
     }
@@ -3188,15 +3225,27 @@ SWIGINTERN int OSRSpatialReferenceShadow_IsSame(OSRSpatialReferenceShadow *self,
 SWIGINTERN int OSRSpatialReferenceShadow_IsSameGeogCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
     return OSRIsSameGeogCS( self, rhs );
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsSameVertCS(OSRSpatialReferenceShadow *self,OSRSpatialReferenceShadow *rhs){
+    return OSRIsSameVertCS( self, rhs );
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsGeographic(OSRSpatialReferenceShadow *self){
     return OSRIsGeographic(self);
   }
 SWIGINTERN int OSRSpatialReferenceShadow_IsProjected(OSRSpatialReferenceShadow *self){
     return OSRIsProjected(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsCompound(OSRSpatialReferenceShadow *self){
+    return OSRIsCompound(self);
+  }
+SWIGINTERN int OSRSpatialReferenceShadow_IsGeocentric(OSRSpatialReferenceShadow *self){
+    return OSRIsGeocentric(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_IsLocal(OSRSpatialReferenceShadow *self){
     return OSRIsLocal(self);
   }
+SWIGINTERN int OSRSpatialReferenceShadow_IsVertical(OSRSpatialReferenceShadow *self){
+    return OSRIsVertical(self);
+  }
 SWIGINTERN int OSRSpatialReferenceShadow_EPSGTreatsAsLatLong(OSRSpatialReferenceShadow *self){
     return OSREPSGTreatsAsLatLong(self);
   }
@@ -3361,6 +3410,9 @@ SWIGINTERN double OSRSpatialReferenceShadow_GetAngularUnits(OSRSpatialReferenceS
     // Return code ignored.
     return OSRGetAngularUnits( self, 0 );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target,char const *name,double to_meters){
+    return OSRSetTargetLinearUnits( self, target, name, to_meters );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnits( self, name, to_meters );
   }
@@ -3485,6 +3537,9 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGS(OSRSpatialReferenceShadow *sel
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGH(OSRSpatialReferenceShadow *self,double cm,double fe,double fn){
     return OSRSetGH( self, cm, fe, fn );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetIGH(OSRSpatialReferenceShadow *self){
+    return OSRSetIGH( self );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGEOS(OSRSpatialReferenceShadow *self,double cm,double satelliteheight,double fe,double fn){
     return OSRSetGEOS( self, cm, satelliteheight,
                        fe, fn );
@@ -3626,6 +3681,15 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeogCS(OSRSpatialReferenceShadow
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetProjCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
     return OSRSetProjCS( self, name );
   }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetGeocCS(OSRSpatialReferenceShadow *self,char const *name="unnamed"){
+    return OSRSetGeocCS( self, name );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetVertCS(OSRSpatialReferenceShadow *self,char const *VertCSName="unnamed",char const *VertDatumName="unnamed",int VertDatumType=0){
+    return OSRSetVertCS( self, VertCSName, VertDatumName, VertDatumType );
+  }
+SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetCompoundCS(OSRSpatialReferenceShadow *self,char const *name,OSRSpatialReferenceShadow *horizcs,OSRSpatialReferenceShadow *vertcs){
+    return OSRSetCompoundCS( self, name, horizcs, vertcs );
+  }
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_ImportFromWkt(OSRSpatialReferenceShadow *self,char **ppszInput){
     return OSRImportFromWkt( self, ppszInput );
   }
@@ -3712,9 +3776,13 @@ SWIGINTERN void delete_OSRCoordinateTransformationShadow(OSRCoordinateTransforma
     OCTDestroyCoordinateTransformation( self );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_0(OSRCoordinateTransformationShadow *self,double inout[3]){
+    if (self == NULL)
+        return;
     OCTTransform( self, 1, &inout[0], &inout[1], &inout[2] );
   }
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoint__SWIG_1(OSRCoordinateTransformationShadow *self,double argout[3],double x,double y,double z=0.0){
+    if (self == NULL)
+        return;
     argout[0] = x;
     argout[1] = y;
     argout[2] = z;
@@ -3796,6 +3864,8 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
 }
 
 SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoints(OSRCoordinateTransformationShadow *self,int nCount,double *x,double *y,double *z){
+    if (self == NULL)
+        return;
     OCTTransform( self, nCount, x, y, z );
   }
 #ifdef __cplusplus
@@ -4215,6 +4285,53 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_IsSameVertCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg2 = (OSRSpatialReferenceShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:SpatialReference_IsSameVertCS",&obj0,&obj1)) 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_IsSameVertCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_IsSameVertCS" "', argument " "2"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OSRSpatialReferenceShadow_IsSameVertCS(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_SpatialReference_IsGeographic(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -4281,6 +4398,72 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_IsCompound(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_IsCompound",&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_IsCompound" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OSRSpatialReferenceShadow_IsCompound(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_IsGeocentric(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_IsGeocentric",&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_IsGeocentric" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OSRSpatialReferenceShadow_IsGeocentric(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_IsLocal(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -4314,6 +4497,39 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_IsVertical(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_IsVertical",&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_IsVertical" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (int)OSRSpatialReferenceShadow_IsVertical(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_EPSGTreatsAsLatLong(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -4676,6 +4892,93 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_SetTargetLinearUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  double arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:SpatialReference_SetTargetLinearUnits",&obj0,&obj1,&obj2,&obj3)) 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_SetTargetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetTargetLinearUnits" "', 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 '" "SpatialReference_SetTargetLinearUnits" "', argument " "3"" of type '" "char const *""'");
+  }
+  arg3 = reinterpret_cast< char * >(buf3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetTargetLinearUnits" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  {
+    if (!arg3) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OSRSpatialReferenceShadow_SetTargetLinearUnits(arg1,(char const *)arg2,(char const *)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;
+    }
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  {
+    /* %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;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -6821,6 +7124,55 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_SetIGH(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:SpatialReference_SetIGH",&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_SetIGH" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OSRSpatialReferenceShadow_SetIGH(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_SpatialReference_SetGEOS(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -9940,6 +10292,256 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_SetGeocCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) "unnamed" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|O:SpatialReference_SetGeocCS",&obj0,&obj1)) 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_SetGeocCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  if (obj1) {
+    res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetGeocCS" "', 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 = (OGRErr)OSRSpatialReferenceShadow_SetGeocCS(arg1,(char const *)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;
+    }
+  }
+  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_SpatialReference_SetVertCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) "unnamed" ;
+  char *arg3 = (char *) "unnamed" ;
+  int arg4 = (int) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 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 *)"O|OOO:SpatialReference_SetVertCS",&obj0,&obj1,&obj2,&obj3)) 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_SetVertCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  if (obj1) {
+    res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetVertCS" "', argument " "2"" of type '" "char const *""'");
+    }
+    arg2 = reinterpret_cast< char * >(buf2);
+  }
+  if (obj2) {
+    res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetVertCS" "', argument " "3"" of type '" "char const *""'");
+    }
+    arg3 = reinterpret_cast< char * >(buf3);
+  }
+  if (obj3) {
+    ecode4 = SWIG_AsVal_int(obj3, &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "SpatialReference_SetVertCS" "', argument " "4"" of type '" "int""'");
+    } 
+    arg4 = static_cast< int >(val4);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OSRSpatialReferenceShadow_SetVertCS(arg1,(char const *)arg2,(char const *)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;
+    }
+  }
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  {
+    /* %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;
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_SpatialReference_SetCompoundCS(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OSRSpatialReferenceShadow *arg3 = (OSRSpatialReferenceShadow *) 0 ;
+  OSRSpatialReferenceShadow *arg4 = (OSRSpatialReferenceShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  OGRErr result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:SpatialReference_SetCompoundCS",&obj0,&obj1,&obj2,&obj3)) 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_SetCompoundCS" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_SetCompoundCS" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "SpatialReference_SetCompoundCS" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
+  res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "SpatialReference_SetCompoundCS" "', argument " "4"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg4 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp4);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg3) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg4) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)OSRSpatialReferenceShadow_SetCompoundCS(arg1,(char const *)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;
+    }
+  }
+  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_SpatialReference_ImportFromWkt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -10083,6 +10685,11 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUrl(PyObject *SWIGUNUSEDPA
   }
   arg2 = reinterpret_cast< char * >(buf2);
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -10653,6 +11260,16 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromERM(PyObject *SWIGUNUSEDPA
   }
   arg4 = reinterpret_cast< char * >(buf4);
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg3) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
@@ -12130,9 +12747,13 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference___str__", _wrap_SpatialReference___str__, METH_VARARGS, (char *)"SpatialReference___str__(SpatialReference self) -> retStringAndCPLFree"},
 	 { (char *)"SpatialReference_IsSame", _wrap_SpatialReference_IsSame, METH_VARARGS, (char *)"SpatialReference_IsSame(SpatialReference self, SpatialReference rhs) -> int"},
 	 { (char *)"SpatialReference_IsSameGeogCS", _wrap_SpatialReference_IsSameGeogCS, METH_VARARGS, (char *)"SpatialReference_IsSameGeogCS(SpatialReference self, SpatialReference rhs) -> int"},
+	 { (char *)"SpatialReference_IsSameVertCS", _wrap_SpatialReference_IsSameVertCS, METH_VARARGS, (char *)"SpatialReference_IsSameVertCS(SpatialReference self, SpatialReference rhs) -> int"},
 	 { (char *)"SpatialReference_IsGeographic", _wrap_SpatialReference_IsGeographic, METH_VARARGS, (char *)"SpatialReference_IsGeographic(SpatialReference self) -> int"},
 	 { (char *)"SpatialReference_IsProjected", _wrap_SpatialReference_IsProjected, METH_VARARGS, (char *)"SpatialReference_IsProjected(SpatialReference self) -> int"},
+	 { (char *)"SpatialReference_IsCompound", _wrap_SpatialReference_IsCompound, METH_VARARGS, (char *)"SpatialReference_IsCompound(SpatialReference self) -> int"},
+	 { (char *)"SpatialReference_IsGeocentric", _wrap_SpatialReference_IsGeocentric, METH_VARARGS, (char *)"SpatialReference_IsGeocentric(SpatialReference self) -> int"},
 	 { (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_SetAuthority", _wrap_SpatialReference_SetAuthority, METH_VARARGS, (char *)"\n"
 		"SpatialReference_SetAuthority(SpatialReference self, char pszTargetKey, char pszAuthority, \n"
@@ -12142,6 +12763,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_SetAttrValue", _wrap_SpatialReference_SetAttrValue, METH_VARARGS, (char *)"SpatialReference_SetAttrValue(SpatialReference self, char name, char value) -> OGRErr"},
 	 { (char *)"SpatialReference_SetAngularUnits", _wrap_SpatialReference_SetAngularUnits, METH_VARARGS, (char *)"SpatialReference_SetAngularUnits(SpatialReference self, char name, double to_radians) -> OGRErr"},
 	 { (char *)"SpatialReference_GetAngularUnits", _wrap_SpatialReference_GetAngularUnits, METH_VARARGS, (char *)"SpatialReference_GetAngularUnits(SpatialReference self) -> double"},
+	 { (char *)"SpatialReference_SetTargetLinearUnits", _wrap_SpatialReference_SetTargetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetTargetLinearUnits(SpatialReference self, char target, char name, double to_meters) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLinearUnits", _wrap_SpatialReference_SetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetLinearUnits(SpatialReference self, char name, double to_meters) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters", _wrap_SpatialReference_SetLinearUnitsAndUpdateParameters, METH_VARARGS, (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters(SpatialReference self, char name, double to_meters) -> OGRErr"},
 	 { (char *)"SpatialReference_GetLinearUnits", _wrap_SpatialReference_GetLinearUnits, METH_VARARGS, (char *)"SpatialReference_GetLinearUnits(SpatialReference self) -> double"},
@@ -12203,6 +12825,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"SpatialReference_SetGS", (PyCFunction) _wrap_SpatialReference_SetGS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGS(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGH", (PyCFunction) _wrap_SpatialReference_SetGH, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGH(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetIGH", _wrap_SpatialReference_SetIGH, METH_VARARGS, (char *)"SpatialReference_SetIGH(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGEOS", (PyCFunction) _wrap_SpatialReference_SetGEOS, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
 		"SpatialReference_SetGEOS(SpatialReference self, double cm, double satelliteheight, \n"
 		"    double fe, double fn) -> OGRErr\n"
@@ -12317,6 +12940,15 @@ static PyMethodDef SwigMethods[] = {
 		"    double dfConvertToRadians = 0.0174532925199433) -> OGRErr\n"
 		""},
 	 { (char *)"SpatialReference_SetProjCS", _wrap_SpatialReference_SetProjCS, METH_VARARGS, (char *)"SpatialReference_SetProjCS(SpatialReference self, char name = \"unnamed\") -> OGRErr"},
+	 { (char *)"SpatialReference_SetGeocCS", _wrap_SpatialReference_SetGeocCS, METH_VARARGS, (char *)"SpatialReference_SetGeocCS(SpatialReference self, char name = \"unnamed\") -> OGRErr"},
+	 { (char *)"SpatialReference_SetVertCS", _wrap_SpatialReference_SetVertCS, METH_VARARGS, (char *)"\n"
+		"SpatialReference_SetVertCS(SpatialReference self, char VertCSName = \"unnamed\", \n"
+		"    char VertDatumName = \"unnamed\", int VertDatumType = 0) -> OGRErr\n"
+		""},
+	 { (char *)"SpatialReference_SetCompoundCS", _wrap_SpatialReference_SetCompoundCS, METH_VARARGS, (char *)"\n"
+		"SpatialReference_SetCompoundCS(SpatialReference self, char name, SpatialReference horizcs, \n"
+		"    SpatialReference vertcs) -> OGRErr\n"
+		""},
 	 { (char *)"SpatialReference_ImportFromWkt", _wrap_SpatialReference_ImportFromWkt, METH_VARARGS, (char *)"SpatialReference_ImportFromWkt(SpatialReference self, char ppszInput) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromProj4", _wrap_SpatialReference_ImportFromProj4, METH_VARARGS, (char *)"SpatialReference_ImportFromProj4(SpatialReference self, char ppszInput) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromUrl", _wrap_SpatialReference_ImportFromUrl, METH_VARARGS, (char *)"SpatialReference_ImportFromUrl(SpatialReference self, char url) -> OGRErr"},
@@ -13014,6 +13646,7 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "SRS_PT_GAUSSSCHREIBERTMERCATOR",SWIG_FromCharPtr("Gauss_Schreiber_Transverse_Mercator"));
   SWIG_Python_SetConstant(d, "SRS_PT_GEOSTATIONARY_SATELLITE",SWIG_FromCharPtr("Geostationary_Satellite"));
   SWIG_Python_SetConstant(d, "SRS_PT_GOODE_HOMOLOSINE",SWIG_FromCharPtr("Goode_Homolosine"));
+  SWIG_Python_SetConstant(d, "SRS_PT_IGH",SWIG_FromCharPtr("Interrupted_Goode_Homolosine"));
   SWIG_Python_SetConstant(d, "SRS_PT_GNOMONIC",SWIG_FromCharPtr("Gnomonic"));
   SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR",SWIG_FromCharPtr("Hotine_Oblique_Mercator"));
   SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN",SWIG_FromCharPtr("Hotine_Oblique_Mercator_Two_Point_Natural_Origin"));
@@ -13096,6 +13729,8 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "SRS_UL_CHAIN_CONV",SWIG_FromCharPtr("20.116684023368047"));
   SWIG_Python_SetConstant(d, "SRS_UL_ROD",SWIG_FromCharPtr("Rod"));
   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_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
new file mode 100755
index 0000000..f0c393e
--- /dev/null
+++ b/swig/python/fallback_build_mingw32_under_unix.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# This is a script to build the python extensions with Python 2.7 and
+# a mingw32 cross-compiler under Linux/Unix. It needs wine to run native python.
+
+# You may need to customize the following versions to match your cross-compiler
+# name and your native python installation
+CXX=i586-mingw32msvc-g++
+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
+    echo "NumPy found !"
+    HAS_NUMPY=yes
+else
+    HAS_NUMPY=no
+fi
+
+INCFLAGS="-I${PYTHONHOME}/include -I../../port -I../../gcore -I../../alg -I../../ogr/"
+LINKFLAGS="-L../../.libs -lgdal -L${PYTHONHOME}/libs -l${PYTHONLIB}"
+CFLAGS="-O2 -D__MSVCRT_VERSION__=0x0601"
+
+# Run native python
+wine ${PYTHONHOME}/python setup.py build
+
+# 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}
+${CXX} ${CFLAGS} extensions/osr_wrap.cpp -shared -o ${OUTDIR}/_osr.pyd ${INCFLAGS} ${LINKFLAGS}
+${CXX} ${CFLAGS} extensions/gdalconst_wrap.c -shared -o ${OUTDIR}/_gdalconst.pyd ${INCFLAGS} ${LINKFLAGS}
+
+if test x${HAS_NUMPY} = "xyes"; then
+    ${CXX} ${CFLAGS} extensions/gdal_array_wrap.cpp -shared -o ${OUTDIR}/_gdal_array.pyd ${INCFLAGS} -I${PYTHONHOME}/Lib/site-packages/numpy/core/include ${LINKFLAGS}
+fi
diff --git a/swig/python/osgeo/gdal.py b/swig/python/osgeo/gdal.py
index 810a8b8..332dfed 100644
--- a/swig/python/osgeo/gdal.py
+++ b/swig/python/osgeo/gdal.py
@@ -207,7 +207,7 @@ def GetConfigOption(*args):
   return _gdal.GetConfigOption(*args)
 
 def CPLBinaryToHex(*args):
-  """CPLBinaryToHex(int nBytes, GByte pabyData) -> char"""
+  """CPLBinaryToHex(int nBytes) -> retStringAndCPLFree"""
   return _gdal.CPLBinaryToHex(*args)
 
 def CPLHexToBinary(*args):
@@ -219,7 +219,7 @@ def FileFromMemBuffer(*args):
   return _gdal.FileFromMemBuffer(*args)
 
 def Unlink(*args):
-  """Unlink(char pszFilename) -> int"""
+  """Unlink(char utf8_path) -> int"""
   return _gdal.Unlink(*args)
 
 def HasThreadSupport(*args):
@@ -237,6 +237,47 @@ def Rmdir(*args):
 def Rename(*args):
   """Rename(char pszOld, char pszNew) -> int"""
   return _gdal.Rename(*args)
+VSI_STAT_EXISTS_FLAG = _gdal.VSI_STAT_EXISTS_FLAG
+VSI_STAT_NATURE_FLAG = _gdal.VSI_STAT_NATURE_FLAG
+VSI_STAT_SIZE_FLAG = _gdal.VSI_STAT_SIZE_FLAG
+class StatBuf(_object):
+    """Proxy of C++ StatBuf class"""
+    __swig_setmethods__ = {}
+    __setattr__ = lambda self, name, value: _swig_setattr(self, StatBuf, name, value)
+    __swig_getmethods__ = {}
+    __getattr__ = lambda self, name: _swig_getattr(self, StatBuf, name)
+    __repr__ = _swig_repr
+    __swig_getmethods__["mode"] = _gdal.StatBuf_mode_get
+    if _newclass:mode = _swig_property(_gdal.StatBuf_mode_get)
+    __swig_getmethods__["size"] = _gdal.StatBuf_size_get
+    if _newclass:size = _swig_property(_gdal.StatBuf_size_get)
+    __swig_getmethods__["mtime"] = _gdal.StatBuf_mtime_get
+    if _newclass:mtime = _swig_property(_gdal.StatBuf_mtime_get)
+    def __init__(self, *args): 
+        """__init__(self, StatBuf psStatBuf) -> StatBuf"""
+        this = _gdal.new_StatBuf(*args)
+        try: self.this.append(this)
+        except: self.this = this
+    __swig_destroy__ = _gdal.delete_StatBuf
+    __del__ = lambda self : None;
+    def IsDirectory(self, *args):
+        """IsDirectory(self) -> int"""
+        return _gdal.StatBuf_IsDirectory(self, *args)
+
+StatBuf_swigregister = _gdal.StatBuf_swigregister
+StatBuf_swigregister(StatBuf)
+
+def PushErrorHandler(*args):
+  """
+    PushErrorHandler(char pszCallbackName = None) -> CPLErr
+    PushErrorHandler(CPLErrorHandler arg0)
+    """
+  return _gdal.PushErrorHandler(*args)
+
+
+def VSIStatL(*args):
+  """VSIStatL(char utf8_path, int nFlags = 0) -> int"""
+  return _gdal.VSIStatL(*args)
 
 def VSIFOpenL(*args):
   """VSIFOpenL(char utf8_path, char pszMode) -> VSILFILE"""
@@ -247,15 +288,19 @@ def VSIFCloseL(*args):
   return _gdal.VSIFCloseL(*args)
 
 def VSIFSeekL(*args):
-  """VSIFSeekL(VSILFILE arg0, long arg1, int arg2) -> int"""
+  """VSIFSeekL(VSILFILE arg0, GIntBig arg1, int arg2) -> int"""
   return _gdal.VSIFSeekL(*args)
 
 def VSIFTellL(*args):
-  """VSIFTellL(VSILFILE arg0) -> long"""
+  """VSIFTellL(VSILFILE arg0) -> GIntBig"""
   return _gdal.VSIFTellL(*args)
 
+def VSIFTruncateL(*args):
+  """VSIFTruncateL(VSILFILE arg0, GIntBig arg1) -> int"""
+  return _gdal.VSIFTruncateL(*args)
+
 def VSIFWriteL(*args):
-  """VSIFWriteL(char arg0, int arg1, int arg2, VSILFILE arg3) -> int"""
+  """VSIFWriteL(int nLen, int size, int memb, VSILFILE f) -> int"""
   return _gdal.VSIFWriteL(*args)
 class MajorObject(_object):
     """Proxy of C++ GDALMajorObjectShadow class"""
@@ -304,13 +349,6 @@ class MajorObject(_object):
 MajorObject_swigregister = _gdal.MajorObject_swigregister
 MajorObject_swigregister(MajorObject)
 
-def PushErrorHandler(*args):
-  """
-    PushErrorHandler(char pszCallbackName = None) -> CPLErr
-    PushErrorHandler(CPLErrorHandler arg0)
-    """
-  return _gdal.PushErrorHandler(*args)
-
 class Driver(MajorObject):
     """Proxy of C++ GDALDriverShadow class"""
     __swig_setmethods__ = {}
@@ -1006,6 +1044,14 @@ class Band(MajorObject):
         """HasArbitraryOverviews(self) -> bool"""
         return _gdal.Band_HasArbitraryOverviews(self, *args)
 
+    def GetCategoryNames(self, *args):
+        """GetCategoryNames(self) -> char"""
+        return _gdal.Band_GetCategoryNames(self, *args)
+
+    def SetCategoryNames(self, *args):
+        """SetCategoryNames(self, char papszCategoryNames) -> CPLErr"""
+        return _gdal.Band_SetCategoryNames(self, *args)
+
     def ReadRaster1(self, *args, **kwargs):
         """
         ReadRaster1(self, int xoff, int yoff, int xsize, int ysize, int buf_xsize = None, 
diff --git a/swig/python/osgeo/ogr.py b/swig/python/osgeo/ogr.py
index c1fc8ca..a8f7f97 100644
--- a/swig/python/osgeo/ogr.py
+++ b/swig/python/osgeo/ogr.py
@@ -103,6 +103,10 @@ OJRight = _ogr.OJRight
 wkbXDR = _ogr.wkbXDR
 wkbNDR = _ogr.wkbNDR
 NullFID = _ogr.NullFID
+ALTER_NAME_FLAG = _ogr.ALTER_NAME_FLAG
+ALTER_TYPE_FLAG = _ogr.ALTER_TYPE_FLAG
+ALTER_WIDTH_PRECISION_FLAG = _ogr.ALTER_WIDTH_PRECISION_FLAG
+ALTER_ALL_FLAG = _ogr.ALTER_ALL_FLAG
 OLCRandomRead = _ogr.OLCRandomRead
 OLCSequentialWrite = _ogr.OLCSequentialWrite
 OLCRandomWrite = _ogr.OLCRandomWrite
@@ -110,6 +114,9 @@ OLCFastSpatialFilter = _ogr.OLCFastSpatialFilter
 OLCFastFeatureCount = _ogr.OLCFastFeatureCount
 OLCFastGetExtent = _ogr.OLCFastGetExtent
 OLCCreateField = _ogr.OLCCreateField
+OLCDeleteField = _ogr.OLCDeleteField
+OLCReorderFields = _ogr.OLCReorderFields
+OLCAlterFieldDefn = _ogr.OLCAlterFieldDefn
 OLCTransactions = _ogr.OLCTransactions
 OLCDeleteFeature = _ogr.OLCDeleteFeature
 OLCFastSetNextByIndex = _ogr.OLCFastSetNextByIndex
@@ -168,7 +175,7 @@ class Driver(_object):
 
         hDriver:  handle to the driver on which data source creation is based.
 
-        pszName:  the name for the new data source.
+        pszName:  the name for the new data source. UTF-8 encoded.
 
         papszOptions:  a StringList of name=value options. Options are driver
         specific, and driver information can be found at the following
@@ -469,6 +476,43 @@ class DataSource(_object):
         """
         return _ogr.DataSource_DeleteLayer(self, *args)
 
+    def SyncToDisk(self, *args):
+        """
+        SyncToDisk(self) -> OGRErr
+
+        OGRErr
+        OGR_DS_SyncToDisk(OGRDataSourceH hDS)
+
+        Flush pending changes to disk.
+
+        This call is intended to force the datasource to flush any pending
+        writes to disk, and leave the disk file in a consistent state. It
+        would not normally have any effect on read-only datasources.
+
+        Some data sources do not implement this method, and will still return
+        OGRERR_NONE. An error is only returned if an error occurs while
+        attempting to flush to disk.
+
+        The default implementation of this method just calls the SyncToDisk()
+        method on each of the layers. Conceptionally, calling SyncToDisk() on
+        a datasource should include any work that might be accomplished by
+        calling SyncToDisk() on layers in that data source.
+
+        In any event, you should always close any opened datasource with
+        OGR_DS_Destroy() that will ensure all data is correctly flushed.
+
+        This method is the same as the C++ method OGRDataSource::SyncToDisk()
+
+        Parameters:
+        -----------
+
+        hDS:  handle to the data source
+
+        OGRERR_NONE if no error occurs (even if nothing is done) or an error
+        code. 
+        """
+        return _ogr.DataSource_SyncToDisk(self, *args)
+
     def CreateLayer(self, *args, **kwargs):
         """
         CreateLayer(self, char name, SpatialReference srs = None, OGRwkbGeometryType geom_type = wkbUnknown, 
@@ -624,7 +668,7 @@ class DataSource(_object):
         error, or that have no results set, or an OGRLayer handle representing
         a results set from the query. Note that this OGRLayer is in addition
         to the layers in the data store and must be destroyed with
-        OGR_DS_ReleaseResultsSet() before the data source is closed
+        OGR_DS_ReleaseResultSet() before the data source is closed
         (destroyed).
 
         For more information on the SQL dialect supported internally by OGR
@@ -642,13 +686,15 @@ class DataSource(_object):
         pszSQLCommand:  the SQL statement to execute.
 
         hSpatialFilter:  handle to a geometry which represents a spatial
-        filter.
+        filter. Can be NULL.
 
-        pszDialect:  allows control of the statement dialect. By default it is
-        assumed to be "generic" SQL, whatever that is.
+        pszDialect:  allows control of the statement dialect. If set to NULL,
+        the OGR SQL engine will be used, except for RDBMS drivers that will
+        use their dedicated SQL engine, unless OGRSQL is explicitely passed as
+        the dialect.
 
         an handle to a OGRLayer containing the results of the query.
-        Deallocate with OGR_DS_ReleaseResultsSet(). 
+        Deallocate with OGR_DS_ReleaseResultSet(). 
         """
         return _ogr.DataSource_ExecuteSQL(self, *args, **kwargs)
 
@@ -667,7 +713,7 @@ class DataSource(_object):
         errors.
 
         This function is the same as the C++ method
-        OGRDataSource::ReleaseResultsSet().
+        OGRDataSource::ReleaseResultSet().
 
         Parameters:
         -----------
@@ -937,11 +983,57 @@ class Layer(_object):
         return _ogr.Layer_ResetReading(self, *args)
 
     def GetName(self, *args):
-        """GetName(self) -> char"""
+        """
+        GetName(self) -> char
+
+        const char* OGR_L_GetName(OGRLayerH
+        hLayer)
+
+        Return the layer name.
+
+        This returns the same content as
+        OGR_FD_GetName(OGR_L_GetLayerDefn(hLayer)), but for a few drivers,
+        calling OGR_L_GetName() directly can avoid lengthy layer definition
+        initialization.
+
+        This function is the same as the C++ method OGRLayer::GetName().
+
+        Parameters:
+        -----------
+
+        hLayer:  handle to the layer.
+
+        the layer name (must not been freed)
+
+        OGR 1.8.0 
+        """
         return _ogr.Layer_GetName(self, *args)
 
     def GetGeomType(self, *args):
-        """GetGeomType(self) -> OGRwkbGeometryType"""
+        """
+        GetGeomType(self) -> OGRwkbGeometryType
+
+        OGRwkbGeometryType
+        OGR_L_GetGeomType(OGRLayerH hLayer)
+
+        Return the layer geometry type.
+
+        This returns the same result as
+        OGR_FD_GetGeomType(OGR_L_GetLayerDefn(hLayer)), but for a few drivers,
+        calling OGR_L_GetGeomType() directly can avoid lengthy layer
+        definition initialization.
+
+        This function is the same as the C++ method OGRLayer::GetGeomType().
+
+        Parameters:
+        -----------
+
+        hLayer:  handle to the layer.
+
+        the geometry type
+
+        OGR 1.8.0 
+        """
         return _ogr.Layer_GetGeomType(self, *args)
 
     def GetGeometryColumn(self, *args):
@@ -1046,8 +1138,7 @@ class Layer(_object):
 
         This function implements sequential access to the features of a layer.
         The OGR_L_ResetReading() function can be used to start at the
-        beginning again. Random reading, writing and spatial filtering will be
-        added to the OGRLayer in the future.
+        beginning again.
 
         This function is the same as the C++ method
         OGRLayer::GetNextFeature().
@@ -1259,6 +1350,9 @@ class Layer(_object):
 
         The returned count takes the spatial filter into account.
 
+        Note that some implementations of this method may alter the read
+        cursor of the layer.
+
         This function is the same as the CPP OGRLayer::GetFeatureCount().
 
         Parameters:
@@ -1275,7 +1369,7 @@ class Layer(_object):
 
     def GetExtent(self, *args, **kwargs):
         """
-        GetExtent(self, int force = 1) -> OGRErr
+        GetExtent(self, int force = 1, int can_return_null = 0)
 
         OGRErr OGR_L_GetExtent(OGRLayerH
         hLayer, OGREnvelope *psExtent, int bForce)
@@ -1295,6 +1389,9 @@ class Layer(_object):
         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().
 
         Parameters:
@@ -1363,6 +1460,18 @@ class Layer(_object):
         OLCCreateField / "CreateField": TRUE if this layer can create new
         fields on the current layer using CreateField(), otherwise FALSE.
 
+        OLCDeleteField / "DeleteField": TRUE if this layer can delete
+        existing fields on the current layer using DeleteField(), otherwise
+        FALSE.
+
+        OLCReorderFields / "ReorderFields": TRUE if this layer can reorder
+        existing fields on the current layer using ReorderField() or
+        ReorderFields(), otherwise FALSE.
+
+        OLCAlterFieldDefn / "AlterFieldDefn": TRUE if this layer can alter
+        the definition of an existing field on the current layer using
+        AlterFieldDefn(), otherwise FALSE.
+
         OLCDeleteFeature / "DeleteFeature": TRUE if the DeleteFeature()
         method is supported on this layer, otherwise FALSE.
 
@@ -1404,6 +1513,16 @@ class Layer(_object):
         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().
 
         Parameters:
@@ -1420,6 +1539,196 @@ class Layer(_object):
         """
         return _ogr.Layer_CreateField(self, *args, **kwargs)
 
+    def DeleteField(self, *args):
+        """
+        DeleteField(self, int iField) -> OGRErr
+
+        OGRErr
+        OGR_L_DeleteField(OGRLayerH hLayer, int iField)
+
+        Create a new field on a layer.
+
+        You must use this to delete existing fields on a real layer.
+        Internally the OGRFeatureDefn for the layer will be updated to reflect
+        the deleted 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 OLCDeleteField 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::DeleteField().
+
+        Parameters:
+        -----------
+
+        hLayer:  handle to the layer.
+
+        iField:  index of the field to delete.
+
+        OGRERR_NONE on success.
+
+        OGR 1.9.0 
+        """
+        return _ogr.Layer_DeleteField(self, *args)
+
+    def ReorderField(self, *args):
+        """
+        ReorderField(self, int iOldFieldPos, int iNewFieldPos) -> OGRErr
+
+        OGRErr
+        OGR_L_ReorderField(OGRLayerH hLayer, int iOldFieldPos, int
+        iNewFieldPos)
+
+        Reorder an existing field on a layer.
+
+        This function is a conveniency wrapper of OGR_L_ReorderFields()
+        dedicated to move a single field.
+
+        You must use this to reorder existing fields on a real layer.
+        Internally the OGRFeatureDefn for the layer will be updated to reflect
+        the reordering of the fields. 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.
+
+        The field definition that was at initial position iOldFieldPos will be
+        moved at position iNewFieldPos, and elements between will be shuffled
+        accordingly.
+
+        For example, let suppose the fields were "0","1","2","3","4"
+        initially. ReorderField(1, 3) will reorder them as
+        "0","2","3","1","4".
+
+        Not all drivers support this function. You can query a layer to check
+        if it supports it with the OLCReorderFields 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::ReorderField().
+
+        Parameters:
+        -----------
+
+        hLayer:  handle to the layer.
+
+        iOldFieldPos:  previous position of the field to move. Must be in the
+        range [0,GetFieldCount()-1].
+
+        iNewFieldPos:  new position of the field to move. Must be in the range
+        [0,GetFieldCount()-1].
+
+        OGRERR_NONE on success.
+
+        OGR 1.9.0 
+        """
+        return _ogr.Layer_ReorderField(self, *args)
+
+    def ReorderFields(self, *args):
+        """
+        ReorderFields(self, int nList) -> OGRErr
+
+        OGRErr
+        OGR_L_ReorderFields(OGRLayerH hLayer, int *panMap)
+
+        Reorder all the fields of a layer.
+
+        You must use this to reorder existing fields on a real layer.
+        Internally the OGRFeatureDefn for the layer will be updated to reflect
+        the reordering of the fields. 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.
+
+        panMap is such that,for each field definition at position i after
+        reordering, its position before reordering was panMap[i].
+
+        For example, let suppose the fields were "0","1","2","3","4"
+        initially. ReorderFields([0,2,3,1,4]) will reorder them as
+        "0","2","3","1","4".
+
+        Not all drivers support this function. You can query a layer to check
+        if it supports it with the OLCReorderFields 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::ReorderFields().
+
+        Parameters:
+        -----------
+
+        hLayer:  handle to the layer.
+
+        panMap:  an array of GetLayerDefn()->GetFieldCount() elements which is
+        a permutation of [0, GetLayerDefn()->GetFieldCount()-1].
+
+        OGRERR_NONE on success.
+
+        OGR 1.9.0 
+        """
+        return _ogr.Layer_ReorderFields(self, *args)
+
+    def AlterFieldDefn(self, *args):
+        """
+        AlterFieldDefn(self, int iField, FieldDefn field_def, int nFlags) -> OGRErr
+
+        OGRErr
+        OGR_L_AlterFieldDefn(OGRLayerH hLayer, int iField, OGRFieldDefnH
+        hNewFieldDefn, int nFlags)
+
+        Alter the definition of an existing field on a layer.
+
+        You must use this to alter the definition of an existing field of a
+        real layer. Internally the OGRFeatureDefn for the layer will be
+        updated to reflect the altered 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 OLCAlterFieldDefn 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. Some drivers might also
+        not support all update flags.
+
+        This function is the same as the C++ method
+        OGRLayer::AlterFieldDefn().
+
+        Parameters:
+        -----------
+
+        hLayer:  handle to the layer.
+
+        iField:  index of the field whose definition must be altered.
+
+        hNewFieldDefn:  new field definition
+
+        nFlags:  combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and
+        ALTER_WIDTH_PRECISION_FLAG to indicate which of the name and/or type
+        and/or width and precision fields from the new field definition must
+        be taken into account.
+
+        OGRERR_NONE on success.
+
+        OGR 1.9.0 
+        """
+        return _ogr.Layer_AlterFieldDefn(self, *args)
+
     def StartTransaction(self, *args):
         """
         StartTransaction(self) -> OGRErr
@@ -1530,7 +1839,37 @@ class Layer(_object):
         return _ogr.Layer_GetFeaturesRead(self, *args)
 
     def SetIgnoredFields(self, *args):
-        """SetIgnoredFields(self, char options) -> OGRErr"""
+        """
+        SetIgnoredFields(self, char options) -> OGRErr
+
+        OGRErr
+        OGR_L_SetIgnoredFields(OGRLayerH hLayer, const char **papszFields)
+
+        Set which fields can be omitted when retrieving features from the
+        layer.
+
+        If the driver supports this functionality (testable using
+        OLCIgnoreFields capability), it will not fetch the specified fields in
+        subsequent calls to GetFeature() / GetNextFeature() and thus save some
+        processing time and/or bandwidth.
+
+        Besides field names of the layers, the following special fields can be
+        passed: "OGR_GEOMETRY" to ignore geometry and "OGR_STYLE" to
+        ignore layer style.
+
+        By default, no fields are ignored.
+
+        This method is the same as the C++ method OGRLayer::SetIgnoredFields()
+
+        Parameters:
+        -----------
+
+        papszFields:  an array of field names terminated by NULL item. If NULL
+        is passed, the ignored list is cleared.
+
+        OGRERR_NONE if all field names have been resolved (even if the driver
+        does not support this method) 
+        """
         return _ogr.Layer_SetIgnoredFields(self, *args)
 
     def Reference(self):
@@ -1835,7 +2174,7 @@ class Feature(_object):
         iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
         the field value. This string is internal, and should not be modified,
-        or freed. It's lifetime may be very brief. 
+        or freed. Its lifetime may be very brief. 
         """
         return _ogr.Feature_GetFieldAsString(self, *args)
 
@@ -1963,7 +2302,7 @@ class Feature(_object):
         pnCount:  an integer to put the list count (number of integers) into.
 
         the field value. This list is internal, and should not be modified, or
-        freed. It's lifetime may be very brief. If *pnCount is zero on return
+        freed. Its lifetime may be very brief. If *pnCount is zero on return
         the returned pointer may be NULL or non-NULL. 
         """
         return _ogr.Feature_GetFieldAsIntegerList(self, *args)
@@ -1993,7 +2332,7 @@ class Feature(_object):
         pnCount:  an integer to put the list count (number of doubles) into.
 
         the field value. This list is internal, and should not be modified, or
-        freed. It's lifetime may be very brief. If *pnCount is zero on return
+        freed. Its lifetime may be very brief. If *pnCount is zero on return
         the returned pointer may be NULL or non-NULL. 
         """
         return _ogr.Feature_GetFieldAsDoubleList(self, *args)
@@ -2023,7 +2362,7 @@ class Feature(_object):
         iField:  the field to fetch, from 0 to GetFieldCount()-1.
 
         the field value. This list is internal, and should not be modified, or
-        freed. It's lifetime may be very brief. 
+        freed. Its lifetime may be very brief. 
         """
         return _ogr.Feature_GetFieldAsStringList(self, *args)
 
@@ -2413,12 +2752,33 @@ class Feature(_object):
     def __copy__(self):
         return self.Clone()
 
-    def __getattr__(self, name):
+
+
+    def __getattr__(self, key):
         """Returns the values of fields by the given name"""
         try:
-            return self.GetField(name)
+            return self.GetField(key)
         except:
-            raise AttributeError(name)
+            raise AttributeError(key)
+
+
+
+    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:
+            self.__dict__[key] = value
+
+
+    def __getitem__(self, key):
+        """Returns the values of fields by the given name / field_index"""
+        return self.GetField(key)
+
+
+    def __setitem__(self, key, value):
+        """Returns the value of a field by field name / index"""
+        self.SetField2( key, value )    
 
     def GetField(self, fld_index):
         import types
@@ -2433,11 +2793,47 @@ class Feature(_object):
             return self.GetFieldAsInteger(fld_index)
         if fld_type == OFTReal:
             return self.GetFieldAsDouble(fld_index)
+        if fld_type == OFTStringList:
+            return self.GetFieldAsStringList(fld_index)
+        if fld_type == OFTIntegerList:
+            return self.GetFieldAsIntegerList(fld_index)
+        if fld_type == OFTRealList:
+            return self.GetFieldAsDoubleList(fld_index)
         
         
         
         return self.GetFieldAsString(fld_index)
 
+    def SetField2(self, fld_index, value):
+        if isinstance(fld_index, str):
+            fld_index = self.GetFieldIndex(fld_index)
+
+        if value is None:
+            self.UnsetField( fld_index )
+            return
+
+        if isinstance(value,list):
+            if len(value) == 0:
+                self.UnsetField( fld_index )
+                return
+            if isinstance(value[0],int):
+                self.SetFieldIntegerList(fld_index,value)
+                return
+            elif isinstance(value[0],float):
+                self.SetFieldDoubleList(fld_index,value)
+                return
+            elif isinstance(value[0],str):
+                self.SetFieldStringList(fld_index,value)
+                return
+            else:
+                raise TypeError( 'Unsupported type of list in SetField2()' )
+
+        try:
+            self.SetField( fld_index, value )
+        except:
+            self.SetField( fld_index, str(value) )
+        return
+
     def keys(self):
         names = []
         for i in range(self.GetFieldCount()):
@@ -2454,10 +2850,11 @@ class Feature(_object):
     def geometry(self):
         return self.GetGeometryRef()
 
-    def ExportToJson(self, as_object = False):
+    def ExportToJson(self, as_object = False, options = None):
         """Exports a GeoJSON object which represents the Feature. The
            as_object parameter determines whether the returned value 
-           should be a Python object instead of a string. Defaults to False."""
+           should be a Python object instead of a string. Defaults to False.
+           The options parameter is passed to Geometry.ExportToJson()"""
 
         try:
             import simplejson
@@ -2469,7 +2866,9 @@ class Feature(_object):
 
         geom = self.GetGeometryRef()
         if geom is not None:
-            geom_json_string = geom.ExportToJson()
+            if options is None:
+                options = []
+            geom_json_string = geom.ExportToJson(options = options)
             geom_json_object = simplejson.loads(geom_json_string)
         else:
             geom_json_object = None
@@ -2615,12 +3014,15 @@ class FeatureDefn(_object):
 
         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_CreateField() instead.
+
         This function should only be called while there are no OGRFeature
         objects in existance based on this OGRFeatureDefn. The OGRFieldDefn
         passed in is copied, and remains the responsibility of the caller.
 
         This function is the same as the C++ method
-        OGRFeatureDefn::AddFieldDefn.
+        OGRFeatureDefn::AddFieldDefn().
 
         Parameters:
         -----------
@@ -2705,19 +3107,91 @@ class FeatureDefn(_object):
         return _ogr.FeatureDefn_GetReferenceCount(self, *args)
 
     def IsGeometryIgnored(self, *args):
-        """IsGeometryIgnored(self) -> int"""
+        """
+        IsGeometryIgnored(self) -> int
+
+        int
+        OGR_FD_IsGeometryIgnored(OGRFeatureDefnH hDefn)
+
+        Determine whether the geometry can be omitted when fetching features.
+
+        This function is the same as the C++ method
+        OGRFeatureDefn::IsGeometryIgnored().
+
+        Parameters:
+        -----------
+
+        hDefn:  hanlde to the feature definition on witch OGRFeature are based
+        on.
+
+        ignore state 
+        """
         return _ogr.FeatureDefn_IsGeometryIgnored(self, *args)
 
     def SetGeometryIgnored(self, *args):
-        """SetGeometryIgnored(self, int bIgnored)"""
+        """
+        SetGeometryIgnored(self, int bIgnored)
+
+        void
+        OGR_FD_SetGeometryIgnored(OGRFeatureDefnH hDefn, int bIgnore)
+
+        Set whether the geometry can be omitted when fetching features.
+
+        This function is the same as the C++ method
+        OGRFeatureDefn::SetGeometryIgnored().
+
+        Parameters:
+        -----------
+
+        hDefn:  hanlde to the feature definition on witch OGRFeature are based
+        on.
+
+        bIgnore:  ignore state 
+        """
         return _ogr.FeatureDefn_SetGeometryIgnored(self, *args)
 
     def IsStyleIgnored(self, *args):
-        """IsStyleIgnored(self) -> int"""
+        """
+        IsStyleIgnored(self) -> int
+
+        int
+        OGR_FD_IsStyleIgnored(OGRFeatureDefnH hDefn)
+
+        Determine whether the style can be omitted when fetching features.
+
+        This function is the same as the C++ method
+        OGRFeatureDefn::IsStyleIgnored().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the feature definition on which OGRFeature are based
+        on.
+
+        ignore state 
+        """
         return _ogr.FeatureDefn_IsStyleIgnored(self, *args)
 
     def SetStyleIgnored(self, *args):
-        """SetStyleIgnored(self, int bIgnored)"""
+        """
+        SetStyleIgnored(self, int bIgnored)
+
+        void
+        OGR_FD_SetStyleIgnored(OGRFeatureDefnH hDefn, int bIgnore)
+
+        Set whether the style can be omitted when fetching features.
+
+        This function is the same as the C++ method
+        OGRFeatureDefn::SetStyleIgnored().
+
+        Parameters:
+        -----------
+
+        hDefn:  hanlde to the feature definition on witch OGRFeature are based
+        on.
+
+        bIgnore:  ignore state 
+        """
         return _ogr.FeatureDefn_SetStyleIgnored(self, *args)
 
     def Destroy(self):
@@ -2965,11 +3439,43 @@ class FieldDefn(_object):
         return _ogr.FieldDefn_GetFieldTypeName(self, *args)
 
     def IsIgnored(self, *args):
-        """IsIgnored(self) -> int"""
+        """
+        IsIgnored(self) -> int
+
+        int OGR_Fld_IsIgnored(OGRFieldDefnH
+        hDefn)
+
+        Return whether this field should be omitted when fetching features.
+
+        This method is the same as the C++ method OGRFieldDefn::IsIgnored().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition
+
+        ignore state 
+        """
         return _ogr.FieldDefn_IsIgnored(self, *args)
 
     def SetIgnored(self, *args):
-        """SetIgnored(self, int bIgnored)"""
+        """
+        SetIgnored(self, int bIgnored)
+
+        void
+        OGR_Fld_SetIgnored(OGRFieldDefnH hDefn, int ignore)
+
+        Set whether this field should be omitted when fetching features.
+
+        This method is the same as the C function OGRFieldDefn::SetIgnored().
+
+        Parameters:
+        -----------
+
+        hDefn:  handle to the field definition
+
+        ignore:  ignore state 
+        """
         return _ogr.FieldDefn_SetIgnored(self, *args)
 
     width = property(GetWidth, SetWidth)
@@ -3116,9 +3622,9 @@ class Geometry(_object):
         """ExportToKML(self, char altitude_mode = None) -> retStringAndCPLFree"""
         return _ogr.Geometry_ExportToKML(self, *args)
 
-    def ExportToJson(self, *args):
-        """ExportToJson(self) -> retStringAndCPLFree"""
-        return _ogr.Geometry_ExportToJson(self, *args)
+    def ExportToJson(self, *args, **kwargs):
+        """ExportToJson(self, char options = None) -> retStringAndCPLFree"""
+        return _ogr.Geometry_ExportToJson(self, *args, **kwargs)
 
     def AddPoint(self, *args, **kwargs):
         """AddPoint(self, double x, double y, double z = 0)"""
@@ -3223,6 +3729,10 @@ class Geometry(_object):
         """GetPointCount(self) -> int"""
         return _ogr.Geometry_GetPointCount(self, *args)
 
+    def GetPoints(self, *args, **kwargs):
+        """GetPoints(self, int nCoordDimension = 0)"""
+        return _ogr.Geometry_GetPoints(self, *args, **kwargs)
+
     def GetX(self, *args, **kwargs):
         """GetX(self, int point = 0) -> double"""
         return _ogr.Geometry_GetX(self, *args, **kwargs)
@@ -3260,26 +3770,77 @@ class Geometry(_object):
         return _ogr.Geometry_GetGeometryRef(self, *args)
 
     def Simplify(self, *args):
-        """Simplify(self, double tolerance) -> Geometry"""
+        """
+        Simplify(self, double tolerance) -> Geometry
+
+        OGRGeometryH
+        OGR_G_Simplify(OGRGeometryH hThis, double dTolerance)
+
+        Compute a simplified geometry.
+
+        This function is the same as the C++ method OGRGeometry::Simplify().
+
+        This function is built on the GEOS library, check it for the
+        definition of the geometry operation. If OGR is built without the GEOS
+        library, this function will always fail, issuing a CPLE_NotSupported
+        error.
+
+        Parameters:
+        -----------
+
+        hThis:  the geometry.
+
+        dTolerance:  the distance tolerance for the simplification.
+
+        the simplified geometry or NULL if an error occurs.
+
+        OGR 1.8.0 
+        """
         return _ogr.Geometry_Simplify(self, *args)
 
-    def Boundary(self, *args):
-        """Boundary(self) -> Geometry"""
-        return _ogr.Geometry_Boundary(self, *args)
+    def SimplifyPreserveTopology(self, *args):
+        """
+        SimplifyPreserveTopology(self, double tolerance) -> Geometry
 
-    def GetBoundary(self, *args):
+        OGRGeometryH
+        OGR_G_SimplifyPreserveTopology(OGRGeometryH hThis, double dTolerance)
+
+        Compute a simplified geometry.
+
+        This function is the same as the C++ method
+        OGRGeometry::SimplifyPreserveTopology().
+
+        This function is built on the GEOS library, check it for the
+        definition of the geometry operation. If OGR is built without the GEOS
+        library, this function will always fail, issuing a CPLE_NotSupported
+        error.
+
+        Parameters:
+        -----------
+
+        hThis:  the geometry.
+
+        dTolerance:  the distance tolerance for the simplification.
+
+        the simplified geometry or NULL if an error occurs.
+
+        OGR 1.9.0 
         """
-        GetBoundary(self) -> Geometry
+        return _ogr.Geometry_SimplifyPreserveTopology(self, *args)
+
+    def Boundary(self, *args):
+        """
+        Boundary(self) -> Geometry
 
         OGRGeometryH
-        OGR_G_GetBoundary(OGRGeometryH hTarget)
+        OGR_G_Boundary(OGRGeometryH hTarget)
 
         Compute boundary.
 
         A new geometry object is created and returned containing the boundary
         of the geometry on which the method is invoked.
 
-        This function is the same as the C++ method OGR_G_GetBoundary().
+        This function is the same as the C++ method OGR_G_Boundary().
 
         This function is built on the GEOS library, check it for the
         definition of the geometry operation. If OGR is built without the GEOS
@@ -3292,7 +3853,22 @@ class Geometry(_object):
         hTarget:  The Geometry to calculate the boundary of.
 
         a handle to a newly allocated geometry now owned by the caller, or
-        NULL on failure. 
+        NULL on failure.
+
+        OGR 1.8.0 
+        """
+        return _ogr.Geometry_Boundary(self, *args)
+
+    def GetBoundary(self, *args):
+        """
+        GetBoundary(self) -> Geometry
+
+        OGRGeometryH
+        OGR_G_GetBoundary(OGRGeometryH hTarget)
+
+        Compute boundary (deprecated).
+
+        Deprecated See:   OGR_G_Boundary() 
         """
         return _ogr.Geometry_GetBoundary(self, *args)
 
@@ -3430,7 +4006,29 @@ class Geometry(_object):
         return _ogr.Geometry_Union(self, *args)
 
     def UnionCascaded(self, *args):
-        """UnionCascaded(self) -> Geometry"""
+        """
+        UnionCascaded(self) -> Geometry
+
+        OGRGeometryH
+        OGR_G_UnionCascaded(OGRGeometryH hThis)
+
+        Compute union using cascading.
+
+        This function is the same as the C++ method
+        OGRGeometry::UnionCascaded().
+
+        This function is built on the GEOS library, check it for the
+        definition of the geometry operation. If OGR is built without the GEOS
+        library, this function will always fail, issuing a CPLE_NotSupported
+        error.
+
+        Parameters:
+        -----------
+
+        hThis:  the geometry.
+
+        a new geometry representing the union or NULL if an error occurs. 
+        """
         return _ogr.Geometry_UnionCascaded(self, *args)
 
     def Difference(self, *args):
@@ -3465,15 +4063,11 @@ class Geometry(_object):
         return _ogr.Geometry_Difference(self, *args)
 
     def SymDifference(self, *args):
-        """SymDifference(self, Geometry other) -> Geometry"""
-        return _ogr.Geometry_SymDifference(self, *args)
-
-    def SymmetricDifference(self, *args):
         """
-        SymmetricDifference(self, Geometry other) -> Geometry
+        SymDifference(self, Geometry other) -> Geometry
 
         OGRGeometryH
-        OGR_G_SymmetricDifference(OGRGeometryH hThis, OGRGeometryH hOther)
+        OGR_G_SymDifference(OGRGeometryH hThis, OGRGeometryH hOther)
 
         Compute symmetric difference.
 
@@ -3496,7 +4090,22 @@ class Geometry(_object):
         hOther:  the other geometry.
 
         a new geometry representing the symmetric difference or NULL if the
-        difference is empty or an error occurs. 
+        difference is empty or an error occurs.
+
+        OGR 1.8.0 
+        """
+        return _ogr.Geometry_SymDifference(self, *args)
+
+    def SymmetricDifference(self, *args):
+        """
+        SymmetricDifference(self, Geometry other) -> Geometry
+
+        OGRGeometryH
+        OGR_G_SymmetricDifference(OGRGeometryH hThis, OGRGeometryH hOther)
+
+        Compute symmetric difference (deprecated).
+
+        Deprecated See:   OGR_G_SymmetricDifference() 
         """
         return _ogr.Geometry_SymmetricDifference(self, *args)
 
@@ -4018,7 +4627,18 @@ class Geometry(_object):
         CloseRings(self)
 
         void OGR_G_CloseRings(OGRGeometryH
-        hGeom) 
+        hGeom)
+
+        Force rings to be closed.
+
+        If this geometry, or any contained geometries has polygon rings that
+        are not closed, they will be closed by adding the starting point at
+        the end.
+
+        Parameters:
+        -----------
+
+        hGeom:  handle to the geometry. 
         """
         return _ogr.Geometry_CloseRings(self, *args)
 
@@ -4089,8 +4709,58 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetEnvelope(self, *args)
 
+    def GetEnvelope3D(self, *args):
+        """
+        GetEnvelope3D(self)
+
+        void
+        OGR_G_GetEnvelope3D(OGRGeometryH hGeom, OGREnvelope3D *psEnvelope)
+
+        Computes and returns the bounding envelope (3D) for this geometry in
+        the passed psEnvelope structure.
+
+        This function is the same as the CPP method
+        OGRGeometry::getEnvelope().
+
+        Parameters:
+        -----------
+
+        hGeom:  handle of the geometry to get envelope from.
+
+        psEnvelope:  the structure in which to place the results.
+
+        OGR 1.9.0 
+        """
+        return _ogr.Geometry_GetEnvelope3D(self, *args)
+
     def Centroid(self, *args):
-        """Centroid(self) -> Geometry"""
+        """
+        Centroid(self) -> Geometry
+
+        int OGR_G_Centroid(OGRGeometryH
+        hGeom, OGRGeometryH hCentroidPoint)
+
+        Compute the geometry centroid.
+
+        The centroid location is applied to the passed in OGRPoint object. The
+        centroid is not necessarily within the geometry.
+
+        This method relates to the SFCOM ISurface::get_Centroid() method
+        however the current implementation based on GEOS can operate on other
+        geometry types such as multipoint, linestring, geometrycollection such
+        as multipolygons. OGC SF SQL 1.1 defines the operation for surfaces
+        (polygons). SQL/MM-Part 3 defines the operation for surfaces and
+        multisurfaces (multipolygons).
+
+        This function is the same as the C++ method OGRGeometry::Centroid().
+
+        This function is built on the GEOS library, check it for the
+        definition of the geometry operation. If OGR is built without the GEOS
+        library, this function will always fail, issuing a CPLE_NotSupported
+        error.
+
+        OGRERR_NONE on success or OGRERR_FAILURE on error. 
+        """
         return _ogr.Geometry_Centroid(self, *args)
 
     def WkbSize(self, *args):
@@ -4139,8 +4809,8 @@ class Geometry(_object):
         hGeom:  handle on the geometry to get the dimension of the coordinates
         from.
 
-        in practice this always returns 2 indicating that coordinates are
-        specified within a two dimensional space. 
+        in practice this will return 2 or 3. It can also return 0 in the case
+        of an empty point. 
         """
         return _ogr.Geometry_GetCoordinateDimension(self, *args)
 
@@ -4149,7 +4819,22 @@ class Geometry(_object):
         SetCoordinateDimension(self, int dimension)
 
         void
-        OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension) 
+        OGR_G_SetCoordinateDimension(OGRGeometryH hGeom, int nNewDimension)
+
+        Set the coordinate dimension.
+
+        This method sets the explicit coordinate dimension. Setting the
+        coordinate dimension of a geometry to 2 should zero out any existing Z
+        values. Setting the dimension of a geometry collection will not
+        necessarily affect the children geometries.
+
+        Parameters:
+        -----------
+
+        hGeom:  handle on the geometry to set the dimension of the
+        coordinates.
+
+        nNewDimension:  New coordinate dimension value, either 2 or 3. 
         """
         return _ogr.Geometry_SetCoordinateDimension(self, *args)
 
diff --git a/swig/python/osgeo/osr.py b/swig/python/osgeo/osr.py
index 70f6328..8991030 100644
--- a/swig/python/osgeo/osr.py
+++ b/swig/python/osgeo/osr.py
@@ -84,6 +84,7 @@ SRS_PT_GALL_STEREOGRAPHIC = _osr.SRS_PT_GALL_STEREOGRAPHIC
 SRS_PT_GAUSSSCHREIBERTMERCATOR = _osr.SRS_PT_GAUSSSCHREIBERTMERCATOR
 SRS_PT_GEOSTATIONARY_SATELLITE = _osr.SRS_PT_GEOSTATIONARY_SATELLITE
 SRS_PT_GOODE_HOMOLOSINE = _osr.SRS_PT_GOODE_HOMOLOSINE
+SRS_PT_IGH = _osr.SRS_PT_IGH
 SRS_PT_GNOMONIC = _osr.SRS_PT_GNOMONIC
 SRS_PT_HOTINE_OBLIQUE_MERCATOR = _osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR
 SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN = _osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN
@@ -166,6 +167,8 @@ SRS_UL_CHAIN = _osr.SRS_UL_CHAIN
 SRS_UL_CHAIN_CONV = _osr.SRS_UL_CHAIN_CONV
 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_UA_DEGREE = _osr.SRS_UA_DEGREE
 SRS_UA_DEGREE_CONV = _osr.SRS_UA_DEGREE_CONV
 SRS_UA_RADIAN = _osr.SRS_UA_RADIAN
@@ -222,6 +225,10 @@ class SpatialReference(_object):
         """IsSameGeogCS(self, SpatialReference rhs) -> int"""
         return _osr.SpatialReference_IsSameGeogCS(self, *args)
 
+    def IsSameVertCS(self, *args):
+        """IsSameVertCS(self, SpatialReference rhs) -> int"""
+        return _osr.SpatialReference_IsSameVertCS(self, *args)
+
     def IsGeographic(self, *args):
         """IsGeographic(self) -> int"""
         return _osr.SpatialReference_IsGeographic(self, *args)
@@ -230,10 +237,22 @@ class SpatialReference(_object):
         """IsProjected(self) -> int"""
         return _osr.SpatialReference_IsProjected(self, *args)
 
+    def IsCompound(self, *args):
+        """IsCompound(self) -> int"""
+        return _osr.SpatialReference_IsCompound(self, *args)
+
+    def IsGeocentric(self, *args):
+        """IsGeocentric(self) -> int"""
+        return _osr.SpatialReference_IsGeocentric(self, *args)
+
     def IsLocal(self, *args):
         """IsLocal(self) -> int"""
         return _osr.SpatialReference_IsLocal(self, *args)
 
+    def IsVertical(self, *args):
+        """IsVertical(self) -> int"""
+        return _osr.SpatialReference_IsVertical(self, *args)
+
     def EPSGTreatsAsLatLong(self, *args):
         """EPSGTreatsAsLatLong(self) -> int"""
         return _osr.SpatialReference_EPSGTreatsAsLatLong(self, *args)
@@ -258,6 +277,10 @@ class SpatialReference(_object):
         """GetAngularUnits(self) -> double"""
         return _osr.SpatialReference_GetAngularUnits(self, *args)
 
+    def SetTargetLinearUnits(self, *args):
+        """SetTargetLinearUnits(self, char target, char name, double to_meters) -> OGRErr"""
+        return _osr.SpatialReference_SetTargetLinearUnits(self, *args)
+
     def SetLinearUnits(self, *args):
         """SetLinearUnits(self, char name, double to_meters) -> OGRErr"""
         return _osr.SpatialReference_SetLinearUnits(self, *args)
@@ -391,6 +414,10 @@ class SpatialReference(_object):
         """SetGH(self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGH(self, *args, **kwargs)
 
+    def SetIGH(self, *args):
+        """SetIGH(self) -> OGRErr"""
+        return _osr.SpatialReference_SetIGH(self, *args)
+
     def SetGEOS(self, *args, **kwargs):
         """SetGEOS(self, double cm, double satelliteheight, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGEOS(self, *args, **kwargs)
@@ -576,6 +603,21 @@ class SpatialReference(_object):
         """SetProjCS(self, char name = "unnamed") -> OGRErr"""
         return _osr.SpatialReference_SetProjCS(self, *args)
 
+    def SetGeocCS(self, *args):
+        """SetGeocCS(self, char name = "unnamed") -> OGRErr"""
+        return _osr.SpatialReference_SetGeocCS(self, *args)
+
+    def SetVertCS(self, *args):
+        """
+        SetVertCS(self, char VertCSName = "unnamed", char VertDatumName = "unnamed", 
+            int VertDatumType = 0) -> OGRErr
+        """
+        return _osr.SpatialReference_SetVertCS(self, *args)
+
+    def SetCompoundCS(self, *args):
+        """SetCompoundCS(self, char name, SpatialReference horizcs, SpatialReference vertcs) -> OGRErr"""
+        return _osr.SpatialReference_SetCompoundCS(self, *args)
+
     def ImportFromWkt(self, *args):
         """ImportFromWkt(self, char ppszInput) -> OGRErr"""
         return _osr.SpatialReference_ImportFromWkt(self, *args)
diff --git a/swig/python/python3.2.patch b/swig/python/python3.2.patch
new file mode 100644
index 0000000..0a62b6f
--- /dev/null
+++ b/swig/python/python3.2.patch
@@ -0,0 +1,88 @@
+--- extensions/gdal_wrap.cpp.before	2011-02-21 21:35:04.495185339 +0100
++++ extensions/gdal_wrap.cpp	2011-02-21 21:36:08.275188019 +0100
+@@ -1129,6 +1129,10 @@
+ 
+ /* Runtime API */
+ 
++#if PY_VERSION_HEX >= 0x03020000
++#define SWIG_PYTHON_USE_CAPSULE
++#endif
++
+ #define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
+ #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
+ #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
+@@ -2448,8 +2452,12 @@
+ #ifdef SWIG_LINK_RUNTIME
+     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
+ #else
++#ifdef SWIG_PYTHON_USE_CAPSULE
++    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
++#else
+     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
+ 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
++#endif
+     if (PyErr_Occurred()) {
+       PyErr_Clear();
+       type_pointer = (void *)0;
+@@ -2492,11 +2500,26 @@
+ #endif
+ 
+ SWIGRUNTIME void
++#ifdef SWIG_PYTHON_USE_CAPSULE
++SWIG_Python_DestroyModule(PyObject *capsule)
++{
++  swig_module_info *swig_module;
++  swig_type_info **types;
++  size_t i;
++  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
++  if (swig_module == NULL)
++  {
++    PyErr_Clear();
++    return;
++  }
++  types = swig_module->types;
++#else
+ SWIG_Python_DestroyModule(void *vptr)
+ {
+   swig_module_info *swig_module = (swig_module_info *) vptr;
+   swig_type_info **types = swig_module->types;
+   size_t i;
++#endif
+   for (i =0; i < swig_module->size; ++i) {
+     swig_type_info *ty = types[i];
+     if (ty->owndata) {
+@@ -2518,7 +2541,13 @@
+   PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
+ 				   swig_empty_runtime_method_table);
+ #endif
++#ifdef SWIG_PYTHON_USE_CAPSULE
++  PyObject *pointer = PyCapsule_New((void *) swig_module,
++                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
++                                    SWIG_Python_DestroyModule);
++#else
+   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
++#endif
+   if (pointer && module) {
+     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
+   } else {
+@@ -2541,12 +2570,20 @@
+   PyObject *obj = PyDict_GetItem(cache, key);
+   swig_type_info *descriptor;
+   if (obj) {
++#ifdef SWIG_PYTHON_USE_CAPSULE
++    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
++#else
+     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
++#endif
+   } else {
+     swig_module_info *swig_module = SWIG_Python_GetModule();
+     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
+     if (descriptor) {
++#ifdef SWIG_PYTHON_USE_CAPSULE
++      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
++#else
+       obj = PyCObject_FromVoidPtr(descriptor, NULL);
++#endif
+       PyDict_SetItem(cache, key, obj);
+       Py_DECREF(obj);
+     }
diff --git a/swig/python/samples/README b/swig/python/samples/README
index 05c3272..280e954 100644
--- a/swig/python/samples/README
+++ b/swig/python/samples/README
@@ -18,7 +18,7 @@ gdal2grd.py		Script to write out ASCII GRD rasters (used in Golden
 
 gdal_vrtmerge.py	Similar to gdal_merge.py, but produces a VRT file. 
 
-gdalcopyproj.py		Duplicate the geotransform and projection metadata from
+gdalcopyproj.py		Duplicate the geotransform, projection and/or GCPs from
 			one raster dataset to another, which can be useful after
 			performing image manipulations with other software that
 			ignores or discards georeferencing metadata.
@@ -80,6 +80,14 @@ hsv_merge.py            Merge greyscale image into rgb image as intensity
 val_at_coord.py         Outputs the value of the raster bands at a given
                         (longitude, latitude) or (X, Y) location.
 
+gdal_ls.py              Display the list of files in a virtual directory,
+                        like /vsicurl or /vsizip
+
+gdal_cp.py              Copy a virtual file
+
+gdal_edit.py            Edit in place various information of an existing GDAL dataset
+                        (projection, geotransform, nodata, metadata)
+
 ------------------------------------------------------------------------------
 Ports of .c/.cpp utilities
 ------------------------------------------------------------------------------
diff --git a/swig/python/samples/assemblepoly.py b/swig/python/samples/assemblepoly.py
old mode 100644
new mode 100755
index 2af6a5a..7731a38
--- a/swig/python/samples/assemblepoly.py
+++ b/swig/python/samples/assemblepoly.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: assemblepoly.py 18195 2009-12-06 20:24:39Z rouault $
+# $Id: assemblepoly.py 22986 2011-08-27 14:20:16Z rouault $
 #
 # Project:  OGR Python samples
 # Purpose:  Assemble polygon geometries from arcs fulled from an arc layer.
diff --git a/swig/python/samples/classify.py b/swig/python/samples/classify.py
old mode 100644
new mode 100755
diff --git a/swig/python/samples/densify.py b/swig/python/samples/densify.py
old mode 100644
new mode 100755
diff --git a/swig/python/samples/gdal_cp.py b/swig/python/samples/gdal_cp.py
new file mode 100755
index 0000000..848f379
--- /dev/null
+++ b/swig/python/samples/gdal_cp.py
@@ -0,0 +1,308 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: gdal_cp.py 23166 2011-10-02 17:48:48Z 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>
+#
+#  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
+import sys
+import os
+import fnmatch
+
+def needsVSICurl(filename):
+    return filename.startswith('http://') or filename.startswith('https://') or filename.startswith('ftp://')
+
+def Usage():
+    print('Usage: gdal_cp [-progress] [-r] [-skipfailures] source_file target_file')
+    return -1
+
+class TermProgress:
+    def __init__(self):
+        self.nLastTick = -1
+
+    def Progress(self, dfComplete, message):
+
+        self.nThisTick = int(dfComplete * 40.0)
+        if self.nThisTick > 40:
+            self.nThisTick = 40
+
+        #// Have we started a new progress run?
+        if self.nThisTick < self.nLastTick and self.nLastTick >= 39:
+            self.nLastTick = -1;
+
+        if self.nThisTick <= self.nLastTick:
+            return True
+
+        while self.nThisTick > self.nLastTick:
+            self.nLastTick = self.nLastTick + 1
+            if self.nLastTick % 4 == 0:
+                val = int((self.nLastTick / 4) * 10)
+                sys.stdout.write("%d" % val)
+            else:
+                sys.stdout.write(".")
+
+        if self.nThisTick == 40:
+            print( " - done." )
+
+        sys.stdout.flush()
+
+        return True
+
+class ScaledProgress:
+    def __init__(self, dfMin, dfMax, UnderlyingProgress):
+        self.dfMin = dfMin
+        self.dfMax = dfMax
+        self.UnderlyingProgress = UnderlyingProgress
+
+    def Progress(self, dfComplete, message):
+        return self.UnderlyingProgress.Progress( dfComplete * (self.dfMax - self.dfMin) + self.dfMin,
+                                                 message )
+
+def gdal_cp_single(srcfile, targetfile, progress):
+    try:
+        if os.path.isdir(targetfile):
+            (head, tail) = os.path.split(srcfile)
+            targetfile = targetfile + '/' + tail
+    except:
+        pass
+
+    fin = gdal.VSIFOpenL(srcfile, "rb")
+    if fin is None:
+        print('Cannot open %s' % srcfile)
+        return -1
+
+    fout = gdal.VSIFOpenL(targetfile, "wb")
+    if fout is None:
+        print('Cannot create %s' % targetfile)
+        gdal.VSIFCloseL(fin)
+        return -1
+
+    version_num = int(gdal.VersionInfo('VERSION_NUM'))
+    total_size = 0
+    if version_num < 1900 or progress is not None:
+        gdal.VSIFSeekL(fin, 0, 2)
+        total_size = gdal.VSIFTellL(fin)
+        gdal.VSIFSeekL(fin, 0, 0)
+
+    buffer_max_size = 4096
+    copied = 0
+    ret = 0
+    #print('Copying %s...' % srcfile)
+    if progress is not None:
+        if not progress.Progress(0.0, 'Copying %s' % srcfile):
+            print('Copy stopped by user')
+            ret = -2
+
+    while ret == 0:
+        if total_size != 0 and copied + buffer_max_size > total_size:
+            to_read = total_size - copied
+        else:
+            to_read = buffer_max_size
+        buffer = gdal.VSIFReadL(1, to_read, fin)
+        if buffer is None:
+            if copied == 0:
+                print('Cannot read %d bytes in %s' % (to_read, srcfile))
+                ret = -1
+            break
+        buffer_size = len(buffer)
+        if gdal.VSIFWriteL(buffer, 1, buffer_size, fout) != buffer_size:
+            print('Error writing %d bytes' % buffer_size)
+            ret = -1
+            break
+        copied += buffer_size
+        if progress is not None and total_size != 0:
+            if not progress.Progress(copied * 1.0 / total_size, 'Copying %s' % srcfile):
+                print('Copy stopped by user')
+                ret = -2
+                break
+        if to_read < buffer_max_size or buffer_size != buffer_max_size:
+            break
+
+    gdal.VSIFCloseL(fin)
+    gdal.VSIFCloseL(fout)
+
+    return ret
+
+def gdal_cp_recurse(srcdir, targetdir, progress, skip_failure):
+
+    if srcdir[-1] == '/':
+        srcdir = srcdir[0:len(srcdir)-1]
+    lst = gdal.ReadDir(srcdir)
+    if lst is None:
+        print('%s is not a directory' % srcdir)
+        return -1
+
+    try:
+        os.stat(targetdir)
+    except:
+        os.mkdir(targetdir)
+
+    for srcfile in lst:
+        if srcfile == '.' or srcfile == '..':
+            continue
+        fullsrcfile = srcdir + '/' + srcfile
+        statBuf = gdal.VSIStatL(fullsrcfile, gdal.VSI_STAT_EXISTS_FLAG | gdal.VSI_STAT_NATURE_FLAG)
+        if statBuf.IsDirectory():
+            ret = gdal_cp_recurse(fullsrcfile, targetdir + '/' + srcfile, progress, skip_failure)
+        else:
+            ret = gdal_cp_single(fullsrcfile, targetdir, progress)
+        if ret == -2 or (ret == -1 and not skip_failure):
+            return ret
+    return 0
+
+def gdal_cp_pattern_match(srcdir, pattern, targetfile, progress, skip_failure):
+
+    if srcdir == '':
+        srcdir = '.'
+
+    lst = gdal.ReadDir(srcdir)
+    lst2 = []
+    if lst is None:
+        print('Cannot read directory %s' % srcdir)
+        return -1
+
+    for filename in lst:
+        if filename == '.' or filename == '..':
+            continue
+        if srcdir != '.':
+            lst2.append(srcdir + '/' + filename)
+        else:
+            lst2.append(filename)
+
+    if progress is not None:
+        total_size = 0
+        filesizelst = []
+        for srcfile in lst2:
+            filesize = 0
+            if fnmatch.fnmatch(srcfile, pattern):
+                fin = gdal.VSIFOpenL(srcfile, "rb")
+                if fin is not None:
+                    gdal.VSIFSeekL(fin, 0, 2)
+                    filesize = gdal.VSIFTellL(fin)
+                    gdal.VSIFCloseL(fin)
+
+            filesizelst.append(filesize)
+            total_size = total_size + filesize
+
+        if total_size == 0:
+            return -1
+
+        cursize = 0
+        i = 0
+        for srcfile in lst2:
+            if filesizelst[i] != 0:
+                dfMin = cursize * 1.0 / total_size
+                dfMax = (cursize + filesizelst[i]) * 1.0 / total_size
+                scaled_progress = ScaledProgress(dfMin, dfMax, progress)
+
+                ret = gdal_cp_single(srcfile, targetfile, scaled_progress)
+                if ret == -2 or (ret == -1 and not skip_failure):
+                    return ret
+
+                cursize += filesizelst[i]
+
+            i = i + 1
+
+    else:
+        for srcfile in lst2:
+            if fnmatch.fnmatch(srcfile, pattern):
+                ret = gdal_cp_single(srcfile, targetfile, progress)
+                if ret == -2 or (ret == -1 and not skip_failure):
+                    return ret
+    return 0
+
+
+def gdal_cp(argv, progress = None):
+    srcfile = None
+    targetfile = None
+    recurse = False
+    skip_failure = False
+
+    argv = gdal.GeneralCmdLineProcessor( argv )
+    if argv is None:
+        return -1
+
+    for i in range(1, len(argv)):
+        if argv[i] == '-progress':
+            progress = TermProgress()
+        elif argv[i] == '-r':
+            version_num = int(gdal.VersionInfo('VERSION_NUM'))
+            if version_num < 1900:
+                print('ERROR: Python bindings of GDAL 1.9.0 or later required for -r option')
+                return -1
+            recurse = True
+        elif len(argv[i]) >= 5 and argv[i][0:5] == '-skip':
+            skip_failure = True
+        elif argv[i][0] == '-':
+            print('Unrecognized option : %s' % argv[i])
+            return Usage()
+        elif srcfile is None:
+            srcfile = argv[i]
+        elif targetfile is None:
+            targetfile = argv[i]
+        else:
+            print('Unexpected option : %s' % argv[i])
+            return Usage()
+
+    if srcfile is None or targetfile is None:
+        return Usage()
+
+    if needsVSICurl(srcfile):
+        srcfile = '/vsicurl/' + srcfile
+
+    if recurse:
+        # Make sure that 'gdal_cp.py -r [srcdir/]lastsubdir targetdir' creates
+        # targetdir/lastsubdir if targetdir already exists (like cp -r does).
+        if srcfile[-1] == '/':
+            srcfile = srcfile[0:len(srcfile)-1]
+        statBufSrc = gdal.VSIStatL(srcfile, gdal.VSI_STAT_EXISTS_FLAG | gdal.VSI_STAT_NATURE_FLAG)
+        statBufDst = gdal.VSIStatL(targetfile, gdal.VSI_STAT_EXISTS_FLAG | gdal.VSI_STAT_NATURE_FLAG)
+        if statBufSrc is not None and statBufSrc.IsDirectory() and statBufDst is not None and statBufDst.IsDirectory():
+            if targetfile[-1] != '/':
+                if srcfile.rfind('/') != -1:
+                    targetfile = targetfile + srcfile[srcfile.rfind('/'):]
+                else:
+                    targetfile = targetfile + '/' + srcfile
+                try:
+                    os.stat(targetfile)
+                except:
+                    os.mkdir(targetfile)
+        return gdal_cp_recurse(srcfile, targetfile, progress, skip_failure)
+
+    (srcdir, pattern) = os.path.split(srcfile)
+    if pattern.find('*') != -1 or pattern.find('?') != -1:
+        return gdal_cp_pattern_match(srcdir, pattern, targetfile, progress, skip_failure)
+    else:
+        return gdal_cp_single(srcfile, targetfile, progress)
+
+if __name__ == '__main__':
+    version_num = int(gdal.VersionInfo('VERSION_NUM'))
+    if version_num < 1800:
+        print('ERROR: Python bindings of GDAL 1.8.0 or later required')
+        sys.exit(1)
+
+    sys.exit(gdal_cp(sys.argv))
diff --git a/swig/python/samples/gdal_edit.py b/swig/python/samples/gdal_edit.py
new file mode 100755
index 0000000..b2e44fa
--- /dev/null
+++ b/swig/python/samples/gdal_edit.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: gdal_edit.py 23103 2011-09-22 16:58:49Z 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>
+#
+#  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 sys
+from osgeo import gdal
+
+def Usage():
+    print('Usage: gdal_edit [--help-general] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]')
+    print('                 [-tr xres yres] [-unsetgt] [-a_nodata value] ')
+    print('                 [-mo "META-TAG=VALUE"]*  datasetname')
+    print('')
+    print('Edit in place various information of an existing GDAL dataset.')
+    return -1
+
+def gdal_edit(argv):
+
+    argv = gdal.GeneralCmdLineProcessor( argv )
+    if argv is None:
+        return -1
+
+    datasetname = None
+    srs = None
+    ulx = None
+    uly = None
+    lrx = None
+    lry = None
+    nodata = None
+    xres = None
+    yres = None
+    unsetgt = False
+    molist = []
+
+    i = 1
+    argc = len(argv)
+    while i < argc:
+        if 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:
+            ulx = float(argv[i+1])
+            i = i + 1
+            uly = float(argv[i+1])
+            i = i + 1
+            lrx = float(argv[i+1])
+            i = i + 1
+            lry = float(argv[i+1])
+            i = i + 1
+        elif argv[i] == '-tr' and i < len(argv)-2:
+            xres = float(argv[i+1])
+            i = i + 1
+            yres = float(argv[i+1])
+            i = i + 1
+        elif argv[i] == '-a_nodata' and i < len(argv)-1:
+            nodata = float(argv[i+1])
+            i = i + 1
+        elif argv[i] == '-mo' and i < len(argv)-1:
+            molist.append(argv[i+1])
+            i = i + 1
+        elif argv[i] == '-unsetgt' :
+            unsetgt = True
+        elif argv[i][0] == '-':
+            sys.stderr.write('Unrecognized option : %s\n' % argv[i])
+            return Usage()
+        elif datasetname is None:
+            datasetname = argv[i]
+        else:
+            sys.stderr.write('Unexpected option : %s\n' % argv[i])
+            return Usage()
+
+        i = i + 1
+
+    if datasetname is None:
+        return Usage()
+
+    if srs is None and lry is None and yres is None and not unsetgt and nodata is None and len(molist) == 0:
+        print('No option specified')
+        print('')
+        return Usage()
+
+    exclusive_option = 0
+    if lry is not None:
+        exclusive_option = exclusive_option + 1
+    if yres is not None:
+        exclusive_option = exclusive_option + 1
+    if unsetgt:
+        exclusive_option = exclusive_option + 1
+    if exclusive_option > 1:
+        print('-a_ullr, -tr and -unsetgt options are exclusive.')
+        print('')
+        return Usage()
+
+    ds = gdal.Open(datasetname, gdal.GA_Update)
+    if ds is None:
+        return -1
+
+    if srs is not None:
+        ds.SetProjection(srs)
+
+    if lry is not None:
+        gt = [ ulx, (lrx - ulx) / ds.RasterXSize, 0,
+               uly, 0, (lry - uly) / ds.RasterYSize ]
+        ds.SetGeoTransform(gt)
+
+    if yres is not None:
+        gt = ds.GetGeoTransform()
+        # Doh ! why is gt a tuple and not an array...
+        gt = [ gt[i] for i in range(6) ]
+        gt[1] = xres
+        gt[5] = yres
+        ds.SetGeoTransform(gt)
+
+    if unsetgt:
+        ds.SetGeoTransform([0,1,0,0,0,1])
+
+    if nodata is not None:
+        for i in range(ds.RasterCount):
+            ds.GetRasterBand(1).SetNoDataValue(nodata)
+
+    if len(molist) != 0:
+        ds.SetMetadata(molist)
+
+    ds = None
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(gdal_edit(sys.argv))
diff --git a/swig/python/samples/gdal_ls.py b/swig/python/samples/gdal_ls.py
new file mode 100755
index 0000000..3ec9681
--- /dev/null
+++ b/swig/python/samples/gdal_ls.py
@@ -0,0 +1,208 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: gdal_ls.py 22993 2011-08-27 23:44:06Z 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>
+#
+#  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
+import sys
+import os
+
+def needsVSICurl(filename):
+    return filename.startswith('http://') or filename.startswith('https://') or filename.startswith('ftp://')
+
+def iszip(filename):
+    return filename.endswith('.zip') or filename.endswith('.ZIP')
+
+def istgz(filename):
+    return filename.endswith('.tgz') or filename.endswith('.TGZ') or \
+           filename.endswith('.tar.gz') or filename.endswith('.TAR.GZ')
+
+def display_file(fout, dirname, prefix, filename, longformat, check_open = False):
+
+    statBuf = None
+    filename_displayed = prefix + filename
+
+    version_num = int(gdal.VersionInfo('VERSION_NUM'))
+    if longformat:
+        if version_num >= 1900:
+            statBuf = gdal.VSIStatL(dirname + '/' + filename, gdal.VSI_STAT_EXISTS_FLAG | gdal.VSI_STAT_NATURE_FLAG | gdal.VSI_STAT_SIZE_FLAG)
+    else:
+        if version_num >= 1900:
+            statBuf = gdal.VSIStatL(dirname + '/' + filename, gdal.VSI_STAT_EXISTS_FLAG | gdal.VSI_STAT_NATURE_FLAG)
+
+    if statBuf is None and check_open:
+        if version_num >= 1900:
+            f = None
+        else:
+            f = gdal.VSIFOpenL(dirname + '/' + filename, "rb")
+        if f is None:
+            sys.stderr.write('Cannot open %s\n' % (dirname + '/' + filename))
+            return
+        gdal.VSIFCloseL(f)
+
+    if statBuf is not None and statBuf.IsDirectory():
+        filename_displayed = filename_displayed + "/"
+
+    if longformat and statBuf is not None:
+        import time
+        bdt = time.gmtime(statBuf.mtime)
+        if statBuf.IsDirectory():
+            permissions = "dr-xr-xr-x"
+        else:
+            permissions = "-r--r--r--"
+        line = "%s  1 unknown unknown %12d %04d-%02d-%02d %02d:%02d %s\n" % \
+            (permissions, statBuf.size, bdt.tm_year, bdt.tm_mon, bdt.tm_mday, bdt.tm_hour, bdt.tm_min, filename_displayed)
+    else:
+        line = filename_displayed + "\n"
+
+    fout.write(line)
+
+def readDir(fout, dirname, prefix, longformat, recurse, depth, recurseInZip, recurseInTGZ, first = False):
+
+    if depth <= 0:
+        return
+
+    if needsVSICurl(dirname):
+        dirname = '/vsicurl/' + dirname
+        prefix = '/vsicurl/' + prefix
+
+    if recurseInZip and iszip(dirname) and not dirname.startswith('/vsizip'):
+        dirname = '/vsizip/' + dirname
+        prefix = '/vsizip/' + prefix
+
+    if recurseInTGZ and istgz(dirname) and not dirname.startswith('/vsitar'):
+        dirname = '/vsitar/' + dirname
+        prefix = '/vsitar/' + prefix
+
+    lst = gdal.ReadDir(dirname)
+    if lst is None:
+        if first:
+            original_dirname = dirname
+            (dirname, filename) = os.path.split(dirname)
+            if gdal.ReadDir(dirname) is None:
+                sys.stderr.write('Cannot open %s\n' % original_dirname)
+                return
+            if dirname == '':
+                dirname = '.'
+                prefix = ''
+            else:
+                prefix = dirname + '/'
+            display_file(fout, dirname, prefix, filename, longformat, True)
+    else:
+        for filename in lst:
+            if filename == '.' or filename == '..':
+                continue
+
+            display_file(fout, dirname, prefix, filename, longformat)
+
+            if recurse:
+                readDir(fout, dirname + '/' + filename, prefix + filename + '/', \
+                        longformat, recurse, depth - 1, recurseInZip, recurseInTGZ)
+
+def Usage():
+    print('Usage: gdal_ls [-l] [-R] [-depth d] [-Rzip] [-Rtgz] name_of_virtual_directory')
+    print('')
+    print('Display the list of files in a virtual directory, like /vsicurl or /vsizip')
+    print('')
+    print('Options :')
+    print(' -l : use a long listing format (same as ls -l)')
+    print(' -R : list subdirectories recursively')
+    print(' -depth d : recurse until depth d')
+    print(' -Rzip : list content of .zip archives')
+    print(' -Rtgz : list content of .tar.gz/.tgz archives (potentially slow on /vsicurl/)')
+    return -1
+
+def gdal_ls(argv, fout = sys.stdout):
+    longformat = False
+    recurse = False
+    recurseInZip = False
+    recurseInTGZ = False
+    display_prefix = True
+    dirname = None
+    depth = 1024
+
+    argv = gdal.GeneralCmdLineProcessor( argv )
+    if argv is None:
+        return -1
+
+    i = 1
+    argc = len(argv)
+    while i < argc:
+        if argv[i] == '-l':
+            longformat = True
+        elif argv[i] == '-R':
+            recurse = True
+        elif argv[i] == '-Rzip':
+            recurseInZip = True
+        elif argv[i] == '-Rtgz':
+            recurseInTGZ = True
+        elif argv[i] == '-noprefix':
+            display_prefix = False
+        elif argv[i] == '-depth' and i < len(argv)-1:
+            depth = int(argv[i+1])
+            i = i + 1
+        elif argv[i][0] == '-':
+            sys.stderr.write('Unrecognized option : %s\n' % argv[i])
+            return Usage()
+        elif dirname is None:
+            dirname = argv[i]
+        else:
+            sys.stderr.write('Unexpected option : %s\n' % argv[i])
+            return Usage()
+
+        i = i + 1
+
+    if dirname is None:
+        return Usage()
+
+    # Remove trailing
+    if dirname[-1] == '/':
+        dirname = dirname[0:len(dirname)-1]
+
+    if needsVSICurl(dirname):
+        dirname = '/vsicurl/' + dirname
+
+    #if iszip(dirname) and not dirname.startswith('/vsizip'):
+    #    dirname = '/vsizip/' + dirname
+
+    #if istgz(dirname) and not dirname.startswith('/vsitar'):
+    #    dirname = '/vsitar/' + dirname
+
+    prefix = ''
+    if display_prefix:
+        prefix = dirname + '/'
+    readDir(fout, dirname, prefix, longformat, recurse, depth, recurseInZip, recurseInTGZ, True)
+    return 0
+
+if __name__ == '__main__':
+    version_num = int(gdal.VersionInfo('VERSION_NUM'))
+    if version_num < 1800:
+        sys.stderr.write('ERROR: Python bindings of GDAL 1.8.0 or later required\n')
+        sys.exit(1)
+
+    sys.exit(gdal_ls(sys.argv))
diff --git a/swig/python/samples/gdal_vrtmerge.py b/swig/python/samples/gdal_vrtmerge.py
old mode 100644
new mode 100755
diff --git a/swig/python/samples/gdalcopyproj.py b/swig/python/samples/gdalcopyproj.py
old mode 100644
new mode 100755
index d4a387f..c409c4e
--- a/swig/python/samples/gdalcopyproj.py
+++ b/swig/python/samples/gdalcopyproj.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gdalcopyproj.py 18195 2009-12-06 20:24:39Z rouault $
+#  $Id: gdalcopyproj.py 23368 2011-11-13 11:18:25Z rouault $
 # 
 #  Name:     gdalcopyproj.py
 #  Project:  GDAL Python Interface
@@ -64,9 +64,15 @@ if dataset2 is None:
     print('Unable to open', output, 'for writing')
     sys.exit(1)
 
-if geotransform is not None:
+if geotransform is not None and geotransform != (0,1,0,0,0,1):
     dataset2.SetGeoTransform( geotransform )
 
-if projection is not None:
+if projection is not None and projection != '':
     dataset2.SetProjection( projection )
 
+gcp_count = dataset.GetGCPs()
+if gcp_count != 0:
+    dataset2.SetGCPs( gcp_count, dataset.GetGCPProjection() )
+
+dataset = None
+dataset2 = None
diff --git a/swig/python/samples/gdalinfo.py b/swig/python/samples/gdalinfo.py
old mode 100644
new mode 100755
index 130ecac..e776428
--- a/swig/python/samples/gdalinfo.py
+++ b/swig/python/samples/gdalinfo.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #/******************************************************************************
-# * $Id: gdalinfo.py 21320 2010-12-27 15:31:50Z rouault $
+# * $Id: gdalinfo.py 22986 2011-08-27 14:20:16Z rouault $
 # *
 # * Project:  GDAL Utilities
 # * Purpose:  Python port of Commandline application to list info about a file.
@@ -45,7 +45,7 @@ except:
 
 def Usage():
     print( "Usage: gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n" + \
-            "                [-norat] [-noct] [-checksum] [-mdd domain]* datasetname" )
+            "                [-norat] [-noct] [-nofl] [-checksum] [-mdd domain]* datasetname" )
     return 1
 
 
@@ -72,6 +72,7 @@ def main( argv = None ):
     papszExtraMDDomains = [ ]
     pszProjection = None
     hTransform = None
+    bShowFileList = True
 
     #/* Must process GDAL_SKIP before GDALAllRegister(), but we can't call */
     #/* GDALGeneralCmdLineProcessor before it needs the drivers to be registered */
@@ -132,6 +133,8 @@ def main( argv = None ):
         elif EQUAL(argv[i], "-mdd") and i < nArgc-1:
             i = i + 1
             papszExtraMDDomains.append( argv[i] )
+        elif EQUAL(argv[i], "-nofl"):
+            bShowFileList = False
         elif argv[i][0] == '-':
             return Usage()
         elif pszFilename is None:
@@ -168,8 +171,9 @@ def main( argv = None ):
         print( "Files: none associated" )
     else:
         print( "Files: %s" % papszFileList[0] )
-        for i in range(1, len(papszFileList)):
-            print( "       %s" % papszFileList[i] )
+        if bShowFileList:
+            for i in range(1, len(papszFileList)):
+                print( "       %s" % papszFileList[i] )
 
     print( "Size is %d, %d" % (hDataset.RasterXSize, hDataset.RasterYSize))
 
diff --git a/swig/python/samples/hsv_merge.py b/swig/python/samples/hsv_merge.py
old mode 100644
new mode 100755
index d9d181d..67f8e4f
--- 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 21244 2010-12-13 18:32:06Z rouault $
+#  $Id: hsv_merge.py 22986 2011-08-27 14:20:16Z rouault $
 # 
 #  Project:  GDAL Python Interface
 #  Purpose:  Script to merge greyscale as intensity into an RGB(A) image, for
diff --git a/swig/python/samples/magphase.py b/swig/python/samples/magphase.py
old mode 100644
new mode 100755
diff --git a/swig/python/samples/ogr2ogr.py b/swig/python/samples/ogr2ogr.py
old mode 100644
new mode 100755
index b7048ae..1325008
--- a/swig/python/samples/ogr2ogr.py
+++ b/swig/python/samples/ogr2ogr.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #/******************************************************************************
-# * $Id: ogr2ogr.py 22027 2011-03-25 19:28:44Z rouault $
+# * $Id: ogr2ogr.py 23515 2011-12-10 21:14:02Z rouault $
 # *
 # * Project:  OpenGIS Simple Features Reference Implementation
 # * Purpose:  Python port of a simple client for translating between formats.
@@ -115,6 +115,14 @@ nGroupTransactions = 200
 bPreserveFID = False
 nFIDToFetch = ogr.NullFID
 
+class Enum(set):
+    def __getattr__(self, name):
+        if name in self:
+            return name
+        raise AttributeError
+
+GeomOperation = Enum(["NONE", "SEGMENTIZE", "SIMPLIFY_PRESERVE_TOPOLOGY"])
+
 def main(args = None, progress_func = TermProgress, progress_data = None):
     
     global bSkipFailures
@@ -140,10 +148,11 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
     pszWHERE = None
     poSpatialFilter = None
     pszSelect = None
-    papszSelFields = []
+    papszSelFields = None
     pszSQLStatement = None
     eGType = -2
-    dfMaxSegmentLength = 0
+    eGeomOp = GeomOperation.NONE
+    dfGeomOpParam = 0
     papszFieldTypesToString = []
     bDisplayProgress = False
     pfnProgress = None
@@ -305,10 +314,18 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
                 papszSelFields = pszSelect.split(',')
             else:
                 papszSelFields = pszSelect.split(' ')
+            if papszSelFields[0] == '':
+                papszSelFields = []
+
+        elif EQUAL(args[iArg],"-simplify") and iArg < nArgc-1:
+            iArg = iArg + 1
+            eGeomOp = GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY
+            dfGeomOpParam = float(args[iArg])
 
         elif EQUAL(args[iArg],"-segmentize") and iArg < nArgc-1:
             iArg = iArg + 1
-            dfMaxSegmentLength = float(args[iArg])
+            eGeomOp = GeomOperation.SEGMENTIZE
+            dfGeomOpParam = float(args[iArg])
 
         elif EQUAL(args[iArg],"-fieldTypeToString") and iArg < nArgc-1:
             iArg = iArg + 1
@@ -533,11 +550,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
 #/*      Find the output driver.                                         */
 #/* -------------------------------------------------------------------- */
     if not bUpdate:
-        for iDriver in range(ogr.GetDriverCount()):
-            if EQUAL(ogr.GetDriver(iDriver).GetName(),pszFormat):
-                poDriver = ogr.GetDriver(iDriver)
-                break
-
+        poDriver = ogr.GetDriverByName(pszFormat)
         if poDriver is None:
             print("Unable to find driver `%s'." % pszFormat)
             print( "The following drivers are available:" )
@@ -552,6 +565,33 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             return False
 
 #/* -------------------------------------------------------------------- */
+#/*      Special case to improve user experience when translating        */
+#/*      a datasource with multiple layers into a shapefile. If the      */
+#/*      user gives a target datasource with .shp and it does not exist, */
+#/*      the shapefile driver will try to create a file, but this is not */
+#/*      appropriate because here we have several layers, so create      */
+#/*      a directory instead.                                            */
+#/* -------------------------------------------------------------------- */
+        if EQUAL(poDriver.GetName(), "ESRI Shapefile") and \
+           pszSQLStatement is None and \
+           (len(papszLayers) > 1 or \
+            (len(papszLayers) == 0 and poDS.GetLayerCount() > 1)) and \
+            pszNewLayerName is None and \
+            EQUAL(os.path.splitext(pszDestDataSource)[1], ".SHP") :
+
+            try:
+                os.stat(pszDestDataSource)
+            except:
+                try:
+                    # decimal 493 = octal 0755. Python 3 needs 0o755, but
+                    # this syntax is only supported by Python >= 2.6
+                    os.mkdir(pszDestDataSource, 493)
+                except:
+                    print("Failed to create directory %s\n"
+                          "for shapefile datastore.\n" % pszDestDataSource )
+                    return False
+
+#/* -------------------------------------------------------------------- */
 #/*      Create the output data source.                                  */
 #/* -------------------------------------------------------------------- */
         poODS = poDriver.CreateDataSource( pszDestDataSource, options = papszDSCO )
@@ -618,7 +658,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             if not TranslateLayer( poDS, poResultSet, poODS, papszLCO, \
                                 pszNewLayerName, bTransform, poOutputSRS, \
                                 poSourceSRS, papszSelFields, bAppend, eGType, \
-                                bOverwrite, dfMaxSegmentLength, papszFieldTypesToString, \
+                                bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString, \
                                 nCountLayerFeatures, poClipSrc, poClipDst, bExplodeCollections, \
                                 pszZField, pszWHERE, pfnProgress, pProgressData ):
                 print(
@@ -679,7 +719,10 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             poLayer = papoLayers[iLayer]
 
             if pszWHERE is not None:
-                poLayer.SetAttributeFilter( pszWHERE )
+                if poLayer.SetAttributeFilter( pszWHERE ) != 0:
+                    print("FAILURE: SetAttributeFilter(%s) failed." % pszWHERE)
+                    if not bSkipFailures:
+                        return False
 
             if poSpatialFilter is not None:
                 poLayer.SetSpatialFilter( poSpatialFilter )
@@ -722,7 +765,7 @@ def main(args = None, progress_func = TermProgress, progress_data = None):
             if not TranslateLayer( poDS, poLayer, poODS, papszLCO,  \
                                 pszNewLayerName, bTransform, poOutputSRS, \
                                 poSourceSRS, papszSelFields, bAppend, eGType, \
-                                bOverwrite, dfMaxSegmentLength, papszFieldTypesToString, \
+                                bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString, \
                                 panLayerCountFeatures[iLayer], poClipSrc, poClipDst, bExplodeCollections, \
                                 pszZField, pszWHERE, pfnProgress, pProgressData)  \
                 and not bSkipFailures:
@@ -754,6 +797,7 @@ def Usage():
             "               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n" + \
             "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n" + \
             "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n" + \
+            "               [-simplify tolerance]\n" + \
             #// "               [-segmentize max_dist] [-fieldTypeToString All|(type1[,type2]*)]\n" + \
             "               [-fieldTypeToString All|(type1[,type2]*)] [-explodecollections] \n" + \
             "               dst_datasource_name src_datasource_name\n" + \
@@ -778,6 +822,7 @@ def Usage():
             " -skipfailures: skip features or layers that fail to convert\n" + \
             " -gt n: group n features per transaction (default 200)\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" + \
             #//"                       Used to create intermediate points\n" + \
             " -dsco NAME=VALUE: Dataset creation option (format specific)\n" + \
@@ -905,7 +950,7 @@ def SetZ (poGeom, dfZ ):
 
 def TranslateLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                     bTransform,  poOutputSRS, poSourceSRS, papszSelFields, \
-                    bAppend, eGType, bOverwrite, dfMaxSegmentLength, \
+                    bAppend, eGType, bOverwrite, eGeomOp, dfGeomOpParam, \
                     papszFieldTypesToString, nCountLayerFeatures, \
                     poClipSrc, poClipDst, bExplodeCollections, pszZField, pszWHERE, \
                     pfnProgress, pProgressData) :
@@ -968,25 +1013,30 @@ def TranslateLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
 #/* -------------------------------------------------------------------- */
 #/*      Find the layer.                                                 */
 #/* -------------------------------------------------------------------- */
-    iLayer = -1
-    poDstLayer = None
 
     #/* 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) */
     gdal.PushErrorHandler('CPLQuietErrorHandler')
-    poDstDS.GetLayerByName(pszNewLayerName)
+    poDstLayer = poDstDS.GetLayerByName(pszNewLayerName)
     gdal.PopErrorHandler()
     gdal.ErrorReset()
 
-    for iLayer in range(poDstDS.GetLayerCount()):
-        poLayer = poDstDS.GetLayer(iLayer)
+    iLayer = -1
+    if poDstLayer is not None:
+        nLayerCount = poDstDS.GetLayerCount()
+        for iLayer in range(nLayerCount):
+            poLayer = poDstDS.GetLayer(iLayer)
+            # The .cpp version compares on pointers directly, but we cannot
+            # do this with swig object, so just compare the names.
+            if poLayer is not None \
+                and poLayer.GetName() == poDstLayer.GetName():
+                break
 
-        if poLayer is not None \
-            and EQUAL(poLayer.GetLayerDefn().GetName(), pszNewLayerName):
-            poDstLayer = poLayer
-            break
+        if (iLayer == nLayerCount):
+            # /* shouldn't happen with an ideal driver */
+            poDstLayer = None
 
 #/* -------------------------------------------------------------------- */
 #/*      If the user requested overwrite, and we have the layer in       */
@@ -1017,7 +1067,8 @@ def TranslateLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                     eGType = ogr.wkbPolygon | n25DBit
                 elif wkbFlatten(eGType) == ogr.wkbGeometryCollection:
                     eGType = ogr.wkbUnknown | n25DBit
-            elif pszZField is not None:
+
+            if pszZField is not None:
                 eGType = eGType | ogr.wkb25DBit
 
         if poDstDS.TestCapability( ogr.ODsCCreateLayer ) == False:
@@ -1059,7 +1110,7 @@ def TranslateLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
 
     poDstFDefn = poDstLayer.GetLayerDefn()
 
-    if len(papszSelFields) > 0 and not bAppend:
+    if papszSelFields is not None and not bAppend:
 
         nDstFieldCount = 0
         if poDstFDefn is not None:
@@ -1123,6 +1174,9 @@ def TranslateLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
                         bFieldRequested = True
                         break
 
+                if pszZField is not None and pszFieldName == pszZField:
+                    bFieldRequested = True
+
                 #/* If source field not requested, add it to ignored files list */
                 if not bFieldRequested:
                     papszIgnoredFields.append(pszFieldName)
@@ -1251,9 +1305,6 @@ def TranslateLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
             if bPreserveFID:
                 poDstFeature.SetFID( poFeature.GetFID() )
 
-            #/*if (poDstFeature.GetGeometryRef() is not None and dfMaxSegmentLength > 0)
-            #    poDstFeature.GetGeometryRef().segmentize(dfMaxSegmentLength);*/
-
             poDstGeometry = poDstFeature.GetGeometryRef()
             if poDstGeometry is not None:
 
@@ -1265,6 +1316,20 @@ def TranslateLayer( poSrcDS, poSrcLayer, poDstDS, papszLCO, pszNewLayerName, \
 
                 if iSrcZField != -1:
                     SetZ(poDstGeometry, poFeature.GetFieldAsDouble(iSrcZField))
+                    # /* This will correct the coordinate dimension to 3 */
+                    poDupGeometry = poDstGeometry.Clone()
+                    poDstFeature.SetGeometryDirectly(poDupGeometry)
+                    poDstGeometry = poDupGeometry
+
+                if eGeomOp == GeomOperation.SEGMENTIZE:
+                    pass
+                    #/*if (poDstFeature.GetGeometryRef() is not None and dfGeomOpParam > 0)
+                    #    poDstFeature.GetGeometryRef().segmentize(dfGeomOpParam);*/
+                elif eGeomOp == GeomOperation.SIMPLIFY_PRESERVE_TOPOLOGY and dfGeomOpParam > 0:
+                    poNewGeom = poDstGeometry.SimplifyPreserveTopology(dfGeomOpParam)
+                    if poNewGeom is not None:
+                        poDstFeature.SetGeometryDirectly(poNewGeom)
+                        poDstGeometry = poNewGeom
 
                 if poClipSrc is not None:
                     poClipped = poDstGeometry.Intersection(poClipSrc)
diff --git a/swig/python/samples/ogrinfo.py b/swig/python/samples/ogrinfo.py
old mode 100644
new mode 100755
index e98cc06..0ebfed0
--- a/swig/python/samples/ogrinfo.py
+++ b/swig/python/samples/ogrinfo.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #/******************************************************************************
-# * $Id: ogrinfo.py 21660 2011-02-08 21:37:51Z rouault $
+# * $Id: ogrinfo.py 23329 2011-11-05 21:09:07Z rouault $
 # *
 # * Project:  OpenGIS Simple Features Reference Implementation
 # * Purpose:  Python port of a simple client for viewing OGR driver data.
@@ -216,7 +216,9 @@ def main(argv = None):
 
         if poResultSet is not None:
             if pszWHERE is not None:
-                poResultSet.SetAttributeFilter( pszWHERE )
+                if poResultSet.SetAttributeFilter( pszWHERE ) != 0:
+                    print("FAILURE: SetAttributeFilter(%s) failed." % pszWHERE)
+                    return 1
 
             ReportOnLayer( poResultSet, None, None, options )
             poDS.ReleaseResultSet( poResultSet )
@@ -296,7 +298,9 @@ def ReportOnLayer( poLayer, pszWHERE, poSpatialFilter, options ):
 #/*      Set filters if provided.                                        */
 #/* -------------------------------------------------------------------- */
     if pszWHERE is not None:
-        poLayer.SetAttributeFilter( pszWHERE )
+        if poLayer.SetAttributeFilter( pszWHERE ) != 0:
+            print("FAILURE: SetAttributeFilter(%s) failed." % pszWHERE)
+            return
 
     if poSpatialFilter is not None:
         poLayer.SetSpatialFilter( poSpatialFilter )
@@ -313,7 +317,7 @@ def ReportOnLayer( poLayer, pszWHERE, poSpatialFilter, options ):
         
         print( "Feature Count: %d" % poLayer.GetFeatureCount() )
         
-        oExt = poLayer.GetExtent(True)
+        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]))
 
diff --git a/swig/python/scripts/gcps2vec.py b/swig/python/scripts/gcps2vec.py
index da9178f..3787c22 100755
--- a/swig/python/scripts/gcps2vec.py
+++ b/swig/python/scripts/gcps2vec.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #******************************************************************************
-#  $Id: gcps2vec.py 18952 2010-02-28 11:59:53Z rouault $
+#  $Id: gcps2vec.py 21739 2011-02-18 14:59:15Z dron $
 # 
 #  Project:  GDAL
 #  Purpose:  Convert GCPs to a point layer.
@@ -27,34 +27,27 @@
 #  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 #  DEALINGS IN THE SOFTWARE.
 #******************************************************************************
-# 
-# $Log$
-# Revision 1.2  2006/03/21 21:54:00  fwarmerdam
-# fixup headers
-#
-# Revision 1.1  2005/02/07 14:36:12  fwarmerdam
-# New
-#
-#
 
 try:
     from osgeo import gdal
     from osgeo import ogr
+    from osgeo import osr
 except ImportError:
     import gdal
     import ogr
+    import osr
 
 import sys
 
 def Usage():
-    print('Usage: gcp2vec.py [-of <ogr_drivername>] <raster_file> <vector_file>')
+    print('Usage: gcps2vec.py [-of <ogr_drivername>] [-p] <raster_file> <vector_file>')
     sys.exit(1)
 
 # =============================================================================
 # 	Mainline
 # =============================================================================
 
-format = 'GML'
+out_format = 'GML'
 in_file = None
 out_file = None
 pixel_out = 0
@@ -70,9 +63,10 @@ while i < len(argv):
     arg = argv[i]
 
     if arg == '-of':
-        format = argv[i]
+        i = i + 1
+        out_format = argv[i]
 
-    if arg == '-p':
+    elif arg == '-p':
         pixel_out = 1
 
     elif in_file is None:
@@ -110,16 +104,25 @@ if gcps is None or len(gcps) == 0:
 # Create output file, and layer.
 # ----------------------------------------------------------------------------
 
-drv = ogr.GetDriverByName( format )
+drv = ogr.GetDriverByName( out_format )
 if drv is None:
-    print('No driver named %s available.' % format)
+    print('No driver named %s available.' % out_format)
     sys.exit(1)
 
 ds = drv.CreateDataSource( out_file )
 
-srs = None
+if pixel_out == 0 and gcp_srs != "":
+    srs = osr.SpatialReference()
+    srs.ImportFromWkt(gcp_srs)
+else:
+    srs = None
+
+if pixel_out == 0:
+    geom_type = ogr.wkbPoint25D
+else:
+    geom_type = ogr.wkbPoint
 
-layer = ds.CreateLayer( 'gcps', srs, geom_type = ogr.wkbPoint25D )
+layer = ds.CreateLayer( 'gcps', srs, geom_type = geom_type )
 
 if pixel_out == 0:
     fd = ogr.FieldDefn( 'Pixel', ogr.OFTReal )
@@ -134,6 +137,9 @@ else:
     fd = ogr.FieldDefn( 'Y', ogr.OFTReal )
     layer.CreateField( fd )
 
+    fd = ogr.FieldDefn( 'Z', ogr.OFTReal )
+    layer.CreateField( fd )
+
 fd = ogr.FieldDefn( 'Id', ogr.OFTString )
 layer.CreateField( fd )
 
@@ -148,15 +154,16 @@ for gcp in gcps:
 
     feat = ogr.Feature( layer.GetLayerDefn() )
 
-    geom = ogr.Geometry( ogr.wkbPoint25D )
-
     if pixel_out == 0:
+        geom = ogr.Geometry( geom_type )
         feat.SetField( 'Pixel', gcp.GCPPixel )
         feat.SetField( 'Line',  gcp.GCPLine )
         geom.SetPoint( 0, gcp.GCPX, gcp.GCPY, gcp.GCPZ )
     else:
+        geom = ogr.Geometry( geom_type )
         feat.SetField( 'X', gcp.GCPX )
         feat.SetField( 'Y',  gcp.GCPY )
+        feat.SetField( 'Z',  gcp.GCPZ )
         geom.SetPoint( 0, gcp.GCPPixel, gcp.GCPLine )
         
     feat.SetField( 'Id',    gcp.Id )
diff --git a/swig/python/scripts/gdal_calc.py b/swig/python/scripts/gdal_calc.py
old mode 100644
new mode 100755
index 5722890..0c43ba4
--- a/swig/python/scripts/gdal_calc.py
+++ b/swig/python/scripts/gdal_calc.py
@@ -97,7 +97,8 @@ def doit(opts, args):
             # check that the dimensions of each layer are the same
             if DimensionsCheck:
                 if DimensionsCheck!=[myFiles[i].RasterXSize, myFiles[i].RasterYSize]:
-                    print("Error! Dimensions of file %s (%i, %i) are different from file %s (%i, %i).  Cannot proceed")
+                    print("Error! Dimensions of file %s (%i, %i) are different from other files (%i, %i).  Cannot proceed" % \
+                            (myF,myFiles[i].RasterXSize, myFiles[i].RasterYSize,DimensionsCheck[0],DimensionsCheck[1]))
                     return
             else:
                 DimensionsCheck=[myFiles[i].RasterXSize, myFiles[i].RasterYSize]
diff --git a/swig/python/scripts/gdal_fillnodata.dox b/swig/python/scripts/gdal_fillnodata.dox
index 5144e08..b348a43 100644
--- a/swig/python/scripts/gdal_fillnodata.dox
+++ b/swig/python/scripts/gdal_fillnodata.dox
@@ -3,7 +3,7 @@
 
 fill raster regions by interpolation from edges
 
-\section synopsis SYNOPSIS
+\section gdal_fillnodata_synopsis SYNOPSIS
 
 \verbatim
 gdal_fillnodata.py [-q] [-md max_distance] [-si smooth_iterations]
@@ -11,7 +11,7 @@ gdal_fillnodata.py [-q] [-md max_distance] [-si smooth_iterations]
                 srcfile [-nomask] [-mask filename] [-of format] [dstfile]
 \endverbatim
 
-\section description DESCRIPTION
+\section gdal_fillnodata_description DESCRIPTION
 
 The gdal_fillnodata.py script fills selection regions (usually nodata areas)
 by interpolating from valid pixels around the edges of the area.  
@@ -60,7 +60,7 @@ non-zero is valid).
 </dl>
 
 \if man
-\section author AUTHORS
+\section gdal_fillnodata_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
diff --git a/swig/python/scripts/gdal_fillnodata.py b/swig/python/scripts/gdal_fillnodata.py
index 6864682..e4778ea 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 19392 2010-04-12 18:27:09Z rouault $
+#  $Id: gdal_fillnodata.py 23153 2011-10-01 13:40:24Z rouault $
 # 
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for filling nodata areas in a raster by interpolation
@@ -47,7 +47,7 @@ def Usage():
     print("""
 gdal_fillnodata [-q] [-md max_distance] [-si smooth_iterations]
                 [-o name=value] [-b band]
-                srcfile [-nomask] [-mask filename] [-of format] [dstfile]
+                srcfile [-nomask] [-mask filename] [-of format] [-co name=value]* [dstfile]
 """)
     sys.exit(1)
     
@@ -64,6 +64,7 @@ src_band = 1
 
 dst_filename = None
 format = 'GTiff'
+creation_options = []
 
 mask = 'default'
 
@@ -81,6 +82,10 @@ while i < len(argv):
         i = i + 1
         format = argv[i]
 
+    elif arg == '-co':
+        i = i + 1
+        creation_options.append(argv[i])
+
     elif arg == '-q' or arg == '-quiet':
         quiet_flag = 1
         
@@ -167,7 +172,7 @@ if dst_filename is not None:
 
     drv = gdal.GetDriverByName(format)
     dst_ds = drv.Create( dst_filename,src_ds.RasterXSize, src_ds.RasterYSize,1,
-                         srcband.DataType )
+                         srcband.DataType, creation_options )
     wkt = src_ds.GetProjection()
     if wkt != '':
         dst_ds.SetProjection( wkt )
diff --git a/swig/python/scripts/gdal_merge.py b/swig/python/scripts/gdal_merge.py
index bf802f6..34df8ea 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 20778 2010-10-06 17:31:34Z rouault $
+# $Id: gdal_merge.py 22325 2011-05-07 19:50:58Z rouault $
 #
 # Project:  InSAR Peppers
 # Purpose:  Module to extract data from many rasters into one output.
@@ -24,6 +24,11 @@
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 ###############################################################################
+# changes 29Apr2011
+# if the input image is a multi-band one, use all 
+# the channels in building the stack
+# anssi.pekkarinen at fao.org
+
 
 try:
     from osgeo import gdal
@@ -65,7 +70,7 @@ def raster_copy( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
     t_band = t_fh.GetRasterBand( t_band_n )
 
     data = s_band.ReadRaster( s_xoff, s_yoff, s_xsize, s_ysize,
-                              t_xsize, t_ysize, t_band.DataType )
+                             t_xsize, t_ysize, t_band.DataType )
     t_band.WriteRaster( t_xoff, t_yoff, t_xsize, t_ysize,
                         data, t_xsize, t_ysize, t_band.DataType )
         
@@ -95,7 +100,7 @@ def raster_copy_with_nodata( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
 
     nodata_test = Numeric.equal(data_src,nodata)
     to_write = Numeric.choose( nodata_test, (data_src, data_dst) )
-                               
+
     t_band.WriteArray( to_write, t_xoff, t_yoff )
 
     return 0
@@ -241,7 +246,8 @@ class file_info:
 def Usage():
     print('Usage: gdal_merge.py [-o out_filename] [-of out_format] [-co NAME=VALUE]*')
     print('                     [-ps pixelsize_x pixelsize_y] [-tap] [-separate] [-q] [-v] [-pct]')
-    print('                     [-ul_lr ulx uly lrx lry] [-n nodata_value] [-init "value [value...]"]')
+    print('                     [-ul_lr ulx uly lrx lry] [-init "value [value...]"]')
+    print('                     [-n nodata_value] [-a_nodata output_nodata_value]')
     print('                     [-ot datatype] [-createonly] input_files')
     print('                     [--help-general]')
     print('')
@@ -265,6 +271,7 @@ def main( argv=None ):
     separate = 0
     copy_pct = 0
     nodata = None
+    a_nodata = None
     create_options = []
     pre_init = []
     band_type = None
@@ -322,6 +329,10 @@ def main( argv=None ):
             i = i + 1
             nodata = float(argv[i])
 
+        elif arg == '-a_nodata':
+            i = i + 1
+            a_nodata = float(argv[i])
+
         elif arg == '-f':
             # for backward compatibility.
             i = i + 1
@@ -419,11 +430,16 @@ def main( argv=None ):
         xsize = int((lrx - ulx) / geotransform[1] + 0.5)
         ysize = int((lry - uly) / geotransform[5] + 0.5)
 
+
         if separate != 0:
-            bands = len(file_infos)
+            bands=0
+
+            for fi in file_infos:
+                bands=bands + fi.bands
         else:
             bands = file_infos[0].bands
 
+
         t_fh = Driver.Create( out_file, xsize, ysize, bands,
                               band_type, create_options )
         if t_fh is None:
@@ -437,13 +453,20 @@ def main( argv=None ):
             t_fh.GetRasterBand(1).SetRasterColorTable(file_infos[0].ct)
     else:
         if separate != 0:
-            bands = len(file_infos)
+            bands=0
+            for fi in file_infos:
+                bands=bands + fi.bands            
             if t_fh.RasterCount < bands :
-                print('Existing output file has less bands than the number of input files. You should delete it before. Terminating gdal_merge.')
+                print('Existing output file has less bands than the input files. You should delete it before. Terminating gdal_merge.')
                 sys.exit( 1 )
         else:
             bands = min(file_infos[0].bands,t_fh.RasterCount)
 
+    # Do we need to set nodata value ?
+    if a_nodata is not None:
+        for i in range(t_fh.RasterCount):
+            t_fh.GetRasterBand(i+1).SetNoDataValue(a_nodata)
+
     # Do we need to pre-initialize the whole mosaic file to some value?
     if pre_init is not None:
         if t_fh.RasterCount <= len(pre_init):
@@ -475,8 +498,9 @@ def main( argv=None ):
             for band in range(1, bands+1):
                 fi.copy_into( t_fh, band, band, nodata )
         else:
-            fi.copy_into( t_fh, 1, t_band, nodata )
-            t_band = t_band+1
+            for band in range(1, fi.bands+1):
+                fi.copy_into( t_fh, band, t_band, nodata )
+                t_band = t_band+1
             
         fi_processed = fi_processed+1
         if quiet == 0 and verbose == 0:
diff --git a/swig/python/scripts/gdal_proximity.py b/swig/python/scripts/gdal_proximity.py
index 8436230..c0ecd6f 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 19392 2010-04-12 18:27:09Z rouault $
+#  $Id: gdal_proximity.py 23152 2011-10-01 13:39:52Z rouault $
 # 
 #  Name:     gdalproximity
 #  Project:  GDAL Python Interface
@@ -160,7 +160,7 @@ if dst_ds is None:
     drv = gdal.GetDriverByName(format)
     dst_ds = drv.Create( dst_filename,
                          src_ds.RasterXSize, src_ds.RasterYSize, 1,
-                         gdal.GetDataTypeByName(creation_type) )
+                         gdal.GetDataTypeByName(creation_type), creation_options )
 
     dst_ds.SetGeoTransform( src_ds.GetGeoTransform() )
     dst_ds.SetProjection( src_ds.GetProjectionRef() )
diff --git a/swig/python/scripts/gdal_sieve.dox b/swig/python/scripts/gdal_sieve.dox
index 5cfef22..962434e 100755
--- a/swig/python/scripts/gdal_sieve.dox
+++ b/swig/python/scripts/gdal_sieve.dox
@@ -3,14 +3,14 @@
 
 removes small raster polygons
 
-\section synopsis SYNOPSIS
+\section gdal_sieve_synopsis SYNOPSIS
 
 \verbatim
 gdal_sieve.py [-q] [-st threshold] [-4] [-8] [-o name=value]
            srcfile [-nomask] [-mask filename] [-of format] [dstfile]
 \endverbatim
 
-\section description DESCRIPTION
+\section gdal_sieve_description DESCRIPTION
 
 The gdal_sieve.py script removes raster polygons smaller than a provided
 threshold size (in pixels) and replaces replaces them with the pixel value 
@@ -63,7 +63,7 @@ non-zero is valid).
 </dl>
 
 \if man
-\section author AUTHORS
+\section gdal_sieve_author AUTHORS
 Frank Warmerdam <warmerdam at pobox.com>
 \endif
 */
diff --git a/swig/python/setup.py b/swig/python/setup.py
index 086489d..e24b1ef 100644
--- a/swig/python/setup.py
+++ b/swig/python/setup.py
@@ -6,7 +6,7 @@
 # Howard Butler hobu.inc at gmail.com
 
 
-gdal_version = '1.8.1'
+gdal_version = '1.9.0'
 
 import sys
 import os
@@ -42,7 +42,6 @@ def get_numpy_include():
     else:
         return '.'
 
-
 # ---------------------------------------------------------------------------
 # Imports
 # ---------------------------------------------------------------------------
@@ -70,22 +69,32 @@ try:
 except ImportError:
     from distutils.core import setup, Extension
 
+class gdal_config_error(Exception): pass
+
 
 from distutils.command.build_ext import build_ext
 from distutils.ccompiler import get_default_compiler
 from distutils.sysconfig import get_python_inc
 
-def get_gdal_config(option, gdal_config='gdal-config'):
-    
+def fetch_config(option, gdal_config='gdal-config'):
+
     command = gdal_config + " --%s" % option
+
     try:
         import subprocess
         command, args = command.split()[0], command.split()[1]
-        p = subprocess.Popen([command, args], stdout=subprocess.PIPE)
         from sys import version_info
         if version_info >= (3,0,0):
+            try:
+                p = subprocess.Popen([command, args], stdout=subprocess.PIPE)
+            except OSError(e):
+                raise gdal_config_error(e)
             r = p.stdout.readline().decode('ascii').strip()
         else:
+            exec("""try:
+    p = subprocess.Popen([command, args], stdout=subprocess.PIPE)
+except OSError, e:
+    raise gdal_config_error, e""")
             r = p.stdout.readline().strip()
         p.stdout.close()
         p.wait()
@@ -116,13 +125,24 @@ class gdal_ext(build_ext):
         self.numpy_include_dir = get_numpy_include()
         self.gdaldir = None
         self.gdal_config = self.GDAL_CONFIG
+        self.already_raised_no_config_error = False
 
     def get_compiler(self):
         return self.compiler or get_default_compiler()
     
     def get_gdal_config(self, option):
-        return get_gdal_config(option, gdal_config =self.gdal_config)
-    
+        try:
+            return fetch_config(option, gdal_config = self.gdal_config)
+        except gdal_config_error:
+            # If an error is thrown, it is possibly because 
+            # the gdal-config location given in setup.cfg is 
+            # incorrect, or possibly the default -- ../../apps/gdal-config
+            # We'll try one time to use the gdal-config that might be 
+            # on the path. If that fails, we're done, however.
+            if not self.already_raised_no_config_error:
+                self.already_raised_no_config_error = True
+                return fetch_config(option)
+            
     def finalize_options(self):
         if self.include_dirs is None:
             self.include_dirs = include_dirs
@@ -140,12 +160,11 @@ class gdal_ext(build_ext):
         
         if self.get_compiler() == 'msvc':
             return True
-        try:
-            self.gdaldir = self.get_gdal_config('prefix')
-            self.library_dirs.append(os.path.join(self.gdaldir,'lib'))
-            self.include_dirs.append(os.path.join(self.gdaldir,'include'))
-        except:
-            print ('Could not run gdal-config!!!!')
+
+        self.gdaldir = self.get_gdal_config('prefix')
+        self.library_dirs.append(os.path.join(self.gdaldir,'lib'))
+        self.include_dirs.append(os.path.join(self.gdaldir,'include'))
+
 
 extra_link_args = []
 extra_compile_args = []
diff --git a/swig/ruby/RubyMakefile.mk b/swig/ruby/RubyMakefile.mk
index e177dc2..0c0e8db 100644
--- a/swig/ruby/RubyMakefile.mk
+++ b/swig/ruby/RubyMakefile.mk
@@ -17,33 +17,55 @@ RUBY = ruby
 
 include $(GDAL_ROOT)/GDALmake.opt
 
-RUBY_MODULES = gdal.so ogr.so gdalconst.so osr.so
-RUBY_INCLUDE_DIR := $(shell ruby -rrbconfig -e "puts Config::CONFIG['archdir']")
+RUBY_MODULES_LIN = gdal.so ogr.so gdalconst.so osr.so  # Linux, Solaris, ...
+RUBY_MODULES_MAC = gdal.bundle ogr.bundle gdalconst.bundle osr.bundle # Darwin
+
+RUBY_INCLUDE_DIR := $(shell ruby -rrbconfig -e "puts Config::CONFIG['rubyhdrdir'] || Config::CONFIG['archdir']")
+RUBY_ARCH_INCLUDE_DIR := $(shell ruby -rrbconfig -e "puts Config::CONFIG['rubyhdrdir'] + '/' + Config::CONFIG['arch'] unless Config::CONFIG['rubyhdrdir'].nil?")
 RUBY_LIB_DIR := $(shell ruby -rrbconfig -e "puts Config::CONFIG['libdir']")
 RUBY_SO_NAME := $(shell ruby -rrbconfig -e "puts Config::CONFIG['RUBY_SO_NAME']")
 RUBY_EXTENSIONS_DIR := $(shell ruby -rrbconfig -e "puts Config::CONFIG['sitearchdir']")
 INSTALL_DIR := $(RUBY_EXTENSIONS_DIR)/gdal
 
+ifeq ($(RUBY_ARCH_INCLUDE_DIR),)
+# For Ruby < 1.9
 RUBY_INCLUDE = -I$(RUBY_INCLUDE_DIR)
+else
+# For Ruby 1.9
+RUBY_INCLUDE = -I$(RUBY_INCLUDE_DIR) -I$(RUBY_ARCH_INCLUDE_DIR)
+endif
+
+ifeq ("$(shell uname -s)", "Darwin")
+RUBY_MODULES=$(RUBY_MODULES_MAC)
+LDFLAGS += -Xcompiler -bundle -L$(RUBY_LIB_DIR)
+RUBY_LIB := -l$(RUBY_SO_NAME)
+else
+RUBY_MODULES=$(RUBY_MODULES_LIN)
 LDFLAGS += -Xcompiler -shared -L$(RUBY_LIB_DIR)
 RUBY_LIB := -l$(RUBY_SO_NAME)
+endif
 
 build: $(RUBY_MODULES)
 
 clean:
 	rm -f *.so
+	rm -f *.bundle
 	rm -f *.o
 	rm -f *.lo
 	
 veryclean: clean
+	rm -f *_wrap.cpp
 
 $(INSTALL_DIR):
 	mkdir -p $(DESTDIR)$(INSTALL_DIR)
 
 install: $(INSTALL_DIR)
-	$(INSTALL) $(RUBY_MODULES) $(DESTDIR)$(INSTALL_DIR) 
+	for i in $(RUBY_MODULES) ; do $(INSTALL) $$i $(DESTDIR)$(INSTALL_DIR) ; done
+
+$(RUBY_MODULES_MAC): %.bundle: %_wrap.o
+	$(LD) $(LDFLAGS) $(LIBS) $(GDAL_SLIB_LINK) $(RUBY_LIB) $< -o $@
 
-$(RUBY_MODULES): %.so: %_wrap.o
+$(RUBY_MODULES_LIN): %.so: %_wrap.o
 	$(LD) $(LDFLAGS) $(LIBS) $(GDAL_SLIB_LINK) $(RUBY_LIB) $< -o $@
 
 %.o: %.cpp

-- 
GDAL/OGR library and tools



More information about the Pkg-grass-devel mailing list